Completed
Pull Request — develop (#509)
by ANTHONIUS
21:03
created

Application::generateVersion()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 9.488
c 0
b 0
f 0
cc 4
nc 4
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
use SebastianBergmann\Version;
20
21
/**
22
 * Yawik Custom MVC Application
23
 *
24
 * @package Core
25
 * @author Anthonius Munthi <[email protected]>
26
 * @since 0.32
27
 */
28
class Application extends BaseApplication
29
{
30
    /**
31
     * Current yawik revision
32
     * @var string
33
     */
34
    public static $revision;
35
36
    /**
37
     * A short version of package
38
     * @var string
39
     */
40
    public static $version;
41
42
    /**
43
     * Current yawik environment
44
     * @var string
45
     */
46
    public static $env;
47
48
    /**
49
     * Current yawik config directory
50
     * @var string
51
     */
52
    private static $configDir;
53
54
    /**
55
     * @return string
56
     */
57
    public static function getCompleteVersion()
58
    {
59
        return sprintf('%s@%s', static::$version, static::$revision);
60
    }
61
62
    /**
63
     * Get required modules for Yawik
64
     *
65
     * @return array
66
     */
67
    public static function getRequiredModules()
68
    {
69
        return array(
70
            'Zend\ServiceManager\Di',
71
            'Zend\Session',
72
            'Zend\Router',
73
            'Zend\Navigation',
74
            'Zend\I18n',
75
            'Zend\Filter',
76
            'Zend\InputFilter',
77
            'Zend\Form',
78
            'Zend\Validator',
79
            'Zend\Log',
80
            'Zend\Mvc\Plugin\Prg',
81
            'Zend\Mvc\Plugin\Identity',
82
            'Zend\Mvc\Plugin\FlashMessenger',
83
            'Zend\Mvc\I18n',
84
            'Zend\Mvc\Console',
85
            'Zend\Hydrator',
86
            'Zend\Serializer',
87
            'DoctrineModule',
88
            'DoctrineMongoODMModule',
89
        );
90
    }
91
92
    /**
93
     * Generate modules to be loaded for Yawik application
94
     *
95
     * @param array $loadModules
96
     * @return array
97
     */
98
    public static function generateModuleConfiguration($loadModules=[])
99
    {
100
        $modules = ArrayUtils::merge(
101
            static::getRequiredModules(),
102
            $loadModules
103
        );
104
        return $modules;
105
    }
106
107
    /**
108
     * Get config directory location
109
     *
110
     * @return string Configuration directory
111
     */
112
    public static function getConfigDir()
113
    {
114
        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...
115
            $configDir = '';
116
            $dirs = [
117
                // path/to/module/test/sandbox/config directories
118
                __DIR__.'/../../../../*/sandbox/config',
119
120
                // path/to/yawik-standard/config
121
                __DIR__.'/../../../config',
122
            ];
123
            foreach ($dirs as $dir) {
124
                foreach (glob($dir) as $testDir) {
125
                    $configDir = $testDir;
126
                    break;
127
                }
128
                if (is_dir($configDir)) {
129
                    break;
130
                }
131
            }
132
133
            if (!is_dir($configDir)) {
134
                throw new InvalidArgumentException('Can not determine which config directory to be used.');
135
            }
136
137
            static::$configDir = $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...
138
        }
139
        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...
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145
    public static function init($configuration = [])
146
    {
147
        if (!version_compare(PHP_VERSION, '5.6.0', 'ge')) {
148
            echo sprintf('<p>Sorry, YAWIK requires at least PHP 5.6.0 to run, but this server currently provides PHP %s</p>', PHP_VERSION);
149
            echo '<p>Please ask your servers\' administrator to install the proper PHP version.</p>';
150
            exit;
151
        }
152
153
        ini_set('display_errors', true);
154
        ini_set('error_reporting', E_ALL | E_STRICT);
155
156
        static::loadDotEnv();
157
158
        if (isset($configuration['config_dir'])) {
159
            static::$configDir = $configuration['config_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...
160
        }
161
        static::generateVersion();
0 ignored issues
show
Bug introduced by
Since generateVersion() 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 generateVersion() 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...
162
        $configuration = static::loadConfig($configuration);
163
        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...
164
        return parent::init($configuration);
165
    }
166
167
    /**
168
     * Check current cache status
169
     * @param array $configuration
170
     */
171
    private static function checkCache(array $configuration)
172
    {
173
        $config = $configuration['module_listener_options'];
174
        $options = new ListenerOptions($config);
175
        $cache = new ClearCacheService($options);
176
        $cache->checkCache();
177
    }
178
179
    /**
180
     * Setup php server
181
     * @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...
182
     * @codeCoverageIgnore
183
     */
184
    public static function setupCliServerEnv()
185
    {
186
        $parseUrl = parse_url(substr($_SERVER["REQUEST_URI"], 1));
187
        $route = isset($parseUrl['path']) ? $parseUrl['path']:null;
188
        if (is_file(__DIR__ . '/' . $route)) {
189
            if (substr($route, -4) == ".php") {
190
                require __DIR__ . '/' . $route;     // Include requested script files
191
                exit;
192
            }
193
            return false;           // Serve file as is
194
        } else {                    // Fallback to index.php
195
            $_GET["q"] = $route;    // Try to emulate the behaviour of a .htaccess here.
196
        }
197
        return true;
198
    }
199
200
    /**
201
     * Load environment variables from .env files
202
     */
203
    public static function loadDotEnv()
204
    {
205
        static $isLoaded=false;
206
        if ($isLoaded) {
207
            return;
208
        }
209
210
        $dotenv = new Dotenv();
211
        if (is_file(getcwd().'/.env.dist')) {
212
            $dotenv->load(getcwd().'/.env.dist');
213
        }
214
        if (is_file($file = getcwd().'/.env')) {
215
            $dotenv->load($file);
216
        }
217
218
        if (!is_string(getenv('TIMEZONE'))) {
219
            putenv('TIMEZONE=Europe/Berlin');
220
        }
221
        date_default_timezone_set(getenv('TIMEZONE'));
222
        $isLoaded = true;
223
    }
224
225
    /**
226
     * Load Application configuration
227
     * @param array $configuration
228
     * @return array
229
     */
230
    public static function loadConfig($configuration = [])
231
    {
232
        $configDir = static::getConfigDir();
233
        if (empty($configuration)) {
234
            $configFile = $configDir.'/config.php';
235
            if (!is_file($configFile)) {
236
                throw new InvalidArgumentException(sprintf(
237
                    'Can not load config file "%s". Please be sure that this file exists and readable',
238
                    $configFile
239
                ));
240
            }
241
            $configuration = include $configFile;
242
        }
243
244
245
        $isCli = php_sapi_name() === 'cli';
246
247
        // load modules
248
        $modules = $configuration['modules'];
249
        $modules = static::generateModuleConfiguration($modules);
250
251
        $yawikConfig = $configDir.'/autoload/yawik.config.global.php';
252
        $installMode = false;
253
        if (!$isCli && !file_exists($yawikConfig)) {
254
            $modules = static::generateModuleConfiguration(['Install']);
255
            $installMode = true;
256
        } elseif (in_array('Install', $modules)) {
257
            $modules = array_diff($modules, ['Install']);
258
        }
259
260
        static::$env = $env = getenv('APPLICATION_ENV') ?: 'production';
261
        $defaults = [
262
            'module_listener_options' => [
263
                'module_paths' => [
264
                    './module',
265
                    './vendor',
266
                    './modules'
267
                ],
268
                // What configuration files should be autoloaded
269
                'config_glob_paths' => [
270
                    sprintf($configDir.'/autoload/{,*.}{global,%s,local}.php', $env)
271
                ],
272
273
                // Use the $env value to determine the state of the flag
274
                // caching disabled during install mode
275
                'config_cache_enabled' => ($env == 'production'),
276
277
278
                // Use the $env value to determine the state of the flag
279
                'module_map_cache_enabled' => ($env == 'production'),
280
281
                'module_map_cache_key' => 'module_map',
282
283
                // Use the $env value to determine the state of the flag
284
                'check_dependencies' => ($env != 'production'),
285
286
                'cache_dir' => getcwd()."/var/cache",
287
            ],
288
        ];
289
290
        $envConfig = [];
291
        $envConfigFile = $configDir.'/config.'.$env.'.php';
292
        if (file_exists($envConfigFile)) {
293
            if (is_readable($envConfigFile)) {
294
                $envConfig = include $envConfigFile;
295
            } else {
296
                \trigger_error(
297
                    sprintf('Environment config file "%s" is not readable.', $envConfigFile),
298
                    E_USER_NOTICE
299
                );
300
            }
301
        }
302
303
        // configuration file always win
304
        $configuration = ArrayUtils::merge($defaults, $configuration);
305
        // environment config always win
306
        $configuration = ArrayUtils::merge($configuration, $envConfig);
307
308
        $configuration['modules'] = $modules;
309
310
        // force disabled cache when in install mode
311
        if ($installMode) {
312
            $configuration['module_listener_options']['config_cache_enabled'] = false;
313
            $configuration['module_listener_options']['module_map_cache_enabled'] = false;
314
        }
315
316
        // setup docker environment
317
        if (getenv('DOCKER_ENV')=='yes') {
318
            $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...
319
        }
320
        return $configuration;
321
    }
322
323
    /**
324
     * Override configuration in docker environment
325
     * This will fix filesystem writing during behat tests
326
     * @param $configuration
327
     * @return array
328
     */
329
    private static function getDockerEnv($configuration)
330
    {
331
        // add doctrine hydrator
332
        $cacheDir = $configuration['module_listener_options']['cache_dir'].'/docker';
333
        $configDir = static::getConfigDir();
334
        $hydratorDir = $cacheDir.'/Doctrine/Hydrator';
335
        $proxyDir = $cacheDir.'/Doctrine/Proxy';
336
        if (!is_dir($hydratorDir)) {
337
            mkdir($hydratorDir, 0777, true);
338
        }
339
        if (!is_dir($proxyDir)) {
340
            mkdir($proxyDir, 0777, true);
341
        }
342
        return [
343
            'module_listener_options' => [
344
                'cache_dir' => $cacheDir,
345
                'config_glob_paths' => [
346
                    $configDir.'/autoload/*.docker.php',
347
                ]
348
            ],
349
            'doctrine' => [
350
                'configuration' => [
351
                    'odm_default' => [
352
                        'hydrator_dir' => $hydratorDir,
353
                        'proxy_dir' => $proxyDir,
354
                    ]
355
                ]
356
            ]
357
        ];
358
    }
359
360
    private static function generateVersion()
361
    {
362
        if (is_null(static::$revision)) {
363
            $dirs = [
364
                // in vendors or modules directory
365
                __DIR__.'/../.git',
366
367
                // in development mode
368
                __DIR__.'/../../../.git',
369
            ];
370
371
            $path = realpath(dirname(__DIR__));
372
373
            foreach ($dirs as $dir) {
374
                if (is_dir($dir)) {
375
                    $path = dirname(realpath($dir));
376
                    break;
377
                }
378
            }
379
            $info = new Version(Module::VERSION, $path);
380
381
            //$exp = explode("@", $info);
382
            $version = $info->getVersion();
383
            static::$version = substr($version, 0, strlen($version)-10);
384
            static::$revision = substr($version, 10);
385
        }
386
    }
387
}
388