PluginProbe ʕ •ᴥ•ʔ
Redux Framework / 4.4.12
Redux Framework v4.4.12
trunk 4.3.0 4.3.1 4.3.10 4.3.11 4.3.12 4.3.13 4.3.14 4.3.15 4.3.16 4.3.17 4.3.18 4.3.19 4.3.2 4.3.20 4.3.21 4.3.22 4.3.24 4.3.25 4.3.26 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.13 4.4.14 4.4.15 4.4.16 4.4.17 4.4.18 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.6 4.5.7 4.5.8 4.5.9
redux-framework / class-redux-framework-plugin.php
redux-framework Last commit date
ReduxCore 2 years ago redux-core 2 years ago redux-templates 2 years ago sample 2 years ago class-redux-framework-plugin.php 2 years ago index.php 4 years ago license.txt 4 years ago readme.txt 2 years ago redux-framework.php 2 years ago uninstall.php 4 years ago wpml-config.xml 4 years ago
class-redux-framework-plugin.php
449 lines
1 <?php
2 /**
3 * Redux_Framework_Plugin main class
4 *
5 * @package Redux Framework
6 * @since 3.0.0
7 */
8
9 // Exit if accessed directly.
10 defined( 'ABSPATH' ) || exit;
11
12 if ( ! class_exists( 'Redux_Framework_Plugin', false ) ) {
13
14 /**
15 * Main Redux_Framework_Plugin class
16 *
17 * @since 3.0.0
18 */
19 class Redux_Framework_Plugin {
20
21 /**
22 * Option array for demo mode.
23 *
24 * @access protected
25 * @var array $options Array of config options, used to check for demo mode
26 * @since 3.0.0
27 */
28 protected $options = array();
29
30 /**
31 * Use this value as the text domain when translating strings from this plugin. It should match
32 * the Text Domain field set in the plugin header, as well as the directory name of the plugin.
33 * Additionally, text domains should only contain letters, number and hyphens, not underscores
34 * or spaces.
35 *
36 * @access protected
37 * @var string $plugin_slug The unique ID (slug) of this plugin
38 * @since 3.0.0
39 */
40 protected $plugin_slug = 'redux-framework';
41
42 /**
43 * Set on network activate.
44 *
45 * @access protected
46 * @var string $plugin_network_activated Check for plugin network activation
47 * @since 3.0.0
48 */
49 protected $plugin_network_activated = null;
50
51 /**
52 * Class instance.
53 *
54 * @access private
55 * @var Redux_Framework_Plugin $instance The one true Redux_Framework_Plugin
56 * @since 3.0.0
57 */
58 private static $instance;
59
60 /**
61 * Crash flag.
62 *
63 * @access private
64 * @var Redux_Framework_Plugin $crash Crash flag if inside a crash.
65 * @since 4.1.15
66 */
67 public static $crash = false;
68
69 /**
70 * Get active instance
71 *
72 * @access public
73 * @since 3.1.3
74 * @return self::$instance The one true Redux_Framework_Plugin
75 */
76 public static function instance(): ?Redux_Framework_Plugin {
77 $path = REDUX_PLUGIN_FILE;
78 $res = false;
79
80 if ( function_exists( 'get_plugin_data' ) && file_exists( $path ) ) {
81 $data = get_plugin_data( $path );
82
83 if ( isset( $data['Version'] ) && '' !== $data['Version'] ) {
84 $res = version_compare( $data['Version'], '4', '<' );
85 }
86
87 if ( is_plugin_active( 'redux-framework/redux-framework.php' ) && true === $res ) {
88 echo '<div class="error"><p>' . esc_html__( 'Redux Framework version 4 is activated but not loaded. Redux Framework version 3 is still installed and activated. Please deactivate Redux Framework version 3.', 'redux-framework' ) . '</p></div>'; // phpcs:ignore WordPress.Security.EscapeOutput
89 return null;
90 }
91 }
92
93 if ( ! self::$instance ) {
94 self::$instance = new self();
95 if ( class_exists( 'ReduxFramework' ) ) {
96 self::$instance->load_first();
97 } else {
98 self::$instance->get_redux_options();
99 self::$instance->includes();
100 self::$instance->hooks();
101 }
102 }
103
104 return self::$instance;
105 }
106
107 /**
108 * Shim for getting instance
109 *
110 * @access public
111 * @since 4.0.1
112 * @return self::$instance The one true Redux_Framework_Plugin
113 */
114 public static function get_instance(): ?Redux_Framework_Plugin {
115 return self::instance();
116 }
117
118 /**
119 * Get Redux options
120 *
121 * @access public
122 * @since 3.1.3
123 * @return void
124 */
125 public function get_redux_options() {
126
127 // Setup defaults.
128 $defaults = array(
129 'demo' => false,
130 );
131
132 // If multisite is enabled.
133 if ( is_multisite() ) {
134
135 // Get network activated plugins.
136 $plugins = get_site_option( 'active_sitewide_plugins' );
137
138 foreach ( $plugins as $file => $plugin ) {
139 if ( strpos( $file, 'redux-framework.php' ) !== false ) {
140 $this->plugin_network_activated = true;
141 $this->options = get_site_option( 'ReduxFrameworkPlugin', $defaults );
142 }
143 }
144 }
145
146 // If options aren't set, grab them now!
147 if ( empty( $this->options ) ) {
148 $this->options = get_option( 'ReduxFrameworkPlugin', $defaults );
149 }
150 }
151
152 /**
153 * Include necessary files
154 *
155 * @access public
156 * @since 3.1.3
157 * @return void
158 */
159 public function includes() {
160
161 // Include Redux_Core.
162 if ( file_exists( __DIR__ . '/redux-core/framework.php' ) ) {
163 require_once __DIR__ . '/redux-core/framework.php';
164 }
165
166 if ( file_exists( __DIR__ . '/redux-templates/redux-templates.php' ) ) {
167 require_once __DIR__ . '/redux-templates/redux-templates.php';
168 }
169
170 if ( isset( Redux_Core::$as_plugin ) ) {
171 Redux_Core::$as_plugin = true;
172 }
173
174 add_action( 'setup_theme', array( $this, 'load_sample_config' ) );
175 }
176
177 /**
178 * Loads the sample config after everything is loaded.
179 *
180 * @access public
181 * @since 4.0.2
182 * @return void
183 */
184 public function load_sample_config() {
185 // Include demo config, if demo mode is active.
186 if ( $this->options['demo'] && file_exists( __DIR__ . '/sample/sample-config.php' ) ) {
187 require_once __DIR__ . '/sample/sample-config.php';
188 }
189 }
190
191 /**
192 * Run action and filter hooks
193 *
194 * @access private
195 * @since 3.1.3
196 * @return void
197 */
198 private function hooks() {
199 add_action( 'activated_plugin', array( $this, 'load_first' ) );
200 add_action( 'wp_loaded', array( $this, 'options_toggle_check' ) );
201
202 // Activate plugin when a new blog is added.
203 add_action( 'wpmu_new_blog', array( $this, 'activate_new_site' ) );
204
205 // Display admin notices.
206 add_action( 'admin_notices', array( $this, 'admin_notices' ) );
207
208 // Edit plugin metalinks.
209 add_filter( 'plugin_row_meta', array( $this, 'plugin_metalinks' ), null, 2 );
210 add_filter( 'network_admin_plugin_action_links', array( $this, 'add_settings_link' ), 1, 2 );
211 add_filter( 'plugin_action_links', array( $this, 'add_settings_link' ), 1, 2 );
212
213 // phpcs:ignore WordPress.NamingConventions.ValidHookName
214 do_action( 'redux/plugin/hooks', $this );
215 }
216
217 /**
218 * Pushes Redux to the top of plugin load list, so it initializes before any plugin that may use it.
219 */
220 public function load_first() {
221 if ( ! class_exists( 'Redux_Functions_Ex' ) ) {
222 require_once __DIR__ . '/redux-core/inc/classes/class-redux-functions-ex.php';
223 }
224
225 $plugin_dir = Redux_Functions_Ex::wp_normalize_path( WP_PLUGIN_DIR ) . '/';
226 $self_file = Redux_Functions_Ex::wp_normalize_path( __FILE__ );
227
228 $path = str_replace( $plugin_dir, '', $self_file );
229 $path = str_replace( 'class-redux-framework-plugin.php', 'redux-framework.php', $path );
230
231 $plugins = get_option( 'active_plugins' );
232
233 if ( $plugins ) {
234 $key = array_search( $path, $plugins, true );
235
236 if ( false !== $key ) {
237 array_splice( $plugins, $key, 1 );
238 array_unshift( $plugins, $path );
239 update_option( 'active_plugins', $plugins );
240 }
241 }
242 }
243
244 /**
245 * Fired on plugin activation
246 *
247 * @access public
248 * @return void
249 * @since 3.0.0
250 */
251 public static function activate() {
252 delete_site_transient( 'update_plugins' );
253 }
254
255 /**
256 * Fired when plugin is deactivated
257 *
258 * @access public
259 * @since 3.0.0
260 *
261 * @param boolean $network_wide True if plugin is network activated, false otherwise.
262 *
263 * @return void
264 */
265 public static function deactivate( ?bool $network_wide ) {
266 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
267 if ( $network_wide ) {
268 // Get all blog IDs.
269 $blog_ids = self::get_blog_ids();
270
271 foreach ( $blog_ids as $blog_id ) {
272 switch_to_blog( $blog_id );
273 self::single_deactivate();
274 }
275 restore_current_blog();
276 } else {
277 self::single_deactivate();
278 }
279 } else {
280 self::single_deactivate();
281 }
282
283 delete_option( 'ReduxFrameworkPlugin' );
284 }
285
286 /**
287 * Fired when a new WPMU site is activated
288 *
289 * @access public
290 *
291 * @param int $blog_id The ID of the new blog.
292 *
293 * @return void
294 * @since 3.0.0
295 */
296 public function activate_new_site( int $blog_id ) {
297 if ( 1 !== did_action( 'wpmu_new_blog' ) ) {
298 return;
299 }
300
301 switch_to_blog( $blog_id );
302 self::single_activate();
303 restore_current_blog();
304 }
305
306 /**
307 * Get all IDs of blogs that are not activated, not spam, and not deleted
308 *
309 * @access private
310 * @since 3.0.0
311 * @global object $wpdb
312 * @return array|false Array of IDs or false if none are found
313 */
314 private static function get_blog_ids() {
315 global $wpdb;
316
317 $var = '0';
318
319 // Get an array of IDs (We have to do it this way because WordPress says so, however redundant).
320 $result = wp_cache_get( 'redux-blog-ids' );
321 if ( false === $result ) {
322
323 // WordPress says get_col is discouraged? I found no alternative. So...ignore! - kp.
324 // phpcs:ignore WordPress.DB.DirectDatabaseQuery
325 $result = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE archived = %s AND spam = %s AND deleted = %s", $var, $var, $var ) );
326
327 wp_cache_set( 'redux-blog-ids', $result );
328 }
329
330 return $result;
331 }
332
333 /**
334 * Fired for each WPMS blog on plugin activation
335 *
336 * @access private
337 * @since 3.0.0
338 * @return void
339 */
340 private static function single_activate() {
341 $nonce = wp_create_nonce( 'redux_framework_demo' );
342
343 $notices = get_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', array() );
344 $notices[] = esc_html__( 'Redux Framework has an embedded demo.', 'redux-framework' ) . ' <a href="./plugins.php?redux-framework-plugin=demo&nonce=' . $nonce . '">' . esc_html__( 'Click here to activate the sample config file.', 'redux-framework' ) . '</a>';
345
346 update_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', $notices );
347 }
348
349 /**
350 * Display admin notices
351 *
352 * @access public
353 * @since 3.0.0
354 * @return void
355 */
356 public function admin_notices() {
357 do_action( 'redux_framework_plugin_admin_notice' );
358 $notices = get_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', '' );
359 if ( ! empty( $notices ) ) {
360 foreach ( $notices as $notice ) {
361 echo '<div class="updated notice is-dismissible"><p>' . $notice . '</p></div>'; // phpcs:ignore WordPress.Security.EscapeOutput
362 }
363
364 delete_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES' );
365 }
366 }
367
368 /**
369 * Fired for each blog when the plugin is deactivated
370 *
371 * @access private
372 * @since 3.0.0
373 * @return void
374 */
375 private static function single_deactivate() {
376 delete_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES' );
377 }
378
379 /**
380 * Turn on or off
381 *
382 * @access public
383 * @since 3.0.0
384 * @return void
385 */
386 public function options_toggle_check() {
387 if ( isset( $_GET['nonce'] ) && wp_verify_nonce( sanitize_key( $_GET['nonce'] ), 'redux_framework_demo' ) ) {
388 if ( isset( $_GET['redux-framework-plugin'] ) && 'demo' === $_GET['redux-framework-plugin'] ) {
389 $url = admin_url( add_query_arg( array( 'page' => 'redux-framework' ), 'options-general.php' ) );
390
391 if ( false === $this->options['demo'] ) {
392 $this->options['demo'] = true;
393 $url = admin_url( add_query_arg( array( 'page' => 'redux_demo' ), 'admin.php' ) );
394 } else {
395 $this->options['demo'] = false;
396 }
397
398 if ( is_multisite() && $this->plugin_network_activated ) {
399 update_site_option( 'ReduxFrameworkPlugin', $this->options );
400 } else {
401 update_option( 'ReduxFrameworkPlugin', $this->options );
402 }
403
404 wp_safe_redirect( esc_url( $url ) );
405
406 exit();
407 }
408 }
409 }
410
411
412 /**
413 * Add a settings link to the Redux entry in the plugin overview screen
414 *
415 * @param array $links Links array.
416 * @param string $file Plugin filename/slug.
417 *
418 * @return array
419 * @see filter:plugin_action_links
420 * @since 1.0
421 */
422 public function add_settings_link( array $links, string $file ): array {
423 return $links;
424 }
425
426 /**
427 * Edit plugin metalinks
428 *
429 * @access public
430 *
431 * @param array $links The current array of links.
432 * @param string $file A specific plugin row.
433 *
434 * @return array The modified array of links
435 * @since 3.0.0
436 */
437 public function plugin_metalinks( array $links, string $file ): array {
438 if ( strpos( $file, 'redux-framework.php' ) !== false && is_plugin_active( $file ) ) {
439 $links[] = '<a href="' . esc_url( admin_url( add_query_arg( array( 'page' => 'redux-framework' ), 'options-general.php' ) ) ) . '">' . esc_html__( 'What is this?', 'redux-framework' ) . '</a>';
440 }
441
442 return $links;
443 }
444 }
445 if ( ! class_exists( 'ReduxFrameworkPlugin' ) ) {
446 class_alias( 'Redux_Framework_Plugin', 'ReduxFrameworkPlugin' );
447 }
448 }
449