337 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * WPSEO plugin file.
 | |
|  *
 | |
|  * @package WPSEO\Internals\Options
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Option: wpseo_social.
 | |
|  */
 | |
| class WPSEO_Option_Social extends WPSEO_Option {
 | |
| 
 | |
| 	/**
 | |
| 	 * Option name.
 | |
| 	 *
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	public $option_name = 'wpseo_social';
 | |
| 
 | |
| 	/**
 | |
| 	 * Array of defaults for the option.
 | |
| 	 *
 | |
| 	 * Shouldn't be requested directly, use $this->get_defaults();
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $defaults = [
 | |
| 		// Form fields.
 | |
| 		'facebook_site'         => '', // Text field.
 | |
| 		'instagram_url'         => '',
 | |
| 		'linkedin_url'          => '',
 | |
| 		'myspace_url'           => '',
 | |
| 		'og_default_image'      => '', // Text field.
 | |
| 		'og_default_image_id'   => '',
 | |
| 		'og_frontpage_title'    => '', // Text field.
 | |
| 		'og_frontpage_desc'     => '', // Text field.
 | |
| 		'og_frontpage_image'    => '', // Text field.
 | |
| 		'og_frontpage_image_id' => '',
 | |
| 		'opengraph'             => true,
 | |
| 		'pinterest_url'         => '',
 | |
| 		'pinterestverify'       => '',
 | |
| 		'twitter'               => true,
 | |
| 		'twitter_site'          => '', // Text field.
 | |
| 		'twitter_card_type'     => 'summary_large_image',
 | |
| 		'youtube_url'           => '',
 | |
| 		'wikipedia_url'         => '',
 | |
| 		'other_social_urls'     => [],
 | |
| 		'mastodon_url'          => '',
 | |
| 	];
 | |
| 
 | |
| 	/**
 | |
| 	 * Array of sub-options which should not be overloaded with multi-site defaults.
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	public $ms_exclude = [
 | |
| 		/* Privacy. */
 | |
| 		'pinterestverify',
 | |
| 	];
 | |
| 
 | |
| 	/**
 | |
| 	 * Array of allowed twitter card types.
 | |
| 	 *
 | |
| 	 * While we only have the options summary and summary_large_image in the
 | |
| 	 * interface now, we might change that at some point.
 | |
| 	 *
 | |
| 	 * {@internal Uncomment any of these to allow them in validation *and* automatically
 | |
| 	 *            add them as a choice in the options page.}}
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	public static $twitter_card_types = [
 | |
| 		'summary_large_image' => '',
 | |
| 		// 'summary'             => '',
 | |
| 		// 'photo'               => '',
 | |
| 		// 'gallery'             => '',
 | |
| 		// 'app'                 => '',
 | |
| 		// 'player'              => '',
 | |
| 		// 'product'             => '',
 | |
| 	];
 | |
| 
 | |
| 	/**
 | |
| 	 * Add the actions and filters for the option.
 | |
| 	 */
 | |
