Completed
Pull Request — 2.x (#3397)
by Scott Kingsley
06:40
created

PodsComponents::toggle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Component managing class
4
 *
5
 * @package Pods
6
 */
7
class PodsComponents {
8
9
    /**
10
     * @var PodsComponents
11
     */
12
    static $instance = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $instance.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
13
14
    /**
15
     * Root of Components directory
16
     *
17
     * @var string
18
     *
19
     * @private
20
     * @since 2.0
21
     */
22
    private $components_dir = null;
23
24
    /**
25
     * Available components
26
     *
27
     * @var string
28
     *
29
     * @since 2.0
30
     */
31
    public $components = array();
32
33
    /**
34
     * Components settings
35
     *
36
     * @var string
37
     *
38
     * @since 2.0
39
     */
40
    public $settings = array();
41
42
    /**
43
     * Singleton handling for a basic pods_components() request
44
     *
45
     * @return \PodsComponents
46
     *
47
     * @since 2.3.5
48
     */
49
    public static function init () {
50
        if ( !is_object( self::$instance ) )
51
            self::$instance = new PodsComponents();
52
53
        return self::$instance;
54
    }
55
56
    /**
57
     * Setup actions and get options
58
     *
59
     * @return \PodsComponents
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
60
     *
61
     * @since 2.0
62
     */
63
    public function __construct () {
64
        $this->components_dir = realpath( apply_filters( 'pods_components_dir', PODS_DIR . 'components' ) ) . '/';
65
66
        $settings = get_option( 'pods_component_settings', '' );
67
68
        if ( !empty( $settings ) )
69
            $this->settings = (array) json_decode( $settings, true );
70
71
        if ( !isset( $this->settings[ 'components' ] ) )
72
            $this->settings[ 'components' ] = array();
73
74
        // Get components (give it access to theme)
75
        add_action( 'setup_theme', array( $this, 'get_components' ), 11 );
76
77
        // Load in components
78
        add_action( 'setup_theme', array( $this, 'load' ), 12 );
79
80
        // AJAX handling
81
        if ( is_admin() ) {
82
            add_action( 'wp_ajax_pods_admin_components', array( $this, 'admin_ajax' ) );
83
            add_action( 'wp_ajax_nopriv_pods_admin_components', array( $this, 'admin_ajax' ) );
84
85
            // Add the Pods Components capabilities
86
            add_filter( 'members_get_capabilities', array( $this, 'admin_capabilities' ) );
87
        }
88
    }
89
90
    /**
91
     * Add menu item
92
     *
93
     * @param string $parent The parent slug.
94
     *
95
     * @since 2.0
96
     *
97
     * @uses add_submenu_page
98
     */
99
    public function menu ( $parent ) {
100
        global $submenu;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
101
102
        $custom_component_menus = array();
103
104
		$pods_component_menu_items = array();
105
106
        foreach ( $this->components as $component => $component_data ) {
0 ignored issues
show
Bug introduced by
The expression $this->components of type string is not traversable.
Loading history...
107
            $component_data[ 'MustUse' ] = apply_filters( 'pods_component_require_' . $component_data[ 'ID' ], $component_data[ 'MustUse' ], $component_data );
108
109 View Code Duplication
            if ( empty( $component_data[ 'MustUse' ] ) && ( !isset( $this->settings[ 'components' ][ $component ] ) || 0 == $this->settings[ 'components' ][ $component ] ) )
110
                continue;
111
112
            if ( !empty( $component_data[ 'Hide' ] ) )
113
                continue;
114
115
            if ( !empty( $component_data[ 'DeveloperMode' ] ) && !pods_developer() )
116
                continue;
117
118
            if ( empty( $component_data[ 'TablelessMode' ] ) && pods_tableless() )
119
                continue;
120
121
            if ( empty( $component_data[ 'MenuPage' ] ) ) {
122
                if ( !isset( $component_data[ 'object' ] ) )
123
                    continue;
124
                elseif ( !method_exists( $component_data[ 'object' ], 'admin' ) && !method_exists( $component_data[ 'object' ], 'options' ) )
125
                    continue;
126
            }
127
128 View Code Duplication
            if ( false === $component_data[ 'External' ] )
129
                $component_data[ 'File' ] = realpath( $this->components_dir . $component_data[ 'File' ] );
130
131 View Code Duplication
            if ( !file_exists( $component_data[ 'File' ] ) ) {
132
                pods_message( 'Pods Component not found: ' . $component_data[ 'File' ] );
133
134
                pods_transient_clear( 'pods_components' );
135
136
                continue;
137
            }
138
139
            $capability = 'pods_component_' . str_replace( '-', '_', sanitize_title( $component ) );
140
141
            if ( 0 < strlen( $component_data[ 'Capability' ] ) )
142
                $capability = $component_data[ 'Capability' ];
143
144
            if ( !pods_is_admin( array( 'pods', 'pods_components', $capability ) ) )
145
                continue;
146
147
            $menu_page = 'pods-component-' . $component;
148
149
            if ( !empty( $component_data[ 'MenuPage' ] ) )
150
                $custom_component_menus[ $menu_page ] = $component_data;
151
152
			$pods_component_menu_items[ $component_data[ 'MenuName' ] ] = array(
153
				'menu_page' => $menu_page,
154
				'page_title' => $component_data[ 'Name' ],
155
				'capability' => 'read',
156
				'callback' => array( $this, 'admin_handler' )
157
			);
158
159
            if ( isset( $component_data[ 'object' ] ) && method_exists( $component_data[ 'object' ], 'admin_assets' ) ) {
160
				$pods_component_menu_items[ $component_data[ 'MenuName' ] ][ 'assets' ] = array( $component_data[ 'object' ], 'admin_assets' );
161
			}
162
        }
163
164
		/**
165
		 * Add or change the items in the Pods Components Submenu.
166
		 *
167
		 * Can also be used to change which menu components is a submenu of or change title of menu.
168
		 *
169
		 * @params array $pods_component_menu_items {
170
		 *          An array of arguments for add_submenu_page
171
		 *
172
		 *		  	@param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
173
		 *		  	@param string $page_title The text to be displayed in the title tags of the page when the menu is selected
174
		 *		  	@param $menu_title The text to be used for the menu
175
		 *		  	@param $capability The capability required for this menu to be displayed to the user.
176
		 *		  	@param $menu_slug The slug name to refer to this menu by (should be unique for this menu)
177
		 *		  	@param $function The function to be called to output the content for this page.
178
		 * }
179
		 *
180
		 * @returns array Array of submenu pages to be passed to add_submenu_page()
181
		 *
182
		 * @since 2.4.1
183
		 */
184
		$pods_component_menu_items = apply_filters( 'pods_admin_components_menu', $pods_component_menu_items );
185
186
		ksort( $pods_component_menu_items );
187
188
		foreach ( $pods_component_menu_items as $menu_title => $menu_data ) {
189
			if ( !is_callable( $menu_data[ 'callback' ] ) ) {
190
				continue;
191
			}
192
193
            $page = add_submenu_page(
194
                $parent,
195
                strip_tags( $menu_data[ 'page_title' ] ),
196
                '- ' . strip_tags( $menu_title ),
197
				pods_v( 'capability', $menu_data, 'read', true ),
198
                $menu_data[ 'menu_page' ],
199
                $menu_data[ 'callback' ]
200
            );
201
202
			if ( isset( $menu_data[ 'assets' ] ) && is_callable( $menu_data[ 'assets' ] ) ) {
203
                add_action( 'admin_print_styles-' . $page, $menu_data[ 'assets' ] );
204
			}
205
		}
206
207
        if ( !empty( $custom_component_menus ) ) {
208
            foreach ( $custom_component_menus as $menu_page => $component_data ) {
209
                if ( isset( $submenu[ $parent ] ) ) {
210
                    foreach ( $submenu[ $parent ] as $sub => &$menu ) {
211
                        if ( $menu[ 2 ] == $menu_page ) {
212
                            $menu_page = $component_data[ 'MenuPage' ];
213
214
                            /*if ( !empty( $component_data[ 'MenuAddPage' ] ) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
215
                                if ( false !== strpos( $_SERVER[ 'REQUEST_URI' ], $component_data[ 'MenuAddPage' ] ) )
216
                                    $menu_page = $component_data[ 'MenuAddPage' ];
217
                            }*/
218
219
                            $menu[ 2 ] = $menu_page;
220
221
                            $page = current( explode( '?', $menu[ 2 ] ) );
222
223
                            if ( isset( $component_data[ 'object' ] ) && method_exists( $component_data[ 'object' ], 'admin_assets' ) )
224
                                add_action( 'admin_print_styles-' . $page, array( $component_data[ 'object' ], 'admin_assets' ) );
225
226
                            break;
227
                        }
228
                    }
229
                }
230
            }
231
        }
232
    }
233
234
    /**
235
     * Load activated components and init component
236
     *
237
     * @since 2.0
238
     */
239
    public function load () {
240
        do_action( 'pods_components_load' );
241
242
        foreach ( (array) $this->components as $component => $component_data ) {
243
            $component_data[ 'MustUse' ] = apply_filters( 'pods_component_require_' . $component_data[ 'ID' ], $component_data[ 'MustUse' ], $component_data );
244
245 View Code Duplication
            if ( false === $component_data[ 'MustUse' ] && ( !isset( $this->settings[ 'components' ][ $component ] ) || 0 == $this->settings[ 'components' ][ $component ] ) )
246
                continue;
247
248
            if ( !empty( $component_data[ 'PluginDependency' ] ) ) {
249
                $dependency = explode( '|', $component_data[ 'PluginDependency' ] );
250
251
                if ( !pods_is_plugin_active( $dependency[ 1 ] ) )
252
                    continue;
253
            }
254
255
            if ( !empty( $component_data[ 'ThemeDependency' ] ) ) {
256
                $dependency = explode( '|', $component_data[ 'ThemeDependency' ] );
257
258
                if ( strtolower( $dependency[ 1 ] ) != strtolower( get_template() ) && strtolower( $dependency[ 1 ] ) != strtolower( get_stylesheet() ) )
259
                    continue;
260
            }
261
262 View Code Duplication
            if ( false === $component_data[ 'External' ] )
263
                $component_data[ 'File' ] = realpath( $this->components_dir . $component_data[ 'File' ] );
264
265
            if ( empty( $component_data[ 'File' ] ) ) {
266
                pods_transient_clear( 'pods_components' );
267
268
                continue;
269
            }
270
271 View Code Duplication
            if ( !file_exists( $component_data[ 'File' ] ) ) {
272
                pods_message( 'Pods Component not found: ' . $component_data[ 'File' ] );
273
274
                pods_transient_clear( 'pods_components' );
275
276
                continue;
277
            }
278
279
            include_once $component_data[ 'File' ];
280
281
            if ( ( !empty( $component_data[ 'Class' ] ) && class_exists( $component_data[ 'Class' ] ) ) || isset( $component_data[ 'object' ] ) ) {
282
                if ( !isset( $this->components[ $component ][ 'object' ] ) )
283
                    $this->components[ $component ][ 'object' ] = new $component_data[ 'Class' ];
284
285
                if ( method_exists( $this->components[ $component ][ 'object' ], 'options' ) ) {
286
                    if ( isset( $this->settings[ 'components' ][ $component ] ) )
287
                        $this->components[ $component ][ 'options' ] = $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] );
0 ignored issues
show
Bug introduced by
The method options cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
288
                    else
289
                        $this->components[ $component ][ 'options' ] = $this->components[ $component ][ 'object' ]->options( array() );
0 ignored issues
show
Bug introduced by
The method options cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
290
291
                    $this->options( $component, $this->components[ $component ][ 'options' ] );
292
                }
293
                else
294
                    $this->options( $component, array() );
295
296 View Code Duplication
                if ( method_exists( $this->components[ $component ][ 'object' ], 'handler' ) )
297
                    $this->components[ $component ][ 'object' ]->handler( $this->settings[ 'components' ][ $component ] );
0 ignored issues
show
Bug introduced by
The method handler cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
298
            }
299
        }
300
    }
