PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.8
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.8
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / alerts / application / default-seo-data / default-seo-data-alert.php

default-seo-data-alert.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.8, at src/alerts/application/default-seo-data/default-seo-data-alert.php

204 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4 namespace Yoast\WP\SEO\Alerts\Application\Default_SEO_Data;
5
6 use Yoast\WP\SEO\Alerts\Infrastructure\Default_SEO_Data\Default_SEO_Data_Collector;
7 use Yoast\WP\SEO\Conditionals\Admin_Conditional;
8 use Yoast\WP\SEO\Helpers\Indexable_Helper;
9 use Yoast\WP\SEO\Helpers\Post_Type_Helper;
10 use Yoast\WP\SEO\Helpers\Product_Helper;
11 use Yoast\WP\SEO\Helpers\Short_Link_Helper;
12 use Yoast\WP\SEO\Integrations\Integration_Interface;
13 use Yoast_Notification;
14 use Yoast_Notification_Center;
15
16 /**
17 * Default_SEO_Data_Alert class.
18 */
19 class Default_SEO_Data_Alert implements Integration_Interface {
20
21 public const NOTIFICATION_ID = 'wpseo-default-seo-data';
22
23 /**
24 * The notifications center.
25 *
26 * @var Yoast_Notification_Center
27 */
28 private $notification_center;
29
30 /**
31 * The default SEO data collector.
32 *
33 * @var Default_SEO_Data_Collector
34 */
35 private $default_seo_data_collector;
36
37 /**
38 * The short link helper.
39 *
40 * @var Short_Link_Helper
41 */
42 private $short_link_helper;
43
44 /**
45 * The product helper.
46 *
47 * @var Product_Helper
48 */
49 private $product_helper;
50
51 /**
52 * The indexable helper.
53 *
54 * @var Indexable_Helper
55 */
56 private $indexable_helper;
57
58 /**
59 * The post type helper.
60 *
61 * @var Post_Type_Helper
62 */
63 private $post_type_helper;
64
65 /**
66 * Default_SEO_Data_Alert constructor.
67 *
68 * @param Yoast_Notification_Center $notification_center The notification center.
69 * @param Default_SEO_Data_Collector $default_seo_data_collector The default SEO data collector.
70 * @param Short_Link_Helper $short_link_helper The short link helper.
71 * @param Product_Helper $product_helper The product helper.
72 * @param Indexable_Helper $indexable_helper The indexable helper.
73 * @param Post_Type_Helper $post_type_helper The post type helper.
74 */
75 public function __construct(
76 Yoast_Notification_Center $notification_center,
77 Default_SEO_Data_Collector $default_seo_data_collector,
78 Short_Link_Helper $short_link_helper,
79 Product_Helper $product_helper,
80 Indexable_Helper $indexable_helper,
81 Post_Type_Helper $post_type_helper
82 ) {
83 $this->notification_center = $notification_center;
84 $this->default_seo_data_collector = $default_seo_data_collector;
85 $this->short_link_helper = $short_link_helper;
86 $this->product_helper = $product_helper;
87 $this->indexable_helper = $indexable_helper;
88 $this->post_type_helper = $post_type_helper;
89 }
90
91 /**
92 * Returns the conditionals based on which this loadable should be active.
93 *
94 * @return array<string>
95 */
96 public static function get_conditionals() {
97 return [ Admin_Conditional::class ];
98 }
99
100 /**
101 * Initializes the integration.
102 *
103 * @return void
104 */
105 public function register_hooks() {
106 \add_action( 'admin_init', [ $this, 'add_notifications' ] );
107 }
108
109 /**
110 * Adds notifications (when necessary).
111 *
112 * We want to show this notification only when there are enough posts that have the default SEO title or meta description, or both.
113 * If this is not the case we will not show the notification at all since it does not serve a purpose yet.
114 *
115 * @return void
116 */
117 public function add_notifications() {
118 if ( ! $this->indexable_helper->should_index_indexables() ) {
119 // Do not show the notification when indexables are disabled.
120 $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID );
121 return;
122 }
123
124 if ( ! $this->post_type_helper->is_indexable( 'post' ) || ! $this->post_type_helper->has_metabox( 'post' ) ) {
125 // Do not show the notification when posts are not indexable or have no metabox.
126 $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID );
127 return;
128 }
129
130 $posts_with_default_seo_title = $this->default_seo_data_collector->get_posts_with_default_seo_title();
131 $posts_with_default_seo_description = $this->default_seo_data_collector->get_posts_with_default_seo_description();
132
133 $has_enough_posts_with_default_title = \count( $posts_with_default_seo_title ) > 4;
134 $has_enough_posts_with_default_desc = \count( $posts_with_default_seo_description ) > 4;
135
136 if ( ! $has_enough_posts_with_default_title && ! $has_enough_posts_with_default_desc ) {
137 $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID );
138 return;
139 }
140
141 $notification = $this->get_default_seo_data_notification( $has_enough_posts_with_default_title, $has_enough_posts_with_default_desc );
142
143 $this->notification_center->add_notification( $notification );
144 }
145
146 /**
147 * Build the default SEO data notification.
148 *
149 * @param bool $has_enough_posts_with_default_title Whether there are content types with default SEO title in their most recent posts.
150 * @param bool $has_enough_posts_with_default_desc Whether there are content types with default SEO description in their most recent posts.
151 *
152 * @return Yoast_Notification The notification containing the suggested plugin.
153 */
154 private function get_default_seo_data_notification( $has_enough_posts_with_default_title, $has_enough_posts_with_default_desc ): Yoast_Notification {
155 $message = $this->get_default_seo_data_message( $has_enough_posts_with_default_title, $has_enough_posts_with_default_desc );
156
157 return new Yoast_Notification(
158 $message,
159 [
160 'id' => self::NOTIFICATION_ID,
161 'type' => Yoast_Notification::WARNING,
162 'capabilities' => [ 'wpseo_manage_options' ],
163 ],
164 );
165 }
166
167 /**
168 * Creates a message to inform users that they are using only default SEO data lately.
169 *
170 * @param bool $has_enough_posts_with_default_title Whether there are content types with default SEO title in their most recent posts.
171 * @param bool $has_enough_posts_with_default_desc Whether there are content types with default SEO description in their most recent posts.
172 *
173 * @return string The default SEO data message.
174 */
175 private function get_default_seo_data_message( $has_enough_posts_with_default_title, $has_enough_posts_with_default_desc ): string {
176 $shortlink = ( $this->product_helper->is_premium() ) ? $this->short_link_helper->get( 'https://yoa.st/ai-generate-alert-premium/' ) : $this->short_link_helper->get( 'https://yoa.st/ai-generate-alert-free/' );
177
178 if ( $has_enough_posts_with_default_title && $has_enough_posts_with_default_desc ) {
179 $default_seo_data = \esc_html__( 'SEO titles and meta descriptions', 'wordpress-seo' );
180 }
181 elseif ( $has_enough_posts_with_default_title ) {
182 $default_seo_data = \esc_html__( 'SEO titles', 'wordpress-seo' );
183 }
184 elseif ( $has_enough_posts_with_default_desc ) {
185 $default_seo_data = \esc_html__( 'meta descriptions', 'wordpress-seo' );
186 }
187 else {
188 $default_seo_data = \esc_html__( 'SEO data', 'wordpress-seo' );
189 }
190
191 /* translators: %1$s expands to "SEO title" or "meta description", %2$s expands to an opening link tag, %3$s expands to an opening strong tag, %4$s expands to a closing strong tag, %5$s expands to a closing link tag. */
192 $message = ( $this->product_helper->is_premium() ) ? \esc_html__( 'Your recent posts are using default %1$s, which can make them easy to overlook in search results. Update them manually or %2$sfind out how %3$sYoast AI Generate%4$s can improve them for you.%5$s', 'wordpress-seo' ) : \esc_html__( 'Your recent posts are using default %1$s, which can make them easy to overlook in search results. Update them for better visibility or %2$stry %3$sYoast AI Generate%4$s for free to do it faster.%5$s', 'wordpress-seo' );
193
194 return \sprintf(
195 $message,
196 $default_seo_data,
197 '<a href="' . \esc_url( $shortlink ) . '" target="_blank">',
198 '<strong>',
199 '</strong>',
200 '</a>',
201 );
202 }
203 }
204