PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,249 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* This class adds columns to the taxonomy table.
*/
class WPSEO_Taxonomy_Columns {
/**
* @var WPSEO_Metabox_Analysis_SEO
*/
private $analysis_seo;
/**
* @var WPSEO_Metabox_Analysis_Readability
*/
private $analysis_readability;
/**
* The current taxonomy.
*
* @var string
*/
private $taxonomy;
/**
* WPSEO_Taxonomy_Columns constructor.
*/
public function __construct() {
$this->taxonomy = $this->get_taxonomy();
if ( ! empty( $this->taxonomy ) ) {
add_filter( 'manage_edit-' . $this->taxonomy . '_columns', array( $this, 'add_columns' ) );
add_filter( 'manage_' . $this->taxonomy . '_custom_column', array( $this, 'parse_column' ), 10, 3 );
}
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
}
/**
* Adds an SEO score column to the terms table, right after the description column.
*
* @param array $columns Current set columns.
*
* @return array
*/
public function add_columns( array $columns ) {
if ( $this->display_metabox( $this->taxonomy ) === false ) {
return $columns;
}
$new_columns = array();
foreach ( $columns as $column_name => $column_value ) {
$new_columns[ $column_name ] = $column_value;
if ( $column_name === 'description' && $this->analysis_seo->is_enabled() ) {
$new_columns['wpseo-score'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'SEO score', 'wordpress-seo' ) . '"><span class="yoast-column-seo-score yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'SEO score', 'wordpress-seo' ) . '</span></span></span>';
}
if ( $column_name === 'description' && $this->analysis_readability->is_enabled() ) {
$new_columns['wpseo-score-readability'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'Readability score', 'wordpress-seo' ) . '"><span class="yoast-column-readability yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'Readability score', 'wordpress-seo' ) . '</span></span></span>';
}
}
return $new_columns;
}
/**
* Parses the column.
*
* @param string $content The current content of the column.
* @param string $column_name The name of the column.
* @param integer $term_id ID of requested taxonomy.
*
* @return string
*/
public function parse_column( $content, $column_name, $term_id ) {
switch ( $column_name ) {
case 'wpseo-score':
return $this->get_score_value( $term_id );
case 'wpseo-score-readability':
return $this->get_score_readability_value( $term_id );
}
return $content;
}
/**
* Retrieves the taxonomy from the $_GET variable.
*
* @return string The current taxonomy.
*/
public function get_current_taxonomy() {
return filter_input( $this->get_taxonomy_input_type(), 'taxonomy' );
}
/**
* Returns the posted/get taxonomy value if it is set.
*
* @return string|null
*/
private function get_taxonomy() {
if ( defined( 'DOING_AJAX' ) && DOING_AJAX === true ) {
return FILTER_INPUT( INPUT_POST, 'taxonomy' );
}
return FILTER_INPUT( INPUT_GET, 'taxonomy' );
}
/**
* Parses the value for the score column.
*
* @param integer $term_id ID of requested term.
*
* @return string
*/
private function get_score_value( $term_id ) {
$term = get_term( $term_id, $this->taxonomy );
// When the term isn't indexable.
if ( ! $this->is_indexable( $term ) ) {
return $this->create_score_icon(
new WPSEO_Rank( WPSEO_Rank::NO_INDEX ),
__( 'Term is set to noindex.', 'wordpress-seo' )
);
}
// When there is a focus key word.
$focus_keyword = $this->get_focus_keyword( $term );
$score = (int) WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $this->taxonomy, 'linkdex' );
$rank = WPSEO_Rank::from_numeric_score( $score );
return $this->create_score_icon( $rank, $rank->get_label() );
}
/**
* Parses the value for the readability score column.
*
* @param int $term_id ID of the requested term.
*
* @return string The HTML for the readability score indicator.
*/
private function get_score_readability_value( $term_id ) {
$score = (int) WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $this->taxonomy, 'content_score' );
$rank = WPSEO_Rank::from_numeric_score( $score );
return $this->create_score_icon( $rank );
}
/**
* Creates an icon by the given values.
*
* @param WPSEO_Rank $rank The ranking object.
* @param string $title Optional. The title to show. Defaults to the rank label.
*
* @return string The HTML for a score icon.
*/
private function create_score_icon( WPSEO_Rank $rank, $title = '' ) {
if ( empty( $title ) ) {
$title = $rank->get_label();
}
return '<div aria-hidden="true" title="' . esc_attr( $title ) . '" class="wpseo-score-icon ' . esc_attr( $rank->get_css_class() ) . '"></div><span class="screen-reader-text wpseo-score-text">' . $title . '</span>';
}
/**
* Check if the taxonomy is indexable.
*
* @param mixed $term The current term.
*
* @return bool Whether or not the term is indexable.
*/
private function is_indexable( $term ) {
// When the no_index value is not empty and not default, check if its value is index.
$no_index = WPSEO_Taxonomy_Meta::get_term_meta( $term->term_id, $this->taxonomy, 'noindex' );
// Check if the default for taxonomy is empty (this will be index).
if ( ! empty( $no_index ) && $no_index !== 'default' ) {
return ( $no_index === 'index' );
}
if ( is_object( $term ) ) {
$no_index_key = 'noindex-tax-' . $term->taxonomy;
// If the option is false, this means we want to index it.
return WPSEO_Options::get( $no_index_key, false ) === false;
}
return true;
}
/**
* Returns the focus keyword if this is set, otherwise it will give the term name.
*
* @param stdClass|WP_Term $term The current term.
*
* @return string
*/
private function get_focus_keyword( $term ) {
$focus_keyword = WPSEO_Taxonomy_Meta::get_term_meta( 'focuskw', $term->term_id, $term->taxonomy );
if ( $focus_keyword !== false ) {
return $focus_keyword;
}
return $term->name;
}
/**
* Checks if a taxonomy is being added via a POST method. If not, it defaults to a GET request.
*
* @return int
*/
private function get_taxonomy_input_type() {
if ( ! empty( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
return INPUT_POST;
}
return INPUT_GET;
}
/**
* Wraps the WPSEO_Metabox check to determine whether the metabox should be displayed either by
* choice of the admin or because the taxonomy is not public.
*
* @since 7.0
*
* @param string $taxonomy Optional. The taxonomy to test, defaults to the current taxonomy.
*
* @return bool Whether or not the meta box (and associated columns etc) should be hidden.
*/
private function display_metabox( $taxonomy = null ) {
$current_taxonomy = sanitize_text_field( $this->get_current_taxonomy() );
if ( ! isset( $taxonomy ) && ! empty( $current_taxonomy ) ) {
$taxonomy = $current_taxonomy;
}
return WPSEO_Utils::is_metabox_active( $taxonomy, 'taxonomy' );
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* This class parses all the values for the general tab in the Yoast SEO settings metabox.
*/
class WPSEO_Taxonomy_Content_Fields extends WPSEO_Taxonomy_Fields {
/**
* Returns array with the fields for the general tab.
*
* @return array
*/
public function get() {
$fields = array(
'title' => $this->get_field_config(
'',
'',
'hidden',
''
),
'desc' => $this->get_field_config(
'',
'',
'hidden',
''
),
'linkdex' => $this->get_field_config(
'',
'',
'hidden',
''
),
'content_score' => $this->get_field_config(
'',
'',
'hidden',
''
),
'focuskw' => $this->get_field_config(
'',
'',
'hidden',
''
),
);
/**
* Filter: 'wpseo_taxonomy_content_fields' - Adds the possibility to register additional content fields.
*
* @api array - The additional fields.
*/
$additional_fields = apply_filters( 'wpseo_taxonomy_content_fields', array() );
return $this->filter_hidden_fields( array_merge( $fields, $additional_fields ) );
}
}

View File

@ -0,0 +1,213 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* Class WPSEO_Taxonomy_Presenter.
*/
class WPSEO_Taxonomy_Fields_Presenter {
/**
* The taxonomy meta data for the current term.
*
* @var array
*/
private $tax_meta;
/**
* @param stdClass $term The current term.
*/
public function __construct( $term ) {
$this->tax_meta = WPSEO_Taxonomy_Meta::get_term_meta( (int) $term->term_id, $term->taxonomy );
}
/**
* Displaying the form fields.
*
* @param array $fields Array with the fields that will be displayed.
*/
public function html( array $fields ) {
$content = '';
foreach ( $fields as $field_name => $field_configuration ) {
$content .= $this->form_row( 'wpseo_' . $field_name, $field_configuration );
}
return $content;
}
/**
* Create a row in the form table.
*
* @param string $field_name Variable the row controls.
* @param array $field_configuration Array with the field configuration.
*/
private function form_row( $field_name, array $field_configuration ) {
$esc_field_name = esc_attr( $field_name );
$options = (array) $field_configuration['options'];
if ( ! empty( $field_configuration['description'] ) ) {
$options['description'] = $field_configuration['description'];
}
$label = $this->get_label( $field_configuration['label'], $esc_field_name );
$field = $this->get_field( $field_configuration['type'], $esc_field_name, $this->get_field_value( $field_name ), $options );
$help_content = isset( $field_configuration['options']['help'] ) ? $field_configuration['options']['help'] : '';
$help_button_text = isset( $field_configuration['options']['help-button'] ) ? $field_configuration['options']['help-button'] : '';
$help = new WPSEO_Admin_Help_Panel( $field_name, $help_button_text, $help_content );
return $this->parse_row( $label, $help, $field );
}
/**
* Generates the html for the given field config.
*
* @param string $field_type The fieldtype, e.g: text, checkbox, etc.
* @param string $field_name The name of the field.
* @param string $field_value The value of the field.
* @param array $options Array with additional options.
*
* @return string
*/
private function get_field( $field_type, $field_name, $field_value, array $options ) {
$class = $this->get_class( $options );
$field = '';
$description = '';
$aria_describedby = '';
if ( ! empty( $options['description'] ) ) {
$aria_describedby = ' aria-describedby="' . $field_name . '-desc"';
$description = '<p id="' . $field_name . '-desc" class="yoast-metabox__description">' . $options['description'] . '</p>';
}
switch ( $field_type ) {
case 'div':
$field .= '<div id="' . $field_name . '"></div>';
break;
case 'text':
$field .= '<input name="' . $field_name . '" id="' . $field_name . '" ' . $class . ' type="text" value="' . esc_attr( $field_value ) . '" size="40"' . $aria_describedby . '/>';
break;
case 'checkbox':
$field .= '<input name="' . $field_name . '" id="' . $field_name . '" type="checkbox" ' . checked( $field_value ) . $aria_describedby . '/>';
break;
case 'textarea':
$rows = 3;
if ( ! empty( $options['rows'] ) ) {
$rows = $options['rows'];
}
$field .= '<textarea class="large-text" rows="' . esc_attr( $rows ) . '" id="' . $field_name . '" name="' . $field_name . '"' . $aria_describedby . '>' . esc_textarea( $field_value ) . '</textarea>';
break;
case 'upload':
$field .= '<input' .
' id="' . $field_name . '"' .
' type="text"' .
' size="36"' .
' name="' . $field_name . '"' .
' value="' . esc_attr( $field_value ) . '"' . $aria_describedby . '' .
' readonly="readonly"' .
' /> ';
$field .= '<input' .
' id="' . esc_attr( $field_name ) . '_button"' .
' class="wpseo_image_upload_button button"' .
' data-target="' . esc_attr( $field_name ) . '"' .
' data-target-id="hidden_' . esc_attr( $field_name ) . '-id"' .
' type="button"' .
' value="' . esc_attr__( 'Upload Image', 'wordpress-seo' ) . '"' .
' /> ';
$field .= '<input' .
' id="' . esc_attr( $field_name ) . '_button"' .
' class="wpseo_image_remove_button button"' .
' type="button"' .
' value="' . esc_attr__( 'Clear Image', 'wordpress-seo' ) . '"' .
' />';
break;
case 'select':
if ( is_array( $options ) && $options !== array() ) {
$field .= '<select name="' . $field_name . '" id="' . $field_name . '"' . $aria_describedby . '>';
$select_options = ( array_key_exists( 'options', $options ) ) ? $options['options'] : $options;
foreach ( $select_options as $option => $option_label ) {
$selected = selected( $option, $field_value, false );
$field .= '<option ' . $selected . ' value="' . esc_attr( $option ) . '">' . esc_html( $option_label ) . '</option>';
}
unset( $option, $option_label, $selected );
$field .= '</select>';
}
break;
case 'hidden':
$field .= '<input name="' . $field_name . '" id="hidden_' . $field_name . '" type="hidden" value="' . esc_attr( $field_value ) . '" />';
break;
}
return $field . $description;
}
/**
* Getting the value for given field_name.
*
* @param string $field_name The fieldname to get the value for.
*
* @return string
*/
private function get_field_value( $field_name ) {
if ( isset( $this->tax_meta[ $field_name ] ) && $this->tax_meta[ $field_name ] !== '' ) {
return $this->tax_meta[ $field_name ];
}
return '';
}
/**
* Getting the class attributes if $options contains a class key.
*
* @param array $options The array with field options.
*
* @return string
*/
private function get_class( array $options ) {
if ( ! empty( $options['class'] ) ) {
return ' class="' . esc_attr( $options['class'] ) . '"';
}
return '';
}
/**
* Getting the label HTML.
*
* @param string $label The label value.
* @param string $field_name The target field.
*
* @return string
*/
private function get_label( $label, $field_name ) {
if ( $label !== '' ) {
return '<label for="' . $field_name . '">' . esc_html( $label ) . '</label>';
}
return '';
}
/**
* Returns the HTML for the row which contains label, help and the field.
*
* @param string $label The html for the label if there was a label set.
* @param WPSEO_Admin_Help_Panel $help The help panel to render in this row.
* @param string $field The html for the field.
*
* @return string
*/
private function parse_row( $label, WPSEO_Admin_Help_Panel $help, $field ) {
if ( $label !== '' || $help !== '' ) {
return $label . $help->get_button_html() . $help->get_panel_html() . $field;
}
return $field;
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* Class WPSEO_Taxonomy_Tab.
*
* Contains the basics for each class extending this one.
*/
abstract class WPSEO_Taxonomy_Fields {
/**
* The current term data.
*
* @var stdClass
*/
protected $term;
/**
* Setting the class properties.
*
* @param stdClass $term The current term.
*/
public function __construct( $term ) {
$this->term = $term;
}
/**
* This method should return the fields.
*
* @return array
*/
abstract public function get();
/**
* Returns array with the field data.
*
* @param string $label The label displayed before the field.
* @param string $description Description which will explain the field.
* @param string $type The field type, for example: input, select.
* @param string|array $options Optional. Array with additional options.
* @param bool $hide Should the field be hidden.
*
* @return array
*/
protected function get_field_config( $label, $description, $type = 'text', $options = '', $hide = false ) {
return array(
'label' => $label,
'description' => $description,
'type' => $type,
'options' => $options,
'hide' => $hide,
);
}
/**
* Filter the hidden fields.
*
* @param array $fields Array with the form fields that has will be filtered.
*
* @return array
*/
protected function filter_hidden_fields( array $fields ) {
foreach ( $fields as $field_name => $field_options ) {
if ( ! empty( $field_options['hide'] ) ) {
unset( $fields[ $field_name ] );
}
}
return $fields;
}
}

View File

@ -0,0 +1,244 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* This class generates the metabox on the edit term page.
*/
class WPSEO_Taxonomy_Metabox {
/**
* @var WP_Term
*/
private $term;
/**
* @var string
*/
private $taxonomy;
/**
* @var WPSEO_Taxonomy_Fields_Presenter
*/
private $taxonomy_tab_content;
/**
* @var WPSEO_Taxonomy_Social_Fields
*/
private $taxonomy_social_fields;
/**
* @var WPSEO_Social_Admin
*/
private $social_admin;
/**
* The constructor.
*
* @param string $taxonomy The taxonomy.
* @param stdClass $term The term.
*/
public function __construct( $taxonomy, $term ) {
$this->term = $term;
$this->taxonomy = $taxonomy;
$this->taxonomy_tab_content = new WPSEO_Taxonomy_Fields_Presenter( $this->term );
}
/**
* Shows the Yoast SEO metabox for the term.
*/
public function display() {
$asset_manager = new WPSEO_Admin_Asset_Manager();
$asset_manager->enqueue_script( 'help-center' );
$content_sections = $this->get_content_sections();
$product_title = 'Yoast SEO';
if ( file_exists( WPSEO_PATH . 'premium/' ) ) {
$product_title .= ' Premium';
}
printf( '<div id="wpseo_meta" class="postbox yoast wpseo-taxonomy-metabox-postbox"><h2><span>%1$s</span></h2>', $product_title );
echo '<div class="inside">';
$helpcenter_tab = new WPSEO_Option_Tab(
'tax-metabox',
__( 'Meta box', 'wordpress-seo' ),
array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/metabox-taxonomy-screencast' ) )
);
$helpcenter = new WPSEO_Help_Center( 'tax-metabox', $helpcenter_tab, WPSEO_Utils::is_yoast_seo_premium() );
$helpcenter->localize_data();
$helpcenter->mount();
echo '<div id="taxonomy_overall"></div>';
if ( ! defined( 'WPSEO_PREMIUM_FILE' ) ) {
echo $this->get_buy_premium_link();
}
echo '<div class="wpseo-metabox-content">';
echo '<div class="wpseo-metabox-sidebar"><ul>';
foreach ( $content_sections as $content_section ) {
$content_section->display_link();
}
echo '</ul></div>';
foreach ( $content_sections as $content_section ) {
$content_section->display_content();
}
echo '</div></div>';
echo '</div>';
}
/**
* Returns the relevant metabox sections for the current view.
*
* @return WPSEO_Metabox_Section[]
*/
private function get_content_sections() {
$content_sections = array();
$content_sections[] = $this->get_content_meta_section();
$content_sections[] = $this->get_social_meta_section();
$content_sections[] = $this->get_settings_meta_section();
return $content_sections;
}
/**
* Returns the metabox section for the content analysis.
*
* @return WPSEO_Metabox_Section
*/
private function get_content_meta_section() {
$taxonomy_content_fields = new WPSEO_Taxonomy_Content_Fields( $this->term );
$content = $this->taxonomy_tab_content->html( $taxonomy_content_fields->get( $this->term ) );
return new WPSEO_Metabox_Section_React(
'content',
'<span class="screen-reader-text">' . __( 'Content optimization', 'wordpress-seo' ) . '</span><span class="yst-traffic-light-container">' . WPSEO_Utils::traffic_light_svg() . '</span>',
$content,
array(
'link_aria_label' => __( 'Content optimization', 'wordpress-seo' ),
'link_class' => 'yoast-tooltip yoast-tooltip-e',
)
);
}
/**
* Returns the metabox section for the settings.
*
* @return WPSEO_Metabox_Section
*/
private function get_settings_meta_section() {
$taxonomy_settings_fields = new WPSEO_Taxonomy_Settings_Fields( $this->term );
$content = $this->taxonomy_tab_content->html( $taxonomy_settings_fields->get() );
$tab = new WPSEO_Metabox_Form_Tab(
'settings',
$content,
__( 'Settings', 'wordpress-seo' ),
array(
'single' => true,
)
);
return new WPSEO_Metabox_Tab_Section(
'settings',
'<span class="screen-reader-text">' . __( 'Settings', 'wordpress-seo' ) . '</span><span class="dashicons dashicons-admin-generic"></span>',
array( $tab ),
array(
'link_aria_label' => __( 'Settings', 'wordpress-seo' ),
'link_class' => 'yoast-tooltip yoast-tooltip-e',
)
);
}
/**
* Returns the metabox section for the social settings.
*
* @return WPSEO_Metabox_Section
*/
private function get_social_meta_section() {
$this->taxonomy_social_fields = new WPSEO_Taxonomy_Social_Fields( $this->term );
$this->social_admin = new WPSEO_Social_Admin();
$tabs = array();
$tabs[] = $this->create_tab( 'facebook', 'opengraph', 'facebook-alt', __( 'Facebook / Open Graph metadata', 'wordpress-seo' ) );
$tabs[] = $this->create_tab( 'twitter', 'twitter', 'twitter', __( 'Twitter metadata', 'wordpress-seo' ) );
return new WPSEO_Metabox_Tab_Section(
'social',
'<span class="screen-reader-text">' . __( 'Social', 'wordpress-seo' ) . '</span><span class="dashicons dashicons-share"></span>',
$tabs,
array(
'link_aria_label' => __( 'Social', 'wordpress-seo' ),
'link_class' => 'yoast-tooltip yoast-tooltip-e',
)
);
}
/**
* Creates a social network tab.
*
* @param string $name The name of the tab.
* @param string $network The network of the tab.
* @param string $icon The icon for the tab.
* @param string $label The label for the tab.
*
* @return WPSEO_Metabox_Form_Tab A WPSEO_Metabox_Form_Tab instance.
*/
private function create_tab( $name, $network, $icon, $label ) {
if ( WPSEO_Options::get( $network ) !== true ) {
return new WPSEO_Metabox_Null_Tab();
}
$meta_fields = $this->taxonomy_social_fields->get_by_network( $network );
$tab_settings = new WPSEO_Metabox_Form_Tab(
$name,
$this->social_admin->get_premium_notice( $network ) . $this->taxonomy_tab_content->html( $meta_fields ),
'<span class="screen-reader-text">' . $label . '</span><span class="dashicons dashicons-' . $icon . '"></span>',
array(
'link_aria_label' => $label,
'link_class' => 'yoast-tooltip yoast-tooltip-se',
'single' => $this->has_single_social_tab(),
)
);
return $tab_settings;
}
/**
* Determine whether we only show one social network or two.
*
* @return bool
*/
private function has_single_social_tab() {
return ( WPSEO_Options::get( 'opengraph' ) === false || WPSEO_Options::get( 'twitter' ) === false );
}
/**
* Returns a link to activate the Buy Premium tab.
*
* @return string
*/
private function get_buy_premium_link() {
return sprintf(
'<div class="wpseo-metabox-buy-premium"><a target="_blank" href="%1$s"><span class="dashicons dashicons-star-filled wpseo-buy-premium"></span>%2$s%3$s</a></div>',
esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/3hh' ) ),
esc_html__( 'Go Premium', 'wordpress-seo' ),
WPSEO_Admin_Utils::get_new_tab_message()
);
}
}

View File

@ -0,0 +1,112 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* This class parses all the values for the general tab in the Yoast SEO settings metabox.
*/
class WPSEO_Taxonomy_Settings_Fields extends WPSEO_Taxonomy_Fields {
/**
* Options array for the no-index options, including translated labels.
*
* @var array
*/
private $no_index_options = array();
/**
* @param stdClass $term The currenct taxonomy.
*/
public function __construct( $term ) {
parent::__construct( $term );
$this->translate_meta_options();
}
/**
* Returns array with the fields for the General tab.
*
* @return array Fields to be used on the General tab.
*/
public function get() {
$labels = $this->get_taxonomy_labels();
$fields = array(
'noindex' => $this->get_field_config(
/* translators: %s = taxonomy name. */
esc_html( sprintf( __( 'Allow search engines to show this %s in search results?', 'wordpress-seo' ), $labels->singular_name ) ),
'',
'select',
$this->get_noindex_options()
),
'bctitle' => $this->get_field_config(
__( 'Breadcrumbs Title', 'wordpress-seo' ),
esc_html__( 'The Breadcrumbs Title is used in the breadcrumbs where this taxonomy appears.', 'wordpress-seo' ),
'text',
'',
( WPSEO_Options::get( 'breadcrumbs-enable' ) !== true )
),
'canonical' => $this->get_field_config(
__( 'Canonical URL', 'wordpress-seo' ),
esc_html__( 'The canonical link is shown on the archive page for this term.', 'wordpress-seo' )
),
);
return $this->filter_hidden_fields( $fields );
}
/**
* Translate options text strings for use in the select fields.
*
* {@internal IMPORTANT: if you want to add a new string (option) somewhere, make sure you add
* that array key to the main options definition array in the class WPSEO_Taxonomy_Meta() as well!!!!}}
*/
private function translate_meta_options() {
$this->no_index_options = WPSEO_Taxonomy_Meta::$no_index_options;
/* translators: %1$s expands to the taxonomy name %2$s expands to the current taxonomy index value */
$this->no_index_options['default'] = __( '%2$s (current default for %1$s)', 'wordpress-seo' );
$this->no_index_options['index'] = __( 'Yes', 'wordpress-seo' );
$this->no_index_options['noindex'] = __( 'No', 'wordpress-seo' );
}
/**
* Getting the data for the noindex fields.
*
* @return array Array containing the no_index options.
*/
private function get_noindex_options() {
$labels = $this->get_taxonomy_labels();
$noindex_options['options'] = $this->no_index_options;
$noindex_options['options']['default'] = sprintf( $noindex_options['options']['default'], $labels->name, $this->get_robot_index() );
return $noindex_options;
}
/**
* Retrieve the taxonomies plural for use in sentences.
*
* @return object Object containing the taxonomy's labels.
*/
private function get_taxonomy_labels() {
$taxonomy = get_taxonomy( $this->term->taxonomy );
return $taxonomy->labels;
}
/**
* Returns the current robot index value for the taxonomy
*
* @return string
*/
private function get_robot_index() {
$robot_index = $this->no_index_options['index'];
$index_option = 'noindex-tax-' . $this->term->taxonomy;
if ( WPSEO_Options::get( $index_option, false ) ) {
$robot_index = $this->no_index_options['noindex'];
}
return $robot_index;
}
}

View File

@ -0,0 +1,161 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* This class parses all the values for the social tab in the Yoast SEO settings metabox.
*/
class WPSEO_Taxonomy_Social_Fields extends WPSEO_Taxonomy_Fields {
/**
* List of social networks.
*
* @var array
*/
protected $networks;
/**
* Setting the class properties.
*
* @param stdClass|WP_Term $term The current taxonomy.
*/
public function __construct( $term ) {
parent::__construct( $term );
$this->networks = $this->get_social_networks();
}
/**
* When this method returns false, the social tab in the meta box will be hidden.
*
* @return bool
*/
public function show_social() {
return ( WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ) );
}
/**
* Gets the social meta fields by social network for the taxonomy.
*
* @param string $network The social network for which to fetch the fields.
*
* @return array
*/
public function get_by_network( $network ) {
$settings = $this->networks[ $network ];
return array(
$settings['network'] . '-title' => $this->get_field_config(
/* translators: %s expands to the social network name */
sprintf( __( '%s Title', 'wordpress-seo' ), $settings['label'] ),
/* translators: %1$s expands to the social network name */
sprintf( esc_html__( 'If you don\'t want to use the title for sharing on %1$s but instead want another title there, write it here.', 'wordpress-seo' ), $settings['label'] ),
'text',
array( 'class' => 'large-text' )
),
$settings['network'] . '-description' => $this->get_field_config(
/* translators: %s expands to the social network name */
sprintf( __( '%s Description', 'wordpress-seo' ), $settings['label'] ),
/* translators: %1$s expands to the social network name */
sprintf( esc_html__( 'If you don\'t want to use the meta description for sharing on %1$s but want another description there, write it here.', 'wordpress-seo' ), $settings['label'] ),
'textarea'
),
$settings['network'] . '-image' => $this->get_field_config(
/* translators: %s expands to the social network name */
sprintf( __( '%s Image', 'wordpress-seo' ), $settings['label'] ),
/* translators: %1$s expands to the social network name */
sprintf( esc_html__( 'If you want to use an image for sharing on %1$s, you can upload / choose an image or add the image URL here.', 'wordpress-seo' ), $settings['label'] ) . '<br />' .
/* translators: %1$s expands to the social network name, %2$s expands to the image size */
sprintf( __( 'The recommended image size for %1$s is %2$s pixels.', 'wordpress-seo' ), $settings['label'], $settings['size'] ),
'upload'
),
$settings['network'] . '-image-id' => $this->get_field_config(
'',
'',
'hidden'
),
);
}
/**
* Returning the fields for the social media tab.
*
* @return array
*/
public function get() {
$fields = array();
foreach ( $this->networks as $option => $settings ) {
$fields_to_push = $this->get_by_network( $option );
$fields = array_merge( $fields, $fields_to_push );
}
return $this->filter_hidden_fields( $fields );
}
/**
* Getting array with the social networks.
*
* @return array
*/
private function get_social_networks() {
// Source: https://developers.facebook.com/docs/sharing/best-practices#images.
$fb_image_size = sprintf(
/* translators: %1$s expands to the image recommended width, %2$s to its height. */
__( '%1$s by %2$s', 'wordpress-seo' ),
'1200',
'630'
);
$twitter_image_size = sprintf(
/* translators: %1$s expands to the image recommended width, %2$s to its height. */
__( '%1$s by %2$s', 'wordpress-seo' ),
'1024',
'512'
);
$social_networks = array(
'opengraph' => $this->social_network( 'opengraph', __( 'Facebook', 'wordpress-seo' ), $fb_image_size ),
'twitter' => $this->social_network( 'twitter', __( 'Twitter', 'wordpress-seo' ), $twitter_image_size ),
);
return $this->filter_social_networks( $social_networks );
}
/**
* Returns array with the config fields for the social network.
*
* @param string $network The name of the social network.
* @param string $label The label for the social network.
* @param string $image_size The image dimensions.
*
* @return array
*/
private function social_network( $network, $label, $image_size ) {
return array(
'network' => $network,
'label' => $label,
'size' => $image_size,
);
}
/**
* Filter the social networks which are disabled in the configuration.
*
* @param array $social_networks Array with the social networks that have to be filtered.
*
* @return array
*/
private function filter_social_networks( array $social_networks ) {
foreach ( $social_networks as $social_network => $settings ) {
if ( WPSEO_Options::get( $social_network, false ) === false ) {
unset( $social_networks[ $social_network ] );
}
}
return $social_networks;
}
}

View File

@ -0,0 +1,394 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* Class that handles the edit boxes on taxonomy edit pages.
*/
class WPSEO_Taxonomy {
/**
* The current active taxonomy.
*
* @var string
*/
private $taxonomy = '';
/**
* @var WPSEO_Metabox_Analysis_SEO
*/
private $analysis_seo;
/**
* @var WPSEO_Metabox_Analysis_Readability
*/
private $analysis_readability;
/**
* Class constructor.
*/
public function __construct() {
$this->taxonomy = $this->get_taxonomy();
add_action( 'edit_term', array( $this, 'update_term' ), 99, 3 );
add_action( 'init', array( $this, 'custom_category_descriptions_allow_html' ) );
add_action( 'admin_init', array( $this, 'admin_init' ) );
if ( self::is_term_overview( $GLOBALS['pagenow'] ) ) {
new WPSEO_Taxonomy_Columns();
}
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
}
/**
* Add hooks late enough for taxonomy object to be available for checks.
*/
public function admin_init() {
$taxonomy = get_taxonomy( $this->taxonomy );
if ( empty( $taxonomy ) || empty( $taxonomy->public ) || ! $this->show_metabox() ) {
return;
}
$this->insert_description_field_editor();
add_action( sanitize_text_field( $this->taxonomy ) . '_edit_form', array( $this, 'term_metabox' ), 90, 1 );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
}
/**
* Show the SEO inputs for term.
*
* @param stdClass|WP_Term $term Term to show the edit boxes for.
*/
public function term_metabox( $term ) {
$tab = new WPSEO_Help_Center_Template_Variables_Tab();
$tab->register_hooks();
$metabox = new WPSEO_Taxonomy_Metabox( $this->taxonomy, $term );
$metabox->display();
}
/**
* Queue assets for taxonomy screens.
*
* @since 1.5.0
*/
public function admin_enqueue_scripts() {
$pagenow = $GLOBALS['pagenow'];
if ( ! ( self::is_term_edit( $pagenow ) || self::is_term_overview( $pagenow ) ) ) {
return;
}
$asset_manager = new WPSEO_Admin_Asset_Manager();
$asset_manager->enqueue_style( 'scoring' );
$tab = new WPSEO_Help_Center_Template_Variables_Tab();
$tab->enqueue_assets();
$tag_id = filter_input( INPUT_GET, 'tag_ID' );
if (
self::is_term_edit( $pagenow ) &&
! empty( $tag_id ) // After we drop support for <4.5 this can be removed.
) {
wp_enqueue_media(); // Enqueue files needed for upload functionality.
$asset_manager->enqueue_style( 'metabox-css' );
$asset_manager->enqueue_style( 'scoring' );
$asset_manager->enqueue_script( 'metabox' );
$asset_manager->enqueue_script( 'term-scraper' );
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'term-scraper', 'wpseoTermScraperL10n', $this->localize_term_scraper_script() );
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$yoast_components_l10n->localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'term-scraper' );
$analysis_worker_location = new WPSEO_Admin_Asset_Analysis_Worker_Location( $asset_manager->flatten_version( WPSEO_VERSION ) );
$used_keywords_assessment_location = new WPSEO_Admin_Asset_Analysis_Worker_Location( $asset_manager->flatten_version( WPSEO_VERSION ), 'used-keywords-assessment' );
$localization_data = array(
'url' => $analysis_worker_location->get_url(
$analysis_worker_location->get_asset(),
WPSEO_Admin_Asset::TYPE_JS
),
'keywords_assessment_url' => $used_keywords_assessment_location->get_url(
$used_keywords_assessment_location->get_asset(),
WPSEO_Admin_Asset::TYPE_JS
),
'log_level' => WPSEO_Utils::get_analysis_worker_log_level(),
);
wp_localize_script(
WPSEO_Admin_Asset_Manager::PREFIX . 'term-scraper',
'wpseoAnalysisWorkerL10n',
$localization_data
);
/**
* Remove the emoji script as it is incompatible with both React and any
* contenteditable fields.
*/
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'replacevar-plugin', 'wpseoReplaceVarsL10n', $this->localize_replace_vars_script() );
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'metabox', 'wpseoSelect2Locale', WPSEO_Language_Utils::get_language( WPSEO_Language_Utils::get_user_locale() ) );
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'metabox', 'wpseoAdminL10n', WPSEO_Utils::get_admin_l10n() );
$asset_manager->enqueue_script( 'admin-media' );
wp_localize_script(
WPSEO_Admin_Asset_Manager::PREFIX . 'admin-media',
'wpseoMediaL10n',
array( 'choose_image' => __( 'Use Image', 'wordpress-seo' ) )
);
}
if ( self::is_term_overview( $pagenow ) ) {
$asset_manager->enqueue_script( 'edit-page-script' );
}
}
/**
* Update the taxonomy meta data on save.
*
* @param int $term_id ID of the term to save data for.
* @param int $tt_id The taxonomy_term_id for the term.
* @param string $taxonomy The taxonomy the term belongs to.
*/
public function update_term( $term_id, $tt_id, $taxonomy ) {
/* Create post array with only our values. */
$new_meta_data = array();
foreach ( WPSEO_Taxonomy_Meta::$defaults_per_term as $key => $default ) {
$posted_value = filter_input( INPUT_POST, $key );
if ( isset( $posted_value ) && $posted_value !== false ) {
$new_meta_data[ $key ] = $posted_value;
}
// If analysis is disabled remove that analysis score value from the DB.
if ( $this->is_meta_value_disabled( $key ) ) {
$new_meta_data[ $key ] = '';
}
}
unset( $key, $default );
// Saving the values.
WPSEO_Taxonomy_Meta::set_values( $term_id, $taxonomy, $new_meta_data );
}
/**
* Determines if the given meta value key is disabled.
*
* @param string $key The key of the meta value.
* @return bool Whether the given meta value key is disabled.
*/
public function is_meta_value_disabled( $key ) {
if ( 'wpseo_linkdex' === $key && ! $this->analysis_seo->is_enabled() ) {
return true;
}
if ( 'wpseo_content_score' === $key && ! $this->analysis_readability->is_enabled() ) {
return true;
}
return false;
}
/**
* Allows HTML in descriptions.
*/
public function custom_category_descriptions_allow_html() {
$filters = array(
'pre_term_description',
'pre_link_description',
'pre_link_notes',
'pre_user_description',
);
foreach ( $filters as $filter ) {
remove_filter( $filter, 'wp_filter_kses' );
}
remove_filter( 'term_description', 'wp_kses_data' );
}
/**
* Output the WordPress editor.
*/
public function custom_category_description_editor() {
wp_editor( '', 'description' );
}
/**
* Pass variables to js for use with the term-scraper.
*
* @return array
*/
public function localize_term_scraper_script() {
$term_id = filter_input( INPUT_GET, 'tag_ID' );
$term = get_term_by( 'id', $term_id, $this->get_taxonomy() );
$taxonomy = get_taxonomy( $term->taxonomy );
$term_formatter = new WPSEO_Metabox_Formatter(
new WPSEO_Term_Metabox_Formatter( $taxonomy, $term )
);
return $term_formatter->get_values();
}
/**
* Pass some variables to js for replacing variables.
*/
public function localize_replace_vars_script() {
return array(
'no_parent_text' => __( '(no parent)', 'wordpress-seo' ),
'replace_vars' => $this->get_replace_vars(),
'recommended_replace_vars' => $this->get_recommended_replace_vars(),
'scope' => $this->determine_scope(),
);
}
/**
* Determines the scope based on the current taxonomy.
* This can be used by the replacevar plugin to determine if a replacement needs to be executed.
*
* @return string String decribing the current scope.
*/
private function determine_scope() {
$taxonomy = $this->get_taxonomy();
if ( $taxonomy === 'category' ) {
return 'category';
}
if ( $taxonomy === 'post_tag' ) {
return 'tag';
}
return 'term';
}
/**
* @param string $page The string to check for the term overview page.
*
* @return bool
*/
public static function is_term_overview( $page ) {
return 'edit-tags.php' === $page;
}
/**
* @param string $page The string to check for the term edit page.
*
* @return bool
*/
public static function is_term_edit( $page ) {
return 'term.php' === $page;
}
/**
* Retrieves a template.
* Check if metabox for current taxonomy should be displayed.
*
* @return bool
*/
private function show_metabox() {
$option_key = 'display-metabox-tax-' . $this->taxonomy;
return WPSEO_Options::get( $option_key );
}
/**
* Getting the taxonomy from the URL.
*
* @return string
*/
private function get_taxonomy() {
return filter_input( INPUT_GET, 'taxonomy', FILTER_DEFAULT, array( 'options' => array( 'default' => '' ) ) );
}
/**
* Prepares the replace vars for localization.
*
* @return array The replacement variables.
*/
private function get_replace_vars() {
$term_id = filter_input( INPUT_GET, 'tag_ID' );
$term = get_term_by( 'id', $term_id, $this->get_taxonomy() );
$cached_replacement_vars = array();
$vars_to_cache = array(
'date',
'id',
'sitename',
'sitedesc',
'sep',
'page',
'term_title',
'term_description',
'category_description',
'tag_description',
'searchphrase',
'currentyear',
);
foreach ( $vars_to_cache as $var ) {
$cached_replacement_vars[ $var ] = wpseo_replace_vars( '%%' . $var . '%%', $term );
}
return $cached_replacement_vars;
}
/**
* Prepares the recommended replace vars for localization.
*
* @return array The recommended replacement variables.
*/
private function get_recommended_replace_vars() {
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
$taxonomy = filter_input( INPUT_GET, 'taxonomy' );
// What is recommended depends on the current context.
$page_type = $recommended_replace_vars->determine_for_term( $taxonomy );
return $recommended_replace_vars->get_recommended_replacevars_for( $page_type );
}
/**
* Adds custom category description editor.
* Needs a hook that runs before the description field. Prior to WP version 4.5 we need to use edit_form as
* term_edit_form_top was introduced in WP 4.5. This can be removed after <4.5 is no longer supported.
*
* @return {void}
*/
private function insert_description_field_editor() {
if ( version_compare( $GLOBALS['wp_version'], '4.5', '<' ) ) {
add_action( "{$this->taxonomy}_edit_form", array( $this, 'custom_category_description_editor' ) );
return;
}
add_action( "{$this->taxonomy}_term_edit_form_top", array( $this, 'custom_category_description_editor' ) );
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Adds shortcode support to category descriptions.
*
* @deprecated 7.9.0
* @codeCoverageIgnore
*
* @param string $desc String to add shortcodes in.
*
* @return string Content with shortcodes filtered out.
*/
public function custom_category_descriptions_add_shortcode_support( $desc ) {
_deprecated_function( __FUNCTION__, 'WPSEO 7.9.0', 'WPSEO_Frontend::custom_category_descriptions_add_shortcode_support' );
$frontend = WPSEO_Frontend::get_instance();
return $frontend->custom_category_descriptions_add_shortcode_support( $desc );
}
}