301
302
    /**
303
     * Get list of components available
304
     *
305
     * @since 2.0
306
     */
307
    public function get_components () {
308
        $components = pods_transient_get( 'pods_components' );
309
310 View Code Duplication
        if ( 1 == pods_var( 'pods_debug_components', 'get', 0 ) && pods_is_admin( array( 'pods' ) ) )
311
            $components = array();
312
313
        if ( PodsInit::$version != PODS_VERSION || !is_array( $components ) || empty( $components ) || ( is_admin() && isset( $_GET[ 'page' ] ) && 'pods-components' == $_GET[ 'page' ] && 1 !== pods_transient_get( 'pods_components_refresh' ) ) ) {
0 ignored issues
show
Bug introduced by
The property version cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
314
            do_action( 'pods_components_get' );
315
316
            $component_dir = @opendir( untrailingslashit( $this->components_dir ) );
317
            $component_files = array();
318
319
            if ( false !== $component_dir ) {
320
                while ( false !== ( $file = readdir( $component_dir ) ) ) {
321
                    if ( '.' == substr( $file, 0, 1 ) )
322
                        continue;
323
                    elseif ( is_dir( $this->components_dir . $file ) ) {
324
                        $component_subdir = @opendir( $this->components_dir . $file );
325
326
                        if ( $component_subdir ) {
327
                            while ( false !== ( $subfile = readdir( $component_subdir ) ) ) {
328
                                if ( '.' == substr( $subfile, 0, 1 ) )
329
                                    continue;
330
                                elseif ( '.php' == substr( $subfile, -4 ) )
331
                                    $component_files[] = str_replace( '\\', '/', $file . '/' . $subfile );
332
                            }
333
334
                            closedir( $component_subdir );
335
                        }
336
                    }
337
                    elseif ( '.php' == substr( $file, -4 ) )
338
                        $component_files[] = $file;
339
                }
340
341
                closedir( $component_dir );
342
            }
343
344
            $default_headers = array(
345
                'ID' => 'ID',
346
                'Name' => 'Name',
347
                'ShortName' => 'Short Name',
348
                'PluginName' => 'Plugin Name',
349
                'ComponentName' => 'Component Name',
350
                'URI' => 'URI',
351
                'MenuName' => 'Menu Name',
352
                'MenuPage' => 'Menu Page',
353
                'MenuAddPage' => 'Menu Add Page',
354
                'MustUse' => 'Must Use',
355
                'Description' => 'Description',
356
                'Version' => 'Version',
357
                'Category' => 'Category',
358
                'Author' => 'Author',
359
                'AuthorURI' => 'Author URI',
360
                'Class' => 'Class',
361
                'Hide' => 'Hide',
362
                'PluginDependency' => 'Plugin Dependency',
363
                'ThemeDependency' => 'Theme Dependency',
364
                'DeveloperMode' => 'Developer Mode',
365
                'TablelessMode' => 'Tableless Mode',
366
                'Capability' => 'Capability',
367
                'Plugin' => 'Plugin'
368
            );
369
370
            $component_files = apply_filters( 'pods_components_register', $component_files );
371
372
            $components = array();
373
374
            foreach ( $component_files as $component_file ) {
375
                $external = false;
376
377
                if ( is_array( $component_file ) && isset( $component_file[ 'File' ] ) ) {
378
                    $component = $component_file = $component_file[ 'File' ];
379
380
                    $external = true;
381
                }
382
                else
383
                    $component = $this->components_dir . $component_file;
384
385
                if ( !is_readable( $component ) )
386
                    continue;
387
388
                $component_data = get_file_data( $component, $default_headers, 'pods_component' );
389
390
                if ( ( empty( $component_data[ 'Name' ] ) && empty( $component_data[ 'ComponentName' ] ) && empty( $component_data[ 'PluginName' ] ) ) || 'yes' == $component_data[ 'Hide' ] )
391
                    continue;
392
393
                if ( isset( $component_data[ 'Plugin' ] ) && pods_is_plugin_active( $component_data[ 'Plugin' ] ) )
394
                    continue;
395
396
                if ( empty( $component_data[ 'Name' ] ) ) {
397
                    if ( !empty( $component_data[ 'ComponentName' ] ) )
398
                        $component_data[ 'Name' ] = $component_data[ 'ComponentName' ];
399
                    elseif ( !empty( $component_data[ 'PluginName' ] ) )
400
                        $component_data[ 'Name' ] = $component_data[ 'PluginName' ];
401
                }
402
403
                if ( empty( $component_data[ 'ShortName' ] ) )
404
                    $component_data[ 'ShortName' ] = $component_data[ 'Name' ];
405
406
                if ( empty( $component_data[ 'MenuName' ] ) )
407
                    $component_data[ 'MenuName' ] = $component_data[ 'Name' ];
408
409
                if ( empty( $component_data[ 'Class' ] ) )
410
                    $component_data[ 'Class' ] = 'Pods_' . pods_js_name( basename( $component, '.php' ), false );
411
412
                if ( empty( $component_data[ 'ID' ] ) )
413
                    $component_data[ 'ID' ] = $component_data[ 'Name' ];
414
415
                $component_data[ 'ID' ] = sanitize_title( $component_data[ 'ID' ] );
416
417 View Code Duplication
                if ( 'on' == strtolower( $component_data[ 'DeveloperMode' ] ) || 1 == $component_data[ 'DeveloperMode' ] )
418
                    $component_data[ 'DeveloperMode' ] = true;
419
                else
420
                    $component_data[ 'DeveloperMode' ] = false;
421
422 View Code Duplication
                if ( 'on' == strtolower( $component_data[ 'TablelessMode' ] ) || 1 == $component_data[ 'TablelessMode' ] )
423
                    $component_data[ 'TablelessMode' ] = true;
424
                else
425
                    $component_data[ 'TablelessMode' ] = false;
426
427
                $component_data[ 'External' ] = (boolean) $external;
428
429
                if ( 'on' == strtolower($component_data[ 'MustUse' ] ) || '1' == $component_data[ 'MustUse' ] )
430
                    $component_data[ 'MustUse' ] = true;
431
                elseif ( 'off' == strtolower($component_data[ 'MustUse' ] ) || '0' == $component_data[ 'MustUse' ] )
432
                    $component_data[ 'MustUse' ] = false;
433
                else
434
                    $component_data[ 'MustUse' ] = $component_data[ 'External' ];
435
436
                $component_data[ 'File' ] = $component_file;
437
438
                $components[ $component_data[ 'ID' ] ] = $component_data;
439
            }
440
441
            ksort( $components );
442
443
            pods_transient_set( 'pods_components_refresh', 1, ( 60 * 60 * 12 ) );
444
445
            pods_transient_set( 'pods_components', $components );
446
        }
447
448 View Code Duplication
        if ( 1 == pods_var( 'pods_debug_components', 'get', 0 ) && pods_is_admin( array( 'pods' ) ) )
449
            pods_debug( $components );
450
451
        $this->components = $components;
452
453
        return $this->components;
454
    }
