PluginProbe
WPSSO Core – Complete Schema Markup and Meta Tags / 22.7.0
WPSSO Core – Complete Schema Markup and Meta Tags v22.7.0
22.7.0 22.6.1 22.6.0 22.5.3 22.5.2 22.5.1 22.4.0 22.3.0 22.2.1 22.2.0 22.1.3 22.1.2 22.1.1 22.1.0 22.0.0 21.13.3 21.13.2 trunk 21.13.1
← All changes | wpsso.php +881 -0 22.5.222.7.0 View file →
@@ -1,0 +1,881 @@
1 +<?php
2 +/*
3 + * Plugin Name: WPSSO Core
4 + * Plugin Slug: wpsso
5 + * Text Domain: wpsso
6 + * Domain Path: /languages
7 + * Plugin URI: https://wpsso.com/extend/plugins/wpsso/
8 + * Assets URI: https://surniaulula.github.io/wpsso/assets/
9 + * Author: JS Morisset
10 + * Author URI: https://wpsso.com/
11 + * License: GPLv3
12 + * License URI: https://www.gnu.org/licenses/gpl.txt
13 + * Description: Present your content at its best for social sites and search results, no matter how URLs are shared, reshared, messaged, posted, embedded, or crawled.
14 + * Requires PHP: 7.4.33
15 + * Requires At Least: 6.0
16 + * Tested Up To: 7.1
17 + * WC Tested Up To: 11.1.0
18 + * Version: 22.7.0
19 + *
20 + * Version Numbering: {major}.{minor}.{bugfix}[-{stage}.{level}]
21 + *
22 + * {major} Major structural code changes and/or incompatible API changes (ie. breaking changes).
23 + * {minor} New functionality was added or improved in a backwards-compatible manner.
24 + * {bugfix} Backwards-compatible bug fixes or small improvements.
25 + * {stage}.{level} Pre-production release: dev < a (alpha) < b (beta) < rc (release candidate).
26 + *
27 + * Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
28 + */
29 +
30 +if ( ! defined( 'ABSPATH' ) ) {
31 +
32 + die( 'These aren\'t the droids you\'re looking for.' );
33 +}
34 +
35 +if ( ! class_exists( 'Wpsso' ) ) {
36 +
37 + class Wpsso {
38 +
39 + /*
40 + * Library class object variables.
41 + */
42 + public $admin; // WpssoAdmin (admin menus and settings page loader) class object.
43 + public $cache; // SucomCache (object and file caching) class object.
44 + public $check; // WpssoCheck class object.
45 + public $comment; // WpssoComment class object (extends WpssoAbstractWpMeta).
46 + public $conflict; // WpssoConflict (admin plugin conflict checks) class object.
47 + public $debug; // SucomDebug or SucomNoDebug class object.
48 + public $edit; // WpssoEdit class object.
49 + public $head; // WpssoHead class object.
50 + public $loader; // WpssoLoader class object.
51 + public $media; // WpssoMedia (images, videos, etc.) class object.
52 + public $msgs; // WpssoMessages (admin tooltip messages) class object.
53 + public $notice; // SucomNotice or SucomNoNotice class object.
54 + public $opt; // WpssoOptions class object.
55 + public $page; // WpssoPage (page title, desc, etc.) class object.
56 + public $post; // WpssoPost class object (extends WpssoAbstractWpMeta).
57 + public $reg; // WpssoRegister class object.
58 + public $script; // WpssoScript (admin jquery tooltips) class object.
59 + public $style; // WpssoStyle (admin styles) class object.
60 + public $term; // WpssoTerm class object (extends WpssoAbstractWpMeta).
61 + public $user; // WpssoUser class object (extends WpssoAbstractWpMeta).
62 + public $util; // WpssoUtil (extends SucomUtil) class object.
63 +
64 + /*
65 + * Library class object variables for meta tags and markup.
66 + */
67 + public $link_rel; // WpssoLinkRel class object.
68 + public $meta_name; // WpssoMetaName class object.
69 + public $oembed; // WpssoOembed class object.
70 + public $og; // WpssoOpenGraph class object.
71 + public $pinterest; // WpssoPinterest class object.
72 + public $schema; // WpssoSchema class object.
73 + public $tc; // WpssoTwitterCard class object.
74 +
75 + /*
76 + * Reference variables (config, options, modules, etc.).
77 + */
78 + public $id = 'wpsso'; // Plugin id.
79 + public $cf = array(); // Config array from WpssoConfig::get_config().
80 + public $avail = array(); // Third-party plugin checks.
81 + public $options = array(); // Blog options array.
82 + public $site_options = array(); // Multisite options array.
83 + public $sc = array(); // Loaded shortcode objects.
84 +
85 + private static $instance = null; // Wpsso class object.
86 +
87 + /*
88 + * Wpsso constructor.
89 + */
90 + public function __construct() {
91 +
92 + $plugin_file = __FILE__;
93 + $plugin_dir = trailingslashit( dirname( $plugin_file ) );
94 +
95 + require_once $plugin_dir . 'lib/config.php';
96 +
97 + $this->cf = WpssoConfig::get_config();
98 +
99 + WpssoConfig::set_constants( $plugin_file );
100 +
101 + WpssoConfig::require_libs( $plugin_file ); // Includes the register.php class library.
102 +
103 + $this->reg = new WpssoRegister( $this ); // Activate, deactivate, uninstall hooks.
104 +
105 + /*
106 + * The WordPress 'init' action fires after WordPress has finished loading, but before any headers are sent.
107 + *
108 + * Most of WordPress is loaded at this stage, and the user is authenticated. WordPress continues to load on
109 + * the 'init' hook (e.g. widgets), and many plugins instantiate themselves on it for all sorts of reasons
110 + * (e.g. they need a user, a taxonomy, etc.).
111 + */
112 + add_action( 'init', array( $this, 'set_config' ), WPSSO_INIT_CONFIG_PRIORITY ); // Runs at init -10.
113 + add_action( 'widgets_init', array( $this, 'register_widgets' ), 10 ); // Runs at init 1.
114 + add_action( 'init', array( $this, 'set_options' ), WPSSO_INIT_OPTIONS_PRIORITY ); // Runs at init 9.
115 + add_action( 'init', array( $this, 'set_objects' ), WPSSO_INIT_OBJECTS_PRIORITY ); // Runs at init 10.
116 + add_action( 'init', array( $this, 'init_shortcodes' ), WPSSO_INIT_SHORTCODES_PRIORITY ); // Runs at init 11.
117 + add_action( 'init', array( $this, 'init_plugin' ), WPSSO_INIT_PLUGIN_PRIORITY ); // Runs at init 12.
118 +
119 + /*
120 + * The 'wpsso_init_textdomain' action is run after the $check, $avail, and $debug properties have been instantiated.
121 + */
122 + add_action( 'wpsso_init_textdomain', array( $this, 'init_textdomain' ), -1000, 0 );
123 +
124 + /*
125 + * The 'change_locale' action also runs the 'wpsso_init_textdomain' action.
126 + */
127 + add_action( 'change_locale', array( $this, 'change_locale' ), -1000, 1 );
128 +
129 + /*
130 + * If the "Use Plugin MO Translations" option is enabled, returns the file path to the plugin or add-on mo file.
131 + */
132 + add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_mofile' ), 10, 3 );
133 +
134 + /*
135 + * Declare compatibility with WooCommerce features.
136 + */
137 + if ( ! empty( $this->cf[ 'plugin' ][ 'wpsso' ][ 'wc_compat' ] ) ) {
138 +
139 + $wc_compat = $this->cf[ 'plugin' ][ 'wpsso' ][ 'wc_compat' ];
140 +
141 + add_action( 'before_woocommerce_init', function () use ( $plugin_file, $wc_compat ) {
142 +
143 + if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
144 +
145 + foreach ( $wc_compat as $feature ) {
146 +
147 + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( $feature, $plugin_file, true );
148 + }
149 + }
150 + }, 10, 0 );
151 +
152 + unset( $wc_compat );
153 + }
154 +
155 + unset( $plugin_file, $plugin_dir );
156 +
157 + }
158 +
159 + public static function &get_instance() {
160 +
161 + if ( null === self::$instance ) {
162 +
163 + self::$instance = new self;
164 + }
165 +
166 + return self::$instance;
167 + }
168 +
169 + /*
170 + * Force a refresh of the plugin config.
171 + *
172 + * Runs at init priority -10 and called by WpssoRegister->activate_plugin() as well.
173 + */
174 + public function set_config( $activate = false ) {
175 +
176 + $this->cf = WpssoConfig::get_config( $read_cache = false );
177 + }
178 +
179 + /*
180 + * Runs at init 1.
181 + */
182 + public function register_widgets() {
183 +
184 + /*
185 + * Load lib/widget/* library files.
186 + */
187 + $classnames = $this->get_lib_classnames( 'widget' ); // Always returns an array.
188 +
189 + foreach ( $classnames as $id => $classname ) {
190 +
191 + register_widget( $classname );
192 + }
193 + }
194 +
195 + /*
196 + * Runs at init priority 9.
197 + *
198 + * Called by WpssoRegister->activate_plugin() as well.
199 + */
200 + public function set_options( $activate = false ) {
201 +
202 + if ( $activate && defined( 'WPSSO_RESET_ON_ACTIVATE' ) && WPSSO_RESET_ON_ACTIVATE ) {
203 +
204 + delete_option( WPSSO_OPTIONS_NAME );
205 +
206 + $this->options = false;
207 +
208 + } else $this->options = get_option( WPSSO_OPTIONS_NAME );
209 +
210 + if ( ! is_array( $this->options ) ) {
211 +
212 + /*
213 + * The set_options() action is run before the set_objects() action, where the WpssoOptions class is
214 + * instantiated, so the WpssoOptions->get_defaults() method is not available yet. Load the defaults
215 + * directly from the config array and trigget a defaults reload in set_objects().
216 + */
217 + $this->options = $this->cf[ 'opt' ][ 'defaults' ];
218 +
219 + $this->options[ '__reload_defaults' ] = true;
220 + }
221 +
222 + if ( is_multisite() ) {
223 +
224 + $this->site_options = get_site_option( WPSSO_SITE_OPTIONS_NAME );
225 +
226 + if ( ! is_array( $this->site_options ) ) {
227 +
228 + $this->site_options = $this->cf[ 'opt' ][ 'site_defaults' ];
229 +
230 + $this->site_options[ '__reload_defaults' ] = true;
231 + }
232 +
233 + if ( is_array( $this->options ) && is_array( $this->site_options ) ) {
234 +
235 + $blog_id = get_current_blog_id();
236 +
237 + $defined_constants = get_defined_constants( $categorize = true );
238 +
239 + foreach ( $this->site_options as $key => $val ) {
240 +
241 + if ( false !== strpos( $key, ':use' ) ) {
242 +
243 + continue;
244 +
245 + } elseif ( isset( $this->site_options[ $key . ':use' ] ) ) {
246 +
247 + switch ( $this->site_options[ $key . ':use' ] ) {
248 +
249 + case 'force':
250 +
251 + $this->options[ $key ] = $this->site_options[ $key ];
252 + $this->options[ $key . ':disabled' ] = true;
253 +
254 + break;
255 +
256 + case 'empty': // Blank string, null, false, or 0.
257 +
258 + if ( empty( $this->options[ $key ] ) ) {
259 +
260 + $this->options[ $key ] = $this->site_options[ $key ];
261 + }
262 +
263 + break;
264 + }
265 + }
266 +
267 + $constant_name = 'WPSSO_ID_' . $blog_id . '_OPT_' . strtoupper( $key );
268 +
269 + if ( isset( $defined_constants[ 'user' ][ $constant_name ] ) ) {
270 +
271 + $this->options[ $key ] = $defined_constants[ 'user' ][ $constant_name ];
272 +
273 + $this->options[ $key . ':disabled' ] = true;
274 + }
275 + }
276 + }
277 + }
278 + }
279 +
280 + /*
281 + * Runs at init priority 10.
282 + *
283 + * Called by WpssoRegister->activate_plugin() as well.
284 + */
285 + public function set_objects( $activate = false ) {
286 +
287 + $is_doing = array(
288 + 'admin' => is_admin(),
289 + 'ajax' => SucomUtilWP::doing_ajax(),
290 + 'cron' => SucomUtilWP::doing_cron(),
291 + 'dev' => SucomUtilWP::doing_dev(),
292 + );
293 +
294 + /*
295 + * Check for defined constants (in order):
296 + *
297 + * WPSSO_CRON_DEBUG_LOG
298 + * WPSSO_CRON_DEBUG_HTML
299 + * WPSSO_AJAX_DEBUG_LOG
300 + * WPSSO_AJAX_DEBUG_HTML
301 + * WPSSO_ADMIN_DEBUG_LOG
302 + * WPSSO_ADMIN_DEBUG_HTML
303 + * WPSSO_DEBUG_LOG
304 + * WPSSO_DEBUG_HTML
305 + */
306 + $debug_log = $this->get_const_status( 'DEBUG_LOG', $is_doing );
307 + $debug_html = $this->get_const_status( 'DEBUG_HTML', $is_doing );
308 +
309 + $this->check = new WpssoCheck( $this );
310 +
311 + $this->avail = $this->check->get_avail(); // Uses $this->options for availability checks.
312 +
313 + /*
314 + * Make sure a debug object variable is always available.
315 + */
316 + if ( null === $debug_html ) { // Constant not defined.
317 +
318 + $debug_html = empty( $this->options[ 'plugin_debug_html' ] ) ? false : true;
319 + }
320 +
321 + if ( $debug_log || $debug_html ) {
322 +
323 + require_once WPSSO_PLUGINDIR . 'lib/com/debug.php'; // Only load class when needed.
324 +
325 + $this->debug = new SucomDebug( $this, array(
326 + 'log' => $debug_log,
327 + 'html' => $debug_html,
328 + ) );
329 +
330 + if ( $this->debug->enabled ) {
331 +
332 + global $wp_version;
333 +
334 + $this->debug->log( __METHOD__ . ' init ' . WPSSO_INIT_OBJECTS_PRIORITY );
335 + $this->debug->log( 'debug enabled on ' . gmdate( 'c' ) );
336 + $this->debug->log( 'PHP version ' . phpversion() );
337 + $this->debug->log( 'WP version ' . $wp_version );
338 + $this->debug->log( 'WP home URL ' . get_home_url() );
339 + $this->debug->log( 'WP site URL ' . get_site_url() );
340 + $this->debug->log_arr( 'generator', $this->check->get_ext_gen_list() );
341 + $this->debug->log_arr( 'avail', $this->avail );
342 + }
343 +
344 + } else $this->debug = new SucomNoDebug(); // Class always loaded in WpssoConfig::require_libs().
345 +
346 + if ( $this->debug->enabled ) {
347 +
348 + $this->debug->mark_diff( 'debug class loaded' );
349 + }
350 +
351 + /*
352 + * The 'wpsso_init_textdomain' action is run after the $check, $avail, and $debug properties have been instantiated.
353 + *
354 + * The WordPress 'change_locale' action also runs the 'wpsso_init_textdomain' action.
355 + */
356 + do_action( 'wpsso_init_textdomain' );
357 +
358 + /*
359 + * Make sure a notice object variable is always available.
360 + */
361 + if ( $is_doing[ 'admin' ] || $is_doing[ 'cron' ] ) {
362 +
363 + require_once WPSSO_PLUGINDIR . 'lib/messages.php'; // Only load class when needed.
364 + require_once WPSSO_PLUGINDIR . 'lib/com/notice.php'; // Only load class when needed.
365 +
366 + $this->msgs = new WpssoMessages( $this ); // Admin tooltip messages.
367 + $this->notice = new SucomNotice( $this );
368 +
369 + } else $this->notice = new SucomNoNotice(); // Class always loaded in WpssoConfig::require_libs().
370 +
371 + if ( $this->debug->enabled ) {
372 +
373 + $this->debug->mark_diff( 'notice class loaded' );
374 + }
375 +
376 + $this->cache = new SucomCache( $this );
377 + $this->util = new WpssoUtil( $this ); // Extends SucomUtil.
378 + $this->opt = new WpssoOptions( $this );
379 +
380 + do_action( 'wpsso_init_options' );
381 +
382 + $this->script = new WpssoScript( $this );
383 + $this->style = new WpssoStyle( $this );
384 +
385 + /*
386 + * Note that when running a cron task, admin is false.
387 + */
388 + if ( $is_doing[ 'admin' ] ) {
389 +
390 + require_once WPSSO_PLUGINDIR . 'lib/admin.php'; // Only load class when needed.
391 + require_once WPSSO_PLUGINDIR . 'lib/conflict.php'; // Only load class when needed.
392 + require_once WPSSO_PLUGINDIR . 'lib/edit.php'; // Only load class when needed.
393 + require_once WPSSO_PLUGINDIR . 'lib/com/form.php'; // Only load class when needed.
394 +
395 + $this->admin = new WpssoAdmin( $this ); // Admin menus and settings pages.
396 + $this->conflict = new WpssoConflict( $this ); // Admin plugin conflict checks.
397 + $this->edit = new WpssoEdit( $this ); // Admin editing page metabox.
398 + }
399 +
400 + /*
401 + * Setup media and module classes:
402 + *
403 + * $comment
404 + * $media
405 + * $page
406 + * $post
407 + * $term
408 + * $user
409 + */
410 + $this->comment = new WpssoComment( $this ); // Extends WpssoAbstractWpMeta.
411 + $this->media = new WpssoMedia( $this );
412 + $this->page = new WpssoPage( $this );
413 + $this->post = new WpssoPost( $this ); // Extends WpssoAbstractWpMeta.
414 + $this->term = new WpssoTerm( $this ); // Extends WpssoAbstractWpMeta.
415 + $this->user = new WpssoUser( $this ); // Extends WpssoAbstractWpMeta.
416 +
417 + if ( $this->debug->enabled ) {
418 +
419 + $this->debug->mark_diff( 'media and module classes loaded' );
420 + }
421 +
422 + /*
423 + * Setup classe for meta tags and Schema markup:
424 + *
425 + * $head
426 + * $link_rel
427 + * $meta_name
428 + * $og
429 + * $pinterest
430 + * $schema
431 + * $tc
432 + * $loader
433 + */
434 + $this->head = new WpssoHead( $this );
435 + $this->link_rel = new WpssoLinkRel( $this ); // Link relation tags.
436 + $this->meta_name = new WpssoMetaName( $this ); // Meta name tags.
437 + $this->oembed = new WpssoOembed( $this ); // Oembed response data.
438 + $this->og = new WpssoOpenGraph( $this ); // Open Graph meta tags.
439 + $this->pinterest = new WpssoPinterest( $this ); // Pinterest image markup.
440 + $this->schema = new WpssoSchema( $this ); // Schema json data.
441 + $this->tc = new WpssoTwitterCard( $this ); // X (Twitter) Card meta tags.
442 +
443 + if ( $this->debug->enabled ) {
444 +
445 + $this->debug->mark_diff( 'meta tags and schema classes loaded' );
446 + }
447 +
448 + do_action( 'wpsso_init_objects_preloader' );
449 +
450 + $this->loader = new WpssoLoader( $this ); // Modules loader.
451 +
452 + do_action( 'wpsso_init_objects' );
453 +
454 + if ( $this->debug->enabled ) {
455 +
456 + $this->debug_reminder( $is_doing );
457 +
458 + $this->debug->mark_diff( 'objects defined' );
459 + }
460 + }
461 +
462 + /*
463 + * Runs at init priority 11.
464 + */
465 + public function init_shortcodes() {
466 +
467 + if ( $this->debug->enabled ) {
468 +
469 + $this->debug->mark( 'init shortcodes' ); // Begin timer.
470 + }
471 +
472 + /*
473 + * Load lib/shortcode/* library files.
474 + */
475 + $classnames = $this->get_lib_classnames( 'shortcode' ); // Always returns an array.
476 +
477 + foreach ( $classnames as $id => $classname ) {
478 +
479 + /*
480 + * Note that Wpsso->sc[ 'schema' ] is used by WpssoSscFilters->filter_json_data_graph_element().
481 + */
482 + if ( ! isset( $this->sc[ $id ] ) ) { // Just in case.
483 +
484 + $this->sc[ $id ] = new $classname( $this );
485 +
486 + if ( $this->debug->enabled ) {
487 +
488 + $this->debug->mark_diff( 'added ' . $id . ' shortcode' );
489 + }
490 + }
491 + }
492 +
493 + if ( $this->debug->enabled ) {
494 +
495 + $this->debug->mark( 'init shortcodes' ); // Begin timer.
496 + }
497 + }
498 +
499 + /*
500 + * Runs at init priority 12.
501 + */
502 + public function init_plugin() {
503 +
504 + if ( $this->debug->enabled ) {
505 +
506 + $this->debug_hooks();
507 + }
508 +
509 + /*
510 + * All WPSSO Core objects are instantiated and configured.
511 + *
512 + * See SucomAbstractAddOn->init_plugin_notices().
513 + */
514 + do_action( 'wpsso_init_plugin' );
515 + }
516 +
517 + /*
518 + * The 'wpsso_init_textdomain' action is run after the $check, $avail, and $debug properties are instantiated.
519 + */
520 + public function init_textdomain() {
521 +
522 + load_plugin_textdomain( 'wpsso', false, 'wpsso/languages/' );
523 + }
524 +
525 + /*
526 + * The 'change_locale' action also runs the 'wpsso_init_textdomain' action.
527 + */
528 + public function change_locale( $locale ) {
529 +
530 + do_action( 'wpsso_init_textdomain' );
531 + }
532 +
533 + /*
534 + * If the "Use Plugin MO Translations" option is enabled, returns the file path to the plugin or add-on mo file.
535 + */
536 + public function textdomain_mofile( $wp_mofile, $domain ) {
537 +
538 + if ( empty( $this->options[ 'plugin_load_mofiles' ] ) ) { // Nothing to do.
539 +
540 + return $wp_mofile;
541 + }
542 +
543 + if ( 0 === strpos( $domain, 'wpsso' ) ) { // Optimize.
544 +
545 + foreach ( $this->cf[ 'plugin' ] as $ext => $info ) {
546 +
547 + if ( empty( $info[ 'slug' ] ) ) { // Just in case.
548 +
549 + continue;
550 +
551 + } elseif ( $domain === $info[ 'slug' ] ) {
552 +
553 + $languages_mofile = 'languages/' . basename( $wp_mofile );
554 +
555 + if ( $plugin_mofile = WpssoConfig::get_ext_file_path( $ext, $languages_mofile ) ) {
556 +
557 + global $l10n;
558 +
559 + unset( $l10n[ $domain ] ); // Prevent merging.
560 +
561 + return $plugin_mofile;
562 + }
563 +
564 + break; // Stop here.
565 + }
566 + }
567 + }
568 +
569 + return $wp_mofile;
570 + }
571 +
572 + /*
573 + * Check for defined constants (in order):
574 + *
575 + * WPSSO_CRON_DEBUG_LOG
576 + * WPSSO_CRON_DEBUG_HTML
577 + * WPSSO_AJAX_DEBUG_LOG
578 + * WPSSO_AJAX_DEBUG_HTML
579 + * WPSSO_ADMIN_DEBUG_LOG
580 + * WPSSO_ADMIN_DEBUG_HTML
581 + * WPSSO_DEBUG_LOG
582 + * WPSSO_DEBUG_HTML
583 + *
584 + * See Wpsso->get_const_status().
585 + * See Wpsso->get_const_status_transl().
586 + */
587 + public function get_const( $const_suffix, $is_doing = null ) {
588 +
589 + if ( ! is_array( $is_doing ) ) {
590 +
591 + $is_doing = array(
592 + 'admin' => is_admin(),
593 + 'ajax' => SucomUtilWP::doing_ajax(),
594 + 'cron' => SucomUtilWP::doing_cron(),
595 + 'dev' => SucomUtilWP::doing_dev(),
596 + );
597 + }
598 +
599 + if ( $is_doing[ 'cron' ] && defined( 'WPSSO_CRON_' . $const_suffix ) ) {
600 +
601 + return 'WPSSO_CRON_' . $const_suffix;
602 +
603 + } elseif ( $is_doing[ 'ajax' ] && defined( 'WPSSO_AJAX_' . $const_suffix ) ) {
604 +
605 + return 'WPSSO_AJAX_' . $const_suffix;
606 +
607 + } elseif ( $is_doing[ 'admin' ] && defined( 'WPSSO_ADMIN_' . $const_suffix ) ) {
608 +
609 + return 'WPSSO_ADMIN_' . $const_suffix;
610 +
611 + } elseif ( defined( 'WPSSO_' . $const_suffix ) ) {
612 +
613 + return 'WPSSO_' . $const_suffix;
614 + }
615 +
616 + return null; // Constant not defined.
617 + }
618 +
619 + /*
620 + * See Wpsso->set_objects().
621 + * See WpssoSubmenuAdvanced->get_table_rows().
622 + */
623 + public function get_const_status( $const_suffix, $is_doing = null ) {
624 +
625 + $const_name = $this->get_const( $const_suffix, $is_doing ); // Returns null if constant not defined.
626 +
627 + return $const_name ? constant( $const_name ) : null;
628 + }
629 +
630 + /*
631 + * See WpssoSubmenuAdvanced->get_table_rows().
632 + */
633 + public function get_const_status_transl( $const_suffix, $is_doing = null ) {
634 +
635 + $const_name = $this->get_const( $const_suffix, $is_doing ); // Returns null if constant not defined.
636 +
637 + if ( $const_name ) {
638 +
639 + if ( constant( $const_name ) ) {
640 +
641 + return sprintf( _x( '(%s constant is true)', 'option comment', 'wpsso' ), $const_name );
642 + }
643 +
644 + return sprintf( _x( '(%s constant is false)', 'option comment', 'wpsso' ), $const_name );
645 + }
646 +
647 + return '';
648 + }
649 +
650 + public function get_lib_classnames( $type_dir ) {
651 +
652 + $classnames = array();
653 +
654 + foreach ( $this->cf[ 'plugin' ] as $ext => $info ) {
655 +
656 + if ( ! isset( $info[ 'lib' ][ $type_dir ] ) ) {
657 +
658 + continue;
659 +
660 + } elseif ( ! is_array( $info[ 'lib' ][ $type_dir ] ) ) {
661 +
662 + continue;
663 + }
664 +
665 + foreach ( $info[ 'lib' ][ $type_dir ] as $sub_dir => $libs ) {
666 +
667 + if ( is_array( $libs ) ) {
668 +
669 + /*
670 + * Skip loading admin library modules if not in admin back-end.
671 + */
672 + if ( 'admin' === $sub_dir && ! is_admin() ) {
673 +
674 + continue;
675 + }
676 +
677 + foreach ( $libs as $id => $label ) {
678 +
679 + $lib_path = $type_dir . '/' . $sub_dir . '/' . $id;
680 +
681 + $classname = apply_filters( $ext . '_load_lib', false, $lib_path );
682 +
683 + if ( is_string( $classname ) && class_exists( $classname ) ) {
684 +
685 + $classnames[ $sub_dir . '-' . $id ] = $classname;
686 + }
687 + }
688 +
689 + } elseif ( is_string( $libs ) ) {
690 +
691 + $id = $sub_dir;
692 + $label = $libs;
693 + $lib_path = $type_dir . '/' . $id;
694 + $classname = apply_filters( $ext . '_load_lib', false, $lib_path );
695 +
696 + if ( is_string( $classname ) && class_exists( $classname ) ) {
697 +
698 + $classnames[ $id ] = $classname;
699 + }
700 + }
701 + }
702 + }
703 +
704 + return $classnames;
705 + }
706 +
707 + public function get_options( $opt_key = false, $def_value = null ) {
708 +
709 + if ( false !== $opt_key ) {
710 +
711 + if ( isset( $this->options[ $opt_key ] ) ) {
712 +
713 + return $this->options[ $opt_key ];
714 + }
715 +
716 + return $def_value;
717 + }
718 +
719 + return $this->options;
720 + }
721 +
722 + public function debug_hooks() {
723 +
724 + /*
725 + * Show debug messages after the head and footer sections.
726 + *
727 + * Do not include the "shutdown" action as that would create HTML after the html closing tag.
728 + */
729 + foreach ( array( 'wp_head', 'wp_footer', 'admin_head', 'admin_footer' ) as $action ) {
730 +
731 + add_action( $action, array( $this, 'show_debug' ), PHP_INT_MAX );
732 + }
733 +
734 + /*
735 + * Show plugin settings just after the footer section.
736 + */
737 + foreach ( array( 'wp_footer', 'admin_footer' ) as $action ) {
738 +
739 + add_action( $action, array( $this, 'show_config' ), PHP_INT_MAX );
740 + }
741 + }
742 +
743 + /*
744 + * Only runs when debug is enabled.
745 + */
746 + public function show_debug() {
747 +
748 + echo "\n\n" . '<!-- wpsso doing action "' . current_action() . '" -->' . "\n\n";
749 +
750 + $this->debug->show_html( null, 'debug log' );
751 + }
752 +
753 + /*
754 + * Only runs when debug is enabled.
755 + */
756 + public function show_config() {
757 +
758 + if ( ! $this->debug->enabled ) { // Just in case.
759 +
760 + return;
761 + }
762 +
763 + $this->debug->mark();
764 +
765 + /*
766 + * Show constants.
767 + */
768 + $defined_constants = get_defined_constants( $categorize = true );
769 + $defined_constants[ 'user' ][ 'WPSSO_NONCE_NAME' ] = '********';
770 +
771 + if ( is_multisite() ) {
772 +
773 + $this->debug->log_arr( 'multisite constants', SucomUtil::preg_grep_keys( '/^(MULTISITE|^SUBDOMAIN_INSTALL|.*_SITE)$/',
774 + $defined_constants[ 'user' ] ) );
775 + }
776 +
777 + $this->debug->log_arr( 'wpsso constants', SucomUtil::preg_grep_keys( '/^WPSSO_/', $defined_constants[ 'user' ] ) );
778 +
779 + /*
780 + * Show active plugins.
781 + */
782 + $this->debug->log_arr( 'active plugins', SucomPlugin::get_active_plugins() );
783 +
784 + /*
785 + * Show available modules.
786 + */
787 + $this->debug->log_arr( 'available features', $this->avail );
788 +
789 + /*
790 + * Show all plugin options.
791 + */
792 + $opts = $this->options;
793 +
794 + foreach ( $opts as $key => $val ) {
795 +
796 + switch ( $key ) {
797 +
798 + case ( false !== strpos( $key, '_js_' ) ? true : false ):
799 + case ( false !== strpos( $key, '_css_' ) ? true : false ):
800 + case ( preg_match( '/(_css|_js|_html)$/', $key ) ? true : false ):
801 + case ( preg_match( '/_(key|secret|tid|token)$/', $key ) ? true : false ):
802 +
803 + if ( '' !== $opts[ $key ] ) $opts[ $key ] = '[removed]';
804 +
805 + break;
806 + }
807 + }
808 +
809 + $this->debug->log_arr( 'wpsso settings', $opts );
810 +
811 + $this->debug->mark();
812 +
813 + $this->debug->show_html();
814 + }
815 +
816 + private function debug_reminder( array $is_doing ) {
817 +
818 + if ( $this->debug->is_enabled( 'log' ) ) {
819 +
820 + $this->debug->log( 'WP debug log mode is active' );
821 + }
822 +
823 + if ( $this->debug->is_enabled( 'html' ) ) {
824 +
825 + $this->debug->log( 'HTML debug mode is active' );
826 + }
827 +
828 + if ( $is_doing[ 'admin' ] && ! $is_doing[ 'dev' ] ) {
829 +
830 + $info = $this->cf[ 'plugin' ][ 'wpsso' ];
831 + $notice_msg = '';
832 + $notice_key = 'debug-mode-is-active';
833 + $dismiss_time = 12 * HOUR_IN_SECONDS;
834 +
835 + if ( $this->debug->is_enabled( 'log' ) ) {
836 +
837 + $notice_key .= '-with-debug-log';
838 +
839 + $notice_msg .= __( 'WP debug logging mode is active - debug messages are being sent to the WordPress debug log.', 'wpsso' ) . ' ';
840 + }
841 +
842 + if ( $this->debug->is_enabled( 'html' ) ) {
843 +
844 + $notice_key .= '-with-html-comments';
845 +
846 + $notice_msg .= __( 'HTML debug mode is active - debug messages are being added to webpages as hidden HTML comments.', 'wpsso' ) . ' ';
847 + }
848 +
849 + /*
850 + * WP debug logging and/or HTML debug mode is active.
851 + */
852 + if ( $notice_msg ) {
853 +
854 + $notice_msg .= sprintf( __( 'The %s plugin\'s debug mode generates thousands of messages during page load, which affects website performance.', 'wpsso' ), $info[ 'name' ] ) . ' ';
855 +
856 + $notice_msg .= __( 'Don\'t forget to disable debug mode when debugging is complete.', 'wpsso' );
857 +
858 + $this->notice->warn( $notice_msg, null, $notice_key, $dismiss_time );
859 + }
860 +
861 + /*
862 + * WPSSO_CACHE_DISABLE constant is true or the 'plugin_cache_disable' option is checked.
863 + */
864 + if ( $this->util->cache->is_disabled() ) {
865 +
866 + $notice_msg = sprintf( __( 'The %s plugin\'s cache feature is disabled for debugging, which affects website performance.', 'wpsso' ), $info[ 'name' ] ) . ' ';
867 +
868 + $notice_msg .= __( 'Don\'t forget to re-enable caching when debugging is complete.', 'wpsso' );
869 +
870 + $notice_key = 'plugin-cache-is-disabled';
871 +
872 + $this->notice->warn( $notice_msg, null, $notice_key, $dismiss_time );
873 + }
874 + }
875 + }
876 + }
877 +
878 + global $wpsso;
879 +
880 + $wpsso =& Wpsso::get_instance();
881 +}