Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 108 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
Yoast | |
0.00% |
0 / 108 |
|
0.00% |
0 / 12 |
1806 | |
0.00% |
0 / 1 |
register_hooks | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
site_representation_updated | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
social_profiles_updated | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
42 | |||
tracking_updated | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
maybe_push_site_representation_event | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
90 | |||
maybe_push_social_profiles_event | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
30 | |||
push_other_social_profiles | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
6 | |||
map_params_names_to_hiive_names | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
map_failures_to_hiive_names | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
is_param_empty | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
get_base_url | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
clean_social_profiles_failures | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | namespace NewfoldLabs\WP\Module\Data\Listeners; |
4 | |
5 | /** |
6 | * Monitors Yoast events |
7 | */ |
8 | class Yoast extends Listener { |
9 | // We don't want to track these fields |
10 | private $site_representation_skip_fields = array( 'company_logo_id', 'person_logo_id', 'description' ); |
11 | |
12 | // The names used for Hiive events tracking are different from the names used for the Yoast options |
13 | private $site_representation_map = array( |
14 | 'company_or_person' => 'site_representation', |
15 | 'company_name' => 'organization_name', |
16 | 'company_logo' => 'organization_logo', |
17 | 'person_logo' => 'logo', |
18 | 'company_or_person_user_id' => 'name', |
19 | 'website_name' => 'website_name', |
20 | ); |
21 | |
22 | private $social_profiles_map = array( |
23 | 'facebook_site' => 'facebook_profile', |
24 | 'twitter_site' => 'twitter_profile', |
25 | 'other_social_urls' => 'other_profiles', |
26 | ); |
27 | |
28 | /** |
29 | * Register the hooks for the listener |
30 | * |
31 | * @return void |
32 | */ |
33 | public function register_hooks() { |
34 | // First time configuration |
35 | add_action( 'wpseo_ftc_post_update_site_representation', array( $this, 'site_representation_updated' ), 10, 3 ); |
36 | add_action( 'wpseo_ftc_post_update_social_profiles', array( $this, 'social_profiles_updated' ), 10, 3 ); |
37 | add_action( 'wpseo_ftc_post_update_enable_tracking', array( $this, 'tracking_updated' ), 10, 3 ); |
38 | } |
39 | |
40 | /** |
41 | * The user just updated their site representation |
42 | * |
43 | * @param array $new_values The new values for the options related to the site representation |
44 | * @param array $old_values The old values for the options related to the site representation |
45 | * @param array $failures The failures that occurred during the update |
46 | * |
47 | * @return void |
48 | */ |
49 | public function site_representation_updated( $new_values, $old_values, $failures ) { |
50 | // All the options are unchanged, opt out |
51 | if ( $new_values === $old_values ) { |
52 | return; |
53 | } |
54 | |
55 | $mapped_new_values = $this->map_params_names_to_hiive_names( $new_values, $this->site_representation_map, $this->site_representation_skip_fields ); |
56 | $mapped_old_values = $this->map_params_names_to_hiive_names( $old_values, $this->site_representation_map, $this->site_representation_skip_fields ); |
57 | $mapped_failures = $this->map_failures_to_hiive_names( $failures, $this->site_representation_map, $this->site_representation_skip_fields ); |
58 | |
59 | foreach ( $mapped_new_values as $key => $value ) { |
60 | $this->maybe_push_site_representation_event( $key, $value, $mapped_old_values[ $key ], \in_array( $key, $mapped_failures ) ); |
61 | } |
62 | } |
63 | |
64 | /** |
65 | * The user just updated their personal profiles |
66 | * |
67 | * @param array $new_values The new values for the options related to the site representation |
68 | * @param array $old_values The old values for the options related to the site representation |
69 | * @param array $failures The failures that occurred during the update |
70 | * |
71 | * @return void |
72 | */ |
73 | public function social_profiles_updated( $new_values, $old_values, $failures ) { |
74 | // Yoast stores only twitter username, and $new_values stores the pre-processed values |
75 | if ( strpos( $new_values['twitter_site'], 'twitter.com/' ) !== false ) { |
76 | $new_values['twitter_site'] = ( explode( 'twitter.com/', $new_values['twitter_site'] )[1] ); |
77 | } |
78 | |
79 | // All the options are unchanged, opt out |
80 | if ( $new_values === $old_values ) { |
81 | return; |
82 | } |
83 | |
84 | // Remove multiple occurences of other_social_urls; |
85 | $cleaned_failures = $this->clean_social_profiles_failures( $failures ); |
86 | |
87 | $mapped_values = $this->map_params_names_to_hiive_names( $new_values, $this->social_profiles_map ); |
88 | $mapped_old_values = $this->map_params_names_to_hiive_names( $old_values, $this->social_profiles_map ); |
89 | $mapped_failures = $this->map_failures_to_hiive_names( $cleaned_failures, $this->social_profiles_map ); |
90 | |
91 | foreach ( $mapped_values as $key => $value ) { |
92 | // The option update failed |
93 | if ( \in_array( $key, $mapped_failures ) ) { |
94 | $this->push( "failed_$key", array( 'category' => 'ftc_personal_profiles' ) ); |
95 | return; |
96 | } |
97 | |
98 | if ( $value !== $mapped_old_values[ $key ] ) { |
99 | $this->maybe_push_social_profiles_event( $key, $value, $mapped_old_values[ $key ], \in_array( $key, $mapped_failures ) ); |
100 | } |
101 | } |
102 | } |
103 | |
104 | /** |
105 | * The user updated their tracking preferences |
106 | * |
107 | * @param string $new_value The new value for the option related to tracking |
108 | * @param string $old_value The old value for the option related to tracking |
109 | * @param bool $failed Whether the option update failed |
110 | * |
111 | * @return void |
112 | */ |
113 | public function tracking_updated( $new_value, $old_value, $failed ) { |
114 | // Option unchanged, opt out |
115 | if ( $new_value === $old_value ) { |
116 | return; |
117 | } |
118 | |
119 | $failed ? $this->push( 'failed_usage_tracking', array( 'category' => 'ftc_tracking' ) ) : $this->push( 'changed_usage_tracking', array( 'category' => 'ftc_tracking' ) ); |
120 | } |
121 | |
122 | /** |
123 | * A method used to (maybe) push a site representation-related event to the queue. |
124 | * |
125 | * @param string $key The option key |
126 | * @param string $value The new option value |
127 | * @param string $old_value The old option value |
128 | * @param bool $failure Whether the option update failed |
129 | * |
130 | * @return void |
131 | */ |
132 | private function maybe_push_site_representation_event( $key, $value, $old_value, $failure ) { |
133 | $category = 'ftc_site_representation'; |
134 | |
135 | // The option update failed |
136 | if ( $failure ) { |
137 | $this->push( "failed_$key", array( 'category' => $category ) ); |
138 | return; |
139 | } |
140 | |
141 | // The option value changed |
142 | if ( $value !== $old_value ) { |
143 | // The option was set for the first time |
144 | |
145 | // name is a special case, because it represents the company_or_person_user_id which is initialised to false, and the first time the user saves the site representation step |
146 | // is set either to 0 if the site represents an organisation, or to an integer > 0 if the site represents a person |
147 | if ( $key === 'name' ) { |
148 | if ( $old_value === false && $value === 0 ) { |
149 | return; |
150 | } |
151 | } |
152 | |
153 | // Again, name is a special case, because if its old value was 0 and a value different that 0 is being received, it means that the user |
154 | // switched from organisation to person, and then the person id is being set. |
155 | // Once the name is assigned an integer > 0, it can never go back to 0, even if the user switches back to organisation |
156 | // ( it "caches" the last user id that was set) |
157 | if ( ( $this->is_param_empty( $old_value ) ) || ( $key === 'name' && $old_value === 0 ) ) { |
158 | $this->push( "set_$key", array( 'category' => $category ) ); |
159 | return; |
160 | } |
161 | |
162 | // The option was updated |
163 | $data = array( |
164 | 'category' => $category, |
165 | 'data' => array( |
166 | 'label_key' => $key, |
167 | 'new_value' => $value, |
168 | ), |
169 | ); |
170 | |
171 | $this->push( |
172 | "changed_$key", |
173 | $data |
174 | ); |
175 | } |
176 | } |
177 | |
178 | /** |
179 | * A method used to (maybe) push a social profile-related event to the queue. |
180 | * |
181 | * @param string $key The option key |
182 | * @param string $value The new option value |
183 | * @param string $old_value The old option value |
184 | * @param bool $failure Whether the option update failed |
185 | * |
186 | * @return void |
187 | */ |
188 | private function maybe_push_social_profiles_event( $key, $value, $old_value, $failure ) { |
189 | $category = 'ftc_personal_profiles'; |
190 | |
191 | // The option update failed |
192 | if ( $failure ) { |
193 | $this->push( "failed_$key", array( 'category' => $category ) ); |
194 | return; |
195 | } |
196 | |
197 | // The option value changed |
198 | if ( $value !== $old_value ) { |
199 | if ( $key === 'other_profiles' ) { |
200 | $this->push_other_social_profiles( $key, $value, $old_value, $category ); |
201 | return; |
202 | } |
203 | |
204 | // The option was set for the first time |
205 | if ( $this->is_param_empty( $old_value ) ) { |
206 | $this->push( "set_$key", array( 'category' => $category ) ); |
207 | return; |
208 | } |
209 | |
210 | // The option was updated |
211 | $this->push( "changed_$key", array( 'category' => $category ) ); |
212 | } |
213 | } |
214 | |
215 | |
216 | /** |
217 | * A method used to (maybe) push the other_profiles-related event to the queue. |
218 | * |
219 | * @param string $key The option key (other_profiles) |
220 | * @param array $new_value The array of new social profiles |
221 | * @param array $old_value The array of old social profiles |
222 | * @param string $category The category of the event |
223 | * |
224 | * @return void |
225 | */ |
226 | private function push_other_social_profiles( $key, $new_value, $old_value, $category ) { |
227 | // The option was set for the first time |
228 | if ( $this->is_param_empty( $old_value ) ) { |
229 | $this->push( "set_$key", array( 'category' => $category ) ); |
230 | return; |
231 | } |
232 | |
233 | $changed_profiles = \array_map( |
234 | function ( $value ) { |
235 | return $this->get_base_url( \wp_unslash( $value ) ); |
236 | }, |
237 | $new_value |
238 | ); |
239 | |
240 | // The option was updated |
241 | $data = array( |
242 | 'category' => $category, |
243 | 'data' => array( |
244 | 'label_key' => $key, |
245 | 'new_value' => $changed_profiles, |
246 | ), |
247 | ); |
248 | |
249 | $this->push( 'changed_other_profiles', $data ); |
250 | } |
251 | |
252 | /** |
253 | * Maps the param names to the names used for Hiive events tracking. |
254 | * |
255 | * @param array $params The params to map. |
256 | * @param array $map The map to use. |
257 | * @param array $skip_fields The fields to skip. |
258 | * |
259 | * @return array The mapped params. |
260 | */ |
261 | private function map_params_names_to_hiive_names( $params, $map, $skip_fields = array() ) { |
262 | $mapped_params = array(); |
263 | |
264 | foreach ( $params as $param_name => $param_value ) { |
265 | if ( in_array( $param_name, $skip_fields, true ) ) { |
266 | continue; |
267 | } |
268 | |
269 | $new_name = $map[ $param_name ]; |
270 | $mapped_params[ $new_name ] = $param_value; |
271 | } |
272 | |
273 | return $mapped_params; |
274 | } |
275 | |
276 | /** |
277 | * Maps the names of the params which failed the update to the names used for Hiive events tracking. |
278 | * |
279 | * @param array $failures The params names to map. |
280 | * @param array $map The map to use. |
281 | * @param array $skip_fields The fields to skip. |
282 | * |
283 | * @return array The mapped params names. |
284 | */ |
285 | private function map_failures_to_hiive_names( $failures, $map, $skip_fields = array() ) { |
286 | $mapped_failures = array(); |
287 | |
288 | foreach ( $failures as $failed_field_name ) { |
289 | if ( in_array( $failed_field_name, $skip_fields, true ) ) { |
290 | continue; |
291 | } |
292 | |
293 | $mapped_failures[] = $map[ $failed_field_name ]; |
294 | } |
295 | |
296 | return $mapped_failures; |
297 | } |
298 | |
299 | /** |
300 | * Checks whether a param is empty. |
301 | * |
302 | * @param mixed $param The param to check. |
303 | * |
304 | * @return bool Whether the param is empty. |
305 | */ |
306 | private function is_param_empty( $param ) { |
307 | if ( is_array( $param ) ) { |
308 | return ( count( $param ) === 0 ); |
309 | } |
310 | |
311 | return ( strlen( $param ) === 0 ); |
312 | } |
313 | |
314 | /** |
315 | * Gets the base url of a given url. |
316 | * |
317 | * @param string $url The url. |
318 | * |
319 | * @return string The base url. |
320 | */ |
321 | private function get_base_url( $url ) { |
322 | $parts = \parse_url( $url ); |
323 | |
324 | return $parts['scheme'] . '://' . $parts['host']; |
325 | } |
326 | |
327 | /** |
328 | * Removes multiple occurences of other_social_urls from the failures array |
329 | * |
330 | * @param array $failures The failures array |
331 | * |
332 | * @return array The cleaned failures array |
333 | */ |
334 | private function clean_social_profiles_failures( $failures ) { |
335 | $cleaned_failures = array(); |
336 | $other_social_profiles_failed = false; |
337 | |
338 | foreach ( $failures as $failure ) { |
339 | if ( strpos( $failure, 'other_social_urls' ) === 0 ) { |
340 | $other_social_profiles_failed = true; |
341 | continue; |
342 | } |
343 | $cleaned_failures[] = $failure; |
344 | } |
345 | |
346 | if ( $other_social_profiles_failed ) { |
347 | $cleaned_failures[] = 'other_social_urls'; |
348 | } |
349 | |
350 | return $cleaned_failures; |
351 | } |
352 | } |