455
456
    /**
457
     * Set component options
458
     *
459
     * @param $component
460
     * @param $options
461
     *
462
     * @since 2.0
463
     */
464
    public function options ( $component, $options ) {
465
        if ( !isset( $this->settings[ 'components' ][ $component ] ) || !is_array( $this->settings[ 'components' ][ $component ] ) )
466
            $this->settings[ 'components' ][ $component ] = array();
467
468
        foreach ( $options as $option => $data ) {
469
            if ( !isset( $this->settings[ 'components' ][ $component ][ $option ] ) && isset( $data[ 'default' ] ) )
470
                $this->settings[ 'components' ][ $component ][ $option ] = $data[ 'default' ];
471
        }
472
    }
473
474
    /**
475
     * Call component specific admin functions
476
     *
477
     * @since 2.0
478
     */
479
    public function admin_handler () {
480
        $component = str_replace( 'pods-component-', '', $_GET[ 'page' ] );
481
482
        if ( isset( $this->components[ $component ] ) && isset( $this->components[ $component ][ 'object' ] ) && is_object( $this->components[ $component ][ 'object' ] ) ) {
483
            // Component init
484 View Code Duplication
            if ( method_exists( $this->components[ $component ][ 'object' ], 'init' ) )
485
                $this->components[ $component ][ 'object' ]->init( $this->settings[ 'components' ][ $component ], $component );
0 ignored issues
show
Bug introduced by
The method init cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
486
487
            // Component Admin handler
488
            if ( method_exists( $this->components[ $component ][ 'object' ], 'admin' ) )
489
                $this->components[ $component ][ 'object' ]->admin( $this->settings[ 'components' ][ $component ], $component );
0 ignored issues
show
Bug introduced by
The method admin cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
490
            // Built-in Admin Handler
491 View Code Duplication
            elseif ( method_exists( $this->components[ $component ][ 'object' ], 'options' ) )
492
                $this->admin( $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] ), $this->settings[ 'components' ][ $component ], $component );
