| 1 |
<?php |
| 2 |
|
| 3 |
namespace Yoast\WP\SEO\Integrations; |
| 4 |
|
| 5 |
use WP_Post; |
| 6 |
use WP_Post_Type; |
| 7 |
use WP_Taxonomy; |
| 8 |
use WP_User; |
| 9 |
use WPSEO_Addon_Manager; |
| 10 |
use WPSEO_Admin_Asset_Manager; |
| 11 |
use WPSEO_Admin_Editor_Specific_Replace_Vars; |
| 12 |
use WPSEO_Admin_Recommended_Replace_Vars; |
| 13 |
use WPSEO_Option_Titles; |
| 14 |
use WPSEO_Options; |
| 15 |
use WPSEO_Replace_Vars; |
| 16 |
use WPSEO_Shortlinker; |
| 17 |
use WPSEO_Sitemaps_Router; |
| 18 |
use Yoast\WP\SEO\Conditionals\Settings_Conditional; |
| 19 |
use Yoast\WP\SEO\Config\Schema_Types; |
| 20 |
use Yoast\WP\SEO\Content_Type_Visibility\Application\Content_Type_Visibility_Dismiss_Notifications; |
| 21 |
use Yoast\WP\SEO\Helpers\Current_Page_Helper; |
| 22 |
use Yoast\WP\SEO\Helpers\Language_Helper; |
| 23 |
use Yoast\WP\SEO\Helpers\Options_Helper; |
| 24 |
use Yoast\WP\SEO\Helpers\Post_Type_Helper; |
| 25 |
use Yoast\WP\SEO\Helpers\Product_Helper; |
| 26 |
use Yoast\WP\SEO\Helpers\Route_Helper; |
| 27 |
use Yoast\WP\SEO\Helpers\Schema\Article_Helper; |
| 28 |
use Yoast\WP\SEO\Helpers\Taxonomy_Helper; |
| 29 |
use Yoast\WP\SEO\Helpers\User_Helper; |
| 30 |
use Yoast\WP\SEO\Helpers\Woocommerce_Helper; |
| 31 |
use Yoast\WP\SEO\Llms_Txt\Application\Configuration\Llms_Txt_Configuration; |
| 32 |
use Yoast\WP\SEO\Llms_Txt\Application\Health_Check\File_Runner; |
| 33 |
use Yoast\WP\SEO\Llms_Txt\Infrastructure\Content\Manual_Post_Collection; |
| 34 |
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager; |
| 35 |
use Yoast\WP\SEO\Schema\Application\Configuration\Schema_Configuration; |
| 36 |
|
| 37 |
/** |
| 38 |
* Class Settings_Integration. |
| 39 |
*/ |
| 40 |
class Settings_Integration implements Integration_Interface { |
| 41 |
|
| 42 |
public const PAGE = 'wpseo_page_settings'; |
| 43 |
|
| 44 |
/** |
| 45 |
* Holds the included WordPress options. |
| 46 |
* |
| 47 |
* @var string[] |
| 48 |
*/ |
| 49 |
public const WP_OPTIONS = [ 'blogdescription' ]; |
| 50 |
|
| 51 |
/** |
| 52 |
* Holds the allowed option groups. |
| 53 |
* |
| 54 |
* @var array |
| 55 |
*/ |
| 56 |
public const ALLOWED_OPTION_GROUPS = [ 'wpseo', 'wpseo_titles', 'wpseo_social', 'wpseo_llmstxt' ]; |
| 57 |
|
| 58 |
/** |
| 59 |
* Holds the disallowed settings, per option group. |
| 60 |
* |
| 61 |
* @var array |
| 62 |
*/ |
| 63 |
public const DISALLOWED_SETTINGS = [ |
| 64 |
'wpseo' => [ |
| 65 |
'myyoast-oauth', |
| 66 |
'semrush_tokens', |
| 67 |
'custom_taxonomy_slugs', |
| 68 |
'import_cursors', |
| 69 |
'workouts_data', |
| 70 |
'configuration_finished_steps', |
| 71 |
'importing_completed', |
| 72 |
'wincher_tokens', |
| 73 |
'least_readability_ignore_list', |
| 74 |
'least_seo_score_ignore_list', |
| 75 |
'most_linked_ignore_list', |
| 76 |
'least_linked_ignore_list', |
| 77 |
'indexables_page_reading_list', |
| 78 |
'show_new_content_type_notification', |
| 79 |
'new_post_types', |
| 80 |
'new_taxonomies', |
| 81 |
], |
| 82 |
'wpseo_titles' => [ |
| 83 |
'company_logo_meta', |
| 84 |
'person_logo_meta', |
| 85 |
], |
| 86 |
]; |
| 87 |
|
| 88 |
/** |
| 89 |
* Holds the disabled on multisite settings, per option group. |
| 90 |
* |
| 91 |
* @var array |
| 92 |
*/ |
| 93 |
public const DISABLED_ON_MULTISITE_SETTINGS = [ |
| 94 |
'wpseo' => [ |
| 95 |
'deny_search_crawling', |
| 96 |
'deny_wp_json_crawling', |
| 97 |
'deny_adsbot_crawling', |
| 98 |
'deny_ccbot_crawling', |
| 99 |
'deny_google_extended_crawling', |
| 100 |
'deny_gptbot_crawling', |
| 101 |
'enable_llms_txt', |
| 102 |
], |
| 103 |
]; |
| 104 |
|
| 105 |
/** |
| 106 |
* Holds the WPSEO_Admin_Asset_Manager. |
| 107 |
* |
| 108 |
* @var WPSEO_Admin_Asset_Manager |
| 109 |
*/ |
| 110 |
protected $asset_manager; |
| 111 |
|
| 112 |
/** |
| 113 |
* Holds the WPSEO_Replace_Vars. |
| 114 |
* |
| 115 |
* @var WPSEO_Replace_Vars |
| 116 |
*/ |
| 117 |
protected $replace_vars; |
| 118 |
|
| 119 |
/** |
| 120 |
* Holds the Schema_Types. |
| 121 |
* |
| 122 |
* @var Schema_Types |
| 123 |
*/ |
| 124 |
protected $schema_types; |
| 125 |
|
| 126 |
/** |
| 127 |
* Holds the Current_Page_Helper. |
| 128 |
* |
| 129 |
* @var Current_Page_Helper |
| 130 |
*/ |
| 131 |
protected $current_page_helper; |
| 132 |
|
| 133 |
/** |
| 134 |
* Holds the Post_Type_Helper. |
| 135 |
* |
| 136 |
* @var Post_Type_Helper |
| 137 |
*/ |
| 138 |
protected $post_type_helper; |
| 139 |
|
| 140 |
/** |
| 141 |
* Holds the Language_Helper. |
| 142 |
* |
| 143 |
* @var Language_Helper |
| 144 |
*/ |
| 145 |
protected $language_helper; |
| 146 |
|
| 147 |
/** |
| 148 |
* Holds the Taxonomy_Helper. |
| 149 |
* |
| 150 |
* @var Taxonomy_Helper |
| 151 |
*/ |
| 152 |
protected $taxonomy_helper; |
| 153 |
|
| 154 |
/** |
| 155 |
* Holds the Product_Helper. |
| 156 |
* |
| 157 |
* @var Product_Helper |
| 158 |
*/ |
| 159 |
protected $product_helper; |
| 160 |
|
| 161 |
/** |
| 162 |
* Holds the Woocommerce_Helper. |
| 163 |
* |
| 164 |
* @var Woocommerce_Helper |
| 165 |
*/ |
| 166 |
protected $woocommerce_helper; |
| 167 |
|
| 168 |
/** |
| 169 |
* Holds the Article_Helper. |
| 170 |
* |
| 171 |
* @var Article_Helper |
| 172 |
*/ |
| 173 |
protected $article_helper; |
| 174 |
|
| 175 |
/** |
| 176 |
* Holds the User_Helper. |
| 177 |
* |
| 178 |
* @var User_Helper |
| 179 |
*/ |
| 180 |
protected $user_helper; |
| 181 |
|
| 182 |
/** |
| 183 |
* Holds the Options_Helper instance. |
| 184 |
* |
| 185 |
* @var Options_Helper |
| 186 |
*/ |
| 187 |
protected $options; |
| 188 |
|
| 189 |
/** |
| 190 |
* Holds the Content_Type_Visibility_Dismiss_Notifications instance. |
| 191 |
* |
| 192 |
* @var Content_Type_Visibility_Dismiss_Notifications |
| 193 |
*/ |
| 194 |
protected $content_type_visibility; |
| 195 |
|
| 196 |
/** |
| 197 |
* Holds the Llms_Txt_Configuration instance. |
| 198 |
* |
| 199 |
* @var Llms_Txt_Configuration |
| 200 |
*/ |
| 201 |
protected $llms_txt_configuration; |
| 202 |
|
| 203 |
/** |
| 204 |
* Holds the Schema_Configuration instance. |
| 205 |
* |
| 206 |
* @var Schema_Configuration |
| 207 |
*/ |
| 208 |
protected $schema_configuration; |
| 209 |
|
| 210 |
/** |
| 211 |
* The manual post collection. |
| 212 |
* |
| 213 |
* @var Manual_Post_Collection |
| 214 |
*/ |
| 215 |
private $manual_post_collection; |
| 216 |
|
| 217 |
/** |
| 218 |
* Runs the health check. |
| 219 |
* |
| 220 |
* @var File_Runner |
| 221 |
*/ |
| 222 |
private $runner; |
| 223 |
|
| 224 |
/** |
| 225 |
* Holds the Route_Helper. |
| 226 |
* |
| 227 |
* @var Route_Helper |
| 228 |
*/ |
| 229 |
private $route_helper; |
| 230 |
|
| 231 |
/** |
| 232 |
* Constructs Settings_Integration. |
| 233 |
* |
| 234 |
* @param WPSEO_Admin_Asset_Manager $asset_manager The WPSEO_Admin_Asset_Manager. |
| 235 |
* @param WPSEO_Replace_Vars $replace_vars The WPSEO_Replace_Vars. |
| 236 |
* @param Schema_Types $schema_types The Schema_Types. |
| 237 |
* @param Current_Page_Helper $current_page_helper The Current_Page_Helper. |
| 238 |
* @param Post_Type_Helper $post_type_helper The Post_Type_Helper. |
| 239 |
* @param Language_Helper $language_helper The Language_Helper. |
| 240 |
* @param Taxonomy_Helper $taxonomy_helper The Taxonomy_Helper. |
| 241 |
* @param Product_Helper $product_helper The Product_Helper. |
| 242 |
* @param Woocommerce_Helper $woocommerce_helper The Woocommerce_Helper. |
| 243 |
* @param Article_Helper $article_helper The Article_Helper. |
| 244 |
* @param User_Helper $user_helper The User_Helper. |
| 245 |
* @param Options_Helper $options The options helper. |
| 246 |
* @param Content_Type_Visibility_Dismiss_Notifications $content_type_visibility The Content_Type_Visibility_Dismiss_Notifications instance. |
| 247 |
* @param Llms_Txt_Configuration $llms_txt_configuration The Llms_Txt_Configuration instance. |
| 248 |
* @param Manual_Post_Collection $manual_post_collection The manual post collection. |
| 249 |
* @param File_Runner $runner The file runner. |
| 250 |
* @param Route_Helper $route_helper The Route_Helper. |
| 251 |
* @param Schema_Configuration $schema_configuration The Schema_Configuration. |
| 252 |
*/ |
| 253 |
public function __construct( |
| 254 |
WPSEO_Admin_Asset_Manager $asset_manager, |
| 255 |
WPSEO_Replace_Vars $replace_vars, |
| 256 |
Schema_Types $schema_types, |
| 257 |
Current_Page_Helper $current_page_helper, |
| 258 |
Post_Type_Helper $post_type_helper, |
| 259 |
Language_Helper $language_helper, |
| 260 |
Taxonomy_Helper $taxonomy_helper, |
| 261 |
Product_Helper $product_helper, |
| 262 |
Woocommerce_Helper $woocommerce_helper, |
| 263 |
Article_Helper $article_helper, |
| 264 |
User_Helper $user_helper, |
| 265 |
Options_Helper $options, |
| 266 |
Content_Type_Visibility_Dismiss_Notifications $content_type_visibility, |
| 267 |
Llms_Txt_Configuration $llms_txt_configuration, |
| 268 |
Manual_Post_Collection $manual_post_collection, |
| 269 |
File_Runner $runner, |
| 270 |
Route_Helper $route_helper, |
| 271 |
Schema_Configuration $schema_configuration |
| 272 |
) { |
| 273 |
$this->asset_manager = $asset_manager; |
| 274 |
$this->replace_vars = $replace_vars; |
| 275 |
$this->schema_types = $schema_types; |
| 276 |
$this->current_page_helper = $current_page_helper; |
| 277 |
$this->taxonomy_helper = $taxonomy_helper; |
| 278 |
$this->post_type_helper = $post_type_helper; |
| 279 |
$this->language_helper = $language_helper; |
| 280 |
$this->product_helper = $product_helper; |
| 281 |
$this->woocommerce_helper = $woocommerce_helper; |
| 282 |
$this->article_helper = $article_helper; |
| 283 |
$this->user_helper = $user_helper; |
| 284 |
$this->options = $options; |
| 285 |
$this->content_type_visibility = $content_type_visibility; |
| 286 |
$this->llms_txt_configuration = $llms_txt_configuration; |
| 287 |
$this->manual_post_collection = $manual_post_collection; |
| 288 |
$this->runner = $runner; |
| 289 |
$this->route_helper = $route_helper; |
| 290 |
$this->schema_configuration = $schema_configuration; |
| 291 |
} |
| 292 |
|
| 293 |
/** |
| 294 |
* Returns the conditionals based on which this loadable should be active. |
| 295 |
* |
| 296 |
* @return array |
| 297 |
*/ |
| 298 |
public static function get_conditionals() { |
| 299 |
return [ Settings_Conditional::class ]; |
| 300 |
} |
| 301 |
|
| 302 |
/** |
| 303 |
* Initializes the integration. |
| 304 |
* |
| 305 |
* This is the place to register hooks and filters. |
| 306 |
* |
| 307 |
* @return void |
| 308 |
*/ |
| 309 |
public function register_hooks() { |
| 310 |
// Add page. |
| 311 |
\add_filter( 'wpseo_submenu_pages', [ $this, 'add_page' ] ); |
| 312 |
\add_filter( 'admin_menu', [ $this, 'add_settings_saved_page' ] ); |
| 313 |
|
| 314 |
// Are we saving the settings? |
| 315 |
if ( $this->current_page_helper->get_current_admin_page() === 'options.php' ) { |
| 316 |
$post_action = ''; |
| 317 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: We are not processing form information. |
| 318 |
if ( isset( $_POST['action'] ) && \is_string( $_POST['action'] ) ) { |
| 319 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information. |
| 320 |
$post_action = \wp_unslash( $_POST['action'] ); |
| 321 |
} |
| 322 |
$option_page = ''; |
| 323 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: We are not processing form information. |
| 324 |
if ( isset( $_POST['option_page'] ) && \is_string( $_POST['option_page'] ) ) { |
| 325 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information. |
| 326 |
$option_page = \wp_unslash( $_POST['option_page'] ); |
| 327 |
} |
| 328 |
|
| 329 |
if ( $post_action === 'update' && $option_page === self::PAGE ) { |
| 330 |
\add_action( 'admin_init', [ $this, 'register_setting' ] ); |
| 331 |
\add_action( 'in_admin_header', [ $this, 'remove_notices' ], \PHP_INT_MAX ); |
| 332 |
} |
| 333 |
|
| 334 |
return; |
| 335 |
} |
| 336 |
|
| 337 |
// Are we on the settings page? |
| 338 |
if ( $this->current_page_helper->get_current_yoast_seo_page() === self::PAGE ) { |
| 339 |
\add_action( 'admin_init', [ $this, 'register_setting' ] ); |
| 340 |
\add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); |
| 341 |
\add_action( 'in_admin_header', [ $this, 'remove_notices' ], \PHP_INT_MAX ); |
| 342 |
} |
| 343 |
} |
| 344 |
|
| 345 |
/** |
| 346 |
* Registers the different options under the setting. |
| 347 |
* |
| 348 |
* @return void |
| 349 |
*/ |
| 350 |
public function register_setting() { |
| 351 |
foreach ( WPSEO_Options::$options as $name => $instance ) { |
| 352 |
if ( \in_array( $name, self::ALLOWED_OPTION_GROUPS, true ) ) { |
| 353 |
\register_setting( self::PAGE, $name ); |
| 354 |
} |
| 355 |
} |
| 356 |
// Only register WP options when the user is allowed to manage them. |
| 357 |
if ( \current_user_can( 'manage_options' ) ) { |
| 358 |
foreach ( self::WP_OPTIONS as $name ) { |
| 359 |
\register_setting( self::PAGE, $name ); |
| 360 |
} |
| 361 |
} |
| 362 |
} |
| 363 |
|
| 364 |
/** |
| 365 |
* Adds the page. |
| 366 |
* |
| 367 |
* @param array $pages The pages. |
| 368 |
* |
| 369 |
* @return array The pages. |
| 370 |
*/ |
| 371 |
public function add_page( $pages ) { |
| 372 |
\array_splice( |
| 373 |
$pages, |
| 374 |
1, |
| 375 |
0, |
| 376 |
[ |
| 377 |
[ |
| 378 |
'wpseo_dashboard', |
| 379 |
'', |
| 380 |
\__( 'Settings', 'wordpress-seo' ), |
| 381 |
'wpseo_manage_options', |
| 382 |
self::PAGE, |
| 383 |
[ $this, 'display_page' ], |
| 384 |
], |
| 385 |
], |
| 386 |
); |
| 387 |
|
| 388 |
return $pages; |
| 389 |
} |
| 390 |
|
| 391 |
/** |
| 392 |
* Adds a dummy page. |
| 393 |
* |
| 394 |
* Because the options route NEEDS to redirect to something. |
| 395 |
* |
| 396 |
* @param array $pages The pages. |
| 397 |
* |
| 398 |
* @return array The pages. |
| 399 |
*/ |
| 400 |
public function add_settings_saved_page( $pages ) { |
| 401 |
$runner = $this->runner; |
| 402 |
\add_submenu_page( |
| 403 |
'options.php', |
| 404 |
'', |
| 405 |
'', |
| 406 |
'wpseo_manage_options', |
| 407 |
self::PAGE . '_saved', |
| 408 |
static function () use ( $runner ) { |
| 409 |
// Add success indication to HTML response. |
| 410 |
$success = empty( \get_settings_errors() ) ? 'true' : 'false'; |
| 411 |
echo \esc_html( "{{ yoast-success: $success }}" ); |
| 412 |
|
| 413 |
$runner->run(); |
| 414 |
if ( ! $runner->is_successful() ) { |
| 415 |
$failure_reason = $runner->get_generation_failure_reason(); |
| 416 |
echo \esc_html( "{{ yoast-llms-txt-generation-failure: $failure_reason }}" ); |
| 417 |
} |
| 418 |
}, |
| 419 |
); |
| 420 |
|
| 421 |
return $pages; |
| 422 |
} |
| 423 |
|
| 424 |
/** |
| 425 |
* Displays the page. |
| 426 |
* |
| 427 |
* @return void |
| 428 |
*/ |
| 429 |
public function display_page() { |
| 430 |
echo '<div id="yoast-seo-settings"></div>'; |
| 431 |
} |
| 432 |
|
| 433 |
/** |
| 434 |
* Enqueues the assets. |
| 435 |
* |
| 436 |
* @return void |
| 437 |
*/ |
| 438 |
public function enqueue_assets() { |
| 439 |
// Remove the emoji script as it is incompatible with both React and any contenteditable fields. |
| 440 |
\remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); |
| 441 |
\wp_enqueue_media(); |
| 442 |
$this->asset_manager->enqueue_script( 'new-settings' ); |
| 443 |
$this->asset_manager->enqueue_style( 'new-settings' ); |
| 444 |
if ( \YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-promotion' ) ) { |
| 445 |
$this->asset_manager->enqueue_style( 'black-friday-banner' ); |
| 446 |
} |
| 447 |
$this->asset_manager->localize_script( 'new-settings', 'wpseoScriptData', $this->get_script_data() ); |
| 448 |
} |
| 449 |
|
| 450 |
/** |
| 451 |
* Removes all current WP notices. |
| 452 |
* |
| 453 |
* @return void |
| 454 |
*/ |
| 455 |
public function remove_notices() { |
| 456 |
\remove_all_actions( 'admin_notices' ); |
| 457 |
\remove_all_actions( 'user_admin_notices' ); |
| 458 |
\remove_all_actions( 'network_admin_notices' ); |
| 459 |
\remove_all_actions( 'all_admin_notices' ); |
| 460 |
} |
| 461 |
|
| 462 |
/** |
| 463 |
* Creates the script data. |
| 464 |
* |
| 465 |
* @return array The script data. |
| 466 |
*/ |
| 467 |
protected function get_script_data() { |
| 468 |
$default_setting_values = $this->get_default_setting_values(); |
| 469 |
$settings = $this->get_settings( $default_setting_values ); |
| 470 |
$post_types = $this->post_type_helper->get_indexable_post_type_objects(); |
| 471 |
$taxonomies = $this->taxonomy_helper->get_indexable_taxonomy_objects(); |
| 472 |
|
| 473 |
// Check if attachments are included in indexation. |
| 474 |
if ( ! \array_key_exists( 'attachment', $post_types ) ) { |
| 475 |
// Always include attachments in the settings, to let the user enable them again. |
| 476 |
$attachment_object = \get_post_type_object( 'attachment' ); |
| 477 |
if ( ! empty( $attachment_object ) ) { |
| 478 |
$post_types['attachment'] = $attachment_object; |
| 479 |
} |
| 480 |
} |
| 481 |
// Check if post formats are included in indexation. |
| 482 |
if ( ! \array_key_exists( 'post_format', $taxonomies ) ) { |
| 483 |
// Always include post_format in the settings, to let the user enable them again. |
| 484 |
$post_format_object = \get_taxonomy( 'post_format' ); |
| 485 |
if ( ! empty( $post_format_object ) ) { |
| 486 |
$taxonomies['post_format'] = $post_format_object; |
| 487 |
} |
| 488 |
} |
| 489 |
|
| 490 |
$transformed_post_types = $this->transform_post_types( $post_types ); |
| 491 |
$transformed_taxonomies = $this->transform_taxonomies( $taxonomies, \array_keys( $transformed_post_types ) ); |
| 492 |
|
| 493 |
// Check if there is a new content type to show notification only once in the settings. |
| 494 |
$show_new_content_type_notification = $this->content_type_visibility->maybe_add_settings_notification(); |
| 495 |
|
| 496 |
return [ |
| 497 |
'settings' => $this->transform_settings( $settings ), |
| 498 |
'defaultSettingValues' => $default_setting_values, |
| 499 |
'disabledSettings' => $this->get_disabled_settings( $settings ), |
| 500 |
'endpoint' => \admin_url( 'options.php' ), |
| 501 |
'nonce' => \wp_create_nonce( self::PAGE . '-options' ), |
| 502 |
'separators' => WPSEO_Option_Titles::get_instance()->get_separator_options_for_display(), |
| 503 |
'replacementVariables' => $this->get_replacement_variables(), |
| 504 |
'schema' => $this->get_schema( $transformed_post_types ), |
| 505 |
'preferences' => $this->get_preferences( $settings ), |
| 506 |
'linkParams' => WPSEO_Shortlinker::get_query_params(), |
| 507 |
'postTypes' => $transformed_post_types, |
| 508 |
'taxonomies' => $transformed_taxonomies, |
| 509 |
'fallbacks' => $this->get_fallbacks(), |
| 510 |
'showNewContentTypeNotification' => $show_new_content_type_notification, |
| 511 |
'currentPromotions' => \YoastSEO()->classes->get( Promotion_Manager::class )->get_current_promotions(), |
| 512 |
'llmsTxt' => $this->llms_txt_configuration->get_configuration(), |
| 513 |
'initialLlmTxtPages' => $this->get_site_llms_txt_pages( $settings ), |
| 514 |
'schemaFrameworkConfiguration' => $this->schema_configuration->get_configuration(), |
| 515 |
]; |
| 516 |
} |
| 517 |
|
| 518 |
/** |
| 519 |
* Retrieves the preferences. |
| 520 |
* |
| 521 |
* @param array $settings The settings. |
| 522 |
* |
| 523 |
* @return array The preferences. |
| 524 |
*/ |
| 525 |
protected function get_preferences( $settings ) { |
| 526 |
$shop_page_id = $this->woocommerce_helper->get_shop_page_id(); |
| 527 |
$homepage_is_latest_posts = \get_option( 'show_on_front' ) === 'posts'; |
| 528 |
$page_on_front = \get_option( 'page_on_front' ); |
| 529 |
$page_for_posts = \get_option( 'page_for_posts' ); |
| 530 |
|
| 531 |
$addon_manager = new WPSEO_Addon_Manager(); |
| 532 |
$woocommerce_seo_active = \is_plugin_active( $addon_manager->get_plugin_file( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ) ); |
| 533 |
|
| 534 |
if ( empty( $page_on_front ) ) { |
| 535 |
$page_on_front = $page_for_posts; |
| 536 |
} |
| 537 |
|
| 538 |
$business_settings_url = \get_admin_url( null, 'admin.php?page=wpseo_local' ); |
| 539 |
if ( \defined( 'WPSEO_LOCAL_FILE' ) ) { |
| 540 |
$local_options = \get_option( 'wpseo_local' ); |
| 541 |
$multiple_locations = $local_options['use_multiple_locations']; |
| 542 |
$same_organization = $local_options['multiple_locations_same_organization']; |
| 543 |
if ( $multiple_locations === 'on' && $same_organization !== 'on' ) { |
| 544 |
$business_settings_url = \get_admin_url( null, 'edit.php?post_type=wpseo_locations' ); |
| 545 |
} |
| 546 |
} |
| 547 |
|
| 548 |
return [ |
| 549 |
'isPremium' => $this->product_helper->is_premium(), |
| 550 |
'isRtl' => \is_rtl(), |
| 551 |
'isNetworkAdmin' => \is_network_admin(), |
| 552 |
'isMainSite' => \is_main_site(), |
| 553 |
'isMultisite' => \is_multisite(), |
| 554 |
'isWooCommerceActive' => $this->woocommerce_helper->is_active(), |
| 555 |
'isLocalSeoActive' => \defined( 'WPSEO_LOCAL_FILE' ), |
| 556 |
'isNewsSeoActive' => \defined( 'WPSEO_NEWS_FILE' ), |
| 557 |
'isWooCommerceSEOActive' => $woocommerce_seo_active, |
| 558 |
'siteUrl' => \get_bloginfo( 'url' ), |
| 559 |
'siteTitle' => \get_bloginfo( 'name' ), |
| 560 |
'sitemapUrl' => WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ), |
| 561 |
'hasWooCommerceShopPage' => $shop_page_id !== -1, |
| 562 |
'editWooCommerceShopPageUrl' => \get_edit_post_link( $shop_page_id, 'js' ), |
| 563 |
'wooCommerceShopPageSettingUrl' => \get_admin_url( null, 'admin.php?page=wc-settings&tab=products' ), |
| 564 |
'localSeoPageSettingUrl' => $business_settings_url, |
| 565 |
'homepageIsLatestPosts' => $homepage_is_latest_posts, |
| 566 |
'homepagePageEditUrl' => \get_edit_post_link( $page_on_front, 'js' ), |
| 567 |
'homepagePostsEditUrl' => \get_edit_post_link( $page_for_posts, 'js' ), |
| 568 |
'createUserUrl' => \admin_url( 'user-new.php' ), |
| 569 |
'createPageUrl' => \admin_url( 'post-new.php?post_type=page' ), |
| 570 |
'editUserUrl' => \admin_url( 'user-edit.php' ), |
| 571 |
'editTaxonomyUrl' => \admin_url( 'edit-tags.php' ), |
| 572 |
'generalSettingsUrl' => \admin_url( 'options-general.php' ), |
| 573 |
'companyOrPersonMessage' => \apply_filters( 'wpseo_knowledge_graph_setting_msg', '' ), |
| 574 |
'currentUserId' => \get_current_user_id(), |
| 575 |
'canCreateUsers' => \current_user_can( 'create_users' ), |
| 576 |
'canCreatePages' => \current_user_can( 'edit_pages' ), |
| 577 |
'canEditUsers' => \current_user_can( 'edit_users' ), |
| 578 |
'canManageOptions' => \current_user_can( 'manage_options' ), |
| 579 |
'userLocale' => \str_replace( '_', '-', \get_user_locale() ), |
| 580 |
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ), |
| 581 |
'showForceRewriteTitlesSetting' => ! \current_theme_supports( 'title-tag' ) && ! ( \function_exists( 'wp_is_block_theme' ) && \wp_is_block_theme() ), |
| 582 |
'upsellSettings' => $this->get_upsell_settings(), |
| 583 |
'siteRepresentsPerson' => $this->get_site_represents_person( $settings ), |
| 584 |
'siteBasicsPolicies' => $this->get_site_basics_policies( $settings ), |
| 585 |
]; |
| 586 |
} |
| 587 |
|
| 588 |
/** |
| 589 |
* Retrieves the currently represented person. |
| 590 |
* |
| 591 |
* @param array $settings The settings. |
| 592 |
* |
| 593 |
* @return array The currently represented person. |
| 594 |
*/ |
| 595 |
protected function get_site_represents_person( $settings ) { |
| 596 |
$person = [ |
| 597 |
'id' => false, |
| 598 |
'name' => '', |
| 599 |
]; |
| 600 |
|
| 601 |
if ( isset( $settings['wpseo_titles']['company_or_person_user_id'] ) ) { |
| 602 |
$person['id'] = $settings['wpseo_titles']['company_or_person_user_id']; |
| 603 |
$user = \get_userdata( $person['id'] ); |
| 604 |
if ( $user instanceof WP_User ) { |
| 605 |
$person['name'] = $user->get( 'display_name' ); |
| 606 |
} |
| 607 |
} |
| 608 |
|
| 609 |
return $person; |
| 610 |
} |
| 611 |
|
| 612 |
/** |
| 613 |
* Get site policy data. |
| 614 |
* |
| 615 |
* @param array $settings The settings. |
| 616 |
* |
| 617 |
* @return array The policy data. |
| 618 |
*/ |
| 619 |
private function get_site_basics_policies( $settings ) { |
| 620 |
$policies = []; |
| 621 |
|
| 622 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['publishing_principles_id'], 'publishing_principles_id' ); |
| 623 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['ownership_funding_info_id'], 'ownership_funding_info_id' ); |
| 624 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['actionable_feedback_policy_id'], 'actionable_feedback_policy_id' ); |
| 625 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['corrections_policy_id'], 'corrections_policy_id' ); |
| 626 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['ethics_policy_id'], 'ethics_policy_id' ); |
| 627 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['diversity_policy_id'], 'diversity_policy_id' ); |
| 628 |
$policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['diversity_staffing_report_id'], 'diversity_staffing_report_id' ); |
| 629 |
|
| 630 |
return $policies; |
| 631 |
} |
| 632 |
|
| 633 |
/** |
| 634 |
* Adds policy data if it is present. |
| 635 |
* |
| 636 |
* @param array $policies The existing policy data. |
| 637 |
* @param int $policy The policy id to check. |
| 638 |
* @param string $key The option key name. |
| 639 |
* |
| 640 |
* @return array<int, string> The policy data. |
| 641 |
*/ |
| 642 |
private function maybe_add_policy( $policies, $policy, $key ) { |
| 643 |
$policy_array = [ |
| 644 |
'id' => 0, |
| 645 |
'name' => \__( 'None', 'wordpress-seo' ), |
| 646 |
]; |
| 647 |
|
| 648 |
if ( isset( $policy ) && \is_int( $policy ) ) { |
| 649 |
$policy_array['id'] = $policy; |
| 650 |
$post = \get_post( $policy ); |
| 651 |
if ( $post instanceof WP_Post ) { |
| 652 |
if ( $post->post_status !== 'publish' || $post->post_password !== '' ) { |
| 653 |
return $policies; |
| 654 |
} |
| 655 |
$policy_array['name'] = $post->post_title; |
| 656 |
} |
| 657 |
} |
| 658 |
|
| 659 |
$policies[ $key ] = $policy_array; |
| 660 |
|
| 661 |
return $policies; |
| 662 |
} |
| 663 |
|
| 664 |
/** |
| 665 |
* Adds page if it is present. |
| 666 |
* |
| 667 |
* @param array<int, string> $pages The existing pages. |
| 668 |
* @param int $page_id The page id to check. |
| 669 |
* @param string $key The option key name. |
| 670 |
* |
| 671 |
* @return array<int, string> The policy data. |
| 672 |
*/ |
| 673 |
private function maybe_add_page( $pages, $page_id, $key ) { |
| 674 |
if ( isset( $page_id ) && \is_int( $page_id ) && $page_id !== 0 ) { |
| 675 |
$post = $this->manual_post_collection->get_content_type_entry( $page_id ); |
| 676 |
if ( $post === null ) { |
| 677 |
return $pages; |
| 678 |
} |
| 679 |
|
| 680 |
$pages[ $key ] = [ |
| 681 |
'id' => $page_id, |
| 682 |
'title' => ( $post->get_title() ) ? $post->get_title() : $post->get_slug(), |
| 683 |
'slug' => $post->get_slug(), |
| 684 |
]; |
| 685 |
} |
| 686 |
|
| 687 |
return $pages; |
| 688 |
} |
| 689 |
|
| 690 |
/** |
| 691 |
* Get site llms.txt pages. |
| 692 |
* |
| 693 |
* @param array $settings The settings. |
| 694 |
* |
| 695 |
* @return array<string, array<string, int|string>> The llms.txt pages. |
| 696 |
*/ |
| 697 |
private function get_site_llms_txt_pages( $settings ) { |
| 698 |
$llms_txt_pages = []; |
| 699 |
|
| 700 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $settings['wpseo_llmstxt']['about_us_page'], 'about_us_page' ); |
| 701 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $settings['wpseo_llmstxt']['contact_page'], 'contact_page' ); |
| 702 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $settings['wpseo_llmstxt']['terms_page'], 'terms_page' ); |
| 703 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $settings['wpseo_llmstxt']['privacy_policy_page'], 'privacy_policy_page' ); |
| 704 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $settings['wpseo_llmstxt']['shop_page'], 'shop_page' ); |
| 705 |
|
| 706 |
if ( isset( $settings['wpseo_llmstxt']['other_included_pages'] ) && \is_array( $settings['wpseo_llmstxt']['other_included_pages'] ) ) { |
| 707 |
foreach ( $settings['wpseo_llmstxt']['other_included_pages'] as $key => $page_id ) { |
| 708 |
$llms_txt_pages = $this->maybe_add_page( $llms_txt_pages, $page_id, 'other_included_pages-' . $key ); |
| 709 |
} |
| 710 |
} |
| 711 |
|
| 712 |
return $llms_txt_pages; |
| 713 |
} |
| 714 |
|
| 715 |
/** |
| 716 |
* Returns settings for the Call to Buy (CTB) buttons. |
| 717 |
* |
| 718 |
* @return array<string> The array of CTB settings. |
| 719 |
*/ |
| 720 |
public function get_upsell_settings() { |
| 721 |
return [ |
| 722 |
'actionId' => 'load-nfd-ctb', |
| 723 |
'premiumCtbId' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2', |
| 724 |
]; |
| 725 |
} |
| 726 |
|
| 727 |
/** |
| 728 |
* Retrieves the default setting values. |
| 729 |
* |
| 730 |
* These default values are currently being used in the UI for dummy fields. |
| 731 |
* Dummy fields should not expose or reflect the actual data. |
| 732 |
* |
| 733 |
* @return array The default setting values. |
| 734 |
*/ |
| 735 |
protected function get_default_setting_values() { |
| 736 |
$defaults = []; |
| 737 |
|
| 738 |
// Add Yoast settings. |
| 739 |
foreach ( WPSEO_Options::$options as $option_name => $instance ) { |
| 740 |
if ( \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) { |
| 741 |
$option_instance = WPSEO_Options::get_option_instance( $option_name ); |
| 742 |
$defaults[ $option_name ] = ( $option_instance ) ? $option_instance->get_defaults() : []; |
| 743 |
} |
| 744 |
} |
| 745 |
// Add WP settings. |
| 746 |
foreach ( self::WP_OPTIONS as $option_name ) { |
| 747 |
$defaults[ $option_name ] = ''; |
| 748 |
} |
| 749 |
|
| 750 |
// Remove disallowed settings. |
| 751 |
foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) { |
| 752 |
foreach ( $disallowed_settings as $disallowed_setting ) { |
| 753 |
unset( $defaults[ $option_name ][ $disallowed_setting ] ); |
| 754 |
} |
| 755 |
} |
| 756 |
|
| 757 |
if ( \defined( 'WPSEO_LOCAL_FILE' ) ) { |
| 758 |
$defaults = $this->get_defaults_from_local_seo( $defaults ); |
| 759 |
} |
| 760 |
|
| 761 |
return $defaults; |
| 762 |
} |
| 763 |
|
| 764 |
/** |
| 765 |
* Retrieves the organization schema values from Local SEO for defaults in Site representation fields. |
| 766 |
* Specifically for the org-vat-id, org-tax-id, org-email and org-phone options. |
| 767 |
* |
| 768 |
* @param array<string|int|bool> $defaults The settings defaults. |
| 769 |
* |
| 770 |
* @return array<string|int|bool> The settings defaults with local seo overides. |
| 771 |
*/ |
| 772 |
protected function get_defaults_from_local_seo( $defaults ) { |
| 773 |
$local_options = \get_option( 'wpseo_local' ); |
| 774 |
$multiple_locations = $local_options['use_multiple_locations']; |
| 775 |
$same_organization = $local_options['multiple_locations_same_organization']; |
| 776 |
$shared_info = $local_options['multiple_locations_shared_business_info']; |
| 777 |
if ( $multiple_locations !== 'on' || ( $multiple_locations === 'on' && $same_organization === 'on' && $shared_info === 'on' ) ) { |
| 778 |
$defaults['wpseo_titles']['org-vat-id'] = $local_options['location_vat_id']; |
| 779 |
$defaults['wpseo_titles']['org-tax-id'] = $local_options['location_tax_id']; |
| 780 |
$defaults['wpseo_titles']['org-email'] = $local_options['location_email']; |
| 781 |
$defaults['wpseo_titles']['org-phone'] = $local_options['location_phone']; |
| 782 |
} |
| 783 |
|
| 784 |
if ( \wpseo_has_primary_location() ) { |
| 785 |
$primary_location = $local_options['multiple_locations_primary_location']; |
| 786 |
|
| 787 |
$location_keys = [ |
| 788 |
'org-phone' => [ |
| 789 |
'is_overridden' => '_wpseo_is_overridden_business_phone', |
| 790 |
'value' => '_wpseo_business_phone', |
| 791 |
], |
| 792 |
'org-email' => [ |
| 793 |
'is_overridden' => '_wpseo_is_overridden_business_email', |
| 794 |
'value' => '_wpseo_business_email', |
| 795 |
], |
| 796 |
'org-tax-id' => [ |
| 797 |
'is_overridden' => '_wpseo_is_overridden_business_tax_id', |
| 798 |
'value' => '_wpseo_business_tax_id', |
| 799 |
], |
| 800 |
'org-vat-id' => [ |
| 801 |
'is_overridden' => '_wpseo_is_overridden_business_vat_id', |
| 802 |
'value' => '_wpseo_business_vat_id', |
| 803 |
], |
| 804 |
]; |
| 805 |
|
| 806 |
foreach ( $location_keys as $key => $meta_keys ) { |
| 807 |
$is_overridden = ( $shared_info === 'on' ) ? \get_post_meta( $primary_location, $meta_keys['is_overridden'], true ) : false; |
| 808 |
if ( $is_overridden === 'on' || $shared_info !== 'on' ) { |
| 809 |
$post_meta_value = \get_post_meta( $primary_location, $meta_keys['value'], true ); |
| 810 |
$defaults['wpseo_titles'][ $key ] = ( $post_meta_value ) ? $post_meta_value : ''; |
| 811 |
} |
| 812 |
} |
| 813 |
} |
| 814 |
|
| 815 |
return $defaults; |
| 816 |
} |
| 817 |
|
| 818 |
/** |
| 819 |
* Retrieves the settings and their values. |
| 820 |
* |
| 821 |
* @param array $default_setting_values The default setting values. |
| 822 |
* |
| 823 |
* @return array The settings. |
| 824 |
*/ |
| 825 |
protected function get_settings( $default_setting_values ) { |
| 826 |
$settings = []; |
| 827 |
|
| 828 |
// Add Yoast settings. |
| 829 |
foreach ( WPSEO_Options::$options as $option_name => $instance ) { |
| 830 |
if ( \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) { |
| 831 |
$settings[ $option_name ] = \array_merge( $default_setting_values[ $option_name ], WPSEO_Options::get_option( $option_name ) ); |
| 832 |
} |
| 833 |
} |
| 834 |
// Add WP settings. |
| 835 |
foreach ( self::WP_OPTIONS as $option_name ) { |
| 836 |
$settings[ $option_name ] = \get_option( $option_name ); |
| 837 |
} |
| 838 |
|
| 839 |
// Remove disallowed settings. |
| 840 |
foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) { |
| 841 |
foreach ( $disallowed_settings as $disallowed_setting ) { |
| 842 |
unset( $settings[ $option_name ][ $disallowed_setting ] ); |
| 843 |
} |
| 844 |
} |
| 845 |
|
| 846 |
return $settings; |
| 847 |
} |
| 848 |
|
| 849 |
/** |
| 850 |
* Transforms setting values. |
| 851 |
* |
| 852 |
* @param array $settings The settings. |
| 853 |
* |
| 854 |
* @return array The settings. |
| 855 |
*/ |
| 856 |
protected function transform_settings( $settings ) { |
| 857 |
if ( isset( $settings['wpseo_titles']['breadcrumbs-sep'] ) ) { |
| 858 |
/** |
| 859 |
* The breadcrumbs separator default value is the HTML entity `»`. |
| 860 |
* Which does not get decoded in our JS, while it did in our Yoast form. Decode it here as an exception. |
| 861 |
*/ |
| 862 |
$settings['wpseo_titles']['breadcrumbs-sep'] = \html_entity_decode( |
| 863 |
$settings['wpseo_titles']['breadcrumbs-sep'], |
| 864 |
( \ENT_NOQUOTES | \ENT_HTML5 ), |
| 865 |
'UTF-8', |
| 866 |
); |
| 867 |
} |
| 868 |
|
| 869 |
/** |
| 870 |
* Decode some WP options. |
| 871 |
*/ |
| 872 |
$settings['blogdescription'] = \html_entity_decode( |
| 873 |
$settings['blogdescription'], |
| 874 |
( \ENT_NOQUOTES | \ENT_HTML5 ), |
| 875 |
'UTF-8', |
| 876 |
); |
| 877 |
|
| 878 |
if ( isset( $settings['wpseo_llmstxt']['other_included_pages'] ) ) { |
| 879 |
// Append an empty page to the other included pages, so that we manage to show an empty field in the UI. |
| 880 |
$settings['wpseo_llmstxt']['other_included_pages'][] = 0; |
| 881 |
} |
| 882 |
|
| 883 |
return $settings; |
| 884 |
} |
| 885 |
|
| 886 |
/** |
| 887 |
* Retrieves the disabled settings. |
| 888 |
* |
| 889 |
* @param array $settings The settings. |
| 890 |
* |
| 891 |
* @return array The settings. |
| 892 |
*/ |
| 893 |
protected function get_disabled_settings( $settings ) { |
| 894 |
$disabled_settings = []; |
| 895 |
$site_language = $this->language_helper->get_language(); |
| 896 |
|
| 897 |
foreach ( WPSEO_Options::$options as $option_name => $instance ) { |
| 898 |
if ( ! \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) { |
| 899 |
continue; |
| 900 |
} |
| 901 |
|
| 902 |
$disabled_settings[ $option_name ] = []; |
| 903 |
$option_instance = WPSEO_Options::get_option_instance( $option_name ); |
| 904 |
if ( $option_instance === false ) { |
| 905 |
continue; |
| 906 |
} |
| 907 |
foreach ( $settings[ $option_name ] as $setting_name => $setting_value ) { |
| 908 |
if ( $option_instance->is_disabled( $setting_name ) ) { |
| 909 |
$disabled_settings[ $option_name ][ $setting_name ] = 'network'; |
| 910 |
} |
| 911 |
} |
| 912 |
} |
| 913 |
|
| 914 |
// Remove disabled on multisite settings. |
| 915 |
if ( \is_multisite() ) { |
| 916 |
foreach ( self::DISABLED_ON_MULTISITE_SETTINGS as $option_name => $disabled_ms_settings ) { |
| 917 |
if ( \array_key_exists( $option_name, $disabled_settings ) ) { |
| 918 |
foreach ( $disabled_ms_settings as $disabled_ms_setting ) { |
| 919 |
$disabled_settings[ $option_name ][ $disabled_ms_setting ] = 'multisite'; |
| 920 |
} |
| 921 |
} |
| 922 |
} |
| 923 |
} |
| 924 |
|
| 925 |
if ( \array_key_exists( 'wpseo', $disabled_settings ) && ! $this->language_helper->has_inclusive_language_support( $site_language ) ) { |
| 926 |
$disabled_settings['wpseo']['inclusive_language_analysis_active'] = 'language'; |
| 927 |
} |
| 928 |
|
| 929 |
return $disabled_settings; |
| 930 |
} |
| 931 |
|
| 932 |
/** |
| 933 |
* Retrieves the replacement variables. |
| 934 |
* |
| 935 |
* @return array The replacement variables. |
| 936 |
*/ |
| 937 |
protected function get_replacement_variables() { |
| 938 |
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); |
| 939 |
$specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); |
| 940 |
$replacement_variables = $this->replace_vars->get_replacement_variables_with_labels(); |
| 941 |
|
| 942 |
return [ |
| 943 |
'variables' => $replacement_variables, |
| 944 |
'recommended' => $recommended_replace_vars->get_recommended_replacevars(), |
| 945 |
'specific' => $specific_replace_vars->get(), |
| 946 |
'shared' => $specific_replace_vars->get_generic( $replacement_variables ), |
| 947 |
]; |
| 948 |
} |
| 949 |
|
| 950 |
/** |
| 951 |
* Retrieves the schema. |
| 952 |
* |
| 953 |
* @param array $post_types The post types. |
| 954 |
* |
| 955 |
* @return array The schema. |
| 956 |
*/ |
| 957 |
protected function get_schema( array $post_types ) { |
| 958 |
$schema = []; |
| 959 |
|
| 960 |
foreach ( $this->schema_types->get_article_type_options() as $article_type ) { |
| 961 |
$schema['articleTypes'][ $article_type['value'] ] = [ |
| 962 |
'label' => $article_type['name'], |
| 963 |
'value' => $article_type['value'], |
| 964 |
]; |
| 965 |
} |
| 966 |
|
| 967 |
foreach ( $this->schema_types->get_page_type_options() as $page_type ) { |
| 968 |
$schema['pageTypes'][ $page_type['value'] ] = [ |
| 969 |
'label' => $page_type['name'], |
| 970 |
'value' => $page_type['value'], |
| 971 |
]; |
| 972 |
} |
| 973 |
|
| 974 |
$schema['articleTypeDefaults'] = []; |
| 975 |
$schema['pageTypeDefaults'] = []; |
| 976 |
foreach ( $post_types as $name => $post_type ) { |
| 977 |
$schema['articleTypeDefaults'][ $name ] = WPSEO_Options::get_default( 'wpseo_titles', "schema-article-type-$name" ); |
| 978 |
$schema['pageTypeDefaults'][ $name ] = WPSEO_Options::get_default( 'wpseo_titles', "schema-page-type-$name" ); |
| 979 |
} |
| 980 |
|
| 981 |
return $schema; |
| 982 |
} |
| 983 |
|
| 984 |
/** |
| 985 |
* Transforms the post types, to represent them. |
| 986 |
* |
| 987 |
* @param WP_Post_Type[] $post_types The WP_Post_Type array to transform. |
| 988 |
* |
| 989 |
* @return array The post types. |
| 990 |
*/ |
| 991 |
protected function transform_post_types( $post_types ) { |
| 992 |
$transformed = []; |
| 993 |
$new_post_types = $this->options->get( 'new_post_types', [] ); |
| 994 |
foreach ( $post_types as $post_type ) { |
| 995 |
$transformed[ $post_type->name ] = [ |
| 996 |
'name' => $post_type->name, |
| 997 |
'route' => $this->route_helper->get_route( $post_type->name, $post_type->rewrite, $post_type->rest_base ), |
| 998 |
'label' => $post_type->label, |
| 999 |
'singularLabel' => $post_type->labels->singular_name, |
| 1000 |
'hasArchive' => $this->post_type_helper->has_archive( $post_type ), |
| 1001 |
'hasSchemaArticleType' => $this->article_helper->is_article_post_type( $post_type->name ), |
| 1002 |
'menuPosition' => $post_type->menu_position, |
| 1003 |
'isNew' => \in_array( $post_type->name, $new_post_types, true ), |
| 1004 |
]; |
| 1005 |
} |
| 1006 |
|
| 1007 |
\uasort( $transformed, [ $this, 'compare_post_types' ] ); |
| 1008 |
|
| 1009 |
return $transformed; |
| 1010 |
} |
| 1011 |
|
| 1012 |
/** |
| 1013 |
* Compares two post types. |
| 1014 |
* |
| 1015 |
* @param array $a The first post type. |
| 1016 |
* @param array $b The second post type. |
| 1017 |
* |
| 1018 |
* @return int The order. |
| 1019 |
*/ |
| 1020 |
protected function compare_post_types( $a, $b ) { |
| 1021 |
if ( $a['menuPosition'] === null && $b['menuPosition'] !== null ) { |
| 1022 |
return 1; |
| 1023 |
} |
| 1024 |
if ( $a['menuPosition'] !== null && $b['menuPosition'] === null ) { |
| 1025 |
return -1; |
| 1026 |
} |
| 1027 |
|
| 1028 |
if ( $a['menuPosition'] === null && $b['menuPosition'] === null ) { |
| 1029 |
// No position specified, order alphabetically by label. |
| 1030 |
return \strnatcmp( $a['label'], $b['label'] ); |
| 1031 |
} |
| 1032 |
|
| 1033 |
return ( ( $a['menuPosition'] < $b['menuPosition'] ) ? -1 : 1 ); |
| 1034 |
} |
| 1035 |
|
| 1036 |
/** |
| 1037 |
* Transforms the taxonomies, to represent them. |
| 1038 |
* |
| 1039 |
* @param WP_Taxonomy[] $taxonomies The WP_Taxonomy array to transform. |
| 1040 |
* @param string[] $post_type_names The post type names. |
| 1041 |
* |
| 1042 |
* @return array The taxonomies. |
| 1043 |
*/ |
| 1044 |
protected function transform_taxonomies( $taxonomies, $post_type_names ) { |
| 1045 |
$transformed = []; |
| 1046 |
$new_taxonomies = $this->options->get( 'new_taxonomies', [] ); |
| 1047 |
foreach ( $taxonomies as $taxonomy ) { |
| 1048 |
$transformed[ $taxonomy->name ] = [ |
| 1049 |
'name' => $taxonomy->name, |
| 1050 |
'route' => $this->route_helper->get_route( $taxonomy->name, $taxonomy->rewrite, $taxonomy->rest_base ), |
| 1051 |
'label' => $taxonomy->label, |
| 1052 |
'showUi' => $taxonomy->show_ui, |
| 1053 |
'singularLabel' => $taxonomy->labels->singular_name, |
| 1054 |
'postTypes' => \array_filter( |
| 1055 |
$taxonomy->object_type, |
| 1056 |
static function ( $object_type ) use ( $post_type_names ) { |
| 1057 |
return \in_array( $object_type, $post_type_names, true ); |
| 1058 |
}, |
| 1059 |
), |
| 1060 |
'isNew' => \in_array( $taxonomy->name, $new_taxonomies, true ), |
| 1061 |
]; |
| 1062 |
} |
| 1063 |
|
| 1064 |
\uasort( |
| 1065 |
$transformed, |
| 1066 |
static function ( $a, $b ) { |
| 1067 |
return \strnatcmp( $a['label'], $b['label'] ); |
| 1068 |
}, |
| 1069 |
); |
| 1070 |
|
| 1071 |
return $transformed; |
| 1072 |
} |
| 1073 |
|
| 1074 |
/** |
| 1075 |
* Retrieves the fallbacks. |
| 1076 |
* |
| 1077 |
* @return array The fallbacks. |
| 1078 |
*/ |
| 1079 |
protected function get_fallbacks() { |
| 1080 |
$site_logo_id = \get_option( 'site_logo' ); |
| 1081 |
if ( ! $site_logo_id ) { |
| 1082 |
$site_logo_id = \get_theme_mod( 'custom_logo' ); |
| 1083 |
} |
| 1084 |
if ( ! $site_logo_id ) { |
| 1085 |
$site_logo_id = '0'; |
| 1086 |
} |
| 1087 |
|
| 1088 |
return [ |
| 1089 |
'siteLogoId' => $site_logo_id, |
| 1090 |
]; |
| 1091 |
} |
| 1092 |
} |
| 1093 |
|