Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
66 / 66
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
Module
100.00% covered (success)
100.00%
66 / 66
100.00% covered (success)
100.00%
10 / 10
56
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
13
 register
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
29
 __set
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 __get
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 __isset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 __unset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 offsetSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetGet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (https://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@noladev.com>
7 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
8 * @license    https://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Module;
15
16use Pop\App;
17use Pop\Application;
18use Pop\Utils\Arr;
19use Pop\Utils\Helper;
20
21/**
22 * Pop module class
23 *
24 * @category   Pop
25 * @package    Pop\Module
26 * @author     Nick Sagona, III <dev@noladev.com>
27 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
28 * @license    https://www.popphp.org/license     New BSD License
29 * @version    4.4.0
30 * @property   $config mixed
31 */
32class Module extends AbstractModule implements \ArrayAccess
33{
34
35    /**
36     * Constructor
37     *
38     * Instantiate a module object
39     *
40     * Optional parameters are an application instance or a configuration object or array
41     */
42    public function __construct()
43    {
44        $args        = func_get_args();
45        $application = null;
46        $config      = null;
47        $name        = null;
48        $version     = null;
49
50        foreach ($args as $arg) {
51            if ($arg instanceof Application) {
52                $application = $arg;
53            } else if (is_array($arg) || ($arg instanceof \ArrayAccess) || ($arg instanceof \ArrayObject)) {
54                $config = $arg;
55            } else if (preg_match('/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/', $arg)) {
56                $version = $arg;
57            } else if (is_string($arg)) {
58                $name = $arg;
59            }
60        }
61
62        if ($name !== null) {
63            $this->setName($name);
64        } else if ($this->name === null) {
65            $this->setName(str_replace('\\', '_', strtolower(get_called_class())));
66        }
67
68        if ($version !== null) {
69            $this->setVersion($version);
70        }
71
72        if ($config !== null) {
73            $this->registerConfig($config);
74        }
75
76        if ($application !== null) {
77            $this->register($application);
78        }
79    }
80
81    /**
82     * Register module
83     *
84     * @param  Application $application
85     * @throws Exception|\Pop\Service\Exception
86     * @return static
87     */
88    public function register(Application $application): static
89    {
90        $this->application = $application;
91
92        if ($this->config !== null) {
93            // Set the name, if available
94            if (isset($this->config['name'])) {
95                $this->setName($this->config['name']);
96            }
97
98            // Set the version, if available
99            if (!empty($this->config['version'])) {
100                $this->setVersion($this->config['version']);
101            }
102
103            // If the autoloader is set and the module config has a
104            // defined prefix and src, register the module with the autoloader
105            if (($this->application !== null) && ($this->application->autoloader() !== null) &&
106                isset($this->config['prefix']) && isset($this->config['src']) && file_exists($this->config['src'])
107            ) {
108                // Register as PSR-0
109                if (isset($this->config['psr-0']) && ($this->config['psr-0'])) {
110                    $this->application->autoloader()->add($this->config['prefix'], $this->config['src']);
111                // Else, default to PSR-4
112                } else {
113                    $this->application->autoloader()->addPsr4($this->config['prefix'], $this->config['src']);
114                }
115            }
116
117            // If routes are set in the module config, register them with the application
118            if (isset($this->config['routes']) && ($this->application !== null) && ($this->application->router() !== null)) {
119                $this->application->router()->addRoutes($this->config['routes']);
120            }
121
122            // If services are set in the module config, register them with the application
123            if (isset($this->config['services']) && ($this->application !== null) && ($this->application->services() !== null)) {
124                foreach ($this->config['services'] as $name => $service) {
125                    $this->application->setService($name, $service);
126                }
127            }
128
129            // If events are set in the module config, register them with the application
130            if (isset($this->config['events']) && ($this->application !== null) && ($this->application->events() !== null)) {
131                foreach ($this->config['events'] as $event) {
132                    if (isset($event['name']) && isset($event['action'])) {
133                        $this->application->on(
134                            $event['name'],
135                            $event['action'],
136                            ((isset($event['priority'])) ? $event['priority'] : 0)
137                        );
138                    }
139                }
140            }
141
142            $middlewareDisabled = App::env('MIDDLEWARE_DISABLED');
143
144            // If middleware is defined in the module  config, register them with the application
145            if (isset($this->config['middleware']) && ($this->application->middleware() !== null) &&
146                (empty($middlewareDisabled) || ($middlewareDisabled == 'route'))) {
147                $this->application->middleware()->addItems(Arr::make($this->config['middleware']));
148            }
149        }
150
151        $this->application->modules->register($this);
152
153        return $this;
154    }
155
156    /**
157     * Set a pre-designated value in the module object
158     *
159     * @param  string $name
160     * @param  mixed  $value
161     * @return void
162     */
163    public function __set(string $name, mixed $value): void
164    {
165        if ($name == 'config') {
166            $this->registerConfig($value);
167        }
168    }
169
170    /**
171     * Get a pre-designated value from the module object
172     *
173     * @param  string $name
174     * @return mixed
175     */
176    public function __get(string $name): mixed
177    {
178        return match ($name) {
179            'config' => $this->config,
180            default  => null,
181        };
182    }
183
184    /**
185     * Determine if a pre-designated value in the module object exists
186     *
187     * @param  string $name
188     * @return bool
189     */
190    public function __isset(string $name): bool
191    {
192        return match ($name) {
193            'config' => ($this->config !== null),
194            default  => false,
195        };
196    }
197
198    /**
199     * Unset a pre-designated value in the module object
200     *
201     * @param  string $name
202     * @return void
203     */
204    public function __unset(mixed $name): void
205    {
206        if ($name == 'config') {
207            $this->config = null;
208        }
209    }
210
211    /**
212     * Set a value in the array
213     *
214     * @param  mixed $offset
215     * @param  mixed $value
216     * @return void
217     */
218    public function offsetSet(mixed $offset, mixed $value): void
219    {
220        $this->__set($offset, $value);
221    }
222
223    /**
224     * Get a value from the array
225     *
226     * @param  mixed $offset
227     * @return mixed
228     */
229    public function offsetGet(mixed $offset): mixed
230    {
231        return $this->__get($offset);
232    }
233
234    /**
235     * Determine if a value exists
236     *
237     * @param  mixed $offset
238     * @return bool
239     */
240    public function offsetExists(mixed $offset): bool
241    {
242        return $this->__isset($offset);
243    }
244
245    /**
246     * Unset a value from the array
247     *
248     * @param  mixed $offset
249     * @return void
250     */
251    public function offsetUnset(mixed $offset): void
252    {
253        $this->__unset($offset);
254    }
255
256}