Completed
Pull Request — 1.x (#286)
by Alexander
02:43
created

SourceTransformingLoader   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 13
lcom 2
cbo 1
dl 0
loc 123
ccs 0
cts 48
cp 0
rs 10
c 2
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 12 3
A getId() 0 8 2
A filter() 0 21 4
A addTransformer() 0 4 1
A transformCode() 0 12 3
1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2011, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\Instrument\ClassLoading;
12
13
use php_user_filter as PhpStreamFilter;
14
use Go\Instrument\Transformer\StreamMetaData;
15
use Go\Instrument\Transformer\SourceTransformer;
16
17
/**
18
 * Php class loader filter for processing php code
19
 */
20
class SourceTransformingLoader extends PhpStreamFilter
21
{
22
    /**
23
     * Php filter definition
24
     */
25
    const PHP_FILTER_READ = 'php://filter/read=';
26
27
    /**
28
     * Default PHP filter name for registration
29
     */
30
    const FILTER_IDENTIFIER = 'go.source.transforming.loader';
31
32
    /**
33
     * String buffer
34
     *
35
     * @var string
36
     */
37
    protected $data = '';
38
39
    /**
40
     * List of transformers
41
     *
42
     * @var array|SourceTransformer[]
43
     */
44
    protected static $transformers = [];
45
46
    /**
47
     * Identifier of filter
48
     *
49
     * @var string
50
     */
51
    protected static $filterId;
52
53
    /**
54
     * Register current loader as stream filter in PHP
55
     *
56
     * @param string $filterId Identifier for the filter
57
     * @throws \RuntimeException If registration was failed
58
     */
59
    public static function register($filterId = self::FILTER_IDENTIFIER)
60
    {
61
        if (!empty(self::$filterId)) {
62
            throw new \RuntimeException('Stream filter already registered');
63
        }
64
65
        $result = stream_filter_register($filterId, __CLASS__);
66
        if (!$result) {
67
            throw new \RuntimeException('Stream filter was not registered');
68
        }
69
        self::$filterId = $filterId;
70
    }
71
72
    /**
73
     * Returns the name of registered filter
74
     *
75
     * @throws \RuntimeException if filter was not registered
76
     * @return string
77
     */
78
    public static function getId()
79
    {
80
        if (empty(self::$filterId)) {
81
            throw new \RuntimeException('Stream filter was not registered');
82
        }
83
84
        return self::$filterId;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function filter($in, $out, &$consumed, $closing)
91
    {
92
        while ($bucket = stream_bucket_make_writeable($in)) {
93
            $this->data .= $bucket->data;
94
        }
95
96
        if ($closing || feof($this->stream)) {
97
            $consumed = strlen($this->data);
98
99
            // $this->stream contains pointer to the source
100
            $metadata = new StreamMetaData($this->stream, $this->data);
0 ignored issues
show
Bug introduced by
The property stream does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
101
            self::transformCode($metadata);
102
103
            $bucket = stream_bucket_new($this->stream, $metadata->source);
104
            stream_bucket_append($out, $bucket);
105
106
            return PSFS_PASS_ON;
107
        }
108
109
        return PSFS_FEED_ME;
110
    }
111
112
    /**
113
     * Adds a SourceTransformer to be applied by this LoadTimeWeaver.
114
     *
115
     * @param $transformer SourceTransformer Transformer for source code
116
     *
117
     * @return void
118
     */
119
    public static function addTransformer(SourceTransformer $transformer)
120
    {
121
        self::$transformers[] = $transformer;
122
    }
123
124
    /**
125
     * Transforms source code by passing it through all transformers
126
     *
127
     * @param StreamMetaData|null $metadata Metadata from stream
128
     * @return void|bool Return false if transformation should be stopped
129
     */
130
    public static function transformCode(StreamMetaData $metadata)
131
    {
132
        $result = null;
133
        foreach (self::$transformers as $transformer) {
134
            $result = $transformer->transform($metadata);
135
            if ($result === false) {
136
                break;
137
            }
138
        }
139
140
        return $result;
141
    }
142
}
143