Completed
Branch dev (1ad2e5)
by
unknown
04:33
created

_replyToModifyEnqueuedAttrbutes()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
c 0
b 0
f 0
nc 4
nop 3
dl 0
loc 26
rs 8.5806
1
<?php 
2
/**
3
 * Admin Page Framework
4
 * 
5
 * http://en.michaeluno.jp/admin-page-framework/
6
 * Copyright (c) 2013-2016 Michael Uno; Licensed MIT
7
 * 
8
 */
9
10
/**
11
 * Provides methods to enqueue or insert resource elements.
12
 *  
13
 * The class handles `<link>`, `<style>` and `<script>` tags to be inserted conditionally into the head tag or the footer of the page.
14
 * 
15
 * @abstract
16
 * @since       2.1.5
17
 * @since       3.3.0       Changed the name from `AdminPageFramework_HeadTag_Base`.
18
 * @since       3.6.3       Changed it to extend `AdminPageFramework_WPUtility`.
19
 * @extends     AdminPageFramework_FrameworkUtility
20
 * @package     AdminPageFramework
21
 * @subpackage  Common/Factory/Resource
22
 * @internal
23
 * @extends     AdminPageFramework_FrameworkUtility
24
 */
25
abstract class AdminPageFramework_Resource_Base extends AdminPageFramework_FrameworkUtility {
26
    
27
    /**
28
     * Represents the structure of the array for enqueuing scripts and styles.
29
     * 
30
     * @since       2.1.2
31
     * @since       2.1.5       Moved to the base class.
32
     * @since       3.0.0       Moved from the property class.
33
     * @since       3.3.0       Changed the name to `$_aStructure_EnqueuingResources` from `$_aStructure_EnqueuingScriptsAndStyles`.
34
     * @internal
35
     */
36
    protected static $_aStructure_EnqueuingResources = array(
37
    
38
        /* The system internal keys. */
39
        'sSRC'          => null,
40
        'aPostTypes'    => array(),     // for meta box class
41
        'sPageSlug'     => null,    
42
        'sTabSlug'      => null,
43
        'sType'         => null,        // script or style
44
        
45
        /* The below keys are for users. */
46
        'handle_id'     => null,
47
        'dependencies'  => array(),
48
        'version'       => false,       // although the type should be string, the wp_enqueue_...() functions want false as the default value.
49
        'translation'   => array(),     // only for scripts
50
        'in_footer'     => false,       // only for scripts
51
        'media'         => 'all',       // only for styles     
52
        'attributes'    => array(),     // 3.3.0+ - the attribute array
53
        
54
    );    
55
      
56
    /**
57
     * Stores the class selector used for the class-specific style.
58
     * 
59
     * @since       3.2.0
60
     * @remark      This value should be overridden in an extended class.
61
     * @internal
62
     */
63
    protected $_sClassSelector_Style    = 'admin-page-framework-style';
64
    
65
    /**
66
     * Stores the class selector used to the class-specific script.
67
     * 
68
     * @since       3.2.0
69
     * @remark      This value should be overridden in an extended class.
70
     * @internal
71
     */    
72
    protected $_sClassSelector_Script   = 'admin-page-framework-script';
73
      
74
    /**
75
     * Stores hand IDs by resource url to look up handle id and add custom arguments.
76
     * @since       3.3.0
77
     * @internal
78
     */ 
79
    protected $_aHandleIDs = array();
80
      
81
    /**
82
     * A property object.
83
     * 
84
     * @remark      Set in the constructor.
85
     */ 
86
    public $oProp;
87
    
88
    /**
89
     * A utility object.
90
     * 
91
     * @remark      Set in the constructor.
92
     * @deprecated  3.6.3
93
     * @remark      kept for backward compatibility.
94
     */
95
    public $oUtil;
96
    
97
    /**
98
     * Sets up properties and hooks.
99
     * @internal
100
     */
101
    public function __construct( $oProp ) {
102
        
103
        if ( $this->isDoingAjax() ) {
104
            return;
105
        }        
106
        
107
        $this->oProp = $oProp;
108
        
109
        // for backward compatibility
110
        $this->oUtil = new AdminPageFramework_WPUtility;
0 ignored issues
show
Deprecated Code introduced by
The property AdminPageFramework_Resource_Base::$oUtil has been deprecated with message: 3.6.3

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...
111
        
112
        // Hook the admin header to insert custom admin stylesheets and scripts.
113
        add_action( 'admin_enqueue_scripts', array( $this, '_replyToEnqueueScripts' ) );
114
        add_action( 'admin_enqueue_scripts', array( $this, '_replyToEnqueueStyles' ) );
115
        
116
        /// A low priority is required to let dependencies loaded fast especially in customizer.php.
117
        add_action( did_action( 'admin_print_styles' ) ? 'admin_print_footer_scripts' : 'admin_print_styles', array( $this, '_replyToAddStyle' ), 999 );
118
        add_action( did_action( 'admin_print_scripts' ) ? 'admin_print_footer_scripts' : 'admin_print_scripts', array( $this, '_replyToAddScript' ), 999 );     
119
    
120
        // Take care of items that could not be added in the head tag.
121
        
122
        /// For wp-admin/customizer.php 
123
        add_action( 'customize_controls_print_footer_scripts', array( $this, '_replyToEnqueueScripts' ) );
124
        add_action( 'customize_controls_print_footer_scripts', array( $this, '_replyToEnqueueStyles' ) );
125
126
        /// For admin pages other than wp-admin/customizer.php 
127
        add_action( 'admin_footer', array( $this, '_replyToEnqueueScripts' ) ); 
128
        add_action( 'admin_footer', array( $this, '_replyToEnqueueStyles' ) );        
129
        
130
        /// For all admin pages.
131
        add_action( 'admin_print_footer_scripts', array( $this, '_replyToAddStyle' ), 999 );
132
        add_action( 'admin_print_footer_scripts', array( $this, '_replyToAddScript' ), 999 );  
133
        
134
        
135
        // To add the custom attributes to the enqueued style and script tags.
136
        add_filter( 'script_loader_src', array( $this, '_replyToSetupArgumentCallback' ), 1, 2 );
137
        add_filter( 'style_loader_src', array( $this, '_replyToSetupArgumentCallback' ), 1, 2 );
138
139
    }    
140
                
141
    /*
142
     * Methods that should be overridden in extended classes.
143
     * @internal
144
     */
145
    
146
    public function _forceToEnqueueStyle( $sSRC, $aCustomArgs=array() ) {}
147
    public function _forceToEnqueueScript( $sSRC, $aCustomArgs=array() ) {}
148
    
149
    /**
150
     * A helper function for the _replyToEnqueueScripts() and the `_replyToEnqueueStyle()` methods.
151
     * 
152
     * @since       2.1.5
153
     * @since       3.7.0      Fixed a typo in the method name.
154
     * @internal
155
     * @remark      The widget fields type does not have conditions unlike the meta-box type that requires to check currently loaded post type.
156
     * @remark      This method should be redefined in the extended class.
157
     */
158
    protected function _enqueueSRCByCondition( $aEnqueueItem ) {
159
        return $this->_enqueueSRC( $aEnqueueItem );            
160
    }
161
    
162
    /*
163
     * Shared methods
164
     */
165
        /**
166
         * Checks the src url of the enqueued script/style to determine whether or not to set up a attribute modification callback.
167
         * 
168
         * If it is one of the framework added item, the method sets up a hook to modify the url to add custom attributes.
169
         * 
170
         * @since       3.3.0
171
         * @internal
172
         * @callback    action      script_loader_src
173
         * @callback    action      style_loader_src
174
         */
175
        public function _replyToSetupArgumentCallback( $sSRC, $sHandleID ) {
176
177
            if ( isset( $this->oProp->aResourceAttributes[ $sHandleID ] ) ) {
178
                $this->_aHandleIDs[ $sSRC ] = $sHandleID;
179
                add_filter( 'clean_url', array( $this, '_replyToModifyEnqueuedAttrbutes' ), 1, 3 );
180
                remove_filter( current_filter(), array( $this, '_replyToSetupArgumentCallback' ), 1, 2 );
181
            }
182
            return $sSRC;
183
            
184
        }    
185
            /**
186
             * Modifies the attributes of the enqueued script tag.
187
             * 
188
             * @since   3.3.0
189
             * @internal
190
             */
191
            public function _replyToModifyEnqueuedAttrbutes( $sSanitizedURL, $sOriginalURL, $sContext ) {
192
                
193
                if ( 'display' !== $sContext ) {
194
                    return $sSanitizedURL;
195
                }
196
            
197
                // Returns the modified url which attributes are embedded at the end.
198
                if ( isset( $this->_aHandleIDs[ $sOriginalURL ] ) ) {
199
                    
200
                    $_sHandleID     = $this->_aHandleIDs[ $sOriginalURL ];
201
                    $_aAttributes   = $this->oProp->aResourceAttributes[ $_sHandleID ];
202
                    
203
                    if ( empty( $_aAttributes ) ) {
204
                        return $sSanitizedURL;
205
                    }
206
                    
207
                    $_sAttributes   = $this->getAttributes( $_aAttributes );
208
                    $_sModifiedURL  = $sSanitizedURL . "' " . rtrim( $_sAttributes, "'\"" );    // '"
209
210
                    return $_sModifiedURL;                    
211
                    
212
                }
213
214
                return $sSanitizedURL;
215
             
216
            }
217
     
218
     
219
    /**
220
     * Flags whether the common styles are loaded or not.
221
     * 
222
     * @since       3.2.0
223
     * @internal
224
     */
225
    static private $_bCommonStyleLoaded = false;
226
    
227
    /**
228
     * Prints the inline stylesheet of the meta-box common CSS rules with the style tag.
229
     * 
230
     * @internal
231
     * @since       3.0.0
232
     * @since       3.2.0       Moved to the base class from the meta box class.
233
     * @remark      The meta box class may be instantiated multiple times so prevent echoing the same styles multiple times.
234
     * @parameter   string      $sIDPrefix   The id selector embedded in the script tag.
235
     * @parameter   string      $sClassName  The class name that identify the call group. This is important for the meta-box class because it can be instantiated multiple times in one particular page.
236
     */
237
    protected function _printCommonStyles( $sIDPrefix, $sClassName ) {
0 ignored issues
show
Unused Code introduced by
The parameter $sClassName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
238
239
        if ( self::$_bCommonStyleLoaded ) { 
240
            return; 
241
        }
242
        self::$_bCommonStyleLoaded = true;
243
        
244
        $_oCaller = $this->oProp->oCaller;     
245
        echo $this->_getStyleTag( $_oCaller, $sIDPrefix );
246
        echo $this->_getIEStyleTag( $_oCaller, $sIDPrefix );
247
            
248
    }   
249
        /**
250
         * @internal
251
         * @since       3.5.7
252
         * @return      string
253
         */
254
        private function _getStyleTag( $oCaller, $sIDPrefix ) {
255
            
256
            $_sStyle     = $this->addAndApplyFilters( 
257
                $oCaller, 
258
                array(
259
                    "style_common_admin_page_framework",            // 3.2.1+
260
                    "style_common_{$this->oProp->sClassName}",
261
                ), 
262
                AdminPageFramework_CSS::getDefaultCSS() 
263
            );
264
            $_sStyle = trim( $_sStyle );
265
            
266
            // @deprecated      3.7.10      The beautifier script compresses inline CSS rules.
267
            // $_sStyle     = $this->isDebugMode()
268
                // ? trim( $_sStyle )
269
                // : $this->getCSSMinified( $_sStyle );
270
                
271
            if ( $_sStyle ) {
272
                echo "<style type='text/css' id='" . esc_attr( $sIDPrefix ) . "'>"
273
                        . $_sStyle
274
                    . "</style>";
275
            }
276
         
277
            
278
        }    
279
        /**
280
         * @internal
281
         * @since       3.5.7
282
         * @return      string
283
         */        
284
        private function _getIEStyleTag( $oCaller, $sIDPrefix ) {
285
                
286
            $_sStyleIE   = $this->addAndApplyFilters( 
287
                $oCaller, 
288
                array(
289
                    "style_ie_common_admin_page_framework",         // 3.2.1+
290
                    "style_ie_common_{$this->oProp->sClassName}", 
291
                ),
292
                AdminPageFramework_CSS::getDefaultCSSIE() 
293
            );
294
            $_sStyleIE = trim( $_sStyleIE );
295
            // @deprecated      3.7.10      The beautifier script compresses inline CSS rules.
296
            // $_sStyleIE   = $this->isDebugMode()
297
                // ? trim( $_sStyleIE )
298
                // : $this->getCSSMinified( $_sStyleIE );
299
            return $_sStyleIE
300
                ? "<!--[if IE]><style type='text/css' id='" . esc_attr( $sIDPrefix . "-ie" ) . "'>"
301
                        . $_sStyleIE
302
                    . "</style><![endif]-->"
303
                : '';
304
    
305
        }
306
    
307
    /**
308
     * Flags whether the common styles are loaded or not.
309
     * 
310
     * @since       3.2.0
311
     * @internal
312
     */
313
    static private $_bCommonScriptLoaded = false;
314
    
315
    /**
316
     * Prints the inline scripts of the meta-box common scripts.
317
     * 
318
     * @internal
319
     * @since       3.0.0
320
     * @since       3.2.0       Moved to the base class from the meta box class.       
321
     * @remark      The meta box class may be instantiated multiple times so prevent echoing the same styles multiple times.
322
     * @parametr    string      $sIDPrefix      The id selector embedded in the script tag.
323
     * @parametr    string      $sClassName     The class name that identify the call group. This is important for the meta-box class because it can be instantiated multiple times in one particular page.
324
     */
325
    protected function _printCommonScripts( $sIDPrefix, $sClassName ) {
0 ignored issues
show
Unused Code introduced by
The parameter $sClassName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
326
        
327
        if ( self::$_bCommonScriptLoaded ) { return; }
328
        self::$_bCommonScriptLoaded = true;
329
        
330
        $_sScript = $this->addAndApplyFilters( 
331
            $this->oProp->oCaller, 
332
            array(
333
                "script_common_admin_page_framework",       // 3.2.1+
334
                "script_common_{$this->oProp->sClassName}", 
335
            ),
336
            AdminPageFramework_Property_Base::$_sDefaultScript 
337
        );
338
        $_sScript = trim( $_sScript );
339
        if ( $_sScript ) {
340
            echo "<script type='text/javascript' id='" . esc_attr( $sIDPrefix ) . "'>"
341
                    . '/* <![CDATA[ */'
342
                    . $_sScript
343
                    . '/* ]]> */'
344
                . "</script>";
345
        }
346
    
347
    }    
348
     
349
    /**
350
     * Prints the inline stylesheet of this class stored in this class property.
351
     * 
352
     * @since       3.0.0
353
     * @since       3.2.0       Made the properties storing styles empty. Moved to the base class.
354
     * @internal
355
     * @return      void
356
     */
357
    protected function _printClassSpecificStyles( $sIDPrefix ) {
358
           
359
        $_oCaller   = $this->oProp->oCaller;     
360
        echo $this->_getClassSpecificStyleTag( $_oCaller, $sIDPrefix );
361
        echo $this->_getClassSpecificIEStyleTag( $_oCaller, $sIDPrefix );
362
        
363
        // As of 3.2.0, this method also gets called in the footer to ensure there is not any left styles.
364
        // This happens when a head tag item is added after the head tag is already rendered such as for widget forms.
365
        $this->oProp->sStyle    = '';          
366
        $this->oProp->sStyleIE  = '';
367
    
368
    }
369
        /**
370
         * 
371
         * @internal
372
         * @since       3.5.7
373
         * @return      string
374
         */
375
        private function _getClassSpecificStyleTag( $_oCaller, $sIDPrefix ) {
376
            
377
            static $_iCallCount = 1;    
378
            $_sStyle = $this->addAndApplyFilters( 
379
                $_oCaller, 
380
                "style_{$this->oProp->sClassName}", 
381
                $this->oProp->sStyle 
382
            );
383
            $_sStyle = trim( $_sStyle );
384
            // @deprecated      3.7.10      The beautifier script compresses inline CSS rules.
385
            // $_sStyle = $this->isDebugMode()
386
                // ? trim( $_sStyle )
387
                // : $this->getCSSMinified( $_sStyle );
388
            if ( $_sStyle ) {
389
                $_iCallCount++;
390
                return "<style type='text/css' id='" . esc_attr( "{$sIDPrefix}-{$this->oProp->sClassName}_{$_iCallCount}" ) . "'>"
391
                        . $_sStyle
392
                    . "</style>";
393
            }         
394
            return '';
395
            
396
        }
397
        /**
398
         * 
399
         * @internal
400
         * @since       3.5.7
401
         * @return      string
402
         */        
403
        private function _getClassSpecificIEStyleTag( $_oCaller, $sIDPrefix ) {
404
            
405
            static $_iCallCountIE = 1;  
406
            $_sStyleIE = $this->addAndApplyFilters( 
407
                $_oCaller,
408
                "style_ie_{$this->oProp->sClassName}",
409
                $this->oProp->sStyleIE 
410
            );
411
            $_sStyleIE = trim( $_sStyleIE );
412
            // @deprecated      3.7.10      The beautifier script compresses inline CSS rules.
413
            // $_sStyleIE = $this->isDebugMode()
414
                // ? trim( $_sStyleIE )
415
                // : $this->getCSSMinified( $_sStyleIE );
416
            if ( $_sStyleIE ) {
417
                $_iCallCountIE++;
418
                return "<!--[if IE]><style type='text/css' id='" . esc_attr( "{$sIDPrefix}-ie-{$this->oProp->sClassName}_{$_iCallCountIE}" ) . "'>" 
419
                        . $_sStyleIE
420
                    . "</style><![endif]-->";
421
            }            
422
            return '';
423
            
424
        }
425
        
426
    /**
427
     * Prints the inline scripts of this class stored in this class property.
428
     * 
429
     * @since       3.0.0
430
     * @since       3.2.0       Made the property empty that stores scripts. Moved to the base class.
431
     * @internal
432
     */
433
    protected function _printClassSpecificScripts( $sIDPrefix ) {
434
        
435
        static $_iCallCount = 1;
436
        $_sScript = $this->addAndApplyFilters( 
437
            $this->oProp->oCaller,
438
            array(
439
                "script_{$this->oProp->sClassName}", 
440
            ),
441
            $this->oProp->sScript 
442
        );
443
        $_sScript = trim( $_sScript );
444
        if ( $_sScript ) {
445
            $_iCallCount++;
446
            echo "<script type='text/javascript' id='" . esc_attr( "{$sIDPrefix}-{$this->oProp->sClassName}_{$_iCallCount}" ) . "'>" 
447
                    . '/* <![CDATA[ */'
448
                    . $_sScript
449
                    . '/* ]]> */'
450
                . "</script>"; 
451
        }
452
        
453
        // As of 3.2.0, this method also gets called in the footer to ensure there is not any left scripts.
454
        // This happens when a head tag item is added after the head tag is already rendered such as for widget forms.
455
        $this->oProp->sScript = '';
456
        
457
    }     
458
459
    
460
    /**
461
     * Appends the CSS rules of the framework in the head tag. 
462
     * 
463
     * @since       2.0.0
464
     * @since       2.1.5       Moved from `AdminPageFramework_MetaBox`. Changed the name from `addAtyle()` to `replyToAddStyle()`.
465
     * @callback    action      admin_head
466
     * @internal
467
     */     
468
    public function _replyToAddStyle() {
469
    
470
        $_oCaller = $this->oProp->oCaller;     
471
        if ( ! $_oCaller->_isInThePage() ) {
472
            return; 
473
        }
474
        
475
        $this->_printCommonStyles( 'admin-page-framework-style-common', get_class() );
476
        $this->_printClassSpecificStyles( $this->_sClassSelector_Style . '-' . $this->oProp->sStructureType );
477
 
478
    }
479
    /**
480
     * Appends the JavaScript script of the framework in the head tag. 
481
     * 
482
     * @callback    action      admin_head
483
     * @since       2.0.0
484
     * @since       2.1.5       Moved from AdminPageFramework_MetaBox. Changed the name from `addScript()` to `replyToAddScript()`.
485
     * @since       3.2.0       Moved from AdminPageFramework_Resource_post_meta_box. 
486
     * @internal
487
     */ 
488
    public function _replyToAddScript() {
489
490
        $_oCaller = $this->oProp->oCaller;     
491
        if ( ! $_oCaller->_isInThePage() ) { 
492
            return; 
493
        }
494
        
495
        $this->_printCommonScripts( 'admin-page-framework-script-common', get_class() );
496
        $this->_printClassSpecificScripts( $this->_sClassSelector_Script . '-' . $this->oProp->sStructureType );
497
        
498
    }        
499
    
500
     
501
    /**
502
     * Performs actual enqueuing items. 
503
     * 
504
     * @since       2.1.2
505
     * @since       2.1.5       Moved from the main class.
506
     * @internal
507
     */
508
    protected function _enqueueSRC( $aEnqueueItem ) {
509
        
510
        // For styles
511
        if ( 'style' === $aEnqueueItem['sType'] ) {
512
            wp_enqueue_style( 
513
                $aEnqueueItem['handle_id'], 
514
                $aEnqueueItem['sSRC'], 
515
                $aEnqueueItem['dependencies'], 
516
                $aEnqueueItem['version'], 
517
                $aEnqueueItem['media']
518
            );
519
            return;
520
        }
521
522
        // For scripts
523
        wp_enqueue_script( 
524
            $aEnqueueItem['handle_id'], 
525
            $aEnqueueItem['sSRC'], 
526
            $aEnqueueItem['dependencies'], 
527
            $aEnqueueItem['version'], 
528
            did_action( 'admin_body_class' ) ? true : $aEnqueueItem['in_footer'] 
529
        );
530
    
531
        if ( $aEnqueueItem['translation'] ) {
532
            wp_localize_script( $aEnqueueItem['handle_id'], $aEnqueueItem['handle_id'], $aEnqueueItem['translation'] );
533
        }
534
        
535
    }
536
    
537
    /**
538
     * Takes care of added enqueuing scripts by checking the currently loading page.
539
     * 
540
     * @remark      A callback for the admin_enqueue_scripts hook.
541
     * @since       2.1.2
542
     * @since       2.1.5   Moved from the main class. Changed the name from `enqueueStylesCalback` to `replyToEnqueueStyles()`.
543
     * @since       3.0.0   Changed the name to `_replyToEnqueueStyles()`.
544
     * @since       3.2.0   Changed it unset the enqueued item so that the method can be called multiple times.
545
     * @internal
546
     */    
547
    public function _replyToEnqueueStyles() {        
548
        foreach( $this->oProp->aEnqueuingStyles as $_sKey => $_aEnqueuingStyle ) {
549
            $this->_enqueueSRCByCondition( $_aEnqueuingStyle );
550
            unset( $this->oProp->aEnqueuingStyles[ $_sKey ] );
551
        }
552
    }
553
    
554
    /**
555
     * Takes care of added enqueuing scripts by page slug and tab slug.
556
     * 
557
     * @remark      A callback for the admin_enqueue_scripts hook.
558
     * @since       2.1.2
559
     * @since       2.1.5   Moved from the main class. Changed the name from `enqueueScriptsCallback` to `callbackEnqueueScripts()`.
560
     * @since       3.0.0   Changed the name to `_replyToEnqueueScripts()`.
561
     * @since       3.2.0   Changed it unset the enqueued item so that the method can be called multiple times.
562
     * @internal
563
     */
564
    public function _replyToEnqueueScripts() {     
565
        foreach( $this->oProp->aEnqueuingScripts as $_sKey => $_aEnqueuingScript ) {
566
            $this->_enqueueSRCByCondition( $_aEnqueuingScript );     
567
            unset( $this->oProp->aEnqueuingScripts[ $_sKey ] );
568
        }
569
    }
570
    
571
}
572