Completed
Pull Request — 1.x (#214)
by Yuu
03:24 queued 55s
created

Bootstrap   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 53.85%

Importance

Changes 19
Bugs 0 Features 1
Metric Value
wmc 14
c 19
b 0
f 1
lcom 1
cbo 10
dl 0
loc 103
ccs 21
cts 39
cp 0.5385
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getApp() 0 4 1
A newApp() 0 14 4
A getAppInstance() 0 14 2
A newModule() 0 18 4
A getCache() 0 9 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\ApcCache;
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
    public function getApp($name, $contexts)
34
    {
35
        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 4
    public function newApp(AbstractAppMeta $appMeta, $contexts, Cache $cache = null)
46
    {
47 1
        $cache = $cache ?: $this->getCache($appMeta, $contexts);
48 4
        $appId = $appMeta->name . $contexts;
49
        $isProd = is_int(strpos($contexts, 'prod'));
50
        $app = $cache->fetch($appId);
51 4
        if ($app && $isProd) {
52 1
            return $app;
53
        }
54 1
        $app = $this->getAppInstance($appMeta, $contexts);
55
        $cache->save($appId, $app);
56
57 4
        return $app;
58 4
    }
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 1
        $module = $this->newModule($appMeta, $contexts);
69
        $module->override(new AppMetaModule($appMeta));
70
        try {
71
            $app = (new ScriptInjector($appMeta->tmpDir))->getInstance(AppInterface::class);
72
        } catch (NotCompiled $e) {
73
            $compiler = new DiCompiler($module, $appMeta->tmpDir);
74
            $compiler->compile();
75
            $app = (new ScriptInjector($appMeta->tmpDir))->getInstance(AppInterface::class);
76 4
        }
77
78 4
        return $app;
79 5
    }
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
        $contextsArray = array_reverse(explode('-', $contexts));
92 5
        $module = null;
93
        foreach ($contextsArray as $context) {
94
            $class = $appMeta->name . '\Module\\' . ucwords($context) . 'Module';
95
            if (!class_exists($class)) {
96
                $class = 'BEAR\Package\Context\\' . ucwords($context) . 'Module';
97
            }
98
            if (! is_a($class, AbstractModule::class, true)) {
99
                throw new InvalidContextException($class);
100
            }
101
            /* @var $module AbstractModule */
102
            $module = new $class($module);
103 1
        }
104
105 4
        return $module;
106 4
    }
107
108
    /**
109
     * Return contextual cache
110
     *
111
     * @param AbstractAppMeta $appMeta
112
     * @param string          $contexts
113
     *
114
     * @return ApcCache|FilesystemCache|VoidCache
115
     */
116 3
    private function getCache(AbstractAppMeta $appMeta, $contexts)
117
    {
118
        $isProd = is_int(strpos($contexts, 'prod'));
119 3
        if ($isProd) {
120
            return function_exists('apc_fetch') ? new ApcCache : new FilesystemCache($appMeta->tmpDir);
0 ignored issues
show
Deprecated Code introduced by
The class Doctrine\Common\Cache\ApcCache has been deprecated with message: since version 1.6, use ApcuCache instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
121
        }
122
123
        return new VoidCache;
124 3
    }
125
}
126