| Server IP : 80.74.154.100 / Your IP : 216.73.217.0 Web Server : Apache System : Linux marissa.metanet.ch 4.18.0-553.141.2.lve.el7h.x86_64 #1 SMP Wed Jul 8 17:20:31 UTC 2026 x86_64 User : onlineadmin ( 10487) PHP Version : 8.5.7 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/httpd/vhosts/comeonline.ch/httpdocs/wp-content/plugins/wpsso/lib/ |
Upload File : |
<?php
/*
* License: GPLv3
* License URI: https://www.gnu.org/licenses/gpl.txt
* Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'These aren\'t the droids you\'re looking for.' );
}
if ( ! defined( 'WPSSO_PLUGINDIR' ) ) {
die( 'Do. Or do not. There is no try.' );
}
if ( ! class_exists( 'SucomPlugin' ) ) {
require_once WPSSO_PLUGINDIR . 'lib/com/plugin.php';
}
if ( ! class_exists( 'WpssoAdmin' ) ) {
class WpssoAdmin {
protected $p; // Wpsso class object.
protected $menu_id;
protected $menu_name;
protected $menu_lib;
protected $menu_ext; // Lowercase acronyn for plugin or add-on.
protected $menu_metaboxes;
protected $pagehook;
protected $pageref_url;
protected $pageref_title;
protected $toolbar_notice_types = array( 'err', 'warn', 'inf', 'upd' );
public static $readme = array();
public $form = null;
public $lang = array();
public $submenu = array();
/*
* Instantiated by Wpsso->set_objects() when is_admin() is true.
*/
public function __construct( &$plugin ) {
$this->p =& $plugin;
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$doing_ajax = SucomUtilWP::doing_ajax();
require_once WPSSO_PLUGINDIR . 'lib/admin-head.php';
new WpssoAdminHead( $plugin );
require_once WPSSO_PLUGINDIR . 'lib/admin-dashboard.php';
new WpssoAdminDashboard( $plugin );
/*
* The WpssoScript add_iframe_inline_script() method includes jQuery in the thickbox iframe to add the
* iframe_parent arguments when the Install or Update button is clicked.
*
* These class properties are used by both the WpssoAdmin plugin_complete_actions() and
* plugin_complete_redirect() methods to direct the user back to the thickbox iframe parent after plugin
* installation / activation / update.
*/
if ( ! empty( $_GET[ 'wpsso_pageref_title' ] ) ) {
$this->pageref_title = esc_html( urldecode( $_GET[ 'wpsso_pageref_title' ] ) );
}
if ( ! empty( $_GET[ 'wpsso_pageref_url' ] ) ) {
$this->pageref_url = esc_url_raw( urldecode( $_GET[ 'wpsso_pageref_url' ] ) );
}
add_action( 'activated_plugin', array( $this, 'activated_plugin' ), 10, 2 );
add_action( 'after_switch_theme', array( $this, 'after_switch_theme' ), 10, 2 );
add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 10, 2 );
/*
* Refresh the cache when the WordPress "home" or "blog_public" options are changed.
*
* See WpssAdmin->wp_site_option_changed().
* See SucomUpdate->wp_site_option_changed().
* See SucomUtilWP->raw_do_option().
* See SucomUpdateUtilWP->raw_do_option().
*/
add_action( 'update_option_home', array( $this, 'wp_site_option_changed' ), PHP_INT_MAX, 3 );
add_action( 'update_option_blog_public', array( $this, 'wp_site_option_changed' ), PHP_INT_MAX, 3 );
add_action( 'sucom_update_option_home', array( $this, 'wp_site_option_changed' ), PHP_INT_MAX, 3 );
/*
* This filter re-sorts (if necessary) the active plugins array to load WPSSO Core before its add-ons.
*/
add_filter( 'pre_update_option_active_plugins', array( $this, 'pre_update_active_plugins' ), PHP_INT_MAX, 3 );
add_filter( 'pre_update_option_active_sitewide_plugins', array( $this, 'pre_update_active_plugins' ), PHP_INT_MAX, 3 );
/*
* Define and disable the "Expect: 100-continue" header.
*/
add_filter( 'http_request_args', array( $this, 'add_expect_header' ), 1000, 2 );
add_filter( 'http_request_host_is_external', array( $this, 'allow_safe_hosts' ), 1000, 3 );
/*
* Provides plugin data / information from the readme.txt for additional add-ons. Don't hook the
* 'plugins_api_result' filter if the update manager is active as it provides more complete plugin data
* than what's available from the readme.txt.
*/
if ( empty( $this->p->avail[ 'p_ext' ][ 'um' ] ) ) {
add_filter( 'plugins_api_result', array( $this, 'external_plugin_data' ), 1000, 3 );
}
/*
* Add plugin / add-on settings links to the WordPress Plugins page. Hook this filter even when doing ajax
* since the WordPress plugin search results are created using an ajax call.
*
* The 5th argument is $menu_lib = 'submenu', so always limit the method arguments to 4.
*/
add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_links' ), 1000, 4 );
if ( is_multisite() ) {
/*
* The 5th argument is $menu_lib = 'sitesubmenu', so always limit the method arguments to 4.
*/
add_filter( 'network_admin_plugin_action_links', array( $this, 'add_site_plugin_action_links' ), 1000, 4 );
}
if ( ! $doing_ajax ) {
add_action( 'wp_dashboard_setup', array( $this, 'dashboard_setup' ) );
/*
* The admin_menu action is run before admin_init.
*/
add_action( 'admin_menu', array( $this, 'load_menu_objects' ), -1000 );
add_action( 'admin_menu', array( $this, 'add_admin_menus' ), WPSSO_ADD_MENU_PRIORITY, 0 );
add_action( 'admin_menu', array( $this, 'add_admin_submenus' ), WPSSO_ADD_SUBMENU_PRIORITY, 0 );
add_action( 'admin_init', array( $this, 'init_check_options' ), -1000 );
add_action( 'admin_init', array( $this, 'add_plugins_page_upgrade_notice' ) );
add_action( 'admin_init', array( $this, 'register_setting' ) );
if ( is_multisite() ) {
add_action( 'network_admin_menu', array( $this, 'load_network_menu_objects' ), -1000 );
add_action( 'network_admin_menu', array( $this, 'add_network_admin_menus' ), WPSSO_ADD_MENU_PRIORITY, 0 );
add_action( 'network_admin_edit_' . WPSSO_SITE_OPTIONS_NAME, array( $this, 'save_site_settings' ) );
}
add_filter( 'install_plugin_complete_actions', array( $this, 'plugin_complete_actions' ), 1000, 1 );
add_filter( 'update_plugin_complete_actions', array( $this, 'plugin_complete_actions' ), 1000, 1 );
add_filter( 'wp_redirect', array( $this, 'plugin_complete_redirect' ), 1000, 1 );
add_filter( 'wp_redirect', array( $this, 'profile_updated_redirect' ), -100, 2 );
add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu_notices' ), WPSSO_TB_NOTICE_MENU_ORDER );
add_action( 'admin_bar_menu', array( $this, 'check_admin_bar_menu_notices' ), PHP_INT_MAX );
add_filter( 'sucom_toolbar_notice_types', array( $this, 'filter_toolbar_notice_types' ) );
}
}
/*
* Since WPSSO Core v9.3.0.
*
* This action is run by WordPress after any plugin is activated.
*
* If a plugin is silently activated (such as during an update), this action does not run.
*/
public function activated_plugin( $plugin_base, $network_activation ) {
$this->p->reg->reset_admin_checks();
/*
* Since WPSSO Core v15.11.0.
*
* If the array of supported plugins has changed, then refresh the cache.
*/
$old_avail = $this->p->avail;
$new_avail = $this->p->check->get_avail();
foreach ( array( 'p', 'p_ext' ) as $key ) { // Remove plugin and add-on information.
unset( $old_avail[ $key ], $new_avail[ $key ] );
}
if ( $old_avail !== $new_avail ) {
$user_id = get_current_user_id();
WpssoRegister::do_multisite( $network_activation, array( $this->p->util->cache, 'schedule_refresh' ), $args = array( $user_id ) );
}
}
/*
* Since WPSSO Core v9.3.0.
*
* This action is run by WordPress multiple times and the parameters differ according to the context (ie. if the
* old theme exists or not). If the old theme is missing, the parameter will be the slug of the old theme.
*/
public function after_switch_theme( $old_name, $old_theme ) {
$this->p->reg->reset_admin_checks();
}
/*
* Since WPSSO Core v9.3.0.
*
* This action is run by WordPress when the upgrader process is complete.
*/
public function upgrader_process_complete( $wp_upgrader_obj, $hook_extra ) {
$this->p->reg->reset_admin_checks();
}
/*
* Refresh the cache when the WordPress "home" or "blog_public" options are changed.
*
* See WpssAdmin->wp_site_option_changed().
* See SucomUpdate->wp_site_option_changed().
* See SucomUtilWP->raw_do_option().
* See SucomUpdateUtilWP->raw_do_option().
*/
public function wp_site_option_changed( $old_value, $new_value, $option_name ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
static $do_once = null;
if ( $do_once ) return; // Stop here.
$do_once = true;
/*
* Standardize old and new values for string comparison.
*/
$old_value = strtolower( untrailingslashit( maybe_serialize( $old_value ) ) );
$new_value = strtolower( untrailingslashit( maybe_serialize( $new_value ) ) );
if ( $old_value !== $new_value ) {
if ( $user_id = get_current_user_id() ) {
if ( 'home' === $option_name ) {
$notice_msg = sprintf( __( 'The Site Address URL value has been changed from %1$s to %2$s.', 'wpsso' ), $old_value, $new_value );
$notice_key = __FUNCTION__ . '_' . $option_name . '_' . $old_value . '_' . $new_value;
$this->p->notice->upd( $notice_msg, $user_id, $notice_key );
}
}
$this->p->util->cache->schedule_refresh();
}
}
public function dashboard_setup() {
$classnames = $this->p->get_lib_classnames( 'dashboard' ); // Always returns an array.
foreach ( $classnames as $id => $classname ) {
new $classname( $this->p );
}
}
public function load_network_menu_objects() {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$this->load_menu_objects( array( 'submenu', 'sitesubmenu' ) );
}
public function load_menu_objects( $menu_libs = array() ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( empty( $menu_libs ) ) {
$menu_libs = array( 'dashboard', 'plugins', 'profile', 'settings', 'submenu', 'tools', 'users' );
}
foreach ( $menu_libs as $menu_lib ) {
foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
if ( ! isset( $info[ 'lib' ][ $menu_lib ] ) ) { // Not all add-ons have submenus.
continue;
}
foreach ( $info[ 'lib' ][ $menu_lib ] as $menu_id => $menu_name ) {
$add_menu_item = true;
if ( empty( $this->p->cf[ 'menu' ][ 'must_load' ][ $menu_id ] ) ) { // Settings page can be disabled.
$opt_key = SucomUtil::sanitize_key( 'plugin_add_' . $menu_lib . '_' . $menu_id );
$filter_name = SucomUtil::sanitize_hookname( 'wpsso_add_menu_' . $menu_lib . '_item_' . $menu_id );
$add_menu_item = isset( $this->p->options[ $opt_key ] ) ? (bool) $this->p->options[ $opt_key ] : true;
$add_menu_item = apply_filters( $filter_name, $add_menu_item );
}
if ( $add_menu_item ) {
$classname = apply_filters( $ext . '_load_lib', false, $menu_lib . '/' . $menu_id );
if ( is_string( $classname ) && class_exists( $classname ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'loading classname ' . $classname . ' for menu id ' . $menu_id );
}
$menu_title = $this->get_submenu_title( $info, $menu_lib, $menu_id );
$this->submenu[ $menu_id ] = new $classname( $this->p, $menu_id, $menu_title, $menu_lib, $ext );
} elseif ( $this->p->debug->enabled ) {
$this->p->debug->log( 'classname not found for menu lib ' . $menu_lib . '/' . $menu_id );
}
}
}
}
}
}
public function add_network_admin_menus() {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$this->add_admin_menus( 'sitesubmenu' );
}
/*
* Add a new main menu and its sub-menu items.
*/
public function add_admin_menus( $menu_lib = 'submenu' ) {
foreach ( $this->p->cf[ '*' ][ 'lib' ][ $menu_lib ] as $this->menu_id => $this->menu_name ) {
if ( isset( $this->submenu[ $this->menu_id ] ) ) {
$menu_slug = 'wpsso-' . $this->menu_id;
$this->submenu[ $this->menu_id ]->add_menu_page( $menu_slug );
break;
}
}
$menu_args = $this->get_submenu_args( $menu_lib );
foreach ( $menu_args as $menu_id => $args ) {
if ( isset( $this->submenu[ $menu_id ] ) ) { // Just in case.
call_user_func_array( array( $this->submenu[ $menu_id ], 'add_submenu_page' ), $args );
}
}
}
/*
* Add sub-menu items to existing WordPress menus.
*/
public function add_admin_submenus() {
foreach ( array( 'dashboard', 'plugins', 'profile', 'settings', 'tools', 'users' ) as $menu_lib ) {
$menu_args = $this->get_submenu_args( $menu_lib );
foreach ( $menu_args as $menu_id => $args ) {
if ( isset( $this->submenu[ $menu_id ] ) ) { // Just in case.
call_user_func_array( array( $this->submenu[ $menu_id ], 'add_submenu_page' ), $args );
}
}
}
}
/*
* Return and maybe set/reset the WpssoAdmin->form value.
*/
public function &get_form_object( $menu_ext ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( ! isset( $this->form ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'form object not defined' );
}
$this->set_form_object( $menu_ext );
} elseif ( $this->form->get_ext_id() !== $menu_ext ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'form object does not match' );
}
$this->set_form_object( $menu_ext );
}
return $this->form;
}
/*
* Set the WpssoAdmin->form value.
*/
protected function set_form_object( $menu_ext ) { // $menu_ext required for text_domain.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'setting form object for ' . $menu_ext );
}
$defs = $this->p->opt->get_defaults();
$this->form = new SucomForm( $this->p, WPSSO_OPTIONS_NAME, $this->p->options, $defs, $menu_ext );
}
public function register_setting() {
register_setting( 'wpsso_settings', WPSSO_OPTIONS_NAME, $args = array(
'sanitize_callback' => array( $this, 'settings_sanitation' ),
) );
}
/*
* Runs at admin_init priority -1000.
*/
public function init_check_options() {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
/*
* set_options() may have loaded the static defaults for new or missing options.
*
* After all objects have been loaded, and all filter / action hooks registered, check to see if the
* options array needs to be reloaded from the filtered defaults.
*/
if ( ! empty( $this->p->options[ '__reload_defaults' ] ) ) {
$this->p->options = $this->p->opt->get_defaults();
}
if ( is_multisite() ) { // Load the site options array.
if ( ! empty( $this->p->site_options[ '__reload_defaults' ] ) ) {
$this->p->site_options = $this->p->opt->get_site_defaults();
}
}
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'checking ' . WPSSO_OPTIONS_NAME . ' options' );
}
$this->p->options = $this->p->opt->check_options( WPSSO_OPTIONS_NAME, $this->p->options, $network = false );
if ( is_multisite() ) { // Load the site options array.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'checking ' . WPSSO_SITE_OPTIONS_NAME . ' options' );
}
$this->p->site_options = $this->p->opt->check_options( WPSSO_SITE_OPTIONS_NAME, $this->p->site_options, $network = true );
}
/*
* Init option checks.
*
* See WpssoWcmd->init_check_options().
*/
do_action( 'wpsso_init_check_options' );
}
public function add_plugins_page_upgrade_notice() {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
if ( ! empty( $info[ 'base' ] ) ) {
/*
* Fires at the end of the update message container in each row of the plugins list table.
*
* See wordpress/wp-admin/includes/update.php:587.
*/
add_action( 'in_plugin_update_message-' . $info[ 'base' ], array( $this, 'show_upgrade_notice' ), 10, 2 );
}
}
}
public function show_upgrade_notice( $data, $response ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( isset( $data[ 'upgrade_notice' ] ) ) { // Just in case.
echo '<span style="display:table;border-collapse:collapse;margin-left:26px;">';
echo '<span style="display:table-cell;">' . strip_tags( $data[ 'upgrade_notice' ] ) . '</span>';
echo '</span>';
}
}
protected function add_menu_page( $menu_slug ) {
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$page_title = $pkg_info[ 'wpsso' ][ 'short_pkg' ] . ' - ' . $this->menu_name;
$menu_title = $this->get_menu_title();
$cf_wp_admin = $this->p->cf[ 'wp' ][ 'admin' ];
$capability = isset( $cf_wp_admin[ $this->menu_lib ][ 'cap' ] ) ? $cf_wp_admin[ $this->menu_lib ][ 'cap' ] : 'manage_options';
$icon_url = 'none'; // Icon provided by WpssoStyle::admin_register_page_styles().
$function = array( $this, 'show_settings_page' );
$position = WPSSO_MENU_ORDER;
$this->pagehook = add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
add_action( 'load-' . $this->pagehook, array( $this, 'load_settings_page' ) );
}
protected function add_submenu_page( $parent_slug, $menu_id, $menu_title, $menu_lib, $menu_ext, $css_class = '' ) {
$css_class = trim( 'wpsso-menu-item wpsso-' . $menu_id . ' ' . $css_class );
$menu_title = '<div class="' . $css_class . ' menu-item-label">' . $menu_title . '</div>'; // Wrap the title string.
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$page_title = $pkg_info[ $menu_ext ][ 'short_pkg' ] . ' - ' . $menu_title;
$cf_wp_admin = $this->p->cf[ 'wp' ][ 'admin' ];
$capability = isset( $cf_wp_admin[ $menu_lib ][ 'cap' ] ) ? $cf_wp_admin[ $menu_lib ][ 'cap' ] : 'manage_options';
$menu_slug = 'wpsso-' . $menu_id;
$function = array( $this, 'show_settings_page' );
$position = null;
if ( isset( $cf_wp_admin[ $menu_lib ][ 'sub' ][ $menu_id ] ) ) {
$cf_menu_id = $cf_wp_admin[ $menu_lib ][ 'sub' ][ $menu_id ];
$capability = isset( $cf_menu_id[ 'cap' ] ) ? $cf_menu_id[ 'cap' ] : $capability;
$position = isset( $cf_menu_id[ 'pos' ] ) ? $cf_menu_id[ 'pos' ] : $position;
}
$this->pagehook = add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function, $position );
add_action( 'load-' . $this->pagehook, array( $this, 'load_settings_page' ) );
}
/*
* Add plugin links for the WordPress network plugins page.
*/
public function add_site_plugin_action_links( $action_links, $plugin_base, $plugin_data, $context, $menu_lib = 'sitesubmenu' ) {
return $this->add_plugin_action_links( $action_links, $plugin_base, $plugin_data, $context, $menu_lib );
}
/*
* Add plugin links for the WordPress plugins page.
*
* $plugin_data is an array of plugin data. See get_plugin_data().
*
* $context can be 'all', 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', or 'search'.
*/
public function add_plugin_action_links( $action_links, $plugin_base, $plugin_data, $context, $menu_lib = 'submenu' ) {
if ( ! isset( $this->p->cf[ '*' ][ 'base' ][ $plugin_base ] ) ) {
return $action_links;
}
$ext = $this->p->cf[ '*' ][ 'base' ][ $plugin_base ];
$info = $this->p->cf[ 'plugin' ][ $ext ];
$settings_page = empty( $info[ 'lib' ][ $menu_lib ] ) ? '' : key( $info[ 'lib' ][ $menu_lib ] );
$settings_page_url = $this->p->util->get_admin_url( $settings_page );
switch ( $ext ) {
case 'wpsso':
$addons_page = 'sitesubmenu' === $menu_lib ? 'site-addons' : 'addons';
$addons_page_url = $this->p->util->get_admin_url( $addons_page );
if ( ! empty( $settings_page ) ) {
$action_links[] = '<a href="' . $settings_page_url . '">' . _x( 'Plugin Settings', 'plugin action link', 'wpsso' ) . '</a>';
}
$action_links[] = '<a href="' . $addons_page_url . '">' . _x( 'Plugin Add-ons', 'plugin action link', 'wpsso' ) . '</a>';
break;
default:
if ( ! empty( $settings_page ) ) {
$action_links[] = '<a href="' . $settings_page_url . '">' . _x( 'Add-on Settings', 'plugin action link', 'wpsso' ) . '</a>';
}
break;
}
return $action_links;
}
/*
* Define and disable the "Expect: 100-continue" header.
*
* $parsed_args should be an array, so make sure other filters aren't giving us a string or boolean.
*/
public function add_expect_header( $parsed_args, $url ) {
if ( ! is_array( $parsed_args ) ) { // Just in case.
$parsed_args = array();
}
if ( empty( $parsed_args[ 'headers' ] ) ) { // Just in case.
$parsed_args[ 'headers' ] = array();
/*
* WordPress allows passing headers as a string -- fix that issue here so we can update the 'headers' array
* properly.
*
* See https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/class-http.php#L310.
*/
} elseif ( ! is_array( $parsed_args[ 'headers' ] ) ) {
$processedHeaders = WP_Http::processHeaders( $parsed_args[ 'headers' ] );
$parsed_args[ 'headers' ] = $processedHeaders[ 'headers' ];
}
$parsed_args[ 'headers' ][ 'Expect' ] = '';
return $parsed_args;
}
public function allow_safe_hosts( $is_allowed, $ip, $url ) {
if ( $is_allowed ) { // Already allowed.
return $is_allowed;
}
if ( isset( $this->p->cf[ 'extend' ] ) ) {
foreach ( $this->p->cf[ 'extend' ] as $host ) {
if ( 0 === strpos( $url, $host ) ) {
return true;
}
}
}
return $is_allowed;
}
/*
* Provides plugin data / information from the readme.txt for additional add-ons.
*/
public function external_plugin_data( $result, $action = null, $args = null ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( 'plugin_information' !== $action ) { // This filter only provides plugin data.
return $result;
} elseif ( empty( $args->slug ) ) { // Make sure we have a slug in the request.
return $result;
} elseif ( empty( $this->p->cf[ '*' ][ 'slug' ][ $args->slug ] ) ) { // Make sure the plugin slug is one of ours.
return $result;
} elseif ( isset( $result->slug ) && $result->slug === $args->slug ) { // If the object from WordPress looks complete, return it as-is.
return $result;
}
$ext = $this->p->cf[ '*' ][ 'slug' ][ $args->slug ]; // Get the add-on acronym to read its config.
if ( empty( $this->p->cf[ 'plugin' ][ $ext ] ) ) { // Make sure we have a config for that acronym.
return $result;
}
$plugin_data = $this->get_plugin_data( $ext, $read_cache = true ); // Get plugin data from the plugin readme.
if ( empty( $plugin_data ) ) { // Make sure we have some data to return.
return $result;
}
$plugin_data->external = true; // Let WordPress known that this is not a wordpress.org plugin.
return $plugin_data;
}
/*
* This method receives only a partial options array, so re-create a full one.
*
* WordPress handles the actual saving of the options to the database table.
*/
public function settings_sanitation( $opts ) {
$current_user_id = get_current_user_id(); // Always returns an integer.
/*
* Clear any old notices for the current user before sanitation checks.
*/
$this->p->notice->clear();
/*
* Make sure the input is an array.
*/
if ( ! is_array( $opts ) ) {
$opts = array();
}
$defs = $this->p->opt->get_defaults();
$opts = SucomUtil::restore_checkboxes( $opts );
$opts = SucomUtil::array_merge_recursive_distinct( $this->p->options, $opts );
$opts = $this->p->opt->sanitize( $opts, $defs, $network = false );
$opts = apply_filters( 'wpsso_save_settings_options', $opts, $network = false, $upgrading = false );
/*
* Maybe clear dismissed notices for enabled options that were previously disabled.
*
* See WpssoAdminHeadSuggestOptions->suggest_options_integration().
*/
foreach ( array(
'add_link_rel_canonical' => 'suggest-options-seo-add_link_rel_canonical',
'add_link_rel_shortlink' => 'suggest-options-seo-add_link_rel_shortlink',
'add_meta_name_description' => 'suggest-options-seo-add_meta_name_description',
'add_meta_name_robots' => 'suggest-options-seo-add_meta_name_robots',
'plugin_filter_content' => 'notice-content-filters-disabled',
'plugin_check_img_dims' => 'notice-check-img-dims-disabled',
'plugin_inherit_featured' => 'notice-wc-inherit-featured-disabled',
) as $opt_key => $notice_key ) {
if ( ! empty( $opts[ $opt_key ] ) ) { // Option is enabled.
$this->p->notice->clear_dismissed( $notice_key, $current_user_id );
}
}
/*
* Update the current options with any changes.
*/
$this->p->options = $opts;
$this->settings_saved_notice();
return $opts;
}
public function settings_saved_notice() {
$cache_md5_pre = 'wpsso_h_'; // Use 'wpsso_cache_expire_head_markup' filter.
$cache_exp_secs = $this->p->util->get_cache_exp_secs( $cache_md5_pre, $cache_type = 'transient' );
$user_id = get_current_user_id();
$notice_msg = '<strong>' . __( 'Plugin settings have been saved.', 'wpsso' ) . '</strong>' . ' ';
$notice_key = 'settings-saved';
if ( $cache_exp_secs > 0 ) {
$refresh_cache_url = $this->p->util->get_admin_url( $menu_id = 'tools' );
$refresh_cache_url = add_query_arg( 'wpsso-action', 'refresh_cache', $refresh_cache_url );
$refresh_cache_url = wp_nonce_url( $refresh_cache_url, WpssoAdmin::get_nonce_action(), WPSSO_NONCE_NAME );
$refresh_cache_link = '<a href="' . $refresh_cache_url . '">' . __( 'refresh the cache now', 'wpsso' ) . '</a>';
$human_cache_exp = human_time_diff( 0, $cache_exp_secs );
$notice_msg .= sprintf( __( 'You can %1$s or let the cache refresh over the next %2$s.', 'wpsso' ), $refresh_cache_link, $human_cache_exp );
}
$this->p->notice->upd( $notice_msg, $user_id, $notice_key );
}
public function save_site_settings() {
$default_page = key( $this->p->cf[ '*' ][ 'lib' ][ 'sitesubmenu' ] );
$default_page_url = $this->p->util->get_admin_url( $default_page );
$setting_page = SucomUtil::get_request_value( 'page', 'POST', $default_page );
$setting_page_url = $this->p->util->get_admin_url( $setting_page );
if ( empty( $_POST[ WPSSO_NONCE_NAME ] ) ) { // WPSSO_NONCE_NAME is an md5() string.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'nonce token validation post field missing' );
}
wp_redirect( $default_page_url ); // Do not trust the 'page' request value.
exit;
} elseif ( ! wp_verify_nonce( $_POST[ WPSSO_NONCE_NAME ], WpssoAdmin::get_nonce_action() ) ) {
$this->p->notice->err( __( 'Nonce token validation failed for network options (update ignored).', 'wpsso' ) );
wp_redirect( $default_page_url ); // Do not trust the 'page' request value.
exit;
} elseif ( ! current_user_can( 'manage_network_options' ) ) {
$this->p->notice->err( __( 'Insufficient privileges to manage network options.', 'wpsso' ) );
wp_redirect( $setting_page_url );
exit;
}
/*
* Clear any old notices for the current user before sanitation checks.
*/
$this->p->notice->clear();
/*
* Make sure the input is an array.
*/
$opts = array();
if ( isset( $_POST[ WPSSO_SITE_OPTIONS_NAME ] ) && is_array( $_POST[ WPSSO_SITE_OPTIONS_NAME ] ) ) {
$opts = $_POST[ WPSSO_SITE_OPTIONS_NAME ];
}
$defs = $this->p->opt->get_site_defaults();
$opts = SucomUtil::restore_checkboxes( $opts );
$opts = SucomUtil::array_merge_recursive_distinct( $this->p->site_options, $opts ); // Complete the array with previous options.
$opts = $this->p->opt->sanitize( $opts, $defs, $network = true );
$opts = apply_filters( 'wpsso_save_settings_options', $opts, $network = true, $upgrading = false );
/*
* Update the current options with any changes.
*/
$this->p->site_options = $opts;
update_site_option( WPSSO_SITE_OPTIONS_NAME, $opts );
$this->p->notice->upd( '<strong>' . __( 'Network plugin settings have been saved.', 'wpsso' ) . '</strong>' );
$setting_page_url = add_query_arg( 'settings-updated', 'true', $setting_page_url );
wp_redirect( $setting_page_url );
exit; // Stop after redirect.
}
public function load_settings_page() {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$user_id = get_current_user_id();
$action_query = 'wpsso-action';
$action_value = SucomUtil::get_request_value( $action_query ) ; // POST or GET with sanitize_text_field().
$action_value = SucomUtil::sanitize_hookname( $action_value );
$nonce_value = SucomUtil::get_request_value( WPSSO_NONCE_NAME ) ; // POST or GET with sanitize_text_field().
$_SERVER[ 'REQUEST_URI' ] = remove_query_arg( array( $action_query, WPSSO_NONCE_NAME ) );
wp_enqueue_script( 'postbox' );
if ( ! empty( $action_value ) ) {
if ( empty( $nonce_value ) ) { // WPSSO_NONCE_NAME is an md5() string.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'nonce token validation field missing' );
}
} elseif ( ! wp_verify_nonce( $nonce_value, WpssoAdmin::get_nonce_action() ) ) {
$notice_msg = sprintf( __( 'Nonce token validation failed for %1$s action "%2$s".', 'wpsso' ), 'admin', $action_value );
$this->p->notice->err( $notice_msg, $user_id );
} else {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'action_value = ' . $action_value );
}
switch ( $action_value ) {
case 'refresh_cache':
$this->p->util->cache->schedule_refresh( $user_id );
break;
case 'clear_cache_files':
$cleared_count = $this->p->util->cache->clear_cache_files();
$notice_msg = sprintf( __( '%s cache files have been cleared.', 'wpsso' ), $cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_ignored_urls':
$cleared_count = $this->p->util->cache->clear_ignored_urls();
$notice_msg = sprintf( __( '%s failed URL connections have been cleared.', 'wpsso' ), $cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_db_transients':
$cleared_count = $this->p->util->cache->clear_db_transients( $key_prefix = '', $incl_shortened = true );
$notice_msg = sprintf( __( '%s database transients have been cleared.', 'wpsso' ), $cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_db_transients_expired':
$cleared_count = $this->p->util->cache->clear_db_transients_expired();
$notice_msg = sprintf( __( '%s expired transients have been cleared.', 'wpsso' ), $cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_db_transients_no_short':
$cleared_count = $this->p->util->cache->clear_db_transients( $key_prefix = '', $incl_shortened = false );
$notice_msg = sprintf( __( '%s database transients have been cleared (shortened URLs preserved).', 'wpsso' ),
$cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_db_transients_shortened':
$cleared_count = $this->p->util->cache->clear_db_transients( $key_prefix = 'wpsso_s_', $incl_shortened = true );
$notice_msg = sprintf( __( '%s shortened URL database transients have been cleared.', 'wpsso' ),
$cleared_count );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'clear_cron_jobs':
$count_cron_jobs = number_format_i18n( $this->p->util->count_cron_jobs() );
update_option( 'cron', '' );
$notice_msg = sprintf( __( '%s WordPress cron jobs have been cleared.', 'wpsso' ), $count_cron_jobs );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'flush_rewrite_rules':
/*
* Update .htaccess and the 'rewrite_rules' option.
*
* This is an expensive operation so it should only be used when necessary.
*/
flush_rewrite_rules( $hard = true );
$notice_msg = __( 'The WordPress rewrite rules have been flushed.', 'wpsso' );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'add_persons':
$this->p->user->schedule_add_person_role( $user_id );
break;
case 'remove_persons':
$this->p->user->schedule_remove_person_role( $user_id );
break;
case 'reset_user_metabox_layout':
WpssoUser::delete_metabox_prefs( $user_id );
$user_obj = get_userdata( $user_id );
$user_name = $user_obj->display_name;
$notice_msg = sprintf( __( 'Metabox layout preferences for user ID #%d "%s" have been reset.', 'wpsso' ),
$user_id, $user_name );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'reset_user_dismissed_notices':
$this->p->notice->reset_dismissed( $user_id );
$user_obj = get_userdata( $user_id );
$user_name = $user_obj->display_name;
$notice_msg = sprintf( __( 'Dismissed notices for user ID #%d "%s" have been reset.', 'wpsso' ),
$user_id, $user_name );
$this->p->notice->upd( $notice_msg, $user_id );
break;
case 'change_show_options':
$_SERVER[ 'REQUEST_URI' ] = remove_query_arg( array( 'show-opts' ) );
$show_opts_key = isset( $_GET[ 'show-opts' ] ) ? SucomUtil::sanitize_key( $_GET[ 'show-opts' ] ) : null;
if ( isset( $this->p->cf[ 'form' ][ 'show_options' ][ $show_opts_key ] ) ) {
$show_name_transl = _x( $this->p->cf[ 'form' ][ 'show_options' ][ $show_opts_key ], 'option value', 'wpsso' );
WpssoUser::save_pref( array( 'show_opts' => $show_opts_key ) );
$notice_msg = '<strong>' . __( 'Option preference has been saved.', 'wpsso' ) . '</strong>';
$notice_msg .= sprintf( __( 'Now viewing "%s" by default.', 'wpsso' ), $show_name_transl );
$this->p->notice->upd( $notice_msg, $user_id );
}
break;
case 'reload_default_image_sizes':
$defs = $this->p->opt->get_defaults();
$img_defs = SucomUtil::preg_grep_keys( '/_img_(width|height|crop|crop_x|crop_y)$/', $defs );
$this->p->options = SucomUtil::array_merge_recursive_distinct( $this->p->options, $img_defs );
$this->p->opt->save_options( WPSSO_OPTIONS_NAME, $this->p->options, $network = false );
$this->p->notice->upd( __( 'Image size settings have been reloaded with their default values and saved.', 'wpsso' ) );
break;
case 'export_plugin_settings_json':
$this->export_plugin_settings_json();
break;
case 'import_plugin_settings_json':
$this->import_plugin_settings_json();
break;
default:
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'doing action "wpsso_load_settings_page_' . $action_value . '"' );
}
do_action( 'wpsso_load_settings_page_' . $action_value, $this->pagehook,
$this->menu_id, $this->menu_name, $this->menu_lib );
break;
}
}
}
$menu_ext = empty( $this->menu_ext ) ? $this->p->id : $this->menu_ext;
$this->get_form_object( $menu_ext ); // Return and maybe set/reset the WpssoAdmin->form value.
$this->add_settings_page_callbacks();
$this->add_settings_page_metaboxes();
$this->add_settings_page_footer();
}
/*
* Add actions and filters for this settings page.
*
* See WpssoAdmin->load_settings_page().
*/
protected function add_settings_page_callbacks() {
}
/*
* Add metaboxes for this settings page.
*
* See WpssoAdmin->load_settings_page().
*/
protected function add_settings_page_metaboxes( $callback_args = array() ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
/*
* Defined in the child construct method of this settings page.
*/
if ( empty( $this->menu_metaboxes ) ) {
return;
}
foreach ( $this->menu_metaboxes as $metabox_id => $metabox_title ) {
$metabox_screen = $this->pagehook;
$metabox_context = 'normal';
$metabox_prio = 'default';
$callback_args[ 'page_id' ] = $this->menu_id;
$callback_args[ 'metabox_id' ] = $metabox_id;
$callback_args[ 'metabox_title' ] = $metabox_title;
$callback_args[ 'network' ] = 'sitesubmenu' === $this->menu_lib ? true : false;
$method_name = method_exists( $this, 'show_metabox_' . $metabox_id ) ?
'show_metabox_' . $metabox_id : 'show_metabox_table';
add_meta_box( $this->pagehook . '_' . $metabox_id, $metabox_title, array( $this, $method_name ),
$metabox_screen, $metabox_context, $metabox_prio, $callback_args );
/*
* Add a class to set a minimum width for the network postboxes.
*/
if ( 'sitesubmenu' === $this->menu_lib ) {
add_filter( 'postbox_classes_' . $this->pagehook . '_' . $this->pagehook . '_' . $metabox_id,
array( $this, 'add_class_postbox_network' ) );
}
}
}
/*
* Include add-on name and version in settings page footer.
*/
protected function add_settings_page_footer() {
add_filter( 'admin_footer_text', array( $this, 'admin_footer_ext' ) );
add_filter( 'update_footer', array( $this, 'admin_footer_host' ) );
}
protected function maybe_show_language_notice() {
$current_locale = SucomUtilWP::get_locale();
$default_locale = SucomUtilWP::get_locale( 'default' );
if ( $current_locale && $default_locale && $current_locale !== $default_locale ) {
$notice_msg = sprintf( __( 'Your current language selection [%1$s] is different from the default site language [%2$s].', 'wpsso' ),
$current_locale, $default_locale ) . ' ';
$notice_msg .= sprintf( __( 'Localized option values [%1$s] will be used for webpages and content in that language.', 'wpsso' ),
$current_locale );
$notice_key = $this->menu_id . '-language-notice-' . $current_locale . '-' . $default_locale;
$this->p->notice->inf( $notice_msg, null, $notice_key, $dismiss_time = true );
}
}
public function show_settings_page() {
if ( ! $this->is_settings() ) { // Default check is for $this->menu_id.
settings_errors( WPSSO_OPTIONS_NAME );
}
if ( ! $this->is_plugin_found() ) { // Just in case.
return;
}
$side_col_boxes = $this->get_side_col_boxes();
$dashicon_html = $this->get_menu_dashicon_html( $this->menu_id );
/*
* Settings page wrapper.
*/
echo '<div id="' . $this->pagehook . '" class="wrap">' . "\n";
/*
* Settings page header.
*/
echo '<div id="wpsso-setting-page-header">' . "\n";
echo '<h1>' . $dashicon_html . ' '. $this->menu_name . '</h1>' . "\n";
echo '</div><!-- #wpsso-setting-page-header -->' . "\n";
/*
* Settings page content.
*/
echo '<div id="wpsso-setting-page-content" class="' . ( empty( $side_col_boxes ) ? 'no' : 'has' ) . '-side-column">' . "\n";
/*
* Metaboxes.
*/
echo '<div id="poststuff" class="metabox-holder no-right-sidebar">' . "\n";
echo '<div id="post-body" class="no-sidebar">' . "\n";
echo '<div id="post-body-content" class="no-sidebar-content">' . "\n";
$this->show_post_body_settings_form();
echo '</div><!-- #post-body-content -->' . "\n";
echo '</div><!-- #post-body -->' . "\n";
echo '</div><!-- #poststuff -->' . "\n";
/*
* Information boxes.
*/
if ( ! empty( $side_col_boxes ) ) {
echo '<div id="side-column">' . "\n";
foreach ( $side_col_boxes as $box ) {
echo '<table class="sucom-settings wpsso side-box">' . "\n";
echo '<tr><td>' . "\n";
echo $box;
echo '</td></tr>' . "\n";
echo '</table><!-- .side-box -->' . "\n";
}
echo '</div><!-- #side-column -->' . "\n";
}
echo '</div><!-- #wpsso-setting-page-content -->' . "\n";
echo '</div><!-- #' . $this->pagehook .' -->' . "\n";
/*
* The type="text/javascript" attribute is unnecessary for JavaScript resources and creates warnings in the W3C validator.
*/
?><script>
jQuery( function(){
jQuery( '.if-js-closed' ).removeClass( 'if-js-closed' ).addClass( 'closed' ); // Postboxes that should be closed.
postboxes.add_postbox_toggles( '<?php echo $this->pagehook; ?>' ); // Postboxes setup.
});
</script><?php
}
public function profile_updated_redirect( $url, $status ) {
if ( false !== strpos( $url, 'updated=' ) && strpos( $url, 'wp_http_referer=' ) ) {
/*
* Match WordPress behavior (users page for admins, profile page for everyone else).
*/
$menu_lib = current_user_can( 'list_users' ) ? 'users' : 'profile';
$parent_slug = $this->p->cf[ 'wp' ][ 'admin' ][ $menu_lib ][ 'page' ];
$referer_match = '/' . $parent_slug . '?page=wpsso-';
/*
* Parses string as if it were the query string passed via a URL and sets variables in the current
* scope (or in the array if result is provided).
*
* See https://www.php.net/manual/en/function.parse-str.php.
*/
parse_str( wp_parse_url( $url, PHP_URL_QUERY ), $parts );
if ( strpos( $parts[ 'wp_http_referer' ], $referer_match ) ) {
// translators: Please ignore - translation uses a different text domain.
$this->p->notice->upd( __( 'Profile updated.' ) );
$url = add_query_arg( 'updated', true, $parts[ 'wp_http_referer' ] );
}
}
return $url;
}
protected function show_post_body_settings_form() {
$menu_hookname = SucomUtil::sanitize_hookname( $this->menu_id );
$form_css_id = 'wpsso_settings_form_' . $menu_hookname;
switch ( $this->menu_lib ) {
case 'profile':
$user_id = get_current_user_id();
$user_obj = get_user_to_edit( $user_id );
$admin_color = get_user_option( 'admin_color', $user_id ); // Note that $user_id is the second argument.
if ( empty( $admin_color ) ) {
$admin_color = 'fresh';
}
/*
* Match WordPress behavior (users page for admins, profile page for everyone else).
*/
$referer_admin_url = current_user_can( 'list_users' ) ?
$this->p->util->get_admin_url( $this->menu_id, null, 'users' ) :
$this->p->util->get_admin_url( $this->menu_id, null, $this->menu_lib );
echo '<form name="wpsso" id="' . $form_css_id . '" action="user-edit.php" method="post">' . "\n";
echo '<input type="hidden" name="wp_http_referer" value="' . $referer_admin_url . '" />' . "\n";
echo '<input type="hidden" name="action" value="update" />' . "\n";
echo '<input type="hidden" name="user_id" value="' . $user_id . '" />' . "\n";
echo '<input type="hidden" name="nickname" value="' . $user_obj->nickname . '" />' . "\n";
echo '<input type="hidden" name="email" value="' . $user_obj->user_email . '" />' . "\n";
echo '<input type="hidden" name="admin_color" value="' . $admin_color . '" />' . "\n";
echo '<input type="hidden" name="rich_editing" value="' . $user_obj->rich_editing . '" />' . "\n";
echo '<input type="hidden" name="comment_shortcuts" value="' . $user_obj->comment_shortcuts . '" />' . "\n";
echo '<input type="hidden" name="admin_bar_front" value="' . _get_admin_bar_pref( 'front', $user_id ) . '" />' . "\n";
wp_nonce_field( 'update-user_' . $user_id );
break;
case 'dashboard':
case 'plugins':
case 'settings':
case 'submenu':
case 'tools':
echo '<form name="wpsso" id="' . $form_css_id . '" action="options.php" method="post">' . "\n";
settings_fields( 'wpsso_settings' );
break;
case 'sitesubmenu':
echo '<form name="wpsso" id="' . $form_css_id . '" action="edit.php?action=' . WPSSO_SITE_OPTIONS_NAME . '" method="post">' . "\n";
echo '<input type="hidden" name="page" value="' . $this->menu_id . '" />' . "\n";
break;
default:
return;
}
echo "\n" . '<!-- wpsso nonce fields -->' . "\n";
wp_nonce_field( WpssoAdmin::get_nonce_action(), WPSSO_NONCE_NAME );
echo "\n";
wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
echo "\n";
wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
echo "\n";
do_meta_boxes( $this->pagehook, $context = 'normal', $object = null );
do_action( 'wpsso_form_content_metaboxes_' . $menu_hookname, $this->pagehook );
echo $this->get_form_buttons();
echo '</form>', "\n";
}
protected function get_side_col_boxes() {
$col_boxes = array();
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$icon_px = 128;
foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
if ( empty( $info[ 'version' ] ) ) { // Exclude add-ons that are not active.
continue;
} elseif ( empty( $info[ 'url' ][ 'purchase' ] ) ) {
continue;
} elseif ( $pkg_info[ $ext ][ 'pp' ] ) {
continue;
}
$box = '<div class="side-box-header">' . "\n";
// translators: %s is the Premium add-on short name.
$box .= '<h2>' . sprintf( __( 'Upgrade to %s', 'wpsso' ), $pkg_info[ $ext ][ 'short_pro' ] ) . '</h2>' . "\n";
$box .= '</div><!-- .side-box-header -->' . "\n";
$box .= '<div class="side-box-icon">' . "\n";
$box .= $this->get_ext_img_icon( $ext, $icon_px ) . "\n";
$box .= '</div><!-- .side-box-icon -->' . "\n";
$box .= '<div class="side-box-content has-buttons">' . "\n";
$box .= $this->p->msgs->get( 'column-purchase-' . $ext, $info ) . "\n";
$box .= '</div><!-- .side-box-content -->' . "\n";
$box .= '<div class="side-box-buttons">' . "\n";
$box .= $this->form->get_button( sprintf( _x( 'Get %s', 'submit button', 'wpsso' ), $pkg_info[ $ext ][ 'short_pro' ] ),
'button-secondary', 'column-purchase', $info[ 'url' ][ 'purchase' ], true ) . "\n";
$box .= '</div><!-- .side-box-buttons -->' . "\n";
$col_boxes[] = $box;
}
return $col_boxes;
}
/*
* Called by WpssoAdmin->show_post_body_settings_form().
* Called by WpssoSubmenuTools->show_post_body_settings_form().
*/
protected function get_form_buttons() {
$this->add_form_buttons_submit( $form_button_rows );
$this->add_form_buttons_change_show_options( $form_button_rows );
$this->add_form_buttons( $form_button_rows );
$filter_name = 'wpsso_form_button_rows';
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
$form_button_rows = apply_filters( $filter_name, $form_button_rows, $this->menu_id );
$buttons_html = '';
$button_row_num = 1;
foreach ( $form_button_rows as $key => $buttons_row ) {
if ( $button_row_num >= 3 ) {
$css_class = 'button-secondary'; // Third+ row.
} elseif ( $button_row_num >= 2 ) {
$css_class = 'button-secondary button-alt'; // Second row.
} else $css_class = 'button-secondary button-highlight'; // First row.
$buttons_html .= '<div class="submit-buttons">';
foreach ( $buttons_row as $action_value => $mixed ) {
if ( empty( $action_value ) || empty( $mixed ) ) { // Just in case.
continue;
}
if ( is_string( $mixed ) ) {
if ( 'submit' === $action_value ) {
$buttons_html .= $this->form->get_submit( $mixed, 'button-primary' );
} else {
$action_url = $this->p->util->get_admin_url( '?wpsso-action=' . $action_value );
$button_url = wp_nonce_url( $action_url, WpssoAdmin::get_nonce_action(), WPSSO_NONCE_NAME );
$buttons_html .= $this->form->get_button( $mixed, $css_class, '', $button_url );
}
} elseif ( is_array( $mixed ) ) {
if ( ! empty( $mixed[ 'html' ] ) ) {
$buttons_html .= $mixed[ 'html' ];
}
}
}
$buttons_html .= '</div>';
$button_row_num++;
}
return $buttons_html;
}
protected function add_form_buttons_submit( &$form_button_rows ) {
if ( $this->menu_lib === 'profile' ) {
$submit_label_transl = _x( 'Save Profile Settings', 'submit button', 'wpsso' );
} else $submit_label_transl = _x( 'Save Plugin Settings', 'submit button', 'wpsso' );
$form_button_rows = array(
array(
'submit' => $submit_label_transl,
),
);
}
protected function add_form_buttons_change_show_options( &$form_button_rows ) {
$change_show_next_key = SucomUtil::next_key( WpssoUser::show_opts(), $this->p->cf[ 'form' ][ 'show_options' ] );
$change_show_name_transl = _x( $this->p->cf[ 'form' ][ 'show_options' ][ $change_show_next_key ], 'option value', 'wpsso' );
$change_show_label_transl = sprintf( _x( 'Change to "%s" View', 'submit button', 'wpsso' ), $change_show_name_transl );
$form_button_rows[ 0 ][ 'change_show_options&show-opts=' . $change_show_next_key ] = $change_show_label_transl;
}
protected function add_form_buttons( &$form_button_rows ) {
}
/*
* Callback method must be public for add_meta_box() hook.
*
* See WpssoAdmin->add_settings_page_metaboxes().
*/
public function show_metabox_table( $obj, $mb ) {
$args = isset( $mb[ 'args' ] ) ? $mb[ 'args' ] : array();
$page_id = isset( $args[ 'page_id' ] ) ? $args[ 'page_id' ] : '';
$metabox_id = isset( $args[ 'metabox_id' ] ) ? $args[ 'metabox_id' ] : '';
$filter_prefix = 'wpsso_mb_' . $page_id . '_' . $metabox_id;
$filter_name = SucomUtil::sanitize_hookname( $filter_prefix . '_rows' );
$table_rows = $this->get_table_rows( $page_id, $metabox_id, $tab_key = '', $args );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
$table_rows = apply_filters( $filter_name, $table_rows, $this->form, $args );
$this->p->util->metabox->do_table( $table_rows, 'metabox-' . $page_id . '-' . $metabox_id );
}
/*
* Since WPSSO Core v17.0.0.
*/
protected function show_metabox_tabbed( $obj, $mb, array $tabs ) {
$args = isset( $mb[ 'args' ] ) ? $mb[ 'args' ] : array();
$page_id = isset( $args[ 'page_id' ] ) ? $args[ 'page_id' ] : '';
$metabox_id = isset( $args[ 'metabox_id' ] ) ? $args[ 'metabox_id' ] : '';
$filter_prefix = 'wpsso_mb_' . $page_id . '_' . $metabox_id;
$filter_name = SucomUtil::sanitize_hookname( $filter_prefix . '_tabs' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
$tabs = apply_filters( $filter_name, $tabs );
if ( empty( $tabs ) ) {
return $this->show_metabox_table( $obj, $mb );
}
$table_rows = array();
foreach ( $tabs as $tab_key => $tab_title ) {
$table_rows[ $tab_key ] = $this->get_table_rows( $page_id, $metabox_id, $tab_key, $args );
$filter_name = SucomUtil::sanitize_hookname( $filter_prefix . '_' . $tab_key . '_rows' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
$table_rows[ $tab_key ] = apply_filters( $filter_name, $table_rows[ $tab_key ], $this->form, $args );
}
$this->p->util->metabox->do_tabbed( $metabox_id, $tabs, $table_rows );
}
/*
* This method is extended by each submenu page with additional arguments:
*
* get_table_rows( $page_id, $metabox_id, $tab_key = '', $args = array() );
*/
protected function get_table_rows( $page_id, $metabox_id ) {
return array();
}
public function get_table_rows_cols( array $table_cells, $row_cols = 2 ) {
sort( $table_cells );
$per_col = ceil( count( $table_cells ) / $row_cols );
$table_rows = array();
foreach ( $table_cells as $num => $cell ) {
if ( empty( $table_rows[ $num % $per_col ] ) ) { // Initialize the array element.
$table_rows[ $num % $per_col ] = '';
}
$table_rows[ $num % $per_col ] .= $cell; // Create the html for each row.
}
return $table_rows;
}
/*
* Always call as WpssoAdmin::get_nonce_action() to have a reliable __METHOD__ value.
*/
public static function get_nonce_action() {
$salt = __FILE__ . __LINE__ . __METHOD__;
return md5( $salt );
}
private function is_plugin_found() {
if ( ! SucomPlugin::is_plugin_active( 'wpsso/wpsso.php' ) ) {
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$notice_msg = sprintf( __( 'The %s plugin is not active and/or not found.', 'wpsso' ), $pkg_info[ 'wpsso' ][ 'name' ] );
$notice_key = 'wpsso-not-found';
$this->p->notice->err( $notice_msg, $user_id = null, $notice_key );
return false;
}
return true;
}
private function is_settings( $menu_id = false ) {
return $this->is_lib( 'settings', $menu_id );
}
private function is_lib( $lib_name, $menu_id = false ) {
if ( false === $menu_id ) {
$menu_id = $this->menu_id;
}
return isset( $this->p->cf[ '*' ][ 'lib' ][ $lib_name ][ $menu_id ] ) ? true : false;
}
public function add_admin_bar_menu_notices( $wp_admin_bar ) {
$menu_icon = '<span class="ab-icon" id="wpsso-toolbar-notices-icon"></span>';
$menu_count = '<span class="ab-label" id="wpsso-toolbar-notices-count">0</span>';
$menu_text = sprintf( __( 'Fetching %s notifications...', 'wpsso' ), $this->get_menu_title() );
$wp_admin_bar->add_node( array(
'id' => 'wpsso-toolbar-notices',
'title' => $menu_icon . $menu_count,
'parent' => false,
'href' => false,
'group' => false,
'meta' => array(),
) );
$wp_admin_bar->add_node( array(
'id' => 'wpsso-toolbar-notices-container',
'title' => $menu_text,
'parent' => 'wpsso-toolbar-notices',
'href' => false,
'group' => false,
'meta' => array(),
) );
}
public function check_admin_bar_menu_notices( $wp_admin_bar ) {
if ( ! $wp_admin_bar->get_node( 'wpsso-toolbar-notices' ) ) {
$this->toolbar_notice_types = array();
}
}
/*
* $toolbar_notice_types may be false if is_admin_bar_showing() is false.
*/
public function filter_toolbar_notice_types( $toolbar_notice_types ) {
return is_array( $toolbar_notice_types ) ? $this->toolbar_notice_types : $toolbar_notice_types;
}
public function admin_footer_ext( $footer_html ) {
if ( SucomUtil::get_const( 'WPSSO_ADMIN_FOOTER_DISABLE' ) ) {
return '';
}
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$footer_html = '<div class="admin-footer-ext">';
if ( isset( $pkg_info[ $this->menu_ext ][ 'name_pkg' ] ) ) {
$footer_html .= $pkg_info[ $this->menu_ext ][ 'name_pkg' ] . '<br/>';
}
if ( isset( $pkg_info[ $this->menu_ext ][ 'gen' ] ) ) {
$footer_html .= $pkg_info[ $this->menu_ext ][ 'gen' ] . '<br/>';
}
$footer_html .= '</div>';
return $footer_html;
}
public function admin_footer_host( $footer_html ) {
if ( SucomUtil::get_const( 'WPSSO_ADMIN_FOOTER_DISABLE' ) ) {
return '';
}
global $wp_version;
$home_url = SucomUtilWP::raw_get_home_url();
$home_path = preg_replace( '/^[a-z]+:\/\//i', '', $home_url );
$footer_html = '<div class="admin-footer-host">';
$footer_html .= $home_path . '<br/>';
$footer_html .= 'WordPress ' . $wp_version . '<br/>';
$footer_html .= 'PHP ' . phpversion() . '<br/>';
$footer_html .= '</div>';
return $footer_html;
}
/*
* WordPress sorts the active plugins array before updating the 'active_plugins' option. The default PHP sort order
* loads WPSSO add-ons before the WPSSO Core plugin. This filter re-sorts (if necessary) the active plugins array
* to load WPSSO Core before its add-ons. This allows WPSSO Core to load the latest WpssoAbstractAddOn and
* SucomAbstractAddon classes (for example) before any (possibly older) add-on does.
*
* When activating a plugin, the activate_plugin() function executes the following:
*
* $current = get_option( 'active_plugins', array() ); // Get current plugins array.
* $current[] = $plugin; // Add the new plugin.
* sort( $current ); // Sort the plugin array.
* update_option( 'active_plugins', $current ); // Save the plugin array.
*
* See the activate_plugin() function in wordpress/wp-admin/includes/plugin.php for additional context.
*/
public function pre_update_active_plugins( $current, $old_value, $option = 'active_plugins' ) {
usort( $current, array( __CLASS__, 'sort_active_plugins' ) );
return $current;
}
/*
* Since WPSSO Core v13.4.1.
*/
public static function get_option_unit_comment( $opt_key ) {
if ( $unit_text = WpssoUtilUnits::get_mixed_label( $opt_key ) ) {
return ' ' . sprintf( _x( 'in %s', 'option comment', 'wpsso' ), $unit_text );
}
return '';
}
public static function get_option_site_use( $name, $form, $network = false, $is_enabled = false ) {
$html = '';
if ( $network ) {
$wpsso =& Wpsso::get_instance();
$pkg_info = $wpsso->util->get_pkg_info(); // Uses a local cache.
$is_enabled = $is_enabled || $pkg_info[ 'wpsso' ][ 'pp' ] ? true : false;
$html .= $form->get_th_html( _x( 'Site Use', 'option label (very short)', 'wpsso' ), 'site-use' );
$html .= $is_enabled ? '<td class="site-use">' : '<td class="blank site-use">';
$html .= $is_enabled ? $form->get_select( $name . ':use', WpssoConfig::$cf[ 'form' ][ 'site_option_use' ], $css_class = 'site-use' ) :
$form->get_no_select( $name . ':use', WpssoConfig::$cf[ 'form' ][ 'site_option_use' ], $css_class = 'site-use' );
$html .= '</td>';
}
return $html;
}
public function plugin_complete_actions( $actions ) {
if ( ! empty( $this->pageref_url ) && ! empty( $this->pageref_title ) ) {
foreach ( $actions as $action => &$html ) {
switch ( $action ) {
case 'plugins_page':
$html = '<a href="' . $this->pageref_url . '" target="_parent">' .
sprintf( __( 'Return to %s', 'wpsso' ), $this->pageref_title ) . '</a>';
break;
default:
if ( preg_match( '/^(.*href=["\'])([^"\']+)(["\'].*)$/', $html, $matches ) ) {
$url = add_query_arg( array(
'wpsso_pageref_url' => urlencode( $this->pageref_url ),
'wpsso_pageref_title' => urlencode( $this->pageref_title ),
), $matches[ 2 ] );
$html = $matches[ 1 ] . $url . $matches[ 3 ];
}
break;
}
}
}
return $actions;
}
public function plugin_complete_redirect( $url ) {
if ( strpos( $url, '?activate=true' ) ) {
if ( ! empty( $this->pageref_url ) ) {
// translators: Please ignore - translation uses a different text domain.
$this->p->notice->upd( __( 'Plugin <strong>activated</strong>.' ) );
$url = $this->pageref_url;
}
}
return $url;
}
public function get_check_for_updates_link( $get_notice = true ) {
$check_url = '';
$notice_msg = '';
if ( class_exists( 'WpssoUm' ) ) {
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$check_url = $this->p->util->get_admin_url( 'um-general?wpsso-action=check_for_updates' );
$check_url = wp_nonce_url( $check_url, WpssoAdmin::get_nonce_action(), WPSSO_NONCE_NAME );
// translators: %1$s is the URL, %2$s is the short plugin name.
$notice_transl = __( 'You may <a href="%1$s">refresh the update information for %2$s and its add-ons</a> to check if newer versions are available.', 'wpsso' );
$notice_msg = sprintf( $notice_transl, $check_url, $pkg_info[ 'wpsso' ][ 'short_pkg' ] );
} elseif ( empty( $_GET[ 'force-check' ] ) ) {
$check_url = self_admin_url( 'update-core.php?force-check=1' );
// translators: %1$s is the URL.
$notice_transl = __( 'You may <a href="%1$s">refresh the update information for WordPress (plugins, themes and translations)</a> to check if newer versions are available.', 'wpsso' );
$notice_msg = sprintf( $notice_transl, $check_url );
}
return $get_notice ? $notice_msg : $check_url;
}
/*
* Called from the network settings pages.
*
* Add a class to set a minimum width for the network postboxes.
*/
public function add_class_postbox_network( $classes ) {
$classes[] = 'postbox-network';
return $classes;
}
public function add_class_postbox_menu_id( $classes ) {
global $wp_current_filter;
$filter_name = end( $wp_current_filter );
$postbox_name = preg_replace( '/^.*-(' . $this->menu_id . '_.*)$/u', '$1', $filter_name );
$classes[] = 'postbox-' . $this->menu_id;
$classes[] = 'postbox-' . $postbox_name;
return $classes;
}
public function export_plugin_settings_json() {
$date_slug = date( 'YmdHiT' );
$home_slug = SucomUtil::sanitize_hookname( preg_replace( '/^.*\/\//', '', get_home_url() ) );
$mime_type_gz = 'application/x-gzip';
$file_name_gz = WpssoConfig::get_version( $add_slug = true ) . '-' . $home_slug . '-' . $date_slug . '.json.gz';
$opts_encoded = wp_json_encode( $this->p->options );
$gzdata = gzencode( $opts_encoded, 9, FORCE_GZIP );
$filesize = strlen( $gzdata );
$disposition = 'attachment';
$chunksize = 1024 * 32; // 32kb per fread().
session_write_close();
ignore_user_abort();
set_time_limit( 300 ); // 5 minutes.
ini_set( 'zlib.output_compression', 0 );
if ( function_exists( 'apache_setenv' ) ) {
apache_setenv( 'no-gzip', 1 );
}
ob_implicit_flush( true );
ob_end_flush();
/*
* Remove all dots, except last one, for MSIE clients.
*/
if ( strstr( $_SERVER[ 'HTTP_USER_AGENT' ], 'MSIE' ) ) {
$file_name_gz = preg_replace( '/\./', '%2e', $file_name_gz, substr_count( $file_name_gz, '.' ) - 1 );
}
if ( isset( $_SERVER[ 'HTTPS' ] ) ) {
$gmt_date = gmdate( 'D, d M Y H:i:s' ) . ' GMT';
header( 'Pragma: ' );
header( 'Cache-Control: ' );
header( 'Expires: ' . $gmt_date );
header( 'Last-Modified: ' . $gmt_date );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
} elseif ( $disposition == 'attachment' ) {
header( 'Cache-control: private' );
} else {
header( 'Cache-Control: no-cache, must-revalidate' );
header( 'Pragma: no-cache' );
}
header( 'Content-Type: application/' . $mime_type_gz );
header( 'Content-Disposition: ' . $disposition . '; filename="' . $file_name_gz . '"' );
header( 'Content-Transfer-Encoding: binary' );
header( 'Content-Length: ' . $filesize );
echo $gzdata;
flush();
sleep( 1 );
exit();
}
public function import_plugin_settings_json() {
$mime_type_gz = 'application/x-gzip';
$dot_file_ext = '.json.gz';
$max_file_size = 100000; // 100K.
if ( ! isset( $_FILES[ 'file' ][ 'error' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'incomplete post method upload' );
}
return false;
} elseif ( $_FILES[ 'file' ][ 'error' ] === UPLOAD_ERR_NO_FILE ) {
$this->p->notice->err( sprintf( __( 'Please select a %1$s settings file to import.', 'wpsso' ), $dot_file_ext ) );
return false;
} elseif ( $_FILES[ 'file' ][ 'type' ] !== 'application/x-gzip' ) {
$this->p->notice->err( sprintf( __( 'The %1$s settings file to import must be an "%2$s" mime type.', 'wpsso' ),
$dot_file_ext, $mime_type_gz ) );
return false;
} elseif ( $_FILES[ 'file' ][ 'size' ] > $max_file_size ) { // Just in case.
$this->p->notice->err( sprintf( __( 'The %1$s settings file is larger than the maximum of %2$d bytes allowed.', 'wpsso' ),
$dot_file_ext, $max_file_size ) );
return false;
}
$gzdata = file_get_contents( $_FILES[ 'file' ][ 'tmp_name' ] );
@unlink( $_FILES[ 'file' ][ 'tmp_name' ] );
$opts_encoded = gzdecode( $gzdata );
if ( empty( $opts_encoded ) ) { // false or empty array.
$this->p->notice->err( sprintf( __( 'The %1$s settings file is appears to be empty or corrupted.', 'wpsso' ), $dot_file_ext ) );
return false;
}
$opts = json_decode( $opts_encoded, $assoc = true );
if ( empty( $opts ) || ! is_array( $opts ) ) { // false or empty array.
$this->p->notice->err( sprintf( __( 'The %1$s settings file could not be decoded into a settings array.', 'wpsso' ), $dot_file_ext ) );
return false;
}
$this->p->options = $this->p->opt->check_options( WPSSO_OPTIONS_NAME, $opts );
$this->p->opt->save_options( WPSSO_OPTIONS_NAME, $opts, $network = false );
$this->p->notice->upd( __( 'Import of plugin and add-on settings is complete.', 'wpsso' ) );
return true;
}
public function get_menu_title() {
$menu_title = _x( $this->p->cf[ 'menu' ][ 'title' ], 'menu title', 'wpsso' );
$filter_name = 'wpsso_menu_title';
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
return apply_filters( 'wpsso_menu_title', $menu_title );
}
public function get_menu_dashicon_html( $menu_id, $css_class = '' ) {
$dashicon = $this->get_menu_dashicon( $menu_id );
return '<div class="' . trim( $css_class . ' dashicons-before dashicons-' . $dashicon ) . '"></div>';
}
public function get_menu_dashicon( $menu_id ) {
$dashicon = 'admin-generic';
if ( ! empty( $this->p->cf[ 'menu' ][ 'dashicons' ][ $menu_id ] ) ) {
$dashicon = $this->p->cf[ 'menu' ][ 'dashicons' ][ $menu_id ];
} elseif ( ! empty( $this->p->cf[ 'menu' ][ 'dashicons' ][ '*' ] ) ) {
$dashicon = $this->p->cf[ 'menu' ][ 'dashicons' ][ '*' ];
}
return $dashicon;
}
public function get_submenu_title( $info, $menu_lib, $menu_id ) {
$menu_title = '';
if ( ! empty( $info[ 'lib' ][ $menu_lib ][ $menu_id ] ) ) { // Just in case.
$menu_title = $info[ 'lib' ][ $menu_lib ][ $menu_id ];
}
if ( ! empty( $info[ 'text_domain' ] ) ) {
$menu_title = _x( $menu_title, 'lib file description', $info[ 'text_domain' ] );
}
/*
* Example $filter_name = 'wpsso_menu_your_sso_title'
*/
$filter_name = SucomUtil::sanitize_hookname( 'wpsso_menu_' . $menu_id . '_title' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'applying filters "' . $filter_name . '"' );
}
return apply_filters( $filter_name, $menu_title );
}
/*
* $menu_lib = 'dashboard', 'plugins', 'profile', 'settings', 'submenu', 'sitesubmenu', 'tools', or 'users'
*/
public function get_submenu_args( $menu_lib = 'submenu' ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( is_admin() ) {
static $local_cache = array();
if ( isset( $local_cache[ $menu_lib ] ) ) {
return $local_cache[ $menu_lib ];
}
} else $local_cache = array();
$local_cache[ $menu_lib ] = array();
$top_first_id = false;
$top_last_id = false;
$ext_first_id = false;
$ext_last_id = false;
$sorted_menu = array();
$unsorted_menu = array();
if ( 'profile' === $menu_lib && current_user_can( 'list_users' ) ) { // Match WordPress behavior.
$parent_slug = $this->p->cf[ 'wp' ][ 'admin' ][ 'users' ][ 'page' ];
} elseif ( 'submenu' === $menu_lib || 'sitesubmenu' === $menu_lib ) { // Plugin submenu.
$parent_slug = 'wpsso-' . $this->menu_id;
} else $parent_slug = $this->p->cf[ 'wp' ][ 'admin' ][ $menu_lib ][ 'page' ];
foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
if ( ! isset( $info[ 'lib' ][ $menu_lib ] ) ) { // Not all add-ons have submenus.
continue;
}
foreach ( $info[ 'lib' ][ $menu_lib ] as $menu_id => $menu_name ) {
$menu_title = $this->get_submenu_title( $info, $menu_lib, $menu_id );
/*
* Leave WPSSO Core submenu items in their original order.
*/
if ( 'wpsso' === $ext ) {
$unsorted_menu[] = array( $parent_slug, $menu_id, $menu_title, $menu_lib, $ext );
if ( false === $top_first_id ) $top_first_id = $menu_id;
$top_last_id = $menu_id;
/*
* Sort add-on submenu items.
*/
} else {
$sorted_menu[ $menu_title . '-' . $menu_id ] = array( $parent_slug, $menu_id, $menu_title, $menu_lib, $ext );
if ( false === $ext_first_id ) $ext_first_id = $menu_id;
$ext_last_id = $menu_id;
}
}
}
SucomUtil::natksort( $sorted_menu );
foreach ( array_merge( $unsorted_menu, $sorted_menu ) as $sort_key => $args ) {
$menu_id = $args[ 1 ];
if ( 'submenu' === $menu_lib || 'sitesubmenu' === $menu_lib ) {
if ( $menu_id === $top_first_id ) {
$args[ 5 ] = 'top-first-submenu-page';
} elseif ( $menu_id === $top_last_id ) {
$args[ 5 ] = 'top-last-submenu-page' . ( empty( $ext_first_id ) ? ' no-add-ons' : ' with-add-ons' );
} elseif ( $menu_id === $ext_first_id ) {
$args[ 5 ] = 'ext-first-submenu-page';
} elseif ( $menu_id === $ext_last_id ) {
$args[ 5 ] = 'ext-last-submenu-page';
}
}
$local_cache[ $menu_lib ][ $menu_id ] = $args;
}
return $local_cache[ $menu_lib ];
}
/*
* Get the plugin readme and convert array elements to a plugin data object.
*/
public function get_plugin_data( $ext, $read_cache = true ) {
$data = new StdClass;
$info = $this->p->cf[ 'plugin' ][ $ext ];
$readme = $this->get_readme_info( $ext, $read_cache );
if ( empty( $readme ) ) { // Make sure we got something back.
return array();
}
foreach ( array(
/*
* Readme array => Plugin object.
*/
'plugin_name' => 'name',
'plugin_slug' => 'slug',
'base' => 'plugin',
'stable_tag' => 'version',
'tested_up_to' => 'tested',
'requires_at_least' => 'requires',
'home' => 'homepage',
'download' => 'download_link',
'author' => 'author',
'upgrade_notice' => 'upgrade_notice',
'last_updated' => 'last_updated',
'sections' => 'sections',
'remaining_content' => 'other_notes', // Added to sections.
'banners' => 'banners',
'icons' => 'icons',
) as $readme_key => $prop_name ) {
switch ( $readme_key ) {
case 'base': // From plugin config.
if ( ! empty( $info[ $readme_key ] ) ) {
$data->$prop_name = $info[ $readme_key ];
}
break;
case 'home': // From plugin config.
if ( ! empty( $info[ 'url' ][ 'purchase' ] ) ) { // Check for purchase url first.
$data->$prop_name = $info[ 'url' ][ 'purchase' ];
} elseif ( ! empty( $info[ 'url' ][ $readme_key ] ) ) {
$data->$prop_name = $info[ 'url' ][ $readme_key ];
}
break;
case 'download': // From plugin config.
if ( ! empty( $info[ 'url' ][ $readme_key ] ) ) {
$data->$prop_name = $info[ 'url' ][ $readme_key ];
}
break;
case 'banners': // From plugin config.
case 'icons': // From plugin config.
if ( ! empty( $info[ 'assets' ][ $readme_key ] ) ) {
$data->$prop_name = $info[ 'assets' ][ $readme_key ]; // Array with 1x / 2x images.
}
break;
case 'remaining_content':
if ( ! empty( $readme[ $readme_key ] ) ) {
$data->sections[ $prop_name ] = $readme[ $readme_key ];
}
break;
default:
if ( ! empty( $readme[ $readme_key ] ) ) {
$data->$prop_name = $readme[ $readme_key ];
}
break;
}
}
return $data;
}
/*
* Return an associative array with plugin readme info.
*
* See WpssoAdmin->get_plugin_data().
* See WpssoAdminDashboard->show_metabox_version_info().
* See WpssoUmActions->action_load_settings_page_check_for_updates().
*/
public function get_readme_info( $ext, $read_cache = true ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log_args( array(
'ext' => $ext,
'read_cache' => $read_cache,
) );
}
$rel_file = 'readme.txt';
$file_content = '';
$cache_md5_pre = 'wpsso_r_'; // 'wpsso_cache_expire_readme_info' filter.
$cache_salt = __METHOD__ . '(ext:' . $ext . ')';
$cache_id = $cache_md5_pre . md5( $cache_salt );
$cache_exp_secs = $this->p->util->get_cache_exp_secs( $cache_md5_pre, $cache_type = 'transient' );
$readme_info = array();
/*
* Maybe get parsed readme from transient cache.
*/
if ( $cache_exp_secs > 0 && $read_cache ) {
$readme_info = get_transient( $cache_id );
if ( ! empty( $readme_info ) && is_array( $readme_info ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'readme_info retrieved from transient' );
}
return $readme_info; // Stop here.
}
} else delete_transient( $cache_id ); // Just in case.
$file_content = $this->get_ext_file_content( $ext, $rel_file, $read_cache );
if ( ! empty( $file_content ) ) {
if ( ! class_exists( 'SuextParseReadme' ) ) {
require_once WPSSO_PLUGINDIR . 'lib/ext/parse-readme.php';
}
$readme_parser =& SuextParseReadme::get_instance();
$readme_info = $readme_parser->parse_content( $file_content );
}
/*
* Save the parsed readme to transient cache.
*/
if ( $cache_exp_secs > 0 ) {
set_transient( $cache_id, $readme_info, $cache_exp_secs );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'readme_info saved to transient cache for ' . $cache_exp_secs . ' seconds' );
}
}
return is_array( $readme_info ) ? $readme_info : array(); // Just in case.
}
/*
* See WpssoSubmenuSetup->show_metabox_setup_guide().
*/
public function get_ext_file_content( $ext, $rel_file, $read_cache = true ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log_args( array(
'ext' => $ext,
'rel_file' => $rel_file,
) );
}
$file_path = WpssoConfig::get_ext_file_path( $ext, $rel_file );
$file_url = WpssoConfig::get_ext_file_url( $ext, $rel_file ); // Returns sanitized URL or false.
$file_content = '';
$text_domain = WpssoConfig::get_ext_text_domain( $ext );
$cache_md5_pre = 'wpsso_c_'; // 'wpsso_cache_expire_file_content' filter.
$cache_exp_secs = $this->p->util->get_cache_exp_secs( $cache_md5_pre, $cache_type = 'file' );
if ( $file_url ) { // Sanitized URL or false.
if ( $cache_exp_secs > 0 ) {
if ( ! $read_cache ) $this->p->cache->clear( $file_url );
$file_content = $this->p->cache->get( $file_url, $format = 'raw', $cache_type = 'file', $cache_exp_secs );
} else $this->p->cache->clear( $file_url );
}
if ( empty( $file_content ) ) { // No content from the file URL.
if ( $file_path && file_exists( $file_path ) && $fh = @fopen( $file_path, 'rb' ) ) {
$file_content = fread( $fh, filesize( $file_path ) );
fclose( $fh );
}
}
if ( $text_domain ) { // False or text domain string.
if ( ! class_exists( 'SucomGetText' ) ) {
require_once WPSSO_PLUGINDIR . 'lib/com/gettext.php';
}
$file_content = SucomGetText::get_html_transl( $file_content, $text_domain );
}
return $file_content;
}
/*
* Plugin links for the addons and licenses settings page.
*/
public function get_ext_action_links( $ext, $info, &$tabindex = false ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache.
$action_links = array();
if ( ! empty( $info[ 'base' ] ) ) {
$install_url = is_multisite() ?
network_admin_url( 'plugin-install.php', null ) :
get_admin_url( $blog_id = null, 'plugin-install.php' );
$details_url = add_query_arg( array(
'plugin' => $info[ 'slug' ],
'tab' => 'plugin-information',
'TB_iframe' => 'true',
'width' => $this->p->cf[ 'wp' ][ 'tb_iframe' ][ 'width' ],
'height' => $this->p->cf[ 'wp' ][ 'tb_iframe' ][ 'height' ],
), $install_url );
if ( SucomPlugin::is_plugin_installed( $info[ 'base' ] ) ) { // Uses a local cache.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $info[ 'base' ] . ' is installed' );
}
if ( SucomPlugin::have_plugin_update( $info[ 'base' ] ) ) { // Uses a local cache.
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $info[ 'base' ] . ' has an update' );
}
$action_links[] = '<a href="' . $details_url . '" class="thickbox" tabindex="' . ++$tabindex . '">' .
'<font color="red">' . ( 'wpsso' === $ext ? _x( 'Plugin Details and Update',
'plugin action link', 'wpsso' ) : _x( 'Add-on Details and Update',
'plugin action link', 'wpsso' ) ) . '</font></a>';
} else {
$action_links[] = '<a href="' . $details_url . '" class="thickbox" tabindex="' . ++$tabindex . '">' .
( 'wpsso' === $ext ? _x( 'Plugin Details', 'plugin action link', 'wpsso' ) :
_x( 'Add-on Details', 'plugin action link', 'wpsso' ) ) . '</a>';
}
} else {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $info[ 'base' ] . ' is not installed' );
}
$action_links[] = '<a href="' . $details_url . '" class="thickbox" tabindex="' . ++$tabindex . '">' .
( 'wpsso' === $ext ? _x( 'Plugin Details and Install', 'plugin action link', 'wpsso' ) :
_x( 'Add-on Details and Install', 'plugin action link', 'wpsso' ) ) . '</a>';
}
} elseif ( ! empty( $info[ 'url' ][ 'home' ] ) ) {
$action_links[] = '<a href="' . $info[ 'url' ][ 'home' ] . '" tabindex="' . ++$tabindex . '">' .
_x( 'About Page', 'plugin action link', 'wpsso' ) . '</a>';
}
if ( ! empty( $info[ 'url' ][ 'docs' ] ) ) {
$action_links[] = '<a href="' . $info[ 'url' ][ 'docs' ] . '"' .
( false !== $tabindex ? ' tabindex="' . ++$tabindex . '"' : '' ) . '>' .
_x( 'Documentation', 'plugin action link', 'wpsso' ) . '</a>';
}
if ( ! empty( $info[ 'url' ][ 'support' ] ) && ! empty( $pkg_info[ $ext ][ 'pp' ] ) ) {
$action_links[] = '<a href="' . $info[ 'url' ][ 'support' ] . '"' .
( false !== $tabindex ? ' tabindex="' . ++$tabindex . '"' : '' ) . '>' .
sprintf( _x( '%s Support', 'plugin action link', 'wpsso' ),
_x( $this->p->cf[ 'packages' ][ 'pro' ], 'package name', 'wpsso' ) ) . '</a>';
} elseif ( ! empty( $info[ 'url' ][ 'forum' ] ) ) {
$action_links[] = '<a href="' . $info[ 'url' ][ 'forum' ] . '"' .
( false !== $tabindex ? ' tabindex="' . ++$tabindex . '"' : '' ) . '>' .
_x( 'Community Forum', 'plugin action link', 'wpsso' ) . '</a>';
}
if ( ! empty( $info[ 'url' ][ 'purchase' ] ) ) {
$action_links[] = $this->p->msgs->get( 'pro-purchase-link', array(
'ext' => $ext,
'url' => $info[ 'url' ][ 'purchase' ],
'tabindex' => false !== $tabindex ? ++$tabindex : false,
) );
}
return $action_links;
}
/*
* Returns a 128x128px image by default.
*/
public function get_ext_img_icon( $ext, $icon_px = 128 ) {
/*
* The default image is a transparent 1px gif.
*/
$img_src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
$img_srcset = '';
if ( ! empty( $this->p->cf[ 'plugin' ][ $ext ][ 'assets' ][ 'icons' ] ) ) {
$icons = $this->p->cf[ 'plugin' ][ $ext ][ 'assets' ][ 'icons' ];
if ( ! empty( $icons[ '1x' ] ) ) {
$img_src = $icons[ '1x' ];
$img_srcset .= $icons[ '1x' ] . ' 128w, ';
}
if ( ! empty( $icons[ '2x' ] ) ) {
$img_srcset .= $icons[ '2x' ] . ' 256w, ';
}
}
return '<img src="' . $img_src . '" srcset="' . trim( $img_srcset, $chars = ', ' ) . '" '
. 'width="' . $icon_px . '" height="' . $icon_px . '" style="width:' . $icon_px . 'px; height:' . $icon_px . 'px;"/>';
}
/*
* Sort the WPSSO Core plugin slug before the WPSSO add-on slugs.
*/
private static function sort_active_plugins( $a, $b ) {
$wpsso_any = 'wpsso';
$wpsso_core = 'wpsso/';
$wpsso_addon = 'wpsso-';
$jsm_plugin = 'jsm-';
if ( 0 === strpos( $a, $wpsso_any ) || 0 === strpos( $b, $wpsso_any ) ) {
/*
* Sort WPSSO Core plugin before WPSSO add-on.
*/
if ( 0 === strpos( $a, $wpsso_core ) && 0 === strpos( $b, $wpsso_addon ) ) return -1;
/*
* Sort WPSSO add-on after the WPSSO Core plugin.
*/
if ( 0 === strpos( $a, $wpsso_addon ) && 0 === strpos( $b, $wpsso_core ) ) return 1;
/*
* Sort WPSSO plugins before JSM plugins.
*/
if ( 0 === strpos( $a, $wpsso_any ) && 0 === strpos( $b, $jsm_plugin ) ) return -1;
/*
* Sort JSM plugins after WPSSO plugins.
*/
if ( 0 === strpos( $a, $jsm_plugin ) && 0 === strpos( $b, $wpsso_any ) ) return 1;
return strcmp( $a, $b );
}
return 0; // No change.
}
}
}