| 	protected function __construct() {
 | |
| 		parent::__construct();
 | |
| 
 | |
| 		add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the singleton instance of this class.
 | |
| 	 *
 | |
| 	 * @return object
 | |
| 	 */
 | |
| 	public static function get_instance() {
 | |
| 		if ( ! ( self::$instance instanceof self ) ) {
 | |
| 			self::$instance = new self();
 | |
| 		}
 | |
| 
 | |
| 		return self::$instance;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Translate/set strings used in the option defaults.
 | |
| 	 *
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function translate_defaults() {
 | |
| 		self::$twitter_card_types['summary_large_image'] = __( 'Summary with large image', 'wordpress-seo' );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Validate the option.
 | |
| 	 *
 | |
| 	 * @param array $dirty New value for the option.
 | |
| 	 * @param array $clean Clean value for the option, normally the defaults.
 | |
| 	 * @param array $old   Old value of the option.
 | |
| 	 *
 | |
| 	 * @return array Validated clean value for the option to be saved to the database.
 | |
| 	 */
 | |
| 	protected function validate_option( $dirty, $clean, $old ) {
 | |
| 
 | |
| 		foreach ( $clean as $key => $value ) {
 | |
| 			switch ( $key ) {
 | |
| 				/* Text fields. */
 | |
| 				case 'og_frontpage_desc':
 | |
| 				case 'og_frontpage_title':
 | |
| 					if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) {
 | |
| 						$clean[ $key ] = WPSEO_Utils::sanitize_text_field( $dirty[ $key ] );
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case 'og_default_image_id':
 | |
| 				case 'og_frontpage_image_id':
 | |
| 					if ( isset( $dirty[ $key ] ) ) {
 | |
| 						$clean[ $key ] = (int) $dirty[ $key ];
 | |
| 
 | |
| 						if ( $dirty[ $key ] === '' ) {
 | |
| 							$clean[ $key ] = $dirty[ $key ];
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				/* URL text fields - no ftp allowed. */
 | |
| 				case 'facebook_site':
 | |
| 				case 'instagram_url':
 | |
| 				case 'linkedin_url':
 | |
| 				case 'myspace_url':
 | |
| 				case 'pinterest_url':
 | |
| 				case 'og_default_image':
 | |
| 				case 'og_frontpage_image':
 | |
| 				case 'youtube_url':
 | |
| 				case 'wikipedia_url':
 | |
| 				case 'mastodon_url':
 | |
| 					$this->validate_url( $key, $dirty, $old, $clean );
 | |
| 					break;
 | |
| 
 | |
| 				case 'pinterestverify':
 | |
| 					$this->validate_verification_string( $key, $dirty, $old, $clean );
 | |
| 					break;
 | |
| 
 | |
| 				/* Twitter user name. */
 | |
| 				case 'twitter_site':
 | |
| 					if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) {
 | |
| 						$twitter_id = $this->validate_twitter_id( $dirty[ $key ] );
 | |
| 
 | |
| 						if ( $twitter_id ) {
 | |
| 							$clean[ $key ] = $twitter_id;
 | |
| 						}
 | |
| 						else {
 | |
| 							if ( isset( $old[ $key ] ) && $old[ $key ] !== '' ) {
 | |
| 								$twitter_id = sanitize_text_field( ltrim( $old[ $key ], '@' ) );
 | |
| 								if ( preg_match( '`^[A-Za-z0-9_]{1,25}$`', $twitter_id ) ) {
 | |
| 									$clean[ $key ] = $twitter_id;
 | |
| 								}
 | |
| 							}
 | |
| 							if ( function_exists( 'add_settings_error' ) ) {
 | |
| 								add_settings_error(
 | |
| 									$this->group_name, // Slug title of the setting.
 | |
| 									$key, // Suffix-ID for the error message box.
 | |
| 									sprintf(
 | |
| 										/* translators: %s expands to a twitter user name. */
 | |
| 										__( '%s does not seem to be a valid Twitter Username. Please correct.', 'wordpress-seo' ),
 | |
| 										'<strong>' . esc_html( sanitize_text_field( $dirty[ $key ] ) ) . '</strong>'
 | |
| 									), // The error message.
 | |
| 									'error' // Message type.
 | |
| 								);
 | |
| 							}
 | |
| 						}
 | |
| 						unset( $twitter_id );
 | |
| 
 | |
| 						Yoast_Input_Validation::add_dirty_value_to_settings_errors( $key, $dirty[ $key ] );
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case 'twitter_card_type':
 | |
| 					if ( isset( $dirty[ $key ], self::$twitter_card_types[ $dirty[ $key ] ] ) && $dirty[ $key ] !== '' ) {
 | |
| 						$clean[ $key ] = $dirty[ $key ];
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				/* Boolean fields. */
 | |
| 				case 'opengraph':
 | |
| 				case 'twitter':
 | |
| 					$clean[ $key ] = ( isset( $dirty[ $key ] ) ? WPSEO_Utils::validate_bool( $dirty[ $key ] ) : false );
 | |
| 					break;
 | |
| 
 | |
| 				/* Array fields. */
 | |
| 				case 'other_social_urls':
 | |
| 					if ( isset( $dirty[ $key ] ) ) {
 | |
| 						$items = $dirty[ $key ];
 | |
| 						if ( ! is_array( $items ) ) {
 | |
| 							$items = json_decode( $dirty[ $key ], true );
 | |
| 						}
 | |
| 
 | |
| 						if ( is_array( $items ) ) {
 | |
| 							foreach ( $items as $item_key => $item ) {
 | |
| 								$validated_url = $this->validate_social_url( $item );
 | |
| 
 | |
| 								if ( $validated_url === false ) {
 | |
| 									// Restore the previous URL values, if any.
 | |
| 									$old_urls = ( isset( $old[ $key ] ) ) ? $old[ $key ] : [];
 | |
| 									foreach ( $old_urls as $old_item_key => $old_url ) {
 | |
| 										if ( $old_url !== '' ) {
 | |
| 											$url = WPSEO_Utils::sanitize_url( $old_url );
 | |
| 											if ( $url !== '' ) {
 | |
| 												$clean[ $key ][ $old_item_key ] = $url;
 | |
| 											}
 | |
| 										}
 | |
| 									}
 | |
| 									break;
 | |
| 								}
 | |
| 
 | |
| 								// The URL format is valid, let's sanitize it.
 | |
| 								$url = WPSEO_Utils::sanitize_url( $validated_url );
 | |
| 								if ( $url !== '' ) {
 | |
| 									$clean[ $key ][ $item_key ] = $url;
 | |
| 								}
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $clean;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Validates a social URL.
 | |
| 	 *
 | |
| 	 * @param string $url The url to be validated.
 | |
| 	 *
 | |
| 	 * @return string|false The validated URL or false if the URL is not valid.
 | |
| 	 */
 | |
| 	public function validate_social_url( $url ) {
 | |
| 		$validated_url = filter_var( WPSEO_Utils::sanitize_url( trim( $url ) ), FILTER_VALIDATE_URL );
 | |
| 
 | |
| 		return $validated_url;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Validates a twitter id.
 | |
| 	 *
 | |
| 	 * @param string $twitter_id    The twitter id to be validated.
 | |
| 	 * @param bool   $strip_at_sign Whether or not to strip the `@` sign.
 | |
| 	 *
 | |
| 	 * @return string|false The validated twitter id or false if it is not valid.
 | |
| 	 */
 | |
| 	public function validate_twitter_id( $twitter_id, $strip_at_sign = true ) {
 | |
| 		$twitter_id = ( $strip_at_sign ) ? sanitize_text_field( ltrim( $twitter_id, '@' ) ) : sanitize_text_field( $twitter_id );
 | |
| 
 | |
| 		/*
 | |
| 		 * From the Twitter documentation about twitter screen names:
 | |
| 		 * Typically a maximum of 15 characters long, but some historical accounts
 | |
| 		 * may exist with longer names.
 | |
| 		 * A username can only contain alphanumeric characters (letters A-Z, numbers 0-9)
 | |
| 		 * with the exception of underscores.
 | |
| 		 *
 | |
| 		 * @link https://support.twitter.com/articles/101299-why-can-t-i-register-certain-usernames
 | |
| 		 */
 | |
| 		if ( preg_match( '`^[A-Za-z0-9_]{1,25}$`', $twitter_id ) ) {
 | |
| 			return $twitter_id;
 | |
| 		}
 | |
| 
 | |
| 		if ( preg_match( '`^http(?:s)?://(?:www\.)?twitter\.com/(?P<handle>[A-Za-z0-9_]{1,25})/?$`', $twitter_id, $matches ) ) {
 | |
| 			return $matches['handle'];
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Clean a given option value.
 | |
| 	 *
 | |
| 	 * @param array       $option_value          Old (not merged with defaults or filtered) option value to
 | |
| 	 *                                           clean according to the rules for this option.
 | |
| 	 * @param string|null $current_version       Optional. Version from which to upgrade, if not set,
 | |
| 	 *                                           version specific upgrades will be disregarded.
 | |
| 	 * @param array|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.
 | |
| 	 *
 | |
| 	 * @return array Cleaned option.
 | |
| 	 */
 | |
| 	protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) {
 | |
| 
 | |
| 		/* Move options from very old option to this one. */
 | |
| 		$old_option = null;
 | |
| 		if ( isset( $all_old_option_values ) ) {
 | |
| 			// Ok, we have an import.
 | |
| 			if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== [] ) {
 | |
| 				$old_option = $all_old_option_values['wpseo_indexation'];
 | |
| 			}
 | |
| 		}
 | |
| 		else {
 | |
| 			$old_option = get_option( 'wpseo_indexation' );
 | |
| 		}
 | |
| 
 | |
| 		if ( is_array( $old_option ) && $old_option !== [] ) {
 | |
| 			$move = [
 | |
| 				'opengraph',
 | |
| 			];
 | |
| 			foreach ( $move as $key ) {
 | |
| 				if ( isset( $old_option[ $key ] ) && ! isset( $option_value[ $key ] ) ) {
 | |
| 					$option_value[ $key ] = $old_option[ $key ];
 | |
| 				}
 | |
| 			}
 | |
| 			unset( $move, $key );
 | |
| 		}
 | |
| 		unset( $old_option );
 | |
| 
 | |
| 		return $option_value;
 | |
| 	}
 | |
| }
 |