Initial commit: Atomaste website
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class that Pro and Lite both extend.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Activate {
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
register_activation_hook( AIOSEO_FILE, [ $this, 'activate' ] );
|
||||
register_deactivation_hook( AIOSEO_FILE, [ $this, 'deactivate' ] );
|
||||
|
||||
// The following only needs to happen when in the admin.
|
||||
if ( ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This needs to run on at least 1000 because we load the roles in the Access class on 999.
|
||||
add_action( 'init', [ $this, 'init' ], 1000 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize activation.
|
||||
*
|
||||
* @since 4.1.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
// If Pro just deactivated the lite version, we need to manually run the activation hook, because it doesn't run here.
|
||||
$proDeactivatedLite = (bool) aioseo()->core->cache->get( 'pro_just_deactivated_lite' );
|
||||
if ( ! $proDeactivatedLite ) {
|
||||
// Also check for the old transient in the options table (because a user might switch from an older Lite version that lacks the Cache class).
|
||||
$proDeactivatedLite = (bool) get_option( '_aioseo_cache_pro_just_deactivated_lite' );
|
||||
}
|
||||
|
||||
if ( $proDeactivatedLite ) {
|
||||
aioseo()->core->cache->delete( 'pro_just_deactivated_lite' );
|
||||
$this->activate( false );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on activation.
|
||||
*
|
||||
* @since 4.0.17
|
||||
*
|
||||
* @param bool $networkWide Whether or not this is a network wide activation.
|
||||
* @return void
|
||||
*/
|
||||
public function activate( $networkWide ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
aioseo()->access->addCapabilities();
|
||||
|
||||
// Make sure our tables exist.
|
||||
aioseo()->updates->addInitialCustomTablesForV4();
|
||||
|
||||
// Set the activation timestamps.
|
||||
$time = time();
|
||||
aioseo()->internalOptions->internal->activated = $time;
|
||||
|
||||
if ( ! aioseo()->internalOptions->internal->firstActivated ) {
|
||||
aioseo()->internalOptions->internal->firstActivated = $time;
|
||||
}
|
||||
|
||||
aioseo()->core->cache->clear();
|
||||
|
||||
$this->maybeRunSetupWizard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on deactivation.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deactivate() {
|
||||
aioseo()->access->removeCapabilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should redirect on activation.
|
||||
*
|
||||
* @since 4.1.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function maybeRunSetupWizard() {
|
||||
if ( '0.0' !== aioseo()->internalOptions->internal->lastActiveVersion ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oldOptions = get_option( 'aioseop_options' );
|
||||
if ( ! empty( $oldOptions ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_network_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $_GET['activate-multi'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Recommended
|
||||
return;
|
||||
}
|
||||
|
||||
// Sets 30 second transient for welcome screen redirect on activation.
|
||||
aioseo()->core->cache->update( 'activation_redirect', true, 30 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds our capabilities to all roles on the next request and the installing user on the current request after upgrading to Pro.
|
||||
*
|
||||
* @link https://github.com/awesomemotive/aioseo/issues/2267
|
||||
* @link https://github.com/awesomemotive/aioseo/issues/2288
|
||||
*
|
||||
* @since 4.1.4.4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addCapabilitiesOnUpgrade() {
|
||||
// In case the user is switching to Pro via the AIOSEO Connect feature,
|
||||
// we need to set this transient here as the regular activation hooks won't run and Pro otherwise won't clear the cache and add the required capabilities.
|
||||
aioseo()->core->cache->update( 'pro_just_deactivated_lite', true );
|
||||
|
||||
// Doing the above isn't sufficient because the current user will be lacking the capabilities on the first request. Therefore, we add them manually just for him.
|
||||
$userId = function_exists( 'get_current_user_id' ) && get_current_user_id()
|
||||
? get_current_user_id() // If there is a logged in user, the user is switching from Lite to Pro via the Plugins menu.
|
||||
: aioseo()->core->cache->get( 'connect_active_user' ); // If there is no logged in user, we're upgrading via AIOSEO Connect.
|
||||
|
||||
$user = get_userdata( $userId );
|
||||
if ( is_object( $user ) ) {
|
||||
$capabilities = aioseo()->access->getCapabilityList();
|
||||
foreach ( $capabilities as $capability ) {
|
||||
$user->add_cap( $capability );
|
||||
}
|
||||
}
|
||||
|
||||
aioseo()->core->cache->delete( 'connect_active_user' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main class with methods that are called.
|
||||
*
|
||||
* @since 4.2.0
|
||||
* @version 4.7.1 Moved from Pro to Common.
|
||||
*/
|
||||
class CategoryBase {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( ! aioseo()->options->searchAppearance->advanced->removeCategoryBase ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'query_vars', [ $this, 'queryVars' ] );
|
||||
add_filter( 'request', [ $this, 'maybeRedirectCategoryUrl' ] );
|
||||
add_filter( 'category_rewrite_rules', [ $this, 'categoryRewriteRules' ] );
|
||||
add_filter( 'term_link', [ $this, 'modifyTermLink' ], 10, 3 );
|
||||
|
||||
// Flush rewrite rules on any of the following actions.
|
||||
add_action( 'created_category', [ $this, 'scheduleFlushRewrite' ] );
|
||||
add_action( 'delete_category', [ $this, 'scheduleFlushRewrite' ] );
|
||||
add_action( 'edited_category', [ $this, 'scheduleFlushRewrite' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the redirect var to the query vars if the "strip category bases" option is enabled.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $queryVars Query vars to filter.
|
||||
* @return array The filtered query vars.
|
||||
*/
|
||||
public function queryVars( $queryVars ) {
|
||||
$queryVars[] = 'aioseo_category_redirect';
|
||||
|
||||
return $queryVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the category URL to the new one.
|
||||
*
|
||||
* @param array $queryVars Query vars to check for redirect var.
|
||||
* @return array The original query vars.
|
||||
*/
|
||||
public function maybeRedirectCategoryUrl( $queryVars ) {
|
||||
if ( isset( $queryVars['aioseo_category_redirect'] ) ) {
|
||||
$categoryUrl = trailingslashit( get_option( 'home' ) ) . user_trailingslashit( $queryVars['aioseo_category_redirect'], 'category' );
|
||||
wp_redirect( $categoryUrl, 301, 'AIOSEO' );
|
||||
die;
|
||||
}
|
||||
|
||||
return $queryVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite the category base.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return array The rewritten rules.
|
||||
*/
|
||||
public function categoryRewriteRules() {
|
||||
global $wp_rewrite; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
|
||||
$categoryRewrite = $this->getCategoryRewriteRules();
|
||||
|
||||
// Redirect from the old base.
|
||||
$categoryStructure = $wp_rewrite->get_category_permastruct(); // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
$categoryBase = trim( str_replace( '%category%', '(.+)', $categoryStructure ), '/' ) . '$';
|
||||
|
||||
// Add the rewrite rules.
|
||||
$categoryRewrite[ $categoryBase ] = 'index.php?aioseo_category_redirect=$matches[1]';
|
||||
|
||||
return $categoryRewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rewrite rules for the category.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return array An array of category rewrite rules.
|
||||
*/
|
||||
private function getCategoryRewriteRules() {
|
||||
global $wp_rewrite; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
|
||||
$categoryRewrite = [];
|
||||
$categories = get_categories( [ 'hide_empty' => false ] );
|
||||
|
||||
if ( empty( $categories ) ) {
|
||||
return $categoryRewrite;
|
||||
}
|
||||
|
||||
$blogPrefix = $this->getBlogPrefix();
|
||||
$paginationBase = $wp_rewrite->pagination_base; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
foreach ( $categories as $category ) {
|
||||
$nicename = $this->getCategoryParents( $category ) . $category->slug;
|
||||
$categoryRewrite = $this->addCategoryRewrites( $categoryRewrite, $nicename, $blogPrefix, $paginationBase );
|
||||
|
||||
// Also add the rules for uppercase.
|
||||
$filteredNicename = $this->convertEncodedToUppercase( $nicename );
|
||||
|
||||
if ( $nicename !== $filteredNicename ) {
|
||||
$categoryRewrite = $this->addCategoryRewrites( $categoryRewrite, $filteredNicename, $blogPrefix, $paginationBase );
|
||||
}
|
||||
}
|
||||
|
||||
return $categoryRewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the blog prefix.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return string The prefix for the blog.
|
||||
*/
|
||||
private function getBlogPrefix() {
|
||||
$permalinkStructure = get_option( 'permalink_structure' );
|
||||
if (
|
||||
is_multisite() &&
|
||||
! is_subdomain_install() &&
|
||||
is_main_site() &&
|
||||
0 === strpos( $permalinkStructure, '/blog/' )
|
||||
) {
|
||||
return 'blog/';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve category parents with separator.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param \WP_Term $category the category instance.
|
||||
* @return string A list of category parents.
|
||||
*/
|
||||
private function getCategoryParents( $category ) {
|
||||
if (
|
||||
$category->parent === $category->term_id ||
|
||||
absint( $category->parent ) < 1
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parents = get_category_parents( $category->parent, false, '/', true );
|
||||
|
||||
return is_wp_error( $parents ) ? '' : $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks through category nicename and convert encoded parts
|
||||
* into uppercase using $this->encode_to_upper().
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $nicename The encoded category string.
|
||||
* @return string The converted category string.
|
||||
*/
|
||||
private function convertEncodedToUppercase( $nicename ) {
|
||||
// Checks if name has any encoding in it.
|
||||
if ( false === strpos( $nicename, '%' ) ) {
|
||||
return $nicename;
|
||||
}
|
||||
|
||||
$nicenames = explode( '/', $nicename );
|
||||
$nicenames = array_map( [ $this, 'convertToUppercase' ], $nicenames );
|
||||
|
||||
return implode( '/', $nicenames );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the encoded URI string to uppercase.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $encoded The encoded category string.
|
||||
* @return string The converted category string.
|
||||
*/
|
||||
private function convertToUppercase( $encoded ) {
|
||||
if ( false === strpos( $encoded, '%' ) ) {
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
return strtoupper( $encoded );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the required category rewrites rules.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param array $categoryRewrite The current set of rules.
|
||||
* @param string $categoryNicename The category nicename.
|
||||
* @param string $blogPrefix Multisite blog prefix.
|
||||
* @param string $paginationBase WP_Query pagination base.
|
||||
* @return array The added set of rules.
|
||||
*/
|
||||
private function addCategoryRewrites( $categoryRewrite, $categoryNicename, $blogPrefix, $paginationBase ) {
|
||||
$categoryRewrite[ $blogPrefix . '(' . $categoryNicename . ')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$' ] = 'index.php?category_name=$matches[1]&feed=$matches[2]';
|
||||
$categoryRewrite[ $blogPrefix . '(' . $categoryNicename . ')/' . $paginationBase . '/?([0-9]{1,})/?$' ] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
|
||||
$categoryRewrite[ $blogPrefix . '(' . $categoryNicename . ')/?$' ] = 'index.php?category_name=$matches[1]';
|
||||
|
||||
return $categoryRewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the category base from the category link.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @param string $link Term link.
|
||||
* @param object $term The current Term Object.
|
||||
* @param string $taxonomy The current Taxonomy.
|
||||
* @return string The modified term link.
|
||||
*/
|
||||
public function modifyTermLink( $link, $term = null, $taxonomy = '' ) {
|
||||
if ( 'category' !== $taxonomy ) {
|
||||
return $link;
|
||||
}
|
||||
|
||||
$categoryBase = get_option( 'category_base' );
|
||||
if ( empty( $categoryBase ) ) {
|
||||
global $wp_rewrite; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
$categoryStructure = $wp_rewrite->get_category_permastruct(); // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
$categoryBase = trim( str_replace( '%category%', '', $categoryStructure ), '/' );
|
||||
}
|
||||
|
||||
// Remove initial slash, if there is one (we remove the trailing slash in the regex replacement and don't want to end up short a slash).
|
||||
if ( '/' === substr( $categoryBase, 0, 1 ) ) {
|
||||
$categoryBase = substr( $categoryBase, 1 );
|
||||
}
|
||||
|
||||
$categoryBase .= '/';
|
||||
|
||||
return preg_replace( '`' . preg_quote( (string) $categoryBase, '`' ) . '`u', '', (string) $link, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the rewrite rules.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function scheduleFlushRewrite() {
|
||||
aioseo()->options->flushRewriteRules();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,605 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Models;
|
||||
use AIOSEO\Plugin\Common\Integrations\BuddyPress as BuddyPressIntegration;
|
||||
|
||||
/**
|
||||
* Abstract class that Pro and Lite both extend.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
abstract class Filters {
|
||||
/**
|
||||
* The plugin we are checking.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $plugin;
|
||||
|
||||
/**
|
||||
* ID of the WooCommerce product that is being duplicated.
|
||||
*
|
||||
* @since 4.1.4
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private static $originalProductId;
|
||||
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter( 'wp_optimize_get_tables', [ $this, 'wpOptimizeAioseoTables' ] );
|
||||
|
||||
// This action needs to run on AJAX/cron for scheduled rewritten posts in Yoast Duplicate Post.
|
||||
add_action( 'duplicate_post_after_rewriting', [ $this, 'updateRescheduledPostMeta' ], 10, 2 );
|
||||
|
||||
if ( wp_doing_ajax() || wp_doing_cron() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'plugin_row_meta', [ $this, 'pluginRowMeta' ], 10, 2 );
|
||||
add_filter( 'plugin_action_links_' . AIOSEO_PLUGIN_BASENAME, [ $this, 'pluginActionLinks' ], 10, 2 );
|
||||
|
||||
// Genesis theme compatibility.
|
||||
add_filter( 'genesis_detect_seo_plugins', [ $this, 'genesisTheme' ] );
|
||||
|
||||
// WeGlot compatibility.
|
||||
if ( isset( $_SERVER['REQUEST_URI'] ) && preg_match( '#(/default-sitemap\.xsl)$#i', (string) sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ) {
|
||||
add_filter( 'weglot_active_translation_before_treat_page', '__return_false' );
|
||||
}
|
||||
|
||||
if ( isset( $_SERVER['REQUEST_URI'] ) && preg_match( '#(\.xml)$#i', (string) sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ) {
|
||||
add_filter( 'jetpack_boost_should_defer_js', '__return_false' );
|
||||
}
|
||||
|
||||
// GoDaddy CDN compatibility.
|
||||
add_filter( 'wpaas_cdn_file_ext', [ $this, 'goDaddySitemapXml' ] );
|
||||
|
||||
// Duplicate Post integration.
|
||||
add_action( 'dp_duplicate_post', [ $this, 'duplicatePost' ], 10, 2 );
|
||||
add_action( 'dp_duplicate_page', [ $this, 'duplicatePost' ], 10, 2 );
|
||||
add_action( 'woocommerce_product_duplicate_before_save', [ $this, 'scheduleDuplicateProduct' ], 10, 2 );
|
||||
add_action( 'add_post_meta', [ $this, 'rewriteAndRepublish' ], 10, 3 );
|
||||
|
||||
// BBpress compatibility.
|
||||
add_action( 'init', [ $this, 'resetUserBBPress' ], -1 );
|
||||
add_filter( 'the_title', [ $this, 'maybeRemoveBBPressReplyFilter' ], 0, 2 );
|
||||
|
||||
// Bypass the JWT Auth plugin's unnecessary restrictions. https://wordpress.org/plugins/jwt-auth/
|
||||
add_filter( 'jwt_auth_default_whitelist', [ $this, 'allowRestRoutes' ] );
|
||||
|
||||
// Clear the site authors cache.
|
||||
add_action( 'profile_update', [ $this, 'clearAuthorsCache' ] );
|
||||
add_action( 'user_register', [ $this, 'clearAuthorsCache' ] );
|
||||
|
||||
add_filter( 'aioseo_public_post_types', [ $this, 'removeInvalidPublicPostTypes' ] );
|
||||
add_filter( 'aioseo_public_taxonomies', [ $this, 'removeInvalidPublicTaxonomies' ] );
|
||||
|
||||
add_action( 'admin_print_scripts', [ $this, 'removeEmojiDetectionScripts' ], 0 );
|
||||
|
||||
// Disable Jetpack sitemaps module.
|
||||
if ( aioseo()->options->sitemap->general->enable ) {
|
||||
add_filter( 'jetpack_get_available_modules', [ $this, 'disableJetpackSitemaps' ] );
|
||||
}
|
||||
|
||||
add_action( 'after_setup_theme', [ $this, 'removeHelloElementorDescriptionTag' ] );
|
||||
add_action( 'wp', [ $this, 'removeAvadaOgTags' ] );
|
||||
add_action( 'init', [ $this, 'declareAioseoFollowingConsentApi' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares AIOSEO and its addons as following the Consent API.
|
||||
*
|
||||
* @since 4.6.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function declareAioseoFollowingConsentApi() {
|
||||
add_filter( 'wp_consent_api_registered_all-in-one-seo-pack/all_in_one_seo_pack.php', '__return_true' );
|
||||
add_filter( 'wp_consent_api_registered_all-in-one-seo-pack-pro/all_in_one_seo_pack.php', '__return_true' );
|
||||
|
||||
foreach ( aioseo()->addons->getAddons() as $addon ) {
|
||||
if ( empty( $addon->installed ) || empty( $addon->basename ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( isset( $addon->basename ) ) {
|
||||
add_filter( 'wp_consent_api_registered_' . $addon->basename, '__return_true' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes emoji detection scripts on WP 6.2 which broke our Emojis.
|
||||
*
|
||||
* @since 4.3.4.1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeEmojiDetectionScripts() {
|
||||
global $wp_version; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
if ( version_compare( $wp_version, '6.2', '>=' ) ) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the current user if bbPress is active.
|
||||
* We have to do this because our calls to wp_get_current_user() set the current user early and this breaks core functionality in bbPress.
|
||||
*
|
||||
* @link https://github.com/awesomemotive/aioseo/issues/22300
|
||||
*
|
||||
* @since 4.1.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetUserBBPress() {
|
||||
if ( function_exists( 'bbpress' ) ) {
|
||||
global $current_user; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
$current_user = null; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the bbPress title filter when adding a new reply with empty title to avoid fatal error.
|
||||
*
|
||||
* @link https://github.com/awesomemotive/aioseo/issues/4183
|
||||
*
|
||||
* @since 4.3.1
|
||||
*
|
||||
* @param string $title The post title.
|
||||
* @param int $id The post ID (optional - in order to fix an issue where other plugins/themes don't pass in the second arg).
|
||||
* @return string The post title.
|
||||
*/
|
||||
public function maybeRemoveBBPressReplyFilter( $title, $id = 0 ) {
|
||||
if (
|
||||
function_exists( 'bbp_get_reply_post_type' ) &&
|
||||
get_post_type( $id ) === bbp_get_reply_post_type() &&
|
||||
aioseo()->helpers->isScreenBase( 'post' )
|
||||
) {
|
||||
remove_filter( 'the_title', 'bbp_get_reply_title_fallback', 2 );
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates the model when duplicate post is triggered.
|
||||
*
|
||||
* @since 4.1.1
|
||||
*
|
||||
* @param integer $targetPostId The target post ID.
|
||||
* @param \WP_Post $sourcePost The source post object.
|
||||
* @return void
|
||||
*/
|
||||
public function duplicatePost( $targetPostId, $sourcePost = null ) {
|
||||
$sourcePostId = ! empty( $sourcePost->ID ) ? $sourcePost->ID : $sourcePost;
|
||||
$sourceAioseoPost = Models\Post::getPost( $sourcePostId );
|
||||
$targetPost = Models\Post::getPost( $targetPostId );
|
||||
|
||||
$columns = $sourceAioseoPost->getColumns();
|
||||
foreach ( $columns as $column => $value ) {
|
||||
// Skip the ID column.
|
||||
if ( 'id' === $column ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'post_id' === $column ) {
|
||||
$targetPost->$column = $targetPostId;
|
||||
continue;
|
||||
}
|
||||
|
||||
$targetPost->$column = $sourceAioseoPost->$column;
|
||||
}
|
||||
|
||||
$targetPost->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates the model when rewrite and republish is triggered.
|
||||
*
|
||||
* @since 4.3.4
|
||||
*
|
||||
* @param integer $postId The post ID.
|
||||
* @param string $metaKey The meta key.
|
||||
* @param mixed $metaValue The meta value.
|
||||
* @return void
|
||||
*/
|
||||
public function rewriteAndRepublish( $postId, $metaKey = '', $metaValue = '' ) {
|
||||
if ( '_dp_has_rewrite_republish_copy' !== $metaKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$originalPost = aioseo()->helpers->getPost( $postId );
|
||||
if ( ! is_object( $originalPost ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->duplicatePost( (int) $metaValue, $originalPost );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the model when a post is republished.
|
||||
* Yoast Duplicate Post doesn't do this since we store our data in a custom table.
|
||||
*
|
||||
* @since 4.6.7
|
||||
*
|
||||
* @param int $scheduledPostId The ID of the scheduled post.
|
||||
* @param int $originalPostId The ID of the original post.
|
||||
* @return void
|
||||
*/
|
||||
public function updateRescheduledPostMeta( $scheduledPostId, $originalPostId ) {
|
||||
$this->duplicatePost( $originalPostId, $scheduledPostId );
|
||||
|
||||
// Delete the AIOSEO post record for the scheduled post.
|
||||
$scheduledAioseoPost = Models\Post::getPost( $scheduledPostId );
|
||||
$scheduledAioseoPost->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an action to duplicate our meta after the duplicated WooCommerce product has been saved.
|
||||
*
|
||||
* @since 4.1.4
|
||||
*
|
||||
* @param \WC_Product $newProduct The new, duplicated product.
|
||||
* @param \WC_Product $originalProduct The original product.
|
||||
* @return void
|
||||
*/
|
||||
public function scheduleDuplicateProduct( $newProduct, $originalProduct = null ) {
|
||||
self::$originalProductId = $originalProduct->get_id();
|
||||
add_action( 'wp_insert_post', [ $this, 'duplicateProduct' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates our meta for the new WooCommerce product.
|
||||
*
|
||||
* @since 4.1.4
|
||||
*
|
||||
* @param integer $postId The new post ID.
|
||||
* @param \WP_Post $post The new post object.
|
||||
* @return void
|
||||
*/
|
||||
public function duplicateProduct( $postId, $post = null ) {
|
||||
if ( ! self::$originalProductId || 'product' !== $post->post_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->duplicatePost( $postId, self::$originalProductId );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable SEO inside the Genesis theme if it's running.
|
||||
*
|
||||
* @since 4.0.3
|
||||
*
|
||||
* @param array $array An array of checks.
|
||||
* @return array An array with our function added.
|
||||
*/
|
||||
public function genesisTheme( $array ) {
|
||||
if ( empty( $array ) || ! isset( $array['functions'] ) ) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
$array['functions'][] = 'aioseo';
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove XML from the GoDaddy CDN so our urls remain intact.
|
||||
*
|
||||
* @since 4.0.5
|
||||
*
|
||||
* @param array $extensions The original extensions list.
|
||||
* @return array The extensions list without xml.
|
||||
*/
|
||||
public function goDaddySitemapXml( $extensions ) {
|
||||
$key = array_search( 'xml', $extensions, true );
|
||||
unset( $extensions[ $key ] );
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers our row meta for the plugins page.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $actions List of existing actions.
|
||||
* @param string $pluginFile The plugin file.
|
||||
* @return array List of action links.
|
||||
*/
|
||||
abstract public function pluginRowMeta( $actions, $pluginFile = '' );
|
||||
|
||||
/**
|
||||
* Registers our action links for the plugins page.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $actions List of existing actions.
|
||||
* @param string $pluginFile The plugin file.
|
||||
* @return array List of action links.
|
||||
*/
|
||||
abstract public function pluginActionLinks( $actions, $pluginFile = '' );
|
||||
|
||||
/**
|
||||
* Parses the action links.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param array $actions The actions.
|
||||
* @param string $pluginFile The plugin file.
|
||||
* @param array $actionLinks The action links.
|
||||
* @param string $position The position.
|
||||
* @return array The parsed actions.
|
||||
*/
|
||||
protected function parseActionLinks( $actions, $pluginFile, $actionLinks = [], $position = 'after' ) {
|
||||
if ( empty( $this->plugin ) ) {
|
||||
$this->plugin = AIOSEO_PLUGIN_BASENAME;
|
||||
}
|
||||
|
||||
if ( $this->plugin === $pluginFile && ! empty( $actionLinks ) ) {
|
||||
foreach ( $actionLinks as $key => $value ) {
|
||||
$link = [
|
||||
$key => sprintf(
|
||||
'<a href="%1$s" %2$s target="_blank">%3$s</a>',
|
||||
esc_url( $value['url'] ),
|
||||
isset( $value['title'] ) ? 'title="' . esc_attr( $value['title'] ) . '"' : '',
|
||||
$value['label']
|
||||
)
|
||||
];
|
||||
|
||||
$actions = 'after' === $position ? array_merge( $actions, $link ) : array_merge( $link, $actions );
|
||||
}
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our routes to this plugins allow list.
|
||||
*
|
||||
* @since 4.1.4
|
||||
*
|
||||
* @param array $allowList The original list.
|
||||
* @return array The modified list.
|
||||
*/
|
||||
public function allowRestRoutes( $allowList ) {
|
||||
return array_merge( $allowList, [
|
||||
'/aioseo/'
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the site authors cache when user is updated or registered.
|
||||
*
|
||||
* @since 4.1.8
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearAuthorsCache() {
|
||||
aioseo()->core->cache->delete( 'site_authors' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out post types that aren't really public when getPublicPostTypes() is called.
|
||||
*
|
||||
* @since 4.1.9
|
||||
*
|
||||
* @param array[object]|array[string] $postTypes The post types.
|
||||
* @return array[object]|array[string] The filtered post types.
|
||||
*/
|
||||
public function removeInvalidPublicPostTypes( $postTypes ) {
|
||||
$postTypesToRemove = [
|
||||
'fusion_element', // Avada
|
||||
'elementor_library',
|
||||
'redirect_rule', // Safe Redirect Manager
|
||||
'seedprod',
|
||||
'tcb_lightbox',
|
||||
|
||||
// Thrive Themes internal post types.
|
||||
'tva_module',
|
||||
'tvo_display',
|
||||
'tvo_capture',
|
||||
'tva_module',
|
||||
'tve_lead_1c_signup',
|
||||
'tve_form_type',
|
||||
'tvd_login_edit',
|
||||
'tve_global_cond_set',
|
||||
'tve_cond_display',
|
||||
'tve_lead_2s_lightbox',
|
||||
'tcb_symbol',
|
||||
'td_nm_notification',
|
||||
'tvd_content_set',
|
||||
'tve_saved_lp',
|
||||
'tve_notifications',
|
||||
'tve_user_template',
|
||||
'tve_video_data',
|
||||
'tva_course_type',
|
||||
'tva-acc-restriction',
|
||||
'tva_course_overview',
|
||||
'tve_ult_schedule',
|
||||
'tqb_optin',
|
||||
'tqb_splash',
|
||||
'tva_certificate',
|
||||
'tva_course_overview',
|
||||
|
||||
// BuddyPress post types.
|
||||
BuddyPressIntegration::getEmailCptSlug()
|
||||
];
|
||||
|
||||
foreach ( $postTypes as $index => $postType ) {
|
||||
if ( is_string( $postType ) && in_array( $postType, $postTypesToRemove, true ) ) {
|
||||
unset( $postTypes[ $index ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_array( $postType ) && in_array( $postType['name'], $postTypesToRemove, true ) ) {
|
||||
unset( $postTypes[ $index ] );
|
||||
}
|
||||
}
|
||||
|
||||
return array_values( $postTypes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out taxonomies that aren't really public when getPublicTaxonomies() is called.
|
||||
*
|
||||
* @since 4.2.4
|
||||
*
|
||||
* @param array[object]|array[string] $taxonomies The taxonomies.
|
||||
* @return array[object]|array[string] The filtered taxonomies.
|
||||
*/
|
||||
public function removeInvalidPublicTaxonomies( $taxonomies ) {
|
||||
$taxonomiesToRemove = [
|
||||
'fusion_tb_category',
|
||||
'element_category',
|
||||
'template_category',
|
||||
|
||||
// Thrive Themes internal taxonomies.
|
||||
'tcb_symbols_tax'
|
||||
];
|
||||
|
||||
foreach ( $taxonomies as $index => $taxonomy ) {
|
||||
if ( is_string( $taxonomy ) && in_array( $taxonomy, $taxonomiesToRemove, true ) ) {
|
||||
unset( $taxonomies[ $index ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_array( $taxonomy ) && in_array( $taxonomy['name'], $taxonomiesToRemove, true ) ) {
|
||||
unset( $taxonomies[ $index ] );
|
||||
}
|
||||
}
|
||||
|
||||
return array_values( $taxonomies );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Jetpack sitemaps module.
|
||||
*
|
||||
* @since 4.2.2
|
||||
*/
|
||||
public function disableJetpackSitemaps( $active ) {
|
||||
unset( $active['sitemaps'] );
|
||||
|
||||
return $active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues third-party scripts from the other plugins or themes that crashes our menu pages.
|
||||
*
|
||||
* @since 4.1.9
|
||||
* @version 4.3.1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dequeueThirdPartyAssets() {
|
||||
// TagDiv Opt-in Builder plugin.
|
||||
wp_dequeue_script( 'tds_js_vue_files_last' );
|
||||
|
||||
// MyListing theme.
|
||||
if ( function_exists( 'mylisting' ) ) {
|
||||
wp_dequeue_script( 'vuejs' );
|
||||
wp_dequeue_script( 'theme-script-vendor' );
|
||||
wp_dequeue_script( 'theme-script-main' );
|
||||
}
|
||||
|
||||
// Voxel theme.
|
||||
if ( class_exists( '\Voxel\Controllers\Assets_Controller' ) ) {
|
||||
wp_dequeue_script( 'vue' );
|
||||
wp_dequeue_script( 'vx:backend.js' );
|
||||
}
|
||||
|
||||
// Meta tags for seo plugin.
|
||||
if ( class_exists( '\Pagup\MetaTags\Settings' ) ) {
|
||||
wp_dequeue_script( 'pmt__vuejs' );
|
||||
wp_dequeue_script( 'pmt__script' );
|
||||
}
|
||||
|
||||
// Plugin: Wpbingo Core (By TungHV).
|
||||
if ( strpos( wp_styles()->query( 'bwp-lookbook-css' )->src ?? '', 'wpbingo' ) !== false ) {
|
||||
wp_dequeue_style( 'bwp-lookbook-css' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues third-party scripts from the other plugins or themes that crashes our menu pages.
|
||||
*
|
||||
* @version 4.3.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dequeueThirdPartyAssetsEarly() {
|
||||
// Disables scripts for plugins StmMotorsExtends and StmPostType.
|
||||
if ( class_exists( 'STM_Metaboxes' ) ) {
|
||||
remove_action( 'admin_enqueue_scripts', [ 'STM_Metaboxes', 'wpcfto_scripts' ] );
|
||||
}
|
||||
|
||||
// Disables scripts for LearnPress plugin.
|
||||
if ( function_exists( 'learn_press_admin_assets' ) ) {
|
||||
remove_action( 'admin_enqueue_scripts', [ learn_press_admin_assets(), 'load_scripts' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the duplicate meta description tag from the Hello Elementor theme.
|
||||
*
|
||||
* @since 4.4.3
|
||||
*
|
||||
* @link https://developers.elementor.com/docs/hello-elementor-theme/hello_elementor_add_description_meta_tag/
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeHelloElementorDescriptionTag() {
|
||||
remove_action( 'wp_head', 'hello_elementor_add_description_meta_tag' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Avada OG tags.
|
||||
*
|
||||
* @since 4.6.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAvadaOgTags() {
|
||||
if ( function_exists( 'Avada' ) ) {
|
||||
$avada = Avada();
|
||||
if ( is_object( $avada->head ?? null ) ) {
|
||||
remove_action( 'wp_head', [ $avada->head, 'insert_og_meta' ], 5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent WP-Optimize from deleting our tables.
|
||||
*
|
||||
* @since 4.4.5
|
||||
*
|
||||
* @param array $tables List of tables.
|
||||
* @return array Filtered tables.
|
||||
*/
|
||||
public function wpOptimizeAioseoTables( $tables ) {
|
||||
foreach ( $tables as &$table ) {
|
||||
if (
|
||||
is_object( $table ) &&
|
||||
property_exists( $table, 'Name' ) &&
|
||||
false !== stripos( $table->Name, 'aioseo_' )
|
||||
) {
|
||||
$table->is_using = true;
|
||||
$table->can_be_removed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Meta;
|
||||
|
||||
/**
|
||||
* Outputs anything we need to the head of the site.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Head {
|
||||
/**
|
||||
* The page title.
|
||||
*
|
||||
* @since 4.0.5
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $pageTitle = null;
|
||||
|
||||
/**
|
||||
* Title class instance.
|
||||
*
|
||||
* @since 4.3.9
|
||||
*
|
||||
* @var Title
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* Links class instance.
|
||||
*
|
||||
* @since 4.2.7
|
||||
*
|
||||
* @var Meta\Links
|
||||
*/
|
||||
protected $links = null;
|
||||
|
||||
/**
|
||||
* Keywords class instance.
|
||||
*
|
||||
* @since 4.2.7
|
||||
*
|
||||
* @var Meta\Keywords
|
||||
*/
|
||||
protected $keywords = null;
|
||||
|
||||
/**
|
||||
* Verification class instance.
|
||||
*
|
||||
* @since 4.2.7
|
||||
*
|
||||
* @var Meta\SiteVerification
|
||||
*/
|
||||
protected $verification = null;
|
||||
|
||||
/**
|
||||
* The views to output.
|
||||
*
|
||||
* @since 4.2.7
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $views = [];
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp', [ $this, 'registerTitleHooks' ], 1000 );
|
||||
add_action( 'wp_head', [ $this, 'wpHead' ], 1 );
|
||||
|
||||
$this->title = new Title();
|
||||
$this->links = new Meta\Links();
|
||||
$this->keywords = new Meta\Keywords();
|
||||
$this->verification = new Meta\SiteVerification();
|
||||
$this->views = [
|
||||
'meta' => AIOSEO_DIR . '/app/Common/Views/main/meta.php',
|
||||
'social' => AIOSEO_DIR . '/app/Common/Views/main/social.php',
|
||||
'schema' => AIOSEO_DIR . '/app/Common/Views/main/schema.php',
|
||||
'clarity' => AIOSEO_DIR . '/app/Common/Views/main/clarity.php'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers our title hooks.
|
||||
*
|
||||
* @since 4.0.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerTitleHooks() {
|
||||
if ( apply_filters( 'aioseo_disable', false ) || apply_filters( 'aioseo_disable_title_rewrites', false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'pre_get_document_title', [ $this, 'getTitle' ], 99999 );
|
||||
add_filter( 'wp_title', [ $this, 'getTitle' ], 99999 );
|
||||
if ( ! current_theme_supports( 'title-tag' ) ) {
|
||||
add_action( 'template_redirect', [ $this->title, 'startOutputBuffering' ], 99999 );
|
||||
add_action( 'wp_head', [ $this->title, 'endOutputBuffering' ], 99999 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the head.
|
||||
*
|
||||
* @since 4.0.5
|
||||
* @version 4.6.1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wpHead() {
|
||||
$included = new Meta\Included();
|
||||
if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ! $included->isIncluded() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page title.
|
||||
*
|
||||
* @since 4.0.5
|
||||
*
|
||||
* @param string $wpTitle The original page title from WordPress.
|
||||
* @return string $pageTitle The page title.
|
||||
*/
|
||||
public function getTitle( $wpTitle = '' ) {
|
||||
if ( null !== self::$pageTitle ) {
|
||||
return self::$pageTitle;
|
||||
}
|
||||
self::$pageTitle = aioseo()->meta->title->filterPageTitle( $wpTitle );
|
||||
|
||||
return self::$pageTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* The output function itself.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function output() {
|
||||
remove_action( 'wp_head', 'rel_canonical' );
|
||||
|
||||
$views = apply_filters( 'aioseo_meta_views', $this->views );
|
||||
if ( empty( $views ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo "\n\t\t<!-- " . sprintf(
|
||||
'%1$s %2$s',
|
||||
esc_html( AIOSEO_PLUGIN_NAME ),
|
||||
aioseo()->helpers->getAioseoVersion() // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
) . " - aioseo.com -->\n";
|
||||
|
||||
foreach ( $views as $view ) {
|
||||
require $view;
|
||||
}
|
||||
|
||||
echo "\t\t<!-- " . esc_html( AIOSEO_PLUGIN_NAME ) . " -->\n\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Models;
|
||||
|
||||
/**
|
||||
* Abstract class that Pro and Lite both extend.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Main {
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
new Media();
|
||||
new QueryArgs();
|
||||
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueueTranslations' ] );
|
||||
add_action( 'wp_enqueue_scripts', [ $this, 'enqueueFrontEndAssets' ] );
|
||||
add_action( 'admin_footer', [ $this, 'adminFooter' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the translations seperately so it can be called from anywhere.
|
||||
*
|
||||
* @since 4.1.9
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueueTranslations() {
|
||||
aioseo()->core->assets->load( 'src/vue/standalone/app/main.js', [], [
|
||||
'translations' => aioseo()->helpers->getJedLocaleData( 'all-in-one-seo-pack' )
|
||||
], 'aioseoTranslations' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles on the front-end.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueueFrontEndAssets() {
|
||||
$canManageSeo = apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' );
|
||||
if (
|
||||
! aioseo()->helpers->isAdminBarEnabled() ||
|
||||
! ( current_user_can( $canManageSeo ) || aioseo()->access->canManage() )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
aioseo()->core->assets->enqueueCss( 'src/vue/assets/scss/app/admin-bar.scss' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the footer file to let vue attach.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function adminFooter() {
|
||||
echo '<div id="aioseo-admin"></div>';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Media class.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Media {
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'template_redirect', [ $this, 'attachmentRedirect' ], 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user wants to redirect attachment pages, this is where we do it.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function attachmentRedirect() {
|
||||
if ( ! is_attachment() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
! aioseo()->dynamicOptions->searchAppearance->postTypes->has( 'attachment' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$redirect = aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls;
|
||||
if ( 'disabled' === $redirect ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'attachment' === $redirect ) {
|
||||
$url = wp_get_attachment_url( get_queried_object_id() );
|
||||
if ( empty( $url ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return wp_safe_redirect( $url, 301, AIOSEO_PLUGIN_SHORT_NAME );
|
||||
}
|
||||
|
||||
global $post;
|
||||
if ( ! empty( $post->post_parent ) ) {
|
||||
wp_safe_redirect( urldecode( get_permalink( $post->post_parent ) ), 301 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class contains pre-updates necessary for the next updates class to run.
|
||||
*
|
||||
* @since 4.1.5
|
||||
*/
|
||||
class PreUpdates {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public function __construct() {
|
||||
// We don't want an AJAX request check here since the plugin might be installed/activated for the first time via AJAX (e.g. EDD/BLC).
|
||||
// If that's the case, the cache table needs to be created before the activation hook runs.
|
||||
if ( wp_doing_cron() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lastActiveVersion = aioseo()->internalOptions->internal->lastActiveVersion;
|
||||
if ( aioseo()->version !== $lastActiveVersion ) {
|
||||
// Bust the table/columns cache so that we can start the update migrations with a fresh slate.
|
||||
aioseo()->internalOptions->database->installedTables = '';
|
||||
}
|
||||
|
||||
if ( version_compare( $lastActiveVersion, '4.1.5', '<' ) ) {
|
||||
$this->createCacheTable();
|
||||
}
|
||||
|
||||
if ( version_compare( $lastActiveVersion, AIOSEO_VERSION, '<' ) ) {
|
||||
aioseo()->core->cache->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new aioseo_cache table.
|
||||
*
|
||||
* @since 4.1.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createCacheTable() {
|
||||
$db = aioseo()->core->db->db;
|
||||
$charsetCollate = '';
|
||||
|
||||
if ( ! empty( $db->charset ) ) {
|
||||
$charsetCollate .= "DEFAULT CHARACTER SET {$db->charset}";
|
||||
}
|
||||
if ( ! empty( $db->collate ) ) {
|
||||
$charsetCollate .= " COLLATE {$db->collate}";
|
||||
}
|
||||
|
||||
$tableName = aioseo()->core->cache->getTableName();
|
||||
if ( ! aioseo()->core->db->tableExists( $tableName ) ) {
|
||||
$tableName = $db->prefix . $tableName;
|
||||
|
||||
aioseo()->core->db->execute(
|
||||
"CREATE TABLE {$tableName} (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`key` varchar(80) NOT NULL,
|
||||
`value` longtext NOT NULL,
|
||||
`expiration` datetime NULL,
|
||||
`created` datetime NOT NULL,
|
||||
`updated` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY ndx_aioseo_cache_key (`key`),
|
||||
KEY ndx_aioseo_cache_expiration (`expiration`)
|
||||
) {$charsetCollate};"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Models\CrawlCleanupLog;
|
||||
use AIOSEO\Plugin\Common\Models\CrawlCleanupBlockedArg;
|
||||
|
||||
/**
|
||||
* Query arguments class.
|
||||
*
|
||||
* @since 4.2.1
|
||||
* @version 4.5.8
|
||||
*/
|
||||
class QueryArgs {
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public function __construct() {
|
||||
if (
|
||||
is_admin() ||
|
||||
aioseo()->helpers->isWpLoginPage() ||
|
||||
aioseo()->helpers->isAjaxCronRestRequest() ||
|
||||
aioseo()->helpers->isDoingWpCli()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'template_redirect', [ $this, 'maybeRemoveQueryArgs' ], 1 );
|
||||
|
||||
$this->removeReplyToCom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we can remove query args.
|
||||
*
|
||||
* @since 4.5.8
|
||||
*
|
||||
* @return boolean True if the query args can be removed.
|
||||
*/
|
||||
private function canRemoveQueryArgs() {
|
||||
if (
|
||||
! aioseo()->options->searchAppearance->advanced->blockArgs->enable ||
|
||||
is_user_logged_in() ||
|
||||
is_admin() ||
|
||||
is_robots() ||
|
||||
get_query_var( 'aiosp_sitemap_path' ) ||
|
||||
empty( $_GET ) // phpcs:ignore HM.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Recommended
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( is_singular() ) {
|
||||
global $post;
|
||||
$thePost = aioseo()->helpers->getPost( $post->ID );
|
||||
|
||||
// Leave the preview query arguments intact.
|
||||
if (
|
||||
// phpcs:disable phpcs:ignore HM.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Recommended
|
||||
isset( $_GET['preview'] ) &&
|
||||
isset( $_GET['preview_nonce'] ) &&
|
||||
// phpcs:enable
|
||||
wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['preview_nonce'] ) ), 'post_preview_' . $thePost->ID ) &&
|
||||
current_user_can( 'edit_post', $thePost->ID )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe remove query args.
|
||||
*
|
||||
* @since 4.5.8
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybeRemoveQueryArgs() {
|
||||
if ( ! $this->canRemoveQueryArgs() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentRequest = aioseo()->helpers->getRequestUrl();
|
||||
|
||||
// Remove the home path from the url for subfolder installs.
|
||||
$currentRequest = aioseo()->helpers->excludeHomePath( $currentRequest );
|
||||
$currentRequestParsed = wp_parse_url( $currentRequest );
|
||||
|
||||
// No query args? Never mind!
|
||||
if ( empty( $currentRequestParsed['query'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
parse_str( $currentRequestParsed['query'], $currentRequestQueryArgs );
|
||||
$notAllowed = [];
|
||||
$recognizedQueryLogs = [];
|
||||
|
||||
foreach ( $currentRequestQueryArgs as $key => $value ) {
|
||||
if ( ! is_string( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
$this->addQueryLog( $currentRequestParsed['path'], $key, $value );
|
||||
|
||||
$blocked = CrawlCleanupBlockedArg::getByKeyValue( $key, null );
|
||||
if ( ! $blocked->exists() ) {
|
||||
$blocked = CrawlCleanupBlockedArg::getByKeyValue( $key, $value );
|
||||
}
|
||||
|
||||
if ( ! $blocked->exists() ) {
|
||||
$blocked = CrawlCleanupBlockedArg::matchRegex( $key, $value );
|
||||
}
|
||||
|
||||
if ( $blocked->exists() ) {
|
||||
$queryArg = $key . ( $value ? '=' . $value : null );
|
||||
$notAllowed[] = $queryArg;
|
||||
$blocked->addHit();
|
||||
continue;
|
||||
}
|
||||
|
||||
$recognizedQueryLogs[ $key ] = empty( $value ) ? true : $value;
|
||||
}
|
||||
|
||||
if ( ! empty( $notAllowed ) ) {
|
||||
$newUrl = home_url( $currentRequestParsed['path'] );
|
||||
|
||||
header( 'Content-Type: redirect', true );
|
||||
header_remove( 'Content-Type' );
|
||||
header_remove( 'Last-Modified' );
|
||||
header_remove( 'X-Pingback' );
|
||||
|
||||
wp_safe_redirect( add_query_arg( $recognizedQueryLogs, $newUrl ), 301, AIOSEO_PLUGIN_SHORT_NAME . ' Crawl Cleanup' );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove ?replytocom.
|
||||
*
|
||||
* @since 4.5.8
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeReplyToCom() {
|
||||
if ( ! apply_filters( 'aioseo_remove_reply_to_com', true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'comment_reply_link', [ $this, 'removeReplyToComLink' ] );
|
||||
add_action( 'template_redirect', [ $this, 'replyToComRedirect' ], 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove ?replytocom.
|
||||
*
|
||||
* @since 4.7.3
|
||||
*
|
||||
* @param string $link The comment link as a string.
|
||||
* @return string The modified link.
|
||||
*/
|
||||
public function removeReplyToComLink( $link ) {
|
||||
return preg_replace( '`href=(["\'])(?:.*(?:\?|&|&)replytocom=(\d+)#respond)`', 'href=$1#comment-$2', (string) $link );
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects out the ?replytocom variables.
|
||||
*
|
||||
* @since 4.7.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function replyToComRedirect() {
|
||||
$replyToCom = absint( wp_unslash( $_GET['replytocom'] ?? null ) ); // phpcs:ignore HM.Security.NonceVerification.Recommended
|
||||
if ( ! empty( $replyToCom ) && is_singular() ) {
|
||||
$url = get_permalink( $GLOBALS['post']->ID );
|
||||
if ( isset( $_SERVER['QUERY_STRING'] ) ) {
|
||||
$queryString = remove_query_arg( 'replytocom', sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) );
|
||||
if ( ! empty( $queryString ) ) {
|
||||
$url = add_query_arg( [], $url ) . '?' . $queryString;
|
||||
}
|
||||
}
|
||||
$url = add_query_arg( [], $url ) . '#comment-' . $replyToCom;
|
||||
|
||||
wp_safe_redirect( $url, 301, AIOSEO_PLUGIN_SHORT_NAME );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add query args log.
|
||||
*
|
||||
* @since 4.5.8
|
||||
*
|
||||
* @param string $path A String of the path to create a slug.
|
||||
* @param string $key A String of key from query arg.
|
||||
* @param string $value A String of value from query arg.
|
||||
* @return void
|
||||
*/
|
||||
private function addQueryLog( $path, $key, $value = null ) {
|
||||
$slug = $path . '?' . $key . ( 0 < strlen( $value ) ? '=' . $value : '' );
|
||||
$log = CrawlCleanupLog::getBySlug( $slug );
|
||||
|
||||
$data = [
|
||||
'slug' => $slug,
|
||||
'key' => $key,
|
||||
'value' => $value
|
||||
];
|
||||
|
||||
$log->set( $data );
|
||||
$log->create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document Title class.
|
||||
*
|
||||
* @since 4.3.9
|
||||
*/
|
||||
class Title {
|
||||
/**
|
||||
* Keeps the buffer level.
|
||||
*
|
||||
* @since 4.3.9
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $bufferLevel = 0;
|
||||
|
||||
/**
|
||||
* Starts the output buffering.
|
||||
*
|
||||
* @since 4.3.2
|
||||
* @version 4.3.9
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function startOutputBuffering() {
|
||||
ob_start();
|
||||
|
||||
$this->bufferLevel = ob_get_level();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the output buffering.
|
||||
*
|
||||
* @since 4.3.2
|
||||
* @version 4.3.9
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function endOutputBuffering() {
|
||||
// Bail if our code didn't start the output buffering at all.
|
||||
if ( 0 === $this->bufferLevel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case the current buffer level is different from the one we kept earlier, then: either a plugin started a new buffer or ended our buffer earlier.
|
||||
* If that's the case, we can't properly rewrite the document title anymore since we don't know what buffer content we'd parse below.
|
||||
* In order to avoid conflicts/errors (blank/broken pages), we just bail.
|
||||
* If we bail, the page won't have the title set by AIOSEO, but this can be fixed if the active theme starts supporting the "title-tag" feature {@link https://codex.wordpress.org/Title_Tag}.
|
||||
*/
|
||||
if ( ob_get_level() !== $this->bufferLevel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $this->rewriteTitle( (string) ob_get_clean() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the page document title.
|
||||
*
|
||||
* @since 4.0.5
|
||||
* @version 4.3.2
|
||||
* @version 4.3.9
|
||||
*
|
||||
* @param string $content The buffer content.
|
||||
* @return string The rewritten title.
|
||||
*/
|
||||
private function rewriteTitle( $content ) {
|
||||
if ( strpos( $content, '<!-- All in One SEO' ) === false ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Remove all existing title tags.
|
||||
$content = preg_replace( '#<title.*?/title>#s', '', (string) $content );
|
||||
$pageTitle = aioseo()->helpers->escapeRegexReplacement( aioseo()->head->getTitle() );
|
||||
|
||||
// Return new output with our new title tag included in our own comment block.
|
||||
return preg_replace( '/(<!--\sAll\sin\sOne\sSEO[a-z0-9\s.]+\s-\saioseo\.com\s-->)/i', "$1\r\n\t\t<title>$pageTitle</title>", (string) $content, 1 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Main;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Utils;
|
||||
|
||||
/**
|
||||
* Handles plugin deinstallation.
|
||||
*
|
||||
* @since 4.8.1
|
||||
*/
|
||||
class Uninstall {
|
||||
/**
|
||||
* Removes all data.
|
||||
*
|
||||
* @since 4.8.1
|
||||
*
|
||||
* @param bool $force Whether we should ignore the uninstall option or not. We ignore it when we reset all data via the Debug Panel.
|
||||
* @return void
|
||||
*/
|
||||
public function dropData( $force = false ) {
|
||||
// Don't call `aioseo()->options` as it's not loaded during uninstall.
|
||||
$aioseoOptions = get_option( 'aioseo_options', '' );
|
||||
$aioseoOptions = json_decode( $aioseoOptions, true );
|
||||
|
||||
// Confirm that user has decided to remove all data, otherwise stop.
|
||||
if (
|
||||
! $force &&
|
||||
empty( $aioseoOptions['advanced']['uninstall'] )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Drop our custom tables.
|
||||
$this->uninstallDb();
|
||||
|
||||
// Delete all our custom capabilities.
|
||||
$this->uninstallCapabilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all our tables and options.
|
||||
*
|
||||
* @since 4.2.3
|
||||
* @version 4.8.1 Moved from Core to Uninstall.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function uninstallDb() {
|
||||
// Delete all our custom tables.
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
foreach ( aioseo()->core->getDbTables() as $tableName ) {
|
||||
$wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $tableName ) );
|
||||
}
|
||||
|
||||
// Delete all AIOSEO Locations and Location Categories.
|
||||
$wpdb->delete( $wpdb->posts, [ 'post_type' => 'aioseo-location' ], [ '%s' ] );
|
||||
$wpdb->delete( $wpdb->term_taxonomy, [ 'taxonomy' => 'aioseo-location-category' ], [ '%s' ] );
|
||||
|
||||
// Delete all the plugin settings.
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", 'aioseo\_%' ) );
|
||||
|
||||
// Remove any transients we've left behind.
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '\_aioseo\_%' ) );
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", 'aioseo\_%' ) );
|
||||
|
||||
// Delete all entries from the action scheduler table.
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}actionscheduler_actions WHERE hook LIKE %s", 'aioseo\_%' ) );
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}actionscheduler_groups WHERE slug = %s", 'aioseo' ) );
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all our custom capabilities.
|
||||
*
|
||||
* @since 4.8.1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function uninstallCapabilities() {
|
||||
$access = new Utils\Access();
|
||||
$customCapabilities = $access->getCapabilityList() ?? [];
|
||||
$roles = aioseo()->helpers->getUserRoles();
|
||||
|
||||
// Loop through roles and remove custom capabilities.
|
||||
foreach ( $roles as $roleName => $roleInfo ) {
|
||||
$role = get_role( $roleName );
|
||||
|
||||
if ( $role ) {
|
||||
$role->remove_cap( 'aioseo_admin' );
|
||||
$role->remove_cap( 'aioseo_manage_seo' );
|
||||
|
||||
foreach ( $customCapabilities as $capability ) {
|
||||
$role->remove_cap( $capability );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove_role( 'aioseo_manager' );
|
||||
remove_role( 'aioseo_editor' );
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user