Completed
Push — clean ( 020cee )
by Akihito
02:31
created

Bootstrap   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 97.44%

Importance

Changes 21
Bugs 0 Features 1
Metric Value
wmc 14
c 21
b 0
f 1
lcom 1
cbo 10
dl 0
loc 107
ccs 38
cts 39
cp 0.9744
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getApp() 0 4 1
A newApp() 0 14 4
A newModule() 0 18 4
A getAppInstance() 0 14 2
A getCache() 0 13 3
1
<?php
2
/**
3
 * This file is part of the BEAR.Package package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Package;
8
9
use BEAR\AppMeta\AbstractAppMeta;
10
use BEAR\AppMeta\AppMeta;
11
use BEAR\Package\Exception\InvalidContextException;
12
use BEAR\Sunday\Extension\Application\AbstractApp;
13
use BEAR\Sunday\Extension\Application\AppInterface;
14
use Doctrine\Common\Cache\ApcuCache;
15
use Doctrine\Common\Cache\Cache;
16
use Doctrine\Common\Cache\FilesystemCache;
17
use Doctrine\Common\Cache\VoidCache;
18
use Ray\Compiler\DiCompiler;
19
use Ray\Compiler\Exception\NotCompiled;
20
use Ray\Compiler\ScriptInjector;
21
use Ray\Di\AbstractModule;
22
23
final class Bootstrap
24
{
25
    /**
26
     * Return application instance by name and contexts
27
     *
28
     * @param string $name     application name    (Vendor.Package)
29
     * @param string $contexts application context (prd-html-app)
30
     *
31
     * @return AbstractApp
32
     */
33 3
    public function getApp($name, $contexts)
34
    {
35 3
        return $this->newApp(new AppMeta($name, $contexts), $contexts);
36
    }
37
38
    /**
39
     * @param AbstractAppMeta $appMeta
40
     * @param string          $contexts
41
     * @param Cache           $cache
42
     *
43
     * @return AbstractApp
44
     */
45 5
    public function newApp(AbstractAppMeta $appMeta, $contexts, Cache $cache = null)
46
    {
47 5
        $cache = $cache ?: $this->getCache($appMeta, $contexts);
48 5
        $appId = $appMeta->name . $contexts;
49 5
        $isProd = is_int(strpos($contexts, 'prod'));
50 5
        $app = $cache->fetch($appId);
51 5
        if ($app && $isProd) {
52 1
            return $app;
53
        }
54 5
        $app = $this->getAppInstance($appMeta, $contexts);
55 4
        $cache->save($appId, $app);
56
57 4
        return $app;
58
    }
59
60
    /**
61
     * @param AbstractAppMeta $appMeta
62
     * @param string          $contexts
63
     *
64
     * @return AbstractApp
65
     */
66 5
    private function getAppInstance(AbstractAppMeta $appMeta, $contexts)
67
    {
68 5
        $module = $this->newModule($appMeta, $contexts);
69 4
        $module->override(new AppMetaModule($appMeta));
70
        try {
71 4
            $app = (new ScriptInjector($appMeta->tmpDir))->getInstance(AppInterface::class);
72 4
        } catch (NotCompiled $e) {
73 4
            $compiler = new DiCompiler($module, $appMeta->tmpDir);
74 4
            $compiler->compile();
75 4
            $app = (new ScriptInjector($appMeta->tmpDir))->getInstance(AppInterface::class);
76
        }
77
78 4
        return $app;
79
    }
80
81
    /**
82
     * Return configured module
83
     *
84
     * @param AbstractAppMeta $appMeta
85
     * @param string          $contexts
86
     *
87
     * @return AbstractModule
88
     */
89 5
    private function newModule(AbstractAppMeta $appMeta, $contexts)
90
    {
91 5
        $contextsArray = array_reverse(explode('-', $contexts));
92 5
        $module = null;
93 5
        foreach ($contextsArray as $context) {
94 5
            $class = $appMeta->name . '\Module\\' . ucwords($context) . 'Module';
95 5
            if (!class_exists($class)) {
96 3
                $class = 'BEAR\Package\Context\\' . ucwords($context) . 'Module';
97
            }
98 5
            if (! is_a($class, AbstractModule::class, true)) {
99 1
                throw new InvalidContextException($class);
100
            }
101
            /* @var $module AbstractModule */
102 4
            $module = new $class($module);
103
        }
104
105 4
        return $module;
106
    }
107
108
    /**
109
     * Return contextual cache
110
     *
111
     * @param AbstractAppMeta $appMeta
112
     * @param string          $contexts
113
     *
114
     * @return ApcuCache|FilesystemCache|VoidCache
115
     */
116 3
    private function getCache(AbstractAppMeta $appMeta, $contexts)
117
    {
118 3
        $isProd = is_int(strpos($contexts, 'prod'));
119 3
        if ($isProd) {
120 1
            if (function_exists('apcu_fetch')) {
121
                return new ApcuCache;
122
            }
123
124 1
            return new FilesystemCache($appMeta->tmpDir);
125
        }
126
127 2
        return new VoidCache;
128
    }
129
}
130