| 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.6.1 |
| 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 |
} |
| 882 |
|