Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
80.00% covered (warning)
80.00%
44 / 55
28.57% covered (danger)
28.57%
2 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
CoreStartup
80.00% covered (warning)
80.00%
44 / 55
28.57% covered (danger)
28.57%
2 / 7
14.35
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setupCommon
91.30% covered (success)
91.30%
21 / 23
0.00% covered (danger)
0.00%
0 / 1
2.00
 setupWebService
88.24% covered (warning)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
2.01
 setupCliService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setupTestService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setupCustom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setup
54.55% covered (warning)
54.55%
6 / 11
0.00% covered (danger)
0.00%
0 / 1
7.35
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\Core;
6
7use PeServer\Core\Collection\Arr;
8use PeServer\Core\StartupOptions;
9use PeServer\Core\DI\DiItem;
10use PeServer\Core\DI\DiRegisterContainer;
11use PeServer\Core\DI\IDiContainer;
12use PeServer\Core\DI\IDiRegisterContainer;
13use PeServer\Core\Encoding;
14use PeServer\Core\Environment;
15use PeServer\Core\Errors\ErrorHandler;
16use PeServer\Core\Errors\HttpErrorHandler;
17use PeServer\Core\Http\HttpMethod;
18use PeServer\Core\Http\IResponsePrinterFactory;
19use PeServer\Core\Http\RequestPath;
20use PeServer\Core\Http\ResponsePrinter;
21use PeServer\Core\Http\ResponsePrinterFactory;
22use PeServer\Core\IO\Path;
23use PeServer\Core\Log\ILogger;
24use PeServer\Core\Log\ILoggerFactory;
25use PeServer\Core\Log\ILogProvider;
26use PeServer\Core\Log\LoggerFactory;
27use PeServer\Core\Log\Logging;
28use PeServer\Core\Log\LogProvider;
29use PeServer\Core\Mvc\ILogicFactory;
30use PeServer\Core\Mvc\LogicFactory;
31use PeServer\Core\Mvc\RouteRequest;
32use PeServer\Core\Mvc\Template\ITemplateFactory;
33use PeServer\Core\Mvc\Template\TemplateFactory;
34use PeServer\Core\Store\CookieStore;
35use PeServer\Core\Store\SessionStore;
36use PeServer\Core\Store\SpecialStore;
37use PeServer\Core\Store\StoreOptions;
38use PeServer\Core\Store\Stores;
39use PeServer\Core\Store\TemporaryStore;
40use PeServer\Core\Throws\NotImplementedException;
41use PeServer\Core\Web\IUrlHelper;
42use PeServer\Core\Web\UrlHelper;
43use PeServer\Core\Web\WebSecurity;
44
45
46/**
47 * スタートアップ処理。
48 *
49 * これだけでも動くけど基本的に書き換えてあれこれする想定。
50 */
51class CoreStartup
52{
53    #region define
54
55    public const MODE_WEB = 'Web';
56    public const MODE_CLI = 'Cli';
57    public const MODE_TEST = 'Test';
58
59    #endregion
60
61    /**
62     * 生成。
63     *
64     * @param StartupOptions $startupOptions スタートアップオプション。
65     */
66    public function __construct(
67        protected StartupOptions $startupOptions
68    ) {
69    }
70
71    #region function
72
73    /**
74     * 共通セットアップ処理。
75     *
76     * 拡張する場合は先に親を呼び出して、子の方で登録(再登録)を行うこと。
77     *
78     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
79     * @param IDiRegisterContainer $container
80     */
81    protected function setupCommon(array $options, IDiRegisterContainer $container): void
82    {
83        $environment = new Environment('C', 'uni', 'Asia/Tokyo', $options['environment'], $options['revision']);
84        Encoding::setDefaultEncoding(Encoding::getUtf8());
85
86        $logging = new Logging($options['special_store'] ?? new SpecialStore());
87        $container->registerValue($logging, Logging::class);
88
89        $programContext = new ProgramContext(
90            $this->startupOptions->root,
91            Path::combine($this->startupOptions->root, 'PeServer'),
92            Path::combine($this->startupOptions->root, $this->startupOptions->public)
93        );
94        $container->registerValue($programContext, ProgramContext::class);
95
96        $container->registerValue($environment, Environment::class);
97        $container->registerValue($this->startupOptions, StartupOptions::class);
98
99        $container->registerClass(WebSecurity::class);
100
101        $container->registerMapping(ILogProvider::class, LogProvider::class, DiItem::LIFECYCLE_SINGLETON);
102        $container->registerMapping(ILoggerFactory::class, LoggerFactory::class);
103        $container->add(ILogger::class, DiItem::factory(Logging::class . '::injectILogger'));
104        // $container->add(ILogger::class, DiItem::factory(function (IDiContainer $container, array $callStack) {
105        //     /** @var DiItem[] $callStack */
106        //     $loggerFactory = $container->get(ILoggerFactory::class);
107        //     if (/*1 < */count($callStack)) {
108        //         //$item = $callStack[count($callStack) - 2];
109        //         $item = $callStack[0];
110        //         $className = (string)$item->data; // あぶねぇかなぁ
111        //         $header = Logging::toHeader($className);
112        //         return $loggerFactory->create($header);
113        //     }
114        //     return $loggerFactory->create('<UNKNOWN>');
115        // }));
116
117        $container->add(IDiContainer::class, new DiItem(DiItem::LIFECYCLE_SINGLETON, DiItem::TYPE_VALUE, $container, true));
118        $container->registerMapping(ITemplateFactory::class, TemplateFactory::class);
119        $container->registerClass(TemplateFactory::class); // こいつは Core からも使われる特殊な奴やねん
120        $container->registerMapping(IResponsePrinterFactory::class, ResponsePrinterFactory::class); // こいつも Core からも使われる特殊な奴やねん
121        //$container->registerClass(ResponsePrinterFactory::class);
122
123        if ($this->startupOptions->errorHandling) {
124            $errorHandler = $container->new(ErrorHandler::class);
125            $errorHandler->register();
126        }
127    }
128
129    /**
130     * Webアプリケーション用セットアップ処理。
131     *
132     * 拡張する場合は先に親を呼び出して、子の方で登録(再登録)を行うこと。
133     *
134     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
135     * @param IDiRegisterContainer $container
136     */
137    protected function setupWebService(array $options, IDiRegisterContainer $container): void
138    {
139        $container->add(IDiRegisterContainer::class, DiItem::factory(fn ($dc) => $dc->clone()));
140        $container->remove(IDiContainer::class);
141        $container->add(IDiContainer::class, DiItem::factory(fn ($dc) => $dc->get(IDiRegisterContainer::class)));
142
143        $container->registerValue($options['url_helper'] ?? new UrlHelper(''), IUrlHelper::class);
144
145        /** @var SpecialStore */
146        $specialStore = $options['special_store'] ?? new SpecialStore();
147        $container->registerValue($specialStore, SpecialStore::class);
148        $container->add(Stores::class, DiItem::factory(fn ($di) => new Stores($di->get(SpecialStore::class), StoreOptions::default(), $di->get(WebSecurity::class)), DiItem::LIFECYCLE_SINGLETON));
149        $container->add(CookieStore::class, DiItem::factory(fn ($di) => $di->get(Stores::class)->cookie));
150        $container->add(SessionStore::class, DiItem::factory(fn ($di) => $di->get(Stores::class)->session));
151        $container->add(TemporaryStore::class, DiItem::factory(fn ($di) => $di->get(Stores::class)->temporary));
152
153        $method = $specialStore->getRequestMethod();
154        $requestPath = new RequestPath($specialStore->getServer('REQUEST_URI'), $container->get(IUrlHelper::class));
155        $container->registerValue(new RouteRequest($method, $requestPath));
156
157        if ($this->startupOptions->errorHandling) {
158            /** @var HttpErrorHandler */
159            $httpErrorHandler = $container->new(HttpErrorHandler::class, [RequestPath::class => $requestPath]);
160            $httpErrorHandler->register();
161        }
162
163        $container->registerMapping(ILogicFactory::class, LogicFactory::class);
164    }
165
166    /**
167     * CLIアプリケーション用セットアップ処理。
168     *
169     * つかわんよ。
170     * 拡張する場合は先に親を呼び出して、子の方で登録(再登録)を行うこと。
171     *
172     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
173     * @param IDiRegisterContainer $container
174     */
175    protected function setupCliService(array $options, IDiRegisterContainer $container): void
176    {
177        //NOP
178    }
179
180    /**
181     * テスト用セットアップ処理。
182     *
183     * 拡張する場合は先に親を呼び出して、子の方で登録(再登録)を行うこと。
184     *
185     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
186     * @param IDiRegisterContainer $container
187     */
188    protected function setupTestService(array $options, IDiRegisterContainer $container): void
189    {
190        //NOP
191    }
192
193    /**
194     * 追加セットアップ処理。
195     *
196     * Coreでは何もしないので拡張側で好きにどうぞ。
197     *
198     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
199     * @param IDiRegisterContainer $container
200     */
201    protected function setupCustom(array $options, IDiRegisterContainer $container): void
202    {
203        //NOP
204    }
205
206    /**
207     * セットアップ処理。
208     *
209     * @param string $mode
210     * @param array{environment:string,revision:string,url_helper?:IUrlHelper,special_store?:SpecialStore} $options
211     * @return IDiRegisterContainer
212     */
213    public function setup(string $mode, array $options): IDiRegisterContainer
214    {
215        $container = new DiRegisterContainer();
216
217        $this->setupCommon($options, $container);
218
219        switch ($mode) {
220            case self::MODE_WEB:
221                $this->setupWebService($options, $container);
222                break;
223
224            case self::MODE_CLI:
225                $this->setupCliService($options, $container);
226                break;
227
228            case self::MODE_TEST:
229                $this->setupTestService($options, $container);
230                break;
231
232            default:
233                throw new NotImplementedException($mode);
234        }
235
236        $this->setupCustom($options, $container);
237
238        return $container;
239    }
240
241    #endregion
242}