Completed
Push — master ( 06ef8e...568e3c )
by Alexander
03:25
created

StreamMetaData   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 78.79%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
lcom 1
cbo 2
dl 0
loc 142
ccs 26
cts 33
cp 0.7879
rs 10
c 1
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 19 5
A __get() 0 8 2
A getSource() 0 9 2
A setSource() 0 7 3
A __set() 0 7 2
1
<?php
2
declare(strict_types = 1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2012, Lisachenko Alexander <[email protected]>
7
 *
8
 * This source file is subject to the license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Go\Instrument\Transformer;
13
14
use Go\Instrument\PathResolver;
15
use Go\ParserReflection\ReflectionEngine;
16
use InvalidArgumentException;
17
use PhpParser\Node;
18
19
/**
20
 * Stream metadata object
21
 *
22
 * @property-read string $source
23
 */
24
class StreamMetaData
25
{
26
    /**
27
     * Mapping between array keys and properties
28
     *
29
     * @var array
30
     */
31
    private static $propertyMap = [
32
        'stream_type'  => 'streamType',
33
        'wrapper_type' => 'wrapperType',
34
        'wrapper_data' => 'wrapperData',
35
        'filters'      => 'filterList',
36
        'uri'          => 'uri',
37
    ];
38
39
    /**
40
     * A label describing the underlying implementation of the stream.
41
     *
42
     * @var string
43
     */
44
    public $streamType;
45
46
    /**
47
     * A label describing the protocol wrapper implementation layered over the stream.
48
     *
49
     * @var string
50
     */
51
    public $wrapperType;
52
53
    /**
54
     * Wrapper-specific data attached to this stream.
55
     *
56
     * @var mixed
57
     */
58
    public $wrapperData;
59
60
    /**
61
     * Array containing the names of any filters that have been stacked onto this stream.
62
     *
63
     * @var array
64
     */
65
    public $filterList;
66
67
    /**
68
     * The URI/filename associated with this stream.
69
     *
70
     * @var string
71
     */
72
    public $uri;
73
74
    /**
75
     * Information about syntax tree
76
     *
77
     * @var Node[]
78
     */
79
    public $syntaxTree;
80
81
    /**
82
     * List of source tokens
83
     *
84
     * @var array
85
     */
86
    public $tokenStream = [];
87
88
    /**
89
     * Creates metadata object from stream
90
     *
91
     * @param resource $stream Instance of stream
92
     * @param string $source Source code or null
93
     * @throws \InvalidArgumentException for invalid stream
94
     */
95 31
    public function __construct($stream, string $source = null)
96
    {
97 31
        if (!is_resource($stream)) {
98
            throw new InvalidArgumentException('Stream should be valid resource');
99
        }
100 31
        $metadata = stream_get_meta_data($stream);
101 31
        if (preg_match('/resource=(.+)$/', $metadata['uri'], $matches)) {
102 6
            $metadata['uri'] = PathResolver::realpath($matches[1]);
103
        }
104 31
        foreach ($metadata as $key => $value) {
105 31
            if (!isset(self::$propertyMap[$key])) {
106 31
                continue;
107
            }
108 31
            $mappedKey = self::$propertyMap[$key];
109 31
            $this->$mappedKey = $value;
110
        }
111 31
        $this->syntaxTree = ReflectionEngine::parseFile($this->uri, $source);
112 31
        $this->setSource($source);
113 31
    }
114
115
    /**
116
     * @inheritDoc
117
     */
118 31
    public function __get($name)
119
    {
120 31
        if ($name === 'source') {
121 31
            return $this->getSource();
122
        }
123
124
        return null;
125
    }
126
127
    /**
128
     * @inheritDoc
129
     */
130
    public function __set($name, $value)
131
    {
132
        if ($name === 'source') {
133
            trigger_error('Setting StreamMetaData->source is deprecated, use tokenStream instead', E_USER_DEPRECATED);
134
            $this->setSource($value);
135
        }
136
    }
137
138
    /**
139
     * Returns source code directly from tokens
140
     */
141 31
    private function getSource(): string
142
    {
143 31
        $transformedSource = '';
144 31
        foreach ($this->tokenStream as $token) {
145 31
            $transformedSource .= $token[1] ?? $token;
146
        }
147
148 31
        return $transformedSource;
149
    }
150
151
    /**
152
     * Sets the new source for this file
153
     *
154
     * @TODO: Unfortunately, AST won't be changed, so please be accurate during transformation
155
     *
156
     * @param string $newSource
157
     */
158 31
    private function setSource(string $newSource)
159
    {
160 31
        $rawTokens = token_get_all($newSource);
161 31
        foreach ($rawTokens as $index => $rawToken) {
162 31
            $this->tokenStream[$index] = \is_array($rawToken) ? $rawToken : [T_STRING, $rawToken];
163
        }
164 31
    }
165
}
166