| Current Path : /home/x/b/o/xbodynamge/namtation/wp-content/ |
| Current File : /home/x/b/o/xbodynamge/namtation/wp-content/Notices.tar |
Notices.php 0000666 00000041164 15113513353 0006673 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// 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 Notices {
/**
* Source of notifications content.
*
* @since 4.0.0
*
* @var string
*/
private $url = 'https://plugin-cdn.aioseo.com/wp-content/notifications.json';
/**
* Review class instance.
*
* @since 4.2.7
*
* @var Review
*/
private $review = null;
/**
* Migration class instance.
*
* @since 4.2.7
*
* @var Migration
*/
private $migration = null;
/**
* Import class instance.
*
* @since 4.2.7
*
* @var Import
*/
private $import = null;
/**
* DeprecatedWordPress class instance.
*
* @since 4.2.7
*
* @var DeprecatedWordPress
*/
private $deprecatedWordPress = null;
/**
* ConflictingPlugins class instance.
*
* @since 4.5.1
*
* @var ConflictingPlugins
*/
private $conflictingPlugins = null;
/**
* Class Constructor.
*
* @since 4.0.0
*/
public function __construct() {
add_action( 'aioseo_admin_notifications_update', [ $this, 'update' ] );
if ( ! is_admin() ) {
return;
}
add_action( 'updated_option', [ $this, 'maybeResetBlogVisibility' ], 10, 3 );
add_action( 'init', [ $this, 'init' ], 2 );
$this->review = new Review();
$this->migration = new Migration();
$this->import = new Import();
$this->deprecatedWordPress = new DeprecatedWordPress();
$this->conflictingPlugins = new ConflictingPlugins();
add_action( 'admin_notices', [ $this, 'notices' ] );
}
/**
* Initialize notifications.
*
* @since 4.0.0
*
* @return void
*/
public function init() {
// If our tables do not exist, create them now.
if ( ! aioseo()->core->db->tableExists( 'aioseo_notifications' ) ) {
aioseo()->updates->addInitialCustomTablesForV4();
}
$this->maybeUpdate();
$this->initInternalNotices();
$this->deleteInternalNotices();
}
/**
* Checks if we should update our notifications.
*
* @since 4.0.0
*
* @return void
*/
private function maybeUpdate() {
$nextRun = aioseo()->core->networkCache->get( 'admin_notifications_update' );
if ( null !== $nextRun && time() < $nextRun ) {
return;
}
// Schedule the action.
aioseo()->actionScheduler->scheduleAsync( 'aioseo_admin_notifications_update' );
// Update the cache.
aioseo()->core->networkCache->update( 'admin_notifications_update', time() + DAY_IN_SECONDS );
}
/**
* Update Notifications from the server.
*
* @since 4.0.0
*
* @return void
*/
public function update() {
$notifications = $this->fetch();
foreach ( $notifications as $notification ) {
// First, let's check to see if this notification already exists. If so, we want to override it.
$n = aioseo()->core->db
->start( 'aioseo_notifications' )
->where( 'notification_id', $notification->id )
->run()
->model( 'AIOSEO\\Plugin\\Common\\Models\\Notification' );
$buttons = [
'button1' => [
'label' => ! empty( $notification->btns->main->text ) ? $notification->btns->main->text : null,
'url' => ! empty( $notification->btns->main->url ) ? $notification->btns->main->url : null
],
'button2' => [
'label' => ! empty( $notification->btns->alt->text ) ? $notification->btns->alt->text : null,
'url' => ! empty( $notification->btns->alt->url ) ? $notification->btns->alt->url : null
]
];
if ( $n->exists() ) {
$n->title = $notification->title;
$n->content = $notification->content;
$n->type = ! empty( $notification->notification_type ) ? $notification->notification_type : 'info';
$n->level = $notification->type;
$n->notification_id = $notification->id;
$n->start = ! empty( $notification->start ) ? $notification->start : null;
$n->end = ! empty( $notification->end ) ? $notification->end : null;
$n->button1_label = $buttons['button1']['label'];
$n->button1_action = $buttons['button1']['url'];
$n->button2_label = $buttons['button2']['label'];
$n->button2_action = $buttons['button2']['url'];
$n->save();
continue;
}
$n = new Models\Notification();
$n->slug = uniqid();
$n->title = $notification->title;
$n->content = $notification->content;
$n->type = ! empty( $notification->notification_type ) ? $notification->notification_type : 'info';
$n->level = $notification->type;
$n->notification_id = $notification->id;
$n->start = ! empty( $notification->start ) ? $notification->start : null;
$n->end = ! empty( $notification->end ) ? $notification->end : null;
$n->button1_label = $buttons['button1']['label'];
$n->button1_action = $buttons['button1']['url'];
$n->button2_label = $buttons['button2']['label'];
$n->button2_action = $buttons['button2']['url'];
$n->dismissed = 0;
$n->save();
// Since we've added a new remote notification, let's show the notification drawer.
aioseo()->core->cache->update( 'show_notifications_drawer', true );
}
}
/**
* Fetches the feed of notifications.
*
* @since 4.0.0
*
* @return array An array of notifications.
*/
private function fetch() {
$response = aioseo()->helpers->wpRemoteGet( $this->getUrl() );
if ( is_wp_error( $response ) ) {
return [];
}
$body = wp_remote_retrieve_body( $response );
if ( empty( $body ) ) {
return [];
}
return $this->verify( json_decode( $body ) );
}
/**
* Verify notification data before it is saved.
*
* @since 4.0.0
*
* @param array $notifications Array of notifications items to verify.
* @return array An array of verified notifications.
*/
private function verify( $notifications ) {
$data = [];
if ( ! is_array( $notifications ) || empty( $notifications ) ) {
return $data;
}
foreach ( $notifications as $notification ) {
// The message and license should never be empty, if they are, ignore.
if ( empty( $notification->content ) || empty( $notification->type ) ) {
continue;
}
if ( ! is_array( $notification->type ) ) {
$notification->type = [ $notification->type ];
}
foreach ( $notification->type as $type ) {
// Ignore if type does not match.
if ( ! $this->validateType( $type ) ) {
continue 2;
}
}
// Ignore if expired.
if ( ! empty( $notification->end ) && time() > strtotime( $notification->end ) ) {
continue;
}
// Ignore if notification existed before installing AIOSEO.
// Prevents bombarding the user with notifications after activation.
$activated = aioseo()->internalOptions->internal->firstActivated( time() );
if (
! empty( $notification->start ) &&
$activated > strtotime( $notification->start )
) {
continue;
}
$data[] = $notification;
}
return $data;
}
/**
* Validates the notification type.
*
* @since 4.0.0
*
* @param string $type The notification type we are targeting.
* @return boolean True if yes, false if no.
*/
public function validateType( $type ) {
$validated = false;
if ( 'all' === $type ) {
$validated = true;
}
// Store notice if version matches.
if ( $this->versionMatch( aioseo()->version, $type ) ) {
$validated = true;
}
return $validated;
}
/**
* Version Compare.
*
* @since 4.0.0
*
* @param string $currentVersion The current version being used.
* @param string|array $compareVersion The version to compare with.
* @return bool True if we match, false if not.
*/
public function versionMatch( $currentVersion, $compareVersion ) {
if ( is_array( $compareVersion ) ) {
foreach ( $compareVersion as $compare_single ) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName
$recursiveResult = $this->versionMatch( $currentVersion, $compare_single ); // phpcs:ignore Squiz.NamingConventions.ValidVariableName
if ( $recursiveResult ) {
return true;
}
}
return false;
}
$currentParse = explode( '.', $currentVersion );
if ( strpos( $compareVersion, '-' ) ) {
$compareParse = explode( '-', $compareVersion );
} elseif ( strpos( $compareVersion, '.' ) ) {
$compareParse = explode( '.', $compareVersion );
} else {
return false;
}
$currentCount = count( $currentParse );
$compareCount = count( $compareParse );
for ( $i = 0; $i < $currentCount || $i < $compareCount; $i++ ) {
if ( isset( $compareParse[ $i ] ) && 'x' === strtolower( $compareParse[ $i ] ) ) {
unset( $compareParse[ $i ] );
}
if ( ! isset( $currentParse[ $i ] ) ) {
unset( $compareParse[ $i ] );
} elseif ( ! isset( $compareParse[ $i ] ) ) {
unset( $currentParse[ $i ] );
}
}
foreach ( $compareParse as $index => $subNumber ) {
if ( $currentParse[ $index ] !== $subNumber ) {
return false;
}
}
return true;
}
/**
* Gets the URL for the notifications api.
*
* @since 4.0.0
*
* @return string The URL to use for the api requests.
*/
private function getUrl() {
if ( defined( 'AIOSEO_NOTIFICATIONS_URL' ) ) {
return AIOSEO_NOTIFICATIONS_URL;
}
return $this->url;
}
/**
* Add notices.
*
* @since 4.0.0
*
* @return void
*/
public function notices() {
// Double check we're actually in the admin before outputting anything.
if ( ! is_admin() ) {
return;
}
$this->review->maybeShowNotice();
$this->migration->maybeShowNotice();
$this->import->maybeShowNotice();
$this->deprecatedWordPress->maybeShowNotice();
$this->conflictingPlugins->maybeShowNotice();
}
/**
* Initialize the internal notices.
*
* @since 4.0.0
*
* @return void
*/
protected function initInternalNotices() {
$this->blogVisibility();
$this->descriptionFormat();
}
/**
* Deletes internal notices we no longer need.
*
* @since 4.0.0
*
* @return void
*/
protected function deleteInternalNotices() {
$pluginData = aioseo()->helpers->getPluginData();
if ( $pluginData['miPro']['installed'] || $pluginData['miLite']['installed'] ) {
$notification = Models\Notification::getNotificationByName( 'install-mi' );
if ( ! $notification->exists() ) {
return;
}
Models\Notification::deleteNotificationByName( 'install-mi' );
}
if ( $pluginData['optinMonster']['installed'] ) {
$notification = Models\Notification::getNotificationByName( 'install-om' );
if ( ! $notification->exists() ) {
return;
}
Models\Notification::deleteNotificationByName( 'install-om' );
}
}
/**
* Extends a notice by a (default) 1 week start date.
*
* @since 4.0.0
*
* @param string $notice The notice to extend.
* @param string $start How long to extend.
* @return void
*/
public function remindMeLater( $notice, $start = '+1 week' ) {
$notification = Models\Notification::getNotificationByName( $notice );
if ( ! $notification->exists() ) {
return;
}
$notification->start = gmdate( 'Y-m-d H:i:s', strtotime( $start ) );
$notification->save();
}
/**
* Add a notice if the blog is set to hidden.
*
* @since 4.0.0
*
* @return void
*/
private function blogVisibility() {
$notification = Models\Notification::getNotificationByName( 'blog-visibility' );
if ( get_option( 'blog_public' ) ) {
if ( $notification->exists() ) {
Models\Notification::deleteNotificationByName( 'blog-visibility' );
}
return;
}
if ( $notification->exists() || ! current_user_can( 'manage_options' ) ) {
return;
}
Models\Notification::addNotification( [
'slug' => uniqid(),
'notification_name' => 'blog-visibility',
'title' => __( 'Search Engines Blocked', 'all-in-one-seo-pack' ),
'content' => sprintf(
// Translators: 1 - The plugin short name ("AIOSEO").
__( 'Warning: %1$s has detected that you are blocking access to search engines. You can change this in Settings > Reading if this was unintended.', 'all-in-one-seo-pack' ),
AIOSEO_PLUGIN_SHORT_NAME
),
'type' => 'error',
'level' => [ 'all' ],
'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
'button1_action' => admin_url( 'options-reading.php' ),
'button2_label' => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
'button2_action' => 'http://action#notification/blog-visibility-reminder',
'start' => gmdate( 'Y-m-d H:i:s' )
] );
}
/**
* Add a notice if the description format is missing the Description tag.
*
* @since 4.0.5
*
* @return void
*/
private function descriptionFormat() {
$notification = Models\Notification::getNotificationByName( 'description-format' );
if ( ! in_array( 'descriptionFormat', aioseo()->internalOptions->deprecatedOptions, true ) ) {
if ( $notification->exists() ) {
Models\Notification::deleteNotificationByName( 'description-format' );
}
return;
}
$descriptionFormat = aioseo()->options->deprecated->searchAppearance->global->descriptionFormat;
if ( false !== strpos( $descriptionFormat, '#description' ) ) {
if ( $notification->exists() ) {
Models\Notification::deleteNotificationByName( 'description-format' );
}
return;
}
if ( $notification->exists() ) {
return;
}
Models\Notification::addNotification( [
'slug' => uniqid(),
'notification_name' => 'description-format',
'title' => __( 'Invalid Description Format', 'all-in-one-seo-pack' ),
'content' => sprintf(
// Translators: 1 - The plugin short name ("AIOSEO").
__( 'Warning: %1$s has detected that you may have an invalid description format. This could lead to descriptions not being properly applied to your content.', 'all-in-one-seo-pack' ),
AIOSEO_PLUGIN_SHORT_NAME
) . ' ' . __( 'A Description tag is required in order to properly display your meta descriptions on your site.', 'all-in-one-seo-pack' ),
'type' => 'error',
'level' => [ 'all' ],
'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
'button1_action' => 'http://route#aioseo-search-appearance&aioseo-scroll=description-format&aioseo-highlight=description-format:advanced',
'button2_label' => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
'button2_action' => 'http://action#notification/description-format-reminder',
'start' => gmdate( 'Y-m-d H:i:s' )
] );
}
/**
* Check if blog visibility is changing and add/delete the appropriate notification.
*
* @since 4.0.0
*
* @param string $optionName The name of the option we are checking.
* @param mixed $oldValue The old value.
* @param mixed $newValue The new value.
* @return void
*/
public function maybeResetBlogVisibility( $optionName, $oldValue = '', $newValue = '' ) {
if ( 'blog_public' === $optionName ) {
if ( 1 === intval( $newValue ) ) {
$notification = Models\Notification::getNotificationByName( 'blog-visibility' );
if ( ! $notification->exists() ) {
return;
}
Models\Notification::deleteNotificationByName( 'blog-visibility' );
return;
}
$this->blogVisibility();
}
}
/**
* Add a notice if the blog is set to hidden.
*
* @since 4.0.0
*
* @return void
*/
public function conflictingPlugins( $plugins = [] ) {
if ( empty( $plugins ) ) {
return;
}
$content = sprintf(
// Translators: 1 - The plugin short name ("AIOSEO").
__( 'Warning: %1$s has detected other active SEO or sitemap plugins. We recommend that you deactivate the following plugins to prevent any conflicts:', 'all-in-one-seo-pack' ),
AIOSEO_PLUGIN_SHORT_NAME
) . '<ul>';
foreach ( $plugins as $pluginName => $pluginPath ) {
$content .= '<li><strong>' . $pluginName . '</strong></li>';
}
$content .= '</ul>';
// Update an existing notice.
$notification = Models\Notification::getNotificationByName( 'conflicting-plugins' );
if ( $notification->exists() ) {
$notification->content = $content;
$notification->save();
return;
}
// Create a new one if it doesn't exist.
Models\Notification::addNotification( [
'slug' => uniqid(),
'notification_name' => 'conflicting-plugins',
'title' => __( 'Conflicting Plugins Detected', 'all-in-one-seo-pack' ),
'content' => $content,
'type' => 'error',
'level' => [ 'all' ],
'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
'button1_action' => 'http://action#sitemap/deactivate-conflicting-plugins?refresh',
'button2_label' => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
'button2_action' => 'http://action#notification/conflicting-plugins-reminder',
'start' => gmdate( 'Y-m-d H:i:s' )
] );
}
} DeprecatedWordPress.php 0000666 00000011266 15114633066 0011205 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WordPress Deprecated Notice.
*
* @since 4.1.2
*/
class DeprecatedWordPress {
/**
* Class Constructor.
*
* @since 4.1.2
*/
public function __construct() {
add_action( 'wp_ajax_aioseo-dismiss-deprecated-wordpress-notice', [ $this, 'dismissNotice' ] );
}
/**
* Go through all the checks to see if we should show the notice.
*
* @since 4.1.2
*
* @return void
*/
public function maybeShowNotice() {
global $wp_version; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
$dismissed = get_option( '_aioseo_deprecated_wordpress_dismissed', true );
if ( '1' === $dismissed ) {
return;
}
// Show to users that interact with our pluign.
if ( ! current_user_can( 'publish_posts' ) ) {
return;
}
// Show if WordPress version is deprecated.
if ( version_compare( $wp_version, '5.4', '>=' ) ) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName
return;
}
$this->showNotice();
// Print the script to the footer.
add_action( 'admin_footer', [ $this, 'printScript' ] );
}
/**
* Actually show the review plugin.
*
* @since 4.1.2
*
* @return void
*/
public function showNotice() {
$medium = false !== strpos( AIOSEO_PHP_VERSION_DIR, 'pro' ) ? 'proplugin' : 'liteplugin';
?>
<div class="notice notice-warning aioseo-deprecated-wordpress-notice is-dismissible">
<p>
<?php
echo wp_kses(
sprintf(
// Translators: 1 - Opening HTML bold tag, 2 - Closing HTML bold tag.
__( 'Your site is running an %1$soutdated version%2$s of WordPress. We recommend using the latest version of WordPress in order to keep your site secure.', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'<strong>',
'</strong>'
),
[
'strong' => [],
]
);
?>
<br><br>
<?php
echo wp_kses(
sprintf(
// phpcs:ignore Generic.Files.LineLength.MaxExceeded
// Translators: 1 - Opening HTML bold tag, 2 - Closing HTML bold tag, 3 - The short plugin name ("AIOSEO"), 4 - The current year, 5 - Opening HTML link tag, 6 - Closing HTML link tag.
__( '%1$sNote:%2$s %3$s will be discontinuing support for WordPress versions older than version 5.7 by the end of %4$s. %5$sRead more for additional information.%6$s', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'<strong>',
'</strong>',
'AIOSEO',
gmdate( 'Y' ),
'<a href="https://aioseo.com/docs/update-wordpress/?utm_source=WordPress&utm_medium=' . $medium . '&utm_campaign=outdated-wordpress-notice" target="_blank" rel="noopener noreferrer">', // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'</a>'
),
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
'strong' => [],
]
);
?>
</p>
</div>
<?php
// In case this is on plugin activation.
if ( isset( $_GET['activate'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Recommended
unset( $_GET['activate'] );
}
}
/**
* Print the script for dismissing the notice.
*
* @since 4.1.2
*
* @return void
*/
public function printScript() {
// Create a nonce.
$nonce = wp_create_nonce( 'aioseo-dismiss-deprecated-wordpress' );
?>
<script>
window.addEventListener('load', function () {
var dismissBtn
// Add an event listener to the dismiss button.
dismissBtn = document.querySelector('.aioseo-deprecated-wordpress-notice .notice-dismiss')
dismissBtn.addEventListener('click', function (event) {
var httpRequest = new XMLHttpRequest(),
postData = ''
// Build the data to send in our request.
postData += '&action=aioseo-dismiss-deprecated-wordpress-notice'
postData += '&nonce=<?php echo esc_html( $nonce ); ?>'
httpRequest.open('POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>')
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
httpRequest.send(postData)
})
});
</script>
<?php
}
/**
* Dismiss the deprecated WordPress notice.
*
* @since 4.1.2
*
* @return string The successful response.
*/
public function dismissNotice() {
// Early exit if we're not on a aioseo-dismiss-deprecated-wordpress-notice action.
if ( ! isset( $_POST['action'] ) || 'aioseo-dismiss-deprecated-wordpress-notice' !== $_POST['action'] ) {
return;
}
check_ajax_referer( 'aioseo-dismiss-deprecated-wordpress', 'nonce' );
update_option( '_aioseo_deprecated_wordpress_dismissed', true );
return wp_send_json_success();
}
} Import.php 0000666 00000002375 15114633066 0006547 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Plugin import notice.
*
* @since 4.0.0
*/
class Import {
/**
* Go through all the checks to see if we should show the notice.
*
* @since 4.0.0
*
* @return void
*/
public function maybeShowNotice() {
if ( ! aioseo()->importExport->isImportRunning() ) {
return;
}
$this->showNotice();
}
/**
* Register the notice so that it appears.
*
* @since 4.0.0
*
* @return void
*/
public function showNotice() {
$string1 = __( 'SEO Meta Import In Progress', 'all-in-one-seo-pack' );
// Translators: 1 - The plugin name ("All in One SEO").
$string2 = sprintf( __( '%1$s is importing your existing SEO data in the background.', 'all-in-one-seo-pack' ), AIOSEO_PLUGIN_NAME );
$string3 = __( 'This notice will automatically disappear as soon as the import has completed. Meanwhile, everything should continue to work as expected.', 'all-in-one-seo-pack' );
?>
<div class="notice notice-info aioseo-migration">
<p><strong><?php echo esc_html( $string1 ); ?></strong></p>
<p><?php echo esc_html( $string2 ); ?></p>
<p><?php echo esc_html( $string3 ); ?></p>
</div>
<style>
</style>
<?php
}
} Review.php 0000666 00000024427 15114633066 0006540 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Review Plugin Notice.
*
* @since 4.0.0
*/
class Review {
/**
* Class Constructor.
*
* @since 4.0.0
*/
public function __construct() {
add_action( 'wp_ajax_aioseo-dismiss-review-plugin-cta', [ $this, 'dismissNotice' ] );
}
/**
* Go through all the checks to see if we should show the notice.
*
* @since 4.0.0
*
* @return void
*/
public function maybeShowNotice() {
$dismissed = get_user_meta( get_current_user_id(), '_aioseo_plugin_review_dismissed', true );
if ( '3' === $dismissed || '4' === $dismissed ) {
return;
}
if ( ! empty( $dismissed ) && $dismissed > time() ) {
return;
}
// Only show to users that interact with our pluign.
if ( ! current_user_can( 'publish_posts' ) ) {
return;
}
// Only show if plugin has been active for over 10 days.
if ( ! aioseo()->internalOptions->internal->firstActivated ) {
aioseo()->internalOptions->internal->firstActivated = time();
}
$activated = aioseo()->internalOptions->internal->firstActivated( time() );
if ( $activated > strtotime( '-10 days' ) ) {
return;
}
if ( get_option( 'aioseop_options' ) || get_option( 'aioseo_options_v3' ) ) {
$this->showNotice();
} else {
$this->showNotice2();
}
// Print the script to the footer.
add_action( 'admin_footer', [ $this, 'printScript' ] );
}
/**
* Actually show the review plugin.
*
* @since 4.0.0
*
* @return void
*/
public function showNotice() {
$feedbackUrl = add_query_arg(
[
'wpf7528_24' => untrailingslashit( home_url() ),
'wpf7528_26' => aioseo()->options->has( 'general' ) && aioseo()->options->general->has( 'licenseKey' )
? aioseo()->options->general->licenseKey
: '',
'wpf7528_27' => aioseo()->pro ? 'pro' : 'lite',
'wpf7528_28' => AIOSEO_VERSION,
'utm_source' => aioseo()->pro ? 'proplugin' : 'liteplugin',
'utm_medium' => 'review-notice',
'utm_campaign' => 'feedback',
'utm_content' => AIOSEO_VERSION,
],
'https://aioseo.com/plugin-feedback/'
);
$string1 = sprintf(
// Translators: 1 - The plugin short name ("AIOSEO").
__( 'Are you enjoying %1$s?', 'all-in-one-seo-pack' ),
AIOSEO_PLUGIN_NAME
);
$string2 = __( 'Yes I love it', 'all-in-one-seo-pack' );
$string3 = __( 'Not Really...', 'all-in-one-seo-pack' );
$string4 = sprintf(
// Translators: 1 - The plugin name ("All in One SEO").
__( 'We\'re sorry to hear you aren\'t enjoying %1$s. We would love a chance to improve. Could you take a minute and let us know what we can do better?', 'all-in-one-seo-pack' ),
AIOSEO_PLUGIN_NAME
); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
$string5 = __( 'Give feedback', 'all-in-one-seo-pack' );
$string6 = __( 'No thanks', 'all-in-one-seo-pack' );
$string7 = __( 'That\'s awesome! Could you please do us a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'all-in-one-seo-pack' );
// Translators: 1 - The plugin name ("All in One SEO").
$string9 = __( 'Ok, you deserve it', 'all-in-one-seo-pack' );
$string10 = __( 'Nope, maybe later', 'all-in-one-seo-pack' );
$string11 = __( 'I already did', 'all-in-one-seo-pack' );
?>
<div class="notice notice-info aioseo-review-plugin-cta is-dismissible">
<div class="step-1">
<p><?php echo esc_html( $string1 ); ?></p>
<p>
<a href="#" class="aioseo-review-switch-step-3" data-step="3"><?php echo esc_html( $string2 ); ?></a> 🙂 |
<a href="#" class="aioseo-review-switch-step-2" data-step="2"><?php echo esc_html( $string3 ); ?></a>
</p>
</div>
<div class="step-2" style="display:none;">
<p><?php echo esc_html( $string4 ); ?></p>
<p>
<a href="<?php echo esc_url( $feedbackUrl ); ?>" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $string5 ); ?></a>
<a href="#" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $string6 ); ?></a>
</p>
</div>
<div class="step-3" style="display:none;">
<p><?php echo esc_html( $string7 ); ?></p>
<p>
<a href="https://wordpress.org/support/plugin/all-in-one-seo-pack/reviews/?filter=5#new-post" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string9 ); ?>
</a> •
<a href="#" class="aioseo-dismiss-review-notice-delay" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string10 ); ?>
</a> •
<a href="#" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string11 ); ?>
</a>
</p>
</div>
</div>
<?php
}
/**
* Actually show the review plugin 2.0.
*
* @since 4.2.2
*
* @return void
*/
public function showNotice2() {
$string1 = sprintf(
// Translators: 1 - The plugin name ("All in One SEO").
__( 'Hey, we noticed you have been using %1$s for some time - that’s awesome! Could you please do us a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'<strong>' . esc_html( AIOSEO_PLUGIN_NAME ) . '</strong>'
);
// Translators: 1 - The plugin name ("All in One SEO").
$string9 = __( 'Ok, you deserve it', 'all-in-one-seo-pack' );
$string10 = __( 'Nope, maybe later', 'all-in-one-seo-pack' );
$string11 = __( 'I already did', 'all-in-one-seo-pack' );
?>
<div class="notice notice-info aioseo-review-plugin-cta is-dismissible">
<div class="step-3">
<p><?php echo $string1; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
<p>
<a href="https://wordpress.org/support/plugin/all-in-one-seo-pack/reviews/?filter=5#new-post" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string9 ); ?>
</a> •
<a href="#" class="aioseo-dismiss-review-notice-delay" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string10 ); ?>
</a> •
<a href="#" class="aioseo-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $string11 ); ?>
</a>
</p>
</div>
</div>
<?php
}
/**
* Print the script for dismissing the notice.
*
* @since 4.0.13
*
* @return void
*/
public function printScript() {
// Create a nonce.
$nonce = wp_create_nonce( 'aioseo-dismiss-review' );
?>
<style>
.aioseop-notice-review_plugin_cta .aioseo-action-buttons {
display: none;
}
@keyframes dismissBtnVisible {
from { opacity: 0.99; }
to { opacity: 1; }
}
.aioseo-review-plugin-cta button.notice-dismiss {
animation-duration: 0.001s;
animation-name: dismissBtnVisible;
}
</style>
<script>
window.addEventListener('load', function () {
var aioseoSetupButton,
dismissBtn
aioseoSetupButton = function (dismissBtn) {
var notice = document.querySelector('.notice.aioseo-review-plugin-cta'),
delay = false,
relay = true,
stepOne = notice.querySelector('.step-1'),
stepTwo = notice.querySelector('.step-2'),
stepThree = notice.querySelector('.step-3')
// Add an event listener to the dismiss button.
dismissBtn.addEventListener('click', function (event) {
var httpRequest = new XMLHttpRequest(),
postData = ''
// Build the data to send in our request.
postData += '&delay=' + delay
postData += '&relay=' + relay
postData += '&action=aioseo-dismiss-review-plugin-cta'
postData += '&nonce=<?php echo esc_html( $nonce ); ?>'
httpRequest.open('POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>')
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
httpRequest.send(postData)
})
notice.addEventListener('click', function (event) {
if (event.target.matches('.aioseo-review-switch-step-3')) {
event.preventDefault()
stepOne.style.display = 'none'
stepTwo.style.display = 'none'
stepThree.style.display = 'block'
}
if (event.target.matches('.aioseo-review-switch-step-2')) {
event.preventDefault()
stepOne.style.display = 'none'
stepThree.style.display = 'none'
stepTwo.style.display = 'block'
}
if (event.target.matches('.aioseo-dismiss-review-notice-delay')) {
event.preventDefault()
delay = true
relay = false
dismissBtn.click()
}
if (event.target.matches('.aioseo-dismiss-review-notice')) {
if ('#' === event.target.getAttribute('href')) {
event.preventDefault()
}
relay = false
dismissBtn.click()
}
})
}
dismissBtn = document.querySelector('.aioseo-review-plugin-cta .notice-dismiss')
if (!dismissBtn) {
document.addEventListener('animationstart', function (event) {
if (event.animationName == 'dismissBtnVisible') {
dismissBtn = document.querySelector('.aioseo-review-plugin-cta .notice-dismiss')
if (dismissBtn) {
aioseoSetupButton(dismissBtn)
}
}
}, false)
} else {
aioseoSetupButton(dismissBtn)
}
});
</script>
<?php
}
/**
* Dismiss the review plugin CTA.
*
* @since 4.0.0
*
* @return string The successful response.
*/
public function dismissNotice() {
// Early exit if we're not on a aioseo-dismiss-review-plugin-cta action.
if ( ! isset( $_POST['action'] ) || 'aioseo-dismiss-review-plugin-cta' !== $_POST['action'] ) {
return;
}
check_ajax_referer( 'aioseo-dismiss-review', 'nonce' );
$delay = isset( $_POST['delay'] ) ? 'true' === sanitize_text_field( wp_unslash( $_POST['delay'] ) ) : false;
$relay = isset( $_POST['relay'] ) ? 'true' === sanitize_text_field( wp_unslash( $_POST['relay'] ) ) : false;
if ( ! $delay ) {
update_user_meta( get_current_user_id(), '_aioseo_plugin_review_dismissed', $relay ? '4' : '3' );
return wp_send_json_success();
}
update_user_meta( get_current_user_id(), '_aioseo_plugin_review_dismissed', strtotime( '+1 week' ) );
return wp_send_json_success();
}
} Migration.php 0000666 00000003044 15114633066 0007220 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* V3 to V4 migration notice.
*
* @since 4.0.0
*/
class Migration {
/**
* Go through all the checks to see if we should show the notice.
*
* @since 4.0.0
*
* @return void
*/
public function maybeShowNotice() {
$transientPosts = aioseo()->core->cache->get( 'v3_migration_in_progress_posts' );
$transientTerms = aioseo()->core->cache->get( 'v3_migration_in_progress_terms' );
if ( ! $transientPosts && ! $transientTerms ) {
return;
}
$this->showNotice();
}
/**
* Register the notice so that it appears.
*
* @since 4.0.0
*
* @return void
*/
public function showNotice() {
// Translators: 1 - The plugin name ("AIOSEO).
$string1 = sprintf( __( '%1$s V3->V4 Migration In Progress', 'all-in-one-seo-pack' ), AIOSEO_PLUGIN_SHORT_NAME );
// Translators: 1 - The plugin name ("All in One SEO").
$string2 = sprintf( __( '%1$s is currently upgrading your database and migrating your SEO data in the background.', 'all-in-one-seo-pack' ), AIOSEO_PLUGIN_NAME );
$string3 = __( 'This notice will automatically disappear as soon as the migration has completed. Meanwhile, everything should continue to work as expected.', 'all-in-one-seo-pack' );
?>
<div class="notice notice-info aioseo-migration">
<p><strong><?php echo esc_html( $string1 ); ?></strong></p>
<p><?php echo esc_html( $string2 ); ?></p>
<p><?php echo esc_html( $string3 ); ?></p>
</div>
<style>
</style>
<?php
}
} ConflictingPlugins.php 0000666 00000012466 15114633066 0011100 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles the Conflicting Plugins notice..
*
* @since 4.5.1
*/
class ConflictingPlugins {
/**
* Class constructor.
*
* @since 4.5.1
*/
public function __construct() {
add_action( 'wp_ajax_aioseo-dismiss-conflicting-plugins-notice', [ $this, 'dismissNotice' ] );
add_action( 'wp_ajax_aioseo-deactivate-conflicting-plugins-notice', [ $this, 'deactivateConflictingPlugins' ] );
}
/**
* Go through all the checks to see if we should show the notice.
*
* @since 4.5.1
*
* @return void
*/
public function maybeShowNotice() {
$dismissed = get_option( '_aioseo_conflicting_plugins_dismissed', true );
if ( '1' === $dismissed ) {
return;
}
if ( ! current_user_can( 'activate_plugins' ) ) {
return;
}
// Only show if there are conflicting plugins.
$conflictingPlugins = aioseo()->conflictingPlugins->getAllConflictingPlugins();
if ( empty( $conflictingPlugins ) ) {
return;
}
$this->showNotice();
// Print the script to the footer.
add_action( 'admin_footer', [ $this, 'printScript' ] );
}
/**
* Renders the notice.
*
* @since 4.5.1
*
* @return void
*/
public function showNotice() {
$type = ! empty( aioseo()->conflictingPlugins->getConflictingPlugins( 'seo' ) ) ? 'SEO' : 'sitemap';
?>
<div class="notice notice-error aioseo-conflicting-plugin-notice is-dismissible">
<p>
<?php
echo wp_kses(
sprintf(
// phpcs:ignore Generic.Files.LineLength.MaxExceeded
// Translators: 1 - Type of conflicting plugin (i.e. SEO or Sitemap), 2 - Opening HTML link tag, 3 - Closing HTML link tag.
__( 'Please keep only one %1$s plugin active, otherwise, you might lose your rankings and traffic. %2$sClick here to Deactivate.%3$s', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
$type,
'<a href="#" rel="noopener noreferrer" class="deactivate-conflicting-plugins">',
'</a>'
),
[
'a' => [
'href' => [],
'rel' => [],
'class' => []
],
'strong' => [],
]
);
?>
</p>
</div>
<style>
#conflicting_seo_plugins.rank-math-notice {
display: none;
}
</style>
<?php
}
/**
* Print the script for dismissing the notice.
*
* @since 4.5.1
*
* @return void
*/
public function printScript() {
// Create a nonce.
$nonce1 = wp_create_nonce( 'aioseo-dismiss-conflicting-plugins' );
$nonce2 = wp_create_nonce( 'aioseo-deactivate-conflicting-plugins' );
?>
<script>
window.addEventListener('load', function () {
var dismissBtn,
deactivateBtn
// Add an event listener to the dismiss button.
dismissBtn = document.querySelector('.aioseo-conflicting-plugin-notice .notice-dismiss')
dismissBtn.addEventListener('click', function (event) {
var httpRequest = new XMLHttpRequest(),
postData = ''
// Build the data to send in our request.
postData += '&action=aioseo-dismiss-conflicting-plugins-notice'
postData += '&nonce=<?php echo esc_html( $nonce1 ); ?>'
httpRequest.open('POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>')
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
httpRequest.send(postData)
})
deactivateBtn = document.querySelector('.aioseo-conflicting-plugin-notice .deactivate-conflicting-plugins')
deactivateBtn.addEventListener('click', function (event) {
event.preventDefault()
var httpRequest = new XMLHttpRequest(),
postData = ''
// Build the data to send in our request.
postData += '&action=aioseo-deactivate-conflicting-plugins-notice'
postData += '&nonce=<?php echo esc_html( $nonce2 ); ?>'
httpRequest.open('POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>')
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
httpRequest.onerror = function () {
window.location.reload()
}
httpRequest.onload = function () {
window.location.reload()
}
httpRequest.send(postData)
})
});
</script>
<?php
}
/**
* Dismiss the notice.
*
* @since 4.5.1
*
* @return string The successful response.
*/
public function dismissNotice() {
// Early exit if we're not on a aioseo-dismiss-conflicting-plugins-notice action.
if ( ! isset( $_POST['action'] ) || 'aioseo-dismiss-conflicting-plugins-notice' !== $_POST['action'] ) {
return wp_send_json_error( 'invalid-action' );
}
check_ajax_referer( 'aioseo-dismiss-conflicting-plugins', 'nonce' );
update_option( '_aioseo_conflicting_plugins_dismissed', true );
return wp_send_json_success();
}
/**
* Deactivates the conflicting plugins.
*
* @since 4.5.1
*
* @return string The successful response.
*/
public function deactivateConflictingPlugins() {
// Early exit if we're not on a aioseo-dismiss-conflicting-plugins-notice action.
if ( ! isset( $_POST['action'] ) || 'aioseo-deactivate-conflicting-plugins-notice' !== $_POST['action'] ) {
return wp_send_json_error( 'invalid-action' );
}
check_ajax_referer( 'aioseo-deactivate-conflicting-plugins', 'nonce' );
aioseo()->conflictingPlugins->deactivateConflictingPlugins( [ 'seo', 'sitemap' ] );
return wp_send_json_success();
}
} WpNotices.php 0000666 00000015515 15114633066 0007210 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Admin\Notices;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WpNotices class.
*
* @since 4.2.3
*/
class WpNotices {
/**
* Notices array
*
* @since 4.2.3
*
* @var array
*/
private $notices = [];
/**
* The cache key.
*
* @since 4.2.3
*
* @var string
*/
private $cacheKey = 'wp_notices';
/**
* Class Constructor.
*
* @since 4.2.3
*/
public function __construct() {
add_action( 'rest_api_init', [ $this, 'registerApiField' ] );
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueueScripts' ] );
add_action( 'admin_notices', [ $this, 'adminNotices' ] );
}
/**
* Enqueue notices scripts.
*
* @since 4.2.3
*
* @return void
*/
public function enqueueScripts() {
aioseo()->core->assets->load( 'src/vue/standalone/wp-notices/main.js' );
}
/**
* Registers an API field with notices.
*
* @since 4.2.3
*
* @return void
*/
public function registerApiField() {
foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
register_rest_field( $postType, 'aioseo_notices', [
'get_callback' => [ $this, 'apiGetNotices' ]
] );
}
}
/**
* API field callback.
*
* @since 4.2.3
*
* @return array Notices array
*/
public function apiGetNotices() {
$notices = $this->getNoticesInContext();
// Notices show only one time.
$this->removeNotices( $notices );
return $notices;
}
/**
* Get all notices.
*
* @since 4.2.3
*
* @return array Notices array
*/
public function getNotices() {
if ( empty( $this->notices ) ) {
$this->notices = (array) aioseo()->core->cache->get( $this->cacheKey );
}
return ! empty( $this->notices ) ? $this->notices : [];
}
/**
* Get all notices in the current context.
*
* @since 4.2.6
*
* @return array Notices array
*/
public function getNoticesInContext() {
$contextNotices = $this->getNotices();
foreach ( $contextNotices as $key => $notice ) {
if ( empty( $notice['allowedContexts'] ) ) {
continue;
}
$allowed = false;
foreach ( $notice['allowedContexts'] as $allowedContext ) {
if ( $this->isAllowedContext( $allowedContext ) ) {
$allowed = true;
break;
}
}
if ( ! $allowed ) {
unset( $contextNotices[ $key ] );
}
}
return $contextNotices;
}
/**
* Test if we are in the current context.
*
* @since 4.2.6
*
* @param string $context The context to test. (posts)
* @return bool Is the required context.
*/
private function isAllowedContext( $context ) {
switch ( $context ) {
case 'posts':
return aioseo()->helpers->isScreenPostList() ||
aioseo()->helpers->isScreenPostEdit() ||
aioseo()->helpers->isAjaxCronRestRequest();
}
return false;
}
/**
* Finds a notice by message.
*
* @since 4.2.3
*
* @param string $message The message string.
* @param string $type The message type.
* @return void|array The found notice.
*/
public function getNotice( $message, $type = '' ) {
$notices = $this->getNotices();
foreach ( $notices as $notice ) {
if ( $notice['options']['id'] === $this->getNoticeId( $message, $type ) ) {
return $notice;
}
}
}
/**
* Generates a notice id.
*
* @since 4.2.3
*
* @param string $message The message string.
* @param string $type The message type.
* @return string The notice id.
*/
public function getNoticeId( $message, $type = '' ) {
return md5( $message . $type );
}
/**
* Clear notices.
*
* @since 4.2.3
*
* @return void
*/
public function clearNotices() {
$this->notices = [];
$this->updateCache();
}
/**
* Remove certain notices.
*
* @since 4.2.6
*
* @param array $notices A list of notices to remove.
* @return void
*/
public function removeNotices( $notices ) {
foreach ( array_keys( $notices ) as $noticeKey ) {
unset( $this->notices[ $noticeKey ] );
}
$this->updateCache();
}
/**
* Adds a notice.
*
* @since 4.2.3
*
* @param string $message The message.
* @param string $status The message status [success, info, warning, error]
* @param array $options Options for the message. https://developer.wordpress.org/block-editor/reference-guides/data/data-core-notices/#createnotice
* @param array $allowedContexts The contexts where this notice will show.
* @return void
*/
public function addNotice( $message, $status = 'warning', $options = [], $allowedContexts = [] ) {
$type = ! empty( $options['type'] ) ? $options['type'] : '';
$foundNotice = $this->getNotice( $message, $type );
if ( empty( $message ) || ! empty( $foundNotice ) ) {
return;
}
$notice = [
'message' => $message,
'status' => $status,
'options' => wp_parse_args( $options, [
'id' => $this->getNoticeId( $message, $type ),
'isDismissible' => true
] ),
'allowedContexts' => $allowedContexts
];
$this->notices[] = $notice;
$this->updateCache();
}
/**
* Show notices on classic editor.
*
* @since 4.2.3
*
* @return void
*/
public function adminNotices() {
// Double check we're actually in the admin before outputting anything.
if ( ! is_admin() ) {
return;
}
$notices = $this->getNoticesInContext();
foreach ( $notices as $notice ) {
// Hide snackbar notices on classic editor.
if ( ! empty( $notice['options']['type'] ) && 'snackbar' === $notice['options']['type'] ) {
continue;
}
$status = ! empty( $notice['status'] ) ? $notice['status'] : 'warning';
$class = ! empty( $notice['options']['class'] ) ? $notice['options']['class'] : '';
?>
<div
class="notice notice-<?php echo esc_attr( $status ) ?> <?php echo esc_attr( $class ) ?>">
<?php echo '<p>' . $notice['message'] . '</p>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php
if ( ! empty( $notice['options']['actions'] ) ) {
foreach ( $notice['options']['actions'] as $action ) {
echo '<p>';
if ( ! empty( $action['url'] ) ) {
$class = ! empty( $action['class'] ) ? $action['class'] : '';
$target = ! empty( $action['target'] ) ? $action['target'] : '';
echo '<a
href="' . esc_attr( $action['url'] ) . '"
class="' . esc_attr( $class ) . '"
target="' . esc_attr( $target ) . '"
>';
}
echo $action['label']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ( ! empty( $action['url'] ) ) {
echo '</a>';
}
echo '</p>';
}
?>
<?php } ?>
</div>
<?php
}
// Notices show only one time.
$this->removeNotices( $notices );
}
/**
* Helper to update the cache with the current notices array.
*
* @since 4.2.6
*
* @return void
*/
private function updateCache() {
aioseo()->core->cache->update( $this->cacheKey, $this->notices );
}
}