| 1 |
<?php |
| 2 |
/** |
| 3 |
* WPSEO plugin file. |
| 4 |
* |
| 5 |
* @package WPSEO\Internals\Options |
| 6 |
*/ |
| 7 |
|
| 8 |
use Yoast\WP\SEO\Config\Schema_Types; |
| 9 |
|
| 10 |
/** |
| 11 |
* Option: wpseo_titles. |
| 12 |
*/ |
| 13 |
class WPSEO_Option_Titles extends WPSEO_Option { |
| 14 |
|
| 15 |
/** |
| 16 |
* Option name. |
| 17 |
* |
| 18 |
* @var string |
| 19 |
*/ |
| 20 |
public $option_name = 'wpseo_titles'; |
| 21 |
|
| 22 |
/** |
| 23 |
* Array of defaults for the option. |
| 24 |
* |
| 25 |
* Shouldn't be requested directly, use $this->get_defaults(); |
| 26 |
* |
| 27 |
* {@internal Note: Some of the default values are added via the translate_defaults() method.}} |
| 28 |
* |
| 29 |
* @var string[] |
| 30 |
*/ |
| 31 |
protected $defaults = [ |
| 32 |
// Form fields. |
| 33 |
'forcerewritetitle' => false, |
| 34 |
'separator' => 'sc-dash', |
| 35 |
'title-home-wpseo' => '%%sitename%% %%page%% %%sep%% %%sitedesc%%', // Text field. |
| 36 |
'title-author-wpseo' => '', // Text field. |
| 37 |
'title-archive-wpseo' => '%%date%% %%page%% %%sep%% %%sitename%%', // Text field. |
| 38 |
'title-search-wpseo' => '', // Text field. |
| 39 |
'title-404-wpseo' => '', // Text field. |
| 40 |
|
| 41 |
'social-title-author-wpseo' => '%%name%%', // Text field. |
| 42 |
'social-title-archive-wpseo' => '%%date%%', // Text field. |
| 43 |
'social-description-author-wpseo' => '', // Text area. |
| 44 |
'social-description-archive-wpseo' => '', // Text area. |
| 45 |
'social-image-url-author-wpseo' => '', // Hidden input field. |
| 46 |
'social-image-url-archive-wpseo' => '', // Hidden input field. |
| 47 |
'social-image-id-author-wpseo' => 0, // Hidden input field. |
| 48 |
'social-image-id-archive-wpseo' => 0, // Hidden input field. |
| 49 |
|
| 50 |
'metadesc-home-wpseo' => '', // Text area. |
| 51 |
'metadesc-author-wpseo' => '', // Text area. |
| 52 |
'metadesc-archive-wpseo' => '', // Text area. |
| 53 |
'rssbefore' => '', // Text area. |
| 54 |
'rssafter' => '', // Text area. |
| 55 |
|
| 56 |
'noindex-author-wpseo' => false, |
| 57 |
'noindex-author-noposts-wpseo' => true, |
| 58 |
'noindex-archive-wpseo' => true, |
| 59 |
|
| 60 |
'disable-author' => false, |
| 61 |
'disable-date' => false, |
| 62 |
'disable-post_format' => false, |
| 63 |
'disable-attachment' => true, |
| 64 |
|
| 65 |
'breadcrumbs-404crumb' => '', // Text field. |
| 66 |
'breadcrumbs-display-blog-page' => true, |
| 67 |
'breadcrumbs-boldlast' => false, |
| 68 |
'breadcrumbs-archiveprefix' => '', // Text field. |
| 69 |
'breadcrumbs-enable' => true, |
| 70 |
'breadcrumbs-home' => '', // Text field. |
| 71 |
'breadcrumbs-prefix' => '', // Text field. |
| 72 |
'breadcrumbs-searchprefix' => '', // Text field. |
| 73 |
'breadcrumbs-sep' => '»', // Text field. |
| 74 |
|
| 75 |
'website_name' => '', |
| 76 |
'person_name' => '', |
| 77 |
'person_logo' => '', |
| 78 |
'person_logo_id' => 0, |
| 79 |
'alternate_website_name' => '', |
| 80 |
'company_logo' => '', |
| 81 |
'company_logo_id' => 0, |
| 82 |
'company_logo_meta' => false, |
| 83 |
'person_logo_meta' => false, |
| 84 |
'company_name' => '', |
| 85 |
'company_alternate_name' => '', |
| 86 |
'company_or_person' => 'company', |
| 87 |
'company_or_person_user_id' => false, |
| 88 |
|
| 89 |
'stripcategorybase' => false, |
| 90 |
|
| 91 |
'open_graph_frontpage_title' => '%%sitename%%', // Text field. |
| 92 |
'open_graph_frontpage_desc' => '', // Text field. |
| 93 |
'open_graph_frontpage_image' => '', // Text field. |
| 94 |
'open_graph_frontpage_image_id' => 0, |
| 95 |
|
| 96 |
'publishing_principles_id' => 0, |
| 97 |
'ownership_funding_info_id' => 0, |
| 98 |
'actionable_feedback_policy_id' => 0, |
| 99 |
'corrections_policy_id' => 0, |
| 100 |
'ethics_policy_id' => 0, |
| 101 |
'diversity_policy_id' => 0, |
| 102 |
'diversity_staffing_report_id' => 0, |
| 103 |
|
| 104 |
'org-description' => '', |
| 105 |
'org-email' => '', |
| 106 |
'org-phone' => '', |
| 107 |
'org-legal-name' => '', |
| 108 |
'org-founding-date' => '', |
| 109 |
'org-number-employees' => '', |
| 110 |
|
| 111 |
'org-vat-id' => '', |
| 112 |
'org-tax-id' => '', |
| 113 |
'org-iso' => '', |
| 114 |
'org-duns' => '', |
| 115 |
'org-leicode' => '', |
| 116 |
'org-naics' => '', |
| 117 |
|
| 118 |
/* |
| 119 |
* Uses enrich_defaults to add more along the lines of: |
| 120 |
* - 'title-' . $pt->name => ''; // Text field. |
| 121 |
* - 'metadesc-' . $pt->name => ''; // Text field. |
| 122 |
* - 'noindex-' . $pt->name => false; |
| 123 |
* - 'display-metabox-pt-' . $pt->name => false; |
| 124 |
* |
| 125 |
* - 'title-ptarchive-' . $pt->name => ''; // Text field. |
| 126 |
* - 'metadesc-ptarchive-' . $pt->name => ''; // Text field. |
| 127 |
* - 'bctitle-ptarchive-' . $pt->name => ''; // Text field. |
| 128 |
* - 'noindex-ptarchive-' . $pt->name => false; |
| 129 |
* |
| 130 |
* - 'title-tax-' . $tax->name => '''; // Text field. |
| 131 |
* - 'metadesc-tax-' . $tax->name => ''; // Text field. |
| 132 |
* - 'noindex-tax-' . $tax->name => false; |
| 133 |
* - 'display-metabox-tax-' . $tax->name => false; |
| 134 |
* |
| 135 |
* - 'schema-page-type-' . $pt->name => 'WebPage'; |
| 136 |
* - 'schema-article-type-' . $pt->name => 'Article'; |
| 137 |
*/ |
| 138 |
]; |
| 139 |
|
| 140 |
/** |
| 141 |
* Used for "caching" during pageload. |
| 142 |
* |
| 143 |
* @var string[]|null |
| 144 |
*/ |
| 145 |
protected $enriched_defaults = null; |
| 146 |
|
| 147 |
/** |
| 148 |
* Array of variable option name patterns for the option. |
| 149 |
* |
| 150 |
* @var string[] |
| 151 |
*/ |
| 152 |
protected $variable_array_key_patterns = [ |
| 153 |
'title-', |
| 154 |
'metadesc-', |
| 155 |
'noindex-', |
| 156 |
'display-metabox-pt-', |
| 157 |
'bctitle-ptarchive-', |
| 158 |
'post_types-', |
| 159 |
'taxonomy-', |
| 160 |
'schema-page-type-', |
| 161 |
'schema-article-type-', |
| 162 |
'social-title-', |
| 163 |
'social-description-', |
| 164 |
'social-image-url-', |
| 165 |
'social-image-id-', |
| 166 |
'org-', |
| 167 |
]; |
| 168 |
|
| 169 |
/** |
| 170 |
* Array of sub-options which should not be overloaded with multi-site defaults. |
| 171 |
* |
| 172 |
* @var string[] |
| 173 |
*/ |
| 174 |
public $ms_exclude = [ |
| 175 |
'forcerewritetitle', |
| 176 |
]; |
| 177 |
|
| 178 |
/** |
| 179 |
* Add the actions and filters for the option. |
| 180 |
* |
| 181 |
* @todo [JRF => testers] Check if the extra actions below would run into problems if an option |
| 182 |
* is updated early on and if so, change the call to schedule these for a later action on add/update |
| 183 |
* instead of running them straight away. |
| 184 |
*/ |
| 185 |
protected function __construct() { |
| 186 |
parent::__construct(); |
| 187 |
add_action( 'update_option_' . $this->option_name, [ 'WPSEO_Utils', 'clear_cache' ] ); |
| 188 |
add_action( 'init', [ $this, 'end_of_init' ], 999 ); |
| 189 |
|
| 190 |
add_action( 'registered_post_type', [ $this, 'invalidate_enrich_defaults_cache' ] ); |
| 191 |
add_action( 'unregistered_post_type', [ $this, 'invalidate_enrich_defaults_cache' ] ); |
| 192 |
add_action( 'registered_taxonomy', [ $this, 'invalidate_enrich_defaults_cache' ] ); |
| 193 |
add_action( 'unregistered_taxonomy', [ $this, 'invalidate_enrich_defaults_cache' ] ); |
| 194 |
|
| 195 |
add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] ); |
| 196 |
} |
| 197 |
|
| 198 |
/** |
| 199 |
* Make sure we can recognize the right action for the double cleaning. |
| 200 |
* |
| 201 |
* @return void |
| 202 |
*/ |
| 203 |
public function end_of_init() { |
| 204 |
do_action( 'wpseo_double_clean_titles' ); |
| 205 |
} |
| 206 |
|
| 207 |
/** |
| 208 |
* Get the singleton instance of this class. |
| 209 |
* |
| 210 |
* @return self |
| 211 |
*/ |
| 212 |
public static function get_instance() { |
| 213 |
if ( ! ( self::$instance instanceof self ) ) { |
| 214 |
self::$instance = new self(); |
| 215 |
} |
| 216 |
|
| 217 |
return self::$instance; |
| 218 |
} |
| 219 |
|
| 220 |
/** |
| 221 |
* Get the available separator options. |
| 222 |
* |
| 223 |
* @return string[] |
| 224 |
*/ |
| 225 |
public function get_separator_options() { |
| 226 |
$separators = wp_list_pluck( self::get_separator_option_list(), 'option' ); |
| 227 |
|
| 228 |
/** |
| 229 |
* Allow altering the array with separator options. |
| 230 |
* |
| 231 |
* @param array $separator_options Array with the separator options. |
| 232 |
*/ |
| 233 |
$filtered_separators = apply_filters( 'wpseo_separator_options', $separators ); |
| 234 |
|
| 235 |
if ( is_array( $filtered_separators ) && $filtered_separators !== [] ) { |
| 236 |
$separators = array_merge( $separators, $filtered_separators ); |
| 237 |
} |
| 238 |
|
| 239 |
return $separators; |
| 240 |
} |
| 241 |
|
| 242 |
/** |
| 243 |
* Get the available separator options aria-labels. |
| 244 |
* |
| 245 |
* @return string[] Array with the separator options aria-labels. |
| 246 |
*/ |
| 247 |
public function get_separator_options_for_display() { |
| 248 |
$separators = $this->get_separator_options(); |
| 249 |
$separator_list = self::get_separator_option_list(); |
| 250 |
|
| 251 |
$separator_options = []; |
| 252 |
|
| 253 |
foreach ( $separators as $key => $label ) { |
| 254 |
$aria_label = ( $separator_list[ $key ]['label'] ?? '' ); |
| 255 |
|
| 256 |
$separator_options[ $key ] = [ |
| 257 |
'label' => $label, |
| 258 |
'aria_label' => $aria_label, |
| 259 |
]; |
| 260 |
} |
| 261 |
|
| 262 |
return $separator_options; |
| 263 |
} |
| 264 |
|
| 265 |
/** |
| 266 |
* Translate strings used in the option defaults. |
| 267 |
* |
| 268 |
* @return void |
| 269 |
*/ |
| 270 |
public function translate_defaults() { |
| 271 |
/* translators: 1: Author name; 2: Site name. */ |
| 272 |
$this->defaults['title-author-wpseo'] = sprintf( __( '%1$s, Author at %2$s', 'wordpress-seo' ), '%%name%%', '%%sitename%%' ) . ' %%page%% '; |
| 273 |
/* translators: %s expands to the search phrase. */ |
| 274 |
$this->defaults['title-search-wpseo'] = sprintf( __( 'You searched for %s', 'wordpress-seo' ), '%%searchphrase%%' ) . ' %%page%% %%sep%% %%sitename%%'; |
| 275 |
$this->defaults['title-404-wpseo'] = __( 'Page not found', 'wordpress-seo' ) . ' %%sep%% %%sitename%%'; |
| 276 |
/* translators: 1: link to post; 2: link to blog. */ |
| 277 |
$this->defaults['rssafter'] = sprintf( __( 'The post %1$s appeared first on %2$s.', 'wordpress-seo' ), '%%POSTLINK%%', '%%BLOGLINK%%' ); |
| 278 |
|
| 279 |
$this->defaults['breadcrumbs-404crumb'] = __( 'Error 404: Page not found', 'wordpress-seo' ); |
| 280 |
$this->defaults['breadcrumbs-archiveprefix'] = __( 'Archives for', 'wordpress-seo' ); |
| 281 |
$this->defaults['breadcrumbs-home'] = __( 'Home', 'wordpress-seo' ); |
| 282 |
$this->defaults['breadcrumbs-searchprefix'] = __( 'You searched for', 'wordpress-seo' ); |
| 283 |
} |
| 284 |
|
| 285 |
/** |
| 286 |
* Add dynamically created default options based on available post types and taxonomies. |
| 287 |
* |
| 288 |
* @return void |
| 289 |
*/ |
| 290 |
public function enrich_defaults() { |
| 291 |
$enriched_defaults = $this->enriched_defaults; |
| 292 |
if ( $enriched_defaults !== null ) { |
| 293 |
$this->defaults += $enriched_defaults; |
| 294 |
return; |
| 295 |
} |
| 296 |
|
| 297 |
$enriched_defaults = []; |
| 298 |
|
| 299 |
/* |
| 300 |
* Retrieve all the relevant post type and taxonomy arrays. |
| 301 |
* |
| 302 |
* WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. |
| 303 |
* These are the defaults and can be prepared for any public post type. |
| 304 |
*/ |
| 305 |
$post_type_objects = get_post_types( [ 'public' => true ], 'objects' ); |
| 306 |
|
| 307 |
if ( $post_type_objects ) { |
| 308 |
/* translators: %s expands to the name of a post type (plural). */ |
| 309 |
$archive = sprintf( __( '%s Archive', 'wordpress-seo' ), '%%pt_plural%%' ); |
| 310 |
|
| 311 |
foreach ( $post_type_objects as $pt ) { |
| 312 |
$enriched_defaults[ 'title-' . $pt->name ] = '%%title%% %%page%% %%sep%% %%sitename%%'; // Text field. |
| 313 |
$enriched_defaults[ 'metadesc-' . $pt->name ] = ''; // Text area. |
| 314 |
$enriched_defaults[ 'noindex-' . $pt->name ] = false; |
| 315 |
$enriched_defaults[ 'display-metabox-pt-' . $pt->name ] = true; |
| 316 |
$enriched_defaults[ 'post_types-' . $pt->name . '-maintax' ] = 0; // Select box. |
| 317 |
$enriched_defaults[ 'schema-page-type-' . $pt->name ] = 'WebPage'; |
| 318 |
$enriched_defaults[ 'schema-article-type-' . $pt->name ] = ( $pt->name === 'post' ) ? 'Article' : 'None'; |
| 319 |
|
| 320 |
if ( $pt->name !== 'attachment' ) { |
| 321 |
$enriched_defaults[ 'social-title-' . $pt->name ] = '%%title%%'; // Text field. |
| 322 |
$enriched_defaults[ 'social-description-' . $pt->name ] = ''; // Text area. |
| 323 |
$enriched_defaults[ 'social-image-url-' . $pt->name ] = ''; // Hidden input field. |
| 324 |
$enriched_defaults[ 'social-image-id-' . $pt->name ] = 0; // Hidden input field. |
| 325 |
} |
| 326 |
|
| 327 |
// Custom post types that have archives. |
| 328 |
if ( ! $pt->_builtin && WPSEO_Post_Type::has_archive( $pt ) ) { |
| 329 |
$enriched_defaults[ 'title-ptarchive-' . $pt->name ] = $archive . ' %%page%% %%sep%% %%sitename%%'; // Text field. |
| 330 |
$enriched_defaults[ 'metadesc-ptarchive-' . $pt->name ] = ''; // Text area. |
| 331 |
$enriched_defaults[ 'bctitle-ptarchive-' . $pt->name ] = ''; // Text field. |
| 332 |
$enriched_defaults[ 'noindex-ptarchive-' . $pt->name ] = false; |
| 333 |
$enriched_defaults[ 'social-title-ptarchive-' . $pt->name ] = $archive; // Text field. |
| 334 |
$enriched_defaults[ 'social-description-ptarchive-' . $pt->name ] = ''; // Text area. |
| 335 |
$enriched_defaults[ 'social-image-url-ptarchive-' . $pt->name ] = ''; // Hidden input field. |
| 336 |
$enriched_defaults[ 'social-image-id-ptarchive-' . $pt->name ] = 0; // Hidden input field. |
| 337 |
} |
| 338 |
} |
| 339 |
} |
| 340 |
|
| 341 |
$taxonomy_objects = get_taxonomies( [ 'public' => true ], 'object' ); |
| 342 |
|
| 343 |
if ( $taxonomy_objects ) { |
| 344 |
/* translators: %s expands to the variable used for term title. */ |
| 345 |
$archives = sprintf( __( '%s Archives', 'wordpress-seo' ), '%%term_title%%' ); |
| 346 |
|
| 347 |
foreach ( $taxonomy_objects as $tax ) { |
| 348 |
$enriched_defaults[ 'title-tax-' . $tax->name ] = $archives . ' %%page%% %%sep%% %%sitename%%'; // Text field. |
| 349 |
$enriched_defaults[ 'metadesc-tax-' . $tax->name ] = ''; // Text area. |
| 350 |
$enriched_defaults[ 'display-metabox-tax-' . $tax->name ] = true; |
| 351 |
|
| 352 |
$enriched_defaults[ 'noindex-tax-' . $tax->name ] = ( $tax->name === 'post_format' ); |
| 353 |
|
| 354 |
$enriched_defaults[ 'social-title-tax-' . $tax->name ] = $archives; // Text field. |
| 355 |
$enriched_defaults[ 'social-description-tax-' . $tax->name ] = ''; // Text area. |
| 356 |
$enriched_defaults[ 'social-image-url-tax-' . $tax->name ] = ''; // Hidden input field. |
| 357 |
$enriched_defaults[ 'social-image-id-tax-' . $tax->name ] = 0; // Hidden input field. |
| 358 |
|
| 359 |
$enriched_defaults[ 'taxonomy-' . $tax->name . '-ptparent' ] = 0; // Select box;. |
| 360 |
} |
| 361 |
} |
| 362 |
|
| 363 |
$this->enriched_defaults = $enriched_defaults; |
| 364 |
$this->defaults += $enriched_defaults; |
| 365 |
} |
| 366 |
|
| 367 |
/** |
| 368 |
* Invalidates enrich_defaults() cache. |
| 369 |
* |
| 370 |
* Called from actions: |
| 371 |
* - (un)registered_post_type |
| 372 |
* - (un)registered_taxonomy |
| 373 |
* |
| 374 |
* @return void |
| 375 |
*/ |
| 376 |
public function invalidate_enrich_defaults_cache() { |
| 377 |
$this->enriched_defaults = null; |
| 378 |
} |
| 379 |
|
| 380 |
/** |
| 381 |
* Validate the option. |
| 382 |
* |
| 383 |
* @param string[] $dirty New value for the option. |
| 384 |
* @param string[] $clean Clean value for the option, normally the defaults. |
| 385 |
* @param string[] $old Old value of the option. |
| 386 |
* |
| 387 |
* @return string[] Validated clean value for the option to be saved to the database. |
| 388 |
*/ |
| 389 |
protected function validate_option( $dirty, $clean, $old ) { |
| 390 |
$allowed_post_types = $this->get_allowed_post_types(); |
| 391 |
|
| 392 |
foreach ( $clean as $key => $value ) { |
| 393 |
$switch_key = $this->get_switch_key( $key ); |
| 394 |
|
| 395 |
switch ( $switch_key ) { |
| 396 |
// Only ever set programmatically, so no reason for intense validation. |
| 397 |
case 'company_logo_meta': |
| 398 |
case 'person_logo_meta': |
| 399 |
if ( isset( $dirty[ $key ] ) ) { |
| 400 |
$clean[ $key ] = $dirty[ $key ]; |
| 401 |
} |
| 402 |
break; |
| 403 |
|
| 404 |
/* Breadcrumbs text fields. */ |
| 405 |
case 'breadcrumbs-404crumb': |
| 406 |
case 'breadcrumbs-archiveprefix': |
| 407 |
case 'breadcrumbs-home': |
| 408 |
case 'breadcrumbs-prefix': |
| 409 |
case 'breadcrumbs-searchprefix': |
| 410 |
case 'breadcrumbs-sep': |
| 411 |
if ( isset( $dirty[ $key ] ) ) { |
| 412 |
$clean[ $key ] = wp_kses_post( $dirty[ $key ] ); |
| 413 |
} |
| 414 |
break; |
| 415 |
|
| 416 |
/* |
| 417 |
* Text fields. |
| 418 |
*/ |
| 419 |
|
| 420 |
/* |
| 421 |
* Covers: |
| 422 |
* 'title-home-wpseo', 'title-author-wpseo', 'title-archive-wpseo', // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. |
| 423 |
* 'title-search-wpseo', 'title-404-wpseo' |
| 424 |
* 'title-' . $pt->name |
| 425 |
* 'title-ptarchive-' . $pt->name |
| 426 |
* 'title-tax-' . $tax->name |
| 427 |
* 'social-title-' . $pt->name |
| 428 |
* 'social-title-ptarchive-' . $pt->name |
| 429 |
* 'social-title-tax-' . $tax->name |
| 430 |
* 'social-title-author-wpseo', 'social-title-archive-wpseo' |
| 431 |
* 'open_graph_frontpage_title' |
| 432 |
*/ |
| 433 |
case 'org-': |
| 434 |
case 'website_name': |
| 435 |
case 'alternate_website_name': |
| 436 |
case 'title-': |
| 437 |
case 'social-title-': |
| 438 |
case 'open_graph_frontpage_title': |
| 439 |
if ( isset( $dirty[ $key ] ) ) { |
| 440 |
$clean[ $key ] = WPSEO_Utils::sanitize_text_field( $dirty[ $key ] ); |
| 441 |
} |
| 442 |
break; |
| 443 |
|
| 444 |
case 'company_or_person': |
| 445 |
if ( isset( $dirty[ $key ] ) ) { |
| 446 |
if ( in_array( $dirty[ $key ], [ 'company', 'person' ], true ) ) { |
| 447 |
$clean[ $key ] = $dirty[ $key ]; |
| 448 |
} |
| 449 |
else { |
| 450 |
$defaults = $this->get_defaults(); |
| 451 |
$clean[ $key ] = $defaults['company_or_person']; |
| 452 |
} |
| 453 |
} |
| 454 |
break; |
| 455 |
|
| 456 |
/* |
| 457 |
* Covers: |
| 458 |
* 'company_logo', 'person_logo' // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. |
| 459 |
*/ |
| 460 |
case 'company_logo': |
| 461 |
case 'person_logo': |
| 462 |
case 'open_graph_frontpage_image': |
| 463 |
// When a logo changes, we need to ditch the caches we have for it. |
| 464 |
unset( $clean[ $switch_key . '_id' ] ); |
| 465 |
unset( $clean[ $switch_key . '_meta' ] ); |
| 466 |
$this->validate_url( $key, $dirty, $old, $clean ); |
| 467 |
break; |
| 468 |
|
| 469 |
/* |
| 470 |
* Covers: |
| 471 |
* 'social-image-url-' . $pt->name |
| 472 |
* 'social-image-url-ptarchive-' . $pt->name |
| 473 |
* 'social-image-url-tax-' . $tax->name |
| 474 |
* 'social-image-url-author-wpseo', 'social-image-url-archive-wpseo' |
| 475 |
*/ |
| 476 |
case 'social-image-url-': |
| 477 |
$this->validate_url( $key, $dirty, $old, $clean ); |
| 478 |
break; |
| 479 |
|
| 480 |
/* |
| 481 |
* Covers: |
| 482 |
* 'metadesc-home-wpseo', 'metadesc-author-wpseo', 'metadesc-archive-wpseo' |
| 483 |
* 'metadesc-' . $pt->name |
| 484 |
* 'metadesc-ptarchive-' . $pt->name |
| 485 |
* 'metadesc-tax-' . $tax->name |
| 486 |
* and also: |
| 487 |
* 'bctitle-ptarchive-' . $pt->name |
| 488 |
* 'social-description-' . $pt->name |
| 489 |
* 'social-description-ptarchive-' . $pt->name |
| 490 |
* 'social-description-tax-' . $tax->name |
| 491 |
* 'social-description-author-wpseo', 'social-description-archive-wpseo' |
| 492 |
* 'open_graph_frontpage_desc' |
| 493 |
*/ |
| 494 |
case 'metadesc-': |
| 495 |
case 'bctitle-ptarchive-': |
| 496 |
case 'company_name': |
| 497 |
case 'company_alternate_name': |
| 498 |
case 'person_name': |
| 499 |
case 'social-description-': |
| 500 |
case 'open_graph_frontpage_desc': |
| 501 |
if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { |
| 502 |
$clean[ $key ] = WPSEO_Utils::sanitize_text_field( $dirty[ $key ] ); |
| 503 |
} |
| 504 |
break; |
| 505 |
|
| 506 |
/* |
| 507 |
* Covers: 'rssbefore', 'rssafter' // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. |
| 508 |
*/ |
| 509 |
case 'rssbefore': |
| 510 |
case 'rssafter': |
| 511 |
if ( isset( $dirty[ $key ] ) ) { |
| 512 |
$clean[ $key ] = wp_kses_post( $dirty[ $key ] ); |
| 513 |
} |
| 514 |
break; |
| 515 |
|
| 516 |
/* 'post_types-' . $pt->name . '-maintax' fields. */ |
| 517 |
case 'post_types-': |
| 518 |
$post_type = str_replace( [ 'post_types-', '-maintax' ], '', $key ); |
| 519 |
$taxonomies = get_object_taxonomies( $post_type, 'names' ); |
| 520 |
|
| 521 |
if ( isset( $dirty[ $key ] ) ) { |
| 522 |
if ( $taxonomies !== [] && in_array( $dirty[ $key ], $taxonomies, true ) ) { |
| 523 |
$clean[ $key ] = $dirty[ $key ]; |
| 524 |
} |
| 525 |
elseif ( (string) $dirty[ $key ] === '0' || (string) $dirty[ $key ] === '' ) { |
| 526 |
$clean[ $key ] = 0; |
| 527 |
} |
| 528 |
elseif ( sanitize_title_with_dashes( $dirty[ $key ] ) === $dirty[ $key ] ) { |
| 529 |
// Allow taxonomies which may not be registered yet. |
| 530 |
$clean[ $key ] = $dirty[ $key ]; |
| 531 |
} |
| 532 |
else { |
| 533 |
if ( isset( $old[ $key ] ) ) { |
| 534 |
$clean[ $key ] = sanitize_title_with_dashes( $old[ $key ] ); |
| 535 |
} |
| 536 |
|
| 537 |
/* |
| 538 |
* @todo [JRF => whomever] Maybe change the untranslated $pt name in the |
| 539 |
* error message to the nicely translated label ? |
| 540 |
*/ |
| 541 |
add_settings_error( |
| 542 |
$this->group_name, // Slug title of the setting. |
| 543 |
$key, // Suffix-id for the error message box. |
| 544 |
/* translators: %s expands to a post type. */ |
| 545 |
sprintf( __( 'Please select a valid taxonomy for post type "%s"', 'wordpress-seo' ), $post_type ), // The error message. |
| 546 |
'error', // Message type. |
| 547 |
); |
| 548 |
} |
| 549 |
} |
| 550 |
elseif ( isset( $old[ $key ] ) ) { |
| 551 |
$clean[ $key ] = sanitize_title_with_dashes( $old[ $key ] ); |
| 552 |
} |
| 553 |
unset( $taxonomies, $post_type ); |
| 554 |
break; |
| 555 |
|
| 556 |
/* 'taxonomy-' . $tax->name . '-ptparent' fields. */ |
| 557 |
case 'taxonomy-': |
| 558 |
if ( isset( $dirty[ $key ] ) ) { |
| 559 |
if ( $allowed_post_types !== [] && in_array( $dirty[ $key ], $allowed_post_types, true ) ) { |
| 560 |
$clean[ $key ] = $dirty[ $key ]; |
| 561 |
} |
| 562 |
elseif ( (string) $dirty[ $key ] === '0' || (string) $dirty[ $key ] === '' ) { |
| 563 |
$clean[ $key ] = 0; |
| 564 |
} |
| 565 |
elseif ( sanitize_key( $dirty[ $key ] ) === $dirty[ $key ] ) { |
| 566 |
// Allow taxonomies which may not be registered yet. |
| 567 |
$clean[ $key ] = $dirty[ $key ]; |
| 568 |
} |
| 569 |
else { |
| 570 |
if ( isset( $old[ $key ] ) ) { |
| 571 |
$clean[ $key ] = sanitize_key( $old[ $key ] ); |
| 572 |
} |
| 573 |
|
| 574 |
/* |
| 575 |
* @todo [JRF =? whomever] Maybe change the untranslated $tax name in the |
| 576 |
* error message to the nicely translated label ? |
| 577 |
*/ |
| 578 |
$tax = str_replace( [ 'taxonomy-', '-ptparent' ], '', $key ); |
| 579 |
add_settings_error( |
| 580 |
$this->group_name, // Slug title of the setting. |
| 581 |
'_' . $tax, // Suffix-ID for the error message box. |
| 582 |
/* translators: %s expands to a taxonomy slug. */ |
| 583 |
sprintf( __( 'Please select a valid post type for taxonomy "%s"', 'wordpress-seo' ), $tax ), // The error message. |
| 584 |
'error', // Message type. |
| 585 |
); |
| 586 |
unset( $tax ); |
| 587 |
} |
| 588 |
} |
| 589 |
elseif ( isset( $old[ $key ] ) ) { |
| 590 |
$clean[ $key ] = sanitize_key( $old[ $key ] ); |
| 591 |
} |
| 592 |
break; |
| 593 |
|
| 594 |
/* |
| 595 |
* Covers: |
| 596 |
* 'company_or_person_user_id' |
| 597 |
* 'company_logo_id', 'person_logo_id', 'open_graph_frontpage_image_id' |
| 598 |
* 'social-image-id-' . $pt->name |
| 599 |
* 'social-image-id-ptarchive-' . $pt->name |
| 600 |
* 'social-image-id-tax-' . $tax->name |
| 601 |
* 'social-image-id-author-wpseo', 'social-image-id-archive-wpseo' |
| 602 |
*/ |
| 603 |
case 'company_or_person_user_id': |
| 604 |
case 'company_logo_id': |
| 605 |
case 'person_logo_id': |
| 606 |
case 'social-image-id-': |
| 607 |
case 'open_graph_frontpage_image_id': |
| 608 |
case 'publishing_principles_id': |
| 609 |
case 'ownership_funding_info_id': |
| 610 |
case 'actionable_feedback_policy_id': |
| 611 |
case 'corrections_policy_id': |
| 612 |
case 'ethics_policy_id': |
| 613 |
case 'diversity_policy_id': |
| 614 |
case 'diversity_staffing_report_id': |
| 615 |
if ( isset( $dirty[ $key ] ) ) { |
| 616 |
$int = WPSEO_Utils::validate_int( $dirty[ $key ] ); |
| 617 |
if ( $int !== false && $int >= 0 ) { |
| 618 |
$clean[ $key ] = $int; |
| 619 |
} |
| 620 |
} |
| 621 |
elseif ( isset( $old[ $key ] ) ) { |
| 622 |
$int = WPSEO_Utils::validate_int( $old[ $key ] ); |
| 623 |
if ( $int !== false && $int >= 0 ) { |
| 624 |
$clean[ $key ] = $int; |
| 625 |
} |
| 626 |
} |
| 627 |
break; |
| 628 |
/* Separator field - Radio. */ |
| 629 |
case 'separator': |
| 630 |
if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { |
| 631 |
|
| 632 |
// Get separator fields. |
| 633 |
$separator_fields = $this->get_separator_options(); |
| 634 |
|
| 635 |
// Check if the given separator exists. |
| 636 |
if ( isset( $separator_fields[ $dirty[ $key ] ] ) ) { |
| 637 |
$clean[ $key ] = $dirty[ $key ]; |
| 638 |
} |
| 639 |
} |
| 640 |
break; |
| 641 |
|
| 642 |
case 'schema-page-type-': |
| 643 |
if ( isset( $dirty[ $key ] ) && is_string( $dirty[ $key ] ) ) { |
| 644 |
if ( array_key_exists( $dirty[ $key ], Schema_Types::PAGE_TYPES ) ) { |
| 645 |
$clean[ $key ] = $dirty[ $key ]; |
| 646 |
} |
| 647 |
else { |
| 648 |
$defaults = $this->get_defaults(); |
| 649 |
$post_type = str_replace( $switch_key, '', $key ); |
| 650 |
$clean[ $key ] = $defaults[ $switch_key . $post_type ]; |
| 651 |
} |
| 652 |
} |
| 653 |
break; |
| 654 |
case 'schema-article-type-': |
| 655 |
if ( isset( $dirty[ $key ] ) && is_string( $dirty[ $key ] ) ) { |
| 656 |
/** |
| 657 |
* Filter: 'wpseo_schema_article_types' - Allow developers to filter the available article types. |
| 658 |
* |
| 659 |
* Make sure when you filter this to also filter `wpseo_schema_article_types_labels`. |
| 660 |
* |
| 661 |
* @param array $schema_article_types The available schema article types. |
| 662 |
*/ |
| 663 |
if ( array_key_exists( $dirty[ $key ], apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ) ) ) { |
| 664 |
$clean[ $key ] = $dirty[ $key ]; |
| 665 |
} |
| 666 |
else { |
| 667 |
$defaults = $this->get_defaults(); |
| 668 |
$post_type = str_replace( $switch_key, '', $key ); |
| 669 |
$clean[ $key ] = $defaults[ $switch_key . $post_type ]; |
| 670 |
} |
| 671 |
} |
| 672 |
break; |
| 673 |
|
| 674 |
/* |
| 675 |
* Boolean fields. |
| 676 |
*/ |
| 677 |
|
| 678 |
/* |
| 679 |
* Covers: |
| 680 |
* 'noindex-author-wpseo', 'noindex-author-noposts-wpseo', 'noindex-archive-wpseo' |
| 681 |
* 'noindex-' . $pt->name |
| 682 |
* 'noindex-ptarchive-' . $pt->name |
| 683 |
* 'noindex-tax-' . $tax->name |
| 684 |
* 'forcerewritetitle': |
| 685 |
* 'noodp': |
| 686 |
* 'noydir': |
| 687 |
* 'disable-author': |
| 688 |
* 'disable-date': |
| 689 |
* 'disable-post_format'; |
| 690 |
* 'noindex-' |
| 691 |
* 'display-metabox-pt-' |
| 692 |
* 'display-metabox-pt-'. $pt->name |
| 693 |
* 'display-metabox-tax-' |
| 694 |
* 'display-metabox-tax-' . $tax->name |
| 695 |
* 'breadcrumbs-display-blog-page' |
| 696 |
* 'breadcrumbs-boldlast' |
| 697 |
* 'breadcrumbs-enable' |
| 698 |
* 'stripcategorybase' |
| 699 |
*/ |
| 700 |
default: |
| 701 |
$clean[ $key ] = ( isset( $dirty[ $key ] ) ? WPSEO_Utils::validate_bool( $dirty[ $key ] ) : false ); |
| 702 |
break; |
| 703 |
} |
| 704 |
} |
| 705 |
|
| 706 |
return $clean; |
| 707 |
} |
| 708 |
|
| 709 |
/** |
| 710 |
* Retrieve a list of the allowed post types as breadcrumb parent for a taxonomy. |
| 711 |
* Helper method for validation. |
| 712 |
* |
| 713 |
* {@internal Don't make static as new types may still be registered.}} |
| 714 |
* |
| 715 |
* @return string[] |
| 716 |
*/ |
| 717 |
protected function get_allowed_post_types() { |
| 718 |
$allowed_post_types = []; |
| 719 |
|
| 720 |
/* |
| 721 |
* WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. |
| 722 |
*/ |
| 723 |
$post_types = get_post_types( [ 'public' => true ], 'objects' ); |
| 724 |
|
| 725 |
if ( get_option( 'show_on_front' ) === 'page' && get_option( 'page_for_posts' ) > 0 ) { |
| 726 |
$allowed_post_types[] = 'post'; |
| 727 |
} |
| 728 |
|
| 729 |
if ( is_array( $post_types ) && $post_types !== [] ) { |
| 730 |
foreach ( $post_types as $type ) { |
| 731 |
if ( WPSEO_Post_Type::has_archive( $type ) ) { |
| 732 |
$allowed_post_types[] = $type->name; |
| 733 |
} |
| 734 |
} |
| 735 |
} |
| 736 |
|
| 737 |
return $allowed_post_types; |
| 738 |
} |
| 739 |
|
| 740 |
/** |
| 741 |
* Clean a given option value. |
| 742 |
* |
| 743 |
* @param string[] $option_value Old (not merged with defaults or filtered) option value to clean according to the rules for this option. |
| 744 |
* @param string[]|null $current_version Optional. Version from which to upgrade, if not set, version specific upgrades will be disregarded. |
| 745 |
* @param string[]|null $all_old_option_values Optional. Only used when importing old options to have access to the real old values, in contrast to the saved ones. |
| 746 |
* |
| 747 |
* @return string[] Cleaned option. |
| 748 |
*/ |
| 749 |
protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { |
| 750 |
static $original = null; |
| 751 |
|
| 752 |
// Double-run this function to ensure renaming of the taxonomy options will work. |
| 753 |
if ( ! isset( $original ) |
| 754 |
&& has_action( 'wpseo_double_clean_titles', [ $this, 'clean' ] ) === false |
| 755 |
) { |
| 756 |
add_action( 'wpseo_double_clean_titles', [ $this, 'clean' ] ); |
| 757 |
$original = $option_value; |
| 758 |
} |
| 759 |
|
| 760 |
/* |
| 761 |
* Move options from very old option to this one. |
| 762 |
* |
| 763 |
* {@internal Don't rename to the 'current' names straight away as that would prevent |
| 764 |
* the rename/unset combi below from working.}} |
| 765 |
* |
| 766 |
* @todo [JRF] Maybe figure out a smarter way to deal with this. |
| 767 |
*/ |
| 768 |
$old_option = null; |
| 769 |
if ( isset( $all_old_option_values ) ) { |
| 770 |
// Ok, we have an import. |
| 771 |
if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== [] ) { |
| 772 |
$old_option = $all_old_option_values['wpseo_indexation']; |
| 773 |
} |
| 774 |
} |
| 775 |
else { |
| 776 |
$old_option = get_option( 'wpseo_indexation' ); |
| 777 |
} |
| 778 |
if ( is_array( $old_option ) && $old_option !== [] ) { |
| 779 |
$move = [ |
| 780 |
'noindexauthor' => 'noindex-author', |
| 781 |
'disableauthor' => 'disable-author', |
| 782 |
'noindexdate' => 'noindex-archive', |
| 783 |
'noindexcat' => 'noindex-category', |
| 784 |
'noindextag' => 'noindex-post_tag', |
| 785 |
'noindexpostformat' => 'noindex-post_format', |
| 786 |
]; |
| 787 |
foreach ( $move as $old => $new ) { |
| 788 |
if ( isset( $old_option[ $old ] ) && ! isset( $option_value[ $new ] ) ) { |
| 789 |
$option_value[ $new ] = $old_option[ $old ]; |
| 790 |
} |
| 791 |
} |
| 792 |
unset( $move, $old, $new ); |
| 793 |
} |
| 794 |
unset( $old_option ); |
| 795 |
|
| 796 |
// Fix wrongness created by buggy version 1.2.2. |
| 797 |
if ( isset( $option_value['title-home'] ) && $option_value['title-home'] === '%%sitename%% - %%sitedesc%% - 12345' ) { |
| 798 |
$option_value['title-home-wpseo'] = '%%sitename%% - %%sitedesc%%'; |
| 799 |
} |
| 800 |
|
| 801 |
/* |
| 802 |
* Renaming these options to avoid ever overwritting these if a (bloody stupid) user / |
| 803 |
* programmer would use any of the following as a custom post type or custom taxonomy: |
| 804 |
* 'home', 'author', 'archive', 'search', '404', 'subpages'. |
| 805 |
* |
| 806 |
* Similarly, renaming the tax options to avoid a custom post type and a taxonomy |
| 807 |
* with the same name occupying the same option. |
| 808 |
*/ |
| 809 |
$rename = [ |
| 810 |
'title-home' => 'title-home-wpseo', |
| 811 |
'title-author' => 'title-author-wpseo', |
| 812 |
'title-archive' => 'title-archive-wpseo', |
| 813 |
'title-search' => 'title-search-wpseo', |
| 814 |
'title-404' => 'title-404-wpseo', |
| 815 |
'metadesc-home' => 'metadesc-home-wpseo', |
| 816 |
'metadesc-author' => 'metadesc-author-wpseo', |
| 817 |
'metadesc-archive' => 'metadesc-archive-wpseo', |
| 818 |
'noindex-author' => 'noindex-author-wpseo', |
| 819 |
'noindex-archive' => 'noindex-archive-wpseo', |
| 820 |
]; |
| 821 |
foreach ( $rename as $old => $new ) { |
| 822 |
if ( isset( $option_value[ $old ] ) && ! isset( $option_value[ $new ] ) ) { |
| 823 |
$option_value[ $new ] = $option_value[ $old ]; |
| 824 |
unset( $option_value[ $old ] ); |
| 825 |
} |
| 826 |
} |
| 827 |
unset( $rename, $old, $new ); |
| 828 |
|
| 829 |
/* |
| 830 |
* {@internal This clean-up action can only be done effectively once the taxonomies |
| 831 |
* and post_types have been registered, i.e. at the end of the init action.}} |
| 832 |
*/ |
| 833 |
if ( ( isset( $original ) && current_filter() === 'wpseo_double_clean_titles' ) || did_action( 'wpseo_double_clean_titles' ) > 0 ) { |
| 834 |
$rename = [ |
| 835 |
'title-' => 'title-tax-', |
| 836 |
'metadesc-' => 'metadesc-tax-', |
| 837 |
'noindex-' => 'noindex-tax-', |
| 838 |
'tax-hideeditbox-' => 'hideeditbox-tax-', |
| 839 |
]; |
| 840 |
|
| 841 |
$taxonomy_names = get_taxonomies( [ 'public' => true ], 'names' ); |
| 842 |
$post_type_names = get_post_types( [ 'public' => true ], 'names' ); |
| 843 |
$defaults = $this->get_defaults(); |
| 844 |
if ( $taxonomy_names !== [] ) { |
| 845 |
foreach ( $taxonomy_names as $tax ) { |
| 846 |
foreach ( $rename as $old_prefix => $new_prefix ) { |
| 847 |
if ( |
| 848 |
( isset( $original[ $old_prefix . $tax ] ) && ! isset( $original[ $new_prefix . $tax ] ) ) |
| 849 |
&& ( ! isset( $option_value[ $new_prefix . $tax ] ) |
| 850 |
|| ( isset( $option_value[ $new_prefix . $tax ] ) |
| 851 |
&& $option_value[ $new_prefix . $tax ] === $defaults[ $new_prefix . $tax ] ) ) |
| 852 |
) { |
| 853 |
$option_value[ $new_prefix . $tax ] = $original[ $old_prefix . $tax ]; |
| 854 |
|
| 855 |
/* |
| 856 |
* Check if there is a cpt with the same name as the tax, |
| 857 |
* if so, we should make sure that the old setting hasn't been removed. |
| 858 |
*/ |
| 859 |
if ( ! isset( $post_type_names[ $tax ] ) && isset( $option_value[ $old_prefix . $tax ] ) ) { |
| 860 |
unset( $option_value[ $old_prefix . $tax ] ); |
| 861 |
} |
| 862 |
elseif ( isset( $post_type_names[ $tax ] ) && ! isset( $option_value[ $old_prefix . $tax ] ) ) { |
| 863 |
$option_value[ $old_prefix . $tax ] = $original[ $old_prefix . $tax ]; |
| 864 |
} |
| 865 |
|
| 866 |
if ( $old_prefix === 'tax-hideeditbox-' ) { |
| 867 |
unset( $option_value[ $old_prefix . $tax ] ); |
| 868 |
} |
| 869 |
} |
| 870 |
} |
| 871 |
} |
| 872 |
} |
| 873 |
unset( $rename, $taxonomy_names, $post_type_names, $defaults, $tax, $old_prefix, $new_prefix ); |
| 874 |
} |
| 875 |
|
| 876 |
return $option_value; |
| 877 |
} |
| 878 |
|
| 879 |
/** |
| 880 |
* Make sure that any set option values relating to post_types and/or taxonomies are retained, |
| 881 |
* even when that post_type or taxonomy may not yet have been registered. |
| 882 |
* |
| 883 |
* {@internal Overrule the abstract class version of this to make sure one extra renamed |
| 884 |
* variable key does not get removed. IMPORTANT: keep this method in line with |
| 885 |
* the parent on which it is based!}} |
| 886 |
* |
| 887 |
* @param string[] $dirty Original option as retrieved from the database. |
| 888 |
* @param string[] $clean Filtered option where any options which shouldn't be in our option |
| 889 |
* have already been removed and any options which weren't set |
| 890 |
* have been set to their defaults. |
| 891 |
* |
| 892 |
* @return string[] |
| 893 |
*/ |
| 894 |
protected function retain_variable_keys( $dirty, $clean ) { |
| 895 |
if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== [] ) && ( is_array( $dirty ) && $dirty !== [] ) ) { |
| 896 |
|
| 897 |
// Add the extra pattern. |
| 898 |
$patterns = $this->variable_array_key_patterns; |
| 899 |
$patterns[] = 'tax-hideeditbox-'; |
| 900 |
|
| 901 |
/** |
| 902 |
* Allow altering the array with variable array key patterns. |
| 903 |
* |
| 904 |
* @param array $patterns Array with the variable array key patterns. |
| 905 |
*/ |
| 906 |
$patterns = apply_filters( 'wpseo_option_titles_variable_array_key_patterns', $patterns ); |
| 907 |
|
| 908 |
foreach ( $dirty as $key => $value ) { |
| 909 |
|
| 910 |
// Do nothing if already in filtered option array. |
| 911 |
if ( isset( $clean[ $key ] ) ) { |
| 912 |
continue; |
| 913 |
} |
| 914 |
|
| 915 |
foreach ( $patterns as $pattern ) { |
| 916 |
if ( strpos( $key, $pattern ) === 0 ) { |
| 917 |
$clean[ $key ] = $value; |
| 918 |
break; |
| 919 |
} |
| 920 |
} |
| 921 |
} |
| 922 |
} |
| 923 |
|
| 924 |
return $clean; |
| 925 |
} |
| 926 |
|
| 927 |
/** |
| 928 |
* Retrieves a list of separator options. |
| 929 |
* |
| 930 |
* @return string[] An array of the separator options. |
| 931 |
*/ |
| 932 |
protected static function get_separator_option_list() { |
| 933 |
$separators = [ |
| 934 |
'sc-dash' => [ |
| 935 |
'option' => '-', |
| 936 |
'label' => __( 'Dash', 'wordpress-seo' ), |
| 937 |
], |
| 938 |
'sc-ndash' => [ |
| 939 |
'option' => '–', |
| 940 |
'label' => __( 'En dash', 'wordpress-seo' ), |
| 941 |
], |
| 942 |
'sc-mdash' => [ |
| 943 |
'option' => '—', |
| 944 |
'label' => __( 'Em dash', 'wordpress-seo' ), |
| 945 |
], |
| 946 |
'sc-colon' => [ |
| 947 |
'option' => ':', |
| 948 |
'label' => __( 'Colon', 'wordpress-seo' ), |
| 949 |
], |
| 950 |
'sc-middot' => [ |
| 951 |
'option' => '·', |
| 952 |
'label' => __( 'Middle dot', 'wordpress-seo' ), |
| 953 |
], |
| 954 |
'sc-bull' => [ |
| 955 |
'option' => '•', |
| 956 |
'label' => __( 'Bullet', 'wordpress-seo' ), |
| 957 |
], |
| 958 |
'sc-star' => [ |
| 959 |
'option' => '*', |
| 960 |
'label' => __( 'Asterisk', 'wordpress-seo' ), |
| 961 |
], |
| 962 |
'sc-smstar' => [ |
| 963 |
'option' => '⋆', |
| 964 |
'label' => __( 'Low asterisk', 'wordpress-seo' ), |
| 965 |
], |
| 966 |
'sc-pipe' => [ |
| 967 |
'option' => '|', |
| 968 |
'label' => __( 'Vertical bar', 'wordpress-seo' ), |
| 969 |
], |
| 970 |
'sc-tilde' => [ |
| 971 |
'option' => '~', |
| 972 |
'label' => __( 'Small tilde', 'wordpress-seo' ), |
| 973 |
], |
| 974 |
'sc-laquo' => [ |
| 975 |
'option' => '«', |
| 976 |
'label' => __( 'Left angle quotation mark', 'wordpress-seo' ), |
| 977 |
], |
| 978 |
'sc-raquo' => [ |
| 979 |
'option' => '»', |
| 980 |
'label' => __( 'Right angle quotation mark', 'wordpress-seo' ), |
| 981 |
], |
| 982 |
'sc-lt' => [ |
| 983 |
'option' => '>', |
| 984 |
'label' => __( 'Less than sign', 'wordpress-seo' ), |
| 985 |
], |
| 986 |
'sc-gt' => [ |
| 987 |
'option' => '<', |
| 988 |
'label' => __( 'Greater than sign', 'wordpress-seo' ), |
| 989 |
], |
| 990 |
]; |
| 991 |
|
| 992 |
/** |
| 993 |
* Allows altering the separator options array. |
| 994 |
* |
| 995 |
* @param array $separators Array with the separator options. |
| 996 |
*/ |
| 997 |
$separator_list = apply_filters( 'wpseo_separator_option_list', $separators ); |
| 998 |
|
| 999 |
if ( ! is_array( $separator_list ) ) { |
| 1000 |
return $separators; |
| 1001 |
} |
| 1002 |
|
| 1003 |
return $separator_list; |
| 1004 |
} |
| 1005 |
} |
| 1006 |
|