Commit 2e81eed4 authored by Simonas's avatar Simonas

Merge branch 'release-1.8.0' into dev

parents 5070f4b1 70b86f4f
......@@ -20,9 +20,9 @@
## Production
- build CSS & JS assets - `C:\web\dev.biuro\ npm run build`
- build new image `docker build -t biuro/web:1.7.0 .` (update version number)
- build new image `docker build -t biuro/web:1.8.0 .` (update version number)
- login to biuro docker account `docker login --username=biuro --password=9Ndtjd2vKsLvGuFOeFq1KdJs`
- push image to docker repository - `docker push biuro/web:1.7.0`
- push image to docker repository - `docker push biuro/web:1.8.0`
## Production
- update biuro/web image version in .env file (staging or www)
......
......@@ -182,8 +182,8 @@ services:
wp plugin install polylang --version=2.6.3 --activate-network;
# wp plugin update polylang --version=2.6.3;
wp plugin install wordpress-seo --version=11.8 --activate-network;
# wp plugin update wordpress-seo --version=11.8;
wp plugin install wordpress-seo --version=11.9 --activate-network;
# wp plugin update wordpress-seo --version=11.9;
wp plugin update akismet --version=4.1.2;
wp plugin uninstall hello;
......
{
"name": "biuro",
"version": "1.7.0",
"version": "1.8.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "biuro",
"version": "1.7.0",
"version": "1.8.0",
"description": "Biuro WP theme",
"scripts": {
"dev": "gulp --require @babel/register --gulpfile tasks",
......
......@@ -17,6 +17,7 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
* @param array $results Results array for encoding.
*/
function wpseo_ajax_json_echo_die( $results ) {
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
echo WPSEO_Utils::format_json_encode( $results );
die();
}
......@@ -82,25 +83,6 @@ function wpseo_dismiss_tagline_notice() {
add_action( 'wp_ajax_wpseo_dismiss_tagline_notice', 'wpseo_dismiss_tagline_notice' );
/**
* Used in the editor to replace vars for the snippet preview.
*/
function wpseo_ajax_replace_vars() {
global $post;
check_ajax_referer( 'wpseo-replace-vars' );
$post = get_post( intval( filter_input( INPUT_POST, 'post_id' ) ) );
global $wp_query;
$wp_query->queried_object = $post;
$wp_query->queried_object_id = $post->ID;
$omit = array( 'excerpt', 'excerpt_only', 'title' );
echo wpseo_replace_vars( stripslashes( filter_input( INPUT_POST, 'string' ) ), $post, $omit );
die;
}
add_action( 'wp_ajax_wpseo_replace_vars', 'wpseo_ajax_replace_vars' );
/**
* Save an individual SEO title from the Bulk Editor.
*/
......@@ -293,6 +275,7 @@ function ajax_get_keyword_usage() {
}
wp_die(
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
WPSEO_Utils::format_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) )
);
}
......@@ -323,6 +306,7 @@ function ajax_get_term_keyword_usage() {
$usage = $usage[ $keyword ];
wp_die(
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
WPSEO_Utils::format_json_encode( $usage )
);
}
......@@ -398,3 +382,25 @@ function wpseo_add_fb_admin() {
_deprecated_function( __FUNCTION__, 'WPSEO 7.0', 'This method is deprecated.' );
wpseo_ajax_json_echo_die( '' );
}
/**
* Used in the editor to replace vars for the snippet preview.
*
* @deprecated 11.9
* @codeCoverageIgnore
*/
function wpseo_ajax_replace_vars() {
_deprecated_function( __METHOD__, 'WPSEO 11.9' );
global $post;
check_ajax_referer( 'wpseo-replace-vars' );
$post = get_post( intval( filter_input( INPUT_POST, 'post_id' ) ) );
global $wp_query;
$wp_query->queried_object = $post;
$wp_query->queried_object_id = $post->ID;
$omit = array( 'excerpt', 'excerpt_only', 'title' );
echo wpseo_replace_vars( stripslashes( filter_input( INPUT_POST, 'string' ) ), $post, $omit );
die;
}
......@@ -28,6 +28,7 @@ class WPSEO_Recalculate_Scores_Ajax {
check_ajax_referer( 'wpseo_recalculate', 'nonce' );
wp_die(
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
WPSEO_Utils::format_json_encode(
array(
'posts' => $this->calculate_posts(),
......@@ -49,6 +50,7 @@ class WPSEO_Recalculate_Scores_Ajax {
$response = $fetch_object->get_items_to_recalculate( $paged );
if ( ! empty( $response ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
wp_die( WPSEO_Utils::format_json_encode( $response ) );
}
}
......
......@@ -36,6 +36,7 @@ class WPSEO_Shortcode_Filter {
);
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
wp_die( WPSEO_Utils::format_json_encode( $parsed_shortcodes ) );
}
}
......@@ -679,22 +679,6 @@ class WPSEO_Admin_Init {
// WordPress hooks that have been deprecated since a Yoast SEO version.
$deprecated_filters = array(
'wpseo_metakey' => array(
'version' => '6.3',
'alternative' => null,
),
'wpseo_metakeywords' => array(
'version' => '6.3',
'alternative' => null,
),
'wpseo_stopwords' => array(
'version' => '7.0',
'alternative' => null,
),
'wpseo_redirect_orphan_attachment' => array(
'version' => '7.0',
'alternative' => null,
),
'wpseo_genesis_force_adjacent_rel_home' => array(
'version' => '9.4',
'alternative' => null,
......@@ -710,11 +694,13 @@ class WPSEO_Admin_Init {
// Show notice for each deprecated filter or action that has been registered.
foreach ( $deprecated_notices as $deprecated_filter ) {
$deprecation_info = $deprecated_filters[ $deprecated_filter ];
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- only uses the hardcoded values from above.
_deprecated_hook(
$deprecated_filter,
'WPSEO ' . $deprecation_info['version'],
$deprecation_info['alternative']
);
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped.
}
}
......@@ -734,13 +720,19 @@ class WPSEO_Admin_Init {
global $pagenow;
if ( $pagenow === 'options-permalink.php' ) {
$warning = esc_html__( 'WARNING:', 'wordpress-seo' );
/* translators: %1$s and %2$s expand to <i> items to emphasize the word in the middle. */
$message = esc_html__( 'Changing your permalinks settings can seriously impact your search engine visibility. It should almost %1$s never %2$s be done on a live website.', 'wordpress-seo' );
$link = esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' );
$url = WPSEO_Shortlinker::get( 'https://yoa.st/why-permalinks/' );
echo '<div class="notice notice-warning"><p><strong>' . $warning . '</strong><br>' . sprintf( $message, '<i>', '</i>' ) . '<br><a href="' . $url . '" target="_blank">' . $link . '</a></p></div>';
printf(
'<div class="notice notice-warning"><p><strong>%1$s</strong><br>%2$s<br><a href="%3$s" target="_blank">%4$s</a></p></div>',
esc_html__( 'WARNING:', 'wordpress-seo' ),
sprintf(
/* translators: %1$s and %2$s expand to <em> items to emphasize the word in the middle. */
esc_html__( 'Changing your permalinks settings can seriously impact your search engine visibility. It should almost %1$s never %2$s be done on a live website.', 'wordpress-seo' ),
'<em>',
'</em>'
),
esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/why-permalinks/' ) ),
// The link's content.
esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' )
);
}
}
}
......@@ -70,6 +70,9 @@ class WPSEO_Bulk_Description_List_Table extends WPSEO_Bulk_List_Table {
case 'col_existing_yoast_seo_metadesc':
// @todo Inconsistent return/echo behavior R.
// I traced the escaping of the attributes to WPSEO_Bulk_List_Table::column_attributes. Alexander.
// The output of WPSEO_Bulk_List_Table::parse_meta_data_field is properly escaped.
// phpcs:ignore WordPress.Security.EscapeOutput
echo $this->parse_meta_data_field( $record->ID, $attributes );
break;
}
......
......@@ -409,11 +409,12 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
);
printf(
'<select name="post_type_filter" id="%2$s">%1$s</select>',
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $options is properly escaped above.
$options,
esc_attr( 'post-type-filter-' . $instance_type )
);
submit_button( __( 'Filter', 'wordpress-seo' ), 'button', false, false, array( 'id' => 'post-query-submit' ) );
submit_button( esc_html__( 'Filter', 'wordpress-seo' ), 'button', false, false, array( 'id' => 'post-query-submit' ) );
echo '</div>';
}
}
......@@ -770,7 +771,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
}
if ( ! empty( $class ) ) {
$attributes = 'class="' . implode( ' ', $class ) . '"';
$attributes = 'class="' . esc_attr( implode( ' ', $class ) ) . '"';
}
$attributes .= ' data-colname="' . esc_attr( $column_display_name ) . '"';
......@@ -910,7 +911,11 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$meta_value = $values[ $meta_value ];
}
return sprintf( '<td %2$s id="wpseo-existing-%4$s-%3$s">%1$s</td>', $meta_value, $attributes, $record_id, $this->target_db_field );
$id = "wpseo-existing-$record_id-$this->target_db_field";
// $attributes correctly escaped, verified by Alexander. See WPSEO_Bulk_Description_List_Table::parse_page_specific_column.
// phpcs:ignore WordPress.Security.EscapeOutput
return sprintf( '<td %2$s id="%3$s">%1$s</td>', esc_html( $meta_value ), $attributes, esc_attr( $id ) );
}
/**
......
......@@ -69,7 +69,10 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table {
switch ( $column_name ) {
case 'col_existing_yoast_seo_title':
// @todo Inconsistent echo/return behavior R.
// @todo Inconsistent return/echo behavior R.
// I traced the escaping of the attributes to WPSEO_Bulk_List_Table::column_attributes.
// The output of WPSEO_Bulk_List_Table::parse_meta_data_field is properly escaped.
// phpcs:ignore WordPress.Security.EscapeOutput
echo $this->parse_meta_data_field( $record->ID, $attributes );
break;
......
......@@ -26,13 +26,6 @@ class WPSEO_Export {
*/
private $export = '';
/**
* Holds the export error message.
*
* @var string
*/
private $error = '';
/**
* Holds whether the export was a success.
*
......@@ -71,29 +64,7 @@ class WPSEO_Export {
)
);
echo '</p>';
echo '<textarea id="wpseo-export" rows="20" cols="100">' . $this->export . '</textarea>';
}
/**
* Returns true when the property error has a value.
*
* @return bool
*/
public function has_error() {
return ( $this->error !== '' );
}
/**
* Sets the error hook, to display the error to the user.
*/
public function set_error_hook() {
/* translators: %1$s expands to Yoast SEO */
$message = sprintf( __( 'Error creating %1$s export: ', 'wordpress-seo' ), 'Yoast SEO' ) . $this->error;
printf(
'<div class="notice notice-error"><p>%1$s</p></div>',
$message
);
echo '<textarea id="wpseo-export" rows="20" cols="100">' . esc_textarea( $this->export ) . '</textarea>';
}
/**
......@@ -173,4 +144,32 @@ class WPSEO_Export {
}
$this->write_line( $key . ' = ' . $val );
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Returns true when the property error has a value.
*
* @deprecated 11.9 Obsolete since the export setting refactor in 9.2.
*
* @codeCoverageIgnore
*
* @return bool
*/
public function has_error() {
_deprecated_function( __METHOD__, 'WPSEO 11.9' );
return false;
}
/**
* Sets the error hook, to display the error to the user.
*
* @deprecated 11.9 Obsolete since the export setting refactor in 9.2.
*
* @codeCoverageIgnore
*/
public function set_error_hook() {
_deprecated_function( __METHOD__, 'WPSEO 11.9' );
}
}
......@@ -15,14 +15,14 @@ class WPSEO_Gutenberg_Compatibility {
*
* @var string
*/
const CURRENT_RELEASE = '6.2.0';
const CURRENT_RELEASE = '6.3.0';
/**
* The minimally supported version of Gutenberg by the plugin.
*
* @var string
*/
const MINIMUM_SUPPORTED = '6.2.0';
const MINIMUM_SUPPORTED = '6.3.0';
/**
* Holds the current version.
......
......@@ -98,10 +98,12 @@ class WPSEO_Meta_Columns {
switch ( $column_name ) {
case 'wpseo-score':
// @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in render_score_indicator() method.
echo $this->parse_column_score( $post_id );
return;
case 'wpseo-score-readability':
// @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in render_score_indicator() method.
echo $this->parse_column_score_readability( $post_id );
return;
......@@ -733,7 +735,7 @@ class WPSEO_Meta_Columns {
$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>';
return '<div aria-hidden="true" title="' . esc_attr( $title ) . '" class="' . esc_attr( 'wpseo-score-icon ' . $rank->get_css_class() ) . '"></div><span class="screen-reader-text wpseo-score-text">' . esc_html( $title ) . '</span>';
}
/**
......
......@@ -64,7 +64,7 @@ class WPSEO_Option_Tabs_Formatter {
*/
$option_tab_content = apply_filters( 'wpseo_option_tab-' . $tab_filter_name, null, $option_tabs, $tab );
if ( ! empty( $option_tab_content ) ) {
echo $option_tab_content;
echo wp_kses_post( $option_tab_content );
}
if ( empty( $option_tab_content ) ) {
......
......@@ -74,8 +74,8 @@ class WPSEO_Premium_Upsell_Admin_Block {
'<span aria-hidden="true" class="yoast-button-upsell__caret"></span>';
$upgrade_button = sprintf(
'<a id="wpseo-%1$s-popup-button" class="yoast-button-upsell" href="%2$s" target="_blank">%3$s</a>',
$this->identifier,
'<a id="%1$s" class="yoast-button-upsell" href="%2$s" target="_blank">%3$s</a>',
esc_attr( 'wpseo-' . $this->identifier . '-popup-button' ),
esc_url( $url ),
$button_text
);
......@@ -98,6 +98,7 @@ class WPSEO_Premium_Upsell_Admin_Block {
'</h2>';
echo '<ul class="' . esc_attr( $class . '--motivation' ) . '">' . $arguments_html . '</ul>';
// @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in $upgrade_button and $button_text above.
echo '<p>' . $upgrade_button . '</p>';
echo '</div>';
......
......@@ -132,11 +132,11 @@ class WPSEO_Social_Admin extends WPSEO_Metabox {
$tab_content .= $this->do_meta_box( $meta_field_defs[ $field_name ], $field_name );
}
$features = new WPSEO_Features();
/**
* If premium hide the form to show the social preview instead, we still need the fields to be output because
* the values of the social preview are saved in the hidden field.
*/
$features = new WPSEO_Features();
if ( $features->is_premium() ) {
return $this->hide_form( $tab_content );
}
......@@ -151,7 +151,7 @@ class WPSEO_Social_Admin extends WPSEO_Metabox {
*
* @return string The content.
*/
public function hide_form( $tab_content ) {
private function hide_form( $tab_content ) {
return '<div class="hidden">' . $tab_content . '</div>';
}
......
......@@ -141,12 +141,14 @@ class Yoast_Alerts {
private function output_ajax_response( $type ) {
$html = $this->get_view_html( $type );
// phpcs:disable WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
echo WPSEO_Utils::format_json_encode(
array(
'html' => $html,
'total' => self::get_active_alert_count(),
)
);
// phpcs:enable -- Reason: WPSEO_Utils::format_json_encode is safe.
}
/**
......
......@@ -369,6 +369,7 @@ class Yoast_Notification_Center {
$notification_json[] = $notification->render();
}
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
echo WPSEO_Utils::format_json_encode( $notification_json );
return;
......
......@@ -65,10 +65,12 @@ class WPSEO_Link_Reindex_Dashboard {
echo '<strong>' . esc_html__( 'Text link counter', 'wordpress-seo' ) . '</strong><br/>';
if ( ! $this->has_unprocessed() ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: `message_already_indexed` is considered a safe method.
echo $this->message_already_indexed();
}
if ( $this->has_unprocessed() ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: `message_start_indexing` is considered a safe method.
printf( '<span id="reindexLinks">%s</span>', $this->message_start_indexing() );
}
......@@ -100,7 +102,7 @@ class WPSEO_Link_Reindex_Dashboard {
if ( $this->has_unprocessed() ) {
$progress = sprintf(
/* translators: 1: expands to a <span> containing the number of items recalculated. 2: expands to a <strong> containing the total number of items. */
__( 'Text %1$s of %2$s processed.', 'wordpress-seo' ),
esc_html__( 'Text %1$s of %2$s processed.', 'wordpress-seo' ),
'<span id="wpseo_count_index_links">0</span>',
sprintf( '<strong id="wpseo_count_total">%d</strong>', $this->get_unprocessed_count() )
);
......@@ -116,7 +118,10 @@ class WPSEO_Link_Reindex_Dashboard {
);
?>
<div id="wpseo_index_links_wrapper" class="hidden">
<?php echo implode( '<hr />', $blocks ); ?>
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: All inputs are escaped properly.
echo implode( '<hr />', $blocks );
?>
<button onclick="tb_remove();" type="button"
class="button"><?php esc_html_e( 'Stop counting', 'wordpress-seo' ); ?></button>
</div>
......@@ -199,40 +204,4 @@ class WPSEO_Link_Reindex_Dashboard {
esc_attr__( 'Count links in your texts', 'wordpress-seo' )
);
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Add the indexing interface for links to the dashboard.
*
* @deprecated 7.0
* @codeCoverageIgnore
*
* @return void
*/
public function add_link_index_interface() {
_deprecated_function( __METHOD__, 'WPSEO 7.0' );
$html = '';
$html .= '<h2>' . esc_html__( 'Text link counter', 'wordpress-seo' ) . '</h2>';
$html .= '<p>' . sprintf(
/* translators: 1: link to yoast.com post about internal linking suggestion. 4: is Yoast.com 3: is anchor closing. */
__( 'The links in all your public texts need to be counted. This will provide insights of which texts need more links to them. If you want to know more about the why and how of internal linking, check out %1$sthe article about internal linking on %2$s%3$s.', 'wordpress-seo' ),
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/15n' ) . '" target="_blank">',
'Yoast.com',
'</a>'
) . '</p>';
if ( ! $this->has_unprocessed() ) {
$html .= '<p>' . $this->message_already_indexed() . '</p>';
}
if ( $this->has_unprocessed() ) {
$html .= '<p id="reindexLinks">' . $this->message_start_indexing() . '</p>';
}
$html .= '<br />';
echo $html;
}
}
......@@ -40,9 +40,13 @@ class WPSEO_Metabox_Collapsibles_Sections extends WPSEO_Abstract_Metabox_Tab_Wit
printf( '<div id="%1$s" class="wpseo-meta-section">', esc_attr( 'wpseo-meta-section-' . $this->name ) );
echo '<div class="wpseo_content_wrapper">';
add_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_forms' ) );
add_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_a11y' ) );
foreach ( $this->collapsibles as $collapsible ) {
echo $collapsible->content();
echo wp_kses_post( $collapsible->content() );
}
remove_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_forms' ) );
remove_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_a11y' ) );
echo '</div></div>';
}
......
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin\Metabox
*/
/**
* Generates and displays an additional metabox section.
*/
class WPSEO_Metabox_Section_Additional implements WPSEO_Metabox_Section {
/**
* Name of the section, used as an identifier in the HTML.
*
* @var string
*/
public $name;
/**
* Content of the tab's section.
*
* @var string
*/
public $content;
/**
* HTML to use in the tab header.
*
* @var string
*/
private $link_content;
/**
* Class to add to the link.
*
* @var string
*/
private $link_class;
/**
* Aria label to use for the link.
*
* @var string
*/
private $link_aria_label;
/**
* Constructor.
*
* @param string $name The name of the section, used as an identifier in the html.
* Can only contain URL safe characters.
* @param string $link_content The text content of the section link.
* @param string $content Optional. Content to use above the React root element.
* @param array $options Optional link attributes.
*/
public function __construct( $name, $link_content, $content = '', array $options = array() ) {
$this->name = $name;
$this->content = $content;
$default_options = array(
'link_class' => '',
'link_aria_label' => '',
);
$options = wp_parse_args( $options, $default_options );
$this->link_content = $link_content;
$this->link_class = $options['link_class'];
$this->link_aria_label = $options['link_aria_label'];
}
/**
* Outputs the section link.
*
* @return void
*/
public function display_link() {
printf(
'<li role="presentation"><a role="tab" href="#wpseo-meta-section-%1$s" id="wpseo-meta-tab-%1$s" aria-controls="wpseo-meta-section-%1$s" class="wpseo-meta-section-link %2$s"%3$s>%4$s</a></li>',
esc_attr( $this->name ),
esc_attr( $this->link_class ),
( '' !== $this->link_aria_label ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '',
$this->link_content
);
}
/**
* Outputs the section content.
*
* @return void
*/
public function display_content() {
$html = sprintf(
'<div role="tabpanel" id="wpseo-meta-section-%1$s" aria-labelledby="wpseo-meta-tab-%1$s" tabindex="0" class="wpseo-meta-section wpseo-form">',
esc_attr( $this->name )
);
$html .= $this->content;
$html .= '</div>';
echo $html;
}
}
......@@ -90,7 +90,7 @@ class WPSEO_Metabox_Section_React implements WPSEO_Metabox_Section {
esc_attr( $this->name ),
esc_attr( $this->link_class ),
( '' !== $this->link_aria_label ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '',
$this->link_content
wp_kses_post( $this->link_content )
);
}
......@@ -100,15 +100,19 @@ class WPSEO_Metabox_Section_React implements WPSEO_Metabox_Section {
* @return void
*/
public function display_content() {
$html = sprintf(
add_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_forms' ) );
add_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_a11y' ) );
printf(
'<div role="tabpanel" id="wpseo-meta-section-%1$s" aria-labelledby="wpseo-meta-tab-%1$s" tabindex="0" class="wpseo-meta-section">',
esc_attr( $this->name )
);
$html .= $this->content;
$html .= '<div id="wpseo-metabox-root" class="wpseo-metabox-root"></div>';
$html .= $this->html_after;
$html .= '</div>';
echo wp_kses_post( $this->content );
echo '<div id="wpseo-metabox-root" class="wpseo-metabox-root"></div>';
echo wp_kses_post( $this->html_after );
echo '</div>';
echo $html;
remove_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_forms' ) );
remove_filter( 'wp_kses_allowed_html', array( 'WPSEO_Utils', 'extend_kses_post_with_a11y' ) );
}
}
......@@ -315,9 +315,7 @@ class WPSEO_Metabox extends WPSEO_Meta {
$content_sections[] = $this->social_admin->get_meta_section();
}
if ( has_action( 'wpseo_tab_header' ) || has_action( 'wpseo_tab_content' ) ) {
$content_sections[] = $this->get_addons_meta_section();
}
$content_sections = array_merge( $content_sections, $this->get_additional_meta_sections() );
return $content_sections;
}
......@@ -381,17 +379,54 @@ class WPSEO_Metabox extends WPSEO_Meta {
}
/**
* Returns a metabox section dedicated to hosting metabox tabs that have been added by other plugins through the
* `wpseo_tab_header` and `wpseo_tab_content` actions.
* Returns metabox sections that have been added by other plugins.
*
* @return WPSEO_Metabox_Section
* @return WPSEO_Metabox_Section_Additional[]
*/
private function get_addons_meta_section() {
return new WPSEO_Metabox_Addon_Tab_Section(
'addons',
'<span class="dashicons dashicons-admin-plugins"></span>' . __( 'Add-ons', 'wordpress-seo' )
protected function get_additional_meta_sections() {
$sections = array();
/**
* Private filter: 'yoast_free_additional_metabox_sections'.
*
* Meant for internal use only. Allows adding additional tabs to the Yoast SEO metabox.
*
* @since 11.9
*
* @param array[] $sections {
* An array of arrays with tab specifications.
*
* @type array $section {
* A tab specification.
*
* @type string $name The name of the tab. Used in the HTML IDs, href and aria properties.
* @type string $link_content The content of the tab link.
* @type string $content The content of the tab.
* @type array $options {
* Optional. Extra options.
*
* @type string $link_class Optional. The class for the tab link.
* @type string $link_aria_label Optional. The aria label of the tab link.
* }
* }
* }
*/
$requested_sections = apply_filters( 'yoast_free_additional_metabox_sections', array() );
foreach ( $requested_sections as $section ) {
if ( is_array( $section ) && array_key_exists( 'name', $section ) && array_key_exists( 'link_content', $section ) && array_key_exists( 'content', $section ) ) {
$options = array_key_exists( 'options', $section ) ? $section['options'] : array();
$sections[] = new WPSEO_Metabox_Section_Additional(
$section['name'],
$section['link_content'],
$section['content'],
$options
);
}
}
return $sections;
}
/**
* Retrieves the contents for the metabox tab.
......@@ -738,7 +773,6 @@ class WPSEO_Metabox extends WPSEO_Meta {
$asset_manager->enqueue_script( 'metabox' );
$asset_manager->enqueue_script( 'admin-media' );
$asset_manager->enqueue_script( 'post-scraper' );
$asset_manager->enqueue_script( 'replacevar-plugin' );
$asset_manager->enqueue_script( 'shortcode-plugin' );
......
......@@ -146,7 +146,7 @@ class WPSEO_Configuration_Notifier implements WPSEO_Listener {
private function notification( $title, $content, $show_dismissal = false ) {
$notification = '<div class="yoast-container yoast-container__configuration-wizard">';
$notification .= sprintf(
'<img src="%1$s" height="%2$s" width="%3$d" />',
'<img src="%1$s" height="%2$s" width="%3$d" alt="" />',
esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/new-to-configuration-notice.svg' ),
60,
60
......
......@@ -202,13 +202,34 @@ class WPSEO_Taxonomy_Metabox {
}
$meta_fields = $this->taxonomy_social_fields->get_by_network( $network );
$content = $this->taxonomy_tab_content->html( $meta_fields );
/**
* If premium hide the form to show the social preview instead, we still need the fields to be output because
* the values of the social preview are saved in the hidden field.
*/
$features = new WPSEO_Features();
if ( $features->is_premium() ) {
$content = $this->hide_form( $content );
}
$tab_settings = new WPSEO_Metabox_Collapsible(
$name,
$this->social_admin->get_premium_notice( $network ) . $this->taxonomy_tab_content->html( $meta_fields ),
$this->social_admin->get_premium_notice( $network ) . $content,
$label
);
return $tab_settings;
}
/**
* Hides the given output when rendered to HTML.
*
* @param string $tab_content The social tab content.
*
* @return string The content.
*/
private function hide_form( $tab_content ) {
return '<div class="hidden">' . $tab_content . '</div>';
}
}
......@@ -158,7 +158,7 @@ $new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(O
class="yoast-link--license">
<?php
/* translators: %s expands to the extension title */
printf( esc_html( 'Manage your %s subscription on MyYoast', 'wordpress-seo' ), $premium_extension->get_title() );
printf( esc_html__( 'Manage your %s subscription on MyYoast', 'wordpress-seo' ), $premium_extension->get_title() );
echo $new_tab_message;
?>
</a>
......@@ -168,7 +168,7 @@ $new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(O
class="yoast-link--license">
<?php
/* translators: %s expands to the extension title */
printf( esc_html( 'Activate %s for your site on MyYoast', 'wordpress-seo' ), $premium_extension->get_title() );
printf( esc_html__( 'Activate %s for your site on MyYoast', 'wordpress-seo' ), $premium_extension->get_title() );
echo $new_tab_message;
?>
</a>
......@@ -242,7 +242,7 @@ $new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(O
class="yoast-link--license">
<?php
/* translators: %s expands to the extension title */
printf( esc_html( 'Manage your %s subscription on MyYoast', 'wordpress-seo' ), $extension->get_title() );
printf( esc_html__( 'Manage your %s subscription on MyYoast', 'wordpress-seo' ), $extension->get_title() );
echo $new_tab_message;
?>
</a>
......@@ -252,7 +252,7 @@ $new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(O
class="yoast-link--license">
<?php
/* translators: %s expands to the extension title */
printf( esc_html( 'Activate %s for your site on MyYoast', 'wordpress-seo' ), $extension->get_title() );
printf( esc_html__( 'Activate %s for your site on MyYoast', 'wordpress-seo' ), $extension->get_title() );
echo $new_tab_message;
?>
</a>
......
......@@ -8,32 +8,62 @@
/**
* Generates and displays a section containing metabox tabs that have been added by other plugins through the
* `wpseo_tab_header` and `wpseo_tab_content` actions.
*
* @deprecated 11.9
*/
class WPSEO_Metabox_Addon_Tab_Section extends WPSEO_Metabox_Tab_Section {
/**
* WPSEO_Metabox_Addon_Tab_Section constructor.
*
* @deprecated 11.9
*
* @param string $name The name of the section, used as an identifier in the html.
* Can only contain URL safe characters.
* @param string $link_content The text content of the section link.
* @param array $tabs The metabox tabs (`WPSEO_Metabox_Tabs[]`) to be included in the section.
* @param array $options Optional link attributes.
*/
public function __construct( $name, $link_content, array $tabs = array(), array $options = array() ) {
_deprecated_constructor( 'WPSEO_Metabox_Addon_Tab_Section', '11.9' );
parent::__construct( $name, $link_content, $tabs, $options );
}
/**
* Applies the actions for adding a tab to the metabox.
*
* @deprecated 11.9
*/
public function display_content() {
_deprecated_function( __METHOD__, '11.9' );
?>
<div role="tabpanel" id="wpseo-meta-section-addons" aria-labelledby="wpseo-meta-tab-addons" tabindex="0" class="wpseo-meta-section">
<div class="wpseo-metabox-tabs-div">
<ul class="wpseo-metabox-tabs">
<?php do_action( 'wpseo_tab_header' ); ?>
<?php
// @deprecated 11.9 This functionality has been replaced by the filter: `yoast_free_additional_metabox_sections`.
do_action_deprecated( 'wpseo_tab_header', array(), '11.9' );
?>
</ul>
<?php do_action( 'wpseo_tab_content' ); ?>
<?php
// @deprecated 11.9 This functionality has been replaced by the filter: `yoast_free_additional_metabox_sections`.
do_action_deprecated( 'wpseo_tab_content', array(), '11.9' );
?>
</div>
</div>
<?php
}
/**
* `WPSEO_Metabox_Addon_Section` always has "tabs", represented by registered actions. If this is not the case,
* `WPSEO_Metabox_Addon_Section` always has "sections", represented by registered actions. If this is not the case,
* it should not be instantiated.
*
* @deprecated 11.9
*
* @return bool
*/
protected function has_sections() {
_deprecated_function( __METHOD__, '11.9' );
return true;
}
}
......@@ -91,13 +91,7 @@ class WPSEO_Schema_Author extends WPSEO_Schema_Person implements WPSEO_Graph_Pie
* @return bool
*/
protected function is_post_author() {
/**
* Filter: 'wpseo_schema_article_post_type' - Allow changing for which post types we output Article schema.
*
* @api array $post_types The post types for which we output Article.
*/
$post_types = apply_filters( 'wpseo_schema_article_post_type', array( 'post' ) );
if ( is_singular( $post_types ) ) {
if ( is_singular() && WPSEO_Schema_Article::is_article_post_type() ) {
return true;
}
......
......@@ -116,7 +116,7 @@ class WPSEO_Shortlinker {
$cohort = '6-30';
break;
default:
$cohort = '>30';
$cohort = '30plus';
}
return $cohort;
}
......
......@@ -1216,6 +1216,155 @@ SVG;
return "<script type='application/ld+json' class='" . esc_attr( $class ) . "'>" . self::format_json_encode( $output ) . '</script>' . "\n";
}
/**
* Extends the allowed post tags with accessibility-related attributes.
*
* @param array $allowed_post_tags The allowed post tags.
* @codeCoverageIgnore
*
* @return array The allowed tags including post tags, input tags and select tags.
*/
public static function extend_kses_post_with_a11y( $allowed_post_tags ) {
static $a11y_tags;
if ( isset( $a11y_tags ) === false ) {
$a11y_tags = array(
'button' => array(
'aria-expanded' => true,
),
'div' => array(
'tabindex' => true,
),
// Below are attributes that are needed for backwards compatibility (WP < 5.1).
'span' => array(
'aria-hidden' => true,
),
'input' => array(
'aria-describedby' => true,
),
'select' => array(
'aria-describedby' => true,
),
'textarea' => array(
'aria-describedby' => true,
),
);
// Add the global allowed attributes to each html element.
$a11y_tags = array_map( '_wp_add_global_attributes', $a11y_tags );
}
return array_merge_recursive( $allowed_post_tags, $a11y_tags );
}
/**
* Extends the allowed post tags with input, select and option tags.
*
* @param array $allowed_post_tags The allowed post tags.
* @codeCoverageIgnore
*
* @return array The allowed tags including post tags, input tags, select tags and option tags.
*/
public static function extend_kses_post_with_forms( $allowed_post_tags ) {
static $input_tags;
if ( isset( $input_tags ) === false ) {
$input_tags = array(
'input' => array(
'accept' => true,
'accesskey' => true,
'align' => true,
'alt' => true,
'autocomplete' => true,
'autofocus' => true,
'checked' => true,
'contenteditable' => true,
'dirname' => true,
'disabled' => true,
'draggable' => true,
'dropzone' => true,
'form' => true,
'formaction' => true,
'formenctype' => true,
'formmethod' => true,
'formnovalidate' => true,
'formtarget' => true,
'height' => true,
'hidden' => true,
'lang' => true,
'list' => true,
'max' => true,
'maxlength' => true,
'min' => true,
'multiple' => true,
'name' => true,
'pattern' => true,
'placeholder' => true,
'readonly' => true,
'required' => true,
'size' => true,
'spellcheck' => true,
'src' => true,
'step' => true,
'tabindex' => true,
'translate' => true,
'type' => true,
'value' => true,
'width' => true,
/*
* Below are attributes that are needed for backwards compatibility (WP < 5.1).
* They are used for the social media image in the metabox.
* These can be removed once we move to the React versions of the social previews.
*/
'data-target' => true,
'data-target-id' => true,
),
'select' => array(
'accesskey' => true,
'autofocus' => true,
'contenteditable' => true,
'disabled' => true,
'draggable' => true,
'dropzone' => true,
'form' => true,
'hidden' => true,
'lang' => true,
'multiple' => true,
'name' => true,
'onblur' => true,
'onchange' => true,
'oncontextmenu' => true,
'onfocus' => true,
'oninput' => true,
'oninvalid' => true,
'onreset' => true,
'onsearch' => true,
'onselect' => true,
'onsubmit' => true,
'required' => true,
'size' => true,
'spellcheck' => true,
'tabindex' => true,
'translate' => true,
),
'option' => array(
'class' => true,
'disabled' => true,
'id' => true,
'label' => true,
'selected' => true,
'value' => true,
),
);
// Add the global allowed attributes to each html element.
$input_tags = array_map( '_wp_add_global_attributes', $input_tags );
}
return array_merge_recursive( $allowed_post_tags, $input_tags );
}
/* ********************* DEPRECATED METHODS ********************* */
/**
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment