Completed
Push — master ( eccf6a...345cbf )
by Alexander
03:07
created

StreamMetaData::__construct()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5.009

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
ccs 13
cts 14
cp 0.9286
rs 8.8571
cc 5
eloc 13
nc 7
nop 2
crap 5.009
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 34
    public function __construct($stream, string $source = null)
96
    {
97 34
        if (!is_resource($stream)) {
98
            throw new InvalidArgumentException('Stream should be valid resource');
99
        }
100 34
        $metadata = stream_get_meta_data($stream);
101 34
        if (preg_match('/resource=(.+)$/', $metadata['uri'], $matches)) {
102 9
            $metadata['uri'] = PathResolver::realpath($matches[1]);
103
        }
104 34
        foreach ($metadata as $key=>$value) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
105 34
            if (!isset(self::$propertyMap[$key])) {
106 34
                continue;
107
            }
108 34
            $mappedKey = self::$propertyMap[$key];
109 34
            $this->$mappedKey = $value;
110
        }
111 34
        $this->syntaxTree = ReflectionEngine::parseFile($this->uri, $source);
112 34
        $this->setSource($source);
113 34
    }
114
115
    /**
116
     * @inheritDoc
117
     */
118 34
    public function __get($name)
119
    {
120 34
        if ($name === 'source') {
121 34
            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 34
    private function getSource(): string
142
    {
143 34
        $transformedSource = '';
144 34
        foreach ($this->tokenStream as $token) {
145 34
            $transformedSource .= $token[1] ?? $token;
146
        }
147
148 34
        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 34
    private function setSource(string $newSource)
159
    {
160 34
        $rawTokens = token_get_all($newSource);
161 34
        foreach ($rawTokens as $index => $rawToken) {
162 34
            $this->tokenStream[$index] = \is_array($rawToken) ? $rawToken : [T_STRING, $rawToken];
163
        }
164 34
    }
165
}
166