Completed
Push — develop ( ff69a2...5c149c )
by Carsten
25:49 queued 22:46
created

Application::loadDotEnv()   C

Complexity

Conditions 10
Paths 257

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 6.1208
c 0
b 0
f 0
cc 10
nc 257
nop 0

How to fix   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
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 Zend\Stdlib\Glob;
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
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...
29
{
30
    public static $VERSION;
0 ignored issues
show
Coding Style introduced by
$VERSION does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
31
32
    public static $env = 'production';
33
34
    private static $configDir;
35
36
    /**
37
     * Get required modules for Yawik
38
     *
39
     * @return array
40
     */
41 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...
42
    {
43
        return array(
44
            'Zend\ServiceManager\Di',
45
            'Zend\Session',
46
            'Zend\Router',
47
            'Zend\Navigation',
48
            'Zend\I18n',
49
            'Zend\Filter',
50
            'Zend\InputFilter',
51
            'Zend\Form',
52
            'Zend\Validator',
53
            'Zend\Log',
54
            'Zend\Mvc\Plugin\Prg',
55
            'Zend\Mvc\Plugin\Identity',
56
            'Zend\Mvc\Plugin\FlashMessenger',
57
            'Zend\Mvc\I18n',
58
            'Zend\Mvc\Console',
59
            'Zend\Hydrator',
60
            'Zend\Serializer',
61
            'DoctrineModule',
62
            'DoctrineMongoODMModule',
63
        );
64
    }
65
66
    /**
67
     * Generate modules to be loaded for Yawik application
68
     *
69
     * @param array $loadModules
70
     * @return array
71
     */
72
    public static function generateModuleConfiguration($loadModules=[])
73
    {
74
        $modules = ArrayUtils::merge(
75
            static::getRequiredModules(),
76
            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...
77
        );
78
        $modules = ArrayUtils::merge($modules, $loadModules);
79
        return $modules;
80
    }
81
82
    /**
83
     * Get config directory location
84
     *
85
     * @return string Configuration directory
86
     */
87
    public static function getConfigDir()
88
    {
89
        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...
90
            $dir = '';
91
            if (is_string($test = getenv('APP_CONFIG_DIR'))) {
92
                if (!is_dir($test)) {
93
                    throw new InvalidArgumentException('Directory in environment variable APP_CONFIG_DIR is not exists.');
94
                }
95
                $dir = realpath($test);
96
            } elseif (is_dir($test = getcwd().'/test/sandbox/config')) {
97
                // module development
98
                $dir = $test;
99
            } elseif (is_dir($test = getcwd().'/config')) {
100
                $dir = $test;
101
            }
102
103
            if (!is_dir($dir)) {
104
                throw new InvalidArgumentException('Can not determine which config directory to be used.');
105
            }
106
107
            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...
108
        }
109
        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...
110
    }
111
112
    /**
113
     * @inheritdoc
114
     */
115
    public static function init($configuration = [])
116
    {
117 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...
118
            echo sprintf('<p>Sorry, YAWIK requires at least PHP 5.6.0 to run, but this server currently provides PHP %s</p>', PHP_VERSION);
119
            echo '<p>Please ask your servers\' administrator to install the proper PHP version.</p>';
120
            exit;
121
        }
122
123
        ini_set('display_errors', true);
124
        ini_set('error_reporting', E_ALL | E_STRICT);
125
126
        if (php_sapi_name() == 'cli-server') {
127
            if (!static::setupCliServerEnv()) {
0 ignored issues
show
Bug introduced by
Since setupCliServerEnv() 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 setupCliServerEnv() 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...
Bug Best Practice introduced by
The expression static::setupCliServerEnv() of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
128
                return false;
129
            }
130
        }
131
132
        static::loadDotEnv();
133
134
        $configuration = static::loadConfig($configuration);
135
        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...
136
        return parent::init($configuration);
137
    }
138
139
    private static function checkCache(array $configuration)
140
    {
141
        $config = $configuration['module_listener_options'];
142
        $options = new ListenerOptions($config);
143
        $cache = new ClearCacheService($options);
144
        $cache->checkCache();
145
    }
146
147
    /**
148
     * Scan additional module in config/autoload/*.module.php files
149
     * return array Module lists
150
     */
151
    private static function scanAdditionalModule()
152
    {
153
        $modules = [];
154
        $configDir = static::getConfigDir();
155
        foreach (glob($configDir. '/autoload/*.module.php') as $moduleFile) {
156
            $addModules = require $moduleFile;
157
            foreach ($addModules as $addModule) {
158
                if (strpos($addModule, '-') === 0) {
159
                    $remove = substr($addModule, 1);
160
                    $modules = array_filter($modules, function ($elem) use ($remove) {
161
                        return strcasecmp($elem, $remove);
162
                    });
163
                } else {
164
                    if (!in_array($addModule, $modules)) {
165
                        $modules[] = $addModule;
166
                    }
167
                }
168
            }
169
        }
170
        return $modules;
171
    }
