fields (WPSEO_Taxonomy_Meta). * Formats checked against Yoast SEO 28.7. */ class Yoast extends Source { /** * Machine id. * * @return string */ public function id() { return 'yoast'; } /** * Display name. * * @return string */ public function name() { return 'Yoast SEO'; } /** * Post meta keys by Orbitstem field. * * @return array */ protected function post_keys() { return array( 'title' => '_yoast_wpseo_title', 'description' => '_yoast_wpseo_metadesc', 'canonical' => '_yoast_wpseo_canonical', 'noindex' => '_yoast_wpseo_meta-robots-noindex', 'nofollow' => '_yoast_wpseo_meta-robots-nofollow', 'focus_keyword' => '_yoast_wpseo_focuskw', ); } /** * Yoast variable names => Orbitstem variables. * * @return array */ protected function variables() { return array( 'title' => '%title%', 'sitename' => '%sitename%', 'sitedesc' => '%tagline%', 'sep' => '%sep%', 'excerpt' => '%excerpt%', 'excerpt_only' => '%excerpt%', 'page' => '%page%', 'term_title' => '%term%', 'term_description' => '%term_description%', 'category_description' => '%term_description%', 'tag_description' => '%term_description%', 'name' => '%author%', 'searchphrase' => '%search%', 'pt_plural' => '%type%', ); } /** * Yoast variables: %%name%%, where the name may hold any character but %. * * @return string */ protected function token_pattern() { return '/%%([^%\s]+)%%/'; } /** * Post meta "1" = noindex/nofollow ("2" = forced index, "0" = default). * Term option "noindex" = noindex. * * @param string $field Field. * @param mixed $raw Stored value. * @return bool */ protected function robots_flag( $field, $raw ) { if ( 'noindex' === $field && 'noindex' === $raw ) { return true; } return '1' === (string) $raw; } /** * Templates from the wpseo_titles option (Search Appearance settings). * * @return array */ public function templates() { $titles = get_option( 'wpseo_titles', array() ); if ( ! is_array( $titles ) ) { return array(); } $out = array(); $separators = array( 'sc-dash' => 'dash', 'sc-ndash' => 'ndash', 'sc-mdash' => 'mdash', 'sc-pipe' => 'pipe', 'sc-middot' => 'middot', 'sc-bull' => 'bullet', 'sc-raquo' => 'raquo', ); if ( isset( $titles['separator'], $separators[ $titles['separator'] ] ) ) { $out['separator'] = $separators[ $titles['separator'] ]; } $keys = array( 'title-home-wpseo' => 'home_title', 'metadesc-home-wpseo' => 'home_description', 'title-author-wpseo' => 'author_archive.title', 'title-archive-wpseo' => 'date_archive.title', 'title-search-wpseo' => 'search_title', 'title-404-wpseo' => 'not_found_title', ); foreach ( get_post_types( array( 'public' => true ) ) as $type ) { $keys[ 'title-' . $type ] = 'post_types.' . $type . '.title'; $keys[ 'metadesc-' . $type ] = 'post_types.' . $type . '.description'; } foreach ( get_taxonomies( array( 'public' => true ) ) as $taxonomy ) { $keys[ 'title-tax-' . $taxonomy ] = 'taxonomies.' . $taxonomy . '.title'; $keys[ 'metadesc-tax-' . $taxonomy ] = 'taxonomies.' . $taxonomy . '.description'; } foreach ( $keys as $yoast => $path ) { if ( isset( $titles[ $yoast ] ) && is_string( $titles[ $yoast ] ) && '' !== trim( $titles[ $yoast ] ) ) { $value = $this->convert_variables( $titles[ $yoast ] ); if ( '' !== $value ) { $out[ $path ] = $value; } } } return $out; } /** * Term data from the option, flattened to term_id => fields. Entries that * hold only non-importable keys (focus keyword, scores) are skipped by the * base class because they convert to empty values. * * @return array */ private function term_map() { $option = get_option( 'wpseo_taxonomy_meta', array() ); $map = array(); if ( ! is_array( $option ) ) { return $map; } foreach ( $option as $terms ) { if ( ! is_array( $terms ) ) { continue; // E.g. the top-level "wpseo_already_validated" flag. } foreach ( $terms as $term_id => $fields ) { if ( is_array( $fields ) ) { $map[ (int) $term_id ] = $fields; } } } ksort( $map ); return $map; } /** * Term IDs present in the option, after a cursor. * * @param int $after Last processed ID. * @param int $limit Batch size. * @return int[] */ protected function candidate_term_ids( $after, $limit ) { $ids = array_filter( array_keys( $this->term_map() ), function ( $id ) use ( $after ) { return $id > $after; } ); return array_slice( array_values( $ids ), 0, $limit ); } /** * Raw values for one term. * * @param int $term_id Term ID. * @return array */ protected function read_term_raw( $term_id ) { $map = $this->term_map(); $fields = isset( $map[ $term_id ] ) ? $map[ $term_id ] : array(); return array( 'title' => isset( $fields['wpseo_title'] ) ? $fields['wpseo_title'] : '', 'description' => isset( $fields['wpseo_desc'] ) ? $fields['wpseo_desc'] : '', 'canonical' => isset( $fields['wpseo_canonical'] ) ? $fields['wpseo_canonical'] : '', 'noindex' => isset( $fields['wpseo_noindex'] ) ? $fields['wpseo_noindex'] : '', 'nofollow' => '', ); } }