0 ignored issues
show
Bug introduced by
The method options cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
493
        }
494
    }
495
496
    public function admin ( $options, $settings, $component ) {
497
        if ( !isset( $this->components[ $component ] ) )
498
            wp_die( 'Invalid Component' );
499
500
        $component_label = $this->components[ $component ][ 'Name' ];
501
502
        include PODS_DIR . 'ui/admin/components-admin.php';
503
    }
504
505
    /**
506
     * Check if a component is active or not
507
     *
508
     * @param string $component The component name to check if active
509
     *
510
     * @return bool
511
     *
512
     * @since 2.7
513
     */
514
    public function is_component_active( $component ) {
515
516
        $active = false;
517
518
        if ( isset( $this->components[ $component ] ) && isset( $this->settings[ 'components' ][ $component ] ) && 0 !== $this->settings[ 'components' ][ $component ] ) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of 0 (integer) and $this->settings['components'][$component] (string) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
519
            $active = true;
520
        }
521
522
        return $active;
523
524
    }
525
526
    /**
527
     * Activate a component
528
     *
529
     * @param string $component The component name to activate
530
     *
531
     * @since 2.7
532
     */
533 View Code Duplication
    public function activate_component( $component ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
534
535
        if ( ! $this->is_component_active( $component ) ) {
536
            if ( isset( $this->components[ $component ] ) ) {
537
                $this->settings[ 'components' ][ $component ] = array();
538
539
                $settings = version_compare( PHP_VERSION, '5.4.0', '>=' ) ? json_encode( $this->settings, JSON_UNESCAPED_UNICODE ) : json_encode( $this->settings );
0 ignored issues
show
Unused Code introduced by
The call to json_encode() has too many arguments starting with JSON_UNESCAPED_UNICODE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
540
541
                update_option( 'pods_component_settings', $settings );
542
            }
543
        }
544
545
    }
