Completed
Branch dev (a4a708)
by
unknown
21:06
created

_triggerUndefinedMethodWarning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4286
cc 1
eloc 7
nc 1
nop 1
1
<?php
2
/**
3
 * Admin Page Framework
4
 * 
5
 * http://en.michaeluno.jp/admin-page-framework/
6
 * Copyright (c) 2013-2015 Michael Uno; Licensed MIT
7
 * 
8
 */
9
10
/**
11
 * Provides routing functionality to the Admin Page Framework factory object based on the fields type.
12
 * 
13
 * This class mainly deals with routing function calls and instantiation of objects based on the type.
14
 * 
15
 * @abstract
16
 * @since       3.0.4
17
 * @package     AdminPageFramework
18
 * @subpackage  Factory
19
 * @internal
20
 * @method      void    start()   User constructor. Defined in `AdminPageFramework_Factory_Controller`.
21
 * @method      void    _setUp()    
22
 */
23
abstract class AdminPageFramework_Factory_Router {
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
24
    
25
    /**
26
     * Stores the property object.
27
     * 
28
     * @since       2.0.0
29
     * @access      public      The AdminPageFramework_Page_MetaBox class accesses it.
30
     */     
31
    public $oProp;    
32
    
33
    /**
34
     * The object that provides the debug methods. 
35
     * 
36
     * @internal
37
     * @access      public
38
     * @since       2.0.0
39
     * @since       3.1.0   Changed the scope to public from protected.
40
     */     
41
    public $oDebug;
42
    /**
43
     * Provides the utility methods. 
44
     * 
45
     * @internal
46
     * @since       2.0.0
47
     * @since       3.1.0     Changed the scope to public from protected.
48
     */         
49
    public $oUtil;
50
    /**
51
     * Provides the methods for text messages of the framework. 
52
     * 
53
     * @since       2.0.0
54
     * @since       3.1.0     Changed the scope to public from protected.
55
     * @access      public
56
     * @internal
57
     */         
58
    public $oMsg;
59
    
60
    /**
61
     * The form object that provides methods to handle form sections and fields.
62
     * @internal
63
     * @since       3.0.0
64
     * @since       3.5.2       Changed the scope to public from protected as the widget class needs to initialize this object.
65
     */     
66
    public $oForm;
67
    
68
    /**
69
     * Inserts page load information into the footer area of the page. 
70
     * 
71
     */
72
    protected $oPageLoadInfo;
73
    
74
    /**
75
     * Provides the methods to insert head tag elements.
76
     * 
77
     * @since   3.3.0   Changed the name from $oHeadTag as it has become to deal with footer elements.
78
     */
79
    protected $oResource;
80
    
81
    /**
82
     * Provides the methods to insert head tag elements.
83
     * @deprecated
84
     */
85
    protected $oHeadTag;
86
    
87
    /**
88
     * Provides methods to manipulate contextual help pane.
89
     */
90
    protected $oHelpPane;
91
    
92
    /**
93
     * Provides the methods for creating HTML link elements. 
94
     * 
95
     */    
96
    protected $oLink;
97
    
98
    /**
99
     * Stores sub-class names.
100
     * 
101
     * Used in the __get() method to check whether a method with the name of the property should be called or not.
102
     * 
103
     * @since       3.5.3
104
     */
105
    protected $_aSubClassNames = array(
106
        'oDebug', 
107
        'oUtil',
108
        'oMsg',
109
        'oForm',
110
        'oPageLoadInfo',
111
        'oResource',
112
        'oHelpPane',
113
        'oLink',
114
    );
115
    
116
    /**
117
     * Sets up built-in objects.
118
     */
119
    public function __construct( $oProp ) {
120
121
        // Let them overload.
122
        unset( 
123
            $this->oDebug, 
124
            $this->oUtil, 
125
            $this->oMsg, 
126
            $this->oForm, 
127
            $this->oPageLoadInfo,
128
            $this->oResource,
129
            $this->oHelpPane,
130
            $this->oLink
131
        );
132
        
133
        // Property object
134
        $this->oProp = $oProp;
135
    
136
        if ( $this->oProp->bIsAdmin && ! $this->oProp->bIsAdminAjax ) {
137
            if ( did_action( 'current_screen' ) ) {
138
                $this->_replyToLoadComponents();
139
            } else {                
140
                add_action( 'current_screen', array( $this, '_replyToLoadComponents' ) );
141
            }
142
        }
143
        
144
        // Call the start method - defined in the controller class.
145
        $this->start();    
146
        
147
    }    
148
        
149
        /**
150
         * Determines whether the class component classes should be instantiated or not.
151
         * 
152
         * @internal
153
         * @callback    action      current_screen
154
         * @return      void
155
         */
156
        public function _replyToLoadComponents( /* $oScreen */ ) {
157
158
            if ( 'plugins.php' === $this->oProp->sPageNow ) {
159
                // triggers __get() if not set.
160
                $this->oLink = $this->oLink;
161
            }
162
    
163
            if ( ! $this->_isInThePage() ) { 
164
                return; 
165
            }
166
            
167
            // Do not load widget resources in the head tag because widgets can be loaded in any page unless it is in customize.php.
168
            if ( in_array( $this->oProp->_sPropertyType, array( 'widget' ) ) && 'customize.php' !== $this->oProp->sPageNow ) {
169
                return;
170
            }
171
            
172
            $this->_setSubClasses();
173
            
174
        }
175
            /**
176
             * Sets sub-class objects.
177
             * 
178
             * This method forces the overload method __get() to be triggered if those sub-class objects
179
             * are not set.
180
             * 
181
             * @since       3.5.3
182
             * @internal
183
             * @return      void
184
             */
185
            private function _setSubClasses() {
186
                $this->oResource        = $this->oResource;
187
                $this->oHeadTag         = $this->oResource; // backward compatibility                
0 ignored issues
show
Deprecated Code introduced by
The property AdminPageFramework_Factory_Router::$oHeadTag has been deprecated.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
188
                $this->oLink            = $this->oLink;
189
                $this->oPageLoadInfo    = $this->oPageLoadInfo;
190
            }
191
192
    /**
193
     * Determines whether the class object is instantiatable in the current page.
194
     * 
195
     * This method should be redefined in the extended class.
196
     * 
197
     * @since       3.1.0
198
     * @internal
199
     */ 
200
    protected function _isInstantiatable() { 
201
        return true; 
202
    }
203
    
204
    /**
205
     * Determines whether the instantiated object and its producing elements belong to the loading page.
206
     * 
207
     * This method should be redefined in the extended class.
208
     * 
209
     * @since       3.0.3
210
     * @since       3.2.0   Changed the scope to public from protected as the head tag object will access it.
211
     * @internal
212
     */
213
    public function _isInThePage() { 
214
        return true; 
215
    }
216
         
217
    /**
218
     * Instantiate a form object based on the type.
219
     * 
220
     * @since       3.1.0
221
     * @internal
222
     * @return      object|null
223
     * @deprecated  DEVVER
224
     */
225
    protected function _getFormInstance( $oProp ) {
226
227
        $_sFormClass = "AdminPageFramework_Form_{$oProp->_sPropertyType}";
228
        return new $_sFormClass(
229
            $oProp->aFormArguments, // Options - for the values that do not need to change through out the script execution. 
230
            $oProp->aFormCallbacks, // Callbacks - for the values which change dynamically depending on conditions such as the loaded page url.
231
            $this->oMsg
232
        );    
233
        
234
    }
235
    
236
    /**
237
     * Stores class names by fields type for help pane objects.
238
     * @since       3.5.3
239
     */    
240
    protected $_aResourceClassNameMap = array(
241
        'admin_page'            => 'AdminPageFramework_Resource_Page',
242
        'network_admin_page'    => 'AdminPageFramework_Resource_Page',
243
        'post_meta_box'         => 'AdminPageFramework_Resource_MetaBox',
244
        'page_meta_box'         => 'AdminPageFramework_Resource_MetaBox_Page',
245
        'post_type'             => 'AdminPageFramework_Resource_PostType',
246
        'taxonomy_field'        => 'AdminPageFramework_Resource_TaxonomyField',
247
        'widget'                => 'AdminPageFramework_Resource_Widget',
248
        'user_meta'             => 'AdminPageFramework_Resource_UserMeta',
249
    );        
250
    /**
251
     * Instantiate a resource handler object based on the type.
252
     * 
253
     * @since       3.0.4
254
     * @internal
255
     */
256
    protected function _getResourceInstance( $oProp ) {
257
        return $this->_getInstanceByMap( $this->_aResourceClassNameMap, $oProp->sStructureType, $oProp );
258
    }
259
    
260
    /**
261
     * Stores class names by fields type for help pane objects.
262
     * @since       3.5.3
263
     */    
264
    protected $_aHelpPaneClassNameMap = array(
265
        'admin_page'            => 'AdminPageFramework_HelpPane_Page',
266
        'network_admin_page'    => 'AdminPageFramework_HelpPane_Page',
267
        'post_meta_box'         => 'AdminPageFramework_HelpPane_MetaBox',
268
        'page_meta_box'         => 'AdminPageFramework_HelpPane_MetaBox_Page',
269
        'post_type'             => null,    // no help pane class for the post type factory class.
270
        'taxonomy_field'        => 'AdminPageFramework_HelpPane_TaxonomyField',
271
        'widget'                => 'AdminPageFramework_HelpPane_Widget',
272
        'user_meta'             => 'AdminPageFramework_HelpPane_UserMeta',
273
    );    
274
    /**
275
     * Instantiates a help pane object based on the type.
276
     * 
277
     * @since       3.0.4
278
     * @internal
279
     */
280
    protected function _getHelpPaneInstance( $oProp ) {
281
        return $this->_getInstanceByMap( $this->_aHelpPaneClassNameMap, $oProp->sStructureType, $oProp );
282
    }
283
    
284
    /**
285
     * Stores class names by fields type for link objects.
286
     * @since       3.5.3
287
     */
288
    protected $_aLinkClassNameMap = array(
289
        'admin_page'            => 'AdminPageFramework_Link_Page',
290
        'network_admin_page'    => 'AdminPageFramework_Link_NetworkAdmin',
291
        'post_meta_box'         => null,
292
        'page_meta_box'         => null,
293
        'post_type'             => 'AdminPageFramework_Link_PostType', 
294
        'taxonomy_field'        => null,
295
        'widget'                => null,
296
        'user_meta'             => null,
297
    );    
298
    /**
299
     * Instantiates a link object based on the type.
300
     * 
301
     * @since       3.0.4
302
     * @internal
303
     */
304
    protected function _getLinkInstancce( $oProp, $oMsg ) {
305
        return $this->_getInstanceByMap( $this->_aLinkClassNameMap, $oProp->sStructureType, $oProp, $oMsg );
306
    }
307
    
308
    /**
309
     * Stores class names by fields type for page load objects.
310
     * @since       3.5.3
311
     */
312
    protected $_aPageLoadClassNameMap = array(
313
        'admin_page'            => 'AdminPageFramework_PageLoadInfo_Page',
314
        'network_admin_page'    => 'AdminPageFramework_PageLoadInfo_NetworkAdminPage',
315
        'post_meta_box'         => null,
316
        'page_meta_box'         => null,
317
        'post_type'             => 'AdminPageFramework_PageLoadInfo_PostType', 
318
        'taxonomy_field'        => null,
319
        'widget'                => null,
320
        'user_meta'             => null,
321
    );
322
    /**
323
     * Instantiates a page load object based on the type.
324
     * 
325
     * @since 3.0.4
326
     * @internal
327
     */
328
    protected function _getPageLoadInfoInstance( $oProp, $oMsg ) {
329
        
330
        if ( ! isset( $this->_aPageLoadClassNameMap[ $oProp->sStructureType ] ) ) {
331
            return null;
332
        }
333
        $_sClassName = $this->_aPageLoadClassNameMap[ $oProp->sStructureType ];
334
        return call_user_func_array( array( $_sClassName, 'instantiate' ), array( $oProp, $oMsg ) );
335
336
    }
337
    
338
    /**
339
     * Returns a class object instance by the given map array and the key, plus one or two arguments.
340
     * 
341
     * @remark      There is a limitation that only can accept up to 3 parameters at the moment. 
342
     * @internal
343
     * @since       3.5.3
344
     * @return      null|object
345
     */
346
    private function _getInstanceByMap( /* array $aClassNameMap, $sKey, $mParam1, $mParam2, $mParam3 */ ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
347
        
348
        $_aParams       = func_get_args();
349
        $_aClassNameMap = array_shift( $_aParams );
350
        $_sKey          = array_shift( $_aParams );
351
        
352
        if ( ! isset( $_aClassNameMap[ $_sKey ] ) ) {
353
            return null;
354
        }
355
        
356
        $_iParamCount = count( $_aParams );
357
        
358
        // passing more than 3 arguments is not supported at the moment.
359
        if ( $_iParamCount > 3 ) {
360
            return null;
361
        }
362
        
363
        // Insert the class name at the beginning of the parameter array.
364
        array_unshift( $_aParams, $_aClassNameMap[ $_sKey ] );    
365
        
366
        // Instantiate the class and return the instance.
367
        return call_user_func_array( 
368
            array( $this, "_replyToGetClassInstanceByArgumentOf{$_iParamCount}" ), 
369
            $_aParams
370
        );
371
    
372
    }
373
        /**#@+
374
         * @internal
375
         * @return      object
376
         */      
377
        /**
378
         * Instantiate a class with zero parameter.
379
         * @since       3.5.3
380
         */
381
        private function _replyToGetClassInstanceByArgumentOf0( $sClassName ) {
382
            return new $sClassName;
383
        }    
384
        /**
385
         * Instantiate a class with one parameter.
386
         * @since       3.5.3
387
         */        
388
        private function _replyToGetClassInstanceByArgumentOf1( $sClassName, $mArg ) {
389
            return new $sClassName( $mArg );
390
        }
391
        /**
392
         * Instantiate a class with two parameters.
393
         * @since       3.5.3
394
         */             
395
        private function _replyToGetClassInstanceByArgumentOf2( $sClassName, $mArg1, $mArg2 ) {
396
            return new $sClassName( $mArg1, $mArg2 );
397
        }      
398
        /**
399
         * Instantiate a class with two parameters.
400
         * @since       3.5.3
401
         */             
402
        private function _replyToGetClassInstanceByArgumentOf3( $sClassName, $mArg1, $mArg2, $mArg3 ) {
403
            return new $sClassName( $mArg1, $mArg2, $mArg3 );
404
        }              
405
        /**#@-*/        
406
    
407
    /**
408
     * Responds to a request of an undefined property.
409
     * 
410
     * This is used to instantiate classes only when necessary, rather than instantiating them all at once.
411
     * 
412
     * @internal
413
     */
414
    public function __get( $sPropertyName ) {
415
            
416
        switch( $sPropertyName ) {
417
            case 'oHeadTag':    // 3.3.0+ for backward compatibility
418
                $sPropertyName = 'oResource';
419
                break;
420
        }     
421
422
        // Set and return the sub class object instance.
423
        if ( in_array( $sPropertyName, $this->_aSubClassNames ) ) {            
424
            return call_user_func( 
425
                array( $this, "_replyTpSetAndGetInstance_{$sPropertyName}"  )
426
            );
427
        }
428
        
429
    }
430
        /**#@+
431
         * @internal
432
         * @return      object
433
         * @callback    function    call_user_func
434
         */          
435
        /**
436
         * Sets and returns the `oUtil` property.
437
         * @since       3.5.3
438
         */
439
        public function _replyTpSetAndGetInstance_oUtil() {
440
            $this->oUtil = new AdminPageFramework_WPUtility;
441
            return $this->oUtil;
442
        }
443
        /**
444
         * Sets and returns the `oDebug` property.
445
         * @since       3.5.3
446
         */        
447
        public function _replyTpSetAndGetInstance_oDebug() {
448
            $this->oDebug = new AdminPageFramework_Debug;
449
            return $this->oDebug;
450
        }
451
        /**
452
         * Sets and returns the `oMsg` property.
453
         * @since       3.5.3
454
         */              
455
        public function _replyTpSetAndGetInstance_oMsg() {
456
            $this->oMsg = AdminPageFramework_Message::getInstance( $this->oProp->sTextDomain );
457
            return $this->oMsg;
458
        }
459
        /**
460
         * Sets and returns the `oForm` property.
461
         * @since       3.5.3
462
         */              
463
        public function _replyTpSetAndGetInstance_oForm() {
464
            $this->oForm = $this->_getFormInstance( $this->oProp );           
0 ignored issues
show
Deprecated Code introduced by
The method AdminPageFramework_Facto...ter::_getFormInstance() has been deprecated with message: DEVVER

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
465
            return $this->oForm;
466
        }
467
        /**
468
         * Sets and returns the `oResouce` property.
469
         * @since       3.5.3
470
         */            
471
        public function _replyTpSetAndGetInstance_oResource() {
472
            $this->oResource = $this->_getResourceInstance( $this->oProp );
473
            return $this->oResource;
474
        }
475
        /**
476
         * Sets and returns the `oHelpPane` property.
477
         * @since       3.5.3
478
         */
479
        public function _replyTpSetAndGetInstance_oHelpPane() {
480
            $this->oHelpPane = $this->_getHelpPaneInstance( $this->oProp );
481
            return $this->oHelpPane;
482
        }
483
        /**
484
         * Sets and returns the `oLink` property.
485
         * @since       3.5.3
486
         */
487
        public function _replyTpSetAndGetInstance_oLink() {
488
            $this->oLink = $this->_getLinkInstancce( $this->oProp, $this->oMsg );
489
            return $this->oLink;
490
        }
491
        /**
492
         * Sets and returns the `oPageLoadInfo` property.
493
         * @since       3.5.3
494
         */        
495
        public function _replyTpSetAndGetInstance_oPageLoadInfo() {
496
            $this->oPageLoadInfo = $this->_getPageLoadInfoInstance( $this->oProp, $this->oMsg );
497
            return $this->oPageLoadInfo;
498
        }
499
        /**#@-*/
500
        
501
    /**
502
     * Redirects dynamic function calls to the pre-defined internal method.
503
     * 
504
     * @internal
505
     */
506
    public function __call( $sMethodName, $aArguments=null ) {    
507
         
508
        $_mFirstArg = $this->oUtil->getElement( $aArguments, 0 );
509
        
510
        switch ( $sMethodName ) {
511
            case 'validate':
512
            case 'content':
513
                return $_mFirstArg;
514
            case 'setup_pre':
515
                $this->_setUp();
516
                
517
                // This action hook must be called AFTER the _setUp() method as there are callback methods that hook into this hook and assumes required configurations have been made.
518
                $this->oUtil->addAndDoAction( 
519
                    $this, 
520
                    "set_up_{$this->oProp->sClassName}", 
521
                    $this 
522
                );
523
                return;
524
        }
525
        
526
        // If it is called with the framework auto-callback,
527
        if ( has_filter( $sMethodName ) ) {
528
            return $this->_getAutoCallback( $sMethodName, $aArguments );
529
        }
530
                
531
        $this->_triggerUndefinedMethodWarning( $sMethodName );
532
        
533
    }     
534
        /**
535
         * Returns the first parameter value if the method name does not contain a backslash.
536
         * If it contains a backslash, the user uses a name-spaced class name. In that case,
537
         * the backslashes need to be converted to underscores to support valid PHP method names.
538
         * 
539
         * @since       DEVVER
540
         */
541
        private function _getAutoCallback( $sMethodName, $aArguments ) {
542
            
543
            // Check if the method name contains a backslash.
544
            if ( false === strpos( $sMethodName, "\\" ) ) {
545
                return $this->oUtil->getElement( $aArguments, 0 );  // the first element - the filter value
546
            }
547
                
548
            // if the method name contains a backslash, the user may be using a name space. 
549
            // In that case, convert the backslash to underscore and call the method.
550
            $_sAutoCallbackClassName = str_replace( '\\', '_', $this->oProp->sClassName );
551
            return method_exists( $this, $_sAutoCallbackClassName )
552
                ? call_user_func_array(
553
                    array( $this, $_sAutoCallbackClassName ),
554
                    $aArguments
555
                )
556
                : $this->oUtil->getElement( $aArguments, 0 );   // the first argument
557
            
558
        }
559
        
560
        /**
561
         * @since   DEVVER
562
         * @return  void
563
         */
564
        private function _triggerUndefinedMethodWarning( $sMethodName ) {
565
            trigger_error(
566
                AdminPageFramework_Registry::NAME . ': ' 
567
                    . sprintf( 
568
                        __( 'The method is not defined: %1$s', $this->oProp->sTextDomain ),
569
                        $sMethodName 
570
                    ), 
571
                E_USER_WARNING 
572
            );            
573
        }
574
            
575
        
576
    
577
    /**
578
     * Prevents the output from getting too long when the object is dumped.
579
     *
580
     * Field definition arrays contain the factory object reference and when the debug log method tries to dump it, the output gets too long.
581
     * So shorten it here.
582
     * 
583
     * @remark      Called when the object is called as a string.
584
     * @since       3.4.4
585
     */   
586
    public function __toString() {
587
        return $this->oUtil->getObjectInfo( $this );        
588
    }
589
 
590
    /**
591
     * Deprecated methods.
592
     */
593
    /**
594
     * @remark          This was not functional since 3.1.3
595
     * @deprecated      3.5.5
596
     */
597
    public function setFooterInfoRight() {}
598
    /**
599
     * @remark          This was not functional since 3.1.3
600
     * @deprecated      3.5.5
601
     */    
602
    public function setFooterInfoLeft() {}
603
 
604
}