PluginProbe
Hello Plus / 1.7.0
Hello Plus v1.7.0
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.3.0 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.5.3 1.6.0 1.6.1 1.6.2 1.7.0 1.7.1 1.7.2 1.7.3 All 30 releases
hello-plus / includes / module-base.php

module-base.php in Hello Plus 1.7.0, at includes/module-base.php

287 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace HelloPlus\Includes;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 /**
10 * Module Base.
11 *
12 * An abstract class providing the properties and methods needed to
13 * manage and handle modules in inheriting classes.
14 *
15 * @abstract
16 * @package HelloPlus
17 * @subpackage HelloPlusModules
18 */
19 abstract class Module_Base {
20
21 /**
22 * Module class reflection.
23 *
24 * Holds the information about a class.
25 * @access private
26 *
27 * @var ?\ReflectionClass
28 */
29 private ?\ReflectionClass $reflection = null;
30
31 /**
32 * Module components.
33 *
34 * Holds the module components.
35 * @access private
36 *
37 * @var array
38 */
39 private array $components = [];
40
41 /**
42 * Module instance.
43 *
44 * Holds the module instance.
45 * @access protected
46 *
47 * @var Module_Base[]
48 */
49 protected static array $instances = [];
50
51 /**
52 * Get module name.
53 *
54 * Retrieve the module name.
55 * @access public
56 * @abstract
57 *
58 * @return string Module name.
59 */
60 abstract public static function get_name(): string;
61
62 /**
63 * @abstract
64 * @access protected
65 *
66 * @return string[]
67 */
68 abstract protected function get_component_ids(): array;
69
70 /**
71 * Singleton Instance.
72 *
73 * Ensures only one instance of the module class is loaded or can be loaded.
74 * @access public
75 * @static
76 *
77 * @return Module_Base An instance of the class.
78 */
79 public static function instance(): Module_Base {
80 $class_name = static::class_name();
81
82 if ( empty( static::$instances[ $class_name ] ) ) {
83 static::$instances[ $class_name ] = new static(); // @codeCoverageIgnore
84 }
85
86 return static::$instances[ $class_name ];
87 }
88
89 /**
90 * is_active
91 *
92 * @access public
93 * @static
94 *
95 * @return bool
96 */
97 public static function is_active(): bool {
98 /**
99 * allow enabling/disabling the module on run-time
100 *
101 * @since 1.0.0
102 *
103 * @param bool $is_active the filters value
104 */
105 return apply_filters( 'hello-plus/modules/' . static::get_name() . '/is-active', true );
106 }
107
108 /**
109 * Class name.
110 *
111 * Retrieve the name of the class.
112 * @access public
113 * @static
114 */
115 public static function class_name(): string {
116 return get_called_class();
117 }
118
119 /**
120 * @access public
121 *
122 * @return \ReflectionClass
123 */
124 public function get_reflection(): \ReflectionClass {
125 if ( null === $this->reflection ) {
126 try {
127 $this->reflection = new \ReflectionClass( $this );
128 } catch ( \ReflectionException $e ) {
129 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
130 error_log( $e->getMessage() ); //phpcs:ignore
131 }
132 }
133 }
134
135 return $this->reflection;
136 }
137
138 /**
139 * Add module component.
140 *
141 * Add new component to the current module.
142 * @access public
143 *
144 * @param string $id Component ID.
145 * @param mixed $instance An instance of the component.
146 */
147 public function add_component( string $id, $instance ) {
148 $this->components[ $id ] = $instance;
149 }
150
151 /**
152 * @access public
153 *
154 * @return array
155 */
156 public function get_components(): array {
157 return $this->components;
158 }
159
160 /**
161 * Get module component.
162 *
163 * Retrieve the module component.
164 * @access public
165 *
166 * @param string $id Component ID.
167 *
168 * @return mixed An instance of the component, or `null` if the component
169 * doesn't exist.
170 */
171 public function get_component( string $id ) {
172 if ( isset( $this->components[ $id ] ) ) {
173 return $this->components[ $id ];
174 }
175
176 return null;
177 }
178
179 /**
180 * Retrieve the namespace of the class
181 *
182 * @static
183 * @access public
184 *
185 * @return string
186 */
187 public static function namespace_name(): string {
188 $class_name = static::class_name();
189 return substr( $class_name, 0, strrpos( $class_name, '\\' ) );
190 }
191
192 /**
193 * Adds an array of components.
194 * Assumes namespace structure contains `\Components\`
195 *
196 * @access protected
197 *
198 * @param ?array $components_ids => component's class name.
199 * @return void
200 */
201 protected function register_components( array $components_ids = null ): void {
202 if ( empty( $components_ids ) ) {
203 $components_ids = $this->get_component_ids();
204 }
205 $namespace = static::namespace_name();
206 foreach ( $components_ids as $component_id ) {
207 $class_name = $namespace . '\\Components\\' . $component_id;
208 $this->add_component( $component_id, new $class_name() );
209 }
210 }
211
212 /**
213 * Registers the Module's widgets.
214 * Assumes namespace structure contains `\Widgets\`
215 *
216 * @access protected
217 *
218 * @param \Elementor\Widgets_Manager $widgets_manager
219 * @return void
220 */
221 public function register_widgets( \Elementor\Widgets_Manager $widgets_manager ): void {
222 $widget_ids = $this->get_widget_ids();
223 $namespace = static::namespace_name();
224
225 foreach ( $widget_ids as $widget_id ) {
226 $class_name = $namespace . '\\Widgets\\' . $widget_id;
227 $widgets_manager->register( new $class_name() );
228 }
229 }
230
231 /**
232 * @access protected
233 *
234 * @return string[]
235 */
236 protected function get_widget_ids(): array {
237 return [];
238 }
239
240 /**
241 * @access protected
242 *
243 * @return void
244 */
245 protected function register_hooks(): void {
246 add_action( 'elementor/widgets/register', [ $this, 'register_widgets' ] );
247 }
248
249 /**
250 * Clone.
251 *
252 * Disable class cloning and throw an error on object clone.
253 *
254 * The whole idea of the singleton design pattern is that there is a single
255 * object. Therefore, we don't want the object to be cloned.
256 *
257 * @access private
258 */
259 public function __clone() {
260 // Cloning instances of the class is forbidden
261 _doing_it_wrong( __FUNCTION__, esc_html__( 'Something went wrong.', 'hello-plus' ), '0.0.1' ); // @codeCoverageIgnore
262 }
263
264 /**
265 * Wakeup.
266 *
267 * Disable un-serializing of the class.
268 * @access public
269 */
270 public function __wakeup() {
271 // Un-serializing instances of the class is forbidden
272 _doing_it_wrong( __FUNCTION__, esc_html__( 'Something went wrong.', 'hello-plus' ), '0.0.1' ); // @codeCoverageIgnore
273 }
274
275 /**
276 * class constructor
277 *
278 * @access protected
279 *
280 * @param ?string[] $components_list
281 */
282 protected function __construct( ?array $components_list = null ) {
283 $this->register_components( $components_list );
284 $this->register_hooks();
285 }
286 }
287