Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
ManagesExtensions
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 registerExtension
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getExtension
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasExtension
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExtensions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRegisteredExtensions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRegisteredPageClasses
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Foundation\Concerns;
6
7use BadMethodCallException;
8use InvalidArgumentException;
9
10use function array_keys;
11use function array_map;
12use function array_merge;
13use function array_unique;
14use function in_array;
15use function is_subclass_of;
16
17/**
18 * @internal Single-use trait for the HydeKernel class.
19 *
20 * @see \Hyde\Foundation\HydeKernel
21 */
22trait ManagesExtensions
23{
24    /**
25     * Register a HydePHP extension within the HydeKernel.
26     *
27     * Typically, you would call this method in the register method of a service provider.
28     * If your package uses the standard Laravel (Composer) package discovery feature,
29     * the extension will automatically be enabled when the package is installed.
30     *
31     * @param  class-string<\Hyde\Foundation\Concerns\HydeExtension>  $extension
32     */
33    public function registerExtension(string $extension): void
34    {
35        if ($this->booted) {
36            // We throw an exception here to prevent the developer from registering aa extension after the Kernel has been booted.
37            // The reason we do this is because at this point all the source files have already been discovered and parsed.
38            // If we allowed new classes after this point, we would have to reboot everything which adds complexity.
39
40            throw new BadMethodCallException('Cannot register an extension after the Kernel has been booted.');
41        }
42
43        if (! is_subclass_of($extension, HydeExtension::class)) {
44            // We want to make sure that the extension class extends the HydeExtension class,
45            // so that we won't have to check the methods we need to call exist later on.
46
47            throw new InvalidArgumentException("Extension [$extension] must extend the HydeExtension class.");
48        }
49
50        if (in_array($extension, $this->getRegisteredExtensions(), true)) {
51            // While throwing an exception here is not required since we are using an associative array,
52            // it may be helpful for the developer to know that their registration logic may be flawed.
53
54            throw new InvalidArgumentException("Extension [$extension] is already registered.");
55        }
56
57        $this->extensions[$extension] = new $extension();
58    }
59
60    /**
61     * Get the singleton instance of the specified extension.
62     *
63     * @template T of \Hyde\Foundation\Concerns\HydeExtension
64     *
65     * @param  class-string<T>  $extension
66     * @return T
67     */
68    public function getExtension(string $extension): HydeExtension
69    {
70        if (! isset($this->extensions[$extension])) {
71            throw new InvalidArgumentException("Extension [$extension] is not registered.");
72        }
73
74        return $this->extensions[$extension];
75    }
76
77    /**
78     * Determine if the specified extension is registered.
79     *
80     * @param  class-string<\Hyde\Foundation\Concerns\HydeExtension>  $extension
81     */
82    public function hasExtension(string $extension): bool
83    {
84        return isset($this->extensions[$extension]);
85    }
86
87    /** @return array<\Hyde\Foundation\Concerns\HydeExtension> */
88    public function getExtensions(): array
89    {
90        return $this->extensions;
91    }
92
93    /** @return array<class-string<\Hyde\Foundation\Concerns\HydeExtension>> */
94    public function getRegisteredExtensions(): array
95    {
96        return array_keys($this->extensions);
97    }
98
99    /** @return array<class-string<\Hyde\Pages\Concerns\HydePage>> */
100    public function getRegisteredPageClasses(): array
101    {
102        return array_unique(array_merge(...array_map(function (string $extension): array {
103            /** @var <class-string<\Hyde\Foundation\Concerns\HydeExtension>> $extension */
104            return $extension::getPageClasses();
105        }, $this->getRegisteredExtensions())));
106    }
107}