Passed
Push — feat/gacela-add-global ( a28ae0 )
by Chema
04:27
created

Gacela::addGlobal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework;
6
7
use Closure;
8
use Gacela\Framework\Bootstrap\GacelaConfig;
9
use Gacela\Framework\Bootstrap\SetupGacela;
10
use Gacela\Framework\Bootstrap\SetupGacelaInterface;
11
use Gacela\Framework\ClassResolver\AbstractClassResolver;
12
use Gacela\Framework\ClassResolver\Cache\GacelaFileCache;
13
use Gacela\Framework\ClassResolver\Cache\InMemoryCache;
14
use Gacela\Framework\ClassResolver\ClassResolverCache;
15
use Gacela\Framework\ClassResolver\GlobalInstance\AnonymousGlobal;
16
use Gacela\Framework\Config\Config;
17
use Gacela\Framework\Config\ConfigFactory;
18
use Gacela\Framework\Container\Container;
19
use Gacela\Framework\Container\Locator;
20
use Gacela\Framework\DocBlockResolver\DocBlockResolverCache;
21
use Gacela\Framework\Exception\GacelaNotBootstrappedException;
22
23
use function is_string;
24
use function sprintf;
25
26
final class Gacela
27
{
28
    private const GACELA_PHP_FILENAME = 'gacela.php';
29
30
    private static ?Container $mainContainer = null;
31
32
    private static ?string $appRootDir = null;
33
34
    /**
35
     * Define the entry point of Gacela.
36
     *
37
     * @param null|Closure(GacelaConfig):void $configFn
38
     */
39
    public static function bootstrap(string $appRootDir, Closure $configFn = null): void
40
    {
41
        self::$appRootDir = $appRootDir;
42
        self::$mainContainer = null;
43
44
        $setup = self::processConfigFnIntoSetup($configFn);
45
46
        if ($setup->shouldResetInMemoryCache()) {
47
            self::resetCache();
48
        }
49
50
        $config = Config::createWithSetup($setup);
51
        $config->setAppRootDir($appRootDir)
52
            ->init();
53
54
        self::runPlugins($config);
55
    }
56
57
    /**
58
     * @template T
59
     *
60
     * @param class-string<T> $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
61
     *
62
     * @return T|null
63
     */
64
    public static function get(string $className): mixed
65
    {
66
        return Locator::getSingleton($className, self::$mainContainer);
67
    }
68
69
    /**
70
     * Get the application root dir set when bootstrapping gacela
71
     */
72
    public static function rootDir(): string
73
    {
74
        if (self::$appRootDir === null) {
75
            throw new GacelaNotBootstrappedException();
76
        }
77
78
        return self::$appRootDir;
79
    }
80
81
    /**
82
     * Add an anonymous class as 'Config', 'Factory' or 'DependencyProvider' as a global resource
83
     * bound to the context that it is passed as first argument.
84
     * It can be the string-key (from a non-class/file context) or the class/object itself.
85
     */
86
    public static function addGlobal(object|string $context, object $resolvedClass): void
87
    {
88
        AnonymousGlobal::addGlobal($context, $resolvedClass);
89
    }
90
91
    /**
92
     * @param null|Closure(GacelaConfig):void $configFn
93
     */
94
    private static function processConfigFnIntoSetup(Closure $configFn = null): SetupGacelaInterface
95
    {
96
        if ($configFn instanceof Closure) {
97
            return SetupGacela::fromCallable($configFn);
98
        }
99
100
        $gacelaFilePath = sprintf(
101
            '%s%s%s',
102
            self::rootDir(),
103
            DIRECTORY_SEPARATOR,
104
            self::GACELA_PHP_FILENAME,
105
        );
106
107
        if (is_file($gacelaFilePath)) {
108
            return SetupGacela::fromFile($gacelaFilePath);
109
        }
110
111
        return new SetupGacela();
112
    }
113
114
    private static function resetCache(): void
115
    {
116
        AnonymousGlobal::resetCache();
117
        AbstractFacade::resetCache();
118
        AbstractFactory::resetCache();
119
        AbstractClassResolver::resetCache();
120
        InMemoryCache::resetCache();
121
        GacelaFileCache::resetCache();
122
        DocBlockResolverCache::resetCache();
123
        ClassResolverCache::resetCache();
124
        ConfigFactory::resetCache();
125
        Config::resetInstance();
126
        Locator::resetInstance();
127
    }
128
129
    private static function runPlugins(Config $config): void
130
    {
131
        self::$mainContainer = Container::withConfig($config);
132
133
        $plugins = $config->getSetupGacela()->getPlugins();
134
135
        foreach ($plugins as $plugin) {
136
            /** @var callable $current */
137
            $current = is_string($plugin)
138
                ? self::$mainContainer->get($plugin)
139
                : $plugin;
140
141
            self::$mainContainer->resolve($current);
142
        }
143
    }
144
}
145