Completed
Pull Request — 2.x (#4180)
by Scott Kingsley
04:50
created

PodsComponents::toggle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 17
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', '', array( 'back_link' => true ) );
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
	    } else {
587
		    $this->deactivate_component( $component );
588
		    $toggle = false;
589
	    }
590
591
	    return $toggle;
592
593
    }
594
595
    /**
596
     * Add pods specific capabilities.
597
     *
598
     * @param $capabilities List of extra capabilities to add
599
     *
600
     * @return array
601
     */
602
    public function admin_capabilities ( $capabilities ) {
603
        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...
604
            if ( !empty( $component_data[ 'Hide' ] ) )
605
                continue;
606
607
            if ( true === (boolean) pods_var( 'DeveloperMode', $component_data, false ) && !pods_developer() )
608
                continue;
609
610
            if ( true === (boolean) pods_var( 'TablelessMode', $component_data, false ) && !pods_developer() )
611
                continue;
612
613
            if ( empty( $component_data[ 'MenuPage' ] ) && ( !isset( $component_data[ 'object' ] ) || !method_exists( $component_data[ 'object' ], 'admin' ) ) )
614
                continue;
615
616
            $capability = 'pods_component_' . str_replace( '-', '_', sanitize_title( str_replace( ' and ', ' ', strip_tags( $component_data[ 'Name' ] ) ) ) );
617
618
            if ( 0 < strlen ( $component_data[ 'Capability' ] ) )
619
                $capability = $component_data[ 'Capability' ];
620
621
            if ( !in_array( $capability, $capabilities ) )
622
                $capabilities[] = $capability;
623
        }
624
625
        return $capabilities;
626
    }
627
628
    /**
629
     * Handle admin ajax
630
     *
631
     * @since 2.0
632
     */
633
    public function admin_ajax () {
634
        if ( false === headers_sent() ) {
635
			pods_session_start();
636
637
            header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) );
638
        }
639
640
        // Sanitize input
641
        $params = pods_unslash( (array) $_POST );
642
643 View Code Duplication
        foreach ( $params as $key => $value ) {
644
            if ( 'action' == $key )
645
                continue;
646
647
            unset( $params[ $key ] );
648
649
            $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
650
        }
651
652
        $params = (object) $params;
653
654
        $component = $params->component;
655
        $method = $params->method;
656
657
        if ( !isset( $component ) || !isset( $this->components[ $component ] ) || !isset( $this->settings[ 'components' ][ $component ] ) )
658
            pods_error( 'Invalid AJAX request', $this );
659
660
        if ( !isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, 'pods-component-' . $component . '-' . $method ) )
661
            pods_error( 'Unauthorized request', $this );
662
663
        // Cleaning up $params
664
        unset( $params->action );
665
        unset( $params->component );
666
        unset( $params->method );
667
        unset( $params->_wpnonce );
668
669
        $params = (object) apply_filters( 'pods_component_ajax_' . $component . '_' . $method, $params, $component, $method );
670
671
        $output = false;
672
673
        // Component init
674 View Code Duplication
        if ( isset( $this->components[ $component ][ 'object' ] ) && method_exists( $this->components[ $component ][ 'object' ], 'init' ) )
675
            $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...
676
677
        // Handle internal methods
678
        if ( isset( $this->components[ $component ][ 'object' ] ) && !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) && method_exists( $this, 'admin_ajax_' . $method ) )
679
            $output = call_user_func( array( $this, 'admin_ajax_' . $method ), $component, $params );
680
        // Make sure method exists
681
        elseif ( !isset( $this->components[ $component ][ 'object' ] ) || !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) )
682
            pods_error( 'API method does not exist', $this );
683
        // Dynamically call the component method
684
        else
685
            $output = call_user_func( array( $this->components[ $component ][ 'object' ], 'ajax_' . $method ), $params );
686
687
        if ( !is_bool( $output ) )
688
            echo $output;
689
690
        die(); // KBAI!
691
    }
692
693
    public function admin_ajax_settings ( $component, $params ) {
694
        if ( !isset( $this->components[ $component ] ) )
695
            wp_die( 'Invalid Component', '', array( 'back_link' => true ) );
696
        elseif ( !method_exists( $this->components[ $component ][ 'object' ], 'options' ) )
697
            pods_error( 'Component options method does not exist', $this );
698
699
        $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...
700
701
        if ( empty( $this->settings[ 'components' ][ $component ] ) )
702
            $this->settings[ 'components' ][ $component ] = array();
703
704
        foreach ( $options as $field_name => $field_option ) {
705
            $field_option = PodsForm::field_setup( $field_option, null, $field_option[ 'type' ] );
706
707
            if ( !is_array( $field_option[ 'group' ] ) ) {
708
                $field_value = pods_var_raw( 'pods_setting_' . $field_name, $params );
709
710
                $this->settings[ 'components' ][ $component ][ $field_name ] = $field_value;
711
            }
712
            else {
713
                foreach ( $field_option[ 'group' ] as $field_group_name => $field_group_option ) {
714
                    $field_value = pods_var_raw( 'pods_setting_' . $field_group_name, $params );
715
716
                    $this->settings[ 'components' ][ $component ][ $field_group_name ] = $field_value;
717
                }
718
            }
719
        }
720
721
        $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...
722
723
        update_option( 'pods_component_settings', $settings );
724
725
        return '1';
726
    }
727
}
728