-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #396 from koriym/injector
Create PackageInjector from Injector
- Loading branch information
Showing
2 changed files
with
98 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace BEAR\Package\Injector; | ||
|
||
use BEAR\AppMeta\AbstractAppMeta; | ||
use BEAR\Package\Module; | ||
use BEAR\Package\Module\ScriptinjectorModule; | ||
use BEAR\Sunday\Extension\Application\AppInterface; | ||
use Ray\Compiler\Annotation\Compile; | ||
use Ray\Compiler\ScriptInjector; | ||
use Ray\Di\AbstractModule; | ||
use Ray\Di\Injector as RayInjector; | ||
use Ray\Di\InjectorInterface; | ||
use Symfony\Component\Cache\Adapter\AdapterInterface; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
use function assert; | ||
use function is_bool; | ||
use function is_dir; | ||
use function mkdir; | ||
use function str_replace; | ||
|
||
final class PackageInjector | ||
{ | ||
/** | ||
* Serialized injector instances | ||
* | ||
* @var array<string, InjectorInterface> | ||
*/ | ||
private static array $instances; | ||
|
||
/** @var array<string, AbstractModule> */ | ||
private static array $modules; | ||
|
||
/** | ||
* @codeCoverageIgnore | ||
*/ | ||
private function __construct() | ||
{ | ||
} | ||
|
||
public static function getInstance(AbstractAppMeta $meta, string $context, ?CacheInterface $cache): InjectorInterface | ||
{ | ||
$injectorId = str_replace('\\', '_', $meta->name) . $context; | ||
if (isset(self::$instances[$injectorId])) { | ||
return self::$instances[$injectorId]; | ||
} | ||
|
||
assert($cache instanceof AdapterInterface); | ||
/** @psalm-suppress all */ | ||
[$injector, $fileUpdate] = $cache->getItem($injectorId)->get(); // @phpstan-ignore-line | ||
$isCacheableInjector = $injector instanceof ScriptInjector || ($injector instanceof InjectorInterface && $fileUpdate instanceof FileUpdate && $fileUpdate->isNotUpdated($meta)); | ||
if (! $isCacheableInjector) { | ||
$injector = self::factory($meta, $context); | ||
$cache->save($cache->getItem($injectorId)->set([$injector, new FileUpdate($meta)])); | ||
} | ||
|
||
self::$instances[$injectorId] = $injector; | ||
|
||
return $injector; | ||
} | ||
|
||
public static function factory(AbstractAppMeta $meta, string $context, ?AbstractModule $overideModule = null): InjectorInterface | ||
{ | ||
$scriptDir = $meta->tmpDir . '/di'; | ||
! is_dir($scriptDir) && ! @mkdir($scriptDir) && ! is_dir($scriptDir); | ||
$moduleId = $meta->appDir . $context; | ||
if (! isset(self::$modules[$moduleId])) { | ||
self::$modules[$moduleId] = (new Module())($meta, $context); | ||
} | ||
|
||
$module = self::$modules[$moduleId]; | ||
if ($overideModule instanceof AbstractModule) { | ||
$module->override($overideModule); | ||
} | ||
|
||
$injector = new RayInjector($module, $scriptDir); | ||
$isProd = $injector->getInstance('', Compile::class); | ||
assert(is_bool($isProd)); | ||
if ($isProd) { | ||
$injector = new ScriptInjector($scriptDir, static fn () => new ScriptinjectorModule($scriptDir, $module)); | ||
} | ||
|
||
$injector->getInstance(AppInterface::class); | ||
|
||
return $injector; | ||
} | ||
} |