546
547
    /**
548
     * Deactivate a component
549
     *
550
     * @param string $component The component name to deactivate
551
     *
552
     * @since 2.7
553
     */
554 View Code Duplication
    public function deactivate_component( $component ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
555
556
        if ( $this->is_component_active( $component ) ) {
557
            if ( isset( $this->components[ $component ] ) ) {
558
                $this->settings[ 'components' ][ $component ] = 0;
559
560
                $settings = version_compare( PHP_VERSION, '5.4.0', '>=' ) ? json_encode( $this->settings, JSON_UNESCAPED_UNICODE ) : json_encode( $this->settings );
0 ignored issues
show
Unused Code introduced by
The call to json_encode() has too many arguments starting with JSON_UNESCAPED_UNICODE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
561
562
                update_option( 'pods_component_settings', $settings );
563
            }
564
        }
565
566
    }
567
568
    /**
569
     * Toggle a component on or off
570
     *
571
     * @param string $component The component name to toggle
572
     *
573
     * @return bool
574
     *
575
     * @since 2.0
576
     */
577
    public function toggle( $component ) {
578
579
        $toggle = null;
580
581
        $toggle_mode = (int) pods_v( 'toggle', 'get' );
582
583
        if ( 1 == $toggle_mode ) {
584
            $this->activate_component( $component );
585
            $toggle = true;
586
        }
587
        else {
588
            $this->deactivate_component( $component );
589
            $toggle = false;
590
        }
591
592
        return $toggle;
593
594
    }
