Compressor::code_array_to_str()   F
last analyzed

Complexity

Conditions 16
Paths 1037

Size

Total Lines 75
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 75
rs 2.289
cc 16
eloc 30
nc 1037
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace samsonphp\compressor;
3
4
use samson\core\Core;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, samsonphp\compressor\Core.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
5
use samson\core\iModule;
6
use samsonframework\localfilemanager\LocalFileManager;
7
use samsonframework\resource\ResourceMap;
8
use samsonos\compressor\Module;
9
use samsonphp\compressor\resource\JavaScript;
10
use samsonphp\event\Event;
11
use samsonphp\resource\Router;
12
13
/**
14
 * Module for automatic code optimization|compression
15
 *
16
 * @package samsonos\compressor
17
 * @author Vitaly Iegorov <[email protected]>
18
 */
19
class Compressor
20
{
21
    /** Identifier of global namespace */
22
    const NS_GLOBAL = '';
23
24
    const E_CREATE_MODULE_LIST = 'compressor.create.module.list';
25
26
    const E_CREATE_RESOURCE_LIST = 'compressor.create.resource.list';
27
28
    const E_RESOURCE_COMPRESS = 'compressor.resource.compress';
29
30
    /** Array key for storing last generated data */
31
    const VIEWS = 'views';
32
33
    /** Output path for compressed web application */
34
    public $output = 'out/';
35
36
    /** Collection of requires to insert in compressed file */
37
    public $require = array();
38
39
    /** Ignored resource extensions */
40
    public $ignored_extensions = array('php', 'js', 'css', 'md', 'map', 'dbs', 'vphp', 'less', 'gz', 'lock', 'json', 'sql', 'xml', 'yml');
41
42
    /** Ignored resource files */
43
    public $ignored_resources = array('.project', '.buildpath', '.gitignore', '.travis.yml', 'phpunit.xml', 'thumbs.db', 'Thumbs.db');
44
45
    /** @var array Collection of folders to be ignored by compressor */
46
    public $ignoredFolders = array('vendor', 'var');
47
48
    /** @var array Collection of file paths to be ignored by compressor */
49
    public $ignoredFiles = array();
50
51
    /** Папка где размещается исходное веб-приложение */
52
    public $input = __SAMSON_CWD__;
53
54
    /** View rendering mode */
55
    protected $view_mode = Core::RENDER_VARIABLE;
0 ignored issues
show
Deprecated Code introduced by
The constant samson\core\Core::RENDER_VARIABLE has been deprecated with message: View rendering algorithm from array of view variables

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
56
57
    /** Указатель на текущий сворачиваемый модуль */
58
    protected $current;
59
60
    /** Коллекция уже обработанных файлов */
61
    protected $files = array();
62
63
    /** Collection for storing all php code by namespace */
64
    private $php = array(self::NS_GLOBAL => array());
65
66
    /** @var string Web-application environment identifier */
67
    protected $environment = 'prod';
68
69
    /** @var bool Debug flag */
70
    protected $debug = false;
71
72
    /** @var string Supported php version */
73
    protected $phpVersion = PHP_VERSION;
74
75
    protected $resourceManager;
76
77
    protected $classConst = array();
78
79
80
    protected $resourceUrlsList = [];
81
82
    /** @var FileManagerInterface File system manager */
83
    protected $fileManager;
84
85
    /**
86
     * Compress web-application
87
     * @param string $output Path for creating compressed version
88
     * @param boolean $debug Disable errors output
89
     * @param string $environment Configuration environment
90
     * @param string $phpVersion PHP version to support
91
     * @param array $configuration Configuration
92
     */
93
    public function __construct($output = 'out/', $debug = false, $environment = 'prod', $phpVersion = PHP_VERSION, $configuration = array())
94
    {
95
        $this->resourceManager = new resource\Generic($this);
96
97
        $this->fileManager = new LocalFileManager();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \samsonframework\loc...ager\LocalFileManager() of type object<samsonframework\l...nager\LocalFileManager> is incompatible with the declared type object<samsonphp\compressor\FileManagerInterface> of property $fileManager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
98
99
        $this->output = $output;
100
        $this->debug = $debug;
101
        $this->environment = $environment;
102
        $this->phpVersion = $phpVersion;
103
        foreach ($configuration as $key => $value) {
104
            // If object has configured property defined
105
            if (property_exists($this, $key)) {
106
                // Set object variable value
107
                $this->$key = $value;
108
            }
109
        }
110
    }
111
112
    /**
113
     * Свернуть файл представления
114
     *
115
     * @param string $view_file Полный путь к файлу представления
116
     * @param iModule $module Указатель на модуль которому принадлежит это представление
117
     *
118
     * @return bool
119
     */
120
    public function compress_view($view_file, iModule & $module)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::compress_view" is not in camel caps format
Loading history...
121
    {
122
        // Build relative path to module view
123
        $rel_path = ($module->id() == 'local' ? '' : $module->id() . '/') . str_replace($module->path(), '', $view_file);
124
125
        $this->log('  -- Preparing view[##] relative path [##]', $view_file, $rel_path);
126
127
        // Прочитаем файл представления
128
        $view_html = file_get_contents($view_file);
129
130
        if (!isset($view_file{0})) return e('View: ##(##) is empty', E_SAMSON_SNAPSHOT_ERROR, array($view_file, $rel_path));
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
131
132
        // TODO: should be done via events in resourcer module
133
        // Найдем обращения к роутеру ресурсов
134
        $view_html = preg_replace_callback(
135
            '/(<\?php)*\s*src\s*\(\s*(\'|\")?(?<path>[^\'\"\?\;\)]+)(\'|\")?(\s*,\s*(\'|\")(?<module>[^\'\"\)]+)(\'|\"))?\s*\)\;?(\s*\?>)?/uis',
136
            array($this, 'src_replace_callback'),
137
            $view_html
138
        );
139
140
        // Replace old inline php tags
141
        $view_html = str_ireplace('<? ', '<?php ', $view_html);
142
143
        // Сожмем HTML
144
        $view_html = Minify_HTML::minify($view_html);
145
146
        // Fire event to render view correctly
147
        Event::fire('core.render', array(&$view_html, array(), &$module));
148
149
        // Template re-rendering
150
        // TODO: We must split regular view and template file to handle differently, for now nothing will change but in future....
151
152
        $template = !isset($this->resourceUrlsList[$view_file])?Router::I_MAIN_PROJECT_TEMPLATE:$view_file;
153
154
        Event::fire('core.rendered', array(&$view_html, $this->resourceUrlsList[$template]));
155
156
        $view_php = "<<<'EOT'" . "\n" . $view_html . "\n" . "EOT;";
157
158
        // Add view code to final global namespace
159
        $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . '$GLOBALS["__compressor_files"]["' . $rel_path . '"] = ' . $view_php;
160
    }
161
162
    /**
163
     * Свернуть модуль
164
     *
165
     * @param iModule $module Указатель на модуль для сворачивания
166
     * @param ResourceMap $data
167
     */
168
    public function compress_module(iModule &$module, ResourceMap &$data)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::compress_module" is not in camel caps format
Loading history...
169
    {
170
        // Идентификатор модуля
171
        $id = $module->id();
172
173
        // Сохраним указатель на текущий модуль
174
        $this->current = &$module;
175
176
        // Build output module path
177
        $module_output_path = $id == 'local' ? '' : basename($module->path()) . '/';
178
179
        // Build resource source path
180
        $module_path = $id == 'local' ? $module->path() . __SAMSON_PUBLIC_PATH : $module->path();
181
182
        $this->log('  - Compressing module[##] from [##]', $id, $module_path);
183
184
        // Call special method enabling module personal resource pre-management on compressing
185
        if ($module->beforeCompress($this, $this->php) !== false) {
186
            // Copy all module resources
187
            $this->copy_path_resources($data->resources, $module_path, $module_output_path);
188
189
            // Internal collection of module php code, not views
190
            $module_php = array();
191
192
            foreach ($data->classes as $key => $php) {
193
                $this->compress_php($key, $module, $module_php);
194
            }
195
            
196
            // Iterate module plain php code
197
            foreach ($data->php as $php) {
198
                $this->compress_php($php, $module, $module_php);
199
            }
200
201
            foreach ($data->globals as $php) {
202
                $this->compress_php($php, $module, $module_php);
203
            }
204
205
            // Iterate module controllers php code
206
            foreach ($data->controllers as $php) {
207
                $this->compress_php($php, $module, $module_php);
208
            }
209
            // Iterate module controllers php code
210
            foreach ($data->modules as $php) {
211
                $this->compress_php($php[1], $module, $module_php);
212
            }
213
            // Iterate module model php code
214
            foreach ($data->models as $php) {
215
                $this->compress_php($php, $module, $module_php);
216
            }
217
            // Iterate module views
218
            foreach ($data->views as $php) {
219
                $this->compress_view($php, $module);
220
            }
221
        }
222
223
        // Call special method enabling module personal resource post-management on compressing
224
        $module->afterCompress($this, $module_php);
0 ignored issues
show
Bug introduced by
The variable $module_php does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
225
226
        // Gather all code in to global code collection with namespaces
227
        $this->code_array_combine($module_php, $this->php);
228
229
        // Change module path
230
        $module->path($id . '/');
231
    }
232
233
    public function rewriteResourceRouter(array $matches)
234
    {
235
        //trace($matches,1);
236
        //die;
237
        return '"' . $this->current->id() . '/' . $matches['path'] . '";';
238
    }
239
240
    /**
241
     * Обработчик замены роутера ресурсов
242
     * @param array $matches Найденые совпадения по шаблону
243
     * @return string Обработанный вариант пути к ресурсу
244
     */
245
    public function src_replace_callback($matches)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::src_replace_callback" is not in camel caps format
Loading history...
246
    {
247
        // Получим относительный путь к ресурсу
248
        $path = trim($matches['path']);
249
250
        // Путь к модуля после сжимания
251
        $module_path = (isset($matches['module']) && strlen($matches['module']) > 0) ? $matches['module'] . '/' : $this->current->id() . '/';
252
253
        // Если передана переменная мы не можем гарантировать её значение
254
        if (strpos($path, '$') !== false) $path = '<?php echo \'' . $module_path . '\'.' . $path . '; ?>';
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
255
        // Просто строка
256
        else $path = $module_path . $path;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
257
258
        return $path;
259
        //e('Файл представления ## - Обращение к роутеру ресурсов через переменную ##', E_SAMSON_SNAPSHOT_ERROR, array($view_path, $path));
260
    }
261
262
    /** Generic log function for further modification */
263
    public function log($message)
264
    {
265
        // Get passed vars
266
        $vars = func_get_args();
267
        // Remove first message var
268
        array_shift($vars);
269
270
        // Render debug message
271
        return trace(debug_parse_markers($message, $vars));
272
    }
273
274
    /**
275
     * Compress web-application
276
     * @param boolean $debug Disable errors output
277
     * @param string $php_version PHP version to support
278
     */
279
    public function compress($debug = false, $environment = 'prod', $php_version = PHP_VERSION)
280
    {
281
        // Set compressed project environment
282
        $this->environment = $environment;
283
284
        elapsed('Started web-application compression[' . $this->environment . ']');
285
286
        s()->async(true);
0 ignored issues
show
Deprecated Code introduced by
The function s() has been deprecated with message: Use $this->system in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
287
        ini_set('memory_limit', '256M');
288
289
        // Check output path
290
        if (!isset($this->output{0})) {
291
            return $this->log('Cannot compress web-application from [##] - No output path is specified', $this->input);
292
        }
293
294
        // Define rendering model depending on PHP version
295
        $php_version = isset($php_version{0}) ? $php_version : PHP_VERSION;
296
        if (version_compare($php_version, '5.3.0', '<')) {
297
            $this->view_mode = Core::RENDER_ARRAY;
298
        }
299
300
        // Add url base to path
301
        $this->output .= url()->base();
302
303
        // Creating output project folder
304
        $result = \samson\core\File::mkdir($this->output);
305
        if ($result) {
306
            $this->log('Created output project folder [##]', $this->output);
307
        } else if ($result == -1) {
308
            return $this->log('Compression failed! Cannot create output project folder [##]', $this->output);
309
        }
310
311
        // Remove all trailing slashes
312
        $this->output = realpath($this->output) . '/';
313
314
        $this->log('[##]## Compressing web-application[##] from [##] to [##]',
315
            $environment,
316
            $debug ? '[DEBUG]' : '',
317
            $php_version,
318
            $this->input,
319
            $this->output
320
        );
321
322
        // Add generic composer auto loader require
323
        $this->php['__before_all']['composer'] = "\n" . 'if(file_exists("vendor/autoload.php")) require "vendor/autoload.php";';
324
325
        // Define global views collection
326
        $this->php[self::NS_GLOBAL][self::VIEWS] = "\n" . '$GLOBALS["__compressor_files"] = array();';
327
328
        // If resourcer is loaded - copy css and js
329
        // Link
330
        $rr = &s()->module_stack['resourcer'];
0 ignored issues
show
Deprecated Code introduced by
The function s() has been deprecated with message: Use $this->system in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
Bug introduced by
The property module_stack does not seem to exist in samson\core\Core.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
331
332
        // Iterate all css and js resources
333
        $ignoreFolders = array();
334
        foreach ($this->ignoredFolders as $folder) {
335
            $ignoreFolders[] = $this->output . $folder;
336
        }
337
338
        // Remove all old javascript and css
339
        \samson\core\File::clear($this->output, array('js', 'css'), $ignoreFolders);
340
341
        $moduleListArray = [];
342
343
        //$moduleListArray[Router::I_MAIN_PROJECT_TEMPLATE] = $this->system->module_stack;
344
345
        Event::fire(self::E_CREATE_MODULE_LIST, array(& $moduleListArray));
346
347
        $resource = new Resource($this->fileManager);
348
349
        foreach ($moduleListArray as $template => $moduleList)
350
        {
351
            $resourceUrls = [];
352
353
            Event::fire(self::E_CREATE_RESOURCE_LIST, array(& $resourceUrls, $moduleList));
354
355
            foreach ($resourceUrls as $type => $urls) {
356
                $file = $resource->compress($urls, $type, $this->output);
357
                $this->resourceUrlsList[$template][$type] = [DIRECTORY_SEPARATOR.$file];
358
            }
359
        }
360
361
        // Iterate core ns resources collection
362
        foreach (s()->module_stack as $id => &$module) {
0 ignored issues
show
Deprecated Code introduced by
The function s() has been deprecated with message: Use $this->system in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
363
            // Work only with compressable modules
364
            if (is_a($module, ns_classname('CompressInterface', 'samsonframework\core')) ||
0 ignored issues
show
Deprecated Code introduced by
The function ns_classname() has been deprecated with message: use \samson\core\AutoLoader::value() and pass full class name to it without splitting into class name and namespace

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
365
                (isset($this->composerParameters['samsonphp_package_compressable']) &&
0 ignored issues
show
Bug introduced by
The property composerParameters 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...
366
                    ($this->composerParameters['samsonphp_package_compressable'] = 1))
367
            ) {
368
                $this->compress_module($module, $module->resourceMap);
369
            }
370
371
            // Change path to local modules
372
            if (is_a($module, '\samson\core\VirtualModule')) {
373
                $module->path('');
374
            }
375
        }
376
377
378
379
380
381
382
383
384
        /*foreach ($rr->cached['js'] as $jsCachedFile) {
385
            // Manage javascript resource
386
            $javascriptManager = new resource\JavaScript($this);
387
            $javascriptManager->compress(__SAMSON_CWD__ . $jsCachedFile, $this->output . basename($jsCachedFile));
388
        }
389
390
        foreach ($rr->cached['css'] as $cssCachedFile) {
391
            // Manage CSS resource
392
            $cssManager = new resource\CSS($this, $rr);
393
            $cssManager->compress(__SAMSON_CWD__ . $cssCachedFile, $this->output . basename($cssCachedFile));
394
        }*/
395
    //}
396
397
        // Copy main project composer.json
398
        $composerPath = __SAMSON_CWD__ . 'composer.json';
399
        if (file_exists($composerPath)) {
400
            // Read json file
401
            $composerJSON = (array)json_decode(file_get_contents($composerPath));
402
            // Remove development dependencies
403
            unset($composerJSON['require-dev']);
404
            // Remove autoload section
405
            unset($composerJSON['autoload']);
406
            // Remove install/update scripts
407
            unset($composerJSON['scripts']);
408
409
            // Write modified composer.json
410
            file_put_contents($this->output . 'composer.json', json_encode($composerJSON));
411
        }
412
413
        // Set errors output
414
        $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . '\samson\core\Error::$OUTPUT = ' . (!$debug ? 'false' : 'true') . ';';
415
416
        // Create SamsonPHP core compressor
417
        $core = new \samsonphp\compressor\Core(s(), $environment, $this);
0 ignored issues
show
Deprecated Code introduced by
The function s() has been deprecated with message: Use $this->system in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
418
419
        // Add global base64 serialized core string
420
        $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . '$GLOBALS["__CORE_SNAPSHOT"] = \'' . $core->compress() . '\';';
421
422
        // Add all specified requires
423
        foreach ($this->require as $require) $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . 'require("' . $require . '");';
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
424
425
        // Add localization data
426
        $locale_str = array();
427
        foreach (\samson\core\SamsonLocale::$locales as $locale) {
428
            if ($locale != '') {
429
                $locale_str[] = '\'' . $locale . '\'';
430
            }
431
        }
432
        // Add [setlocales] code
433
        $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . 'setlocales( ' . implode(',', $locale_str) . ');';
434
435
        // TODO: add generic handlers to modules to provide compressing logic for each module
436
        // TODO: add generic constants namespace to put all constants definition there - and put only defined constrat and redeclare them
437
438
        // TODO: WTF???? Thi must be local module logic
439
        // If this is remote web-app - collect local resources
440
        if (__SAMSON_REMOTE_APP) {
0 ignored issues
show
Deprecated Code introduced by
The constant __SAMSON_REMOTE_APP has been deprecated with message: Flag that this script runs from remote app

This class constant has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
441
            // Gather all resources
442
            $path = __SAMSON_CWD__;
443
            $ls = array();
444
            s()->resources($path, $ls);
0 ignored issues
show
Bug introduced by
The method resources() does not seem to exist on object<samson\core\Core>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Deprecated Code introduced by
The function s() has been deprecated with message: Use $this->system in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
445
446
            // If we have any resources
447
            if (isset($ls['resources'])) {
448
                $this->copy_path_resources($ls['resources'], __SAMSON_CWD__, '');
449
            }
450
        }
451
452
        // If default locale is defined
453
        if (!defined('DEFAULT_LOCALE')) {
454
            define('DEFAULT_LOCALE', 'ru');
455
        }
456
457
        // Add default system locale to them end of core definition
458
        $this->php['samson\core'][self::VIEWS] = "\n" . 'define("DEFAULT_LOCALE", "' . DEFAULT_LOCALE . '");';
459
460
        // Pointer to entry script code
461
        $entryScriptPath = __SAMSON_CWD__ . __SAMSON_PUBLIC_PATH . 'index.php';
462
463
        $entryScript = &$this->php[self::NS_GLOBAL][$entryScriptPath];
464
465
        // Collect all event system data
466
        $eventCompressor = new EventCompressor();
467
        $eventCompressor->collect($entryScript);
468
469
        // Remove standard framework entry point from index.php	- just preserve default controller
470
        if (preg_match('/start\(\s*(\'|\")(?<default>[^\'\"]+)/i', $entryScript, $matches)) {
471
            /*
472
             * Temporary solution to support compressed version, because other way localization does not work,
473
             * as chain is broken, first time URL object is created and URL is parsed only after start, so
474
             * CMS::afterCompress does not knows what is current locale and does not inject it to all material
475
             * queries.
476
             */
477
            $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . 'url();';
478
479
            $this->php[self::NS_GLOBAL][self::VIEWS] .= "\n" . 's()->start(\'' . $matches['default'] . '\');';
480
        } else e('Default module definition not found - possible errors at compressed version');
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
481
482
        // Clear default entry point
483
        unset($this->php[self::NS_GLOBAL][$entryScriptPath]);
484
485
        // Set global namespace as last
486
        $global_ns = $this->php[self::NS_GLOBAL];
487
        unset($this->php[self::NS_GLOBAL]);
488
        $this->php[self::NS_GLOBAL] = $global_ns;
489
490
        // Set view data to the end of global namespace
491
        $s = $this->php[self::NS_GLOBAL][self::VIEWS];
492
        unset($this->php[self::NS_GLOBAL][self::VIEWS]);
493
        $this->php[self::NS_GLOBAL][self::VIEWS] = $s;
494
495
        // Load all OOP entities
496
        $classes = array();
497
        // Соберем коллекцию загруженных интерфейсов их файлов по пространствам имен
498
        $this->classes_to_ns_files(get_declared_interfaces(), $classes);
499
500
        // Соберем коллекцию загруженных классов их файлов по пространствам имен
501
        $this->classes_to_ns_files(get_declared_classes(), $classes);
502
503
        // Fix OOP entities
504
        foreach ($this->php as $ns => & $files) {
505
            // If this namespace has been loaded
506
            if (isset($classes[$ns])) {
507
                // Fill namespace entities, make OOP entities correct order
508
                $files = array_merge($classes[$ns], $files);
509
            }
510
        }
511
512
        // Соберем весь PHP код в один файл
513
        $index_php = $this->code_array_to_str($this->php, ($this->view_mode == 2));
514
515
        // Collect all event system data
516
        $eventCompressor->collect($index_php);
517
518
        // Transform event system in all project code
519
        if ($eventCompressor->transform($index_php, $index_php)) {
520
            //trace($eventCompressor->subscriptions, true);
521
        }
522
523
        // Remove url_base parsing and put current url base
524 View Code Duplication
        if (preg_match('/define\(\'__SAMSON_BASE__\',\s*([^;]+)/i', $index_php, $matches)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
525
            $index_php = str_replace($matches[0], 'define(\'__SAMSON_BASE__\',\'' . __SAMSON_BASE__ . '\');', $index_php);
526
        }
527
528
        // Set global constant to specify supported PHP version
529 View Code Duplication
        if (preg_match('/define\s*\(\'__SAMSON_PHP_OLD[^;]+/', $index_php, $matches)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
530
            $index_php = str_replace($matches[0], 'define(\'__SAMSON_PHP_OLD\',\'' . ($this->view_mode == 2) . '\');', $index_php);
531
        }
532
533
        $index_php = $this->removeBlankLines($index_php);
534
        $index_php = preg_replace('/(declare *\( *strict_types *= *1 *\) *;)/i', ' ', $index_php);
535
536
        // Запишем пусковой файл
537
        file_put_contents($this->output . 'index.php', '<?php ' . $index_php . "\n" . '?>');
538
539
        // Minify PHP code if no debug is needed
540
        if (!$debug) {
541
            file_put_contents($this->output . 'index.php', php_strip_whitespace($this->output . 'index.php'));
542
        }
543
544
        elapsed('Site has been successfully compressed to ' . $this->output);
545
    }
546
547
    /**
548
     * Преобразовать коллекцию полученного кода в виде NS/Files в строку
549
     * с правильными NS
550
     *
551
     * @param array $code Коллекция кода полученная функцией @see compress_php()
552
     * @param boolean $no_ns Флаг убирания NS из кода
553
     * @return string Правильно собранный код в виде строки
554
     */
555
    public function code_array_to_str(array $code, $no_ns = false)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::code_array_to_str" is not in camel caps format
Loading history...
556
    {
557
        // Соберем весь PHP код модуля
558
        $php_code = '';
559
        foreach ($code as $ns => $files) {
560
            // If we support namespaces
561
            if (!$no_ns) $php_code .= "\n" . 'namespace ' . $ns . '{';
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
562
563
            // Insert files code
564
            foreach ($files as $file => $php) {
565
                // Ignore uses array
566
                if ($file == 'uses') continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
567
                // TODO: Add uses support class name changing
568
569
                // If we does not support namespaces
570
                if ($no_ns) {
571
                    // Find all static class usage
572
                    if (preg_match_all('/[\!\.\,\(\s\n\=\:]+\s*(?:self|parent|static|(?<classname>[\\\a-z_0-9]+))::/i', $php, $matches)) {
573
                        $php = $this->changeClassName($matches, $php, $ns);
574
                    }
575
576
                    // Find all class definition
577
                    if (preg_match_all('/(\n|\s)\s*class\s+(?<classname>[^\s]+)/i', $php, $matches)) {
578
                        $php = $this->changeClassName($matches, $php, $ns);
579
                    }
580
581
                    // Find all instanceof definition
582
                    if (preg_match_all('/\s+instanceof\s+(?<classname>[\\\a-z_0-9]+)/i', $php, $matches)) {
583
                        $php = $this->changeClassName($matches, $php, $ns);
584
                    }
585
586
                    // Find all interface definition
587
                    if (preg_match_all('/(\n|\s)\s*interface\s+(?<classname>[^\s]+)/i', $php, $matches)) {
588
                        $php = $this->changeClassName($matches, $php, $ns);
589
                    }
590
591
                    // Find all class implements, class can implement many interfaces
592
                    if (preg_match_all('/\s+implements\s+(?<classes>.*)/i', $php, $matches)) {
593
                        $replace = $matches[0][0];
594
                        foreach (explode(',', $matches['classes'][0]) as $classname) {
595
                            $replace = $this->transformClassName($classname, $classname, $replace, $ns);
596
                        }
597
598
                        $php = str_replace($matches[0][0], $replace, $php);
599
                    }
600
601
                    // Find all class extends
602
                    if (preg_match_all('/\s+extends\s+(?<classname>[^\s]+)/i', $php, $matches)) {
603
                        $php = $this->changeClassName($matches, $php, $ns);
604
                    }
605
606
                    // Find all class creation
607
                    if (preg_match_all('/[\.\,\(\s\n=:]+\s*new\s+(?<classname>[^\(]+)\s*\(/i', $php, $matches)) {
608
                        $php = $this->changeClassName($matches, $php, $ns);
609
                    }
610
611
                    // Find all class hints
612
                    if (preg_match_all('/(\(|\,)\s*(?:array|(?<classname>[\\\a-z_0-9]+))\s*(\&|\$)/i', $php, $matches)) {
613
                        $php = $this->changeClassName($matches, $php, $ns);
614
                    }
615
616
                    // Replace special word with its value
617
                    $php = str_replace('__NAMESPACE__', '\'' . $ns . '\'', $php);
618
                }
619
620
                // Just concatenate file code
621
                $php_code .= $php;
622
            }
623
624
            // Close namespace if we support
625
            if (!$no_ns) $php_code .= "\n" . '}';
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
626
        }
627
628
        return $php_code;
629
    }
630
631
    public function code_array_combine(array & $source, array & $target)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::code_array_combine" is not in camel caps format
Loading history...
632
    {
633
        foreach ($source as $ns => $files) {
634
            // Если в целевом массиве нет нужного NS - создадим
635
            if (!isset($target[$ns])) $target[$ns] = array();
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
636
637
            // Запишем содержание NS/Files
638
            foreach ($files as $file => $php) {
639
                if (isset($target[$ns][$file]) && is_string($php)) $target[$ns][$file] .= $php;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
640
                else if (isset($target[$ns][$file]) && is_array($php)) {
641
                    $target[$ns][$file] = array_unique(array_merge($target[$ns][$file], $php));
642
                } else $target[$ns][$file] = $php;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
643
            }
644
        }
645
    }
646
647
    /**
648
     * Выполнить рекурсивное "собирание" файла
649
     *
650
     * @param string $path Абсолютный путь к файлу сайта
651
     *
652
     * @param null $module
653
     * @param array $code
654
     * @param string $namespace
655
     *
656
     * @return string
657
     */
658
    public function compress_php($path, $module = NULL, & $code = array(), $namespace = self::NS_GLOBAL)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::compress_php" is not in camel caps format
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
659
    {
660
        // TODO: Довести до ума разпознование require - убрать точку с зяпятоц которая остается
661
        // TODO: Убрать пустые линии
662
        // TODO: Анализатор использования функция и переменных??
663
664
        //trace(' + Вошли в функцию:'.$path.'('.$namespace.')');
665
        $_path = $path;
666
        $path = normalizepath(realpath($path));
667
668
        // Если мы уже подключили данный файл или он не существует
669 View Code Duplication
        if (isset($this->files[$path])) return $this->log('    ! Файл: [##], already compressed', $path);
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
670
        else if (!is_file($path)) return $this->log('    ! Файл: [##], не существует', $_path);
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
671
        else if (strpos($path, 'vendor/autoload.php') !== false) return $this->log('    Ignoring composer autoloader [##]', $path);
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
672
        else if (in_array(basename($path), $this->ignoredFiles)) {
673
            return $this->log('    Ignoring file[##] by configuration', $path);
674
        }
675
676
677
        $this->log('   -- Compressing file [##]', $path);
678
679
        // Load file
680
        require_once($path);
681
682
        //trace('Чтение файла: '.$path );
683
684
        // Сохраним файл
685
        $this->files[$path] = $path;
686
687
        // Относительный путь к файлу
688
        if (isset($rel_path)) $this->files[$rel_path] = $path;
0 ignored issues
show
Bug introduced by
The variable $rel_path seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
689
690
        // Прочитаем php файл
691
        $fileStr = file_get_contents($path);
692
693
        // Если в файле нет namespace - считаем его глобальным
694
        if (strpos($fileStr, 'namespace') === false)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
695
696
            //$file_dir = '';
697
            // Вырежим путь к файлу
698
            //$file_dir = (pathinfo( $path, PATHINFO_DIRNAME ) == '.' ? '' : pathinfo( $path, PATHINFO_DIRNAME ).'/');
699
700
            // Сюда соберем код программы
701
            $main_code = '';
0 ignored issues
show
Unused Code introduced by
$main_code is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
702
        $main_code = "\n" . '// Модуль: ' . m($module)->id() . ', файл: ' . $path . "\n";
0 ignored issues
show
Deprecated Code introduced by
The function m() has been deprecated with message: Use $this->system->module() in module context

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
703
704
        // Создадим уникальную коллекцию алиасов для NS
705
        if (!isset($code[$namespace]['uses'])) $code[$namespace]['uses'] = array();
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
706
707
        // Установим ссылку на коллекцию алиасов
708
        $uses = &$code[$namespace]['uses'];
709
710
        // Local file uses collection
711
        $file_uses = array();
712
713
        // Получим константы документа
714
        $consts = get_defined_constants();
715
716
        // Маркеры для отрезания специальных блоков которые не нужны в PRODUCTION
717
        $rmarker_st = '\/\/\[PHPCOMPRESSOR\(remove\,start\)\]';
718
        $rmarker_en = '\/\/\[PHPCOMPRESSOR\(remove\,end\)\]';
719
720
        // Найдем все "ненужные" блоки кода и уберем их
721
        $fileStr = preg_replace('/' . $rmarker_st . '.*?' . $rmarker_en . '/uis', '', $fileStr);
722
723
        $className = '';
724
        $classConstList = array();
725
726
        //TODO: Fix to normal external dependency with ResourceRouter
727
        $fileStr = preg_replace_callback('/(\\\\samson\\\\resourcer\\\\)?ResourceRouter::url\((\'|\")(?<path>[^,)]+)(\'|\")(,(?<module>[^)]+))?\);/i', array($this, 'rewriteResourceRouter'), $fileStr);
728
729
        /** @var bool $classStared Flag for matching trait uses */
730
        $classStared = false;
731
732
        // Разберем код программы
733
        $tokens = token_get_all($fileStr);
734
        for ($i = 0; $i < sizeof($tokens); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
735
            // Получим следующий жетон из кода программы
736
            $token = $tokens[$i];
737
738
            // Если просто строка
739
            if (is_string($token)) $main_code .= $token;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
740
            // Если это специальный жетон
741
            else {
742
                // token array
743
                list($id, $text) = $token;
744
745
                // Перебирем тип комманды
746
                switch ($id) {
747
                    case T_COMMENT: // Пропускаем все комментарии
748
                    case T_DOC_COMMENT:
749
                    case T_CLOSE_TAG: // Начало,конец файла
750
                    case T_OPEN_TAG:
751
                        break;
752
753
                    case T_WHITESPACE:
754
                        $main_code .= $text; /*$main_code .= ' ';*/
755
                        break;
756
757
                    // Обработаем алиасы
758
                    case T_USE:
759
                        $_use = '';
760
761
                        // Переберем все что иде после комманды алиаса
762
                        for ($j = $i + 1; $j < sizeof($tokens); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
763
                            // Получим идентификатор метки и текстовое представление
764
                            $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
765
                            $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
766
767
                            //trace('"'.$id.'" - "'.$text.'"');
768
769
                            // Если use используется в функции
770
                            if ($id == '(') {
771
                                $j--;
772
                                break;
773
                            }
774
775
                            // Если это закрывающая скобка - прекратим собирание пути к файлу
776
                            if ($id == ';') break;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
777
778
                            // Все пробелы игнорирую
779
                            if ($id == T_WHITESPACE) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
780
781
                            // Если у метки есть текстовое представление
782
                            if (isset($text)) {
783
                                // Если єто константа
784
                                if (isset($consts[$text])) $_use .= $consts[$text];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
785
                                // Если это путь
786
                                else $_use .= $text;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
787
                            }
788
                        }
789
790
                        // Если это не use в inline функции - добавим алиас в коллекцию
791
                        // для данного ns с проверкой на уникальность
792
                        if ($id !== '(') {
793
                            // If this tait use
794
                            if ($classStared) {
795
                                // Consider rewriting trait usage fully qualified name
796
                                //TODO: Not fully qualified trait name adds slash before
797
                                $_use = strpos($_use, '\\') === false
798
                                ? '\\' . $namespace . '\\' . $_use
799
                                : $_use;
800
801
                                // TODO: Import trait code
802
                                if (!trait_exists($_use)) {
803
                                    throw new \Exception('Trait "' . $_use . '" does not exists in "' . $path . '"');
804
                                } else {
805
                                    $main_code .= ' use ' . $_use . ';';
806
                                }
807
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
808
                            } else {
809
                                // Преведем все use к одному виду
810
                                if ($_use{0} !== '\\') {
811
                                    $_use = '\\' . $_use;
812
                                }
813
814
                                // Add local file uses
815
                                $file_uses[] = $_use;
816
817
                                // TODO: Вывести замечание что бы код везде был одинаковый
818
                                if (!in_array($_use, $uses)) {
819
                                    $uses[] = $_use;
820
                                }
821
                            }
822
                        } else {
823
                            $main_code .= ' use ';
824
                        }
825
826
                        // Сместим указатель чтения файла
827
                        $i = $j;
828
829
                        break;
830
831 View Code Duplication
                    case T_NAMESPACE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
832
833
                        // Определим временное пространство имен
834
                        $_namespace = '';
835
836
                        // Переберем все что иде после комманды подключения файла
837
                        for ($j = $i + 1; $j < sizeof($tokens); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
838
                            // Получим идентификатор метки и текстовое представление
839
                            $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
840
                            $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
841
842
                            //trace('"'.$id.'" - "'.$text.'"');
843
844
                            // Если это закрывающая скобка - прекратим собирание пути к файлу
845
                            if ($id == ')' || $id == ';' || $id == '{') break;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
846
847
                            // Все пробелы игнорирую
848
                            if ($id == T_WHITESPACE) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
849
850
                            // Если у метки есть текстовое представление
851
                            if (isset($text)) {
852
                                // Если єто константа
853
                                if (isset($consts[$text])) $_namespace .= $consts[$text];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
854
                                // Если это путь
855
                                else $_namespace .= $text;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
856
                            }
857
                        }
858
859
                        // Если найденный NS отличается от текущего - установим переход к новому NS
860
                        if ($namespace !== $_namespace) {
861
                            // Сохраним новый как текущий
862
                            $namespace = strtolower($_namespace);
863
864
                            //trace('               #'.$i.' -> Изменили NS с '.$namespace.' на '.$_namespace);
865
866
                            // Если мы еще не создали данный NS
867
                            if (!isset($code[$namespace])) $code[$namespace] = array();
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
868
                            // Создадим уникальную коллекцию алиасов для NS
869
                            if (!isset($code[$namespace]['uses'])) $code[$namespace]['uses'] = array();
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
870
                            // Установим ссылку на коллекцию алиасов
871
                            $uses = &$code[$namespace]['uses'];
872
                        }
873
874
                        // Сместим указатель чтения файла
875
                        $i = $j;
876
877
                        break;
878
879
                    // Выделяем код подключаемых файлов
880
                    case T_REQUIRE :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
881
                    case T_REQUIRE_ONCE :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
882
                        //case T_INCLUDE :
883 View Code Duplication
                    case T_INCLUDE_ONCE: {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
884
                        // Получим путь к подключаемому файлу
885
                        $file_path = '';
886
887
                        // Переберем все что иде после комманды подключения файла
888
                        for ($j = $i + 1; $j < sizeof($tokens); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
889
                            // Получим идентификатор метки и текстовое представление
890
                            $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
891
                            $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
892
893
                            //trace('"'.$id.'" - "'.$text.'"');
894
895
                            // Если это закрывающая скобка - прекратим собирание пути к файлу
896
                            if ($id == ';') break;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
897
898
                            // Все пробелы игнорирую
899
                            if ($id == T_WHITESPACE) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
900
901
                            // Если у метки есть текстовое представление
902
                            if (isset($text)) {
903
                                // Если єто константа
904
                                if (isset($consts[$text])) $file_path .= $consts[$text];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
905
                                // Если это путь
906
                                else $file_path .= $text;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
907
                            }
908
                        }
909
910
                        // Если указан путь к файлу
911
                        if (isset($file_path{1})) {
912
                            // Уберем ковычки
913
                            $file_path = str_replace(array("'", '"'), array('', ''), $file_path);
914
915
                            // Если это не абсолютный путь - попробуем относительный
916
                            if (!file_exists($file_path)) $file_path = pathname($path) . $file_path;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
917
918
                            // Если файл найден - получим его содержимое
919
                            if (file_exists($file_path)) {
920
                                //trace('Углубляемся в файл:'.$file_path.'('.$namespace.')');
921
922
                                // Углубимся в рекурсию
923
                                $this->compress_php($file_path, $module, $code, $namespace);
924
925
                                // Измением позицию маркера чтения файла
926
                                $i = $j + 1;
927
                            }
928
                        } else {
929
                            $main_code .= $text;
930
                        }
931
932
                    }
933
                        break;
934
935
                    case T_INTERFACE:
936
                    case T_CLASS:
937
                        $classStared = true;
938
                        $main_code .= $text;
939
                        for ($j = $i + 1; $j < sizeof($tokens); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
940
                            // Get id and text of token
941
                            $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
942
                            $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
943
944
                            // Ignore all whitespace
945
                            if ($id == T_WHITESPACE) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
946
947
                            if (isset($text)) {
948
                                $className = $text;
949
                                break;
950
                            }
951
                        }
952
953
                        break;
954
955
                    case T_CONST:
956
                        $main_code .= $text;
957
                        $classConst = array();
958
                        $nameFlag = 'name';
959
                        for ($j = $i + 1; $j < sizeof($tokens); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
960
                            // Get id and text of token
961
                            $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
962
                            $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
963
                            if ($id == ';') break;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
964
965
                            // Ignore all whitespace
966
                            if ($id == T_WHITESPACE) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
967
968
                            if ($id == '=') {
969
                                $nameFlag = 'value';
970
                                continue;
971
                            }
972
973
                            if (isset($text)) {
974
                                // Is it defined constant
975
                                if (isset($consts[$text])) $classConst[$nameFlag] = $consts[$text];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
976
                                else $classConst[$nameFlag] = $text;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
977
                            }
978
                        }
979
                        $classConstList[$classConst['name']] = $classConst['value'];
980
981
                        break;
982
983
                    // Собираем основной код программы
984
                    default:
985
                        $main_code .= $text;
986
                        break;
987
                }
988
            }
989
        }
990
991
992
        // Replace all class shortcut usage with full name
993
        if (count($file_uses)) {
994
            $main_code = $this->removeUSEStatement($main_code, $file_uses);
995
        }
996
997
        $matches = array();
998
        if ($className == 'Module') {
999
            $temp = '';
0 ignored issues
show
Unused Code introduced by
$temp is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1000
        }
1001
1002
        if (preg_match_all('/(?<start>[(=+-\/*%., \n\t])(?<class>[\\\\a-zA-Z_]+)::(?<name>[a-zA-Z_]+)(?<end>[):;=+-\/*%., \n\t])/i', $main_code, $matches)) {
1003
            for ($i = 0; $i < sizeof($matches['name']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1004
                $matchClass = $matches['class'][$i];
1005
                // If this is self - use current file class
1006
                if ($matches['class'][$i] === 'self') {
1007
                    $constantName = $namespace . '\\' . $className;
1008
                } elseif ($matches['class'][$i] == $className) {
1009
                    // If this is current class add namespace
1010
                    $constantName = $namespace . '\\' . $className;
1011
                } elseif ($matches['class'][$i] === 'parent') {
1012
                    continue;
1013
                } elseif ($matches['class'][$i] === 'static') {
1014
                    continue;
1015
                } else {
1016
                    $constantName = $matches['class'][$i];
1017
                }
1018
1019
                // If constant has no namespace - use current
1020
                if (strpos($constantName, '\\') === false) {
1021
                    $constantName = $namespace . '\\' . $constantName;
1022
                }
1023
1024
                // Add constant name
1025
                $constantName .= '::' . $matches['name'][$i];
1026
1027
                $replaceName = $matches['start'][$i] . $matchClass . '::' . $matches['name'][$i] . $matches['end'][$i];
1028
1029
                // Check if we have this constant defined
1030
                if (defined($constantName)) {
1031
                    // Get constant value
1032
                    $value = constant($constantName);
1033
                    // Fix slashes, add quotes for string
1034
                    $value = is_string($value) ? str_replace('\\', '\\\\\\\\', "'" . $value . "'") : $value;
1035
                    $replacer = str_replace('\\', '\\\\', $replaceName);
1036
                    $replacer = str_replace(array(')','('), array('\)', '\('), $replacer);
1037
                    // Replace constant call in the code
1038
                    $main_code = preg_replace(
1039
                        '/' . $replacer . '/i', //([;=+-\/*%., ])
1040
                        $matches['start'][$i] . $value . $matches['end'][$i],
1041
                        $main_code
1042
                    );
1043
                }
1044
            }
1045
        }
1046
        // Запишем в коллекцию кода полученный код
1047
        $code[$namespace][$path] = $main_code;
1048
1049
        return $main_code;
1050
    }
1051
1052
    /**
1053
     * Transform class name with namespace to PHP 5.2 format
1054
     * @param $source
1055
     * @param $className
1056
     * @param $php
1057
     * @param $ns
1058
     *
1059
     * @return mixed
1060
     */
1061
    private function transformClassName($source, $className, $php, $ns)
1062
    {
1063
        // Create copy
1064
        $nClassName = trim($className);
1065
1066
        // If this class uses other namespace or in global namespace
1067
        if (strrpos($nClassName, '\\') > 0) {
1068
            // If this is full class name
1069
            if ($nClassName{0} == '\\') {
1070
                // Remove global name space character from beginning
1071
                $nClassName = substr($nClassName, 1);
1072
            }
1073
1074
            // Transform namespace
1075
            $nClassName = str_replace('\\', '_', $nClassName);
1076
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1077
        } else if ($nClassName{0} == '\\') { // This is global namespace class
1078
            // Remove first character "\"
1079
            $nClassName = substr($nClassName, 1);
1080
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1081
        } else { // No name space in class name
1082
            // Create old-styled namespace format
1083
            $nClassName = str_replace('\\', '_', $ns) . '_' . $nClassName;
1084
        }
1085
1086
        // Replace class name in source
1087
        $replace = str_replace($className, $nClassName, $source);
1088
1089
        if (strpos($source, 'm(')) {
1090
            //trace($source, true);
1091
        }
1092
1093
        // Replace code
1094
        $php = str_ireplace($source, $replace, $php);
1095
1096
        //trace('Changing class name('.$ns.')"'.htmlentities(trim($className)).'" with "'.htmlentities(trim($nClassName)).'"');
1097
        //trace('Replacing "'.htmlentities(trim($source)).'" with "'.htmlentities(trim($replace)).'"');
1098
1099
        return $php;
1100
    }
1101
1102
    /**
1103
     * Remove blank lines from code
1104
     * http://stackoverflow.com/questions/709669/how-do-i-remove-blank-lines-from-text-in-php
1105
     * @param string $code Code for removing blank lines
1106
     * @return string Modified code
1107
     */
1108
    protected function removeBlankLines($code)
1109
    {
1110
        // New line is required to split non-blank lines
1111
        return preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $code);
1112
    }
1113
1114
    /** Change class name to old format without namespace */
1115
    private function changeClassName($matches, $php, $ns, $uses = array())
1116
    {
1117
        // Iterate all class name usage matches
1118
        for ($i = 0; $i < sizeof($matches[0]); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1119
            // Get source matching string
1120
            $source = $matches[0][$i];
1121
1122
            // Get found classname
1123
            $className = &$matches['classname'][$i];
1124
1125
            // If class name found or this is variable
1126
            if (!isset($className) || !isset($className{0}) || strpos($className, '$') !== false) {
1127
                continue;
1128
            }
1129
1130
            // Transform class name
1131
            $php = $this->transformClassName($source, $className, $php, $ns, $uses);
0 ignored issues
show
Unused Code introduced by
The call to Compressor::transformClassName() has too many arguments starting with $uses.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1132
        }
1133
1134
        return $php;
1135
    }
1136
1137
    /**
1138
     * Copy resources
1139
     */
1140
    private function copy_path_resources($path_resources, $module_path, $module_output_path)
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::copy_path_resources" is not in camel caps format
Loading history...
1141
    {
1142
        $this->log(' -> Copying resources from [##] to [##]', $module_path, $module_output_path);
1143
1144
        // Iterate module resources
1145
        foreach ($path_resources as $extension => $resources) {
1146
            foreach ($resources as $resource) {
1147
                // Build relative module resource path
1148
                $relative_path = str_replace($module_path, '', $resource);
1149
1150
                $this->resourceManager->compress($resource, $this->output . $module_output_path . $relative_path);
1151
            }
1152
        }
1153
    }
1154
1155
    /**
1156
     * Remove all USE statements and replace class shortcuts to full class names
1157
     *
1158
     * @param string $code Code to work with
1159
     * @param array $classes Array of class names to replace
1160
     *
1161
     * @return bool|mixed|string
1162
     */
1163
    private function removeUSEStatement($code, array $classes)
1164
    {
1165
        // Iterate found use statements
1166
        foreach (array_unique($classes) as $full_class) {
1167
            // Ignore trait uses
1168
            if (trait_exists($full_class)) {
1169
                continue;
1170
            }
1171
1172
            // Get class shortcut
1173
            $class_name = \samson\core\AutoLoader::getOnlyClass($full_class);
1174
1175
            // Check class existance
1176
            if (!class_exists($full_class) && !interface_exists($full_class)) {
1177
                //return e('Found USE statement for undeclared class ##', E_SAMSON_FATAL_ERROR, $full_class);
1178
                continue;
1179
            }
1180
1181
            // Replace class static call
1182
            $code = preg_replace('/([^\\\a-z])' . $class_name . '::/i', '$1' . $full_class . '::', $code);
1183
1184
            // Replace class implements calls
1185
            $code = preg_replace('/\s+implements(.*\W)' . $class_name . '([^\\\])/i', ' implements $1' . $full_class . '$2 ', $code);
1186
1187
            // Handle instanceof operator
1188
            $code = preg_replace('/instanceof\s+' . $class_name . '/i', 'instanceof ' . $full_class . '', $code);
1189
1190
            // Replace class extends calls
1191
            $code = preg_replace('/extends\s+' . $class_name . '/i', 'extends ' . $full_class . '', $code);
1192
1193
            // Replace multiple class extends calls
1194
            $code = preg_replace('/\s+extends(.*\W),?\s' . $class_name . '([^\\\])/i', ' extends $1' . $full_class . '$2 ', $code);
1195
1196
            // Replace class hint calls
1197
            $code = preg_replace('/(\(|\s|\,)\s*' . $class_name . '\s*(&|$)/i', '$1' . $full_class . ' $2', $code);
1198
1199
            // Replace class creation call
1200
            $code = preg_replace('/new\s+' . $class_name . '\s*\(/i', 'new ' . $full_class . '(', $code);
1201
1202
            // Replace annotations
1203
            $code = preg_replace('/([, (])' . $class_name . '\s\$/i', '$1 $2' . $full_class . ' $', $code);
1204
        }
1205
1206
        return $code;
1207
    }
1208
1209
    /**
1210
     * Преобразовать коллекцию имен классов в коллекцию
1211
     * [Namespace][ ClassFileName ]
1212
     *
1213
     * @param array $collection Коллекция имен классов
1214
     * @param array $classes Коллекция для возврата результатов
1215
     */
1216
    private function classes_to_ns_files($collection, & $classes = array())
0 ignored issues
show
Coding Style introduced by
Method name "Compressor::classes_to_ns_files" is not in camel caps format
Loading history...
1217
    {
1218
        // Соберем коллекцию загруженных интерфейсов их файлов по пространствам имен
1219
        foreach ($collection as $class) {
1220
            $ac = new \ReflectionClass($class);
1221
1222
            $ns = $ac->getNamespaceName();
1223
1224
            if ($ns != '') {
1225
                $ns = strtolower($ns);
1226
1227
                if (!isset($classes[$ns])) {
1228
                    $classes[$ns] = array();
1229
                }
1230
1231
                $classes[$ns][normalizepath($ac->getFileName())] = '';
1232
            }
1233
        }
1234
    }
1235
}
1236