Version Description
Download this release
Release Info
Developer | Yoast |
Plugin | Yoast SEO |
Version | 7.7 |
Comparing to | |
See all releases |
Code changes from version 7.6.1 to 7.7
- admin/banner/class-admin-banner-sidebar.php +1 -1
- admin/capabilities/class-register-capabilities.php +40 -7
- admin/class-admin-asset-dev-server-location.php +1 -0
- admin/class-admin-asset-manager.php +9 -0
- admin/class-admin-asset-yoast-components-l10n.php +11 -7
- admin/class-admin-init.php +2 -1
- admin/class-admin-media-purge-notification.php +1 -21
- admin/class-admin-recommended-replace-vars.php +203 -0
- admin/class-admin.php +3 -2
- admin/class-config.php +28 -4
- admin/class-database-proxy.php +33 -8
- admin/class-help-center.php +9 -6
- admin/class-yoast-alerts.php +2 -1
- admin/class-yoast-notification-center.php +128 -17
- admin/class-yoast-notification.php +39 -1
- admin/formatter/class-metabox-formatter.php +0 -1
- admin/formatter/class-post-metabox-formatter.php +8 -2
- admin/formatter/class-term-metabox-formatter.php +8 -2
- admin/menu/class-replacevar-editor.php +77 -0
- admin/menu/class-replacevar-field.php +67 -0
- admin/metabox/class-metabox.php +19 -11
- admin/taxonomy/class-taxonomy-content-fields.php +1 -6
- admin/taxonomy/class-taxonomy.php +20 -9
- admin/views/class-view-utils.php +10 -16
- admin/views/tabs/metas/archives.php +9 -10
- admin/views/tabs/metas/general/homepage.php +3 -2
- admin/views/tabs/metas/post-types.php +64 -42
- admin/views/tabs/metas/taxonomies.php +7 -2
- admin/watchers/class-slug-change-watcher.php +89 -29
- css/dist/{admin-global-761-rtl.min.css → admin-global-770-rtl.min.css} +1 -1
- css/dist/{admin-global-761.min.css → admin-global-770.min.css} +1 -1
- css/dist/{adminbar-761-rtl.min.css → adminbar-770-rtl.min.css} +0 -0
- css/dist/{adminbar-761.min.css → adminbar-770.min.css} +0 -0
- css/dist/{alerts-761-rtl.min.css → alerts-770-rtl.min.css} +0 -0
- css/dist/{alerts-761.min.css → alerts-770.min.css} +0 -0
- css/dist/{dashboard-761-rtl.min.css → dashboard-770-rtl.min.css} +0 -0
- css/dist/{dashboard-761.min.css → dashboard-770.min.css} +0 -0
- css/dist/{edit-page-761-rtl.min.css → edit-page-770-rtl.min.css} +0 -0
- css/dist/{edit-page-761.min.css → edit-page-770.min.css} +0 -0
- css/dist/{featured-image-761-rtl.min.css → featured-image-770-rtl.min.css} +0 -0
- css/dist/{featured-image-761.min.css → featured-image-770.min.css} +0 -0
- css/dist/{filter-explanation-761-rtl.min.css → filter-explanation-770-rtl.min.css} +0 -0
- css/dist/{filter-explanation-761.min.css → filter-explanation-770.min.css} +0 -0
- css/dist/{inside-editor-761-rtl.min.css → inside-editor-770-rtl.min.css} +0 -0
- css/dist/{inside-editor-761.min.css → inside-editor-770.min.css} +0 -0
- css/dist/{metabox-761-rtl.min.css → metabox-770-rtl.min.css} +1 -1
- css/dist/{metabox-761.min.css → metabox-770.min.css} +1 -1
- css/dist/{metabox-primary-category-761-rtl.min.css → metabox-primary-category-770-rtl.min.css} +0 -0
- css/dist/{metabox-primary-category-761.min.css → metabox-primary-category-770.min.css} +0 -0
- css/dist/search-appearance-770-rtl.min.css +1 -0
- css/dist/search-appearance-770.min.css +1 -0
- css/dist/{snippet-761-rtl.min.css → snippet-770-rtl.min.css} +0 -0
- css/dist/{snippet-761.min.css → snippet-770.min.css} +0 -0
- css/dist/{toggle-switch-761-rtl.min.css → toggle-switch-770-rtl.min.css} +1 -1
- css/dist/{toggle-switch-761.min.css → toggle-switch-770.min.css} +1 -1
- css/dist/{wpseo-dismissible-761-rtl.min.css → wpseo-dismissible-770-rtl.min.css} +0 -0
- css/dist/{wpseo-dismissible-761.min.css → wpseo-dismissible-770.min.css} +0 -0
- css/dist/{yoast-components-761-rtl.min.css → yoast-components-770-rtl.min.css} +0 -0
- css/dist/{yoast-components-761.min.css → yoast-components-770.min.css} +0 -0
- css/dist/{yoast-extensions-761-rtl.min.css → yoast-extensions-770-rtl.min.css} +0 -0
- css/dist/{yoast-extensions-761.min.css → yoast-extensions-770.min.css} +0 -0
- css/dist/yst_plugin_tools-761-rtl.min.css +0 -1
- css/dist/yst_plugin_tools-761.min.css +0 -1
- css/dist/yst_plugin_tools-770-rtl.min.css +1 -0
- css/dist/yst_plugin_tools-770.min.css +1 -0
- css/dist/{yst_seo_score-761-rtl.min.css → yst_seo_score-770-rtl.min.css} +0 -0
- css/dist/{yst_seo_score-761.min.css → yst_seo_score-770.min.css} +0 -0
- frontend/class-breadcrumbs.php +42 -23
- frontend/class-frontend.php +16 -1
- frontend/class-json-ld.php +45 -0
- frontend/class-opengraph-image.php +15 -8
- images/banner/yoast-seo-for-wordpress-training-2018.png +0 -0
- images/banner/yoast-seo-for-wordpress-training.png +0 -0
- images/pinterest-23x30.png +0 -0
- inc/class-rewrite.php +1 -0
- inc/class-upgrade.php +14 -0
- inc/class-wpseo-content-images.php +10 -52
- inc/class-wpseo-image-utils.php +36 -1
- inc/class-wpseo-replace-vars.php +195 -69
- inc/class-wpseo-replacement-variable.php +73 -0
- inc/sitemaps/class-sitemaps-router.php +1 -0
- js/dist/{commons-761.min.js → commons-770.min.js} +7 -7
- js/dist/configuration-wizard-761.min.js +0 -12
admin/banner/class-admin-banner-sidebar.php
CHANGED
@@ -270,7 +270,7 @@ class WPSEO_Admin_Banner_Sidebar {
|
|
270 |
$courses_spot->add_banner(
|
271 |
new WPSEO_Admin_Banner(
|
272 |
WPSEO_Shortlinker::get( 'https://yoa.st/jv' ),
|
273 |
-
'yoast-seo-for-wordpress-training.png',
|
274 |
261,
|
275 |
152,
|
276 |
sprintf(
|
270 |
$courses_spot->add_banner(
|
271 |
new WPSEO_Admin_Banner(
|
272 |
WPSEO_Shortlinker::get( 'https://yoa.st/jv' ),
|
273 |
+
'yoast-seo-for-wordpress-training-2018.png',
|
274 |
261,
|
275 |
152,
|
276 |
sprintf(
|
admin/capabilities/class-register-capabilities.php
CHANGED
@@ -16,6 +16,10 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
|
|
16 |
*/
|
17 |
public function register_hooks() {
|
18 |
add_action( 'wpseo_register_capabilities', array( $this, 'register' ) );
|
|
|
|
|
|
|
|
|
19 |
}
|
20 |
|
21 |
/**
|
@@ -29,14 +33,43 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
|
|
29 |
$manager->register( 'wpseo_bulk_edit', array( 'editor', 'wpseo_editor', 'wpseo_manager' ) );
|
30 |
$manager->register( 'wpseo_edit_advanced_metadata', array( 'wpseo_editor', 'wpseo_manager' ) );
|
31 |
|
32 |
-
$manager->register( 'wpseo_manage_options', array( 'wpseo_manager' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
* This means that local admins do not get the `wpseo_manage_options` capability.
|
37 |
-
*/
|
38 |
-
if ( WPSEO_Options::get( 'access' ) !== 'superadmins' ) {
|
39 |
-
$manager->register( 'wpseo_manage_options', array( 'administrator' ) );
|
40 |
}
|
|
|
|
|
41 |
}
|
42 |
}
|
16 |
*/
|
17 |
public function register_hooks() {
|
18 |
add_action( 'wpseo_register_capabilities', array( $this, 'register' ) );
|
19 |
+
|
20 |
+
if ( is_multisite() ) {
|
21 |
+
add_action( 'user_has_cap', array( $this, 'filter_user_has_wpseo_manage_options_cap' ), 10, 4 );
|
22 |
+
}
|
23 |
}
|
24 |
|
25 |
/**
|
33 |
$manager->register( 'wpseo_bulk_edit', array( 'editor', 'wpseo_editor', 'wpseo_manager' ) );
|
34 |
$manager->register( 'wpseo_edit_advanced_metadata', array( 'wpseo_editor', 'wpseo_manager' ) );
|
35 |
|
36 |
+
$manager->register( 'wpseo_manage_options', array( 'administrator', 'wpseo_manager' ) );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Revokes the 'wpseo_manage_options' capability from administrator users if it should only
|
41 |
+
* only be granted to network administrators.
|
42 |
+
*
|
43 |
+
* @param array $allcaps An array of all the user's capabilities.
|
44 |
+
* @param array $caps Actual capabilities being checked.
|
45 |
+
* @param array $args Optional parameters passed to has_cap(), typically object ID.
|
46 |
+
* @param WP_User $user The user object.
|
47 |
+
*
|
48 |
+
* @return array Possibly modified array of the user's capabilities.
|
49 |
+
*/
|
50 |
+
public function filter_user_has_wpseo_manage_options_cap( $allcaps, $caps, $args, $user ) {
|
51 |
+
|
52 |
+
// We only need to do something if 'wpseo_manage_options' is being checked.
|
53 |
+
if ( ! in_array( 'wpseo_manage_options', $caps, true ) ) {
|
54 |
+
return $allcaps;
|
55 |
+
}
|
56 |
+
|
57 |
+
// If the user does not have 'wpseo_manage_options' anyway, we don't need to revoke access.
|
58 |
+
if ( empty( $allcaps['wpseo_manage_options'] ) ) {
|
59 |
+
return $allcaps;
|
60 |
+
}
|
61 |
+
|
62 |
+
// If the user does not have 'delete_users', they are not an administrator.
|
63 |
+
if ( empty( $allcaps['delete_users'] ) ) {
|
64 |
+
return $allcaps;
|
65 |
+
}
|
66 |
+
|
67 |
+
$options = WPSEO_Options::get_instance();
|
68 |
|
69 |
+
if ( $options->get( 'access' ) === 'superadmin' && ! is_super_admin( $user->ID ) ) {
|
70 |
+
unset( $allcaps['wpseo_manage_options'] );
|
|
|
|
|
|
|
|
|
71 |
}
|
72 |
+
|
73 |
+
return $allcaps;
|
74 |
}
|
75 |
}
|
admin/class-admin-asset-dev-server-location.php
CHANGED
@@ -17,6 +17,7 @@ final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_L
|
|
17 |
private static $dev_server_script = array(
|
18 |
'commons',
|
19 |
'configuration-wizard',
|
|
|
20 |
'wp-seo-dashboard-widget',
|
21 |
'wp-seo-help-center',
|
22 |
'wp-seo-metabox',
|
17 |
private static $dev_server_script = array(
|
18 |
'commons',
|
19 |
'configuration-wizard',
|
20 |
+
'search-appearance',
|
21 |
'wp-seo-dashboard-widget',
|
22 |
'wp-seo-help-center',
|
23 |
'wp-seo-metabox',
|
admin/class-admin-asset-manager.php
CHANGED
@@ -220,6 +220,11 @@ class WPSEO_Admin_Asset_Manager {
|
|
220 |
self::PREFIX . 'babel-polyfill',
|
221 |
),
|
222 |
),
|
|
|
|
|
|
|
|
|
|
|
223 |
array(
|
224 |
'name' => 'wp-globals-backport',
|
225 |
'src' => 'wp-seo-wp-globals-backport-' . $flat_version,
|
@@ -520,6 +525,10 @@ class WPSEO_Admin_Asset_Manager {
|
|
520 |
'name' => 'filter-explanation',
|
521 |
'src' => 'filter-explanation-' . $flat_version,
|
522 |
),
|
|
|
|
|
|
|
|
|
523 |
);
|
524 |
}
|
525 |
}
|
220 |
self::PREFIX . 'babel-polyfill',
|
221 |
),
|
222 |
),
|
223 |
+
array(
|
224 |
+
'name' => 'search-appearance',
|
225 |
+
'src' => 'search-appearance-' . $flat_version,
|
226 |
+
'deps' => 'react-dependencies',
|
227 |
+
),
|
228 |
array(
|
229 |
'name' => 'wp-globals-backport',
|
230 |
'src' => 'wp-seo-wp-globals-backport-' . $flat_version,
|
525 |
'name' => 'filter-explanation',
|
526 |
'src' => 'filter-explanation-' . $flat_version,
|
527 |
),
|
528 |
+
array(
|
529 |
+
'name' => 'search-appearance',
|
530 |
+
'src' => 'search-appearance-' . $flat_version,
|
531 |
+
),
|
532 |
);
|
533 |
}
|
534 |
}
|
admin/class-admin-asset-yoast-components-l10n.php
CHANGED
@@ -4,29 +4,33 @@
|
|
4 |
*/
|
5 |
|
6 |
/**
|
7 |
-
* Localizes
|
8 |
*/
|
9 |
final class WPSEO_Admin_Asset_Yoast_Components_l10n {
|
10 |
/**
|
11 |
-
* Localizes the given script with the
|
12 |
*
|
13 |
* @param string $script_handle The script handle to localize for.
|
14 |
*
|
15 |
* @return void
|
16 |
*/
|
17 |
public function localize_script( $script_handle ) {
|
18 |
-
wp_localize_script( $script_handle, '
|
|
|
|
|
|
|
19 |
}
|
20 |
|
21 |
/**
|
22 |
-
* Returns translations necessary for
|
23 |
*
|
24 |
-
* @
|
|
|
25 |
*/
|
26 |
-
protected function get_translations() {
|
27 |
$locale = WPSEO_Utils::get_user_locale();
|
28 |
|
29 |
-
$file = plugin_dir_path( WPSEO_FILE ) . 'languages/
|
30 |
if ( file_exists( $file ) ) {
|
31 |
$file = file_get_contents( $file );
|
32 |
if ( is_string( $file ) && $file !== '' ) {
|
4 |
*/
|
5 |
|
6 |
/**
|
7 |
+
* Localizes JavaScript files.
|
8 |
*/
|
9 |
final class WPSEO_Admin_Asset_Yoast_Components_l10n {
|
10 |
/**
|
11 |
+
* Localizes the given script with the JavaScript translations.
|
12 |
*
|
13 |
* @param string $script_handle The script handle to localize for.
|
14 |
*
|
15 |
* @return void
|
16 |
*/
|
17 |
public function localize_script( $script_handle ) {
|
18 |
+
wp_localize_script( $script_handle, 'wpseoYoastJSL10n', array(
|
19 |
+
'yoast-components' => $this->get_translations( 'yoast-components' ),
|
20 |
+
'wordpress-seo' => $this->get_translations( 'wordpress-seojs' ),
|
21 |
+
) );
|
22 |
}
|
23 |
|
24 |
/**
|
25 |
+
* Returns translations necessary for JS files.
|
26 |
*
|
27 |
+
* @param string $component The component to retrieve the translations for.
|
28 |
+
* @return object The translations in a Jed format for JS files.
|
29 |
*/
|
30 |
+
protected function get_translations( $component ) {
|
31 |
$locale = WPSEO_Utils::get_user_locale();
|
32 |
|
33 |
+
$file = plugin_dir_path( WPSEO_FILE ) . 'languages/' . $component . '-' . $locale . '.json';
|
34 |
if ( file_exists( $file ) ) {
|
35 |
$file = file_get_contents( $file );
|
36 |
if ( is_string( $file ) && $file !== '' ) {
|
admin/class-admin-init.php
CHANGED
@@ -83,7 +83,8 @@ class WPSEO_Admin_Init {
|
|
83 |
$current_url = ( is_ssl() ? 'https://' : 'http://' );
|
84 |
$current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
|
85 |
$customize_url = add_query_arg( array(
|
86 |
-
'
|
|
|
87 |
), wp_customize_url() );
|
88 |
|
89 |
$info_message = sprintf(
|
83 |
$current_url = ( is_ssl() ? 'https://' : 'http://' );
|
84 |
$current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
|
85 |
$customize_url = add_query_arg( array(
|
86 |
+
'autofocus[control]' => 'blogdescription',
|
87 |
+
'url' => urlencode( $current_url ),
|
88 |
), wp_customize_url() );
|
89 |
|
90 |
$info_message = sprintf(
|
admin/class-admin-media-purge-notification.php
CHANGED
@@ -55,27 +55,7 @@ class WPSEO_Admin_Media_Purge_Notification implements WPSEO_WordPress_Integratio
|
|
55 |
* @return void
|
56 |
*/
|
57 |
public function manage_notification() {
|
58 |
-
|
59 |
-
$this->remove_notification();
|
60 |
-
|
61 |
-
return;
|
62 |
-
}
|
63 |
-
|
64 |
-
// This is the desired behaviour, remove any notifications and carry on.
|
65 |
-
if ( WPSEO_Options::get( 'disable-attachment' ) === true ) {
|
66 |
-
$this->remove_notification();
|
67 |
-
|
68 |
-
return;
|
69 |
-
}
|
70 |
-
|
71 |
-
// When the attachments are no-indexed, this is acceptable.
|
72 |
-
if ( WPSEO_Options::get( 'noindex-attachment' ) === true ) {
|
73 |
-
$this->remove_notification();
|
74 |
-
|
75 |
-
return;
|
76 |
-
}
|
77 |
-
|
78 |
-
$this->add_notification();
|
79 |
}
|
80 |
|
81 |
/**
|
55 |
* @return void
|
56 |
*/
|
57 |
public function manage_notification() {
|
58 |
+
$this->remove_notification();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
admin/class-admin-recommended-replace-vars.php
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WPSEO plugin file.
|
4 |
+
*
|
5 |
+
* @package WPSEO\Admin
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Determines the recommended replacement variables based on the context.
|
10 |
+
*/
|
11 |
+
class WPSEO_Admin_Recommended_Replace_Vars {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var array The recommended replacement variables.
|
15 |
+
*/
|
16 |
+
protected $recommended_replace_vars = array(
|
17 |
+
// Posts types.
|
18 |
+
'page' => array( 'sitename', 'title', 'sep', 'primary_category' ),
|
19 |
+
'post' => array( 'sitename', 'title', 'sep', 'primary_category' ),
|
20 |
+
// Homepage.
|
21 |
+
'homepage' => array( 'sitename', 'sitedesc', 'sep' ),
|
22 |
+
// Custom post type.
|
23 |
+
'custom_post_type' => array( 'sitename', 'title', 'sep' ),
|
24 |
+
|
25 |
+
// Taxonomies.
|
26 |
+
'category' => array( 'sitename', 'term_title', 'sep' ),
|
27 |
+
'post_tag' => array( 'sitename', 'term_title', 'sep' ),
|
28 |
+
'post_format' => array( 'sitename', 'term_title', 'sep', 'page' ),
|
29 |
+
|
30 |
+
// Custom taxonomy.
|
31 |
+
'term-in-custom-taxomomy' => array( 'sitename', 'term_title', 'sep' ),
|
32 |
+
|
33 |
+
// Settings - archive pages.
|
34 |
+
'author_archive' => array( 'sitename', 'title', 'sep', 'page' ),
|
35 |
+
'date_archive' => array( 'sitename', 'sep', 'date', 'page' ),
|
36 |
+
'custom-post-type_archive' => array( 'sitename', 'title', 'sep', 'page' ),
|
37 |
+
|
38 |
+
// Settings - special pages.
|
39 |
+
'search' => array( 'sitename', 'searchphrase', 'sep', 'page' ),
|
40 |
+
'404' => array( 'sitename', 'sep' ),
|
41 |
+
);
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Determines the page type of the current term.
|
45 |
+
*
|
46 |
+
* @param string $taxonomy The taxonomy name.
|
47 |
+
*
|
48 |
+
* @return string The page type.
|
49 |
+
*/
|
50 |
+
public function determine_for_term( $taxonomy ) {
|
51 |
+
$recommended_replace_vars = $this->get_recommended_replacevars();
|
52 |
+
if ( array_key_exists( $taxonomy, $recommended_replace_vars ) ) {
|
53 |
+
return $taxonomy;
|
54 |
+
}
|
55 |
+
|
56 |
+
return 'term-in-custom-taxomomy';
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Determines the page type of the current post.
|
61 |
+
*
|
62 |
+
* @param WP_Post $post The WordPress global post object.
|
63 |
+
*
|
64 |
+
* @return string The page type.
|
65 |
+
*/
|
66 |
+
public function determine_for_post( $post ) {
|
67 |
+
if ( $post instanceof WP_Post === false ) {
|
68 |
+
return 'post';
|
69 |
+
}
|
70 |
+
|
71 |
+
if ( $post->post_type === 'page' && $this->is_homepage( $post ) ) {
|
72 |
+
return 'homepage';
|
73 |
+
}
|
74 |
+
|
75 |
+
$recommended_replace_vars = $this->get_recommended_replacevars();
|
76 |
+
if ( array_key_exists( $post->post_type, $recommended_replace_vars ) ) {
|
77 |
+
return $post->post_type;
|
78 |
+
}
|
79 |
+
|
80 |
+
return 'custom_post_type';
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Determines the page type for a post type.
|
85 |
+
*
|
86 |
+
* @param string $post_type The name of the post_type.
|
87 |
+
* @param string $fallback The page type to fall back to.
|
88 |
+
*
|
89 |
+
* @return string The page type.
|
90 |
+
*/
|
91 |
+
public function determine_for_post_type( $post_type, $fallback = 'custom_post_type' ) {
|
92 |
+
$page_type = $post_type;
|
93 |
+
$recommended_replace_vars = $this->get_recommended_replacevars();
|
94 |
+
$has_recommended_replacevars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
95 |
+
|
96 |
+
if ( ! $has_recommended_replacevars ) {
|
97 |
+
return $fallback;
|
98 |
+
}
|
99 |
+
|
100 |
+
return $page_type;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Determines the page type for an archive page.
|
105 |
+
*
|
106 |
+
* @param string $name The name of the archive.
|
107 |
+
* @param string $fallback The page type to fall back to.
|
108 |
+
*
|
109 |
+
* @return string The page type.
|
110 |
+
*/
|
111 |
+
public function determine_for_archive( $name, $fallback = 'custom-post-type_archive' ) {
|
112 |
+
$page_type = $name . '_archive';
|
113 |
+
$recommended_replace_vars = $this->get_recommended_replacevars();
|
114 |
+
$has_recommended_replacevars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
115 |
+
|
116 |
+
if ( ! $has_recommended_replacevars ) {
|
117 |
+
return $fallback;
|
118 |
+
}
|
119 |
+
|
120 |
+
return $page_type;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Retrieves the recommended replacement variables for the given page type.
|
125 |
+
*
|
126 |
+
* @param string $page_type The page type.
|
127 |
+
*
|
128 |
+
* @return array The recommended replacement variables.
|
129 |
+
*/
|
130 |
+
public function get_recommended_replacevars_for( $page_type ) {
|
131 |
+
$recommended_replace_vars = $this->get_recommended_replacevars();
|
132 |
+
$has_recommended_replace_vars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
133 |
+
|
134 |
+
if ( ! $has_recommended_replace_vars ) {
|
135 |
+
return array();
|
136 |
+
}
|
137 |
+
|
138 |
+
return $recommended_replace_vars[ $page_type ];
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Retrieves the recommended replacement variables.
|
143 |
+
*
|
144 |
+
* @return array The recommended replacement variables.
|
145 |
+
*/
|
146 |
+
public function get_recommended_replacevars() {
|
147 |
+
/**
|
148 |
+
* Filter: Adds the possibility to add extra recommended replacement variables.
|
149 |
+
*
|
150 |
+
* @api array $additional_replace_vars Empty array to add the replacevars to.
|
151 |
+
*/
|
152 |
+
$recommended_replace_vars = apply_filters( 'wpseo_recommended_replace_vars', $this->recommended_replace_vars );
|
153 |
+
|
154 |
+
if ( ! is_array( $recommended_replace_vars ) ) {
|
155 |
+
return $this->recommended_replace_vars;
|
156 |
+
}
|
157 |
+
|
158 |
+
return $recommended_replace_vars;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Returns whether the given page type has recommended replace vars.
|
163 |
+
*
|
164 |
+
* @param array $recommended_replace_vars The recommended replace vars
|
165 |
+
* to check in.
|
166 |
+
* @param string $page_type The page type to check.
|
167 |
+
*
|
168 |
+
* @return bool True if there are associated recommended replace vars.
|
169 |
+
*/
|
170 |
+
private function has_recommended_replace_vars( $recommended_replace_vars, $page_type ) {
|
171 |
+
if ( ! isset( $recommended_replace_vars[ $page_type ] ) ) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
|
175 |
+
if ( ! is_array( $recommended_replace_vars[ $page_type ] ) ) {
|
176 |
+
return false;
|
177 |
+
}
|
178 |
+
|
179 |
+
return true;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Determines whether or not a post is the homepage.
|
184 |
+
*
|
185 |
+
* @param WP_Post $post The WordPress global post object.
|
186 |
+
*
|
187 |
+
* @return bool True if the given post is the homepage.
|
188 |
+
*/
|
189 |
+
private function is_homepage( $post ) {
|
190 |
+
if ( $post instanceof WP_Post === false ) {
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
+
/*
|
195 |
+
* The page on front returns a string with normal WordPress interaction, while the post ID is an int.
|
196 |
+
* This way we make sure we always compare strings.
|
197 |
+
*/
|
198 |
+
$post_id = (int) $post->ID;
|
199 |
+
$page_on_front = (int) get_option( 'page_on_front' );
|
200 |
+
|
201 |
+
return get_option( 'show_on_front' ) === 'page' && $page_on_front === $post_id;
|
202 |
+
}
|
203 |
+
}
|
admin/class-admin.php
CHANGED
@@ -71,6 +71,8 @@ class WPSEO_Admin {
|
|
71 |
|
72 |
add_action( 'admin_init', array( $this, 'map_manage_options_cap' ) );
|
73 |
|
|
|
|
|
74 |
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'wpseo' );
|
75 |
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'home' );
|
76 |
|
@@ -86,7 +88,6 @@ class WPSEO_Admin {
|
|
86 |
|
87 |
$this->set_upsell_notice();
|
88 |
|
89 |
-
$this->check_php_version();
|
90 |
$this->initialize_cornerstone_content();
|
91 |
|
92 |
new Yoast_Modal();
|
@@ -322,7 +323,7 @@ class WPSEO_Admin {
|
|
322 |
*
|
323 |
* @return void
|
324 |
*/
|
325 |
-
|
326 |
// If the user isn't an admin, don't display anything.
|
327 |
if ( ! current_user_can( 'manage_options' ) ) {
|
328 |
return;
|
71 |
|
72 |
add_action( 'admin_init', array( $this, 'map_manage_options_cap' ) );
|
73 |
|
74 |
+
add_action( 'admin_init', array( $this, 'check_php_version' ) );
|
75 |
+
|
76 |
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'wpseo' );
|
77 |
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'home' );
|
78 |
|
88 |
|
89 |
$this->set_upsell_notice();
|
90 |
|
|
|
91 |
$this->initialize_cornerstone_content();
|
92 |
|
93 |
new Yoast_Modal();
|
323 |
*
|
324 |
* @return void
|
325 |
*/
|
326 |
+
public function check_php_version() {
|
327 |
// If the user isn't an admin, don't display anything.
|
328 |
if ( ! current_user_can( 'manage_options' ) ) {
|
329 |
return;
|
admin/class-config.php
CHANGED
@@ -80,11 +80,20 @@ class WPSEO_Admin_Pages {
|
|
80 |
$this->asset_manager->enqueue_script( 'admin-script' );
|
81 |
$this->asset_manager->enqueue_script( 'help-center' );
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
wp_enqueue_script( 'dashboard' );
|
84 |
wp_enqueue_script( 'thickbox' );
|
85 |
|
86 |
-
$page = filter_input( INPUT_GET, 'page' );
|
87 |
-
|
88 |
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-script', 'wpseoSelect2Locale', WPSEO_Utils::get_language( WPSEO_Utils::get_user_locale() ) );
|
89 |
|
90 |
if ( in_array( $page, array( 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ), true ) ) {
|
@@ -100,9 +109,9 @@ class WPSEO_Admin_Pages {
|
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
-
*
|
104 |
*
|
105 |
-
* @return
|
106 |
*/
|
107 |
public function localize_media_script() {
|
108 |
return array(
|
@@ -110,6 +119,21 @@ class WPSEO_Admin_Pages {
|
|
110 |
);
|
111 |
}
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
/**
|
114 |
* Enqueues and handles all the tool dependencies.
|
115 |
*/
|
80 |
$this->asset_manager->enqueue_script( 'admin-script' );
|
81 |
$this->asset_manager->enqueue_script( 'help-center' );
|
82 |
|
83 |
+
$page = filter_input( INPUT_GET, 'page' );
|
84 |
+
|
85 |
+
if ( $page === 'wpseo_titles' ) {
|
86 |
+
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'search-appearance', 'wpseoReplaceVarsL10n', $this->localize_replace_vars_script() );
|
87 |
+
$this->asset_manager->enqueue_script( 'search-appearance' );
|
88 |
+
$this->asset_manager->enqueue_style( 'search-appearance' );
|
89 |
+
|
90 |
+
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_l10n();
|
91 |
+
$yoast_components_l10n->localize_script( 'search-appearance' );
|
92 |
+
}
|
93 |
+
|
94 |
wp_enqueue_script( 'dashboard' );
|
95 |
wp_enqueue_script( 'thickbox' );
|
96 |
|
|
|
|
|
97 |
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-script', 'wpseoSelect2Locale', WPSEO_Utils::get_language( WPSEO_Utils::get_user_locale() ) );
|
98 |
|
99 |
if ( in_array( $page, array( 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ), true ) ) {
|
109 |
}
|
110 |
|
111 |
/**
|
112 |
+
* Retrieves some variables that are needed for the upload module in JS.
|
113 |
*
|
114 |
+
* @return array The upload module variables.
|
115 |
*/
|
116 |
public function localize_media_script() {
|
117 |
return array(
|
119 |
);
|
120 |
}
|
121 |
|
122 |
+
/**
|
123 |
+
* Retrieves some variables that are needed for replacing variables in JS.
|
124 |
+
*
|
125 |
+
* @return array The replacement and recommended replacement variables.
|
126 |
+
*/
|
127 |
+
public function localize_replace_vars_script() {
|
128 |
+
$replace_vars = new WPSEO_Replace_Vars();
|
129 |
+
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
|
130 |
+
|
131 |
+
return array(
|
132 |
+
'replace_vars' => $replace_vars->get_replacement_variables_list(),
|
133 |
+
'recommended_replace_vars' => $recommended_replace_vars->get_recommended_replacevars(),
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
/**
|
138 |
* Enqueues and handles all the tool dependencies.
|
139 |
*/
|
admin/class-database-proxy.php
CHANGED
@@ -91,22 +91,47 @@ class WPSEO_Database_Proxy {
|
|
91 |
/**
|
92 |
* Upserts data in the database.
|
93 |
*
|
94 |
-
*
|
95 |
*
|
96 |
* @param array $data Data to update on the table.
|
97 |
-
* @param array $where Where condition as key => value array.
|
98 |
-
* @param null $format Optional.
|
99 |
-
* @param null $where_format
|
100 |
*
|
101 |
* @return false|int False when the upsert request is invalid, int on number of rows changed.
|
102 |
*/
|
103 |
-
public function upsert( array $data, array $where, $format = null, $where_format = null ) {
|
104 |
-
|
|
|
|
|
105 |
|
106 |
-
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
return $result;
|
111 |
}
|
112 |
|
91 |
/**
|
92 |
* Upserts data in the database.
|
93 |
*
|
94 |
+
* Performs an insert into and if key is duplicate it will update the existing record.
|
95 |
*
|
96 |
* @param array $data Data to update on the table.
|
97 |
+
* @param array $where Unused. Where condition as key => value array.
|
98 |
+
* @param null $format Optional. Data prepare format.
|
99 |
+
* @param null $where_format Deprecated. Where prepare format.
|
100 |
*
|
101 |
* @return false|int False when the upsert request is invalid, int on number of rows changed.
|
102 |
*/
|
103 |
+
public function upsert( array $data, array $where = null, $format = null, $where_format = null ) {
|
104 |
+
if ( $where_format !== null ) {
|
105 |
+
_deprecated_argument( __METHOD__, '7.7.0', 'The where_format argument is deprecated' );
|
106 |
+
}
|
107 |
|
108 |
+
$this->pre_execution();
|
109 |
+
|
110 |
+
$update = array();
|
111 |
+
$keys = array();
|
112 |
+
$columns = array_keys( $data );
|
113 |
+
foreach ( $columns as $column ) {
|
114 |
+
$keys[] = '`' . $column . '`';
|
115 |
+
$update[] = sprintf( '`%1$s` = VALUES(`%1$s`)', $column );
|
116 |
}
|
117 |
|
118 |
+
$query = sprintf(
|
119 |
+
'INSERT INTO `%1$s` (%2$s) VALUES ( %3$s ) ON DUPLICATE KEY UPDATE %4$s',
|
120 |
+
$this->get_table_name(),
|
121 |
+
implode( ', ', $keys ),
|
122 |
+
implode( ', ', array_fill( 0, count( $data ), '%s' ) ),
|
123 |
+
implode( ', ', $update )
|
124 |
+
);
|
125 |
+
|
126 |
+
$result = $this->database->query(
|
127 |
+
$this->database->prepare(
|
128 |
+
$query,
|
129 |
+
array_values( $data )
|
130 |
+
)
|
131 |
+
);
|
132 |
+
|
133 |
+
$this->post_execution();
|
134 |
+
|
135 |
return $result;
|
136 |
}
|
137 |
|
admin/class-help-center.php
CHANGED
@@ -104,20 +104,23 @@ class WPSEO_Help_Center {
|
|
104 |
|
105 |
$formatted_data['translations'] = self::get_translated_texts();
|
106 |
|
107 |
-
$formatted_data['videoDescriptions'] = array(
|
108 |
-
|
|
|
|
|
109 |
'title' => __( 'Need some help?', 'wordpress-seo' ),
|
110 |
'description' => __( 'Go Premium and our experts will be there for you to answer any questions you might have about the setup and use of the plugin.', 'wordpress-seo' ),
|
111 |
'link' => WPSEO_Shortlinker::get( 'https://yoa.st/seo-premium-vt' ),
|
112 |
'linkText' => __( 'Get Yoast SEO Premium now »', 'wordpress-seo' ),
|
113 |
-
)
|
114 |
-
|
|
|
115 |
'title' => __( 'Want to be a Yoast SEO Expert?', 'wordpress-seo' ),
|
116 |
'description' => __( 'Follow our Yoast SEO for WordPress training and become a certified Yoast SEO Expert!', 'wordpress-seo' ),
|
117 |
'link' => WPSEO_Shortlinker::get( 'https://yoa.st/wordpress-training-vt' ),
|
118 |
'linkText' => __( 'Enroll in the Yoast SEO for WordPress training »', 'wordpress-seo' ),
|
119 |
-
)
|
120 |
-
|
121 |
|
122 |
$formatted_data['contactSupportParagraphs'] = array(
|
123 |
array(
|
104 |
|
105 |
$formatted_data['translations'] = self::get_translated_texts();
|
106 |
|
107 |
+
$formatted_data['videoDescriptions'] = array();
|
108 |
+
|
109 |
+
if ( $is_premium === false ) {
|
110 |
+
$formatted_data['videoDescriptions'][] = array(
|
111 |
'title' => __( 'Need some help?', 'wordpress-seo' ),
|
112 |
'description' => __( 'Go Premium and our experts will be there for you to answer any questions you might have about the setup and use of the plugin.', 'wordpress-seo' ),
|
113 |
'link' => WPSEO_Shortlinker::get( 'https://yoa.st/seo-premium-vt' ),
|
114 |
'linkText' => __( 'Get Yoast SEO Premium now »', 'wordpress-seo' ),
|
115 |
+
);
|
116 |
+
|
117 |
+
$formatted_data['videoDescriptions'][] = array(
|
118 |
'title' => __( 'Want to be a Yoast SEO Expert?', 'wordpress-seo' ),
|
119 |
'description' => __( 'Follow our Yoast SEO for WordPress training and become a certified Yoast SEO Expert!', 'wordpress-seo' ),
|
120 |
'link' => WPSEO_Shortlinker::get( 'https://yoa.st/wordpress-training-vt' ),
|
121 |
'linkText' => __( 'Enroll in the Yoast SEO for WordPress training »', 'wordpress-seo' ),
|
122 |
+
);
|
123 |
+
}
|
124 |
|
125 |
$formatted_data['contactSupportParagraphs'] = array(
|
126 |
array(
|
admin/class-yoast-alerts.php
CHANGED
@@ -87,7 +87,8 @@ class Yoast_Alerts {
|
|
87 |
|
88 |
$notification = $this->get_notification_from_ajax_request();
|
89 |
if ( $notification ) {
|
90 |
-
|
|
|
91 |
|
92 |
$this->output_ajax_response( $notification->get_type() );
|
93 |
}
|
87 |
|
88 |
$notification = $this->get_notification_from_ajax_request();
|
89 |
if ( $notification ) {
|
90 |
+
$notification_center = Yoast_Notification_Center::get();
|
91 |
+
$notification_center->restore_notification( $notification );
|
92 |
|
93 |
$this->output_ajax_response( $notification->get_type() );
|
94 |
}
|
admin/class-yoast-notification-center.php
CHANGED
@@ -25,12 +25,18 @@ class Yoast_Notification_Center {
|
|
25 |
/** @var array Notifications that were resolved this execution */
|
26 |
private $resolved = 0;
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
* Construct
|
30 |
*/
|
31 |
private function __construct() {
|
32 |
|
33 |
-
$this
|
34 |
|
35 |
add_action( 'all_admin_notices', array( $this, 'display_notifications' ) );
|
36 |
|
@@ -96,7 +102,15 @@ class Yoast_Notification_Center {
|
|
96 |
$user_id = ( ! is_null( $user_id ) ? $user_id : get_current_user_id() );
|
97 |
$dismissal_key = $notification->get_dismissal_key();
|
98 |
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
return ! empty( $current_value );
|
102 |
}
|
@@ -146,6 +160,42 @@ class Yoast_Notification_Center {
|
|
146 |
return self::dismiss_notification( $notification, $meta_value );
|
147 |
}
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
/**
|
150 |
* Clear dismissal information for the specified Notification
|
151 |
*
|
@@ -158,6 +208,8 @@ class Yoast_Notification_Center {
|
|
158 |
*/
|
159 |
public function clear_dismissal( $notification ) {
|
160 |
|
|
|
|
|
161 |
if ( $notification instanceof Yoast_Notification ) {
|
162 |
$dismissal_key = $notification->get_dismissal_key();
|
163 |
}
|
@@ -171,11 +223,36 @@ class Yoast_Notification_Center {
|
|
171 |
}
|
172 |
|
173 |
// Remove notification dismissal for all users.
|
174 |
-
$deleted = delete_metadata( 'user', 0, $dismissal_key, '', true );
|
|
|
|
|
|
|
175 |
|
176 |
return $deleted;
|
177 |
}
|
178 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
/**
|
180 |
* Add notification to the cookie
|
181 |
*
|
@@ -183,6 +260,12 @@ class Yoast_Notification_Center {
|
|
183 |
*/
|
184 |
public function add_notification( Yoast_Notification $notification ) {
|
185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
// Don't add if the user can't see it.
|
187 |
if ( ! $notification->display_for_current_user() ) {
|
188 |
return;
|
@@ -273,6 +356,12 @@ class Yoast_Notification_Center {
|
|
273 |
*/
|
274 |
public function remove_notification( Yoast_Notification $notification, $resolve = true ) {
|
275 |
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
$index = false;
|
277 |
|
278 |
// Match persistent Notifications by ID, non persistent by item in the array.
|
@@ -448,6 +537,12 @@ class Yoast_Notification_Center {
|
|
448 |
*/
|
449 |
private function retrieve_notifications_from_storage() {
|
450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
451 |
$stored_notifications = get_user_option( self::STORAGE_KEY, get_current_user_id() );
|
452 |
|
453 |
// Check if notifications are stored.
|
@@ -492,19 +587,6 @@ class Yoast_Notification_Center {
|
|
492 |
return 0;
|
493 |
}
|
494 |
|
495 |
-
/**
|
496 |
-
* Dismiss the notification
|
497 |
-
*
|
498 |
-
* @param Yoast_Notification $notification Notification to dismiss.
|
499 |
-
* @param string $meta_value Value to save in the dismissal.
|
500 |
-
*
|
501 |
-
* @return bool
|
502 |
-
*/
|
503 |
-
private static function dismiss_notification( Yoast_Notification $notification, $meta_value = 'seen' ) {
|
504 |
-
// Dismiss notification.
|
505 |
-
return ( false !== update_user_meta( get_current_user_id(), $notification->get_dismissal_key(), $meta_value ) );
|
506 |
-
}
|
507 |
-
|
508 |
/**
|
509 |
* Remove all notifications from storage
|
510 |
*/
|
@@ -518,7 +600,8 @@ class Yoast_Notification_Center {
|
|
518 |
*/
|
519 |
private function clear_notifications() {
|
520 |
|
521 |
-
$this->notifications
|
|
|
522 |
}
|
523 |
|
524 |
/**
|
@@ -597,4 +680,32 @@ class Yoast_Notification_Center {
|
|
597 |
private function is_notification_persistent( Yoast_Notification $notification ) {
|
598 |
return ! $notification->is_persistent();
|
599 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
}
|
25 |
/** @var array Notifications that were resolved this execution */
|
26 |
private $resolved = 0;
|
27 |
|
28 |
+
/** @var array Internal storage for transaction before notifications have been retrieved from storage. */
|
29 |
+
private $queued_transactions = array();
|
30 |
+
|
31 |
+
/** @var bool Internal flag for whether notifications have been retrieved from storage. */
|
32 |
+
private $notifications_retrieved = false;
|
33 |
+
|
34 |
/**
|
35 |
* Construct
|
36 |
*/
|
37 |
private function __construct() {
|
38 |
|
39 |
+
add_action( 'init', array( $this, 'setup_current_notifications' ), 1 );
|
40 |
|
41 |
add_action( 'all_admin_notices', array( $this, 'display_notifications' ) );
|
42 |
|
102 |
$user_id = ( ! is_null( $user_id ) ? $user_id : get_current_user_id() );
|
103 |
$dismissal_key = $notification->get_dismissal_key();
|
104 |
|
105 |
+
// This checks both the site-specific user option and the meta value.
|
106 |
+
$current_value = get_user_option( $dismissal_key, $user_id );
|
107 |
+
|
108 |
+
// Migrate old user meta to user option on-the-fly.
|
109 |
+
if ( ! empty( $current_value )
|
110 |
+
&& metadata_exists( 'user', $user_id, $dismissal_key )
|
111 |
+
&& update_user_option( $user_id, $dismissal_key, $current_value ) ) {
|
112 |
+
delete_user_meta( $user_id, $dismissal_key );
|
113 |
+
}
|
114 |
|
115 |
return ! empty( $current_value );
|
116 |
}
|
160 |
return self::dismiss_notification( $notification, $meta_value );
|
161 |
}
|
162 |
|
163 |
+
/**
|
164 |
+
* Dismisses a notification.
|
165 |
+
*
|
166 |
+
* @param Yoast_Notification $notification Notification to dismiss.
|
167 |
+
* @param string $meta_value Value to save in the dismissal.
|
168 |
+
*
|
169 |
+
* @return bool True if dismissed, false otherwise.
|
170 |
+
*/
|
171 |
+
public static function dismiss_notification( Yoast_Notification $notification, $meta_value = 'seen' ) {
|
172 |
+
// Dismiss notification.
|
173 |
+
return update_user_option( get_current_user_id(), $notification->get_dismissal_key(), $meta_value ) !== false;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Restores a notification.
|
178 |
+
*
|
179 |
+
* @param Yoast_Notification $notification Notification to restore.
|
180 |
+
*
|
181 |
+
* @return bool True if restored, false otherwise.
|
182 |
+
*/
|
183 |
+
public static function restore_notification( Yoast_Notification $notification ) {
|
184 |
+
|
185 |
+
$user_id = get_current_user_id();
|
186 |
+
$dismissal_key = $notification->get_dismissal_key();
|
187 |
+
|
188 |
+
// Restore notification.
|
189 |
+
$restored = delete_user_option( $user_id, $dismissal_key );
|
190 |
+
|
191 |
+
// Delete unprefixed user meta too for backward-compatibility.
|
192 |
+
if ( metadata_exists( 'user', $user_id, $dismissal_key ) ) {
|
193 |
+
$restored = delete_user_meta( $user_id, $dismissal_key ) && $restored;
|
194 |
+
}
|
195 |
+
|
196 |
+
return $restored;
|
197 |
+
}
|
198 |
+
|
199 |
/**
|
200 |
* Clear dismissal information for the specified Notification
|
201 |
*
|
208 |
*/
|
209 |
public function clear_dismissal( $notification ) {
|
210 |
|
211 |
+
global $wpdb;
|
212 |
+
|
213 |
if ( $notification instanceof Yoast_Notification ) {
|
214 |
$dismissal_key = $notification->get_dismissal_key();
|
215 |
}
|
223 |
}
|
224 |
|
225 |
// Remove notification dismissal for all users.
|
226 |
+
$deleted = delete_metadata( 'user', 0, $wpdb->get_blog_prefix() . $dismissal_key, '', true );
|
227 |
+
|
228 |
+
// Delete unprefixed user meta too for backward-compatibility.
|
229 |
+
$deleted = delete_metadata( 'user', 0, $dismissal_key, '', true ) || $deleted;
|
230 |
|
231 |
return $deleted;
|
232 |
}
|
233 |
|
234 |
+
/**
|
235 |
+
* Retrieves notifications from the storage and merges in previous notification changes.
|
236 |
+
*
|
237 |
+
* The current user in WordPress is not loaded shortly before the 'init' hook, but the plugin
|
238 |
+
* sometimes needs to add or remove notifications before that. In such cases, the transactions
|
239 |
+
* are not actually executed, but added to a queue. That queue is then handled in this method,
|
240 |
+
* after notifications for the current user have been set up.
|
241 |
+
*
|
242 |
+
* @return void
|
243 |
+
*/
|
244 |
+
public function setup_current_notifications() {
|
245 |
+
$this->retrieve_notifications_from_storage();
|
246 |
+
|
247 |
+
foreach ( $this->queued_transactions as $transaction ) {
|
248 |
+
list( $callback, $args ) = $transaction;
|
249 |
+
|
250 |
+
call_user_func_array( $callback, $args );
|
251 |
+
}
|
252 |
+
|
253 |
+
$this->queued_transactions = array();
|
254 |
+
}
|
255 |
+
|
256 |
/**
|
257 |
* Add notification to the cookie
|
258 |
*
|
260 |
*/
|
261 |
public function add_notification( Yoast_Notification $notification ) {
|
262 |
|
263 |
+
$callback = array( $this, __METHOD__ );
|
264 |
+
$args = func_get_args();
|
265 |
+
if ( $this->queue_transaction( $callback, $args ) ) {
|
266 |
+
return;
|
267 |
+
}
|
268 |
+
|
269 |
// Don't add if the user can't see it.
|
270 |
if ( ! $notification->display_for_current_user() ) {
|
271 |
return;
|
356 |
*/
|
357 |
public function remove_notification( Yoast_Notification $notification, $resolve = true ) {
|
358 |
|
359 |
+
$callback = array( $this, __METHOD__ );
|
360 |
+
$args = func_get_args();
|
361 |
+
if ( $this->queue_transaction( $callback, $args ) ) {
|
362 |
+
return;
|
363 |
+
}
|
364 |
+
|
365 |
$index = false;
|
366 |
|
367 |
// Match persistent Notifications by ID, non persistent by item in the array.
|
537 |
*/
|
538 |
private function retrieve_notifications_from_storage() {
|
539 |
|
540 |
+
if ( $this->notifications_retrieved ) {
|
541 |
+
return;
|
542 |
+
}
|
543 |
+
|
544 |
+
$this->notifications_retrieved = true;
|
545 |
+
|
546 |
$stored_notifications = get_user_option( self::STORAGE_KEY, get_current_user_id() );
|
547 |
|
548 |
// Check if notifications are stored.
|
587 |
return 0;
|
588 |
}
|
589 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
590 |
/**
|
591 |
* Remove all notifications from storage
|
592 |
*/
|
600 |
*/
|
601 |
private function clear_notifications() {
|
602 |
|
603 |
+
$this->notifications = array();
|
604 |
+
$this->notifications_retrieved = false;
|
605 |
}
|
606 |
|
607 |
/**
|
680 |
private function is_notification_persistent( Yoast_Notification $notification ) {
|
681 |
return ! $notification->is_persistent();
|
682 |
}
|
683 |
+
|
684 |
+
/**
|
685 |
+
* Queues a notification transaction for later execution if notifications are not yet set up.
|
686 |
+
*
|
687 |
+
* @param callable $callback Callback that performs the transaction.
|
688 |
+
* @param array $args Arguments to pass to the callback.
|
689 |
+
*
|
690 |
+
* @return bool True if transaction was queued, false if it can be performed immediately.
|
691 |
+
*/
|
692 |
+
private function queue_transaction( $callback, $args ) {
|
693 |
+
if ( $this->notifications_retrieved ) {
|
694 |
+
return false;
|
695 |
+
}
|
696 |
+
|
697 |
+
$this->add_transaction_to_queue( $callback, $args );
|
698 |
+
|
699 |
+
return true;
|
700 |
+
}
|
701 |
+
|
702 |
+
/**
|
703 |
+
* Adds a notification transaction to the queue for later execution.
|
704 |
+
*
|
705 |
+
* @param callable $callback Callback that performs the transaction.
|
706 |
+
* @param array $args Arguments to pass to the callback.
|
707 |
+
*/
|
708 |
+
private function add_transaction_to_queue( $callback, $args ) {
|
709 |
+
$this->queued_transactions[] = array( $callback, $args );
|
710 |
+
}
|
711 |
}
|
admin/class-yoast-notification.php
CHANGED
@@ -62,8 +62,16 @@ class Yoast_Notification {
|
|
62 |
'dismissal_key' => null,
|
63 |
'capabilities' => array(),
|
64 |
'capability_check' => self::MATCH_ALL,
|
|
|
65 |
);
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
/**
|
68 |
* Notification class constructor.
|
69 |
*
|
@@ -282,8 +290,38 @@ class Yoast_Notification {
|
|
282 |
// Combined attribute key and value into a string.
|
283 |
array_walk( $attributes, array( $this, 'parse_attributes' ) );
|
284 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
285 |
// Build the output DIV.
|
286 |
-
return '<div ' . implode( ' ', $attributes ) . '>' .
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
}
|
288 |
|
289 |
/**
|
62 |
'dismissal_key' => null,
|
63 |
'capabilities' => array(),
|
64 |
'capability_check' => self::MATCH_ALL,
|
65 |
+
'yoast_branding' => false,
|
66 |
);
|
67 |
|
68 |
+
/**
|
69 |
+
* The message for the notification.
|
70 |
+
*
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
private $message;
|
74 |
+
|
75 |
/**
|
76 |
* Notification class constructor.
|
77 |
*
|
290 |
// Combined attribute key and value into a string.
|
291 |
array_walk( $attributes, array( $this, 'parse_attributes' ) );
|
292 |
|
293 |
+
$message = null;
|
294 |
+
if ( $this->options['yoast_branding'] ) {
|
295 |
+
$message = $this->wrap_yoast_seo_icon( $this->message );
|
296 |
+
}
|
297 |
+
|
298 |
+
if ( $message === null ) {
|
299 |
+
$message = wpautop( $this->message );
|
300 |
+
}
|
301 |
+
|
302 |
// Build the output DIV.
|
303 |
+
return '<div ' . implode( ' ', $attributes ) . '>' . $message . '</div>' . PHP_EOL;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Wraps the message with a Yoast SEO icon.
|
308 |
+
*
|
309 |
+
* @param string $message The message to wrap.
|
310 |
+
*
|
311 |
+
* @return string The wrapped message.
|
312 |
+
*/
|
313 |
+
private function wrap_yoast_seo_icon( $message ) {
|
314 |
+
$out = sprintf(
|
315 |
+
'<img src="%1$s" height="%2$d" width="%3$d" class="yoast-seo-icon" />',
|
316 |
+
esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/Yoast_SEO_Icon.svg' ),
|
317 |
+
60,
|
318 |
+
60
|
319 |
+
);
|
320 |
+
$out .= '<div class="yoast-seo-icon-wrap">';
|
321 |
+
$out .= $message;
|
322 |
+
$out .= '</div>';
|
323 |
+
|
324 |
+
return $out;
|
325 |
}
|
326 |
|
327 |
/**
|
admin/formatter/class-metabox-formatter.php
CHANGED
@@ -64,7 +64,6 @@ class WPSEO_Metabox_Formatter {
|
|
64 |
'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0,
|
65 |
'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0,
|
66 |
'intl' => $this->get_content_analysis_component_translations(),
|
67 |
-
'reactSnippetPreview' => defined( 'YOAST_FEATURE_SNIPPET_PREVIEW' ) && YOAST_FEATURE_SNIPPET_PREVIEW,
|
68 |
|
69 |
/**
|
70 |
* Filter to determine if the markers should be enabled or not.
|
64 |
'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0,
|
65 |
'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0,
|
66 |
'intl' => $this->get_content_analysis_component_translations(),
|
|
|
67 |
|
68 |
/**
|
69 |
* Filter to determine if the markers should be enabled or not.
|
admin/formatter/class-post-metabox-formatter.php
CHANGED
@@ -153,10 +153,16 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
|
|
153 |
/**
|
154 |
* Retrieves the title template.
|
155 |
*
|
156 |
-
* @return string
|
157 |
*/
|
158 |
private function get_title_template() {
|
159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
|
162 |
/**
|
153 |
/**
|
154 |
* Retrieves the title template.
|
155 |
*
|
156 |
+
* @return string The title template.
|
157 |
*/
|
158 |
private function get_title_template() {
|
159 |
+
$title = $this->get_template( 'title' );
|
160 |
+
|
161 |
+
if ( $title === '' ) {
|
162 |
+
return '%%title%% %%sep%% %%sitename%%';
|
163 |
+
}
|
164 |
+
|
165 |
+
return $title;
|
166 |
}
|
167 |
|
168 |
/**
|
admin/formatter/class-term-metabox-formatter.php
CHANGED
@@ -109,10 +109,16 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
|
|
109 |
/**
|
110 |
* Retrieves the title template.
|
111 |
*
|
112 |
-
* @return string
|
113 |
*/
|
114 |
private function get_title_template() {
|
115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
117 |
|
118 |
/**
|
109 |
/**
|
110 |
* Retrieves the title template.
|
111 |
*
|
112 |
+
* @return string The title template.
|
113 |
*/
|
114 |
private function get_title_template() {
|
115 |
+
$title = $this->get_template( 'title' );
|
116 |
+
|
117 |
+
if ( $title === '' ) {
|
118 |
+
return '%%title%% %%sep%% %%sitename%%';
|
119 |
+
}
|
120 |
+
|
121 |
+
return $title;
|
122 |
}
|
123 |
|
124 |
/**
|
admin/menu/class-replacevar-editor.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WPSEO plugin file.
|
4 |
+
*
|
5 |
+
* @package WPSEO\Admin\Menu
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Renders a replacement variable editor.
|
10 |
+
*/
|
11 |
+
class WPSEO_Replacevar_Editor {
|
12 |
+
/**
|
13 |
+
* @var Yoast_Form Yoast Forms instance.
|
14 |
+
*/
|
15 |
+
private $yform;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string The id for the hidden title field.
|
19 |
+
*/
|
20 |
+
private $title;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string The id for the hidden description field.
|
24 |
+
*/
|
25 |
+
private $description;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string The page type for context.
|
29 |
+
*/
|
30 |
+
private $page_type;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var bool Whether the editor has paper style.
|
34 |
+
*/
|
35 |
+
private $paper_style;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Constructs the object.
|
39 |
+
*
|
40 |
+
* @param Yoast_Form $yform Yoast forms.
|
41 |
+
* @param string $title The title field id.
|
42 |
+
* @param string $description The description field id.
|
43 |
+
* @param string $page_type The page type for context.
|
44 |
+
* @param bool $paper_style Whether the editor has paper style.
|
45 |
+
*/
|
46 |
+
public function __construct( Yoast_Form $yform, $title, $description, $page_type, $paper_style = true ) {
|
47 |
+
$this->yform = $yform;
|
48 |
+
$this->title = (string) $title;
|
49 |
+
$this->description = (string) $description;
|
50 |
+
$this->page_type = (string) $page_type;
|
51 |
+
$this->paper_style = (bool) $paper_style;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Renders a div for the react application to mount to, and hidden inputs where
|
56 |
+
* the app should store it's value so they will be properly saved when the form
|
57 |
+
* is submitted.
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
+
public function render() {
|
62 |
+
$this->yform->hidden( $this->title, $this->title );
|
63 |
+
$this->yform->hidden( $this->description, $this->description );
|
64 |
+
|
65 |
+
printf( '<div
|
66 |
+
data-react-replacevar-editor
|
67 |
+
data-react-replacevar-title-field-id="%1$s"
|
68 |
+
data-react-replacevar-metadesc-field-id="%2$s"
|
69 |
+
data-react-replacevar-page-type="%3$s"
|
70 |
+
data-react-replacevar-paper-style="%4$s"></div>',
|
71 |
+
esc_attr( $this->title ),
|
72 |
+
esc_attr( $this->description ),
|
73 |
+
esc_attr( $this->page_type ),
|
74 |
+
esc_attr( $this->paper_style )
|
75 |
+
);
|
76 |
+
}
|
77 |
+
}
|
admin/menu/class-replacevar-field.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WPSEO plugin file.
|
4 |
+
*
|
5 |
+
* @package WPSEO\Admin\Menu
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Renders a single replacement variable field.
|
10 |
+
*/
|
11 |
+
class WPSEO_Replacevar_Field {
|
12 |
+
/**
|
13 |
+
* @var Yoast_Form Yoast Forms instance.
|
14 |
+
*/
|
15 |
+
private $yform;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string The id for the hidden field.
|
19 |
+
*/
|
20 |
+
private $field_id;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string The label for the field.
|
24 |
+
*/
|
25 |
+
private $label;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string The page type for context.
|
29 |
+
*/
|
30 |
+
private $page_type;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Constructs the object.
|
34 |
+
*
|
35 |
+
* @param Yoast_Form $yform Yoast forms.
|
36 |
+
* @param string $field_id The field id.
|
37 |
+
* @param string $label The field label.
|
38 |
+
* @param string $page_type The page type for context.
|
39 |
+
*/
|
40 |
+
public function __construct( Yoast_Form $yform, $field_id, $label, $page_type ) {
|
41 |
+
$this->yform = $yform;
|
42 |
+
$this->field_id = $field_id;
|
43 |
+
$this->label = $label;
|
44 |
+
$this->page_type = $page_type;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Renders a div for the react application to mount to, and hidden inputs where
|
49 |
+
* the app should store it's value so they will be properly saved when the form
|
50 |
+
* is submitted.
|
51 |
+
*
|
52 |
+
* @return void
|
53 |
+
*/
|
54 |
+
public function render() {
|
55 |
+
$this->yform->hidden( $this->field_id, $this->field_id );
|
56 |
+
|
57 |
+
printf( '<div
|
58 |
+
data-react-replacevar-field
|
59 |
+
data-react-replacevar-field-id="%1$s"
|
60 |
+
data-react-replacevar-field-label="%2$s",
|
61 |
+
data-react-replacevar-page-type="%3$s"></div>',
|
62 |
+
esc_attr( $this->field_id ),
|
63 |
+
esc_attr( $this->label ),
|
64 |
+
esc_attr( $this->page_type )
|
65 |
+
);
|
66 |
+
}
|
67 |
+
}
|
admin/metabox/class-metabox.php
CHANGED
@@ -60,9 +60,6 @@ class WPSEO_Metabox extends WPSEO_Meta {
|
|
60 |
*/
|
61 |
public static function translate_meta_boxes() {
|
62 |
self::$meta_fields['general']['snippetpreview']['title'] = __( 'Snippet editor', 'wordpress-seo' );
|
63 |
-
/* translators: 1: link open tag; 2: link close tag. */
|
64 |
-
self::$meta_fields['general']['snippetpreview']['help'] = sprintf( __( 'This is a rendering of what this post might look like in Google\'s search results. %1$sLearn more about the Snippet Preview%2$s.', 'wordpress-seo' ), '<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/snippet-preview' ) . '">', '</a>' );
|
65 |
-
self::$meta_fields['general']['snippetpreview']['help-button'] = __( 'Show information about the snippet editor', 'wordpress-seo' );
|
66 |
|
67 |
self::$meta_fields['general']['pageanalysis']['title'] = __( 'Analysis', 'wordpress-seo' );
|
68 |
/* translators: 1: link open tag; 2: link close tag. */
|
@@ -257,9 +254,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
|
|
257 |
*/
|
258 |
public function localize_replace_vars_script() {
|
259 |
return array(
|
260 |
-
'no_parent_text'
|
261 |
-
'replace_vars'
|
262 |
-
'
|
|
|
263 |
);
|
264 |
}
|
265 |
|
@@ -985,11 +983,6 @@ class WPSEO_Metabox extends WPSEO_Meta {
|
|
985 |
'sitedesc',
|
986 |
'sep',
|
987 |
'page',
|
988 |
-
'currenttime',
|
989 |
-
'currentdate',
|
990 |
-
'currentday',
|
991 |
-
'currentmonth',
|
992 |
-
'currentyear',
|
993 |
);
|
994 |
|
995 |
foreach ( $vars_to_cache as $var ) {
|
@@ -1000,6 +993,21 @@ class WPSEO_Metabox extends WPSEO_Meta {
|
|
1000 |
return array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $post ) );
|
1001 |
}
|
1002 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1003 |
/**
|
1004 |
* Gets the custom replace variables for custom taxonomies and fields.
|
1005 |
*
|
60 |
*/
|
61 |
public static function translate_meta_boxes() {
|
62 |
self::$meta_fields['general']['snippetpreview']['title'] = __( 'Snippet editor', 'wordpress-seo' );
|
|
|
|
|
|
|
63 |
|
64 |
self::$meta_fields['general']['pageanalysis']['title'] = __( 'Analysis', 'wordpress-seo' );
|
65 |
/* translators: 1: link open tag; 2: link close tag. */
|
254 |
*/
|
255 |
public function localize_replace_vars_script() {
|
256 |
return array(
|
257 |
+
'no_parent_text' => __( '(no parent)', 'wordpress-seo' ),
|
258 |
+
'replace_vars' => $this->get_replace_vars(),
|
259 |
+
'recommended_replace_vars' => $this->get_recommended_replace_vars(),
|
260 |
+
'scope' => $this->determine_scope(),
|
261 |
);
|
262 |
}
|
263 |
|
983 |
'sitedesc',
|
984 |
'sep',
|
985 |
'page',
|
|
|
|
|
|
|
|
|
|
|
986 |
);
|
987 |
|
988 |
foreach ( $vars_to_cache as $var ) {
|
993 |
return array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $post ) );
|
994 |
}
|
995 |
|
996 |
+
/**
|
997 |
+
* Prepares the recommended replace vars for localization.
|
998 |
+
*
|
999 |
+
* @return array Recommended replacement variables.
|
1000 |
+
*/
|
1001 |
+
private function get_recommended_replace_vars() {
|
1002 |
+
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
|
1003 |
+
$post = $this->get_metabox_post();
|
1004 |
+
|
1005 |
+
// What is recommended depends on the current context.
|
1006 |
+
$post_type = $recommended_replace_vars->determine_for_post( $post );
|
1007 |
+
|
1008 |
+
return $recommended_replace_vars->get_recommended_replacevars_for( $post_type );
|
1009 |
+
}
|
1010 |
+
|
1011 |
/**
|
1012 |
* Gets the custom replace variables for custom taxonomies and fields.
|
1013 |
*
|
admin/taxonomy/class-taxonomy-content-fields.php
CHANGED
@@ -20,12 +20,7 @@ class WPSEO_Taxonomy_Content_Fields extends WPSEO_Taxonomy_Fields {
|
|
20 |
'snippet' => $this->get_field_config(
|
21 |
__( 'Snippet editor', 'wordpress-seo' ),
|
22 |
'',
|
23 |
-
'snippetpreview'
|
24 |
-
array(
|
25 |
-
'help-button' => __( 'Show information about the snippet editor', 'wordpress-seo' ),
|
26 |
-
/* translators: 1: link open tag; 2: link close tag. */
|
27 |
-
'help' => sprintf( __( 'This is a rendering of what this post might look like in Google\'s search results. %1$sLearn more about the Snippet Preview%2$s.', 'wordpress-seo' ), '<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/snippet-preview' ) . '">', '</a>' ),
|
28 |
-
)
|
29 |
),
|
30 |
'focuskw' => $this->get_field_config(
|
31 |
__( 'Focus keyword', 'wordpress-seo' ),
|
20 |
'snippet' => $this->get_field_config(
|
21 |
__( 'Snippet editor', 'wordpress-seo' ),
|
22 |
'',
|
23 |
+
'snippetpreview'
|
|
|
|
|
|
|
|
|
|
|
24 |
),
|
25 |
'focuskw' => $this->get_field_config(
|
26 |
__( 'Focus keyword', 'wordpress-seo' ),
|
admin/taxonomy/class-taxonomy.php
CHANGED
@@ -234,9 +234,10 @@ class WPSEO_Taxonomy {
|
|
234 |
*/
|
235 |
public function localize_replace_vars_script() {
|
236 |
return array(
|
237 |
-
'no_parent_text'
|
238 |
-
'replace_vars'
|
239 |
-
'
|
|
|
240 |
);
|
241 |
}
|
242 |
|
@@ -302,7 +303,7 @@ class WPSEO_Taxonomy {
|
|
302 |
/**
|
303 |
* Prepares the replace vars for localization.
|
304 |
*
|
305 |
-
* @return array
|
306 |
*/
|
307 |
private function get_replace_vars() {
|
308 |
$term_id = filter_input( INPUT_GET, 'tag_ID' );
|
@@ -317,11 +318,6 @@ class WPSEO_Taxonomy {
|
|
317 |
'sitedesc',
|
318 |
'sep',
|
319 |
'page',
|
320 |
-
'currenttime',
|
321 |
-
'currentdate',
|
322 |
-
'currentday',
|
323 |
-
'currentmonth',
|
324 |
-
'currentyear',
|
325 |
'term_title',
|
326 |
'term_description',
|
327 |
'category_description',
|
@@ -336,6 +332,21 @@ class WPSEO_Taxonomy {
|
|
336 |
return $cached_replacement_vars;
|
337 |
}
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
/**
|
340 |
* Adds custom category description editor.
|
341 |
* Needs a hook that runs before the description field. Prior to WP version 4.5 we need to use edit_form as
|
234 |
*/
|
235 |
public function localize_replace_vars_script() {
|
236 |
return array(
|
237 |
+
'no_parent_text' => __( '(no parent)', 'wordpress-seo' ),
|
238 |
+
'replace_vars' => $this->get_replace_vars(),
|
239 |
+
'recommended_replace_vars' => $this->get_recommended_replace_vars(),
|
240 |
+
'scope' => $this->determine_scope(),
|
241 |
);
|
242 |
}
|
243 |
|
303 |
/**
|
304 |
* Prepares the replace vars for localization.
|
305 |
*
|
306 |
+
* @return array The replacement variables.
|
307 |
*/
|
308 |
private function get_replace_vars() {
|
309 |
$term_id = filter_input( INPUT_GET, 'tag_ID' );
|
318 |
'sitedesc',
|
319 |
'sep',
|
320 |
'page',
|
|
|
|
|
|
|
|
|
|
|
321 |
'term_title',
|
322 |
'term_description',
|
323 |
'category_description',
|
332 |
return $cached_replacement_vars;
|
333 |
}
|
334 |
|
335 |
+
/**
|
336 |
+
* Prepares the recommended replace vars for localization.
|
337 |
+
*
|
338 |
+
* @return array The recommended replacement variables.
|
339 |
+
*/
|
340 |
+
private function get_recommended_replace_vars() {
|
341 |
+
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
|
342 |
+
$taxonomy = filter_input( INPUT_GET, 'taxonomy' );
|
343 |
+
|
344 |
+
// What is recommended depends on the current context.
|
345 |
+
$page_type = $recommended_replace_vars->determine_for_term( $taxonomy );
|
346 |
+
|
347 |
+
return $recommended_replace_vars->get_recommended_replacevars_for( $page_type );
|
348 |
+
}
|
349 |
+
|
350 |
/**
|
351 |
* Adds custom category description editor.
|
352 |
* Needs a hook that runs before the description field. Prior to WP version 4.5 we need to use edit_form as
|
admin/views/class-view-utils.php
CHANGED
@@ -72,13 +72,7 @@ class Yoast_View_Utils {
|
|
72 |
}
|
73 |
|
74 |
$show_post_type_help = $this->search_results_setting_help( $post_type );
|
75 |
-
|
76 |
$noindex_option_name = 'noindex-' . $post_type->name;
|
77 |
-
$this->form->index_switch(
|
78 |
-
$noindex_option_name,
|
79 |
-
$post_type->labels->name,
|
80 |
-
$show_post_type_help->get_button_html() . $show_post_type_help->get_panel_html()
|
81 |
-
);
|
82 |
|
83 |
if ( WPSEO_Options::get( 'is-media-purge-relevant' ) ) {
|
84 |
if ( $post_type->name === 'attachment' && WPSEO_Options::get( $noindex_option_name ) === false ) {
|
@@ -97,16 +91,10 @@ you want more information about the impact of showing media in search results.',
|
|
97 |
}
|
98 |
}
|
99 |
|
100 |
-
$this->form->
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
);
|
105 |
-
|
106 |
-
$this->form->textarea(
|
107 |
-
'metadesc-' . $post_type->name,
|
108 |
-
__( 'Meta description template', 'wordpress-seo' ),
|
109 |
-
array( 'class' => 'template posttype-template' )
|
110 |
);
|
111 |
|
112 |
$this->form->show_hide_switch(
|
@@ -119,5 +107,11 @@ you want more information about the impact of showing media in search results.',
|
|
119 |
/* translators: %1$s expands to Yoast SEO */
|
120 |
sprintf( __( '%1$s Meta Box', 'wordpress-seo' ), 'Yoast SEO' )
|
121 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
}
|
123 |
}
|
72 |
}
|
73 |
|
74 |
$show_post_type_help = $this->search_results_setting_help( $post_type );
|
|
|
75 |
$noindex_option_name = 'noindex-' . $post_type->name;
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
if ( WPSEO_Options::get( 'is-media-purge-relevant' ) ) {
|
78 |
if ( $post_type->name === 'attachment' && WPSEO_Options::get( $noindex_option_name ) === false ) {
|
91 |
}
|
92 |
}
|
93 |
|
94 |
+
$this->form->index_switch(
|
95 |
+
$noindex_option_name,
|
96 |
+
$post_type->labels->name,
|
97 |
+
$show_post_type_help->get_button_html() . $show_post_type_help->get_panel_html()
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
);
|
99 |
|
100 |
$this->form->show_hide_switch(
|
107 |
/* translators: %1$s expands to Yoast SEO */
|
108 |
sprintf( __( '%1$s Meta Box', 'wordpress-seo' ), 'Yoast SEO' )
|
109 |
);
|
110 |
+
|
111 |
+
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
|
112 |
+
$page_type = $recommended_replace_vars->determine_for_post_type( $post_type->name );
|
113 |
+
|
114 |
+
$editor = new WPSEO_Replacevar_Editor( $this->form, 'title-' . $post_type->name, 'metadesc-' . $post_type->name, $page_type, false );
|
115 |
+
$editor->render();
|
116 |
}
|
117 |
}
|
admin/views/tabs/metas/archives.php
CHANGED
@@ -87,8 +87,8 @@ $yform->index_switch(
|
|
87 |
$author_archives_no_posts_help->get_button_html() . $author_archives_no_posts_help->get_panel_html()
|
88 |
);
|
89 |
|
90 |
-
$
|
91 |
-
$
|
92 |
echo '</div>';
|
93 |
echo '</div>';
|
94 |
|
@@ -119,8 +119,8 @@ $yform->index_switch(
|
|
119 |
$date_archives_help->get_button_html() . $date_archives_help->get_panel_html()
|
120 |
);
|
121 |
|
122 |
-
$
|
123 |
-
$
|
124 |
echo '</div>';
|
125 |
echo '</div>';
|
126 |
|
@@ -139,10 +139,9 @@ echo '<div class="tab-block" id="special-pages-titles-metas">';
|
|
139 |
echo '<h2 class="help-button-inline">' . esc_html__( 'Special Pages', 'wordpress-seo' ) . $spcia_pages_help->get_button_html() . '</h2>';
|
140 |
echo $spcia_pages_help->get_panel_html();
|
141 |
|
142 |
-
|
143 |
-
$
|
144 |
-
echo '
|
145 |
-
|
146 |
-
$
|
147 |
-
echo '</p>';
|
148 |
echo '</div>';
|
87 |
$author_archives_no_posts_help->get_button_html() . $author_archives_no_posts_help->get_panel_html()
|
88 |
);
|
89 |
|
90 |
+
$editor = new WPSEO_Replacevar_Editor( $yform, 'title-author-wpseo', 'metadesc-author-wpseo', 'author_archive' );
|
91 |
+
$editor->render();
|
92 |
echo '</div>';
|
93 |
echo '</div>';
|
94 |
|
119 |
$date_archives_help->get_button_html() . $date_archives_help->get_panel_html()
|
120 |
);
|
121 |
|
122 |
+
$editor = new WPSEO_Replacevar_Editor( $yform, 'title-archive-wpseo', 'metadesc-archive-wpseo', 'date_archive' );
|
123 |
+
$editor->render();
|
124 |
echo '</div>';
|
125 |
echo '</div>';
|
126 |
|
139 |
echo '<h2 class="help-button-inline">' . esc_html__( 'Special Pages', 'wordpress-seo' ) . $spcia_pages_help->get_button_html() . '</h2>';
|
140 |
echo $spcia_pages_help->get_panel_html();
|
141 |
|
142 |
+
$editor = new WPSEO_Replacevar_Field( $yform, 'title-search-wpseo', __( 'Search pages', 'wordpress-seo' ), 'search' );
|
143 |
+
$editor->render();
|
144 |
+
echo '<br/>';
|
145 |
+
$editor = new WPSEO_Replacevar_Field( $yform, 'title-404-wpseo', __( '404 pages', 'wordpress-seo' ), '404' );
|
146 |
+
$editor->render();
|
|
|
147 |
echo '</div>';
|
admin/views/tabs/metas/general/homepage.php
CHANGED
@@ -20,8 +20,9 @@
|
|
20 |
|
21 |
echo '<h2 class="help-button-inline">', esc_html__( 'Homepage', 'wordpress-seo' ), $homepage_help->get_button_html(), '</h2>';
|
22 |
echo $homepage_help->get_panel_html();
|
23 |
-
|
24 |
-
$
|
|
|
25 |
}
|
26 |
else {
|
27 |
echo '<h2>', esc_html__( 'Homepage & Front page', 'wordpress-seo' ), '</h2>';
|
20 |
|
21 |
echo '<h2 class="help-button-inline">', esc_html__( 'Homepage', 'wordpress-seo' ), $homepage_help->get_button_html(), '</h2>';
|
22 |
echo $homepage_help->get_panel_html();
|
23 |
+
|
24 |
+
$editor = new WPSEO_Replacevar_Editor( $yform, 'title-home-wpseo', 'metadesc-home-wpseo', 'homepage' );
|
25 |
+
$editor->render();
|
26 |
}
|
27 |
else {
|
28 |
echo '<h2>', esc_html__( 'Homepage & Front page', 'wordpress-seo' ), '</h2>';
|
admin/views/tabs/metas/post-types.php
CHANGED
@@ -6,6 +6,8 @@
|
|
6 |
*/
|
7 |
|
8 |
/**
|
|
|
|
|
9 |
* @var Yoast_Form $yform
|
10 |
*/
|
11 |
|
@@ -27,12 +29,69 @@ $post_types = WPSEO_Post_Type::filter_attachment_post_type( $post_types );
|
|
27 |
|
28 |
$view_utils = new Yoast_View_Utils();
|
29 |
|
|
|
|
|
|
|
|
|
30 |
if ( is_array( $post_types ) && $post_types !== array() ) {
|
31 |
-
foreach ( $post_types as $post_type ) {
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
$view_utils->show_post_type_settings( $post_type );
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* Allow adding a custom checkboxes to the admin meta page - Post Types tab
|
38 |
*
|
@@ -40,45 +99,8 @@ if ( is_array( $post_types ) && $post_types !== array() ) {
|
|
40 |
* @api String $name The post type name
|
41 |
*/
|
42 |
do_action( 'wpseo_admin_page_meta_post_types', $yform, $post_type->name );
|
43 |
-
}
|
44 |
-
unset( $post_type );
|
45 |
-
}
|
46 |
-
|
47 |
-
$post_types = get_post_types(
|
48 |
-
array(
|
49 |
-
'_builtin' => false,
|
50 |
-
'has_archive' => true,
|
51 |
-
),
|
52 |
-
'objects'
|
53 |
-
);
|
54 |
|
55 |
-
|
56 |
-
echo '<h2>' . esc_html__( 'Custom Content Type Archives', 'wordpress-seo' ) . '</h2>';
|
57 |
-
echo '<p>' . esc_html__( 'Note: instead of templates these are the actual titles and meta descriptions for these custom content type archive pages.', 'wordpress-seo' ) . '</p>';
|
58 |
-
foreach ( $post_types as $post_type ) {
|
59 |
-
$name = $post_type->name;
|
60 |
-
echo '<div class="tab-block">';
|
61 |
-
echo '<h3>' . esc_html( ucfirst( $post_type->labels->name ) ) . '</h3>';
|
62 |
-
|
63 |
-
$custom_post_type_archive_help = $view_utils->search_results_setting_help( $post_type, 'archive' );
|
64 |
-
|
65 |
-
$yform->index_switch(
|
66 |
-
'noindex-ptarchive-' . $name,
|
67 |
-
sprintf(
|
68 |
-
/* translators: %s expands to the post type's name. */
|
69 |
-
__( 'the archive for %s', 'wordpress-seo' ),
|
70 |
-
$post_type->labels->name
|
71 |
-
),
|
72 |
-
$custom_post_type_archive_help->get_button_html() . $custom_post_type_archive_help->get_panel_html()
|
73 |
-
);
|
74 |
-
|
75 |
-
$yform->textinput( 'title-ptarchive-' . $name, __( 'Title', 'wordpress-seo' ), 'template posttype-template' );
|
76 |
-
$yform->textarea( 'metadesc-ptarchive-' . $name, __( 'Meta description', 'wordpress-seo' ), array( 'class' => 'template posttype-template' ) );
|
77 |
-
if ( WPSEO_Options::get( 'breadcrumbs-enable' ) === true ) {
|
78 |
-
$yform->textinput( 'bctitle-ptarchive-' . $name, __( 'Breadcrumbs title', 'wordpress-seo' ) );
|
79 |
-
}
|
80 |
echo '</div>';
|
81 |
}
|
82 |
-
unset( $post_type );
|
83 |
}
|
84 |
-
unset( $post_types );
|
6 |
*/
|
7 |
|
8 |
/**
|
9 |
+
* Form object.
|
10 |
+
*
|
11 |
* @var Yoast_Form $yform
|
12 |
*/
|
13 |
|
29 |
|
30 |
$view_utils = new Yoast_View_Utils();
|
31 |
|
32 |
+
echo '<p>';
|
33 |
+
esc_html_e( 'The settings on this page allow you to specify what the default search appearance should be for any type of content you have. You can choose which content types appear in search results and what their default description should be.', 'wordpress-seo' );
|
34 |
+
echo '</p>';
|
35 |
+
|
36 |
if ( is_array( $post_types ) && $post_types !== array() ) {
|
37 |
+
foreach ( $post_types as $id => $post_type ) {
|
38 |
+
$single_label = $post_type->labels->singular_name;
|
39 |
+
$plural_label = $post_type->labels->name;
|
40 |
+
|
41 |
+
echo '<div class="paper tab-block" id="' . esc_attr( $post_type->name . '-titles-metas' ) . '">';
|
42 |
+
|
43 |
+
$toggle_icon = 'dashicons-arrow-up-alt2';
|
44 |
+
$class = 'toggleable-container';
|
45 |
+
|
46 |
+
if ( $id !== 'post' ) {
|
47 |
+
$toggle_icon = 'dashicons-arrow-down-alt2';
|
48 |
+
$class .= ' toggleable-container-hidden';
|
49 |
+
}
|
50 |
+
|
51 |
+
printf(
|
52 |
+
'<h2 id="%s">%s (<code>%s</code>) <button class="toggleable-container-trigger"><span class="toggleable-container-icon dashicons %s"></span></button></h2>',
|
53 |
+
esc_attr( $post_type->name ),
|
54 |
+
esc_html( $plural_label ),
|
55 |
+
esc_html( $post_type->name ),
|
56 |
+
$toggle_icon
|
57 |
+
);
|
58 |
+
|
59 |
+
echo '<div class="' . $class . '">';
|
60 |
+
|
61 |
+
// translators: %s is the singular version of the post type's name.
|
62 |
+
echo '<h3>' . esc_html( sprintf( __( 'Settings for single %s URLs', 'wordpress-seo' ), $single_label ) ) . '</h3>';
|
63 |
+
|
64 |
$view_utils->show_post_type_settings( $post_type );
|
65 |
+
|
66 |
+
if ( $post_type->has_archive === true ) {
|
67 |
+
// translators: %s is the plural version of the post type's name.
|
68 |
+
echo '<h3>' . esc_html( sprintf( __( 'Settings for %s archive', 'wordpress-seo' ), $plural_label ) ) . '</h3>';
|
69 |
+
|
70 |
+
$custom_post_type_archive_help = $view_utils->search_results_setting_help( $post_type, 'archive' );
|
71 |
+
|
72 |
+
$yform->index_switch(
|
73 |
+
'noindex-ptarchive-' . $post_type->name,
|
74 |
+
sprintf(
|
75 |
+
/* translators: %s expands to the post type's name. */
|
76 |
+
__( 'the archive for %s', 'wordpress-seo' ),
|
77 |
+
$plural_label
|
78 |
+
),
|
79 |
+
$custom_post_type_archive_help->get_button_html() . $custom_post_type_archive_help->get_panel_html()
|
80 |
+
);
|
81 |
+
|
82 |
+
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
|
83 |
+
$page_type = $recommended_replace_vars->determine_for_archive( $post_type->name );
|
84 |
+
|
85 |
+
$editor = new WPSEO_Replacevar_Editor( $yform, 'title-ptarchive-' . $post_type->name, 'metadesc-ptarchive-' . $post_type->name, $page_type, false );
|
86 |
+
$editor->render();
|
87 |
+
|
88 |
+
if ( WPSEO_Options::get( 'breadcrumbs-enable' ) === true ) {
|
89 |
+
// translators: %s is the plural version of the post type's name.
|
90 |
+
echo '<h4>' . esc_html( sprintf( __( 'Breadcrumb settings for %s archive', 'wordpress-seo' ), $plural_label ) ) . '</h4>';
|
91 |
+
$yform->textinput( 'bctitle-ptarchive-' . $post_type->name, __( 'Breadcrumbs title', 'wordpress-seo' ) );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
/**
|
96 |
* Allow adding a custom checkboxes to the admin meta page - Post Types tab
|
97 |
*
|
99 |
* @api String $name The post type name
|
100 |
*/
|
101 |
do_action( 'wpseo_admin_page_meta_post_types', $yform, $post_type->name );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
|
103 |
+
echo '</div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<