PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.3
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.3
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 / introductions / user-interface / introductions-integration.php

introductions-integration.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.3, at src/introductions/user-interface/introductions-integration.php

220 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Introductions\User_Interface;
4
5 use WPSEO_Admin_Asset_Manager;
6 use Yoast\WP\SEO\Conditionals\Admin_Conditional;
7 use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional;
8 use Yoast\WP\SEO\Helpers\Product_Helper;
9 use Yoast\WP\SEO\Helpers\Short_Link_Helper;
10 use Yoast\WP\SEO\Helpers\User_Helper;
11 use Yoast\WP\SEO\Integrations\Integration_Interface;
12 use Yoast\WP\SEO\Introductions\Application\Current_Page_Trait;
13 use Yoast\WP\SEO\Introductions\Application\Introductions_Collector;
14 use Yoast\WP\SEO\Introductions\Infrastructure\Introductions_Seen_Repository;
15 use Yoast\WP\SEO\Introductions\Infrastructure\Wistia_Embed_Permission_Repository;
16
17 /**
18 * Loads introduction modal scripts, when there are applicable introductions.
19 */
20 class Introductions_Integration implements Integration_Interface {
21
22 use Current_Page_Trait;
23
24 public const SCRIPT_HANDLE = 'introductions';
25
26 /**
27 * Holds the admin asset manager.
28 *
29 * @var WPSEO_Admin_Asset_Manager
30 */
31 private $admin_asset_manager;
32
33 /**
34 * Holds the introduction collector.
35 *
36 * @var Introductions_Collector
37 */
38 private $introductions_collector;
39
40 /**
41 * Holds the product helper.
42 *
43 * @var Product_Helper
44 */
45 private $product_helper;
46
47 /**
48 * Holds the user helper.
49 *
50 * @var User_Helper
51 */
52 private $user_helper;
53
54 /**
55 * Holds the short link helper.
56 *
57 * @var Short_Link_Helper
58 */
59 private $short_link_helper;
60
61 /**
62 * Holds the repository.
63 *
64 * @var Wistia_Embed_Permission_Repository
65 */
66 private $wistia_embed_permission_repository;
67
68 /**
69 * Holds the WooCommerce conditional.
70 *
71 * @var WooCommerce_Conditional
72 */
73 private $woocommerce_conditional;
74
75 /**
76 * Returns the conditionals based in which this loadable should be active.
77 *
78 * In this case: when on an admin page.
79 *
80 * @return array<string>
81 */
82 public static function get_conditionals() {
83 return [ Admin_Conditional::class ];
84 }
85
86 /**
87 * Constructs the integration.
88 *
89 * @param WPSEO_Admin_Asset_Manager $admin_asset_manager The admin asset manager.
90 * @param Introductions_Collector $introductions_collector The introductions' collector.
91 * @param Product_Helper $product_helper The product helper.
92 * @param User_Helper $user_helper The user helper.
93 * @param Short_Link_Helper $short_link_helper The short link helper.
94 * @param Wistia_Embed_Permission_Repository $wistia_embed_permission_repository The repository.
95 * @param WooCommerce_Conditional $woocommerce_conditional The WooCommerce conditional.
96 */
97 public function __construct(
98 WPSEO_Admin_Asset_Manager $admin_asset_manager,
99 Introductions_Collector $introductions_collector,
100 Product_Helper $product_helper,
101 User_Helper $user_helper,
102 Short_Link_Helper $short_link_helper,
103 Wistia_Embed_Permission_Repository $wistia_embed_permission_repository,
104 WooCommerce_Conditional $woocommerce_conditional
105 ) {
106 $this->admin_asset_manager = $admin_asset_manager;
107 $this->introductions_collector = $introductions_collector;
108 $this->product_helper = $product_helper;
109 $this->user_helper = $user_helper;
110 $this->short_link_helper = $short_link_helper;
111 $this->wistia_embed_permission_repository = $wistia_embed_permission_repository;
112 $this->woocommerce_conditional = $woocommerce_conditional;
113 }
114
115 /**
116 * Registers the action to enqueue the needed script(s).
117 *
118 * @return void
119 */
120 public function register_hooks() {
121 if ( $this->is_on_installation_page() ) {
122 return;
123 }
124 \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
125 }
126
127 /**
128 * Enqueue the new features assets.
129 *
130 * @return void
131 */
132 public function enqueue_assets() {
133 $user_id = $this->user_helper->get_current_user_id();
134 $this->update_metadata_for( $user_id );
135 $introductions = $this->introductions_collector->get_for( $user_id );
136
137 if ( ! $introductions ) {
138 // Bail when there are no introductions to show.
139 return;
140 }
141 // Update user meta to have "seen" these introductions.
142 $this->update_user_introductions( $user_id, $introductions );
143
144 $this->admin_asset_manager->enqueue_script( self::SCRIPT_HANDLE );
145 $this->admin_asset_manager->localize_script(
146 self::SCRIPT_HANDLE,
147 'wpseoIntroductions',
148 [
149 'introductions' => $introductions,
150 'isPremium' => $this->product_helper->is_premium(),
151 'isRtl' => \is_rtl(),
152 'linkParams' => $this->short_link_helper->get_query_params(),
153 'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
154 'wistiaEmbedPermission' => $this->wistia_embed_permission_repository->get_value_for_user( $user_id ),
155 'isWooEnabled' => $this->woocommerce_conditional->is_met(),
156 ],
157 );
158 $this->admin_asset_manager->enqueue_style( 'introductions' );
159 }
160
161 /**
162 * Updates the user metadata to have "seen" the introductions.
163 *
164 * @param int $user_id The user ID.
165 * @param array $introductions The introductions.
166 *
167 * @return void
168 */
169 private function update_user_introductions( $user_id, $introductions ) {
170 $metadata = $this->user_helper->get_meta( $user_id, Introductions_Seen_Repository::USER_META_KEY, true );
171 if ( ! \is_array( $metadata ) ) {
172 $metadata = [];
173 }
174
175 if ( empty( $introductions ) || ! \is_array( $introductions ) ) {
176 return;
177 }
178
179 // Find the introduction with the highest priority, because JS will only show that one.
180 $highest_priority_intro = \array_reduce(
181 $introductions,
182 static function ( $carry, $item ) {
183 return ( $carry === null || $item['priority'] < $carry['priority'] ) ? $item : $carry;
184 },
185 null,
186 );
187
188 if ( $highest_priority_intro === null ) {
189 return;
190 }
191
192 // Mark the introduction with the highest priority as seen.
193 $metadata[ $highest_priority_intro['id'] ]['is_seen'] = true;
194 $metadata[ $highest_priority_intro['id'] ]['seen_on'] = \time();
195
196 $this->user_helper->update_meta( $user_id, Introductions_Seen_Repository::USER_META_KEY, $metadata );
197 }
198
199 /**
200 * Updates the introductions metadata format for the user
201 * This is needed because we're introducing timestamps for introductions that have been seen, thus changing the format.
202 *
203 * @param int $user_id The user ID.
204 *
205 * @return void
206 */
207 private function update_metadata_for( int $user_id ) {
208 $metadata = $this->introductions_collector->get_metadata( $user_id );
209 foreach ( $metadata as $introduction_name => $introduction_data ) {
210 if ( \is_bool( $introduction_data ) ) {
211 $metadata[ $introduction_name ] = [
212 'is_seen' => $introduction_data,
213 'seen_on' => ( $introduction_data === true ) ? \time() : 0,
214 ];
215 }
216 }
217 $this->user_helper->update_meta( $user_id, Introductions_Seen_Repository::USER_META_KEY, $metadata );
218 }
219 }
220