Completed
Push — master ( 91676c...354384 )
by Alexander
02:23
created

SourceTransformingLoader   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 87.5%

Importance

Changes 0
Metric Value
wmc 13
lcom 2
cbo 2
dl 0
loc 109
ccs 28
cts 32
cp 0.875
rs 10
c 0
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 9 3
1
<?php
2
declare(strict_types = 1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2011, 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\ClassLoading;
13
14
use php_user_filter as PhpStreamFilter;
15
use Go\Instrument\Transformer\StreamMetaData;
16
use Go\Instrument\Transformer\SourceTransformer;
17
use RuntimeException;
18
use function strlen;
19
20
/**
21
 * Php class loader filter for processing php code
22
 *
23
 * @property resource $stream Stream instance of underlying resource
24
*/
25
class SourceTransformingLoader extends PhpStreamFilter
26
{
27
    /**
28
     * Php filter definition
29
     */
30
    public const PHP_FILTER_READ = 'php://filter/read=';
31
32
    /**
33
     * Default PHP filter name for registration
34
     */
35
    public const FILTER_IDENTIFIER = 'go.source.transforming.loader';
36
37
    /**
38
     * String buffer
39
     */
40
    protected $data = '';
41
42
    /**
43
     * List of transformers
44
     *
45
     * @var SourceTransformer[]
46
     */
47
    protected static $transformers = [];
48
49
    /**
50
     * Identifier of filter
51
     *
52
     * @var string
53
     */
54
    protected static $filterId;
55
56
    /**
57
     * Register current loader as stream filter in PHP
58
     *
59
     * @throws RuntimeException If registration was failed
60
     */
61 1
    public static function register(string $filterId = self::FILTER_IDENTIFIER): void
62
    {
63 1
        if (!empty(self::$filterId)) {
64
            throw new RuntimeException('Stream filter already registered');
65
        }
66
67 1
        $result = stream_filter_register($filterId, __CLASS__);
68 1
        if ($result === false) {
69
            throw new RuntimeException('Stream filter was not registered');
70
        }
71 1
        self::$filterId = $filterId;
72 1
    }
73
74
    /**
75
     * Returns the name of registered filter
76
     *
77
     * @throws RuntimeException if filter was not registered
78
     */
79 1
    public static function getId(): string
80
    {
81 1
        if (empty(self::$filterId)) {
82
            throw new RuntimeException('Stream filter was not registered');
83
        }
84
85 1
        return self::$filterId;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 1
    public function filter($in, $out, &$consumed, $closing)
92
    {
93 1
        while ($bucket = stream_bucket_make_writeable($in)) {
94 1
            $this->data .= $bucket->data;
95
        }
96
97 1
        if ($closing || feof($this->stream)) {
98 1
            $consumed = strlen($this->data);
99
100
            // $this->stream contains pointer to the source
101 1
            $metadata = new StreamMetaData($this->stream, $this->data);
102 1
            self::transformCode($metadata);
103
104 1
            $bucket = stream_bucket_new($this->stream, $metadata->source);
105 1
            stream_bucket_append($out, $bucket);
106
107 1
            return PSFS_PASS_ON;
108
        }
109
110 1
        return PSFS_FEED_ME;
111
    }
112
113
    /**
114
     * Adds a SourceTransformer to be applied by this LoadTimeWeaver.
115
     */
116 1
    public static function addTransformer(SourceTransformer $transformer): void
117
    {
118 1
        self::$transformers[] = $transformer;
119 1
    }
120
121
    /**
122
     * Transforms source code by passing it through all transformers
123
     */
124 1
    public static function transformCode(StreamMetaData $metadata): void
125
    {
126 1
        foreach (self::$transformers as $transformer) {
127 1
            $result = $transformer->transform($metadata);
128 1
            if ($result === SourceTransformer::RESULT_ABORTED) {
129
                break;
130
            }
131
        }
132 1
    }
133
}
134