595
596
    /**
597
     * Add pods specific capabilities.
598
     *
599
     * @param $capabilities List of extra capabilities to add
600
     *
601
     * @return array
602
     */
603
    public function admin_capabilities ( $capabilities ) {
604
        foreach ( $this->components as $component => $component_data ) {
0 ignored issues
show
Bug introduced by
The expression $this->components of type string is not traversable.
Loading history...
605
            if ( !empty( $component_data[ 'Hide' ] ) )
606
                continue;
607
608
            if ( true === (boolean) pods_var( 'DeveloperMode', $component_data, false ) && !pods_developer() )
609
                continue;
610
611
            if ( true === (boolean) pods_var( 'TablelessMode', $component_data, false ) && !pods_developer() )
612
                continue;
613
614
            if ( empty( $component_data[ 'MenuPage' ] ) && ( !isset( $component_data[ 'object' ] ) || !method_exists( $component_data[ 'object' ], 'admin' ) ) )
615
                continue;
616
617
            $capability = 'pods_component_' . str_replace( '-', '_', sanitize_title( str_replace( ' and ', ' ', strip_tags( $component_data[ 'Name' ] ) ) ) );
618
619
            if ( 0 < strlen ( $component_data[ 'Capability' ] ) )
620
                $capability = $component_data[ 'Capability' ];
621
622
            if ( !in_array( $capability, $capabilities ) )
623
                $capabilities[] = $capability;
624
        }
625
626
        return $capabilities;
627
    }
