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)) { |
|
|
|
|
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; |
|
|
|
|
138
|
|
|
} |
139
|
|
|
return static::$configDir; |
|
|
|
|
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']; |
|
|
|
|
160
|
|
|
} |
161
|
|
|
static::generateVersion(); |
|
|
|
|
162
|
|
|
$configuration = static::loadConfig($configuration); |
163
|
|
|
static::checkCache($configuration); |
|
|
|
|
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 |
|
|
|
|
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)); |
|
|
|
|
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
|
|
|
|
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.