@@ -173,45 +173,86 @@ public function init() {
173173 }
174174
175175 /**
176- * Magic method to get properties.
177- * We use this to avoid a lot of code duplication.
176+ * Magic method to dynamically instantiate and cache plugin classes.
178177 *
179- * Use a double underscore to separate namespaces:
180- * - get_foo() will return an instance of Progress_Planner\Foo.
181- * - get_foo_bar() will return an instance of Progress_Planner\Foo_Bar.
182- * - get_foo_bar__baz() will return an instance of Progress_Planner\Foo_Bar\Baz.
178+ * This method enables lazy-loading of plugin classes using a simple naming convention,
179+ * reducing code duplication and improving performance by instantiating classes only when needed.
183180 *
184- * @param string $name The name of the property.
185- * @param array $arguments The arguments passed to the class constructor.
181+ * Naming convention and transformation rules:
182+ * - Method names must start with 'get_'
183+ * - Single underscore (_) = word boundary, becomes uppercase in class name
184+ * - Double underscore (__) = namespace separator, becomes backslash (\)
186185 *
187- * @return mixed
186+ * Examples:
187+ * ```
188+ * get_settings() → Progress_Planner\Settings
189+ * get_admin__page() → Progress_Planner\Admin\Page
190+ * get_activities__query() → Progress_Planner\Activities\Query
191+ * get_suggested_tasks_db() → Progress_Planner\Suggested_Tasks_Db
192+ * get_admin__widgets__todo() → Progress_Planner\Admin\Widgets\Todo
193+ * ```
194+ *
195+ * Transformation process:
196+ * 1. Remove 'get_' prefix from method name
197+ * 2. Split on '__' to separate namespace parts
198+ * 3. For each part, split on '_', uppercase first letter of each word, rejoin
199+ * 4. Join namespace parts with '\' and prepend 'Progress_Planner\'
200+ *
201+ * Caching:
202+ * - Once instantiated, classes are cached in $this->cached array
203+ * - Subsequent calls return the cached instance (singleton pattern per class)
204+ * - Cache key is the method name without 'get_' prefix
205+ *
206+ * Backwards compatibility:
207+ * - Deprecated method names are mapped in Deprecations::BASE_METHODS
208+ * - Triggers WordPress deprecation notice and redirects to new method
209+ *
210+ * @param string $name The method name being called (e.g., 'get_admin__page').
211+ * @param array $arguments Arguments passed to the method (forwarded to class constructor).
212+ *
213+ * @return object|null The instantiated class, cached instance, or null if method doesn't start with 'get_'.
188214 */
189215 public function __call ( $ name , $ arguments ) {
216+ // Only handle methods starting with 'get_'.
190217 if ( 0 !== \strpos ( $ name , 'get_ ' ) ) {
191- return ;
218+ return null ;
192219 }
220+
221+ // Extract cache key by removing 'get_' prefix.
193222 $ cache_name = \substr ( $ name , 4 );
223+
224+ // Return cached instance if already instantiated (singleton pattern).
194225 if ( isset ( $ this ->cached [ $ cache_name ] ) ) {
195226 return $ this ->cached [ $ cache_name ];
196227 }
197228
229+ // Transform method name to fully qualified class name.
230+ // Step 1: Split on '__' to get namespace parts (e.g., 'admin__page' → ['admin', 'page']).
198231 $ class_name = \implode ( '\\' , \explode ( '__ ' , $ cache_name ) );
232+ // Step 2: Split each part on '_', capitalize words, and rejoin.
233+ // e.g., 'suggested_tasks_db' → 'Suggested_Tasks_Db'.
234+ // Then prepend namespace: 'Progress_Planner\Suggested_Tasks_Db'.
199235 $ class_name = 'Progress_Planner \\' . \implode ( '_ ' , \array_map ( 'ucfirst ' , \explode ( '_ ' , $ class_name ) ) );
236+
237+ // Instantiate the class if it exists.
200238 if ( \class_exists ( $ class_name ) ) {
201239 $ this ->cached [ $ cache_name ] = new $ class_name ( $ arguments );
202240 return $ this ->cached [ $ cache_name ];
203241 }
204242
205- // Backwards- compatibility.
243+ // Handle deprecated method names for backwards compatibility.
206244 if ( isset ( Deprecations::BASE_METHODS [ $ name ] ) ) {
207- // Deprecated method .
245+ // Trigger WordPress deprecation notice .
208246 \_deprecated_function (
209247 \esc_html ( $ name ),
210- \esc_html ( Deprecations::BASE_METHODS [ $ name ][1 ] ),
211- \esc_html ( Deprecations::BASE_METHODS [ $ name ][0 ] )
248+ \esc_html ( Deprecations::BASE_METHODS [ $ name ][1 ] ), // Version deprecated.
249+ \esc_html ( Deprecations::BASE_METHODS [ $ name ][0 ] ) // Replacement method.
212250 );
251+ // Call the replacement method.
213252 return $ this ->{Deprecations::BASE_METHODS [ $ name ][0 ]}();
214253 }
254+
255+ return null ;
215256 }
216257
217258 /**
0 commit comments