PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.3
WP-Stateless – Google Cloud Storage v3.0.3
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / vendor / udx / lib-wp-bootstrap / lib / classes / class-bootstrap.php

class-bootstrap.php in WP-Stateless – Google Cloud Storage 3.0.3, at vendor/udx/lib-wp-bootstrap/lib/classes/class-bootstrap.php

629 lines 21.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Bootstrap
4 *
5 * @namespace UsabilityDynamics
6 *
7 * This file is being used to bootstrap WordPress theme.
8 */
9 namespace UsabilityDynamics\WP {
10
11 if( !class_exists( 'UsabilityDynamics\WP\Bootstrap' ) ) {
12
13 /**
14 * Bootstrap the theme in WordPress.
15 *
16 * @class Bootstrap
17 * @author: peshkov@UD
18 */
19 class Bootstrap extends Scaffold {
20
21 /**
22 * Schemas
23 *
24 * @public
25 * @property schema
26 * @var array
27 */
28 public $schema = null;
29
30 /**
31 * Absolute path to schema ( composer.json )
32 *
33 * @public
34 * @property schema_path
35 * @var array
36 */
37 public $schema_path = null;
38
39 /**
40 * Admin Notices handler object
41 *
42 * @public
43 * @property errors
44 * @var object UsabilityDynamics\WP\Errors object
45 */
46 public $errors = false;
47
48 /**
49 * Settings
50 *
51 * @public
52 * @static
53 * @property $settings
54 * @type \UsabilityDynamics\Settings object
55 */
56 public $settings = null;
57
58 /**
59 * Path to main plugin/theme file
60 *
61 * @public
62 * @property boot_file
63 * @var array
64 */
65 public $boot_file = false;
66
67 /**
68 * Constructor
69 * Attention: MUST NOT BE CALLED DIRECTLY! USE get_instance() INSTEAD!
70 *
71 * @author peshkov@UD
72 */
73 protected function __construct( $args ) {
74 parent::__construct( $args );
75 //** Define our Admin Notices handler object */
76 $this->errors = new Errors( array_merge( $args, array(
77 'type' => $this->type
78 ) ) );
79 //** Determine if Composer autoloader is included and modules classes are up to date */
80 $this->composer_dependencies();
81 //** Determine if plugin/theme requires or recommends another plugin(s) */
82 $this->plugins_dependencies();
83 // Maybe run install or upgrade processes.
84 $this->maybe_run_upgrade_process();
85 //** Set install/upgrade pages if needed */
86 $this->define_splash_pages();
87 //** Maybe need to show UD splash page. Used static functions intentionaly. */
88 if ( !has_action( 'admin_init', array( Dashboard::get_instance(), 'maybe_ud_splash_page' ) ) ) {
89 add_action( 'admin_init', array( Dashboard::get_instance(), 'maybe_ud_splash_page' ) );
90 }
91 if ( !has_action( 'admin_menu', array( Dashboard::get_instance(), 'add_ud_splash_page') ) ) {
92 add_action( 'admin_menu', array( Dashboard::get_instance(), 'add_ud_splash_page') );
93 }
94 add_action( 'wp_ajax_ud_bootstrap_dismiss_notice', array( $this, 'ud_bootstrap_dismiss_notice' ) );
95 }
96
97 /**
98 * Initialize application.
99 * Redeclare the method in final class!
100 *
101 * @author peshkov@UD
102 */
103 public function init() {}
104
105 /**
106 * Determine if errors exist
107 * Just wrapper.
108 */
109 public function has_errors() {
110 return $this->errors->has_errors();
111 }
112
113 /**
114 * @param string $key
115 * @param mixed $value
116 *
117 * @author peshkov@UD
118 * @return \UsabilityDynamics\Settings
119 */
120 public function set( $key = null, $value = null ) {
121 if( !is_object( $this->settings ) || !is_callable( array( $this->settings, 'set' ) ) ) {
122 return false;
123 }
124 return $this->settings->set( $key, $value );
125 }
126
127 /**
128 * @param string $key
129 * @param mixed $default
130 *
131 * @author peshkov@UD
132 * @return \UsabilityDynamics\type
133 */
134 public function get( $key = null, $default = null ) {
135 if( !is_object( $this->settings ) || !is_callable( array( $this->settings, 'get' ) ) ) {
136 return $default;
137 }
138 return $this->settings->get( $key, $default );
139 }
140
141 /**
142 * Returns specific schema from composer.json file.
143 *
144 * @param string $file Path to file
145 * @author peshkov@UD
146 * @return mixed array or false
147 */
148 public function get_schema( $key = '' ) {
149 if( $this->schema === null ) {
150 if( !empty( $this->schema_path ) && file_exists( $this->schema_path ) ) {
151 $this->schema = (array)\UsabilityDynamics\Utility::l10n_localize( json_decode( file_get_contents( $this->schema_path ), true ), (array)$this->get_localization() );
152 }
153 }
154 //** Break if composer.json does not exist */
155 if( !is_array( $this->schema ) ) {
156 return false;
157 }
158 //** Resolve dot-notated key. */
159 if( strpos( $key, '.' ) ) {
160 $current = $this->schema;
161 $p = strtok( $key, '.' );
162 while( $p !== false ) {
163 if( !isset( $current[ $p ] ) ) {
164 return false;
165 }
166 $current = $current[ $p ];
167 $p = strtok( '.' );
168 }
169 return $current;
170 }
171 //** Get default key */
172 else {
173 return isset( $this->schema[ $key ] ) ? $this->schema[ $key ] : false;
174 }
175 }
176
177 /**
178 * Return localization's list.
179 *
180 * Example:
181 * If schema contains l10n.{key} values:
182 *
183 * { 'config': 'l10n.hello_world' }
184 *
185 * the current function should return something below:
186 *
187 * return array(
188 * 'hello_world' => __( 'Hello World', $this->domain ),
189 * );
190 *
191 * @author peshkov@UD
192 * @return array
193 */
194 public function get_localization() {
195 return array();
196 }
197
198 /**
199 * Determine if product is just installed or upgraded
200 * and run install/upgrade processes
201 *
202 * @author peshkov@UD
203 */
204 protected function maybe_run_upgrade_process() {
205 //** Determine what to show depending on version installed */
206 $version = get_option($this->slug . '-current-version', 0);
207 $this->old_version = $version;
208 //** Just installed */
209 if (!$version) {
210 /* Run Install handlers */
211 add_action( 'plugins_loaded', array( $this, '_run_install_process' ), 0 );
212 }
213 //** Upgraded */
214 elseif (version_compare($version, $this->args['version']) == -1) {
215 /* Run Upgrade handlers */
216 add_action( 'plugins_loaded', array( $this, '_run_upgrade_process' ), 0 );
217 }
218 // Need to save current version on plugins_loaded action,
219 // unless _run_install_process and _run_upgrade_process not get called.
220 add_action( 'plugins_loaded', array( $this, 'save_version_no' ), 100 );
221 }
222
223 /**
224 * Saving version no to database.
225 *
226 */
227 public function save_version_no($value=''){
228 update_option( $this->slug . '-current-version', $this->args['version'] );
229 }
230
231 /**
232 * Installation Handler
233 * Internal method. Use run_install_process() instead
234 */
235 public function _run_install_process() {
236 /* Delete 'Install/Upgrade' notice 'dismissed' information */
237 delete_option( sanitize_key( 'dismiss_' . $this->slug . '_' . str_replace( '.', '_', $this->args['version'] ) . '_notice' ) );
238 /* Delete 'Bootstrap' notice 'dismissed' information */
239 delete_option( 'dismissed_notice_' . sanitize_key( $this->name ) );
240 $this->run_install_process();
241 }
242
243 /**
244 * Upgrade Handler
245 * Internal method. Use run_upgrade_process() instead
246 */
247 public function _run_upgrade_process() {
248 /* Delete 'Install/Upgrade' notice 'dismissed' information */
249 delete_option( sanitize_key( 'dismiss_' . $this->slug . '_' . str_replace( '.', '_', $this->args['version'] ) . '_notice' ) );
250 /* Delete 'Bootstrap' notice 'dismissed' information */
251 delete_option( 'dismissed_notice_' . sanitize_key( $this->name ) );
252 $this->run_upgrade_process();
253 }
254
255 /**
256 * Run Install Process.
257 *
258 * Re-define the function in child.
259 */
260 public function run_install_process() {}
261
262 /**
263 * Run Upgrade Process.
264 *
265 * Re-define the function in child.
266 */
267 public function run_upgrade_process() {}
268
269 /**
270 * Define splash pages for plugins if needed
271 * And Renders Admin Notice about installed product
272 *
273 * @return boolean
274 * @author korotkov@UD
275 * @author peshkov@UD
276 */
277 public function define_splash_pages() {
278 //** If not defined in schemas or not determined - skip */
279 if ( !$splashes = $this->get_schema( 'extra.splashes' ) ) {
280 return false;
281 }
282
283 foreach( (array)$splashes as $splash => $shortpath ) {
284 $path = $this->type == 'theme' ? get_template_directory() . '/' . ltrim( $shortpath, '/\\' ) : $this->path( $shortpath, 'dir' );
285 if( !file_exists( $path ) ) {
286 unset( $splashes[ $splash ] );
287 }
288 }
289
290 //** If no splash templates files or missed 'install' splash - skip */
291 if( empty( $splashes ) || !isset( $splashes[ 'install' ] ) ) {
292 return false;
293 }
294
295 $page = false;
296
297 //** Determine what to show depending on version installed */
298 $version = get_option( $this->slug . '-splash-version', 0 );
299
300 //** Just installed */
301 if( !$version ) {
302 $page = 'install';
303 }
304 //** Upgraded */
305 elseif ( version_compare( $version, $this->args['version'] ) == -1 ) {
306 if( isset( $splashes[ 'upgrade' ] ) ) {
307 $page = 'upgrade';
308 } else {
309 $page = 'install';
310 }
311 }
312 //** In other case do not do this */
313 else {
314
315 /**
316 * Maybe Render Install Notice
317 * about current instance
318 */
319
320 $option = sanitize_key( 'dismiss_' . $this->slug . '_' . str_replace( '.', '_', $this->args['version'] ) . '_notice' );
321
322 if(
323 isset( $_REQUEST[ 'page' ] ) &&
324 $_REQUEST[ 'page' ] == Dashboard::get_instance()->page_slug &&
325 isset( $_REQUEST[ 'slug' ] ) &&
326 $_REQUEST[ 'slug' ] == $this->slug
327 ) {
328
329 /** Dismiss Admin Notice */
330 if( isset( $_REQUEST[ 'dismiss' ] ) ) {
331
332 update_option( $option, array(
333 'slug' => $this->slug,
334 'type' => $this->type,
335 'version' => $this->args['version']
336 ) );
337
338 if( !function_exists( 'wp_redirect' ) ) {
339 require_once( ABSPATH . 'wp-includes/pluggable.php' );
340 }
341
342 if( !empty( $_SERVER[ 'HTTP_REFERER' ] ) ) {
343 wp_redirect( $_SERVER[ 'HTTP_REFERER' ] );
344 } else {
345 wp_redirect( admin_url( 'plugins.php' ) );
346 }
347 exit;
348
349 }
350
351 /** Add information about product to Dashboard page */
352 else {
353
354 if( isset( $splashes[ 'upgrade' ] ) ) {
355 $page = 'upgrade';
356 } else {
357 $page = 'install';
358 }
359
360 }
361
362 }
363
364 if( !get_option( $option ) ) {
365 add_action( 'admin_notices', array( $this, 'render_upgrade_notice' ), 1 );
366 }
367
368 if( empty( $page ) ) {
369 return false;
370 }
371
372 }
373
374 $content = $this->root_path . ltrim( $splashes[$page], '/\\' );
375
376 //** Abort if no files exist */
377 if ( !file_exists( $content ) ) {
378 return false;
379 }
380
381 //** Push data to temp transient */
382 $_current_pages_to_show = get_transient( Dashboard::get_instance()->transient_key );
383
384 //** If empty - create */
385 if ( !$_current_pages_to_show ) {
386 set_transient( Dashboard::get_instance()->transient_key, array(
387 $this->slug => array(
388 'name' => $this->name,
389 'content' => $content,
390 'version' => $this->args['version']
391 )
392 ), 30 );
393 }
394 //** If not empty - update */
395 else {
396 $_current_pages_to_show[$this->slug] = array(
397 'name' => $this->name,
398 'content' => $content,
399 'version' => $this->args['version']
400 );
401 set_transient( Dashboard::get_instance()->transient_key, $_current_pages_to_show, 30 );
402 }
403
404 set_transient( Dashboard::get_instance()->need_splash_key, Dashboard::get_instance()->transient_key, 30 );
405
406 }
407
408 /**
409 * Renders Upgrade Notice.
410 *
411 */
412 public function render_upgrade_notice() {
413
414 if( $this->type == 'theme' ) {
415 if( !current_user_can( 'switch_themes' ) ) {
416 return;
417 }
418 $icon = file_exists( get_template_directory() . '/static/images/icon.png' ) ? get_template_directory_uri() . '/static/images/icon.png' : false;
419 } else {
420 if( !current_user_can( 'activate_plugins' ) ) {
421 return;
422 }
423 $icon = file_exists( $this->path( 'static/images/icon.png', 'dir' ) ) ? $this->path( 'static/images/icon.png', 'url' ) : false;
424 }
425
426 ob_start();
427 $vars = apply_filters( 'ud::bootstrap::upgrade_notice::vars', array(
428 'content' => false,
429 'icon' => $icon,
430 'name' => $this->name,
431 'type' => $this->type,
432 'slug' => $this->slug,
433 'version' => $this->args['version'],
434 'dashboard_link' => admin_url( 'index.php?page='. Dashboard::get_instance()->page_slug . '&slug=' . $this->slug ),
435 'dismiss_link' => admin_url( 'index.php?page='. Dashboard::get_instance()->page_slug . '&slug=' . $this->slug . '&dismiss=1' ),
436 'home_link' => !empty( $this->schema[ 'homepage' ] ) ? $this->schema[ 'homepage' ] : false,
437 ) );
438 extract( $vars );
439 $content = ob_get_clean();
440 echo apply_filters( 'ud::bootstrap::upgrade_notice::template', $content, $this->slug, $vars );
441 }
442
443 /**
444 * Check plugins requirements
445 *
446 * @author peshkov@UD
447 */
448 public function check_plugins_requirements() {
449 //** Determine if we have TGMA Plugin Activation initialized. */
450 $is_tgma = $this->is_tgma;
451 if( $is_tgma ) {
452 $tgma = TGM_Plugin_Activation::get_instance();
453 //** Maybe get TGMPA notices. */
454 $notices = $tgma->notices( get_class( $this ) );
455 if( !empty( $notices[ 'messages' ] ) && is_array( $notices[ 'messages' ] ) ) {
456 $error_links = false;
457 $message_links = false;
458 foreach( $notices[ 'messages' ] as $m ) {
459 if( $m[ 'type' ] == 'error' ) $error_links = true;
460 elseif( $m[ 'type' ] == 'message' ) $message_links = true;
461 $this->errors->add( $m[ 'value' ], $m[ 'type' ] );
462 }
463 //** Maybe add footer action links to errors and|or notices block. */
464 if( !empty( $notices[ 'links' ] ) && is_array( $notices[ 'links' ] ) ) {
465 foreach( $notices[ 'links' ] as $type => $links ) {
466 foreach( $links as $link ) {
467 $this->errors->add_action_link( $link, $type );
468 }
469 }
470 }
471 }
472 }
473 }
474
475 /**
476 * Maybe determines if Composer autoloader is included and modules classes are up to date
477 *
478 * @author peshkov@UD
479 */
480 private function composer_dependencies() {
481 $dependencies = $this->get_schema( 'extra.schemas.dependencies.modules' );
482 if( !empty( $dependencies ) && is_array( $dependencies ) ) {
483 foreach( $dependencies as $module => $classes ) {
484 if( !empty( $classes ) && is_array( $classes ) ) {
485 foreach( $classes as $class => $v ) {
486 if( !class_exists( $class ) ) {
487 $this->errors->add( sprintf( __( 'Module <b>%s</b> is not installed or the version is old, class <b>%s</b> does not exist.', $this->domain ), $module, $class ) );
488 continue;
489 }
490 if ( '*' != trim( $v ) && ( !property_exists( $class, 'version' ) || $class::$version < $v ) ) {
491 $this->errors->add( sprintf( __( 'Module <b>%s</b> should be updated to the latest version, class <b>%s</b> must have version <b>%s</b> or higher.', $this->domain ), $module, $class, $v ) );
492 }
493 }
494 }
495 }
496 }
497 }
498
499 /**
500 * Determine if plugin/theme requires or recommends another plugin(s)
501 *
502 * @author peshkov@UD
503 */
504 private function plugins_dependencies() {
505 /**
506 * Dependencies must be checked before plugins_loaded hook to prevent issues!
507 *
508 * The current condition fixes incorrect behaviour on custom 'Install Plugins' page
509 * after activation plugin which has own dependencies.
510 *
511 * The condition belongs to WordPress 4.3 and higher.
512 */
513 if( did_action( 'plugins_loaded' ) && $this->type == 'plugin' ) {
514 return;
515 }
516 $plugins = $this->get_schema( 'extra.schemas.dependencies.plugins' );
517 if( !empty( $plugins ) && is_array( $plugins ) ) {
518 $tgma = TGM_Plugin_Activation::get_instance();
519 foreach( $plugins as $plugin ) {
520 $plugin[ '_referrer' ] = get_class( $this );
521 $plugin[ '_referrer_name' ] = $this->name;
522 $tgma->register( $plugin );
523 }
524 $this->is_tgma = true;
525 }
526 }
527
528
529 /**
530 * Defines License Client if 'licenses' schema is set
531 *
532 * @author peshkov@UD
533 */
534 protected function define_license_client() {
535 //** Break if we already have errors to prevent fatal ones. */
536 if( $this->has_errors() ) {
537 return false;
538 }
539 //** Be sure we have licenses scheme to continue */
540 $schema = $this->get_schema( 'extra.schemas.licenses.client' );
541 if( !$schema ) {
542 return false;
543 }
544 //** Licenses Manager */
545 if( !class_exists( '\UsabilityDynamics\UD_API\Bootstrap' ) ) {
546 $this->errors->add( __( 'Class \UsabilityDynamics\UD_API\Bootstrap does not exist. Be sure all required plugins and (or) composer modules installed and activated.', $this->domain ) );
547 return false;
548 }
549 $args = $this->args;
550 $args = array_merge( $args, array(
551 'type' => $this->type,
552 'name' => $this->name,
553 'slug' => $this->slug,
554 'referrer_slug' => $this->slug,
555 'domain' => $this->domain,
556 'errors_callback' => array( $this->errors, 'add' ),
557 ), $schema );
558 if( empty( $args[ 'screen' ] ) ) {
559 $this->errors->add( __( 'Licenses client can not be activated due to invalid \'licenses\' schema.', $this->domain ) );
560 }
561 $this->client = new \UsabilityDynamics\UD_API\Bootstrap( $args );
562 }
563
564 /**
565 * Defines License Manager if 'license' schema is set
566 *
567 * @author peshkov@UD
568 */
569 public function define_license_manager() {
570 //** Break if we already have errors to prevent fatal ones. */
571 if( $this->has_errors() ) {
572 return false;
573 }
574 //** Be sure we have license scheme to continue */
575 $schema = $this->get_schema( 'extra.schemas.licenses.product' );
576 if( !$schema ) {
577 return false;
578 }
579 if( empty( $schema[ 'product_id' ] ) || ( empty( $schema[ 'referrer' ] ) && $this->type !== 'theme' ) ) {
580 $this->errors->add( __( 'Product requires license, but product ID and (or) referrer is undefined. Please, be sure, that license schema has all required data.', $this->domain ), 'message' );
581 }
582 $schema = array_merge( (array)$schema, array(
583 'type' => $this->type,
584 'name' => $this->name,
585 'boot_file' => $this->boot_file,
586 'errors_callback' => array( $this->errors, 'add' )
587 ) );
588 //** Licenses Manager */
589 if( !class_exists( '\UsabilityDynamics\UD_API\Manager' ) ) {
590 //$this->errors->add( __( 'Class \UsabilityDynamics\UD_API\Manager does not exist. Be sure all required plugins installed and activated.', $this->domain ), 'message' );
591 return false;
592 }
593 $this->license_manager = new \UsabilityDynamics\UD_API\Manager( $schema );
594 return true;
595 }
596
597 public function ud_bootstrap_dismiss_notice() {
598 $response = array(
599 'success' => '0',
600 'error' => __( 'There was an error in request.', $this->domain ),
601 );
602 $error = false;
603
604 if( empty( $_POST['key'] ) ||
605 empty( $_POST['slug'] ) ||
606 empty( $_POST['type'] ) ||
607 empty( $_POST['version'] )
608 ) {
609 $response['error'] = __( 'Invalid values', $this->domain );
610 $error = true;
611 }
612
613 if ( ! $error && update_option( ( $_POST['key'] ), array(
614 'slug' => $_POST['slug'],
615 'type' => $_POST['type'],
616 'version' => $_POST['version'],
617 ) ) ) {
618 $response['success'] = '1';
619 }
620
621 wp_send_json( $response );
622 }
623
624 }
625
626 }
627
628 }
629