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

MagicConstantTransformer   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 97.37%
Metric Value
wmc 12
lcom 1
cbo 2
dl 0
loc 106
ccs 37
cts 38
cp 0.9737
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
C transform() 0 29 7
A resolveFileName() 0 8 1
A replaceMagicConstants() 0 19 3
1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2012, 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\Transformer;
12
13
use Go\Core\AspectKernel;
14
15
/**
16
 * Transformer that replaces magic __DIR__ and __FILE__ constants in the source code
17
 *
18
 * Additionally, ReflectionClass->getFileName() is also wrapped into normalizer method call
19
 */
20
class MagicConstantTransformer extends BaseSourceTransformer
21
{
22
23
    /**
24
     * Root path of application
25
     *
26
     * @var string
27
     */
28
    protected static $rootPath = '';
29
30
    /**
31
     * Path to rewrite to (cache directory)
32
     *
33
     * @var string
34
     */
35
    protected static $rewriteToPath = '';
36
37
    /**
38
     * Class constructor
39
     *
40
     * @param AspectKernel $kernel Instance of kernel
41
     */
42 6
    public function __construct(AspectKernel $kernel)
43
    {
44 6
        parent::__construct($kernel);
45 6
        self::$rootPath      = $this->options['appDir'];
46 6
        self::$rewriteToPath = $this->options['cacheDir'];
47 6
    }
48
49
    /**
50
     * This method may transform the supplied source and return a new replacement for it
51
     *
52
     * @param StreamMetaData $metadata Metadata for source
53
     * @return void|bool Return false if transformation should be stopped
54
     */
55 5
    public function transform(StreamMetaData $metadata)
56
    {
57
        // Make the job only when we use cache directory
58 5
        if (!self::$rewriteToPath) {
59
            return;
60
        }
61
62 5
        $hasReflectionFilename = strpos($metadata->source, 'getFileName') !== false;
63 5
        $hasMagicConstants     = (strpos($metadata->source, '__DIR__') !== false) ||
64 5
            (strpos($metadata->source, '__FILE__') !== false);
65
66 5
        if (!$hasMagicConstants && !$hasReflectionFilename) {
67 1
            return;
68
        }
69
70
        // Resolve magic constants
71 4
        if ($hasMagicConstants) {
72 3
            $this->replaceMagicConstants($metadata);
73
        }
74
75 4
        if ($hasReflectionFilename) {
76
            // need to make more reliable solution
77 1
            $metadata->source = preg_replace(
78 1
                '/\$([\w\$\-\>\:\(\)]*?getFileName\(\))/S',
79 1
                '\\' . __CLASS__ . '::resolveFileName(\$\1)',
80 1
                $metadata->source
81
            );
82
        }
83 4
    }
84
85
    /**
86
     * Resolves file name from the cache directory to the real application root dir
87
     *
88
     * @param string $fileName Absolute file name
89
     *
90
     * @return string Resolved file name
91
     */
92 1
    public static function resolveFileName($fileName)
93
    {
94 1
        return str_replace(
95 1
            array(self::$rewriteToPath, DIRECTORY_SEPARATOR . '_proxies'),
96 1
            array(self::$rootPath, ''),
97
            $fileName
98
        );
99
    }
100
101
    /**
102
     * Replace only magic constants in the code
103
     *
104
     * @param StreamMetaData $metadata
105
     */
106 3
    private function replaceMagicConstants(StreamMetaData $metadata)
107
    {
108 3
        $originalUri = $metadata->uri;
109
        $replacement = array(
110 3
            T_FILE => $originalUri,
111 3
            T_DIR  => dirname($originalUri)
112
        );
113 3
        $tokenStream = token_get_all($metadata->source);
114
115 3
        $transformedSource = '';
116 3
        foreach ($tokenStream as $token) {
117 3
            list ($token, $value) = (array) $token + array(1 => $token);
118 3
            if (isset($replacement[$token])) {
119 2
                $value = "'" . $replacement[$token] . "'";
120
            }
121 3
            $transformedSource .= $value;
122
        }
123 3
        $metadata->source = $transformedSource;
124 3
    }
125
}
126