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

Bootstrap::newModule()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 6.5971

Importance

Changes 6
Bugs 0 Features 0
Metric Value
c 6
b 0
f 0
dl 0
loc 18
ccs 5
cts 11
cp 0.4545
rs 9.2
cc 4
eloc 11
nc 5
nop 2
crap 6.5971
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