PluginProbe
Parse.ly / 3.14.1
Parse.ly v3.14.1
3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 All 105 releases
← All changes | src/class-parsely.php +58 -404 3.24.13.14.1 View file →
@@ -9,15 +9,10 @@
9 9 declare(strict_types=1);
10 10
11 11 namespace Parsely;
12 12
13 -use Parsely\Content_Helper\Suggestion_Defaults;
14 -use Parsely\REST_API\REST_API_Controller;
15 -use Parsely\Services\Content_API\Content_API_Service;
16 -use Parsely\Services\Suggestions_API\Suggestions_API_Service;
17 13 use Parsely\UI\Metadata_Renderer;
18 14 use Parsely\UI\Settings_Page;
19 -use Parsely\Utils\Utils;
20 15 use WP_Post;
21 16
22 17 /**
23 18 * Holds most of the logic for the plugin.
@@ -31,10 +26,8 @@
31 26 * api_secret: string,
32 27 * use_top_level_cats: bool,
33 28 * custom_taxonomy_section: string,
34 29 * cats_as_tags: bool,
35 - * content_helper: Parsely_Options_Content_Helper,
36 - * headline_testing: Parsely_Options_Headline_Testing,
37 30 * track_authenticated_users: bool,
38 31 * lowercase_tags: bool,
39 32 * force_https_canonicals: bool,
40 33 * track_post_types: string[],
@@ -39,9 +32,9 @@
39 32 * force_https_canonicals: bool,
40 33 * track_post_types: string[],
41 34 * track_page_types: string[],
42 35 * track_post_types_as?: array<string, string>,
43 - * full_metadata_in_non_posts: bool,
36 + * full_metadata_in_non_posts: ?bool,
44 37 * disable_javascript: bool,
45 38 * disable_amp: bool,
46 39 * meta_type: string,
47 40 * logo: string,
@@ -49,40 +42,15 @@
49 42 * disable_autotrack: bool,
50 43 * plugin_version: string,
51 44 * }
52 45 *
53 - * @phpstan-type Parsely_Options_Content_Helper array{
54 - * ai_features_enabled: bool,
55 - * smart_linking: Parsely_Options_Content_Helper_Feature,
56 - * title_suggestions: Parsely_Options_Content_Helper_Feature,
57 - * excerpt_suggestions: Parsely_Options_Content_Helper_Feature,
58 - * traffic_boost: Parsely_Options_Content_Helper_Feature,
59 - * }
60 - *
61 - * @phpstan-type Parsely_Options_Content_Helper_Feature array{
62 - * enabled: bool,
63 - * allowed_user_roles: string[],
64 - * default_length?: int,
65 - * default_tone?: string,
66 - * default_persona?: string,
67 - * }
68 - *
69 - * @phpstan-type Parsely_Options_Headline_Testing array{
70 - * enabled: bool,
71 - * installation_method: string,
72 - * enable_flicker_control: bool,
73 - * enable_live_updates: bool,
74 - * live_update_timeout: int,
75 - * allow_after_content_load: bool,
76 - * }
77 - *
78 46 * @phpstan-type WP_HTTP_Request_Args array{
79 - * method?: string,
80 - * timeout?: float,
81 - * blocking?: bool,
82 - * headers?: array<string, string>,
83 - * body?: string,
84 - * data_format?: string,
47 + * method: string,
48 + * timeout: float,
49 + * blocking: bool,
50 + * headers: array<string, string>,
51 + * body: string,
52 + * data_format: string,
85 53 * }
86 54 *
87 55 * @phpstan-import-type Metadata_Attributes from Metadata
88 56 */
@@ -89,38 +57,17 @@
89 57 class Parsely {
90 58 /**
91 59 * Declare our constants
92 60 */
93 - public const VERSION = PARSELY_VERSION;
94 - public const MENU_SLUG = 'parsely-settings'; // The page param passed to admin.php.
95 - public const OPTIONS_KEY = 'parsely'; // The key used to store options in the WP database.
96 - public const CAPABILITY = 'manage_options'; // The capability required to administer settings.
97 - public const DASHBOARD_BASE_URL = 'https://dash.parsely.com';
61 + public const VERSION = PARSELY_VERSION;
62 + public const MENU_SLUG = 'parsely'; // The page param passed to options-general.php.
63 + public const OPTIONS_KEY = 'parsely'; // The key used to store options in the WP database.
64 + public const CAPABILITY = 'manage_options'; // The capability required to administer settings.
65 + public const DASHBOARD_BASE_URL = 'https://dash.parsely.com';
66 + public const PUBLIC_API_BASE_URL = 'https://api.parsely.com/v2';
67 + public const PUBLIC_SUGGESTIONS_API_BASE_URL = 'https://content-suggestions-api.parsely.net/prod';
98 68
99 - private const PARSELY_CANONICAL_URL_META_KEY = '_parsely_canonical_url';
100 -
101 69 /**
102 - * The Content API service.
103 - *
104 - * @var ?Content_API_Service $content_api_service
105 - */
106 - private $content_api_service;
107 -
108 - /**
109 - * The Suggestions API service.
110 - *
111 - * @var ?Suggestions_API_Service $suggestions_api_service
112 - */
113 - private $suggestions_api_service;
114 -
115 - /**
116 - * The Parse.ly internal REST API controller.
117 - *
118 - * @var REST_API_Controller|null $rest_api_controller
119 - */
120 - private $rest_api_controller;
121 -
122 - /**
123 70 * Declare some class properties
124 71 *
125 72 * @var Parsely_Options $option_defaults The defaults we need for the class.
126 73 */
@@ -130,40 +77,8 @@
130 77 'api_secret' => '',
131 78 'use_top_level_cats' => false,
132 79 'custom_taxonomy_section' => 'category',
133 80 'cats_as_tags' => false,
134 - 'content_helper' => array(
135 - 'ai_features_enabled' => true,
136 - 'smart_linking' => array(
137 - 'enabled' => true,
138 - 'allowed_user_roles' => array( 'administrator' ),
139 - ),
140 - 'title_suggestions' => array(
141 - 'enabled' => true,
142 - 'allowed_user_roles' => array( 'administrator' ),
143 - 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
144 - 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
145 - ),
146 - 'excerpt_suggestions' => array(
147 - 'enabled' => true,
148 - 'allowed_user_roles' => array( 'administrator' ),
149 - 'default_length' => Suggestion_Defaults::DEFAULT_LENGTH,
150 - 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
151 - 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
152 - ),
153 - 'traffic_boost' => array(
154 - 'enabled' => true,
155 - 'allowed_user_roles' => array( 'administrator' ),
156 - ),
157 - ),
158 - 'headline_testing' => array(
159 - 'enabled' => false,
160 - 'installation_method' => 'one_line',
161 - 'enable_flicker_control' => false,
162 - 'enable_live_updates' => false,
163 - 'live_update_timeout' => 30000,
164 - 'allow_after_content_load' => false,
165 - ),
166 81 'track_authenticated_users' => false,
167 82 'lowercase_tags' => true,
168 83 'force_https_canonicals' => false,
169 84 'track_post_types' => array(),
@@ -266,34 +181,8 @@
266 181 $this->allow_parsely_remote_requests();
267 182 }
268 183
269 184 /**
270 - * Gets the allowed post statuses for tracking.
271 - *
272 - * Uses the `wp_parsely_trackable_statuses` filter to determine which post statuses are allowed to be tracked.
273 - *
274 - * @since 3.17.0
275 - *
276 - * @param WP_Post|int|null $post The post object.
277 - * @return array<string> The allowed post statuses.
278 - */
279 - public static function get_trackable_statuses( $post = null ): array {
280 - /**
281 - * Filters the statuses that are permitted to be tracked.
282 - *
283 - * By default, the only status tracked is 'publish'. Use this filter if
284 - * you have other published content that has a different (custom) status.
285 - *
286 - * @since 2.5.0
287 - * @since 3.17.0 Filter extracted to a separate method.
288 - *
289 - * @param string[] $trackable_statuses The list of post statuses that are allowed to be tracked.
290 - * @param WP_Post|int|null $post Which post object or ID is being checked.
291 - */
292 - return apply_filters( 'wp_parsely_trackable_statuses', array( 'publish' ), $post );
293 - }
294 -
295 - /**
296 185 * Registers action and filter hook callbacks, and immediately upgrades
297 186 * options if needed.
298 187 */
299 188 public function run(): void {
@@ -315,64 +204,12 @@
315 204 $options['plugin_version'] = self::VERSION;
316 205 update_option( self::OPTIONS_KEY, $options );
317 206 }
318 207
319 - // @phpstan-ignore return.void
320 - add_action( 'save_post', array( $this, 'call_update_metadata_endpoint' ) );
208 + add_action( 'save_post', array( $this, 'update_metadata_endpoint' ) );
321 209 }
322 210
323 211 /**
324 - * Returns the Content API service.
325 - *
326 - * This method returns the Content API service, which is used to interact with the Parse.ly Content API.
327 - *
328 - * @since 3.17.0
329 - *
330 - * @return Content_API_Service
331 - */
332 - public function get_content_api(): Content_API_Service {
333 - if ( ! isset( $this->content_api_service ) ) {
334 - $this->content_api_service = new Content_API_Service( $this );
335 - }
336 -
337 - return $this->content_api_service;
338 - }
339 -
340 - /**
341 - * Returns the Suggestions API service.
342 - *
343 - * This method returns the Suggestions API service, which is used to interact with the Parse.ly Suggestions API.
344 - *
345 - * @since 3.17.0
346 - *
347 - * @return Suggestions_API_Service
348 - */
349 - public function get_suggestions_api(): Suggestions_API_Service {
350 - if ( ! isset( $this->suggestions_api_service ) ) {
351 - $this->suggestions_api_service = new Suggestions_API_Service( $this );
352 - }
353 -
354 - return $this->suggestions_api_service;
355 - }
356 -
357 - /**
358 - * Gets the REST API controller.
359 - *
360 - * If the controller is not set, a new instance is created.
361 - *
362 - * @since 3.17.0
363 - *
364 - * @return REST_API_Controller
365 - */
366 - public function get_rest_api_controller(): REST_API_Controller {
367 - if ( ! isset( $this->rest_api_controller ) ) {
368 - $this->rest_api_controller = new REST_API_Controller( $this );
369 - }
370 -
371 - return $this->rest_api_controller;
372 - }
373 -
374 - /**
375 212 * Gets the full URL of the JavaScript tracker file for the site. If an API
376 213 * key is not set, return an empty string.
377 214 *
378 215 * @since 3.2.0
@@ -381,21 +218,10 @@
381 218 */
382 219 public function get_tracker_url(): string {
383 220 if ( $this->site_id_is_set() ) {
384 221 $tracker_url = 'https://cdn.parsely.com/keys/' . $this->get_site_id() . '/p.js';
385 -
386 - /**
387 - * Filters the URL of the Parse.ly tracker script.
388 - *
389 - * The filtered value gets sanitized with {@see esc_url_raw()}.
390 - *
391 - * @since 3.23.0
392 - *
393 - * @param string $tracker_url The URL of the tracker script.
394 - */
395 - return esc_url_raw( apply_filters( 'wp_parsely_tracker_url', $tracker_url ) );
222 + return esc_url( $tracker_url );
396 223 }
397 -
398 224 return '';
399 225 }
400 226
401 227 /**
@@ -442,8 +268,14 @@
442 268 * @return bool Should the post status be tracked for the provided post's post_type.
443 269 * By default,only 'publish' is allowed.
444 270 */
445 271 public static function post_has_trackable_status( $post ): bool {
272 + static $cache = array();
273 + $post_id = is_int( $post ) ? $post : $post->ID;
274 + if ( isset( $cache[ $post_id ] ) ) {
275 + return $cache[ $post_id ];
276 + }
277 +
446 278 /**
447 279 * Filters whether the post password check should be skipped when getting
448 280 * the post trackable status.
449 281 *
@@ -455,13 +287,26 @@
455 287 * @return bool
456 288 */
457 289 $skip_password_check = apply_filters( 'wp_parsely_skip_post_password_check', false, $post );
458 290 if ( ! $skip_password_check && post_password_required( $post ) ) {
291 + $cache[ $post_id ] = false;
459 292 return false;
460 293 }
461 294
462 - $statuses = self::get_trackable_statuses( $post );
463 - return in_array( get_post_status( $post ), $statuses, true );
295 + /**
296 + * Filters the statuses that are permitted to be tracked.
297 + *
298 + * By default, the only status tracked is 'publish'. Use this filter if
299 + * you have other published content that has a different (custom) status.
300 + *
301 + * @since 2.5.0
302 + *
303 + * @param string[] $trackable_statuses The list of post statuses that are allowed to be tracked.
304 + * @param int|WP_Post $post Which post object or ID is being checked.
305 + */
306 + $statuses = apply_filters( 'wp_parsely_trackable_statuses', array( 'publish' ), $post );
307 + $cache[ $post_id ] = in_array( get_post_status( $post ), $statuses, true );
308 + return $cache[ $post_id ];
464 309 }
465 310
466 311 /**
467 312 * Deprecated. Please use the `Metadata` class instead.
@@ -481,52 +326,23 @@
481 326 return $metadata->construct_metadata( $post );
482 327 }
483 328
484 329 /**
485 - * Calls Parse.ly's update metadata endpoint, sending the post's updated
486 - * metadata.
330 + * Updates the Parsely metadata endpoint with the new metadata of the post.
487 331 *
488 - * @param int $post_id The ID of the post to update.
489 - * @return bool True if the metadata endpoint was called, false otherwise.
332 + * @param int $post_id id of the post to update.
490 333 */
491 - public function call_update_metadata_endpoint( int $post_id ): bool {
492 - $options = $this->get_options();
493 -
494 - if ( $this->site_id_is_missing() || '' === $options['metadata_secret'] ) {
495 - return false;
334 + public function update_metadata_endpoint( int $post_id ): void {
335 + $parsely_options = $this->get_options();
336 + if ( $this->site_id_is_missing() || '' === $parsely_options['metadata_secret'] ) {
337 + return;
496 338 }
497 339
498 - $current_post_type = get_post_type( $post_id );
499 - if ( false === $current_post_type ) {
500 - return false;
501 - }
502 -
503 - $tracked_post_types = array_merge(
504 - $options['track_post_types'],
505 - $options['track_page_types']
506 - );
507 -
508 - // Check that the post's type is trackable.
509 - if ( ! in_array( $current_post_type, $tracked_post_types, true ) ) {
510 - return false;
511 - }
512 -
513 - // Check that the post's status is trackable.
514 - if ( ! self::post_has_trackable_status( $post_id ) ) {
515 - return false;
516 - }
517 -
518 340 $post = get_post( $post_id );
519 341 if ( null === $post ) {
520 - return false;
342 + return;
521 343 }
522 344
523 - // Don't call the endpoint when integration tests are running, but
524 - // signal that the above checks have passed.
525 - if ( defined( 'INTEGRATION_TESTS_RUNNING' ) ) {
526 - return true;
527 - }
528 -
529 345 $metadata = ( new Metadata( $this ) )->construct_metadata( $post );
530 346
531 347 $endpoint_metadata = array(
532 348 'canonical_url' => $metadata['url'] ?? '',
@@ -538,11 +354,10 @@
538 354 'authors' => $metadata['creator'] ?? '',
539 355 'tags' => $metadata['keywords'] ?? '',
540 356 );
541 357
542 - $parsely_api_base_url = Content_API_Service::get_base_url();
543 - $parsely_api_endpoint = $parsely_api_base_url . '/metadata/posts';
544 - $parsely_metadata_secret = $options['metadata_secret'];
358 + $parsely_api_endpoint = self::PUBLIC_API_BASE_URL . '/metadata/posts';
359 + $parsely_metadata_secret = $parsely_options['metadata_secret'];
545 360
546 361 $headers = array( 'Content-Type' => 'application/json' );
547 362 $body = wp_json_encode(
548 363 array(
@@ -554,11 +369,11 @@
554 369
555 370 /**
556 371 * POST request options.
557 372 *
558 - * @var WP_HTTP_Request_Args $request_options
373 + * @var WP_HTTP_Request_Args $options
559 374 */
560 - $request_options = array(
375 + $options = array(
561 376 'method' => 'POST',
562 377 'headers' => $headers,
563 378 'blocking' => false,
564 379 'body' => $body,
@@ -564,17 +379,14 @@
564 379 'body' => $body,
565 380 'data_format' => 'body',
566 381 );
567 382
568 - $response = wp_remote_post( $parsely_api_endpoint, $request_options );
383 + $response = wp_remote_post( $parsely_api_endpoint, $options );
569 384
570 - if ( is_wp_error( $response ) ) {
571 - return false;
385 + if ( ! is_wp_error( $response ) ) {
386 + $current_timestamp = time();
387 + update_post_meta( $post_id, 'parsely_metadata_last_updated', $current_timestamp );
572 388 }
573 -
574 - update_post_meta( $post_id, 'parsely_metadata_last_updated', time() );
575 -
576 - return true;
577 389 }
578 390
579 391 /**
580 392 * Safely returns options for the plugin by assigning defaults contained in
@@ -592,43 +404,12 @@
592 404 * @var Parsely_Options|null
593 405 */
594 406 $options = get_option( self::OPTIONS_KEY, null );
595 407
596 - // Existing plugin installation without full metadata option.
597 - /* @phpstan-ignore isset.offset, booleanAnd.alwaysFalse */
598 408 if ( is_array( $options ) && ! isset( $options['full_metadata_in_non_posts'] ) ) {
599 409 $this->set_default_full_metadata_in_non_posts();
600 410 }
601 411
602 - // Existing plugin installation without Content Intelligence options.
603 - /* @phpstan-ignore isset.offset, booleanAnd.alwaysFalse */
604 - if ( is_array( $options ) && ! isset( $options['content_helper'] ) ) {
605 - $this->set_default_content_helper_settings_values();
606 - }
607 -
608 - // Existing plugin installation that's missing a Content Intelligence
609 - // feature option.
610 - /* @phpstan-ignore isset.offset */
611 - if ( is_array( $options ) && isset( $options['content_helper'] ) ) {
612 - /** @var array<string,Parsely_Options_Content_Helper_Feature> $pch_options */
613 - $pch_options = $options['content_helper'];
614 -
615 - /** @var array<string,Parsely_Options_Content_Helper_Feature> $pch_options_defaults */
616 - $pch_options_defaults = $this->option_defaults['content_helper'];
617 -
618 - if ( count( $pch_options ) !== count( $pch_options_defaults ) ) {
619 - $new_keys = array_diff(
620 - array_keys( $pch_options_defaults ),
621 - array_keys( $pch_options )
622 - );
623 -
624 - foreach ( $new_keys as $key ) {
625 - $options['content_helper'][ $key ] = $pch_options_defaults[ $key ];
626 - }
627 - }
628 - }
629 -
630 - // New plugin installation that hasn't saved its options yet.
631 412 if ( ! is_array( $options ) ) {
632 413 $this->set_default_track_as_values();
633 414 $this->set_default_full_metadata_in_non_posts();
634 415 $options = $this->option_defaults;
@@ -647,30 +428,8 @@
647 428 );
648 429 }
649 430
650 431 /**
651 - * Returns the value of a nested option.
652 - *
653 - * @since 3.16.0
654 - *
655 - * @param string $option The option to get.
656 - * @param Parsely_Options $options The options to get the value from.
657 - * @return mixed The value of the nested option.
658 - */
659 - public static function get_nested_option_value( $option, $options ) {
660 - $keys = explode( '[', str_replace( ']', '', $option ) );
661 - $value = $options;
662 -
663 - foreach ( $keys as $key ) {
664 - if ( isset( $value[ $key ] ) ) {
665 - $value = $value[ $key ];
666 - }
667 - }
668 -
669 - return $value;
670 - }
671 -
672 - /**
673 432 * Sets the default values for the track_post_types and track_page_types
674 433 * options.
675 434 *
676 435 * @since 3.9.0
@@ -723,24 +482,8 @@
723 482 }
724 483 }
725 484
726 485 /**
727 - * Sets the default values for Content Intelligence options.
728 - *
729 - * Gives PCH access to all users having the edit_posts capability, to keep
730 - * consistent behavior with plugin versions prior to 3.16.0.
731 - *
732 - * @since 3.16.0
733 - */
734 - public function set_default_content_helper_settings_values(): void {
735 - $this->option_defaults['content_helper'] =
736 - Permissions::build_pch_permissions_settings_array(
737 - true,
738 - array_keys( Permissions::get_user_roles_with_edit_posts_cap() )
739 - );
740 - }
741 -
742 - /**
743 486 * Gets the URL of the plugin's settings page.
744 487 *
745 488 * @param int|null $_blog_id The Blog ID for the multisite subsite to use
746 489 * for context (Default null for current).
@@ -745,10 +488,10 @@
745 488 * @param int|null $_blog_id The Blog ID for the multisite subsite to use
746 489 * for context (Default null for current).
747 490 * @return string
748 491 */
749 - public static function get_settings_url( ?int $_blog_id = null ): string {
750 - return get_admin_url( $_blog_id, 'admin.php?page=' . self::MENU_SLUG );
492 + public static function get_settings_url( int $_blog_id = null ): string {
493 + return get_admin_url( $_blog_id, 'options-general.php?page=' . self::MENU_SLUG );
751 494 }
752 495
753 496 /**
754 497 * Returns the URL of the Parse.ly dashboard for a specific page. If a page
@@ -1033,97 +776,8 @@
1033 776 }
1034 777 }
1035 778
1036 779 /**
1037 - * Gets the Parse.ly canonical URL for a given post.
1038 - *
1039 - * @since 3.19.0
1040 - *
1041 - * @param WP_Post|int $post The post ID or post object.
1042 - * @return string The Parse.ly canonical URL.
1043 - */
1044 - public static function get_canonical_url_from_post( $post ): string {
1045 - $post_id = is_int( $post ) ? $post : $post->ID;
1046 - $canonical_url = get_post_meta( $post_id, self::PARSELY_CANONICAL_URL_META_KEY, true );
1047 -
1048 - if ( null !== $canonical_url && is_string( $canonical_url ) && '' !== $canonical_url ) {
1049 - return self::get_canonical_url( $canonical_url );
1050 - }
1051 -
1052 - $permalink = get_permalink( $post );
1053 -
1054 - if ( false === $permalink ) {
1055 - return __( 'no permalink', 'wp-parsely' );
1056 - }
1057 -
1058 - return self::get_canonical_url( $permalink );
1059 - }
1060 -
1061 - /**
1062 - * Returns the canonical version of the passed URL.
1063 - *
1064 - * In this context, the canonical URL is the URL containing the Site ID as
1065 - * its domain. If the Site ID differs from the real domain, the
1066 - * `wp_parsely_canonical_url_domain` filter can be used to set it.
1067 - *
1068 - * @since 3.19.0
1069 - * @since 3.20.4 Made the domain overridable.
1070 - *
1071 - * @param string $url The URL to get the canonical URL for.
1072 - * @return string The canonical URL.
1073 - */
1074 - public static function get_canonical_url( string $url ): string {
1075 - $canonical_url_domain = apply_filters(
1076 - 'wp_parsely_canonical_url_domain',
1077 - null
1078 - );
1079 -
1080 - // Handle domain override.
1081 - if ( is_string( $canonical_url_domain ) ) {
1082 - // Get the canonical URL domain without protocol, trailing slashes
1083 - // or accidental whitespace.
1084 - $canonical_url_domain = rtrim( trim( $canonical_url_domain ), '/' );
1085 - $canonical_url_domain = preg_replace( '#^https?://#', '', $canonical_url_domain );
1086 -
1087 - if ( is_string( $canonical_url_domain ) && '' !== $canonical_url_domain ) {
1088 - $url_domain = (string) wp_parse_url( $url, PHP_URL_HOST );
1089 - return str_replace( $url_domain, $canonical_url_domain, $url );
1090 - }
1091 - }
1092 -
1093 - $site_id = \Parsely\get_parsely()->get_site_id();
1094 - $home_url_host = (string) wp_parse_url( home_url(), PHP_URL_HOST );
1095 -
1096 - if ( $home_url_host === $site_id ) {
1097 - // URL does not need to be modified.
1098 - return $url;
1099 - }
1100 -
1101 - // Return the URL with the Site ID as the domain.
1102 - return str_replace( $home_url_host, $site_id, $url );
1103 - }
1104 -
1105 - /**
1106 - * Sets the Parse.ly canonical URL for a post.
1107 - *
1108 - * @since 3.19.0
1109 - *
1110 - * @param WP_Post|int $post The post object or post ID.
1111 - * @param string $url The canonical URL.
1112 - * @return bool True if the canonical URL was set, false otherwise.
1113 - */
1114 - public static function set_canonical_url( $post, string $url ): bool {
1115 - $post_id = is_int( $post ) ? $post : $post->ID;
1116 - $canonical_url = self::get_canonical_url( $url );
1117 -
1118 - return false !== update_post_meta(
1119 - $post_id,
1120 - self::PARSELY_CANONICAL_URL_META_KEY,
1121 - sanitize_url( $canonical_url, array( 'http', 'https' ) )
1122 - );
1123 - }
1124 -
1125 - /**
1126 780 * Sanitizes the value of the passed managed option.
1127 781 *
1128 782 * @since 3.9.0
1129 783 * @access private
@@ -1207,18 +861,18 @@
1207 861 */
1208 862 private function allow_parsely_remote_requests(): void {
1209 863 $allowed_urls = array(
1210 864 self::DASHBOARD_BASE_URL,
1211 - Content_API_Service::get_base_url(),
1212 - Suggestions_API_Service::get_base_url(),
865 + self::PUBLIC_API_BASE_URL,
866 + self::PUBLIC_SUGGESTIONS_API_BASE_URL,
1213 867 );
1214 868
1215 869 add_filter(
1216 870 'http_request_host_is_external',
1217 - function ( bool $external, string $host, string $url ) use ( $allowed_urls ) {
871 + function ( $external, $host, $url ) use ( $allowed_urls ) {
1218 872 // Check if the URL matches any URLs on the allowed list.
1219 873 foreach ( $allowed_urls as $allowed_url ) {
1220 - if ( Utils::str_starts_with( $url, $allowed_url ) ) {
874 + if ( \Parsely\Utils\str_starts_with( $url, $allowed_url ) ) {
1221 875 return true;
1222 876 }
1223 877 }
1224 878 return $external;