628
629
    /**
630
     * Handle admin ajax
631
     *
632
     * @since 2.0
633
     */
634
    public function admin_ajax () {
635
        if ( false === headers_sent() ) {
636
			pods_session_start();
637
638
            header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) );
639
        }
640
641
        // Sanitize input
642
        $params = pods_unslash( (array) $_POST );
643
644 View Code Duplication
        foreach ( $params as $key => $value ) {
645
            if ( 'action' == $key )
646
                continue;
647
648
            unset( $params[ $key ] );
649
650
            $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
651
        }
652
653
        $params = (object) $params;
654
655
        $component = $params->component;
656
        $method = $params->method;
657
658
        if ( !isset( $component ) || !isset( $this->components[ $component ] ) || !isset( $this->settings[ 'components' ][ $component ] ) )
659
            pods_error( 'Invalid AJAX request', $this );
660
661
        if ( !isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, 'pods-component-' . $component . '-' . $method ) )
662
            pods_error( 'Unauthorized request', $this );
663
664
        // Cleaning up $params
665
        unset( $params->action );
666
        unset( $params->component );
667
        unset( $params->method );
668
        unset( $params->_wpnonce );
669
670
        $params = (object) apply_filters( 'pods_component_ajax_' . $component . '_' . $method, $params, $component, $method );
671
672
        $output = false;
673
674
        // Component init
675 View Code Duplication
        if ( isset( $this->components[ $component ][ 'object' ] ) && method_exists( $this->components[ $component ][ 'object' ], 'init' ) )
676
            $this->components[ $component ][ 'object' ]->init( $this->settings[ 'components' ][ $component ], $component );
0 ignored issues
show
Bug introduced by
The method init cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
677
678
        // Handle internal methods
679
        if ( isset( $this->components[ $component ][ 'object' ] ) && !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) && method_exists( $this, 'admin_ajax_' . $method ) )
680
            $output = call_user_func( array( $this, 'admin_ajax_' . $method ), $component, $params );
681
        // Make sure method exists
682 View Code Duplication
        elseif ( !isset( $this->components[ $component ][ 'object' ] ) || !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) )
683
            pods_error( 'API method does not exist', $this );
684
        // Dynamically call the component method
685
        else
686
            $output = call_user_func( array( $this->components[ $component ][ 'object' ], 'ajax_' . $method ), $params );
687
688
        if ( !is_bool( $output ) )
689
            echo $output;
690
691
        die(); // KBAI!
0 ignored issues
show
Coding Style Compatibility introduced by
The method admin_ajax() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
692
    }
693
694
    public function admin_ajax_settings ( $component, $params ) {
695 View Code Duplication
        if ( !isset( $this->components[ $component ] ) )
696
            wp_die( 'Invalid Component' );
697
        elseif ( !method_exists( $this->components[ $component ][ 'object' ], 'options' ) )
698
            pods_error( 'Component options method does not exist', $this );
699
700
        $options = $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] );
0 ignored issues
show
Bug introduced by
The method options cannot be called on $this->components[$component]['object'] (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
701
702
        if ( empty( $this->settings[ 'components' ][ $component ] ) )
703
            $this->settings[ 'components' ][ $component ] = array();
704
705
        foreach ( $options as $field_name => $field_option ) {
706
            $field_option = PodsForm::field_setup( $field_option, null, $field_option[ 'type' ] );
707
708
            if ( !is_array( $field_option[ 'group' ] ) ) {
709
                $field_value = pods_var_raw( 'pods_setting_' . $field_name, $params );
710
711
                $this->settings[ 'components' ][ $component ][ $field_name ] = $field_value;
712
            }
713
            else {
714
                foreach ( $field_option[ 'group' ] as $field_group_name => $field_group_option ) {
715
                    $field_value = pods_var_raw( 'pods_setting_' . $field_group_name, $params );
716
717
                    $this->settings[ 'components' ][ $component ][ $field_group_name ] = $field_value;
718
                }
719
            }
720
        }
721
722
        $settings = version_compare( PHP_VERSION, '5.4.0', '>=' ) ? json_encode( $this->settings, JSON_UNESCAPED_UNICODE ) : json_encode( $this->settings );
0 ignored issues
show
Unused Code introduced by
The call to json_encode() has too many arguments starting with JSON_UNESCAPED_UNICODE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
723
724
        update_option( 'pods_component_settings', $settings );
725
726
        return '1';
727
    }
728
}
729