| @@ -9,14 +9,10 @@ | ||
| 9 | 9 | declare(strict_types=1); |
| 10 | 10 | |
| 11 | 11 | namespace Parsely; |
| 12 | 12 | |
| 13 | -use Parsely\REST_API\REST_API_Controller; | |
| 14 | -use Parsely\Services\Content_API\Content_API_Service; | |
| 15 | -use Parsely\Services\Suggestions_API\Suggestions_API_Service; | |
| 16 | 13 | use Parsely\UI\Metadata_Renderer; |
| 17 | 14 | use Parsely\UI\Settings_Page; |
| 18 | -use Parsely\Utils\Utils; | |
| 19 | 15 | use WP_Post; |
| 20 | 16 | |
| 21 | 17 | /** |
| 22 | 18 | * Holds most of the logic for the plugin. |
| @@ -30,9 +26,8 @@ | ||
| 30 | 26 | * api_secret: string, |
| 31 | 27 | * use_top_level_cats: bool, |
| 32 | 28 | * custom_taxonomy_section: string, |
| 33 | 29 | * cats_as_tags: bool, |
| 34 | - * content_helper: Parsely_Options_Content_Helper, | |
| 35 | 30 | * track_authenticated_users: bool, |
| 36 | 31 | * lowercase_tags: bool, |
| 37 | 32 | * force_https_canonicals: bool, |
| 38 | 33 | * track_post_types: string[], |
| @@ -37,9 +32,9 @@ | ||
| 37 | 32 | * force_https_canonicals: bool, |
| 38 | 33 | * track_post_types: string[], |
| 39 | 34 | * track_page_types: string[], |
| 40 | 35 | * track_post_types_as?: array<string, string>, |
| 41 | - * full_metadata_in_non_posts: bool, | |
| 36 | + * full_metadata_in_non_posts: ?bool, | |
| 42 | 37 | * disable_javascript: bool, |
| 43 | 38 | * disable_amp: bool, |
| 44 | 39 | * meta_type: string, |
| 45 | 40 | * logo: string, |
| @@ -47,27 +42,15 @@ | ||
| 47 | 42 | * disable_autotrack: bool, |
| 48 | 43 | * plugin_version: string, |
| 49 | 44 | * } |
| 50 | 45 | * |
| 51 | - * @phpstan-type Parsely_Options_Content_Helper array{ | |
| 52 | - * ai_features_enabled: bool, | |
| 53 | - * smart_linking: Parsely_Options_Content_Helper_Feature, | |
| 54 | - * title_suggestions: Parsely_Options_Content_Helper_Feature, | |
| 55 | - * excerpt_suggestions: Parsely_Options_Content_Helper_Feature, | |
| 56 | - * } | |
| 57 | - * | |
| 58 | - * @phpstan-type Parsely_Options_Content_Helper_Feature array{ | |
| 59 | - * enabled: bool, | |
| 60 | - * allowed_user_roles: string[], | |
| 61 | - * } | |
| 62 | - * | |
| 63 | 46 | * @phpstan-type WP_HTTP_Request_Args array{ |
| 64 | - * method?: string, | |
| 65 | - * timeout?: float, | |
| 66 | - * blocking?: bool, | |
| 67 | - * headers?: array<string, string>, | |
| 68 | - * body?: string, | |
| 69 | - * data_format?: string, | |
| 47 | + * method: string, | |
| 48 | + * timeout: float, | |
| 49 | + * blocking: bool, | |
| 50 | + * headers: array<string, string>, | |
| 51 | + * body: string, | |
| 52 | + * data_format: string, | |
| 70 | 53 | * } |
| 71 | 54 | * |
| 72 | 55 | * @phpstan-import-type Metadata_Attributes from Metadata |
| 73 | 56 | */ |
| @@ -74,36 +57,17 @@ | ||
| 74 | 57 | class Parsely { |
| 75 | 58 | /** |
| 76 | 59 | * Declare our constants |
| 77 | 60 | */ |
| 78 | - public const VERSION = PARSELY_VERSION; | |
| 79 | - public const MENU_SLUG = 'parsely'; // The page param passed to options-general.php. | |
| 80 | - public const OPTIONS_KEY = 'parsely'; // The key used to store options in the WP database. | |
| 81 | - public const CAPABILITY = 'manage_options'; // The capability required to administer settings. | |
| 82 | - 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'; | |
| 83 | 68 | |
| 84 | 69 | /** |
| 85 | - * The Content API service. | |
| 86 | - * | |
| 87 | - * @var ?Content_API_Service $content_api_service | |
| 88 | - */ | |
| 89 | - private $content_api_service; | |
| 90 | - | |
| 91 | - /** | |
| 92 | - * The Suggestions API service. | |
| 93 | - * | |
| 94 | - * @var ?Suggestions_API_Service $suggestions_api_service | |
| 95 | - */ | |
| 96 | - private $suggestions_api_service; | |
| 97 | - | |
| 98 | - /** | |
| 99 | - * The Parse.ly internal REST API controller. | |
| 100 | - * | |
| 101 | - * @var REST_API_Controller|null $rest_api_controller | |
| 102 | - */ | |
| 103 | - private $rest_api_controller; | |
| 104 | - | |
| 105 | - /** | |
| 106 | 70 | * Declare some class properties |
| 107 | 71 | * |
| 108 | 72 | * @var Parsely_Options $option_defaults The defaults we need for the class. |
| 109 | 73 | */ |
| @@ -113,23 +77,8 @@ | ||
| 113 | 77 | 'api_secret' => '', |
| 114 | 78 | 'use_top_level_cats' => false, |
| 115 | 79 | 'custom_taxonomy_section' => 'category', |
| 116 | 80 | 'cats_as_tags' => false, |
| 117 | - 'content_helper' => array( | |
| 118 | - 'ai_features_enabled' => true, | |
| 119 | - 'smart_linking' => array( | |
| 120 | - 'enabled' => true, | |
| 121 | - 'allowed_user_roles' => array( 'administrator' ), | |
| 122 | - ), | |
| 123 | - 'title_suggestions' => array( | |
| 124 | - 'enabled' => true, | |
| 125 | - 'allowed_user_roles' => array( 'administrator' ), | |
| 126 | - ), | |
| 127 | - 'excerpt_suggestions' => array( | |
| 128 | - 'enabled' => true, | |
| 129 | - 'allowed_user_roles' => array( 'administrator' ), | |
| 130 | - ), | |
| 131 | - ), | |
| 132 | 81 | 'track_authenticated_users' => false, |
| 133 | 82 | 'lowercase_tags' => true, |
| 134 | 83 | 'force_https_canonicals' => false, |
| 135 | 84 | 'track_post_types' => array(), |
| @@ -232,34 +181,8 @@ | ||
| 232 | 181 | $this->allow_parsely_remote_requests(); |
| 233 | 182 | } |
| 234 | 183 | |
| 235 | 184 | /** |
| 236 | - * Gets the allowed post statuses for tracking. | |
| 237 | - * | |
| 238 | - * Uses the `wp_parsely_trackable_statuses` filter to determine which post statuses are allowed to be tracked. | |
| 239 | - * | |
| 240 | - * @since 3.17.0 | |
| 241 | - * | |
| 242 | - * @param WP_Post|int|null $post The post object. | |
| 243 | - * @return array<string> The allowed post statuses. | |
| 244 | - */ | |
| 245 | - public static function get_trackable_statuses( $post = null ): array { | |
| 246 | - /** | |
| 247 | - * Filters the statuses that are permitted to be tracked. | |
| 248 | - * | |
| 249 | - * By default, the only status tracked is 'publish'. Use this filter if | |
| 250 | - * you have other published content that has a different (custom) status. | |
| 251 | - * | |
| 252 | - * @since 2.5.0 | |
| 253 | - * @since 3.17.0 Filter extracted to a separate method. | |
| 254 | - * | |
| 255 | - * @param string[] $trackable_statuses The list of post statuses that are allowed to be tracked. | |
| 256 | - * @param WP_Post|int|null $post Which post object or ID is being checked. | |
| 257 | - */ | |
| 258 | - return apply_filters( 'wp_parsely_trackable_statuses', array( 'publish' ), $post ); | |
| 259 | - } | |
| 260 | - | |
| 261 | - /** | |
| 262 | 185 | * Registers action and filter hook callbacks, and immediately upgrades |
| 263 | 186 | * options if needed. |
| 264 | 187 | */ |
| 265 | 188 | public function run(): void { |
| @@ -285,59 +208,8 @@ | ||
| 285 | 208 | add_action( 'save_post', array( $this, 'update_metadata_endpoint' ) ); |
| 286 | 209 | } |
| 287 | 210 | |
| 288 | 211 | /** |
| 289 | - * Returns the Content API service. | |
| 290 | - * | |
| 291 | - * This method returns the Content API service, which is used to interact with the Parse.ly Content API. | |
| 292 | - * | |
| 293 | - * @since 3.17.0 | |
| 294 | - * | |
| 295 | - * @return Content_API_Service | |
| 296 | - */ | |
| 297 | - public function get_content_api(): Content_API_Service { | |
| 298 | - if ( ! isset( $this->content_api_service ) ) { | |
| 299 | - $this->content_api_service = new Content_API_Service( $this ); | |
| 300 | - } | |
| 301 | - | |
| 302 | - return $this->content_api_service; | |
| 303 | - } | |
| 304 | - | |
| 305 | - /** | |
| 306 | - * Returns the Suggestions API service. | |
| 307 | - * | |
| 308 | - * This method returns the Suggestions API service, which is used to interact with the Parse.ly Suggestions API. | |
| 309 | - * | |
| 310 | - * @since 3.17.0 | |
| 311 | - * | |
| 312 | - * @return Suggestions_API_Service | |
| 313 | - */ | |
| 314 | - public function get_suggestions_api(): Suggestions_API_Service { | |
| 315 | - if ( ! isset( $this->suggestions_api_service ) ) { | |
| 316 | - $this->suggestions_api_service = new Suggestions_API_Service( $this ); | |
| 317 | - } | |
| 318 | - | |
| 319 | - return $this->suggestions_api_service; | |
| 320 | - } | |
| 321 | - | |
| 322 | - /** | |
| 323 | - * Gets the REST API controller. | |
| 324 | - * | |
| 325 | - * If the controller is not set, a new instance is created. | |
| 326 | - * | |
| 327 | - * @since 3.17.0 | |
| 328 | - * | |
| 329 | - * @return REST_API_Controller | |
| 330 | - */ | |
| 331 | - public function get_rest_api_controller(): REST_API_Controller { | |
| 332 | - if ( ! isset( $this->rest_api_controller ) ) { | |
| 333 | - $this->rest_api_controller = new REST_API_Controller( $this ); | |
| 334 | - } | |
| 335 | - | |
| 336 | - return $this->rest_api_controller; | |
| 337 | - } | |
| 338 | - | |
| 339 | - /** | |
| 340 | 212 | * Gets the full URL of the JavaScript tracker file for the site. If an API |
| 341 | 213 | * key is not set, return an empty string. |
| 342 | 214 | * |
| 343 | 215 | * @since 3.2.0 |
| @@ -419,9 +291,20 @@ | ||
| 419 | 291 | $cache[ $post_id ] = false; |
| 420 | 292 | return false; |
| 421 | 293 | } |
| 422 | 294 | |
| 423 | - $statuses = self::get_trackable_statuses( $post ); | |
| 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 ); | |
| 424 | 307 | $cache[ $post_id ] = in_array( get_post_status( $post ), $statuses, true ); |
| 425 | 308 | return $cache[ $post_id ]; |
| 426 | 309 | } |
| 427 | 310 | |
| @@ -471,10 +354,9 @@ | ||
| 471 | 354 | 'authors' => $metadata['creator'] ?? '', |
| 472 | 355 | 'tags' => $metadata['keywords'] ?? '', |
| 473 | 356 | ); |
| 474 | 357 | |
| 475 | - $parsely_api_base_url = Content_API_Service::get_base_url(); | |
| 476 | - $parsely_api_endpoint = $parsely_api_base_url . '/metadata/posts'; | |
| 358 | + $parsely_api_endpoint = self::PUBLIC_API_BASE_URL . '/metadata/posts'; | |
| 477 | 359 | $parsely_metadata_secret = $parsely_options['metadata_secret']; |
| 478 | 360 | |
| 479 | 361 | $headers = array( 'Content-Type' => 'application/json' ); |
| 480 | 362 | $body = wp_json_encode( |
| @@ -522,21 +404,12 @@ | ||
| 522 | 404 | * @var Parsely_Options|null |
| 523 | 405 | */ |
| 524 | 406 | $options = get_option( self::OPTIONS_KEY, null ); |
| 525 | 407 | |
| 526 | - // @phpstan-ignore isset.offset, booleanAnd.alwaysFalse | |
| 527 | 408 | if ( is_array( $options ) && ! isset( $options['full_metadata_in_non_posts'] ) ) { |
| 528 | - // Existing plugin installation without full metadata option. | |
| 529 | 409 | $this->set_default_full_metadata_in_non_posts(); |
| 530 | 410 | } |
| 531 | 411 | |
| 532 | - // @phpstan-ignore isset.offset, booleanAnd.alwaysFalse | |
| 533 | - if ( is_array( $options ) && ! isset( $options['content_helper'] ) ) { | |
| 534 | - // Existing plugin installation without Content Helper options. | |
| 535 | - $this->set_default_content_helper_settings_values(); | |
| 536 | - } | |
| 537 | - | |
| 538 | - // New plugin installation that hasn't saved its options yet. | |
| 539 | 412 | if ( ! is_array( $options ) ) { |
| 540 | 413 | $this->set_default_track_as_values(); |
| 541 | 414 | $this->set_default_full_metadata_in_non_posts(); |
| 542 | 415 | $options = $this->option_defaults; |
| @@ -555,30 +428,8 @@ | ||
| 555 | 428 | ); |
| 556 | 429 | } |
| 557 | 430 | |
| 558 | 431 | /** |
| 559 | - * Returns the value of a nested option. | |
| 560 | - * | |
| 561 | - * @since 3.16.0 | |
| 562 | - * | |
| 563 | - * @param string $option The option to get. | |
| 564 | - * @param Parsely_Options $options The options to get the value from. | |
| 565 | - * @return mixed The value of the nested option. | |
| 566 | - */ | |
| 567 | - public static function get_nested_option_value( $option, $options ) { | |
| 568 | - $keys = explode( '[', str_replace( ']', '', $option ) ); | |
| 569 | - $value = $options; | |
| 570 | - | |
| 571 | - foreach ( $keys as $key ) { | |
| 572 | - if ( isset( $value[ $key ] ) ) { | |
| 573 | - $value = $value[ $key ]; | |
| 574 | - } | |
| 575 | - } | |
| 576 | - | |
| 577 | - return $value; | |
| 578 | - } | |
| 579 | - | |
| 580 | - /** | |
| 581 | 432 | * Sets the default values for the track_post_types and track_page_types |
| 582 | 433 | * options. |
| 583 | 434 | * |
| 584 | 435 | * @since 3.9.0 |
| @@ -631,24 +482,8 @@ | ||
| 631 | 482 | } |
| 632 | 483 | } |
| 633 | 484 | |
| 634 | 485 | /** |
| 635 | - * Sets the default values for Content Helper options. | |
| 636 | - * | |
| 637 | - * Gives PCH access to all users having the edit_posts capability, to keep | |
| 638 | - * consistent behavior with plugin versions prior to 3.16.0. | |
| 639 | - * | |
| 640 | - * @since 3.16.0 | |
| 641 | - */ | |
| 642 | - public function set_default_content_helper_settings_values(): void { | |
| 643 | - $this->option_defaults['content_helper'] = | |
| 644 | - Permissions::build_pch_permissions_settings_array( | |
| 645 | - true, | |
| 646 | - array_keys( Permissions::get_user_roles_with_edit_posts_cap() ) | |
| 647 | - ); | |
| 648 | - } | |
| 649 | - | |
| 650 | - /** | |
| 651 | 486 | * Gets the URL of the plugin's settings page. |
| 652 | 487 | * |
| 653 | 488 | * @param int|null $_blog_id The Blog ID for the multisite subsite to use |
| 654 | 489 | * for context (Default null for current). |
| @@ -653,9 +488,9 @@ | ||
| 653 | 488 | * @param int|null $_blog_id The Blog ID for the multisite subsite to use |
| 654 | 489 | * for context (Default null for current). |
| 655 | 490 | * @return string |
| 656 | 491 | */ |
| 657 | - public static function get_settings_url( ?int $_blog_id = null ): string { | |
| 492 | + public static function get_settings_url( int $_blog_id = null ): string { | |
| 658 | 493 | return get_admin_url( $_blog_id, 'options-general.php?page=' . self::MENU_SLUG ); |
| 659 | 494 | } |
| 660 | 495 | |
| 661 | 496 | /** |
| @@ -1026,10 +861,10 @@ | ||
| 1026 | 861 | */ |
| 1027 | 862 | private function allow_parsely_remote_requests(): void { |
| 1028 | 863 | $allowed_urls = array( |
| 1029 | 864 | self::DASHBOARD_BASE_URL, |
| 1030 | - Content_API_Service::get_base_url(), | |
| 1031 | - Suggestions_API_Service::get_base_url(), | |
| 865 | + self::PUBLIC_API_BASE_URL, | |
| 866 | + self::PUBLIC_SUGGESTIONS_API_BASE_URL, | |
| 1032 | 867 | ); |
| 1033 | 868 | |
| 1034 | 869 | add_filter( |
| 1035 | 870 | 'http_request_host_is_external', |
| @@ -1035,9 +870,9 @@ | ||
| 1035 | 870 | 'http_request_host_is_external', |
| 1036 | 871 | function ( $external, $host, $url ) use ( $allowed_urls ) { |
| 1037 | 872 | // Check if the URL matches any URLs on the allowed list. |
| 1038 | 873 | foreach ( $allowed_urls as $allowed_url ) { |
| 1039 | - if ( Utils::str_starts_with( $url, $allowed_url ) ) { | |
| 874 | + if ( \Parsely\Utils\str_starts_with( $url, $allowed_url ) ) { | |
| 1040 | 875 | return true; |
| 1041 | 876 | } |
| 1042 | 877 | } |
| 1043 | 878 | return $external; |