Completed
Push — develop ( 911e58...200791 )
by Carsten
13s
created

Application::getCompleteVersion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * YAWIK
5
 *
6
 * @filesource
7
 * @copyright (c) 2013 - 2018 Cross Solution (http://cross-solution.de)
8
 * @license   MIT
9
 */
10
11
namespace Core;
12
13
use Core\Service\ClearCacheService;
14
use Symfony\Component\Dotenv\Dotenv;
15
use Zend\Config\Exception\InvalidArgumentException;
16
use Zend\ModuleManager\Listener\ListenerOptions;
17
use Zend\Mvc\Application as BaseApplication;
18
use Zend\Stdlib\ArrayUtils;
19
20
/**
21
 * Yawik Custom MVC Application
22
 *
23
 * @package Core
24
 * @author Anthonius Munthi <[email protected]>
25
 * @since 0.32
26
 */
27
class Application extends BaseApplication
0 ignored issues
show
Coding Style introduced by
Application does not seem to conform to the naming convention (Utils?$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
28
{
29
    const VERSION = '0.32-dev';
30
31
    /**
32
     * Current yawik revision
33
     * @var string
34
     */
35
    public static $revision;
36
37
    /**
38
     * Current yawik environment
39
     * @var string
40
     */
41
    public static $env;
42
43
    /**
44
     * Current yawik config directory
45
     * @var string
46
     */
47
    private static $configDir;
48
49
    public static function getCompleteVersion()
50
    {
51
        //@TODO: provide better way to handle git versioning
52
        //$isVendor = strpos(__FILE__, 'modules')!==false || strpos(__FILE__, 'vendor') !== false;
53
        //$version = getenv('TRAVIS') || $isVendor ? "undefined":exec('git describe');
54
        //$branch = getenv('TRAVIS') || $isVendor ? "undefined":exec('git rev-parse --abbrev-ref HEAD', $output, $retVal);
55
        //static::$revision = $version.'['.$branch.']';
56
        return static::VERSION;
57
    }
58
59
    /**
60
     * Get required modules for Yawik
61
     *
62
     * @return array
63
     */
64 View Code Duplication
    public static function getRequiredModules()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
65
    {
66
        return array(
67
            'Zend\ServiceManager\Di',
68
            'Zend\Session',
69
            'Zend\Router',
70
            'Zend\Navigation',
71
            'Zend\I18n',
72
            'Zend\Filter',
73
            'Zend\InputFilter',
74
            'Zend\Form',
75
            'Zend\Validator',
76
            'Zend\Log',
77
            'Zend\Mvc\Plugin\Prg',
78
            'Zend\Mvc\Plugin\Identity',
79
            'Zend\Mvc\Plugin\FlashMessenger',
80
            'Zend\Mvc\I18n',
81
            'Zend\Mvc\Console',
82
            'Zend\Hydrator',
83
            'Zend\Serializer',
84
            'DoctrineModule',
85
            'DoctrineMongoODMModule',
86
        );
87
    }
88
89
    /**
90
     * Generate modules to be loaded for Yawik application
91
     *
92
     * @param array $loadModules
93
     * @return array
94
     */
95
    public static function generateModuleConfiguration($loadModules=[])
96
    {
97
        $modules = array_merge(
98
            static::getRequiredModules(),
99
            $loadModules,
100
            static::scanAdditionalModule()
0 ignored issues
show
Bug introduced by
Since scanAdditionalModule() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of scanAdditionalModule() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
101
        );
102
        return $modules;
103
    }
104
105
    /**
106
     * Get config directory location
107
     *
108
     * @return string Configuration directory
109
     */
110
    public static function getConfigDir()
111
    {
112
        if (is_null(static::$configDir)) {
0 ignored issues
show
Bug introduced by
Since $configDir is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $configDir to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
113
            $dir = '';
114
            if (is_string($test = getenv('APP_CONFIG_DIR'))) {
115
                if (!is_dir($test)) {
116
                    throw new InvalidArgumentException('Directory in environment variable APP_CONFIG_DIR is not exists.');
117
                }
118
                $dir = realpath($test);
119
            } elseif (is_dir($test = getcwd().'/test/sandbox/config')) {
120
                // module development
121
                $dir = $test;
122
            } elseif (is_dir($test = getcwd().'/config')) {
123
                $dir = $test;
124
            }
125
126
            if (!is_dir($dir)) {
127
                throw new InvalidArgumentException('Can not determine which config directory to be used.');
128
            }
129
130
            static::$configDir = $dir;
0 ignored issues
show
Bug introduced by
Since $configDir is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $configDir to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
131
        }
132
        return static::$configDir;
0 ignored issues
show
Bug introduced by
Since $configDir is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $configDir to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138
    public static function init($configuration = [])
139
    {
140 View Code Duplication
        if (!version_compare(PHP_VERSION, '5.6.0', 'ge')) {
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...
141
            echo sprintf('<p>Sorry, YAWIK requires at least PHP 5.6.0 to run, but this server currently provides PHP %s</p>', PHP_VERSION);
142
            echo '<p>Please ask your servers\' administrator to install the proper PHP version.</p>';
143
            exit;
144
        }
145
146
        ini_set('display_errors', true);
147
        ini_set('error_reporting', E_ALL | E_STRICT);
148
149
        static::loadDotEnv();
150
151
        $configuration = static::loadConfig($configuration);
152
        static::checkCache($configuration);
0 ignored issues
show
Bug introduced by
Since checkCache() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of checkCache() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
153
        return parent::init($configuration);
154
    }
155
156
    /**
157
     * Check current cache status
158
     * @param array $configuration
159
     */
160
    private static function checkCache(array $configuration)
161
    {
162
        $config = $configuration['module_listener_options'];
163
        $options = new ListenerOptions($config);
164
        $cache = new ClearCacheService($options);
165
        $cache->checkCache();
166
    }
167
168
    /**
169
     * Scan additional module in config/autoload/*.module.php files
170
     * return array Module lists
171
     */
172
    private static function scanAdditionalModule()
173
    {
174
        $modules = [];
175
        $configDir = static::getConfigDir();
176
        foreach (glob($configDir. '/autoload/*.module.php') as $moduleFile) {
177
            $addModules = require $moduleFile;
178
            foreach ($addModules as $addModule) {
179
                if (strpos($addModule, '-') === 0) {
180
                    $remove = substr($addModule, 1);
181
                    $modules = array_filter($modules, function ($elem) use ($remove) {
182
                        return strcasecmp($elem, $remove);
183
                    });
184
                } else {
185
                    if (!in_array($addModule, $modules)) {
186
                        $modules[] = $addModule;
187
                    }
188
                }
189
            }
190
        }
191
        return $modules;
192
    }
193
194
    /**
195
     * Setup php server
196
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be null|boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
197
     * @codeCoverageIgnore
198
     */
199
    public static function setupCliServerEnv()
200
    {
201
        $parseUrl = parse_url(substr($_SERVER["REQUEST_URI"], 1));
202
        $route = isset($parseUrl['path']) ? $parseUrl['path']:null;
203 View Code Duplication
        if (is_file(__DIR__ . '/' . $route)) {
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...
204
            if (substr($route, -4) == ".php") {
205
                require __DIR__ . '/' . $route;     // Include requested script files
206
                exit;
207
            }
208
            return false;           // Serve file as is
209
        } else {                    // Fallback to index.php
210
            $_GET["q"] = $route;    // Try to emulate the behaviour of a .htaccess here.
211
        }
212
        return true;
213
    }
214
215
    /**
216
     * Load environment variables from .env files
217
     */
218
    public static function loadDotEnv()
219
    {
220
        static $isLoaded=false;
221
        if ($isLoaded) {
222
            return;
223
        }
224
225
        $dotenv = new Dotenv();
226
        $dotenv->load(getcwd().'/.env.dist');
227
        if (is_file($file = getcwd().'/.env')) {
228
            $dotenv->load($file);
229
        }
230
231
        if (!is_string(getenv('TIMEZONE'))) {
232
            putenv('TIMEZONE=Europe/Berlin');
233
        }
234
        date_default_timezone_set(getenv('TIMEZONE'));
235
        $isLoaded = true;
236
    }
237
238
    /**
239
     * Load Application configuration
240
     * @param array $configuration
241
     * @return array
242
     */
243
    public static function loadConfig($configuration = [])
244
    {
245
        $configDir = static::getConfigDir();
246
        if (empty($configuration)) {
247
            $configFile = $configDir.'/config.php';
248
            if (!is_file($configFile)) {
249
                throw new InvalidArgumentException(sprintf(
250
                    'Can not load config file "%s". Please be sure that this file exists and readable',
251
                    $configFile
252
                ));
253
            }
254
            $configuration = include $configFile;
255
        }
256
257
258
        $isCli = php_sapi_name() === 'cli';
259
260
        // load modules
261
        $modules = $configuration['modules'];
262
        $modules = static::generateModuleConfiguration($modules);
263
264
        $yawikConfig = $configDir.'/autoload/yawik.config.global.php';
265
        $installMode = false;
266
        if (!$isCli && !file_exists($yawikConfig)) {
267
            $modules = ['Install'];
268
            $installMode = true;
269
        } elseif (in_array('Install', $modules)) {
270
            $modules = array_diff($modules, ['Install']);
271
        }
272
273
        static::$env = $env = getenv('APPLICATION_ENV') ?: 'production';
274
        $defaults = [
275
            'module_listener_options' => [
276
                'module_paths' => [
277
                    './module',
278
                    './vendor',
279
                    './modules'
280
                ],
281
                // What configuration files should be autoloaded
282
                'config_glob_paths' => [
283
                    sprintf($configDir.'/autoload/{,*.}{global,%s,local}.php', $env)
284
                ],
285
286
                // Use the $env value to determine the state of the flag
287
                // caching disabled during install mode
288
                'config_cache_enabled' => ($env == 'production'),
289
290
291
                // Use the $env value to determine the state of the flag
292
                'module_map_cache_enabled' => ($env == 'production'),
293
294
                'module_map_cache_key' => 'module_map',
295
296
                // Use the $env value to determine the state of the flag
297
                'check_dependencies' => ($env != 'production'),
298
299
                'cache_dir' => getcwd()."/var/cache",
300
            ],
301
        ];
302
303
        $envConfig = [];
304
        $envConfigFile = $configDir.'/config.'.$env.'.php';
305
        if (file_exists($envConfigFile)) {
306
            if (is_readable($envConfigFile)) {
307
                $envConfig = include $envConfigFile;
308
            } else {
309
                \trigger_error(
310
                    sprintf('Environment config file "%s" is not readable.', $envConfigFile),
311
                    E_USER_NOTICE
312
                );
313
            }
314
        }
315
316
        // configuration file always win
317
        $configuration = ArrayUtils::merge($defaults, $configuration);
318
        // environment config always win
319
        $configuration = ArrayUtils::merge($configuration, $envConfig);
320
321
        // force override modules to load only install module in installation mode
322
        $modules = static::generateModuleConfiguration($modules);
323
        $configuration['modules'] = $modules;
324
325
        // force disabled cache when in install mode
326
        if ($installMode) {
327
            $configuration['module_listener_options']['config_cache_enabled'] = false;
328
            $configuration['module_listener_options']['module_map_cache_enabled'] = false;
329
        }
330
331
        // setup docker environment
332
        if (getenv('DOCKER_ENV')=='yes') {
333
            $configuration = ArrayUtils::merge($configuration, static::getDockerEnv($configuration));
0 ignored issues
show
Bug introduced by
Since getDockerEnv() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of getDockerEnv() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
334
        }
335
        return $configuration;
336
    }
337
338
    /**
339
     * Override configuration in docker environment
340
     * @param $configuration
341
     * @return array
342
     */
343
    private static function getDockerEnv($configuration)
344
    {
345
        $cacheDir = $configuration['module_listener_options']['cache_dir'].'/docker';
346
        $configDir = static::getConfigDir();
347
        return [
348
            'module_listener_options' => [
349
                'cache_dir' => $cacheDir,
350
                'config_glob_paths' => [
351
                    $configDir.'/autoload/*.docker.php',
352
                ]
353
            ]
354
        ];
355
    }
356
}
357