172
173
    /**
174
     * Setup php server
175
     * @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...
176
     * @codeCoverageIgnore
177
     */
178
    private static function setupCliServerEnv()
179
    {
180
        $parseUrl = parse_url(substr($_SERVER["REQUEST_URI"], 1));
181
        $route = isset($parseUrl['path']) ? $parseUrl['path']:null;
182 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...
183
            if (substr($route, -4) == ".php") {
184
                require __DIR__ . '/' . $route;     // Include requested script files
185
                exit;
186
            }
187
            return false;           // Serve file as is
188
        } else {                    // Fallback to index.php
189
            $_GET["q"] = $route;    // Try to emulate the behaviour of a .htaccess here.
190
        }
191
        return true;
192
    }
193
194
    /**
195
     * Load environment variables from .env files
196
     */
197
    public static function loadDotEnv()
198
    {
199
        static $isLoaded=false;
200
        if ($isLoaded) {
201
            return;
202
        }
203
204
        $env = getcwd().'/.env';
205
        if (!is_file($env)) {
206
            $env = getcwd().'/.env.dist';
207
        }
208
        if (is_file($env)) {
209
            $dotenv = new Dotenv();
210
            $dotenv->load($env);
211
        }
212
213
        //@TODO: should move this version loading to somewhere else
214
        $isVendor = strpos(__FILE__, 'modules')!==false || strpos(__FILE__, 'vendor') !== false;
215
        $version = getenv('TRAVIS') || $isVendor ? "undefined":exec('git describe');
216
        $branch = getenv('TRAVIS') || $isVendor ? "undefined":exec('git rev-parse --abbrev-ref HEAD', $output, $retVal);
217
        static::$VERSION = $version.'['.$branch.']';
218
219
220
        //@TODO: default timezone turns error when used
221
        if (!is_string(getenv('TIMEZONE'))) {
222
            putenv('TIMEZONE=Europe/Berlin');
223
        }
224
        date_default_timezone_set(getenv('TIMEZONE'));
225
        $isLoaded = true;
226
    }
227
228
    /**
229
     * Load Application configuration
230
     * @param array $configuration
231
     * @return array
232
     */
233
    public static function loadConfig($configuration = [])
234
    {
235
        $configDir = static::getConfigDir();
236
        if (empty($configuration)) {
237
            $configFile = $configDir.'/config.php';
238
            if (!is_file($configFile)) {
239
                throw new InvalidArgumentException(sprintf(
240
                    'Can not load config file "%s". Please be sure that this file exists and readable',
241
                    $configFile
242
                ));
243
            }
244
            $configuration = include $configFile;
245
        }
246
247
248
        $isCli = php_sapi_name() === 'cli';
249
250
        // load modules
251
        $modules = $configuration['modules'];
252
        $modules = static::generateModuleConfiguration($modules);
253
254
        $yawikConfig = $configDir.'/autoload/yawik.config.global.php';
255
        $installMode = false;
256
        if (!$isCli && !file_exists($yawikConfig)) {
257
            $modules = ['Install'];
258
            $installMode = true;
259
        } elseif (in_array('Install', $modules)) {
260
            $modules = array_diff($modules, ['Install']);
261
        }
262
263
        static::$env = $env = getenv('APPLICATION_ENV') ?: 'production';
264
        $defaults = [
265
            'module_listener_options' => [
266
                'module_paths' => [
267
                    './module',
268
                    './vendor',
269
                    './modules'
270
                ],
271
                // What configuration files should be autoloaded
272
                'config_glob_paths' => [
273
                    sprintf($configDir.'/autoload/{,*.}{global,%s,local}.php', $env)
274
                ],
275
276
                // Use the $env value to determine the state of the flag
277
                // caching disabled during install mode
278
                'config_cache_enabled' => ($env == 'production') && !$installMode,
279
280
281
                // Use the $env value to determine the state of the flag
282
                'module_map_cache_enabled' => ($env == 'production') && !$installMode,
283
284
                'module_map_cache_key' => 'module_map',
285
286
                // Use the $env value to determine the state of the flag
287
                'check_dependencies' => ($env != 'production'),
288
289
                'cache_dir' => getcwd()."/var/cache",
290
            ],
291
        ];
292
293
        $envConfig = [];
294
        $envConfigFile = $configDir.'/config.'.$env.'.php';
295
        if (file_exists($envConfigFile)) {
296
            if (is_readable($envConfigFile)) {
297
                $envConfig = include $envConfigFile;
298
            } else {
299
                \trigger_error(
300
                    sprintf('Environment config file "%s" is not readable.', $envConfigFile),
301
                    E_USER_NOTICE
302
                );
303
            }
304
        }
305
306
        // configuration file always win
307
        $configuration = ArrayUtils::merge($defaults, $configuration);
308
        // environment config always win
309
        $configuration = ArrayUtils::merge($configuration, $envConfig);
310
311
        // force override modules to load only install module in installation mode
312
        $modules = static::generateModuleConfiguration($modules);
313
        $configuration['modules'] = $modules;
314
        return $configuration;
315
    }
316
}
317