From 61c2add0b8ee8e2967a976ec67d563c63079b8e7 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 2 Feb 2024 13:04:10 +0100 Subject: [PATCH 001/344] add hidden fields data to metabox object --- .../class-post-metabox-formatter.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index aa4eb2f296f..a4e1c3d3c35 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -83,6 +83,7 @@ public function get_values() { 'social_description_template' => $this->get_social_description_template(), 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), + 'metaData' => $this->get_post_meta_data(), ]; $values = ( $values_to_set + $values ); @@ -314,4 +315,44 @@ private function get_metadesc_date() { protected function is_insights_enabled() { return WPSEO_Options::get( 'enable_metabox_insights', false ); } + + /** + * Get post meta data. + * + * @return void + */ + protected function get_post_meta_data() { + $post_type = $this->post->post_type; + $meta_data = []; + $fields = []; + + $social_is_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); + $is_advanced_metadata_enabled = WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false; + + $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'general', $post_type ) ); + + if ( $is_advanced_metadata_enabled ) { + $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'advanced', $post_type ) ); + } + + $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'schema', $post_type ) ); + + if ( $social_is_enabled ) { + $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'social', $post_type ) ); + } + + foreach ( $fields as $key => $meta_field ) { + $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); + $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); + + $default = ''; + if ( isset( $meta_field['default'] ) ) { + $default = $meta_field['default']; + } + + $meta_data[ $form_key ] = \esc_attr( $meta_value ) ? \esc_attr( $meta_value ) : $default; + } + + return $meta_data; + } } From e1472285720aa5f1eb82e7d961527d48ced3b4d2 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:36:26 +0100 Subject: [PATCH 002/344] Add metadata to scriptdata window object for post --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index a4e1c3d3c35..20f7f4f9fe0 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -350,7 +350,7 @@ protected function get_post_meta_data() { $default = $meta_field['default']; } - $meta_data[ $form_key ] = \esc_attr( $meta_value ) ? \esc_attr( $meta_value ) : $default; + $meta_data[ $key ] = \esc_attr( $meta_value ) ? \esc_attr( $meta_value ) : $default; } return $meta_data; From 3b0937479e89dd6326f110f2640196b7061ff594 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:36:38 +0100 Subject: [PATCH 003/344] Add metadata to scriptdata window object for term --- .../class-term-metabox-formatter.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index aa596cdcaa2..1e260684b8e 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -86,12 +86,44 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), + 'metadata' => $this->get_metadata(), ]; } return $values; } + /** + * Returns the metadata for the term. + * + * @return array + */ + protected function get_metadata() { + $metadata = []; + + $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); + $field_definitions = new WPSEO_Taxonomy_Fields(); + $is_social_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); + $meta_prefix = 'wpseo_'; + + foreach ($field_definitions->get( 'content' ) as $key => $field) { + $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + } + if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { + foreach ($field_definitions->get( 'settings' ) as $key => $field) { + $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + } + } + + if ( $is_social_enabled ) { + foreach ($field_definitions->get( 'social' ) as $key => $field) { + $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + } + } + + return $metadata; + } + /** * Gets the image URL for the term's social preview. * From adabf63024880ffd79fb663806cc1e252d0e2792 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:37:07 +0100 Subject: [PATCH 004/344] expose metafields in rest endpoint for posts --- inc/class-wpseo-meta.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 65e2cd9bcb4..b3e8929c4b5 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -304,7 +304,11 @@ public static function init() { register_meta( 'post', self::$meta_prefix . $key, - [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ] ] + [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], + 'show_in_rest' => true, + 'type' => 'string', + 'single' => true, + ] ); // Set the $fields_index property for efficiency. From 04513b2d6038cc65ed3d11199bd82043d3384568 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:37:42 +0100 Subject: [PATCH 005/344] use presenter methods outside class, so turning it to public --- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index 9ab28b0c5b1..dbef6711b79 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -163,7 +163,7 @@ private function get_field( $field_type, $field_name, $field_value, array $optio * * @return string */ - private function get_field_value( $field_name ) { + public function get_field_value( $field_name ) { if ( isset( $this->tax_meta[ $field_name ] ) && $this->tax_meta[ $field_name ] !== '' ) { return $this->tax_meta[ $field_name ]; } From 48451f5e5cf128a50f2a77af1011a9034cbac5a8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:42:06 +0100 Subject: [PATCH 006/344] Add field sync js class --- packages/js/src/helpers/fields/FieldSync.js | 92 +++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 packages/js/src/helpers/fields/FieldSync.js diff --git a/packages/js/src/helpers/fields/FieldSync.js b/packages/js/src/helpers/fields/FieldSync.js new file mode 100644 index 00000000000..3b7401052eb --- /dev/null +++ b/packages/js/src/helpers/fields/FieldSync.js @@ -0,0 +1,92 @@ +import { dispatch } from "@wordpress/data"; + +/** + * This class is responsible for syncing hidden fields with store. + */ +export default class FieldSync { + static isPost = window.wpseoScriptData?.isPost; + static metaPrefix = "_yoast_wpseo_"; + + // Whether we are handling a post or a term. + static idPrefix = this.isPost ? "yoast_wpseo_" : "hidden_wpseo_"; + + static booleanFields = [ "isCornerstone", "wordproof_timestamp" ]; + + /** + * Get input element by id for classic editor. + * + * @param {string} fieldKey The key of the input element. + * @returns {HTMLElement} The input element. + */ + static getInputElement( fieldKey ) { + return document.getElementById( this.idPrefix + fieldKey ); + } + + /** + * Get the initial value of a field. Same location in window object for post and term. + * + * @param {string} fieldKey The field key. + * @returns {value} The initial value of the field. + */ + static getInitialValue( fieldKey ) { + return window.wpseoScriptData?.metabox.metadata[ fieldKey ]; + } + + /** + * Toggle the hidden field value. + * + * @param {string} fieldkey The field key. + * @returns {void} + */ + static toggleFieldValue( fieldkey ) { + try { + const value = this.getInputElement( fieldkey ); + const newValue = value === "1" ? "0" : "1"; + this.setFieldValue( fieldkey, newValue ); + } finally { + // Do nothing. + } + } + + /** + * Prepare the value of a field. + * @param {string} fieldKey The field key. + * @param {value} value The value of the field. + * @returns {value} The prepared value of the field. + */ + static preparedValue( fieldKey, value ) { + if ( this.booleanFields.includes( fieldKey ) ) { + return value ? "1" : "0"; + } + return value ?? ""; + } + + /** + * Set the value of a field. + * @param {string} fieldKey The field id. + * @param {value} value The value of the field. + * @returns {void} + */ + static setFieldValue( fieldKey, value ) { + const inputElement = this.getInputElement( fieldKey ); + + // If Classic Editor + if ( inputElement ) { + inputElement.value = value; + return; + } + + // If Block Editor and a post + try { + const editPost = dispatch( "core/editor" ).editPost; + editPost( { + meta: { [ this.metaPrefix + fieldKey ]: value }, + } ); + return; + } catch ( e ) { + // Do nothing. + } + + // If Site Editor + } +} From ba1657168f30adf62f64b264e7423677392f9a5b Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 13 Feb 2024 16:54:56 +0100 Subject: [PATCH 007/344] apply field sync class on twitter fields --- .../js/src/redux/actions/twitterEditor.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/js/src/redux/actions/twitterEditor.js b/packages/js/src/redux/actions/twitterEditor.js index 92c41b53310..2393afa5087 100644 --- a/packages/js/src/redux/actions/twitterEditor.js +++ b/packages/js/src/redux/actions/twitterEditor.js @@ -2,7 +2,7 @@ import { select } from "@wordpress/data"; /* Internal dependencies */ -import TwitterFields from "../../helpers/fields/TwitterFields"; +import FieldSync from "../../helpers/fields/FieldSync"; export const SET_TWITTER_TITLE = "SET_TWITTER_TITLE"; export const SET_TWITTER_DESCRIPTION = "SET_TWITTER_DESCRIPTION"; @@ -19,9 +19,9 @@ export const LOAD_TWITTER_PREVIEW = "LOAD_TWITTER_PREVIEW"; */ export const setTwitterPreviewTitle = ( title ) => { if ( title.trim() === select( "yoast-seo/editor" ).getSocialTitleTemplate().trim() ) { - TwitterFields.title = ""; + FieldSync.setFieldValue( "twitter-title", "" ); } else { - TwitterFields.title = title; + FieldSync.setFieldValue( "twitter-title", title ); } return { type: SET_TWITTER_TITLE, title }; @@ -36,9 +36,9 @@ export const setTwitterPreviewTitle = ( title ) => { */ export const setTwitterPreviewDescription = ( description ) => { if ( description.trim() === select( "yoast-seo/editor" ).getSocialDescriptionTemplate().trim() ) { - TwitterFields.description = ""; + FieldSync.setFieldValue( "twitter-description", "" ); } else { - TwitterFields.description = description; + FieldSync.setFieldValue( "twitter-description", description ); } return { type: SET_TWITTER_DESCRIPTION, description }; @@ -52,8 +52,8 @@ export const setTwitterPreviewDescription = ( description ) => { * @returns {Object} The action object. */ export const setTwitterPreviewImage = ( image ) => { - TwitterFields.imageId = image.id; - TwitterFields.imageUrl = image.url; + FieldSync.setFieldValue( "twitter-image-id", image.id ); + FieldSync.setFieldValue( "twitter-image", image.url ); return { type: SET_TWITTER_IMAGE, image }; }; @@ -63,8 +63,8 @@ export const setTwitterPreviewImage = ( image ) => { * @returns {Object} The action object. */ export const clearTwitterPreviewImage = () => { - TwitterFields.imageId = ""; - TwitterFields.imageUrl = ""; + FieldSync.setFieldValue( "twitter-image-id", "" ); + FieldSync.setFieldValue( "twitter-image", "" ); return { type: CLEAR_TWITTER_IMAGE }; }; @@ -81,9 +81,9 @@ export const loadTwitterPreviewData = () => { return { type: LOAD_TWITTER_PREVIEW, - imageId: TwitterFields.imageId, - imageUrl: TwitterFields.imageUrl, - description: TwitterFields.description || getSocialDescriptionTemplate(), - title: TwitterFields.title || getSocialTitleTemplate(), + imageId: FieldSync.getInitialValue( "twitter-image-id" ), + imageUrl: FieldSync.getInitialValue( "twitter-image" ), + description: FieldSync.getInitialValue( "twitter-description" ) || getSocialDescriptionTemplate(), + title: FieldSync.getInitialValue( "twitter-title" ) || getSocialTitleTemplate(), }; }; From 4bce4b4511f039a321fa41d5f945b05e692359a1 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 12:09:59 +0100 Subject: [PATCH 008/344] Replaced metabox fields syncing methods --- .../elementor/redux/actions/snippetEditor.js | 19 +++-- .../{FieldSync.js => MetaboxFieldSync.js} | 73 ++++++++++++++----- packages/js/src/insights/redux/actions.js | 6 +- .../js/src/redux/actions/advancedSettings.js | 28 +++---- .../js/src/redux/actions/contentAnalysis.js | 8 +- .../src/redux/actions/cornerstoneContent.js | 8 +- .../js/src/redux/actions/facebookEditor.js | 26 +++---- packages/js/src/redux/actions/focusKeyword.js | 6 +- .../js/src/redux/actions/twitterEditor.js | 26 +++---- 9 files changed, 120 insertions(+), 80 deletions(-) rename packages/js/src/helpers/fields/{FieldSync.js => MetaboxFieldSync.js} (56%) diff --git a/packages/js/src/elementor/redux/actions/snippetEditor.js b/packages/js/src/elementor/redux/actions/snippetEditor.js index 435cecffc45..5365001914c 100644 --- a/packages/js/src/elementor/redux/actions/snippetEditor.js +++ b/packages/js/src/elementor/redux/actions/snippetEditor.js @@ -1,5 +1,5 @@ import { get } from "lodash"; -import SearchMetadataFields from "../../../helpers/fields/SearchMetadataFields"; +import MetaboxFieldSync from "../../../helpers/fields/MetaboxFieldSync"; import { actions } from "@yoast/externals/redux"; const { UPDATE_DATA, LOAD_SNIPPET_EDITOR_DATA } = actions; @@ -25,19 +25,18 @@ export function updateData( data ) { if ( data.title === get( window, "wpseoScriptData.metabox.title_template", "" ) ) { titleToBeSaved = ""; } - - SearchMetadataFields.title = titleToBeSaved; + MetaboxFieldSync.setFieldValue( "metadesc", titleToBeSaved ); } if ( data.hasOwnProperty( "description" ) ) { - let metaDescToBeSaved = data.description; + const metaDescToBeSaved = data.description; // Test whether this is actually the template, which we don't want to save. if ( data.description === get( window, "wpseoScriptData.metabox.metadesc_template", "" ) ) { - metaDescToBeSaved = ""; + MetaboxFieldSync.setFieldValue( "metadesc", "" ); } - SearchMetadataFields.description = metaDescToBeSaved; + MetaboxFieldSync.setFieldValue( "metadesc", metaDescToBeSaved ); } if ( data.hasOwnProperty( "slug" ) ) { - SearchMetadataFields.slug = data.slug; + MetaboxFieldSync.setFieldValue( "slug", data.slug ); } return { @@ -58,9 +57,9 @@ export const loadSnippetEditorData = () => { return { type: LOAD_SNIPPET_EDITOR_DATA, data: { - title: SearchMetadataFields.title || titleTemplate, - description: SearchMetadataFields.description || descriptionTemplate, - slug: SearchMetadataFields.slug, + title: MetaboxFieldSync.getInitialValue( "title" ) || titleTemplate, + description: MetaboxFieldSync.getInitialValue( "metadesc" ) || descriptionTemplate, + slug: MetaboxFieldSync.getInitialValue( "slug" ), }, templates: { title: titleTemplate, diff --git a/packages/js/src/helpers/fields/FieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js similarity index 56% rename from packages/js/src/helpers/fields/FieldSync.js rename to packages/js/src/helpers/fields/MetaboxFieldSync.js index 3b7401052eb..8f7a11f75a7 100644 --- a/packages/js/src/helpers/fields/FieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -3,7 +3,7 @@ import { dispatch } from "@wordpress/data"; /** * This class is responsible for syncing hidden fields with store. */ -export default class FieldSync { +export default class MetaboxFieldSync { static isPost = window.wpseoScriptData?.isPost; static metaPrefix = "_yoast_wpseo_"; @@ -13,7 +13,7 @@ export default class FieldSync { static booleanFields = [ "isCornerstone", "wordproof_timestamp" ]; /** - * Get input element by id for classic editor. + * Get input element by key. * * @param {string} fieldKey The key of the input element. * @returns {HTMLElement} The input element. @@ -29,6 +29,16 @@ export default class FieldSync { * @returns {value} The initial value of the field. */ static getInitialValue( fieldKey ) { + return window.wpseoScriptData?.metabox?.metadata[ fieldKey ]; + } + + /** + * Get no index value. + * @param {string} value The value. + * @returns {void} + */ + static getNoIndex() { + const fieldKey = this.isPost ? "meta-robots-noindex" : "noindex"; return window.wpseoScriptData?.metabox.metadata[ fieldKey ]; } @@ -39,42 +49,71 @@ export default class FieldSync { * @returns {void} */ static toggleFieldValue( fieldkey ) { - try { - const value = this.getInputElement( fieldkey ); - const newValue = value === "1" ? "0" : "1"; + const inputElement = this.getInputElement( fieldkey ); + if ( inputElement ) { + const newValue = inputElement.value === "1" ? "0" : "1"; this.setFieldValue( fieldkey, newValue ); - } finally { - // Do nothing. } } /** - * Prepare the value of a field. + * Set the value of a boolean field. * @param {string} fieldKey The field key. * @param {value} value The value of the field. * @returns {value} The prepared value of the field. */ - static preparedValue( fieldKey, value ) { - if ( this.booleanFields.includes( fieldKey ) ) { - return value ? "1" : "0"; + static setBooleanFieldValue( fieldKey, value ) { + const inputElement = this.getInputElement( fieldKey ); + + if ( inputElement ) { + inputElement.value = value ? "1" : "0"; } - return value ?? ""; } /** * Set the value of a field. - * @param {string} fieldKey The field id. + * @param {string} fieldId The field id. * @param {value} value The value of the field. * @returns {void} */ - static setFieldValue( fieldKey, value ) { - const inputElement = this.getInputElement( fieldKey ); + static setFieldValueBySingleId( fieldId, value ) { + const inputElement = document.getElementById( fieldId ); - // If Classic Editor + if ( inputElement ) { + inputElement.value = value ?? ""; + } + } + + /** + * Set no index value. + * @param {string} value The value. + * @returns {void} + */ + static setNoIndex( value ) { + const inputElement = document.getElementById( this.isPost ? "yoast_wpseo_meta-robots-noindex" : "hidden_wpseo_noindex" ); if ( inputElement ) { inputElement.value = value; - return; } + } + + /** + * Set the value of a field. + * @param {string} fieldKey The field key. + * @param {value} value The value of the field. + * @returns {void} + */ + static setFieldValue( fieldKey, value ) { + const inputElement = this.getInputElement( fieldKey ); + + try { + if ( inputElement ) { + inputElement.value = value ?? ""; + return; + } + } catch ( e ) { + // Do nothing. + } + // If Block Editor and a post try { diff --git a/packages/js/src/insights/redux/actions.js b/packages/js/src/insights/redux/actions.js index 87fe3e86f17..0756ddd0f03 100644 --- a/packages/js/src/insights/redux/actions.js +++ b/packages/js/src/insights/redux/actions.js @@ -1,5 +1,5 @@ import { toSafeInteger } from "lodash"; -import EstimatedReadingTimeFields from "../../helpers/fields/EstimatedReadingTimeFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; export const SET_ESTIMATED_READING_TIME = "SET_ESTIMATED_READING_TIME"; export const LOAD_ESTIMATED_READING_TIME = "LOAD_ESTIMATED_READING_TIME"; @@ -15,7 +15,7 @@ export const SET_TEXT_LENGTH = "SET_TEXT_LENGTH"; * @returns {Object} The SET_ESTIMATED_READING_TIME action. */ export const setEstimatedReadingTime = estimatedReadingTime => { - EstimatedReadingTimeFields.estimatedReadingTime = estimatedReadingTime.toString(); + MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_estimated-reading-time-minutes", estimatedReadingTime.toString() ); return { type: SET_ESTIMATED_READING_TIME, payload: estimatedReadingTime, @@ -29,7 +29,7 @@ export const setEstimatedReadingTime = estimatedReadingTime => { */ export const loadEstimatedReadingTime = () => ( { type: LOAD_ESTIMATED_READING_TIME, - payload: toSafeInteger( EstimatedReadingTimeFields.estimatedReadingTime ), + payload: toSafeInteger( MetaboxFieldSync.getInitialValue( "estimated-reading-time-minutes" ) ), } ); /** diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index 6b5170ed12f..f345b39dea8 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -1,4 +1,4 @@ -import AdvancedFields from "../../helpers/fields/AdvancedFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; export const SET_NO_INDEX = "SET_NO_INDEX"; export const SET_NO_FOLLOW = "SET_NO_FOLLOW"; @@ -16,7 +16,7 @@ export const LOAD_ADVANCED_SETTINGS = "LOAD_ADVANCED_SETTINGS"; * @returns {Object} The action object. */ export const setNoIndex = ( value ) => { - AdvancedFields.noIndex = value; + MetaboxFieldSync.setNoIndex( value ); return { type: SET_NO_INDEX, value }; }; @@ -28,7 +28,7 @@ export const setNoIndex = ( value ) => { * @returns {Object} The action object. */ export const setNoFollow = ( value ) => { - AdvancedFields.noFollow = value; + MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_meta-robots-nofollow", value ); return { type: SET_NO_FOLLOW, value }; }; @@ -40,7 +40,7 @@ export const setNoFollow = ( value ) => { * @returns {Object} The action object. */ export const setAdvanced = ( value ) => { - AdvancedFields.advanced = value.join( "," ); + MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_meta-robots-adv", value.join( "," ) ); return { type: SET_ADVANCED, value }; }; @@ -52,7 +52,7 @@ export const setAdvanced = ( value ) => { * @returns {Object} The action object. */ export const setBreadcrumbsTitle = ( value ) => { - AdvancedFields.breadcrumbsTitle = value; + MetaboxFieldSync.setFieldValue( "bctitle", value ); return { type: SET_BREADCRUMBS_TITLE, value }; }; @@ -64,7 +64,7 @@ export const setBreadcrumbsTitle = ( value ) => { * @returns {Object} The action object. */ export const setCanonical = ( value ) => { - AdvancedFields.canonical = value; + MetaboxFieldSync.setFieldValue( "canonical", value ); return { type: SET_CANONICAL_URL, value }; }; @@ -76,7 +76,7 @@ export const setCanonical = ( value ) => { * @returns {Object} The action object. */ export const setWordProofTimestamp = ( value ) => { - AdvancedFields.wordproofTimestamp = value; + MetaboxFieldSync.setBooleanFieldValue( "wordproof_timestamp", value ); return { type: SET_WORDPROOF_TIMESTAMP, value }; }; @@ -86,15 +86,17 @@ export const setWordProofTimestamp = ( value ) => { * @returns {object} The action object. */ export const loadAdvancedSettingsData = () => { + const advancedValue = MetaboxFieldSync.getInitialValue( "meta-robots-adv" ); + const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; return { type: LOAD_ADVANCED_SETTINGS, settings: { - noIndex: AdvancedFields.noIndex, - noFollow: AdvancedFields.noFollow, - advanced: AdvancedFields.advanced.split( "," ), - breadcrumbsTitle: AdvancedFields.breadcrumbsTitle, - canonical: AdvancedFields.canonical, - wordproofTimestamp: AdvancedFields.wordproofTimestamp, + noIndex: MetaboxFieldSync.getNoIndex(), + noFollow: MetaboxFieldSync.getInitialValue( "meta-robots-nofollow" ), + advanced: advancedList, + breadcrumbsTitle: MetaboxFieldSync.getInitialValue( "bctitle" ), + canonical: MetaboxFieldSync.getInitialValue( "canonical" ), + wordproofTimestamp: MetaboxFieldSync.getInitialValue( "wordproof_timestamp" ) === "1", isLoading: false, }, }; diff --git a/packages/js/src/redux/actions/contentAnalysis.js b/packages/js/src/redux/actions/contentAnalysis.js index a6e4138f434..56398e23ede 100644 --- a/packages/js/src/redux/actions/contentAnalysis.js +++ b/packages/js/src/redux/actions/contentAnalysis.js @@ -1,4 +1,4 @@ -import AnalysisFields from "../../helpers/fields/AnalysisFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; /* * Action types @@ -148,7 +148,7 @@ export function updateInclusiveLanguageResult( result ) { * @returns {Object} A set overall score action. */ export function setOverallReadabilityScore( overallScore ) { - AnalysisFields.readabilityScore = overallScore; + MetaboxFieldSync.setFieldValue( "content_score", overallScore ); return { type: SET_OVERALL_READABILITY_SCORE, overallScore: overallScore, @@ -164,7 +164,7 @@ export function setOverallReadabilityScore( overallScore ) { * @returns {Object} A set overall score action. */ export function setOverallSeoScore( overallScore, keyword ) { - AnalysisFields.seoScore = overallScore; + MetaboxFieldSync.setFieldValue( "linkdex", overallScore ); return { type: SET_OVERALL_SEO_SCORE, keyword: keyword, @@ -180,7 +180,7 @@ export function setOverallSeoScore( overallScore, keyword ) { * @returns {Object} A set overall score action. */ export function setOverallInclusiveLanguageScore( overallScore ) { - AnalysisFields.inclusiveLanguageScore = overallScore; + MetaboxFieldSync.setFieldValue( "inclusive_language_score", overallScore ); return { type: SET_OVERALL_INCLUSIVE_LANGUAGE_SCORE, overallScore: overallScore, diff --git a/packages/js/src/redux/actions/cornerstoneContent.js b/packages/js/src/redux/actions/cornerstoneContent.js index 3dc672d411e..9edad68ec6c 100644 --- a/packages/js/src/redux/actions/cornerstoneContent.js +++ b/packages/js/src/redux/actions/cornerstoneContent.js @@ -1,4 +1,4 @@ -import AnalysisFields from "../../helpers/fields/AnalysisFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; const PREFIX = "WPSEO_"; @@ -14,7 +14,7 @@ export const SET_CORNERSTONE_CONTENT = `${ PREFIX }SET_CORNERSTONE_CONTENT`; export const loadCornerstoneContent = () => { return { type: SET_CORNERSTONE_CONTENT, - isCornerstone: AnalysisFields.isCornerstone, + isCornerstone: MetaboxFieldSync.getInitialValue( "is_cornerstone" ) === "1", }; }; @@ -26,7 +26,7 @@ export const loadCornerstoneContent = () => { * @returns {Object} The set cornerstone content action. */ export const setCornerstoneContent = ( isCornerstone ) => { - AnalysisFields.isCornerstone = isCornerstone; + MetaboxFieldSync.setBooleanFieldValue( "is_cornerstone", isCornerstone ); return { type: SET_CORNERSTONE_CONTENT, isCornerstone, @@ -39,7 +39,7 @@ export const setCornerstoneContent = ( isCornerstone ) => { * @returns {Object} The toggle cornerstone content action. */ export const toggleCornerstoneContent = () => { - AnalysisFields.isCornerstone = ! AnalysisFields.isCornerstone; + MetaboxFieldSync.toggleFieldValue( "is_cornerstone" ); return { type: TOGGLE_CORNERSTONE_CONTENT, }; diff --git a/packages/js/src/redux/actions/facebookEditor.js b/packages/js/src/redux/actions/facebookEditor.js index 9aa170f506a..a4597c7dcd9 100644 --- a/packages/js/src/redux/actions/facebookEditor.js +++ b/packages/js/src/redux/actions/facebookEditor.js @@ -2,7 +2,7 @@ import { select } from "@wordpress/data"; /* Internal dependencies */ -import FacebookFields from "../../helpers/fields/FacebookFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; export const SET_FACEBOOK_TITLE = "SET_FACEBOOK_TITLE"; @@ -20,9 +20,9 @@ export const LOAD_FACEBOOK_PREVIEW = "LOAD_FACEBOOK_PREVIEW"; */ export const setFacebookPreviewTitle = ( title ) => { if ( title.trim() === select( "yoast-seo/editor" ).getSocialTitleTemplate().trim() ) { - FacebookFields.title = ""; + MetaboxFieldSync.setFieldValue( "opengraph-title", "" ); } else { - FacebookFields.title = title; + MetaboxFieldSync.setFieldValue( "opengraph-title", title ); } return { type: SET_FACEBOOK_TITLE, title }; @@ -37,9 +37,9 @@ export const setFacebookPreviewTitle = ( title ) => { */ export const setFacebookPreviewDescription = ( description ) => { if ( description.trim() === select( "yoast-seo/editor" ).getSocialDescriptionTemplate().trim() ) { - FacebookFields.description = ""; + MetaboxFieldSync.setFieldValue( "opengraph-description", "" ); } else { - FacebookFields.description = description; + MetaboxFieldSync.setFieldValue( "opengraph-description", description ); } return { type: SET_FACEBOOK_DESCRIPTION, description }; @@ -53,8 +53,8 @@ export const setFacebookPreviewDescription = ( description ) => { * @returns {object} The action object. */ export const setFacebookPreviewImage = ( image ) => { - FacebookFields.imageUrl = image.url; - FacebookFields.imageId = image.id; + MetaboxFieldSync.setFieldValue( "opengraph-image", image.url ); + MetaboxFieldSync.setFieldValue( "opengraph-image-id", image.id ); return { type: SET_FACEBOOK_IMAGE, image }; }; @@ -64,8 +64,8 @@ export const setFacebookPreviewImage = ( image ) => { * @returns {object} The action object. */ export const clearFacebookPreviewImage = () => { - FacebookFields.imageId = ""; - FacebookFields.imageUrl = ""; + MetaboxFieldSync.setFieldValue( "opengraph-image", "" ); + MetaboxFieldSync.setFieldValue( "opengraph-image-id", "" ); return { type: CLEAR_FACEBOOK_IMAGE }; }; @@ -82,9 +82,9 @@ export const loadFacebookPreviewData = () => { return { type: LOAD_FACEBOOK_PREVIEW, - imageId: FacebookFields.imageId, - imageUrl: FacebookFields.imageUrl, - description: FacebookFields.description || getSocialDescriptionTemplate(), - title: FacebookFields.title || getSocialTitleTemplate(), + imageId: MetaboxFieldSync.getInitialValue( "opengraph-image-id" ), + imageUrl: MetaboxFieldSync.getInitialValue( "opengraph-image" ), + description: MetaboxFieldSync.getInitialValue( "opengraph-description" ) || getSocialDescriptionTemplate(), + title: MetaboxFieldSync.getInitialValue( "opengraph-title" ) || getSocialTitleTemplate(), }; }; diff --git a/packages/js/src/redux/actions/focusKeyword.js b/packages/js/src/redux/actions/focusKeyword.js index ea97bc9609b..81ad63cb580 100644 --- a/packages/js/src/redux/actions/focusKeyword.js +++ b/packages/js/src/redux/actions/focusKeyword.js @@ -1,4 +1,4 @@ -import AnalysisFields from "../../helpers/fields/AnalysisFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; const PREFIX = "WPSEO_"; @@ -13,7 +13,7 @@ export const SET_FOCUS_KEYWORD = `${ PREFIX }SET_FOCUS_KEYWORD`; export const loadFocusKeyword = () => { return { type: LOAD_FOCUS_KEYWORD, - keyword: AnalysisFields.keyphrase, + keyword: MetaboxFieldSync.getInitialValue( "focuskw" ), }; }; @@ -25,7 +25,7 @@ export const loadFocusKeyword = () => { * @returns {Object} Action. */ export const setFocusKeyword = function( keyword ) { - AnalysisFields.keyphrase = keyword; + MetaboxFieldSync.setFieldValue( "focuskw", keyword ); return { type: SET_FOCUS_KEYWORD, keyword: keyword, diff --git a/packages/js/src/redux/actions/twitterEditor.js b/packages/js/src/redux/actions/twitterEditor.js index 2393afa5087..2554cf71214 100644 --- a/packages/js/src/redux/actions/twitterEditor.js +++ b/packages/js/src/redux/actions/twitterEditor.js @@ -2,7 +2,7 @@ import { select } from "@wordpress/data"; /* Internal dependencies */ -import FieldSync from "../../helpers/fields/FieldSync"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; export const SET_TWITTER_TITLE = "SET_TWITTER_TITLE"; export const SET_TWITTER_DESCRIPTION = "SET_TWITTER_DESCRIPTION"; @@ -19,9 +19,9 @@ export const LOAD_TWITTER_PREVIEW = "LOAD_TWITTER_PREVIEW"; */ export const setTwitterPreviewTitle = ( title ) => { if ( title.trim() === select( "yoast-seo/editor" ).getSocialTitleTemplate().trim() ) { - FieldSync.setFieldValue( "twitter-title", "" ); + MetaboxFieldSync.setFieldValue( "twitter-title", "" ); } else { - FieldSync.setFieldValue( "twitter-title", title ); + MetaboxFieldSync.setFieldValue( "twitter-title", title ); } return { type: SET_TWITTER_TITLE, title }; @@ -36,9 +36,9 @@ export const setTwitterPreviewTitle = ( title ) => { */ export const setTwitterPreviewDescription = ( description ) => { if ( description.trim() === select( "yoast-seo/editor" ).getSocialDescriptionTemplate().trim() ) { - FieldSync.setFieldValue( "twitter-description", "" ); + MetaboxFieldSync.setFieldValue( "twitter-description", "" ); } else { - FieldSync.setFieldValue( "twitter-description", description ); + MetaboxFieldSync.setFieldValue( "twitter-description", description ); } return { type: SET_TWITTER_DESCRIPTION, description }; @@ -52,8 +52,8 @@ export const setTwitterPreviewDescription = ( description ) => { * @returns {Object} The action object. */ export const setTwitterPreviewImage = ( image ) => { - FieldSync.setFieldValue( "twitter-image-id", image.id ); - FieldSync.setFieldValue( "twitter-image", image.url ); + MetaboxFieldSync.setFieldValue( "twitter-image-id", image.id ); + MetaboxFieldSync.setFieldValue( "twitter-image", image.url ); return { type: SET_TWITTER_IMAGE, image }; }; @@ -63,8 +63,8 @@ export const setTwitterPreviewImage = ( image ) => { * @returns {Object} The action object. */ export const clearTwitterPreviewImage = () => { - FieldSync.setFieldValue( "twitter-image-id", "" ); - FieldSync.setFieldValue( "twitter-image", "" ); + MetaboxFieldSync.setFieldValue( "twitter-image-id", "" ); + MetaboxFieldSync.setFieldValue( "twitter-image", "" ); return { type: CLEAR_TWITTER_IMAGE }; }; @@ -81,9 +81,9 @@ export const loadTwitterPreviewData = () => { return { type: LOAD_TWITTER_PREVIEW, - imageId: FieldSync.getInitialValue( "twitter-image-id" ), - imageUrl: FieldSync.getInitialValue( "twitter-image" ), - description: FieldSync.getInitialValue( "twitter-description" ) || getSocialDescriptionTemplate(), - title: FieldSync.getInitialValue( "twitter-title" ) || getSocialTitleTemplate(), + imageId: MetaboxFieldSync.getInitialValue( "twitter-image-id" ), + imageUrl: MetaboxFieldSync.getInitialValue( "twitter-image" ), + description: MetaboxFieldSync.getInitialValue( "twitter-description" ) || getSocialDescriptionTemplate(), + title: MetaboxFieldSync.getInitialValue( "twitter-title" ) || getSocialTitleTemplate(), }; }; From c3e32a2b9a35c5d03890ed57c6b85186bea01ded Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 16:58:07 +0100 Subject: [PATCH 009/344] use metabox sync with primary category --- packages/js/src/components/PrimaryTaxonomyPicker.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index d222eeb0acf..3d15e697df8 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -6,6 +6,7 @@ import apiFetch from "@wordpress/api-fetch"; import { addQueryArgs } from "@wordpress/url"; import styled from "styled-components"; import { difference, noop } from "lodash"; +import MetaboxFieldSync from "../helpers/fields/MetaboxFieldSync"; /* Internal dependencies */ import TaxonomyPicker from "./TaxonomyPicker"; @@ -30,8 +31,11 @@ class PrimaryTaxonomyPicker extends Component { this.updateReplacementVariable = this.updateReplacementVariable.bind( this ); const { fieldId, name } = props.taxonomy; - this.input = document.getElementById( fieldId ); - props.setPrimaryTaxonomyId( name, parseInt( this.input.value, 10 ) ); + + const initialPrimaryTaxonomyId = parseInt( MetaboxFieldSync.getInitialValue( `primary_${name}` ), 10 ); + + props.setPrimaryTaxonomyId( name, initialPrimaryTaxonomyId ); + this.state = { selectedTerms: [], @@ -188,7 +192,7 @@ class PrimaryTaxonomyPicker extends Component { this.props.setPrimaryTaxonomyId( name, termId ); - this.input.value = termId === -1 ? "" : termId; + MetaboxFieldSync.setFieldValue( `primary_${name}`, termId === -1 ? "" : termId ); } /** From a81f3e7f30188bb9f1608326011e93003d9f8db5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 16:58:31 +0100 Subject: [PATCH 010/344] rename property for meta data --- packages/js/src/helpers/fields/MetaboxFieldSync.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js index 8f7a11f75a7..60d759ef136 100644 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -29,7 +29,7 @@ export default class MetaboxFieldSync { * @returns {value} The initial value of the field. */ static getInitialValue( fieldKey ) { - return window.wpseoScriptData?.metabox?.metadata[ fieldKey ]; + return window.wpseoScriptData?.metabox?.metaData[ fieldKey ]; } /** @@ -39,7 +39,7 @@ export default class MetaboxFieldSync { */ static getNoIndex() { const fieldKey = this.isPost ? "meta-robots-noindex" : "noindex"; - return window.wpseoScriptData?.metabox.metadata[ fieldKey ]; + return window.wpseoScriptData.metabox.metaData[ fieldKey ]; } /** From 44427dd6e22d5a8f62f3417f38c228abaa5034cf Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 16:58:53 +0100 Subject: [PATCH 011/344] Add primary terms to register post meta --- inc/class-wpseo-meta.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index b3e8929c4b5..32fdf13c6f2 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -296,6 +296,24 @@ public static function init() { if ( is_array( $extra_fields ) ) { self::$meta_fields = self::array_merge_recursive_distinct( $extra_fields, self::$meta_fields ); } + // register meta data for taxonomies. + $primay_terms[ 'primary_terms' ] = []; + + $taxonomies = get_taxonomies(); + foreach ( $taxonomies as $taxonomy_name ) { + $primay_terms[ 'primary_terms' ]['primary_' .$taxonomy_name ]= [ + 'type' => 'hidden', + 'title' => '', // Translation added later. + 'default_value' => '', + 'description' => '', // Translation added later. + ]; + } + + if ( $primay_terms && is_array( $primay_terms ) ) { + self::$meta_fields = self::array_merge_recursive_distinct( $primay_terms, self::$meta_fields ); + } + + unset( $extra_fields ); foreach ( self::$meta_fields as $subset => $field_group ) { From 879a156182de40f95b3e07fed1e648a0d24e7a9d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 16:59:40 +0100 Subject: [PATCH 012/344] rename meta data in term formator --- admin/formatter/class-term-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 1e260684b8e..673e6c03e55 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -86,7 +86,7 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metadata' => $this->get_metadata(), + 'metaData' => $this->get_metadata(), ]; } From bd28241ca96aaed6751cbb4f700a6ca6e4bb4f00 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 14 Feb 2024 17:03:02 +0100 Subject: [PATCH 013/344] add primary terms to window object --- admin/formatter/class-post-metabox-formatter.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 20f7f4f9fe0..52031dcb163 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -353,6 +353,13 @@ protected function get_post_meta_data() { $meta_data[ $key ] = \esc_attr( $meta_value ) ? \esc_attr( $meta_value ) : $default; } + $taxonomies = get_object_taxonomies( $post_type, 'objects' ); + foreach ( $taxonomies as $taxonomy ) { + $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); + $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term_object->get_primary_term(); + } + + return $meta_data; } } From 8b7f42288feb052ad3457708cd80f7800d62b4fb Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 14:38:24 +0100 Subject: [PATCH 014/344] add initial value for focus keyphrase in the store --- packages/js/src/initializers/editor-store.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 5824882ed7f..257488657c9 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -28,6 +28,8 @@ const populateStore = store => { } ) ); + store.dispatch( actions.setFocusKeyword( window.wpseoScriptData.metabox.metaData.focuskw ) ); + store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); From 6cfa089621f7586f340264071a01bd7df32ff553 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 14:50:26 +0100 Subject: [PATCH 015/344] get focus keyphrase from the store and not from the input field --- packages/js/src/analysis/PostDataCollector.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 8b9e9b167fd..0ae63992cae 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -75,14 +75,14 @@ PostDataCollector.prototype.getData = function() { }; /** - * Returns the keyword from the DOM. + * Returns the keyword from the Store. * * @returns {string} The keyword. */ PostDataCollector.prototype.getKeyword = function() { - var val = document.getElementById( "yoast_wpseo_focuskw" ) && document.getElementById( "yoast_wpseo_focuskw" ).value || ""; - - return val; + const store = select( "yoast-seo/editor" ); + const keyword = store.getFocusKeyword(); + return keyword; }; /** From 8966f29e67ac932785b1eee0eabb68e6d3efc871 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 15:08:57 +0100 Subject: [PATCH 016/344] updates store instead of input field, it will be populated through the metabox sync class --- packages/js/src/initializers/post-scraper.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index 62ae0ed3d81..1738b0df978 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -49,6 +49,7 @@ import { actions } from "@yoast/externals/redux"; // Helper dependencies. import isBlockEditor from "../helpers/isBlockEditor"; +import { getFocusKeyphrase } from "../redux/selectors/focusKeyPhrase.js"; const { setFocusKeyword, @@ -255,7 +256,9 @@ export default function initPostScraper( $, store, editorData ) { }; if ( isKeywordAnalysisActive() ) { - store.dispatch( setFocusKeyword( $( "#yoast_wpseo_focuskw" ).val() ) ); + const focuskw = getFocusKeyphrase(); + store.dispatch( focuskw ); + args.callbacks.saveScores = postDataCollector.saveScores.bind( postDataCollector ); args.callbacks.updatedKeywordsResults = function( results ) { @@ -535,7 +538,8 @@ export default function initPostScraper( $, store, editorData ) { focusKeyword = newFocusKeyword; requestWordsToHighlight( window.YoastSEO.analysis.worker.runResearch, store, focusKeyword ); - $( "#yoast_wpseo_focuskw" ).val( focusKeyword ); + setFocusKeyword( focusKeyword ); + refreshAfterFocusKeywordChange(); } From 9040feef7c8d51381ba473cbe38f7b1d281eb693 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 15:51:58 +0100 Subject: [PATCH 017/344] set primary category in store --- packages/js/src/initializers/editor-store.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 257488657c9..0ec4d0a07b5 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -1,6 +1,6 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; -import { get, pickBy } from "lodash"; +import { get, pickBy, forEach } from "lodash"; import * as controls from "../redux/controls"; /** @@ -28,6 +28,15 @@ const populateStore = store => { } ) ); + const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); + + const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); + } ); + store.dispatch( actions.setFocusKeyword( window.wpseoScriptData.metabox.metaData.focuskw ) ); store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); From 3091f63ec966a20ba89031c191d700334e70142d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 15:53:37 +0100 Subject: [PATCH 018/344] cleanup duplicates --- packages/js/src/initializers/editor-store.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 0ec4d0a07b5..09e1a6feeb0 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -37,8 +37,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - store.dispatch( actions.setFocusKeyword( window.wpseoScriptData.metabox.metaData.focuskw ) ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); From fa7a79200600d6510149f868d6d3bc7dd6e374e4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 16:26:57 +0100 Subject: [PATCH 019/344] fixed naming --- packages/js/src/redux/reducers/primaryTaxonomies.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/reducers/primaryTaxonomies.js b/packages/js/src/redux/reducers/primaryTaxonomies.js index 301714a81af..acf0f7c658b 100644 --- a/packages/js/src/redux/reducers/primaryTaxonomies.js +++ b/packages/js/src/redux/reducers/primaryTaxonomies.js @@ -10,7 +10,7 @@ const INITIAL_STATE = {}; * * @returns {string} The state. */ -function focusKeywordReducer( state = INITIAL_STATE, action ) { +function primaryTaxonomyReducer( state = INITIAL_STATE, action ) { switch ( action.type ) { case SET_PRIMARY_TAXONOMY: return { @@ -22,4 +22,4 @@ function focusKeywordReducer( state = INITIAL_STATE, action ) { } } -export default focusKeywordReducer; +export default primaryTaxonomyReducer; From e11b46e9dd1d819201e2dfe8757c3310ae0a4d10 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 15 Feb 2024 18:49:22 +0100 Subject: [PATCH 020/344] add property of value type --- inc/class-wpseo-meta.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 32fdf13c6f2..368a0538749 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -301,11 +301,12 @@ public static function init() { $taxonomies = get_taxonomies(); foreach ( $taxonomies as $taxonomy_name ) { - $primay_terms[ 'primary_terms' ]['primary_' .$taxonomy_name ]= [ + $primay_terms[ 'primary_terms' ]['primary_' .$taxonomy_name ] = [ 'type' => 'hidden', - 'title' => '', // Translation added later. + 'title' => '', 'default_value' => '', - 'description' => '', // Translation added later. + 'description' => '', + 'value_type' => 'integer' ]; } @@ -324,7 +325,7 @@ public static function init() { self::$meta_prefix . $key, [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], 'show_in_rest' => true, - 'type' => 'string', + 'type' => $field_def[ "value_type" ] ?? 'string', 'single' => true, ] ); From 33718b146fad8128f34b9e1839693b32a953885e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 10:11:51 +0100 Subject: [PATCH 021/344] register only taxonomies that can have primary term --- admin/formatter/class-post-metabox-formatter.php | 7 ++++--- inc/class-wpseo-meta.php | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 52031dcb163..0f21fbe1eef 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -355,11 +355,12 @@ protected function get_post_meta_data() { $taxonomies = get_object_taxonomies( $post_type, 'objects' ); foreach ( $taxonomies as $taxonomy ) { - $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); - $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term_object->get_primary_term(); + if( $taxonomy->hierarchical ){ + $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); + $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term_object->get_primary_term(); + } } - return $meta_data; } } diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 368a0538749..88726003586 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -299,7 +299,7 @@ public static function init() { // register meta data for taxonomies. $primay_terms[ 'primary_terms' ] = []; - $taxonomies = get_taxonomies(); + $taxonomies = get_taxonomies( [ 'hierarchical' => true ], 'names' ); foreach ( $taxonomies as $taxonomy_name ) { $primay_terms[ 'primary_terms' ]['primary_' .$taxonomy_name ] = [ 'type' => 'hidden', @@ -462,7 +462,7 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = self::$defaults[ $meta_key ]; switch ( true ) { - case ( $meta_key === self::$meta_prefix . 'linkdex' ): + case ( $meta_key === self::$meta_prefix . 'linkdex' || $field_def[ 'value_type' ] === 'integer' || $field_def[ 'value_type' ] === 'number' ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int >= 0 ) { $clean = strval( $int ); // Convert to string to make sure default check works. From 424f6cf9113dcd3b2f13e8ef0b3f4ff4618fe000 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 10:12:46 +0100 Subject: [PATCH 022/344] add defensive coding --- packages/js/src/components/PrimaryTaxonomyPicker.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index 3d15e697df8..5e6ceb871ce 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -32,10 +32,10 @@ class PrimaryTaxonomyPicker extends Component { const { fieldId, name } = props.taxonomy; - const initialPrimaryTaxonomyId = parseInt( MetaboxFieldSync.getInitialValue( `primary_${name}` ), 10 ); - - props.setPrimaryTaxonomyId( name, initialPrimaryTaxonomyId ); - + this.input = document.getElementById( fieldId ); + if ( this.input ) { + props.setPrimaryTaxonomyId( name, parseInt( this.input.value, 10 ) ); + } this.state = { selectedTerms: [], From 74ddeda3191058c64c2a3a98cc3782e2cc14d66d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 10:16:04 +0100 Subject: [PATCH 023/344] update initial state in elementor store --- .../js/src/elementor/initializers/editor-store.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index df212c60861..48c3082d97d 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -1,6 +1,6 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; -import { get, pickBy } from "lodash"; +import { get, pickBy, forEach } from "lodash"; import * as controls from "../../redux/controls"; import * as snippetEditorActions from "../redux/actions/snippetEditor"; import * as analysisSelectors from "../redux/selectors/analysis"; @@ -46,6 +46,15 @@ const populateStore = store => { store.dispatch( actions.loadTwitterPreviewData() ); } + const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); + + const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); + } ); + store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); From f54551fa014041e902e6c085601680ca7e08f64c Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Fri, 16 Feb 2024 15:45:54 +0100 Subject: [PATCH 024/344] Include social fields in the REST API --- inc/class-wpseo-meta.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 88726003586..1072254740d 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -280,6 +280,7 @@ public static function init() { self::$meta_fields['social'][ $network . '-' . $box ] = [ 'type' => $type, 'title' => '', // Translation added later. + 'show_in_rest' => true, 'default_value' => '', 'description' => '', // Translation added later. ]; From ee0a97aef2fc99735b15e1b6d7018aee03347b5c Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Fri, 16 Feb 2024 15:46:19 +0100 Subject: [PATCH 025/344] Ensure setFieldValue to work with a string --- packages/js/src/helpers/fields/MetaboxFieldSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js index 60d759ef136..ebfbdae88c6 100644 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -119,7 +119,7 @@ export default class MetaboxFieldSync { try { const editPost = dispatch( "core/editor" ).editPost; editPost( { - meta: { [ this.metaPrefix + fieldKey ]: value }, + meta: { [ this.metaPrefix + fieldKey ]: value.toString() }, } ); return; } catch ( e ) { From 52d3f07a3f605ee37f4cd0346a09ee31e596254a Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Fri, 16 Feb 2024 15:46:37 +0100 Subject: [PATCH 026/344] Initialize social fields --- packages/js/src/initializers/editor-store.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 09e1a6feeb0..caaf6d00ff4 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -31,6 +31,14 @@ const populateStore = store => { const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); + store.dispatch( actions.setFacebookPreviewTitle( metaData[ "opengraph-title" ] ) ); + store.dispatch( actions.setFacebookPreviewDescription( metaData[ "opengraph-description" ] ) ); + store.dispatch( actions.setFacebookPreviewImage( { url: metaData[ "opengraph-image" ], id: metaData[ "opengraph-image-id" ] } ) ); + + store.dispatch( actions.setTwitterPreviewTitle( metaData[ "twitter-title" ] ) ); + store.dispatch( actions.setTwitterPreviewDescription( metaData[ "twitter-description" ] ) ); + store.dispatch( actions.setTwitterPreviewImage( { url: metaData[ "twitter-image" ], id: metaData[ "twitter-image-id" ] } ) ); + const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); From c8ccd5a79018d8aff20776f33bbb8d07f7abe1bc Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:08:28 +0100 Subject: [PATCH 027/344] php fix cs --- admin/formatter/class-post-metabox-formatter.php | 16 ++++++++-------- admin/formatter/class-term-metabox-formatter.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 0f21fbe1eef..d3a4f0b6f62 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -83,7 +83,7 @@ public function get_values() { 'social_description_template' => $this->get_social_description_template(), 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metaData' => $this->get_post_meta_data(), + 'metaData' => $this->get_post_meta_data(), ]; $values = ( $values_to_set + $values ); @@ -324,11 +324,11 @@ protected function is_insights_enabled() { protected function get_post_meta_data() { $post_type = $this->post->post_type; $meta_data = []; - $fields = []; + $fields = []; $social_is_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); $is_advanced_metadata_enabled = WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false; - + $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'general', $post_type ) ); if ( $is_advanced_metadata_enabled ) { @@ -342,21 +342,21 @@ protected function get_post_meta_data() { } foreach ( $fields as $key => $meta_field ) { - $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); + $form_key = esc_attr( WPSEO_Meta::$form_prefix . $key ); $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); $default = ''; if ( isset( $meta_field['default'] ) ) { $default = $meta_field['default']; } - - $meta_data[ $key ] = \esc_attr( $meta_value ) ? \esc_attr( $meta_value ) : $default; + + $meta_data[ $key ] = esc_attr( $meta_value ) ? esc_attr( $meta_value ) : $default; } $taxonomies = get_object_taxonomies( $post_type, 'objects' ); foreach ( $taxonomies as $taxonomy ) { - if( $taxonomy->hierarchical ){ - $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); + if ( $taxonomy->hierarchical ) { + $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term_object->get_primary_term(); } } diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 673e6c03e55..06cbbc18fdb 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -86,7 +86,7 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metaData' => $this->get_metadata(), + 'metaData' => $this->get_metadata(), ]; } @@ -104,20 +104,20 @@ protected function get_metadata() { $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); $field_definitions = new WPSEO_Taxonomy_Fields(); $is_social_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); - $meta_prefix = 'wpseo_'; + $meta_prefix = 'wpseo_'; - foreach ($field_definitions->get( 'content' ) as $key => $field) { - $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + foreach ( $field_definitions->get( 'content' ) as $key => $field ) { + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { - foreach ($field_definitions->get( 'settings' ) as $key => $field) { - $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + foreach ( $field_definitions->get( 'settings' ) as $key => $field ) { + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } } if ( $is_social_enabled ) { - foreach ($field_definitions->get( 'social' ) as $key => $field) { - $metadata[$key] = $fields_presenter->get_field_value( $meta_prefix.$key ); + foreach ( $field_definitions->get( 'social' ) as $key => $field ) { + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } } From f4f4c36991f6509c7bedff15c72e99747cccde79 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:09:08 +0100 Subject: [PATCH 028/344] added value type to social fields --- inc/class-wpseo-meta.php | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 1072254740d..b669b9b8802 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -262,10 +262,13 @@ class WPSEO_Meta { * @var array */ private static $social_fields = [ - 'title' => 'hidden', - 'description' => 'hidden', - 'image' => 'hidden', - 'image-id' => 'hidden', + 'title' => [ 'type' => 'hidden' ], + 'description' => [ 'type' => 'hidden' ], + 'image' => [ 'type' => 'hidden' ], + 'image-id' => [ + 'type' => 'hidden', + 'value_type' => 'integer', + ], ]; /** @@ -280,9 +283,9 @@ public static function init() { self::$meta_fields['social'][ $network . '-' . $box ] = [ 'type' => $type, 'title' => '', // Translation added later. - 'show_in_rest' => true, 'default_value' => '', 'description' => '', // Translation added later. + 'value_type' => ( $type['value_type'] ?? 'string' ), ]; } } @@ -298,24 +301,23 @@ public static function init() { self::$meta_fields = self::array_merge_recursive_distinct( $extra_fields, self::$meta_fields ); } // register meta data for taxonomies. - $primay_terms[ 'primary_terms' ] = []; + $primay_terms['primary_terms'] = []; $taxonomies = get_taxonomies( [ 'hierarchical' => true ], 'names' ); foreach ( $taxonomies as $taxonomy_name ) { - $primay_terms[ 'primary_terms' ]['primary_' .$taxonomy_name ] = [ + $primay_terms['primary_terms'][ 'primary_' . $taxonomy_name ] = [ 'type' => 'hidden', - 'title' => '', + 'title' => '', 'default_value' => '', 'description' => '', - 'value_type' => 'integer' + 'value_type' => 'integer', ]; - } + } if ( $primay_terms && is_array( $primay_terms ) ) { self::$meta_fields = self::array_merge_recursive_distinct( $primay_terms, self::$meta_fields ); } - unset( $extra_fields ); foreach ( self::$meta_fields as $subset => $field_group ) { @@ -324,10 +326,11 @@ public static function init() { register_meta( 'post', self::$meta_prefix . $key, - [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], - 'show_in_rest' => true, - 'type' => $field_def[ "value_type" ] ?? 'string', - 'single' => true, + [ + 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], + 'show_in_rest' => true, + 'type' => ( $field_def['value_type'] ?? 'string' ), + 'single' => true, ] ); @@ -463,7 +466,7 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = self::$defaults[ $meta_key ]; switch ( true ) { - case ( $meta_key === self::$meta_prefix . 'linkdex' || $field_def[ 'value_type' ] === 'integer' || $field_def[ 'value_type' ] === 'number' ): + case ( $meta_key === self::$meta_prefix . 'linkdex' || $field_def['value_type'] === 'integer' || $field_def['value_type'] === 'number' ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int >= 0 ) { $clean = strval( $int ); // Convert to string to make sure default check works. From f33fc5b6170872606d499d3e53957abecedadc28 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:09:40 +0100 Subject: [PATCH 029/344] cleaned metabox sync class from sync to block editor --- .../js/src/helpers/fields/MetaboxFieldSync.js | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js index ebfbdae88c6..a762ae10807 100644 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -1,5 +1,3 @@ -import { dispatch } from "@wordpress/data"; - /** * This class is responsible for syncing hidden fields with store. */ @@ -105,27 +103,9 @@ export default class MetaboxFieldSync { static setFieldValue( fieldKey, value ) { const inputElement = this.getInputElement( fieldKey ); - try { - if ( inputElement ) { - inputElement.value = value ?? ""; - return; - } - } catch ( e ) { - // Do nothing. - } - - - // If Block Editor and a post - try { - const editPost = dispatch( "core/editor" ).editPost; - editPost( { - meta: { [ this.metaPrefix + fieldKey ]: value.toString() }, - } ); + if ( inputElement && inputElement.value ) { + inputElement.value = value ?? ""; return; - } catch ( e ) { - // Do nothing. } - - // If Site Editor } } From 6cdf883e4bda69355bada70830e36bff2245fafa Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:11:47 +0100 Subject: [PATCH 030/344] add block editor sync class --- packages/js/src/block-editor.js | 3 + packages/js/src/helpers/create-watcher.js | 19 ++++- .../js/src/helpers/fields/blockEditorSync.js | 76 +++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 packages/js/src/helpers/fields/blockEditorSync.js diff --git a/packages/js/src/block-editor.js b/packages/js/src/block-editor.js index 90426be4f27..e4874f5b8e3 100644 --- a/packages/js/src/block-editor.js +++ b/packages/js/src/block-editor.js @@ -1,8 +1,11 @@ /* eslint-disable no-unused-vars */ import initBlockEditorIntegration from "./initializers/block-editor-integration"; import BlockEditorData from "./analysis/blockEditorData"; +import blockEditorSync from "./helpers/fields/blockEditorSync"; window.yoast = window.yoast || {}; window.yoast.initEditorIntegration = initBlockEditorIntegration; window.yoast.EditorData = BlockEditorData; + +blockEditorSync(); /* eslint-enable no-unused-vars */ diff --git a/packages/js/src/helpers/create-watcher.js b/packages/js/src/helpers/create-watcher.js index f856e745b5d..4eef8fa89b3 100644 --- a/packages/js/src/helpers/create-watcher.js +++ b/packages/js/src/helpers/create-watcher.js @@ -1,4 +1,4 @@ -import { clone, isEqual } from "lodash"; +import { clone, isEqual, reduce } from "lodash"; /** * Creates a getter for an array of getters. @@ -40,4 +40,21 @@ const createWatcher = ( getData, onChange ) => { }; }; +/** + * Creates a getter for an object of getters. + * + * Use this if you want to combine getData functions. + * + * @param {Object} getters The getters. + * @returns {function} The combined getter. + */ +export const createCollectorFromObject = ( getters ) => () => reduce( + getters, + ( result, getData, key ) => { + result[ key ] = getData(); + return result; + }, + {} +); + export default createWatcher; diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js new file mode 100644 index 00000000000..450bbc69c2d --- /dev/null +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -0,0 +1,76 @@ + +import { dispatch, select, subscribe } from "@wordpress/data"; +import { debounce, forEach, pickBy } from "lodash"; +import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; + +const METADATA_IDS = { + focusKeyphrase: "_yoast_wpseo_focuskw", + facebookImageId: "_yoast_wpseo_opengraph-image-id", +}; + +const SYNC_TIME = { + wait: 1500, + max: 3000, +}; + +/** + * Retrieves the focus keyphrase. + * @returns {string} The focus keyphrase. + */ +const getFocusKeyphrase = () => select( "yoast-seo/editor" )?.getFocusKeyphrase(); + +/** + * Retrieve facebook image id. + * @returns {string} The facebook image id. + */ +const getFacebookImageId = () => select( "yoast-seo/editor" )?.getFacebookImageId(); + +/** + * Creates an updater. + * @returns {function} The updater. + */ +const createUpdater = () => { + const { editPost } = dispatch( "core/editor" ); + + /** + * Syncs the data to the WP entity record. + * @param {Object} data The collected data. + * @returns {void} + */ + return ( data ) => { + // Unfortunately, we need to pass the full metadata to update a part of it. + const metadata = select( "core/editor" ).getCurrentPost().meta; + if ( ! metadata || ! data ) { + return; + } + + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + + if ( changedData ) { + const newMetadata = {}; + forEach( changedData, ( value, key ) => { + newMetadata[ METADATA_IDS[ key ] ] = value; + } ); + // eslint-disable-next-line camelcase + editPost( { + meta: newMetadata, + } ); + } + }; +}; + +/** + * Initializes the sync: from Yoast editor store to product metadata. + * @returns {function} The un-subscriber. + */ +const blockEditorSync = () => { + return subscribe( debounce( createWatcher( + createCollectorFromObject( { + focusKeyphrase: getFocusKeyphrase, + facebookImageId: getFacebookImageId, + } ), + createUpdater() + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), "yoast-seo/editor" ); +}; + +export default blockEditorSync; From 563cc73bc04d9c55ba0cf8fdfdb7f95fad992761 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:27:02 +0100 Subject: [PATCH 031/344] Add constants in separate folder --- packages/js/src/constants/index.js | 2 ++ packages/js/src/constants/stores.js | 3 +++ packages/js/src/constants/sync.js | 9 +++++++++ 3 files changed, 14 insertions(+) create mode 100644 packages/js/src/constants/index.js create mode 100644 packages/js/src/constants/stores.js create mode 100644 packages/js/src/constants/sync.js diff --git a/packages/js/src/constants/index.js b/packages/js/src/constants/index.js new file mode 100644 index 00000000000..6fcf3304728 --- /dev/null +++ b/packages/js/src/constants/index.js @@ -0,0 +1,2 @@ +export * from "./stores"; +export * from "./sync"; diff --git a/packages/js/src/constants/stores.js b/packages/js/src/constants/stores.js new file mode 100644 index 00000000000..d32364b3425 --- /dev/null +++ b/packages/js/src/constants/stores.js @@ -0,0 +1,3 @@ +export const STORE = "yoast-seo/editor"; + +export const CORE_EDITOR_STORE = "yoast-seo"; diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js new file mode 100644 index 00000000000..6b0b234df81 --- /dev/null +++ b/packages/js/src/constants/sync.js @@ -0,0 +1,9 @@ +export const METADATA_IDS = { + focusKeyphrase: "_yoast_wpseo_focuskw", + facebookImageId: "_yoast_wpseo_opengraph-image-id", +}; + +export const SYNC_TIME = { + wait: 1500, + max: 3000, +}; From 14cdb272457a12c7a9db69408c150a63c61df85c Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 16:27:32 +0100 Subject: [PATCH 032/344] Apply constants from new constant folder --- .../js/src/helpers/fields/blockEditorSync.js | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 450bbc69c2d..e4256da1f7e 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -2,35 +2,26 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; - -const METADATA_IDS = { - focusKeyphrase: "_yoast_wpseo_focuskw", - facebookImageId: "_yoast_wpseo_opengraph-image-id", -}; - -const SYNC_TIME = { - wait: 1500, - max: 3000, -}; +import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; /** * Retrieves the focus keyphrase. * @returns {string} The focus keyphrase. */ -const getFocusKeyphrase = () => select( "yoast-seo/editor" )?.getFocusKeyphrase(); +const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); /** * Retrieve facebook image id. * @returns {string} The facebook image id. */ -const getFacebookImageId = () => select( "yoast-seo/editor" )?.getFacebookImageId(); +const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); /** * Creates an updater. * @returns {function} The updater. */ const createUpdater = () => { - const { editPost } = dispatch( "core/editor" ); + const { editPost } = dispatch( CORE_EDITOR_STORE ); /** * Syncs the data to the WP entity record. @@ -39,7 +30,7 @@ const createUpdater = () => { */ return ( data ) => { // Unfortunately, we need to pass the full metadata to update a part of it. - const metadata = select( "core/editor" ).getCurrentPost().meta; + const metadata = select( CORE_EDITOR_STORE ).getCurrentPost().meta; if ( ! metadata || ! data ) { return; } @@ -70,7 +61,7 @@ const blockEditorSync = () => { facebookImageId: getFacebookImageId, } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), "yoast-seo/editor" ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); }; export default blockEditorSync; From 18c2ab4ad94c7e9a98ee33620a811b754212804c Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Fri, 16 Feb 2024 17:15:30 +0100 Subject: [PATCH 033/344] Specify value type for meta-robots-noindex --- inc/class-wpseo-meta.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index b669b9b8802..e67b8691cca 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -160,6 +160,7 @@ class WPSEO_Meta { '2' => '', // Index - translation added later. '1' => '', // No-index - translation added later. ], + 'value_type' => 'integer', ], 'meta-robots-nofollow' => [ 'type' => 'hidden', From 5a1e8241ab0c60fd7e0931647ea0a3557cf9d222 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Fri, 16 Feb 2024 17:15:51 +0100 Subject: [PATCH 034/344] Sync meta-robots-noindex value --- packages/js/src/constants/sync.js | 1 + packages/js/src/helpers/fields/blockEditorSync.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 6b0b234df81..3e8b47fbbc3 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -1,6 +1,7 @@ export const METADATA_IDS = { focusKeyphrase: "_yoast_wpseo_focuskw", facebookImageId: "_yoast_wpseo_opengraph-image-id", + noIndex: "_yoast_wpseo_meta-robots-noindex", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index e4256da1f7e..bb7afa25a06 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -16,6 +16,8 @@ const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); */ const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); +const getNoIndex = () => select( STORE )?.getNoIndex(); + /** * Creates an updater. * @returns {function} The updater. @@ -59,6 +61,7 @@ const blockEditorSync = () => { createCollectorFromObject( { focusKeyphrase: getFocusKeyphrase, facebookImageId: getFacebookImageId, + noIndex: getNoIndex, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); From 96f1a7b1b2d7947466fa981bed9c7595f006e8d1 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:00:34 +0100 Subject: [PATCH 035/344] fix constant --- packages/js/src/constants/stores.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/constants/stores.js b/packages/js/src/constants/stores.js index d32364b3425..41605a3f524 100644 --- a/packages/js/src/constants/stores.js +++ b/packages/js/src/constants/stores.js @@ -1,3 +1,3 @@ export const STORE = "yoast-seo/editor"; -export const CORE_EDITOR_STORE = "yoast-seo"; +export const CORE_EDITOR_STORE = "core/editor"; From ef0f6317928cb68e518b5fd1baf4c819e7c603e8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:00:52 +0100 Subject: [PATCH 036/344] export helpers with index file --- packages/js/src/helpers/fields/index.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 packages/js/src/helpers/fields/index.js diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js new file mode 100644 index 00000000000..7a946717eda --- /dev/null +++ b/packages/js/src/helpers/fields/index.js @@ -0,0 +1,2 @@ +export * from "./hasHiddenFields"; +export * from "./blockEditorSync"; From 211353a27dccbc99cf86807b0c129a4c9a860428 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:01:23 +0100 Subject: [PATCH 037/344] add selector for facebook image id --- packages/js/src/redux/selectors/facebookEditor.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/js/src/redux/selectors/facebookEditor.js b/packages/js/src/redux/selectors/facebookEditor.js index 20518c26342..792ea9521e3 100644 --- a/packages/js/src/redux/selectors/facebookEditor.js +++ b/packages/js/src/redux/selectors/facebookEditor.js @@ -47,6 +47,15 @@ export const getFacebookImageUrl = state => get( state, "facebookEditor.image.ur */ export const getFacebookImageSrc = state => get( state, "facebookEditor.image.src", "" ); +/** + * Gets the facebook image id from the state. + * + * @param {Object} state The state. + * + * @returns {integer} Facebook image id. + */ +export const getFacebookImageId = state => get( state, "facebookEditor.image.id", "" ); + /** * Gets the facebook alt text from the state. * From c27df592604917db521d7d20fe232e5db122b802 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:01:52 +0100 Subject: [PATCH 038/344] get initial focus keyphrase --- packages/js/src/initializers/post-scraper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index 1738b0df978..5b6439347b2 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -2,7 +2,7 @@ // External dependencies. import { App } from "yoastseo"; -import { debounce, isUndefined } from "lodash"; +import { debounce, isUndefined, get } from "lodash"; import { isShallowEqualObjects } from "@wordpress/is-shallow-equal"; import { select, subscribe } from "@wordpress/data"; @@ -256,8 +256,8 @@ export default function initPostScraper( $, store, editorData ) { }; if ( isKeywordAnalysisActive() ) { - const focuskw = getFocusKeyphrase(); - store.dispatch( focuskw ); + const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + store.dispatch( setFocusKeyword( metaData.focuskw ) ); args.callbacks.saveScores = postDataCollector.saveScores.bind( postDataCollector ); From b410d5a8f9dbe6bf0ba794f01c0e78df88f7a1d0 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:02:24 +0100 Subject: [PATCH 039/344] fix export og block editor sync --- packages/js/src/helpers/fields/blockEditorSync.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index bb7afa25a06..3bdbc8155bc 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -16,6 +16,11 @@ const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); */ const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); +/** + * Retrieves the no index value. + * + * @returns {integer} The no index value. + */ const getNoIndex = () => select( STORE )?.getNoIndex(); /** @@ -56,7 +61,7 @@ const createUpdater = () => { * Initializes the sync: from Yoast editor store to product metadata. * @returns {function} The un-subscriber. */ -const blockEditorSync = () => { +export const blockEditorSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { focusKeyphrase: getFocusKeyphrase, @@ -66,5 +71,3 @@ const blockEditorSync = () => { createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); }; - -export default blockEditorSync; From acad0f6600588af96a0cbfcd768789448fd74510 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:02:54 +0100 Subject: [PATCH 040/344] import helper functions from index --- packages/js/src/block-editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/js/src/block-editor.js b/packages/js/src/block-editor.js index e4874f5b8e3..d03c8c33946 100644 --- a/packages/js/src/block-editor.js +++ b/packages/js/src/block-editor.js @@ -1,11 +1,14 @@ /* eslint-disable no-unused-vars */ import initBlockEditorIntegration from "./initializers/block-editor-integration"; import BlockEditorData from "./analysis/blockEditorData"; -import blockEditorSync from "./helpers/fields/blockEditorSync"; +import { blockEditorSync, hasHiddenFields } from "./helpers/fields"; window.yoast = window.yoast || {}; window.yoast.initEditorIntegration = initBlockEditorIntegration; window.yoast.EditorData = BlockEditorData; +// console.log( hasHiddenFields() ); +// if ( hasHiddenFields() ) { blockEditorSync(); +// } /* eslint-enable no-unused-vars */ From b34660a3530b241906d166b33292b3af1979f8ba Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:03:13 +0100 Subject: [PATCH 041/344] fix register of social meta data --- inc/class-wpseo-meta.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index e67b8691cca..a77ba0f6d0c 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -160,7 +160,7 @@ class WPSEO_Meta { '2' => '', // Index - translation added later. '1' => '', // No-index - translation added later. ], - 'value_type' => 'integer', + 'value_type' => 'integer', ], 'meta-robots-nofollow' => [ 'type' => 'hidden', @@ -280,13 +280,13 @@ class WPSEO_Meta { public static function init() { foreach ( self::$social_networks as $option => $network ) { if ( WPSEO_Options::get( $option, false ) === true ) { - foreach ( self::$social_fields as $box => $type ) { + foreach ( self::$social_fields as $box => $field_def ) { self::$meta_fields['social'][ $network . '-' . $box ] = [ - 'type' => $type, + 'type' => $field_def['type'], 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - 'value_type' => ( $type['value_type'] ?? 'string' ), + 'value_type' => ( $field_def['value_type'] ?? 'string' ), ]; } } From a62dd66985b95b3860b15b90657bf88e8c036449 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:03:55 +0100 Subject: [PATCH 042/344] WIP to check if hidden fields are there to avoid sync --- .../js/src/helpers/fields/hasHiddenFields.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/js/src/helpers/fields/hasHiddenFields.js diff --git a/packages/js/src/helpers/fields/hasHiddenFields.js b/packages/js/src/helpers/fields/hasHiddenFields.js new file mode 100644 index 00000000000..27486e9cbfa --- /dev/null +++ b/packages/js/src/helpers/fields/hasHiddenFields.js @@ -0,0 +1,18 @@ +/** + * Check if an element has hidden fields in order to use the block editor sync to core store. + * + * @returns {boolean} True if the element has hidden fields. + */ +export const hasHiddenFields = () => { + var element = document.getElementById( "wpseo_meta" ); + console.log( element ); + if ( element ) { + var inputs = element.getElementsByTagName( "input" ); + for ( var i = 0; i < inputs.length; i++ ) { + if ( inputs[ i ].type === "hidden" ) { + return true; + } + } + } + return false; +}; From 35b405d20c05819d5731a755979a5dc80fc7c70c Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:04:53 +0100 Subject: [PATCH 043/344] fixed method to get value from store --- packages/js/src/analysis/PostDataCollector.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 0ae63992cae..0f1dd0e5029 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -16,6 +16,8 @@ import getIndicatorForScore from "./getIndicatorForScore"; import isKeywordAnalysisActive from "./isKeywordAnalysisActive"; import isContentAnalysisActive from "./isContentAnalysisActive"; +import { STORE } from "../constants"; + const { tmceId } = tmceHelper; const $ = jQuery; /** @@ -80,8 +82,7 @@ PostDataCollector.prototype.getData = function() { * @returns {string} The keyword. */ PostDataCollector.prototype.getKeyword = function() { - const store = select( "yoast-seo/editor" ); - const keyword = store.getFocusKeyword(); + const keyword = select( STORE ).getFocusKeyphrase(); return keyword; }; @@ -101,12 +102,12 @@ PostDataCollector.prototype.getMetaDescForAnalysis = function( state ) { }; /** - * Returns the Meta from the DOM. + * Returns the Meta from the Store. * * @returns {string} The meta description. */ PostDataCollector.prototype.getMeta = function() { - return document.getElementById( "yoast_wpseo_metadesc" ) && document.getElementById( "yoast_wpseo_metadesc" ).value || ""; + return select( STORE ).getDescription(); }; /** From 10c93247f43588347e195cc52f22e4aeea9df8d5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:05:27 +0100 Subject: [PATCH 044/344] WIP add defensive coding need to add listener to changes in store --- packages/yoastseo/src/app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/yoastseo/src/app.js b/packages/yoastseo/src/app.js index 5b051e3088b..c049fb16c4a 100644 --- a/packages/yoastseo/src/app.js +++ b/packages/yoastseo/src/app.js @@ -573,7 +573,9 @@ App.prototype.initAssessorPresenters = function() { App.prototype.bindInputEvent = function() { for ( var i = 0; i < this.config.elementTarget.length; i++ ) { var elem = document.getElementById( this.config.elementTarget[ i ] ); - elem.addEventListener( "input", this.refresh.bind( this ) ); + if ( elem ) { + elem.addEventListener( "input", this.refresh.bind( this ) ); + } } }; From 6633efb9cb451c912c48e21c6d96157b73df94b2 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:26:43 +0100 Subject: [PATCH 045/344] WIP adding primary category to block editor sync --- packages/js/src/constants/sync.js | 1 + packages/js/src/helpers/fields/blockEditorSync.js | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 3e8b47fbbc3..7170cddef60 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -2,6 +2,7 @@ export const METADATA_IDS = { focusKeyphrase: "_yoast_wpseo_focuskw", facebookImageId: "_yoast_wpseo_opengraph-image-id", noIndex: "_yoast_wpseo_meta-robots-noindex", + primaryCategory: "_yoast_wpseo_primary_category", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 3bdbc8155bc..eb3fc55f988 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -23,6 +23,13 @@ const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); */ const getNoIndex = () => select( STORE )?.getNoIndex(); +/** + * Retrieves the no index value. + * + * @returns {integer} The no index value. + */ +const getPrimaryTaxonomyId = () => select( STORE )?.getPrimaryTaxonomyId( "category" ); + /** * Creates an updater. * @returns {function} The updater. @@ -67,6 +74,7 @@ export const blockEditorSync = () => { focusKeyphrase: getFocusKeyphrase, facebookImageId: getFacebookImageId, noIndex: getNoIndex, + primaryCategory: getPrimaryTaxonomyId, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); From 5a1c21f87217d43e85ed45bb735959386f38411d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 18:33:48 +0100 Subject: [PATCH 046/344] refactor value_type when registering meta --- inc/class-wpseo-meta.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index a77ba0f6d0c..d8ef78cfa0a 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -286,7 +286,7 @@ public static function init() { 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - 'value_type' => ( $field_def['value_type'] ?? 'string' ), + 'value_type' => $field_def['value_type'] ?? 'string', ]; } } @@ -323,14 +323,14 @@ public static function init() { foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { - + $value_type = isset( $field_def[ 'value_type' ] ) ? $field_def[ 'value_type' ] : 'string'; register_meta( 'post', self::$meta_prefix . $key, [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], 'show_in_rest' => true, - 'type' => ( $field_def['value_type'] ?? 'string' ), + 'type' => $value_type, 'single' => true, ] ); From 2ef0aad41bb3104e78d562688e2517885ff39cc9 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 16 Feb 2024 20:01:13 +0100 Subject: [PATCH 047/344] fixed value type one wrong type prevents saving of all, to see the error, add break point at line 193 in core file wp-includes/rest-api/fields/class-wp-rest-meta-fields.php --- inc/class-wpseo-meta.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index d8ef78cfa0a..541d42d4f99 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -160,7 +160,6 @@ class WPSEO_Meta { '2' => '', // Index - translation added later. '1' => '', // No-index - translation added later. ], - 'value_type' => 'integer', ], 'meta-robots-nofollow' => [ 'type' => 'hidden', @@ -266,10 +265,7 @@ class WPSEO_Meta { 'title' => [ 'type' => 'hidden' ], 'description' => [ 'type' => 'hidden' ], 'image' => [ 'type' => 'hidden' ], - 'image-id' => [ - 'type' => 'hidden', - 'value_type' => 'integer', - ], + 'image-id' => [ 'type' => 'hidden' ], ]; /** @@ -286,7 +282,7 @@ public static function init() { 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - 'value_type' => $field_def['value_type'] ?? 'string', + 'value_type' => ( $field_def['value_type'] ?? 'string' ), ]; } } @@ -323,7 +319,7 @@ public static function init() { foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { - $value_type = isset( $field_def[ 'value_type' ] ) ? $field_def[ 'value_type' ] : 'string'; + $value_type = isset( $field_def['value_type'] ) ? $field_def['value_type'] : 'string'; register_meta( 'post', self::$meta_prefix . $key, From 0ed3046c19d2f29ded8b82b201972c3864d6b026 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 19 Feb 2024 13:48:33 +0100 Subject: [PATCH 048/344] fix facebook sync --- inc/class-wpseo-meta.php | 2 +- packages/js/src/constants/sync.js | 5 +++- .../js/src/helpers/fields/blockEditorSync.js | 18 +++++++------ .../src/helpers/fields/facebookFieldsStore.js | 27 +++++++++++++++++++ packages/js/src/initializers/editor-store.js | 4 --- .../js/src/redux/actions/facebookEditor.js | 2 +- 6 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 packages/js/src/helpers/fields/facebookFieldsStore.js diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 541d42d4f99..dc3556b3173 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -265,7 +265,7 @@ class WPSEO_Meta { 'title' => [ 'type' => 'hidden' ], 'description' => [ 'type' => 'hidden' ], 'image' => [ 'type' => 'hidden' ], - 'image-id' => [ 'type' => 'hidden' ], + 'image-id' => [ 'type' => 'hidden', 'value_type' => 'integer' ], ]; /** diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 7170cddef60..8f87dfe4fdb 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -1,8 +1,11 @@ export const METADATA_IDS = { focusKeyphrase: "_yoast_wpseo_focuskw", - facebookImageId: "_yoast_wpseo_opengraph-image-id", noIndex: "_yoast_wpseo_meta-robots-noindex", primaryCategory: "_yoast_wpseo_primary_category", + facebookTitle: "_yoast_wpseo_opengraph-title", + facebookDescription: "_yoast_wpseo_opengraph-description", + facebookImageUrl: "_yoast_wpseo_opengraph-image", + facebookImageId: "_yoast_wpseo_opengraph-image-id", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index eb3fc55f988..adf7039c0a3 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -3,6 +3,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; +import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; /** * Retrieves the focus keyphrase. @@ -10,11 +11,6 @@ import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constan */ const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); -/** - * Retrieve facebook image id. - * @returns {string} The facebook image id. - */ -const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); /** * Retrieves the no index value. @@ -30,6 +26,7 @@ const getNoIndex = () => select( STORE )?.getNoIndex(); */ const getPrimaryTaxonomyId = () => select( STORE )?.getPrimaryTaxonomyId( "category" ); + /** * Creates an updater. * @returns {function} The updater. @@ -48,15 +45,17 @@ const createUpdater = () => { if ( ! metadata || ! data ) { return; } + console.log( data ); + console.log( metadata ); - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { newMetadata[ METADATA_IDS[ key ] ] = value; } ); - // eslint-disable-next-line camelcase + editPost( { meta: newMetadata, } ); @@ -72,9 +71,12 @@ export const blockEditorSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { focusKeyphrase: getFocusKeyphrase, - facebookImageId: getFacebookImageId, noIndex: getNoIndex, primaryCategory: getPrimaryTaxonomyId, + facebookTitle: getFacebookTitle, + facebookDescription: getFacebookDescription, + facebookImageUrl: getFacebookImageUrl, + facebookImageId: getFacebookImageId, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js new file mode 100644 index 00000000000..40f1137c5e3 --- /dev/null +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -0,0 +1,27 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Retrieve facebook image id. + * @returns {integer} The facebook image id. + */ +export const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); + +/** + * Get facebook title. + * @returns {string} The facebook title. + */ +export const getFacebookTitle = () => select( STORE )?.getFacebookTitle(); + +/** + * Get facebook description. + * @returns {string} The facebook description. + */ +export const getFacebookDescription = () => select( STORE )?.getFacebookDescription(); + +/** + * Get facebook image Url. + * @returns {string} The facebook image Url. + */ +export const getFacebookImageUrl = () => select( STORE )?.getFacebookImageUrl(); + diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index caaf6d00ff4..7a493f9f911 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -31,10 +31,6 @@ const populateStore = store => { const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); - store.dispatch( actions.setFacebookPreviewTitle( metaData[ "opengraph-title" ] ) ); - store.dispatch( actions.setFacebookPreviewDescription( metaData[ "opengraph-description" ] ) ); - store.dispatch( actions.setFacebookPreviewImage( { url: metaData[ "opengraph-image" ], id: metaData[ "opengraph-image-id" ] } ) ); - store.dispatch( actions.setTwitterPreviewTitle( metaData[ "twitter-title" ] ) ); store.dispatch( actions.setTwitterPreviewDescription( metaData[ "twitter-description" ] ) ); store.dispatch( actions.setTwitterPreviewImage( { url: metaData[ "twitter-image" ], id: metaData[ "twitter-image-id" ] } ) ); diff --git a/packages/js/src/redux/actions/facebookEditor.js b/packages/js/src/redux/actions/facebookEditor.js index a4597c7dcd9..f7d4fc1a724 100644 --- a/packages/js/src/redux/actions/facebookEditor.js +++ b/packages/js/src/redux/actions/facebookEditor.js @@ -82,7 +82,7 @@ export const loadFacebookPreviewData = () => { return { type: LOAD_FACEBOOK_PREVIEW, - imageId: MetaboxFieldSync.getInitialValue( "opengraph-image-id" ), + imageId: Number( MetaboxFieldSync.getInitialValue( "opengraph-image-id" ) ), imageUrl: MetaboxFieldSync.getInitialValue( "opengraph-image" ), description: MetaboxFieldSync.getInitialValue( "opengraph-description" ) || getSocialDescriptionTemplate(), title: MetaboxFieldSync.getInitialValue( "opengraph-title" ) || getSocialTitleTemplate(), From cbde59676e64fac2fbba18feea5c50e00cf886e1 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Mon, 19 Feb 2024 17:02:02 +0100 Subject: [PATCH 049/344] Keep image-id as string --- inc/class-wpseo-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index dc3556b3173..541d42d4f99 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -265,7 +265,7 @@ class WPSEO_Meta { 'title' => [ 'type' => 'hidden' ], 'description' => [ 'type' => 'hidden' ], 'image' => [ 'type' => 'hidden' ], - 'image-id' => [ 'type' => 'hidden', 'value_type' => 'integer' ], + 'image-id' => [ 'type' => 'hidden' ], ]; /** From 36a3d6e21739baaf51d23523444b6c5390b6d406 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Mon, 19 Feb 2024 17:02:44 +0100 Subject: [PATCH 050/344] Add nofollow to sync fields --- packages/js/src/constants/sync.js | 1 + packages/js/src/helpers/fields/blockEditorSync.js | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 8f87dfe4fdb..5a34ce68bc1 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -1,6 +1,7 @@ export const METADATA_IDS = { focusKeyphrase: "_yoast_wpseo_focuskw", noIndex: "_yoast_wpseo_meta-robots-noindex", + noFollow: "_yoast_wpseo_meta-robots-nofollow", primaryCategory: "_yoast_wpseo_primary_category", facebookTitle: "_yoast_wpseo_opengraph-title", facebookDescription: "_yoast_wpseo_opengraph-description", diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index adf7039c0a3..88d8f399c9f 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -17,7 +17,14 @@ const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); * * @returns {integer} The no index value. */ -const getNoIndex = () => select( STORE )?.getNoIndex(); +const getNoIndex = () => String( select( STORE )?.getNoIndex() ); + +/** + * Retrieves the no follow value. + * + * @returns {integer} The no follow value. + */ +const getNoFollow = () => String( select( STORE )?.getNoFollow() ); /** * Retrieves the no index value. @@ -45,10 +52,11 @@ const createUpdater = () => { if ( ! metadata || ! data ) { return; } - console.log( data ); - console.log( metadata ); + console.log( { data } ); + console.log( { metadata } ); const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + console.log( { changedData } ); if ( changedData ) { const newMetadata = {}; @@ -72,6 +80,7 @@ export const blockEditorSync = () => { createCollectorFromObject( { focusKeyphrase: getFocusKeyphrase, noIndex: getNoIndex, + noFollow: getNoFollow, primaryCategory: getPrimaryTaxonomyId, facebookTitle: getFacebookTitle, facebookDescription: getFacebookDescription, From f54deecf834e90b30669516a7c3c80965ef483b1 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Mon, 19 Feb 2024 17:03:07 +0100 Subject: [PATCH 051/344] Cast nofollow to string --- packages/js/src/redux/actions/advancedSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index f345b39dea8..365d119dd0a 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -29,7 +29,7 @@ export const setNoIndex = ( value ) => { */ export const setNoFollow = ( value ) => { MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_meta-robots-nofollow", value ); - return { type: SET_NO_FOLLOW, value }; + return { type: SET_NO_FOLLOW, value: String( value ) }; }; /** From 152dd3e24fad462b35c5457f03f1e0f87d483478 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Mon, 19 Feb 2024 17:03:22 +0100 Subject: [PATCH 052/344] Change nofollow and noindex default values to "0" --- packages/js/src/redux/selectors/advancedSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/selectors/advancedSettings.js b/packages/js/src/redux/selectors/advancedSettings.js index 41775c3f20d..15d02fbec92 100644 --- a/packages/js/src/redux/selectors/advancedSettings.js +++ b/packages/js/src/redux/selectors/advancedSettings.js @@ -7,7 +7,7 @@ import { get } from "lodash"; * * @returns {String} Twitter title. */ -export const getNoIndex = state => get( state, "advancedSettings.noIndex", "" ); +export const getNoIndex = state => get( state, "advancedSettings.noIndex", "0" ); /** * Gets the twitter description from the state. @@ -16,7 +16,7 @@ export const getNoIndex = state => get( state, "advancedSettings.noIndex", "" ); * * @returns {String} Twitter description. */ -export const getNoFollow = state => get( state, "advancedSettings.noFollow", "" ); +export const getNoFollow = state => get( state, "advancedSettings.noFollow", "0" ); /** * Gets the twitter image URL from the state. From 5133e248a66dde1d2c32e0bff898841ea8e68f29 Mon Sep 17 00:00:00 2001 From: Paolo Luigi Scala Date: Tue, 20 Feb 2024 10:41:47 +0100 Subject: [PATCH 053/344] Add twitter fields --- packages/js/src/constants/sync.js | 4 +++ .../js/src/helpers/fields/blockEditorSync.js | 5 ++++ .../src/helpers/fields/twitterFieldsStore.js | 27 +++++++++++++++++++ .../js/src/redux/selectors/twitterEditor.js | 9 +++++++ 4 files changed, 45 insertions(+) create mode 100644 packages/js/src/helpers/fields/twitterFieldsStore.js diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 5a34ce68bc1..bac1e2fe7f5 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -7,6 +7,10 @@ export const METADATA_IDS = { facebookDescription: "_yoast_wpseo_opengraph-description", facebookImageUrl: "_yoast_wpseo_opengraph-image", facebookImageId: "_yoast_wpseo_opengraph-image-id", + twitterTitle: "_yoast_wpseo_twitter-title", + twitterDescription: "_yoast_wpseo_twitter-description", + twitterImageUrl: "_yoast_wpseo_twitter-image", + twitterImageId: "_yoast_wpseo_twitter-image-id", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 88d8f399c9f..d1eda40506b 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -4,6 +4,7 @@ import { debounce, forEach, pickBy } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; +import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; /** * Retrieves the focus keyphrase. @@ -86,6 +87,10 @@ export const blockEditorSync = () => { facebookDescription: getFacebookDescription, facebookImageUrl: getFacebookImageUrl, facebookImageId: getFacebookImageId, + twitterTitle: getTwitterTitle, + twitterDescription: getTwitterDescription, + twitterImageUrl: getTwitterImageUrl, + twitterImageId: getTwitterImageId, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js new file mode 100644 index 00000000000..e407aa6314d --- /dev/null +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -0,0 +1,27 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Retrieve twitter image id. + * @returns {integer} The twitter image id. + */ +export const getTwitterImageId = () => select( STORE )?.getTwitterImageId(); + +/** + * Get twitter title. + * @returns {string} The twitter title. + */ +export const getTwitterTitle = () => select( STORE )?.getTwitterTitle(); + +/** + * Get twitter description. + * @returns {string} The twitter description. + */ +export const getTwitterDescription = () => select( STORE )?.getTwitterDescription(); + +/** + * Get twitter image Url. + * @returns {string} The twitter image Url. + */ +export const getTwitterImageUrl = () => select( STORE )?.getTwitterImageUrl(); + diff --git a/packages/js/src/redux/selectors/twitterEditor.js b/packages/js/src/redux/selectors/twitterEditor.js index 90ed071179b..8b1095a5b54 100644 --- a/packages/js/src/redux/selectors/twitterEditor.js +++ b/packages/js/src/redux/selectors/twitterEditor.js @@ -57,6 +57,15 @@ export const getTwitterImageType = state => get( state, "settings.socialPreviews */ export const getTwitterImageSrc = state => get( state, "twitterEditor.image.src", "" ); +/** + * Gets the twitter image id from the state. + * + * @param {Object} state The state. + * + * @returns {integer} Twitter image id. + */ +export const getTwitterImageId = state => get( state, "twitterEditor.image.id", "" ).toString(); + /** * Gets the Twitter alt text from the state. * From 8abb49509e65dec8c41c9a4525493c3046d111d8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 13:09:25 +0100 Subject: [PATCH 054/344] keep value type as string --- inc/class-wpseo-meta.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 541d42d4f99..cd425b5a4f4 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -282,7 +282,6 @@ public static function init() { 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - 'value_type' => ( $field_def['value_type'] ?? 'string' ), ]; } } @@ -307,7 +306,6 @@ public static function init() { 'title' => '', 'default_value' => '', 'description' => '', - 'value_type' => 'integer', ]; } @@ -319,14 +317,14 @@ public static function init() { foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { - $value_type = isset( $field_def['value_type'] ) ? $field_def['value_type'] : 'string'; + register_meta( 'post', self::$meta_prefix . $key, [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], 'show_in_rest' => true, - 'type' => $value_type, + 'type' => 'string', 'single' => true, ] ); @@ -463,7 +461,7 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = self::$defaults[ $meta_key ]; switch ( true ) { - case ( $meta_key === self::$meta_prefix . 'linkdex' || $field_def['value_type'] === 'integer' || $field_def['value_type'] === 'number' ): + case ( $meta_key === self::$meta_prefix . 'linkdex' ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int >= 0 ) { $clean = strval( $int ); // Convert to string to make sure default check works. From 4bcec2bc31d4ae0b0bf553389e6bb0f1df2c4e11 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 13:58:08 +0100 Subject: [PATCH 055/344] WIP should sync primary terms --- packages/js/src/helpers/fields/blockEditorSync.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index d1eda40506b..64cecf35c5b 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -32,7 +32,7 @@ const getNoFollow = () => String( select( STORE )?.getNoFollow() ); * * @returns {integer} The no index value. */ -const getPrimaryTaxonomyId = () => select( STORE )?.getPrimaryTaxonomyId( "category" ); +const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); /** @@ -50,19 +50,20 @@ const createUpdater = () => { return ( data ) => { // Unfortunately, we need to pass the full metadata to update a part of it. const metadata = select( CORE_EDITOR_STORE ).getCurrentPost().meta; + if ( ! metadata || ! data ) { return; } console.log( { data } ); console.log( { metadata } ); - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); console.log( { changedData } ); if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { - newMetadata[ METADATA_IDS[ key ] ] = value; + newMetadata[ METADATA_IDS[ key ] ] = String( value ); } ); editPost( { @@ -82,7 +83,7 @@ export const blockEditorSync = () => { focusKeyphrase: getFocusKeyphrase, noIndex: getNoIndex, noFollow: getNoFollow, - primaryCategory: getPrimaryTaxonomyId, + primaryCategory: getPrimaryCategoryId, facebookTitle: getFacebookTitle, facebookDescription: getFacebookDescription, facebookImageUrl: getFacebookImageUrl, From 6a825c0480feffecc7ad5a94870f85abf60f544a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 16:38:24 +0100 Subject: [PATCH 056/344] fixed schema fields, and refactor analysis fields --- .../class-post-metabox-formatter.php | 1 + packages/js/src/constants/sync.js | 3 ++ .../src/helpers/fields/analysisFieldsStore.js | 8 ++++ .../js/src/helpers/fields/blockEditorSync.js | 10 ++--- packages/js/src/helpers/fields/index.js | 3 ++ .../src/helpers/fields/schemaFieldsStore.js | 38 +++++++++++++++++++ packages/js/src/redux/actions/schemaTab.js | 14 +++---- 7 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 packages/js/src/helpers/fields/analysisFieldsStore.js create mode 100644 packages/js/src/helpers/fields/schemaFieldsStore.js diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index d3a4f0b6f62..e05be574015 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -348,6 +348,7 @@ protected function get_post_meta_data() { $default = ''; if ( isset( $meta_field['default'] ) ) { $default = $meta_field['default']; + $meta_data[ $key.'_default' ] = $default; } $meta_data[ $key ] = esc_attr( $meta_value ) ? esc_attr( $meta_value ) : $default; diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index bac1e2fe7f5..2d7792b97b0 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -11,6 +11,9 @@ export const METADATA_IDS = { twitterDescription: "_yoast_wpseo_twitter-description", twitterImageUrl: "_yoast_wpseo_twitter-image", twitterImageId: "_yoast_wpseo_twitter-image-id", + pageType: "_yoast_wpseo_schema_page_type", + articleType: "_yoast_wpseo_schema_article_type", + }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js new file mode 100644 index 00000000000..e64e4ac0ac0 --- /dev/null +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -0,0 +1,8 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Retrieves the focus keyphrase. + * @returns {string} The focus keyphrase. + */ +export const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 64cecf35c5b..d3e27fa1c93 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -5,12 +5,8 @@ import createWatcher, { createCollectorFromObject } from "../../helpers/create-w import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; - -/** - * Retrieves the focus keyphrase. - * @returns {string} The focus keyphrase. - */ -const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); +import { getPageType, getArticleType } from "./schemaFieldsStore"; +import { getFocusKeyphrase } from "./analysisFieldsStore"; /** @@ -92,6 +88,8 @@ export const blockEditorSync = () => { twitterDescription: getTwitterDescription, twitterImageUrl: getTwitterImageUrl, twitterImageId: getTwitterImageId, + pageType: getPageType, + articleType: getArticleType, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index 7a946717eda..8d25c76ff2d 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,2 +1,5 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; +export * from "./facebookFieldsStore"; +export * from "./twitterFieldsStore"; +export * from "./schemaFieldsStore"; diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js new file mode 100644 index 00000000000..6b0742565b3 --- /dev/null +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -0,0 +1,38 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Gets the defaultPageType from the state. + * + * @param {Object} state The state. + * + * @returns {String} Default page type. + */ +export const getDefaultPageType = () => select( STORE )?.getDefaultPageType(); + +/** + * Gets the pageType from the state. + * + * @param {Object} state The state. + * + * @returns {String} Page type. + */ +export const getPageType = () => select( STORE )?.getPageType(); + +/** + * Gets the defaultArticleType from the state. + * + * @param {Object} state The state. + * + * @returns {String} Default article type. + */ +export const getDefaultArticleType = () => select( STORE )?.getDefaultArticleType(); + +/** + * Gets the articleType from the state. + * + * @param {Object} state The state. + * + * @returns {String} Article type. + */ +export const getArticleType = () => select( STORE )?.getArticleType(); diff --git a/packages/js/src/redux/actions/schemaTab.js b/packages/js/src/redux/actions/schemaTab.js index 722a59d53ef..1ef197dd479 100644 --- a/packages/js/src/redux/actions/schemaTab.js +++ b/packages/js/src/redux/actions/schemaTab.js @@ -1,4 +1,4 @@ -import SchemaFields from "../../helpers/SchemaFields"; +import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; export const SET_PAGE_TYPE = "SET_PAGE_TYPE"; export const SET_ARTICLE_TYPE = "SET_ARTICLE_TYPE"; @@ -13,7 +13,7 @@ export const GET_SCHEMA_ARTICLE_DATA = "GET_SCHEMA_ARTICLE_DATA"; * @returns {object} The action object. */ export const setPageType = ( pageType ) => { - SchemaFields.pageType = pageType; + MetaboxFieldSync.setFieldValue( "schema_page_type", pageType ); return { type: SET_PAGE_TYPE, pageType }; }; @@ -25,7 +25,7 @@ export const setPageType = ( pageType ) => { * @returns {object} The action object. */ export const setArticleType = ( articleType ) => { - SchemaFields.articleType = articleType; + MetaboxFieldSync.setFieldValue( "schema_article_type", articleType ); return { type: SET_ARTICLE_TYPE, articleType }; }; @@ -37,8 +37,8 @@ export const setArticleType = ( articleType ) => { export const getSchemaPageData = () => { return { type: GET_SCHEMA_PAGE_DATA, - pageType: SchemaFields.pageType, - defaultPageType: SchemaFields.defaultPageType, + pageType: MetaboxFieldSync.getInitialValue( "schema_page_type" ), + defaultPageType: MetaboxFieldSync.getInitialValue( "schema_page_type_default" ), }; }; @@ -50,7 +50,7 @@ export const getSchemaPageData = () => { export const getSchemaArticleData = () => { return { type: GET_SCHEMA_ARTICLE_DATA, - articleType: SchemaFields.articleType, - defaultArticleType: SchemaFields.defaultArticleType, + articleType: MetaboxFieldSync.getInitialValue( "schema_article_type" ), + defaultArticleType: MetaboxFieldSync.getInitialValue( "schema_article_type_default" ), }; }; From 806e3ef41b57be6d0c3e877162528392e793b4eb Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 16:40:05 +0100 Subject: [PATCH 057/344] remove get defaults --- .../js/src/helpers/fields/schemaFieldsStore.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index 6b0742565b3..65a4df202df 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,15 +1,6 @@ import { select } from "@wordpress/data"; import { STORE } from "../../constants"; -/** - * Gets the defaultPageType from the state. - * - * @param {Object} state The state. - * - * @returns {String} Default page type. - */ -export const getDefaultPageType = () => select( STORE )?.getDefaultPageType(); - /** * Gets the pageType from the state. * @@ -19,15 +10,6 @@ export const getDefaultPageType = () => select( STORE )?.getDefaultPageType(); */ export const getPageType = () => select( STORE )?.getPageType(); -/** - * Gets the defaultArticleType from the state. - * - * @param {Object} state The state. - * - * @returns {String} Default article type. - */ -export const getDefaultArticleType = () => select( STORE )?.getDefaultArticleType(); - /** * Gets the articleType from the state. * From 9ade5992a2c7a7001e99dcfb2b3b9e5436c82202 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 17:01:21 +0100 Subject: [PATCH 058/344] add conent score and is corner stone to block editor sync --- packages/js/src/constants/sync.js | 2 ++ .../js/src/helpers/fields/analysisFieldsStore.js | 14 ++++++++++++++ packages/js/src/helpers/fields/blockEditorSync.js | 5 +++-- packages/js/src/helpers/fields/index.js | 4 +--- packages/js/src/redux/selectors/analysis.js | 8 ++++++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 2d7792b97b0..bd93594b1f8 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -13,6 +13,8 @@ export const METADATA_IDS = { twitterImageId: "_yoast_wpseo_twitter-image-id", pageType: "_yoast_wpseo_schema_page_type", articleType: "_yoast_wpseo_schema_article_type", + isCornerstone: "_yoast_wpseo_is_cornerstone", + contentScore: "_yoast_wpseo_content_score", }; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index e64e4ac0ac0..a8f5acefe69 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -6,3 +6,17 @@ import { STORE } from "../../constants"; * @returns {string} The focus keyphrase. */ export const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); + +/** + * Returns whether the current content is cornerstone content. + * + * @returns {string} Whether the current content is cornerstone content. + */ +export const isCornerstoneContent = () => select( STORE )?.isCornerstoneContent() ? "1" : "0"; + +/** + * Retrieves the content score. + * + * @returns {string} The content score. + */ +export const getContentScore = () => String( select( STORE )?.getContentScore() ); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index d3e27fa1c93..fa2b816ab1c 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -6,8 +6,7 @@ import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constan import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase } from "./analysisFieldsStore"; - +import { getFocusKeyphrase, isCornerstoneContent, getContentScore } from "./analysisFieldsStore"; /** * Retrieves the no index value. @@ -90,6 +89,8 @@ export const blockEditorSync = () => { twitterImageId: getTwitterImageId, pageType: getPageType, articleType: getArticleType, + isCornerstone: isCornerstoneContent, + contentScore: getContentScore, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index 8d25c76ff2d..e90ed53451d 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,5 +1,3 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; -export * from "./facebookFieldsStore"; -export * from "./twitterFieldsStore"; -export * from "./schemaFieldsStore"; + diff --git a/packages/js/src/redux/selectors/analysis.js b/packages/js/src/redux/selectors/analysis.js index 392f64747cc..0298fa51cfe 100644 --- a/packages/js/src/redux/selectors/analysis.js +++ b/packages/js/src/redux/selectors/analysis.js @@ -72,3 +72,11 @@ export const getAnalysisData = ( state ) => { permalink: getBaseUrlFromSettings( state ) + slug, }; }; + +/** + * Get content score. + * + * @param {Object} state The state. + * @returns {integer} The content score. + */ +export const getContentScore = ( state ) => get( state, "overallScore", "0" ); From ad69d37680b2539384884f2c02a1883a98900419 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 20 Feb 2024 18:29:17 +0100 Subject: [PATCH 059/344] update data collector --- packages/js/src/analysis/PostDataCollector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 0f1dd0e5029..ed634a5a21b 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -4,7 +4,7 @@ import { __ } from "@wordpress/i18n"; import { get } from "lodash"; import { markers } from "yoastseo"; -import { select } from "@wordpress/data"; +import { select, dispatch } from "@wordpress/data"; /* Internal dependencies */ import measureTextWidth from "../helpers/measureTextWidth"; @@ -415,7 +415,7 @@ PostDataCollector.prototype.saveContentScore = function( score ) { updateAdminBar( indicator ); } - $( "#yoast_wpseo_content_score" ).val( score ); + dispatch( STORE ).setOverallReadabilityScore( score ); }; /** From c6b9959bb7eaf17b54a4959ce69572cf403b7e72 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 21 Feb 2024 12:00:15 +0100 Subject: [PATCH 060/344] restore search metadata fields since it's for elementor --- .../elementor/redux/actions/snippetEditor.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/js/src/elementor/redux/actions/snippetEditor.js b/packages/js/src/elementor/redux/actions/snippetEditor.js index 5365001914c..435cecffc45 100644 --- a/packages/js/src/elementor/redux/actions/snippetEditor.js +++ b/packages/js/src/elementor/redux/actions/snippetEditor.js @@ -1,5 +1,5 @@ import { get } from "lodash"; -import MetaboxFieldSync from "../../../helpers/fields/MetaboxFieldSync"; +import SearchMetadataFields from "../../../helpers/fields/SearchMetadataFields"; import { actions } from "@yoast/externals/redux"; const { UPDATE_DATA, LOAD_SNIPPET_EDITOR_DATA } = actions; @@ -25,18 +25,19 @@ export function updateData( data ) { if ( data.title === get( window, "wpseoScriptData.metabox.title_template", "" ) ) { titleToBeSaved = ""; } - MetaboxFieldSync.setFieldValue( "metadesc", titleToBeSaved ); + + SearchMetadataFields.title = titleToBeSaved; } if ( data.hasOwnProperty( "description" ) ) { - const metaDescToBeSaved = data.description; + let metaDescToBeSaved = data.description; // Test whether this is actually the template, which we don't want to save. if ( data.description === get( window, "wpseoScriptData.metabox.metadesc_template", "" ) ) { - MetaboxFieldSync.setFieldValue( "metadesc", "" ); + metaDescToBeSaved = ""; } - MetaboxFieldSync.setFieldValue( "metadesc", metaDescToBeSaved ); + SearchMetadataFields.description = metaDescToBeSaved; } if ( data.hasOwnProperty( "slug" ) ) { - MetaboxFieldSync.setFieldValue( "slug", data.slug ); + SearchMetadataFields.slug = data.slug; } return { @@ -57,9 +58,9 @@ export const loadSnippetEditorData = () => { return { type: LOAD_SNIPPET_EDITOR_DATA, data: { - title: MetaboxFieldSync.getInitialValue( "title" ) || titleTemplate, - description: MetaboxFieldSync.getInitialValue( "metadesc" ) || descriptionTemplate, - slug: MetaboxFieldSync.getInitialValue( "slug" ), + title: SearchMetadataFields.title || titleTemplate, + description: SearchMetadataFields.description || descriptionTemplate, + slug: SearchMetadataFields.slug, }, templates: { title: titleTemplate, From 93f34d2038ae36007d24891a157c0fbbc1dd6f5a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 21 Feb 2024 13:46:30 +0100 Subject: [PATCH 061/344] decouple analysis scores --- packages/js/src/analysis/PostDataCollector.js | 2 +- packages/js/src/constants/sync.js | 4 +++- .../src/helpers/fields/analysisFieldsStore.js | 18 ++++++++++++++++-- .../js/src/helpers/fields/blockEditorSync.js | 7 +++++-- packages/js/src/initializers/post-scraper.js | 11 ++++++----- packages/js/src/redux/selectors/analysis.js | 8 -------- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index ed634a5a21b..3a4f0841a8e 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -434,7 +434,7 @@ PostDataCollector.prototype.saveInclusiveLanguageScore = function( score ) { updateAdminBar( indicator ); } - $( "#yoast_wpseo_inclusive_language_score" ).val( score ); + dispatch( STORE ).setOverallInclusiveLanguageScore( score ); }; diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index bd93594b1f8..fb7370a2da8 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -14,7 +14,9 @@ export const METADATA_IDS = { pageType: "_yoast_wpseo_schema_page_type", articleType: "_yoast_wpseo_schema_article_type", isCornerstone: "_yoast_wpseo_is_cornerstone", - contentScore: "_yoast_wpseo_content_score", + readabilityScore: "_yoast_wpseo_content_score", + seoScore: "_yoast_wpseo_linkdex", + inclusiveLanguageScore: "_yoast_wpseo_inclusive_language_score", }; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index a8f5acefe69..963ca4f27a9 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -15,8 +15,22 @@ export const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); export const isCornerstoneContent = () => select( STORE )?.isCornerstoneContent() ? "1" : "0"; /** - * Retrieves the content score. + * Retrieves the readability score. * * @returns {string} The content score. */ -export const getContentScore = () => String( select( STORE )?.getContentScore() ); +export const getReadabilityScore = () => String( select( STORE )?.getReadabilityResults()?.overallScore ); + +/** + * Retrieves the inclusive language score. + * + * @returns {string} The content score. + */ +export const getInclusiveLanguageScore = () => String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ); + +/** + * Retrieves the seo score. + * + * @returns {string} The content score. + */ +export const getSeoScore = () => String( select( STORE )?.getSeoResults().overallScore ); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index fa2b816ab1c..a91be9dd3d5 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -6,7 +6,7 @@ import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constan import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase, isCornerstoneContent, getContentScore } from "./analysisFieldsStore"; +import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; /** * Retrieves the no index value. @@ -90,7 +90,10 @@ export const blockEditorSync = () => { pageType: getPageType, articleType: getArticleType, isCornerstone: isCornerstoneContent, - contentScore: getContentScore, + readabilityScore: getReadabilityScore, + seoScore: getSeoScore, + inclusiveLanguageScore: getInclusiveLanguageScore, + } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index 5b6439347b2..b085ec62dc7 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -49,7 +49,6 @@ import { actions } from "@yoast/externals/redux"; // Helper dependencies. import isBlockEditor from "../helpers/isBlockEditor"; -import { getFocusKeyphrase } from "../redux/selectors/focusKeyPhrase.js"; const { setFocusKeyword, @@ -134,7 +133,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeKeywordAnalysis( activePublishBox ) { - const savedKeywordScore = $( "#yoast_wpseo_linkdex" ).val(); + const savedKeywordScore = get( window, "wpseoScriptData.metabox.metaData.linkdex", 0 ); const indicator = getIndicatorForScore( savedKeywordScore ); @@ -152,7 +151,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeContentAnalysis( activePublishBox ) { - const savedContentScore = $( "#yoast_wpseo_content_score" ).val(); + const savedContentScore = get( window, "wpseoScriptData.metabox.metaData.content_score", 0 ); const indicator = getIndicatorForScore( savedContentScore ); @@ -169,7 +168,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeInclusiveLanguageAnalysis( activePublishBox ) { - const savedContentScore = $( "#yoast_wpseo_inclusive_language_score" ).val(); + const savedContentScore = get( window, "wpseoScriptData.metabox.metaData.inclusive_language_score", 0 ); const indicator = getIndicatorForScore( savedContentScore ); @@ -409,8 +408,10 @@ export default function initPostScraper( $, store, editorData ) { handlePageBuilderCompatibility(); + const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + // Avoid error when snippet metabox is not rendered. - if ( metaboxContainer.length === 0 ) { + if ( metaboxContainer.length === 0 && metaData.length === 0 ) { return; } diff --git a/packages/js/src/redux/selectors/analysis.js b/packages/js/src/redux/selectors/analysis.js index 0298fa51cfe..392f64747cc 100644 --- a/packages/js/src/redux/selectors/analysis.js +++ b/packages/js/src/redux/selectors/analysis.js @@ -72,11 +72,3 @@ export const getAnalysisData = ( state ) => { permalink: getBaseUrlFromSettings( state ) + slug, }; }; - -/** - * Get content score. - * - * @param {Object} state The state. - * @returns {integer} The content score. - */ -export const getContentScore = ( state ) => get( state, "overallScore", "0" ); From 1fd24330de36b7ee86e4f8b1d87094047b223a10 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 21 Feb 2024 14:10:21 +0100 Subject: [PATCH 062/344] sync advanced fields --- packages/js/src/constants/sync.js | 5 +- .../src/helpers/fields/advancedFieldsStore.js | 52 +++++++++++++++++++ .../js/src/helpers/fields/blockEditorSync.js | 19 ++----- 3 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 packages/js/src/helpers/fields/advancedFieldsStore.js diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index fb7370a2da8..00167c0a11e 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -17,7 +17,10 @@ export const METADATA_IDS = { readabilityScore: "_yoast_wpseo_content_score", seoScore: "_yoast_wpseo_linkdex", inclusiveLanguageScore: "_yoast_wpseo_inclusive_language_score", - + advanced: "_yoast_wpseo_meta-robots-adv", + breadcrumbsTitle: "_yoast_wpseo_bctitle", + canonical: "_yoast_wpseo_canonical", + wordProofTimestamp: "_yoast_wpseo_wordproof_timestamp", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js new file mode 100644 index 00000000000..fbbaa1952f9 --- /dev/null +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -0,0 +1,52 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Retrieves the no index value. + * + * @returns {integer} The no index value. + */ +export const getNoIndex = () => String( select( STORE )?.getNoIndex() ); + +/** + * Retrieves the no follow value. + * + * @returns {integer} The no follow value. + */ +export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); + +/** + * Gets the twitter image URL from the state. + * + * @param {Object} state The state. + * + * @returns {String} Twitter image URL. + */ +export const getAdvanced = () => select( STORE )?.getAdvanced(); + +/** + * Gets the twitter image type from the state. + * + * @param {Object} state The state. + * + * @returns {String} Twitter image type. + */ +export const getBreadcrumbsTitle = () => select( STORE )?.getBreadcrumbsTitle(); + +/** + * Gets the Twitter image src from the state. + * + * @param {Object} state The state. + * + * @returns {String} Twitter image src. + */ +export const getCanonical = () => select( STORE )?.getCanonical(); + +/** + * Gets the WordProof timestamp value. + * + * @param {Object} state The state. + * + * @returns {Boolean} WordProof timestamp value. + */ +export const getWordProofTimestamp = () => select( STORE )?.getWordProofTimestamp(); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index a91be9dd3d5..f25eb0e18f0 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -7,20 +7,7 @@ import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebo import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; - -/** - * Retrieves the no index value. - * - * @returns {integer} The no index value. - */ -const getNoIndex = () => String( select( STORE )?.getNoIndex() ); - -/** - * Retrieves the no follow value. - * - * @returns {integer} The no follow value. - */ -const getNoFollow = () => String( select( STORE )?.getNoFollow() ); +import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; /** * Retrieves the no index value. @@ -93,6 +80,10 @@ export const blockEditorSync = () => { readabilityScore: getReadabilityScore, seoScore: getSeoScore, inclusiveLanguageScore: getInclusiveLanguageScore, + advanced: getAdvanced, + breadcrumbsTitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordProofTimestamp: getWordProofTimestamp, } ), createUpdater() From 937ab9a0c713e588ec5bec8d07dc23b47d47df2d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 22 Feb 2024 14:15:48 +0100 Subject: [PATCH 063/344] disable block editor store sync when render hidden fields --- packages/js/src/block-editor.js | 12 +++++++----- packages/js/src/helpers/fields/hasHiddenFields.js | 14 +++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/js/src/block-editor.js b/packages/js/src/block-editor.js index d03c8c33946..7341007eb9a 100644 --- a/packages/js/src/block-editor.js +++ b/packages/js/src/block-editor.js @@ -2,13 +2,15 @@ import initBlockEditorIntegration from "./initializers/block-editor-integration"; import BlockEditorData from "./analysis/blockEditorData"; import { blockEditorSync, hasHiddenFields } from "./helpers/fields"; +import domReady from "@wordpress/dom-ready"; window.yoast = window.yoast || {}; window.yoast.initEditorIntegration = initBlockEditorIntegration; window.yoast.EditorData = BlockEditorData; -// console.log( hasHiddenFields() ); -// if ( hasHiddenFields() ) { -blockEditorSync(); -// } -/* eslint-enable no-unused-vars */ +domReady( () => { + if ( ! hasHiddenFields() ) { + blockEditorSync(); + } +} ); + diff --git a/packages/js/src/helpers/fields/hasHiddenFields.js b/packages/js/src/helpers/fields/hasHiddenFields.js index 27486e9cbfa..b409b0e8a28 100644 --- a/packages/js/src/helpers/fields/hasHiddenFields.js +++ b/packages/js/src/helpers/fields/hasHiddenFields.js @@ -4,15 +4,11 @@ * @returns {boolean} True if the element has hidden fields. */ export const hasHiddenFields = () => { - var element = document.getElementById( "wpseo_meta" ); - console.log( element ); - if ( element ) { - var inputs = element.getElementsByTagName( "input" ); - for ( var i = 0; i < inputs.length; i++ ) { - if ( inputs[ i ].type === "hidden" ) { - return true; - } - } + const element = document.getElementById( "wpseo_meta" ); + const inside = element?.querySelector( ".inside" ); + const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); + if ( hiddenFields && hiddenFields.length ) { + return true; } return false; }; From a8faf60bee251a9a136c498c02fec6a541b0f0b4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 22 Feb 2024 15:53:42 +0100 Subject: [PATCH 064/344] advanced fields and analysis update --- .../js/src/helpers/fields/advancedFieldsStore.js | 4 ++-- .../js/src/helpers/fields/analysisFieldsStore.js | 6 +++--- packages/js/src/helpers/fields/blockEditorSync.js | 3 +-- packages/js/src/initializers/editor-store.js | 11 +++++++---- packages/js/src/initializers/post-scraper.js | 7 +++++-- packages/js/src/redux/actions/advancedSettings.js | 12 +++++++----- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index fbbaa1952f9..659dbccee8b 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -22,7 +22,7 @@ export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); * * @returns {String} Twitter image URL. */ -export const getAdvanced = () => select( STORE )?.getAdvanced(); +export const getAdvanced = () => select( STORE )?.getAdvanced().join( "," ); /** * Gets the twitter image type from the state. @@ -49,4 +49,4 @@ export const getCanonical = () => select( STORE )?.getCanonical(); * * @returns {Boolean} WordProof timestamp value. */ -export const getWordProofTimestamp = () => select( STORE )?.getWordProofTimestamp(); +export const getWordProofTimestamp = () => select( STORE )?.getWordProofTimestamp() ? "1" : "0"; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index 963ca4f27a9..fd62fbe53bf 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -19,18 +19,18 @@ export const isCornerstoneContent = () => select( STORE )?.isCornerstoneContent( * * @returns {string} The content score. */ -export const getReadabilityScore = () => String( select( STORE )?.getReadabilityResults()?.overallScore ); +export const getReadabilityScore = () => select( STORE )?.getReadabilityResults()?.overallScore ? String( select( STORE )?.getReadabilityResults()?.overallScore ) : "0"; /** * Retrieves the inclusive language score. * * @returns {string} The content score. */ -export const getInclusiveLanguageScore = () => String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ); +export const getInclusiveLanguageScore = () => select( STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ) : "0"; /** * Retrieves the seo score. * * @returns {string} The content score. */ -export const getSeoScore = () => String( select( STORE )?.getSeoResults().overallScore ); +export const getSeoScore = () => select( STORE )?.getSeoResults().overallScore ? String( select( STORE )?.getSeoResults().overallScore ) : "0"; diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index f25eb0e18f0..e4760c2914a 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,4 +1,3 @@ - import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; @@ -45,7 +44,7 @@ const createUpdater = () => { if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { - newMetadata[ METADATA_IDS[ key ] ] = String( value ); + newMetadata[ METADATA_IDS[ key ] ] = value; } ); editPost( { diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 7a493f9f911..b71cfafc6a8 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -31,16 +31,19 @@ const populateStore = store => { const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); - store.dispatch( actions.setTwitterPreviewTitle( metaData[ "twitter-title" ] ) ); - store.dispatch( actions.setTwitterPreviewDescription( metaData[ "twitter-description" ] ) ); - store.dispatch( actions.setTwitterPreviewImage( { url: metaData[ "twitter-image" ], id: metaData[ "twitter-image-id" ] } ) ); - const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); + // store.dispatch( actions.setNoIndex( metaData[ "meta-robots-noindex" ] ) ); + // store.dispatch( actions.setNoFollow( metaData[ "meta-robots-nofollow" ] ) ); + // store.dispatch( actions.setAdvanced( metaData[ "meta-robots-adv" ]?.split( "," ) ) ); + store.dispatch( actions.setBreadcrumbsTitle( metaData.bctitle ) ); + store.dispatch( actions.setCanonical( metaData.canonical ) ); + // store.dispatch( actions.setWordProofTimestamp( metaData.wordproof_timestamp ) === "1" ); + store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index b085ec62dc7..b1e02beb62b 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -1,3 +1,5 @@ +/* eslint-disable max-statements */ +/* eslint-disable complexity */ /* global wpseoScriptData */ // External dependencies. @@ -521,7 +523,7 @@ export default function initPostScraper( $, store, editorData ) { // Set the initial snippet editor data. store.dispatch( updateData( snippetEditorData ) ); // This used to be a checkbox, then became a hidden input. For consistency, we set the value to '1'. - store.dispatch( setCornerstoneContent( document.getElementById( "yoast_wpseo_is_cornerstone" ).value === "1" ) ); + store.dispatch( setCornerstoneContent( get( window, "wpseoScriptData.metabox.metaData.is_cornerstone", 0 ) === "1" ) ); // Save the keyword, in order to compare it to store changes. let focusKeyword = store.getState().focusKeyword; @@ -564,7 +566,8 @@ export default function initPostScraper( $, store, editorData ) { if ( previousCornerstoneValue !== currentState.isCornerstone ) { previousCornerstoneValue = currentState.isCornerstone; - document.getElementById( "yoast_wpseo_is_cornerstone" ).value = currentState.isCornerstone; + + store.dispatch( setCornerstoneContent( currentState.isCornerstone ) ); app.changeAssessorOptions( { useCornerstone: currentState.isCornerstone, diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index 365d119dd0a..0720c5cbcaf 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -1,4 +1,5 @@ import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { get } from "lodash"; export const SET_NO_INDEX = "SET_NO_INDEX"; export const SET_NO_FOLLOW = "SET_NO_FOLLOW"; @@ -86,17 +87,18 @@ export const setWordProofTimestamp = ( value ) => { * @returns {object} The action object. */ export const loadAdvancedSettingsData = () => { - const advancedValue = MetaboxFieldSync.getInitialValue( "meta-robots-adv" ); + const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + const advancedValue = metaData[ "meta-robots-adv" ]; const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; return { type: LOAD_ADVANCED_SETTINGS, settings: { noIndex: MetaboxFieldSync.getNoIndex(), - noFollow: MetaboxFieldSync.getInitialValue( "meta-robots-nofollow" ), + noFollow: metaData[ "meta-robots-nofollow" ], advanced: advancedList, - breadcrumbsTitle: MetaboxFieldSync.getInitialValue( "bctitle" ), - canonical: MetaboxFieldSync.getInitialValue( "canonical" ), - wordproofTimestamp: MetaboxFieldSync.getInitialValue( "wordproof_timestamp" ) === "1", + breadcrumbsTitle: metaData.bctitle, + canonical: metaData.canonical, + wordproofTimestamp: metaData.wordproof_timestamp === "1", isLoading: false, }, }; From 2ddde604ee85c5d02b8e96d1193b6e7fe2a23a83 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 22 Feb 2024 16:17:22 +0100 Subject: [PATCH 065/344] fix analysis scores --- packages/js/src/analysis/PostDataCollector.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 3a4f0841a8e..18ee480f041 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -381,8 +381,6 @@ PostDataCollector.prototype.saveScores = function( score, keyword ) { publishBox.updateScore( "content", indicator.className ); - document.getElementById( "yoast_wpseo_linkdex" ).value = score; - if ( "" === keyword ) { indicator.className = "na"; indicator.screenReaderText = __( @@ -414,8 +412,6 @@ PostDataCollector.prototype.saveContentScore = function( score ) { updateTrafficLight( indicator ); updateAdminBar( indicator ); } - - dispatch( STORE ).setOverallReadabilityScore( score ); }; /** @@ -433,8 +429,6 @@ PostDataCollector.prototype.saveInclusiveLanguageScore = function( score ) { updateTrafficLight( indicator ); updateAdminBar( indicator ); } - - dispatch( STORE ).setOverallInclusiveLanguageScore( score ); }; From 14fde8b55e910c09480a2575bebab6178830847a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 22 Feb 2024 17:07:42 +0100 Subject: [PATCH 066/344] cleanup code --- packages/js/src/analysis/PostDataCollector.js | 2 +- packages/js/src/initializers/editor-store.js | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 18ee480f041..4a0e729f5fc 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -4,7 +4,7 @@ import { __ } from "@wordpress/i18n"; import { get } from "lodash"; import { markers } from "yoastseo"; -import { select, dispatch } from "@wordpress/data"; +import { select } from "@wordpress/data"; /* Internal dependencies */ import measureTextWidth from "../helpers/measureTextWidth"; diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index b71cfafc6a8..09e1a6feeb0 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -37,13 +37,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - // store.dispatch( actions.setNoIndex( metaData[ "meta-robots-noindex" ] ) ); - // store.dispatch( actions.setNoFollow( metaData[ "meta-robots-nofollow" ] ) ); - // store.dispatch( actions.setAdvanced( metaData[ "meta-robots-adv" ]?.split( "," ) ) ); - store.dispatch( actions.setBreadcrumbsTitle( metaData.bctitle ) ); - store.dispatch( actions.setCanonical( metaData.canonical ) ); - // store.dispatch( actions.setWordProofTimestamp( metaData.wordproof_timestamp ) === "1" ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); From c79869461d4e8db70a089695ddb97301e6b6d0df Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 12:42:54 +0100 Subject: [PATCH 067/344] fix dynamic sync to primary term --- packages/js/src/constants/sync.js | 1 - .../js/src/helpers/fields/blockEditorSync.js | 22 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 00167c0a11e..fdca5ffd6cd 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -2,7 +2,6 @@ export const METADATA_IDS = { focusKeyphrase: "_yoast_wpseo_focuskw", noIndex: "_yoast_wpseo_meta-robots-noindex", noFollow: "_yoast_wpseo_meta-robots-nofollow", - primaryCategory: "_yoast_wpseo_primary_category", facebookTitle: "_yoast_wpseo_opengraph-title", facebookDescription: "_yoast_wpseo_opengraph-description", facebookImageUrl: "_yoast_wpseo_opengraph-image", diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index e4760c2914a..02d317f5391 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy } from "lodash"; +import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -9,12 +9,21 @@ import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoSco import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; /** - * Retrieves the no index value. + * Retrieves primary terms from store methods. * * @returns {integer} The no index value. */ -const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); - +const getPrimaryTerms = () => { + const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + const getPrimaryTermsStore = {}; + const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( STORE )?.getPrimaryTaxonomyId( taxonomy ) ); + METADATA_IDS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; + } ); + return getPrimaryTermsStore; +}; /** * Creates an updater. @@ -35,12 +44,15 @@ const createUpdater = () => { if ( ! metadata || ! data ) { return; } + console.log( { data } ); console.log( { metadata } ); const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + console.log( { changedData } ); + if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { @@ -64,7 +76,6 @@ export const blockEditorSync = () => { focusKeyphrase: getFocusKeyphrase, noIndex: getNoIndex, noFollow: getNoFollow, - primaryCategory: getPrimaryCategoryId, facebookTitle: getFacebookTitle, facebookDescription: getFacebookDescription, facebookImageUrl: getFacebookImageUrl, @@ -83,6 +94,7 @@ export const blockEditorSync = () => { breadcrumbsTitle: getBreadcrumbsTitle, canonical: getCanonical, wordProofTimestamp: getWordProofTimestamp, + ...getPrimaryTerms(), } ), createUpdater() From 61f64bedead80f29b02142f70859b15710274d9a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 13:45:07 +0100 Subject: [PATCH 068/344] sync snippet editor title and description --- packages/js/src/analysis/PostDataCollector.js | 13 ++++++++---- packages/js/src/constants/sync.js | 2 ++ .../js/src/helpers/fields/blockEditorSync.js | 10 +++------- .../fields/snippetEditorFieldsStore.js | 20 +++++++++++++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 packages/js/src/helpers/fields/snippetEditorFieldsStore.js diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 4a0e729f5fc..ec01502fd2e 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -1,3 +1,4 @@ +/* eslint-disable complexity */ /* global wpseoScriptData */ /* External dependencies */ @@ -172,7 +173,7 @@ PostDataCollector.prototype.getExcerpt = function() { * @returns {string} The snippet title. */ PostDataCollector.prototype.getSnippetTitle = function() { - return document.getElementById( "yoast_wpseo_title" ) && document.getElementById( "yoast_wpseo_title" ).value || ""; + return get( window, "wpseoScriptData.metabox.metaData.title", "" ); }; /** @@ -181,7 +182,7 @@ PostDataCollector.prototype.getSnippetTitle = function() { * @returns {string} The snippet meta. */ PostDataCollector.prototype.getSnippetMeta = function() { - return document.getElementById( "yoast_wpseo_metadesc" ) && document.getElementById( "yoast_wpseo_metadesc" ).value || ""; + return get( window, "wpseoScriptData.metabox.metaData.metadesc", "" ); }; /** @@ -275,7 +276,9 @@ PostDataCollector.prototype.getCategoryName = function( li ) { PostDataCollector.prototype.setDataFromSnippet = function( value, type ) { switch ( type ) { case "snippet_meta": - document.getElementById( "yoast_wpseo_metadesc" ).value = value; + if ( document.getElementById( "yoast_wpseo_metadesc" ) ) { + document.getElementById( "yoast_wpseo_metadesc" ).value = value; + } break; case "snippet_cite": @@ -299,7 +302,9 @@ PostDataCollector.prototype.setDataFromSnippet = function( value, type ) { } break; case "snippet_title": - document.getElementById( "yoast_wpseo_title" ).value = value; + if ( document.getElementById( "yoast_wpseo_title" ) ) { + document.getElementById( "yoast_wpseo_title" ).value = value; + } break; default: break; diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index fdca5ffd6cd..988cde9ed0c 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -20,6 +20,8 @@ export const METADATA_IDS = { breadcrumbsTitle: "_yoast_wpseo_bctitle", canonical: "_yoast_wpseo_canonical", wordProofTimestamp: "_yoast_wpseo_wordproof_timestamp", + seoTitle: "_yoast_wpseo_title", + seoDescription: "_yoast_wpseo_metadesc", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 02d317f5391..162df420f67 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -7,6 +7,7 @@ import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterIm import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; +import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; /** * Retrieves primary terms from store methods. @@ -38,21 +39,14 @@ const createUpdater = () => { * @returns {void} */ return ( data ) => { - // Unfortunately, we need to pass the full metadata to update a part of it. const metadata = select( CORE_EDITOR_STORE ).getCurrentPost().meta; if ( ! metadata || ! data ) { return; } - console.log( { data } ); - console.log( { metadata } ); - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); - console.log( { changedData } ); - - if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { @@ -94,6 +88,8 @@ export const blockEditorSync = () => { breadcrumbsTitle: getBreadcrumbsTitle, canonical: getCanonical, wordProofTimestamp: getWordProofTimestamp, + seoTitle: getSeoTitle, + seoDescription: getSeoDescription, ...getPrimaryTerms(), } ), diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js new file mode 100644 index 00000000000..bd768e1b93c --- /dev/null +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -0,0 +1,20 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Gets the snippet editor title. + * + * @param {Object} state The state object. + * + * @returns {string} The snippet editor title. + */ +export const getSeoTitle = () => select( STORE )?.getSnippetEditorTitle(); + +/** + * Gets the snippet editor description. + * + * @param {Object} state The state object. + * + * @returns {string} The snippet editor description. + */ +export const getSeoDescription = () => select( STORE )?.getSnippetEditorDescription(); From 6d85e2eddf95074e7674f1940901281c46599191 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 16:06:54 +0100 Subject: [PATCH 069/344] renamed constant --- packages/js/src/helpers/fields/blockEditorSync.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 162df420f67..247c9539aa0 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_IDS } from "../../constants"; +import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -21,7 +21,7 @@ const getPrimaryTerms = () => { forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( STORE )?.getPrimaryTaxonomyId( taxonomy ) ); - METADATA_IDS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; + METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; } ); return getPrimaryTermsStore; }; @@ -44,15 +44,19 @@ const createUpdater = () => { if ( ! metadata || ! data ) { return; } - - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_IDS[ key ] ] ); + console.log( { data } ); + console.log( { metadata } ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); + console.log( { changedData } ); if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { - newMetadata[ METADATA_IDS[ key ] ] = value; + newMetadata[ METADATA_KEYS[ key ] ] = value; } ); + console.log( { newMetadata } ); + editPost( { meta: newMetadata, } ); From 18bf603d03e75f2dd256cdf267a3b167efa0d6ea Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 16:07:44 +0100 Subject: [PATCH 070/344] fix score to match database --- packages/js/src/helpers/fields/analysisFieldsStore.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index fd62fbe53bf..4f0bb32c522 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -19,18 +19,18 @@ export const isCornerstoneContent = () => select( STORE )?.isCornerstoneContent( * * @returns {string} The content score. */ -export const getReadabilityScore = () => select( STORE )?.getReadabilityResults()?.overallScore ? String( select( STORE )?.getReadabilityResults()?.overallScore ) : "0"; +export const getReadabilityScore = () => select( STORE )?.getReadabilityResults()?.overallScore ? String( select( STORE )?.getReadabilityResults()?.overallScore ) : ""; /** * Retrieves the inclusive language score. * * @returns {string} The content score. */ -export const getInclusiveLanguageScore = () => select( STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ) : "0"; +export const getInclusiveLanguageScore = () => select( STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ) : ""; /** * Retrieves the seo score. * * @returns {string} The content score. */ -export const getSeoScore = () => select( STORE )?.getSeoResults().overallScore ? String( select( STORE )?.getSeoResults().overallScore ) : "0"; +export const getSeoScore = () => select( STORE )?.getSeoResults().overallScore ? String( select( STORE )?.getSeoResults().overallScore ) : ""; From 7c3cb4f5e5edb2318543bfbe27ebb0ea64d889c9 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 16:08:16 +0100 Subject: [PATCH 071/344] load advanced settings when populating the store --- packages/js/src/components/AdvancedSettings.js | 10 ---------- packages/js/src/containers/AdvancedSettings.js | 2 -- packages/js/src/initializers/editor-store.js | 2 ++ 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/js/src/components/AdvancedSettings.js b/packages/js/src/components/AdvancedSettings.js index 710dde707fc..664d239adb1 100644 --- a/packages/js/src/components/AdvancedSettings.js +++ b/packages/js/src/components/AdvancedSettings.js @@ -282,7 +282,6 @@ const AdvancedSettings = ( props ) => { onBreadcrumbsTitleChange, onCanonicalChange, onWordProofTimestampChange, - onLoad, isLoading, editorContext, isBreadcrumbsDisabled, @@ -290,14 +289,6 @@ const AdvancedSettings = ( props ) => { isWordProofIntegrationActive, } = props; - useEffect( () => { - setTimeout( () => { - if ( isLoading ) { - onLoad(); - } - } ); - } ); - const noIndexProps = { noIndex, onNoIndexChange, @@ -355,7 +346,6 @@ AdvancedSettings.propTypes = { onNoIndexChange: PropTypes.func.isRequired, onCanonicalChange: PropTypes.func.isRequired, onWordProofTimestampChange: PropTypes.func, - onLoad: PropTypes.func.isRequired, isLoading: PropTypes.bool.isRequired, editorContext: PropTypes.object.isRequired, isBreadcrumbsDisabled: PropTypes.bool.isRequired, diff --git a/packages/js/src/containers/AdvancedSettings.js b/packages/js/src/containers/AdvancedSettings.js index 807c8f3b6e4..66a099b0c6f 100644 --- a/packages/js/src/containers/AdvancedSettings.js +++ b/packages/js/src/containers/AdvancedSettings.js @@ -44,7 +44,6 @@ export default compose( [ setBreadcrumbsTitle, setCanonical, setWordProofTimestamp, - loadAdvancedSettingsData, } = dispatch( "yoast-seo/editor" ); return { @@ -54,7 +53,6 @@ export default compose( [ onBreadcrumbsTitleChange: setBreadcrumbsTitle, onCanonicalChange: setCanonical, onWordProofTimestampChange: setWordProofTimestamp, - onLoad: loadAdvancedSettingsData, }; } ), ] )( AdvancedSettings ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 09e1a6feeb0..01635ac5590 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -37,6 +37,8 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); + store.dispatch( actions.loadAdvancedSettingsData() ); + store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); From e275b94eed1872fd82391ef9e4d6d254027b211c Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 16:08:38 +0100 Subject: [PATCH 072/344] rename constant metadata keys --- packages/js/src/constants/sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index 988cde9ed0c..a8325d7ef2d 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -1,4 +1,4 @@ -export const METADATA_IDS = { +export const METADATA_KEYS = { focusKeyphrase: "_yoast_wpseo_focuskw", noIndex: "_yoast_wpseo_meta-robots-noindex", noFollow: "_yoast_wpseo_meta-robots-nofollow", From 2c9ff7ee320b502ad8e818a8fae14793812690c5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 16:34:33 +0100 Subject: [PATCH 073/344] cleanup import --- packages/js/src/components/AdvancedSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/components/AdvancedSettings.js b/packages/js/src/components/AdvancedSettings.js index 664d239adb1..3bf558ef73f 100644 --- a/packages/js/src/components/AdvancedSettings.js +++ b/packages/js/src/components/AdvancedSettings.js @@ -1,5 +1,5 @@ /* global wpseoAdminL10n */ -import { Fragment, useEffect } from "@wordpress/element"; +import { Fragment } from "@wordpress/element"; import { __, sprintf } from "@wordpress/i18n"; import { Alert, MultiSelect, RadioButtonGroup, Select, TextInput } from "@yoast/components"; import { join } from "@yoast/helpers"; From 410b9a6035c7e0689fdf60249fab8aab5e5198d7 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:00:27 +0100 Subject: [PATCH 074/344] fix default value --- admin/formatter/class-post-metabox-formatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index e05be574015..c553e188da7 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -346,9 +346,9 @@ protected function get_post_meta_data() { $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); $default = ''; - if ( isset( $meta_field['default'] ) ) { - $default = $meta_field['default']; - $meta_data[ $key.'_default' ] = $default; + if ( isset( $meta_field['default_value'] ) ) { + $default = $meta_field['default_value']; + $meta_data[ $key . '_default' ] = $default; } $meta_data[ $key ] = esc_attr( $meta_value ) ? esc_attr( $meta_value ) : $default; From c3f7a2103768132ae1f60787e77f1596368bb172 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:01:09 +0100 Subject: [PATCH 075/344] better to use get --- .../js/src/redux/actions/advancedSettings.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index 0720c5cbcaf..45e2ae4f53a 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -29,8 +29,8 @@ export const setNoIndex = ( value ) => { * @returns {Object} The action object. */ export const setNoFollow = ( value ) => { - MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_meta-robots-nofollow", value ); - return { type: SET_NO_FOLLOW, value: String( value ) }; + MetaboxFieldSync.setFieldValue( "meta-robots-nofollow", value ); + return { type: SET_NO_FOLLOW, value }; }; /** @@ -41,7 +41,7 @@ export const setNoFollow = ( value ) => { * @returns {Object} The action object. */ export const setAdvanced = ( value ) => { - MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_meta-robots-adv", value.join( "," ) ); + MetaboxFieldSync.setFieldValue( "meta-robots-adv", value.join( "," ) ); return { type: SET_ADVANCED, value }; }; @@ -87,18 +87,17 @@ export const setWordProofTimestamp = ( value ) => { * @returns {object} The action object. */ export const loadAdvancedSettingsData = () => { - const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); - const advancedValue = metaData[ "meta-robots-adv" ]; + const advancedValue = get( window, "wpseoScriptData.metabox.metaData.meta-robots-adv", "" ); const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; return { type: LOAD_ADVANCED_SETTINGS, settings: { - noIndex: MetaboxFieldSync.getNoIndex(), - noFollow: metaData[ "meta-robots-nofollow" ], + noIndex: get( window, "wpseoScriptData.metabox.metaData.meta-robots-noindex", "" ), + noFollow: get( window, "wpseoScriptData.metabox.metaData.meta-robots-nofollow", "0" ), advanced: advancedList, - breadcrumbsTitle: metaData.bctitle, - canonical: metaData.canonical, - wordproofTimestamp: metaData.wordproof_timestamp === "1", + breadcrumbsTitle: get( window, "wpseoScriptData.metabox.metaData.bctitle", "" ), + canonical: get( window, "wpseoScriptData.metabox.metaData.canonical", "" ), + wordproofTimestamp: get( window, "wpseoScriptData.metabox.metaData.wordproof_timestamp", "" ) === "1", isLoading: false, }, }; From d5f6462a3ef66d570773b4913f4e313fd3df6edb Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:01:31 +0100 Subject: [PATCH 076/344] add defensive coding --- packages/js/src/helpers/fields/MetaboxFieldSync.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js index a762ae10807..53c67dc4d7a 100644 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -1,8 +1,9 @@ +import { get } from "lodash"; /** * This class is responsible for syncing hidden fields with store. */ export default class MetaboxFieldSync { - static isPost = window.wpseoScriptData?.isPost; + static isPost = get( window, "wpseoScriptData.isPost", false ); static metaPrefix = "_yoast_wpseo_"; // Whether we are handling a post or a term. @@ -36,8 +37,10 @@ export default class MetaboxFieldSync { * @returns {void} */ static getNoIndex() { - const fieldKey = this.isPost ? "meta-robots-noindex" : "noindex"; - return window.wpseoScriptData.metabox.metaData[ fieldKey ]; + if ( this.isPost ) { + return get( window, "wpseoScriptData.metabox.metaData.meta-robots-noindex", "" ); + } + return get( window, "wpseoScriptData.metabox.metaData.noindex", "" ); } /** From 60b6a5c0ab9289577ce878d573d7df1576f49c4c Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:29:42 +0100 Subject: [PATCH 077/344] php fix cs --- .../class-post-metabox-formatter.php | 19 +++++++++---------- .../class-term-metabox-formatter.php | 8 ++++---- .../class-taxonomy-fields-presenter.php | 18 +++++++++--------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index c553e188da7..6270df272d2 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -34,9 +34,9 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Constructor. * - * @param WP_Post|array $post Post object. - * @param array $options Title options to use. - * @param string $structure The permalink to follow. + * @param WP_Post $post Post object. + * @param array $options Title options to use. + * @param string $structure The permalink to follow. */ public function __construct( $post, array $options, $structure ) { $this->post = $post; @@ -57,7 +57,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array + * @return array,array> */ public function get_values() { @@ -156,7 +156,7 @@ private function base_url_for_js() { /** * Counts the number of given keywords used for other posts other than the given post_id. * - * @return array The keyword and the associated posts that use it. + * @return array> The keyword and the associated posts that use it. */ private function get_focus_keyword_usage() { $keyword = WPSEO_Meta::get_value( 'focuskw', $this->post->ID ); @@ -174,8 +174,8 @@ private function get_focus_keyword_usage() { /** * Retrieves the post types for the given post IDs. * - * @param array $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. - * @return array The post types for the given post IDs. + * @param array> $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. + * @return array The post types for the given post IDs. */ private function get_post_types_for_all_ids( $post_ids_per_keyword ) { @@ -192,7 +192,7 @@ private function get_post_types_for_all_ids( $post_ids_per_keyword ) { * * @param string $keyword The keyword to check the usage of. * - * @return array The post IDs which use the passed keyword. + * @return array The post IDs which use the passed keyword. */ protected function get_keyword_usage_for_current_post( $keyword ) { return WPSEO_Meta::keyword_usage( $keyword, $this->post->ID ); @@ -319,7 +319,7 @@ protected function is_insights_enabled() { /** * Get post meta data. * - * @return void + * @return array */ protected function get_post_meta_data() { $post_type = $this->post->post_type; @@ -342,7 +342,6 @@ protected function get_post_meta_data() { } foreach ( $fields as $key => $meta_field ) { - $form_key = esc_attr( WPSEO_Meta::$form_prefix . $key ); $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); $default = ''; diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 06cbbc18fdb..1232c5f3647 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -34,7 +34,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Array with the WPSEO_Titles options. * - * @var array + * @var array */ protected $options; @@ -63,7 +63,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array + * @return array,array> */ public function get_values() { $values = []; @@ -96,7 +96,7 @@ public function get_values() { /** * Returns the metadata for the term. * - * @return array + * @return array */ protected function get_metadata() { $metadata = []; @@ -171,7 +171,7 @@ private function base_url_for_js() { /** * Counting the number of given keyword used for other term than given term_id. * - * @return array + * @return array */ private function get_focus_keyword_usage() { $focuskw = WPSEO_Taxonomy_Meta::get_term_meta( $this->term, $this->term->taxonomy, 'focuskw' ); diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index dbef6711b79..c0a3dce0116 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -13,7 +13,7 @@ class WPSEO_Taxonomy_Fields_Presenter { /** * The taxonomy meta data for the current term. * - * @var array + * @var array */ private $tax_meta; @@ -29,7 +29,7 @@ public function __construct( $term ) { /** * Displaying the form fields. * - * @param array $fields Array with the fields that will be displayed. + * @param array> $fields Array with the fields that will be displayed. * * @return string */ @@ -44,8 +44,8 @@ public function html( array $fields ) { /** * Create a row in the form table. * - * @param string $field_name Variable the row controls. - * @param array $field_configuration Array with the field configuration. + * @param string $field_name Variable the row controls. + * @param array $field_configuration Array with the field configuration. * * @return string */ @@ -70,10 +70,10 @@ private function form_row( $field_name, array $field_configuration ) { /** * 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. + * @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 */ @@ -174,7 +174,7 @@ public function get_field_value( $field_name ) { /** * Getting the class attributes if $options contains a class key. * - * @param array $options The array with field options. + * @param array $options The array with field options. * * @return string */ From 2b92bfde300f460b522211028f2044b630728dc4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:30:14 +0100 Subject: [PATCH 078/344] restore field configuration --- .../js/src/helpers/fields/hiddenFieldsSync.js | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 packages/js/src/helpers/fields/hiddenFieldsSync.js diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js new file mode 100644 index 00000000000..e130e3cb478 --- /dev/null +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -0,0 +1,91 @@ +/* eslint-disable camelcase */ +import { select, subscribe } from "@wordpress/data"; +import { debounce, forEach, pickBy } from "lodash"; +import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; +import { STORE, SYNC_TIME } from "../../constants"; +import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; +import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; +import { getPageType, getArticleType } from "./schemaFieldsStore"; +import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; +import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; + +/** + * Retrieves the no index value. + * + * @returns {integer} The no index value. + */ +const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); + + +/** + * Creates an updater. + * @returns {function} The updater. + */ +const createUpdater = () => { + /** + * Syncs the data to the WP entity record. + * @param {Object} data The collected data. + * @returns {void} + */ + return ( data ) => { + // Get the values from hidden fields. + const metadata = {}; + const wpseoMetaElement = document.getElementById( "wpseo_meta" ); + const inside = wpseoMetaElement?.querySelector( ".inside" ); + const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); + forEach( hiddenFields, ( field ) => { + metadata[ field.id ] = field.value; + } ); + + if ( ! metadata || ! data ) { + return; + } + console.log( { data } ); + console.log( { metadata } ); + const prefix = "yoast_wpseo_"; + + const changedData = pickBy( data, ( value, key ) => value !== metadata[ prefix + key ] ); + console.log( { changedData } ); + + if ( changedData ) { + forEach( changedData, ( value, key ) => { + document.getElementById( prefix + key ).value = value; + } ); + } + }; +}; + +/** + * Initializes the sync: from Yoast editor store to product metadata. + * @returns {function} The un-subscriber. + */ +export const blockEditorSync = () => { + return subscribe( debounce( createWatcher( + createCollectorFromObject( { + focuskw: getFocusKeyphrase, + "meta-robots-noindex": getNoIndex, + "meta-robots-nofollow": getNoFollow, + primary_category: getPrimaryCategoryId, + "opengraph-title": getFacebookTitle, + "opengraph-description": getFacebookDescription, + "opengraph-image": getFacebookImageUrl, + "opengraph-image-id": getFacebookImageId, + "twitter-title": getTwitterTitle, + "twitter-description": getTwitterDescription, + "twitter-image": getTwitterImageUrl, + "twitter-image-id": getTwitterImageId, + schema_page_type: getPageType, + schema_article_type: getArticleType, + is_cornerstone: isCornerstoneContent, + content_score: getReadabilityScore, + linkdex: getSeoScore, + inclusive_language_score: getInclusiveLanguageScore, + "meta-robots-adv": getAdvanced, + bctitle: getBreadcrumbsTitle, + wpseo_canonical: getCanonical, + wordproof_timestamp: getWordProofTimestamp, + + } ), + createUpdater() + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); +}; From eaa6ac062bc0a56c378a6511b5d84b92a835eade Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:41:40 +0100 Subject: [PATCH 079/344] fix-cs --- admin/formatter/class-post-metabox-formatter.php | 4 ++-- inc/class-wpseo-meta.php | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 6270df272d2..06aebbf4b88 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -34,9 +34,9 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Constructor. * - * @param WP_Post $post Post object. + * @param WP_Post $post Post object. * @param array $options Title options to use. - * @param string $structure The permalink to follow. + * @param string $structure The permalink to follow. */ public function __construct( $post, array $options, $structure ) { $this->post = $post; diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index cd425b5a4f4..b3028e802fe 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -262,10 +262,10 @@ class WPSEO_Meta { * @var array */ private static $social_fields = [ - 'title' => [ 'type' => 'hidden' ], - 'description' => [ 'type' => 'hidden' ], - 'image' => [ 'type' => 'hidden' ], - 'image-id' => [ 'type' => 'hidden' ], + 'title' => 'hidden', + 'description' => 'hidden', + 'image' => 'hidden', + 'image-id' => 'hidden', ]; /** @@ -276,9 +276,9 @@ class WPSEO_Meta { public static function init() { foreach ( self::$social_networks as $option => $network ) { if ( WPSEO_Options::get( $option, false ) === true ) { - foreach ( self::$social_fields as $box => $field_def ) { + foreach ( self::$social_fields as $box => $type ) { self::$meta_fields['social'][ $network . '-' . $box ] = [ - 'type' => $field_def['type'], + 'type' => $type, 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. From cc3de1dbee689c15cac828185ab8ec70320b3f11 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 23 Feb 2024 17:41:58 +0100 Subject: [PATCH 080/344] fix-cs --- inc/class-wpseo-meta.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index b3028e802fe..c84a1cf178d 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -297,6 +297,7 @@ public static function init() { self::$meta_fields = self::array_merge_recursive_distinct( $extra_fields, self::$meta_fields ); } // register meta data for taxonomies. + $primay_terms = []; $primay_terms['primary_terms'] = []; $taxonomies = get_taxonomies( [ 'hierarchical' => true ], 'names' ); From a39ff7002a53af2fba28b07de565fe6244ad0f40 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:03:39 +0100 Subject: [PATCH 081/344] fix hidden fields sync --- .../js/src/helpers/fields/hiddenFieldsSync.js | 81 ++++++++++++------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index e130e3cb478..b0bc57f07a9 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,6 +1,6 @@ /* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy } from "lodash"; +import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { STORE, SYNC_TIME } from "../../constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -16,6 +16,23 @@ import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical */ const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); +/** + * Prepare value to be saved in hidden field. + * + * @param {string} key The key of the value. + * @param {string} value The value to be saved. + * + * @returns {string} The value to be saved. + */ +const prepareValue = ( key, value ) => { + switch ( key ) { + case "is_cornerstone": + return value ? "1" : "0"; + default: + return value; + } +}; + /** * Creates an updater. @@ -29,27 +46,31 @@ const createUpdater = () => { */ return ( data ) => { // Get the values from hidden fields. - const metadata = {}; + const hiddenFieldsData = {}; const wpseoMetaElement = document.getElementById( "wpseo_meta" ); const inside = wpseoMetaElement?.querySelector( ".inside" ); const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); forEach( hiddenFields, ( field ) => { - metadata[ field.id ] = field.value; + if ( field.id ) { + hiddenFieldsData[ field.id ] = field.value; + } } ); - if ( ! metadata || ! data ) { + if ( ! hiddenFieldsData || ! data ) { return; } console.log( { data } ); - console.log( { metadata } ); - const prefix = "yoast_wpseo_"; + console.log( { hiddenFieldsData } ); + + const isPost = get( window, "wpseoScriptData.isPost", false ); + const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; - const changedData = pickBy( data, ( value, key ) => value !== metadata[ prefix + key ] ); + const changedData = pickBy( data, ( value, key ) => hiddenFieldsData[ prefix + key ] && value !== hiddenFieldsData[ prefix + key ] ); console.log( { changedData } ); if ( changedData ) { forEach( changedData, ( value, key ) => { - document.getElementById( prefix + key ).value = value; + document.getElementById( prefix + key ).value = prepareValue( key, value ); } ); } }; @@ -59,31 +80,31 @@ const createUpdater = () => { * Initializes the sync: from Yoast editor store to product metadata. * @returns {function} The un-subscriber. */ -export const blockEditorSync = () => { +export const hiddenFieldsrSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { focuskw: getFocusKeyphrase, - "meta-robots-noindex": getNoIndex, - "meta-robots-nofollow": getNoFollow, - primary_category: getPrimaryCategoryId, - "opengraph-title": getFacebookTitle, - "opengraph-description": getFacebookDescription, - "opengraph-image": getFacebookImageUrl, - "opengraph-image-id": getFacebookImageId, - "twitter-title": getTwitterTitle, - "twitter-description": getTwitterDescription, - "twitter-image": getTwitterImageUrl, - "twitter-image-id": getTwitterImageId, - schema_page_type: getPageType, - schema_article_type: getArticleType, - is_cornerstone: isCornerstoneContent, - content_score: getReadabilityScore, - linkdex: getSeoScore, - inclusive_language_score: getInclusiveLanguageScore, - "meta-robots-adv": getAdvanced, - bctitle: getBreadcrumbsTitle, - wpseo_canonical: getCanonical, - wordproof_timestamp: getWordProofTimestamp, + // "meta-robots-noindex": getNoIndex, + // "meta-robots-nofollow": getNoFollow, + // primary_category: getPrimaryCategoryId, + // "opengraph-title": getFacebookTitle, + // "opengraph-description": getFacebookDescription, + // "opengraph-image": getFacebookImageUrl, + // "opengraph-image-id": getFacebookImageId, + // "twitter-title": getTwitterTitle, + // "twitter-description": getTwitterDescription, + // "twitter-image": getTwitterImageUrl, + // "twitter-image-id": getTwitterImageId, + // schema_page_type: getPageType, + // schema_article_type: getArticleType, + is_cornerstone: isCornerstoneContent, + // content_score: getReadabilityScore, + // linkdex: getSeoScore, + // inclusive_language_score: getInclusiveLanguageScore, + // "meta-robots-adv": getAdvanced, + // bctitle: getBreadcrumbsTitle, + // wpseo_canonical: getCanonical, + // wordproof_timestamp: getWordProofTimestamp, } ), createUpdater() From 54f1861588deec03d69ac9b036c1a4fbf66c416e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:04:23 +0100 Subject: [PATCH 082/344] add sync to post edit --- packages/js/src/post-edit.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/js/src/post-edit.js b/packages/js/src/post-edit.js index 5467bea3231..0e80a50971d 100644 --- a/packages/js/src/post-edit.js +++ b/packages/js/src/post-edit.js @@ -11,6 +11,7 @@ import initTabs from "./initializers/metabox-tabs"; import initPostScraper from "./initializers/post-scraper"; import initPrimaryCategory from "./initializers/primary-category"; import initializeInsights from "./insights/initializer"; +import { hiddenFieldsrSync } from "./helpers/fields/hiddenFieldsSync"; // Backwards compatibility globals. window.wpseoPostScraperL10n = window.wpseoScriptData.metabox; @@ -30,6 +31,9 @@ domReady( () => { // Initialize the editor store. const store = initEditorStore(); + // Initialize the hidden fields sync. + hiddenFieldsrSync(); + // Initialize the editor integration window.yoast.initEditorIntegration( store ); const editorData = new window.yoast.EditorData( noop, store ); From 5ab74efd6360bcb2ae0d870b19d5a0b5cd1301df Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:04:43 +0100 Subject: [PATCH 083/344] cleanup sync for focus keyphrase action --- packages/js/src/redux/actions/focusKeyword.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/js/src/redux/actions/focusKeyword.js b/packages/js/src/redux/actions/focusKeyword.js index 81ad63cb580..f8450289d89 100644 --- a/packages/js/src/redux/actions/focusKeyword.js +++ b/packages/js/src/redux/actions/focusKeyword.js @@ -1,4 +1,4 @@ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { get } from "lodash"; const PREFIX = "WPSEO_"; @@ -13,7 +13,7 @@ export const SET_FOCUS_KEYWORD = `${ PREFIX }SET_FOCUS_KEYWORD`; export const loadFocusKeyword = () => { return { type: LOAD_FOCUS_KEYWORD, - keyword: MetaboxFieldSync.getInitialValue( "focuskw" ), + keyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), }; }; @@ -25,7 +25,6 @@ export const loadFocusKeyword = () => { * @returns {Object} Action. */ export const setFocusKeyword = function( keyword ) { - MetaboxFieldSync.setFieldValue( "focuskw", keyword ); return { type: SET_FOCUS_KEYWORD, keyword: keyword, From 23bfae2078bb821db8d61f7d3e32e358dc68f6ab Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:05:12 +0100 Subject: [PATCH 084/344] cleaned sync from is cornerstone action --- packages/js/src/redux/actions/cornerstoneContent.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/js/src/redux/actions/cornerstoneContent.js b/packages/js/src/redux/actions/cornerstoneContent.js index 9edad68ec6c..3ceb15a3fb4 100644 --- a/packages/js/src/redux/actions/cornerstoneContent.js +++ b/packages/js/src/redux/actions/cornerstoneContent.js @@ -1,4 +1,4 @@ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { get } from "lodash"; const PREFIX = "WPSEO_"; @@ -14,7 +14,7 @@ export const SET_CORNERSTONE_CONTENT = `${ PREFIX }SET_CORNERSTONE_CONTENT`; export const loadCornerstoneContent = () => { return { type: SET_CORNERSTONE_CONTENT, - isCornerstone: MetaboxFieldSync.getInitialValue( "is_cornerstone" ) === "1", + isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", "0" ) === "1", }; }; @@ -26,7 +26,6 @@ export const loadCornerstoneContent = () => { * @returns {Object} The set cornerstone content action. */ export const setCornerstoneContent = ( isCornerstone ) => { - MetaboxFieldSync.setBooleanFieldValue( "is_cornerstone", isCornerstone ); return { type: SET_CORNERSTONE_CONTENT, isCornerstone, @@ -39,7 +38,6 @@ export const setCornerstoneContent = ( isCornerstone ) => { * @returns {Object} The toggle cornerstone content action. */ export const toggleCornerstoneContent = () => { - MetaboxFieldSync.toggleFieldValue( "is_cornerstone" ); return { type: TOGGLE_CORNERSTONE_CONTENT, }; From df10582894f3c45d719aba4874a703ec2b3115b4 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:06:24 +0100 Subject: [PATCH 085/344] rename metaData to metadata --- admin/formatter/class-post-metabox-formatter.php | 2 +- admin/formatter/class-term-metabox-formatter.php | 2 +- packages/js/src/analysis/PostDataCollector.js | 4 ++-- .../src/elementor/initializers/editor-store.js | 6 +++--- .../js/src/helpers/fields/MetaboxFieldSync.js | 6 +++--- .../js/src/helpers/fields/blockEditorSync.js | 2 +- packages/js/src/initializers/editor-store.js | 6 +++--- packages/js/src/initializers/post-scraper.js | 16 ++++++++-------- .../js/src/redux/actions/advancedSettings.js | 12 ++++++------ 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 06aebbf4b88..2b3dc8007ed 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -83,7 +83,7 @@ public function get_values() { 'social_description_template' => $this->get_social_description_template(), 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metaData' => $this->get_post_meta_data(), + 'metadata' => $this->get_post_meta_data(), ]; $values = ( $values_to_set + $values ); diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 1232c5f3647..e0fc076e0a0 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -86,7 +86,7 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metaData' => $this->get_metadata(), + 'metadata' => $this->get_metadata(), ]; } diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index ec01502fd2e..4e2d63487b3 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -173,7 +173,7 @@ PostDataCollector.prototype.getExcerpt = function() { * @returns {string} The snippet title. */ PostDataCollector.prototype.getSnippetTitle = function() { - return get( window, "wpseoScriptData.metabox.metaData.title", "" ); + return get( window, "wpseoScriptData.metabox.metadata.title", "" ); }; /** @@ -182,7 +182,7 @@ PostDataCollector.prototype.getSnippetTitle = function() { * @returns {string} The snippet meta. */ PostDataCollector.prototype.getSnippetMeta = function() { - return get( window, "wpseoScriptData.metabox.metaData.metadesc", "" ); + return get( window, "wpseoScriptData.metabox.metadata.metadesc", "" ); }; /** diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 48c3082d97d..0334dc278f6 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -46,10 +46,10 @@ const populateStore = store => { store.dispatch( actions.loadTwitterPreviewData() ); } - const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); - store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); + store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); - const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js index 53c67dc4d7a..6f52ed72796 100644 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ b/packages/js/src/helpers/fields/MetaboxFieldSync.js @@ -28,7 +28,7 @@ export default class MetaboxFieldSync { * @returns {value} The initial value of the field. */ static getInitialValue( fieldKey ) { - return window.wpseoScriptData?.metabox?.metaData[ fieldKey ]; + return window.wpseoScriptData?.metabox?.metadata[ fieldKey ]; } /** @@ -38,9 +38,9 @@ export default class MetaboxFieldSync { */ static getNoIndex() { if ( this.isPost ) { - return get( window, "wpseoScriptData.metabox.metaData.meta-robots-noindex", "" ); + return get( window, "wpseoScriptData.metabox.metadata.meta-robots-noindex", "" ); } - return get( window, "wpseoScriptData.metabox.metaData.noindex", "" ); + return get( window, "wpseoScriptData.metabox.metadata.noindex", "" ); } /** diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 247c9539aa0..58a77965e6f 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -15,7 +15,7 @@ import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; * @returns {integer} The no index value. */ const getPrimaryTerms = () => { - const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", [] ); const getPrimaryTermsStore = {}; const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 01635ac5590..293cf77064b 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -28,10 +28,10 @@ const populateStore = store => { } ) ); - const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); - store.dispatch( actions.setFocusKeyword( metaData.focuskw ) ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); + store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); - const primaryTerms = pickBy( metaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index b1e02beb62b..8bedf1f9bee 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -135,7 +135,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeKeywordAnalysis( activePublishBox ) { - const savedKeywordScore = get( window, "wpseoScriptData.metabox.metaData.linkdex", 0 ); + const savedKeywordScore = get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 ); const indicator = getIndicatorForScore( savedKeywordScore ); @@ -153,7 +153,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeContentAnalysis( activePublishBox ) { - const savedContentScore = get( window, "wpseoScriptData.metabox.metaData.content_score", 0 ); + const savedContentScore = get( window, "wpseoScriptData.metabox.metadata.content_score", 0 ); const indicator = getIndicatorForScore( savedContentScore ); @@ -170,7 +170,7 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializeInclusiveLanguageAnalysis( activePublishBox ) { - const savedContentScore = get( window, "wpseoScriptData.metabox.metaData.inclusive_language_score", 0 ); + const savedContentScore = get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 ); const indicator = getIndicatorForScore( savedContentScore ); @@ -257,8 +257,8 @@ export default function initPostScraper( $, store, editorData ) { }; if ( isKeywordAnalysisActive() ) { - const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); - store.dispatch( setFocusKeyword( metaData.focuskw ) ); + const focusKeyPhrase = get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ); + store.dispatch( setFocusKeyword( focusKeyPhrase ) ); args.callbacks.saveScores = postDataCollector.saveScores.bind( postDataCollector ); @@ -410,10 +410,10 @@ export default function initPostScraper( $, store, editorData ) { handlePageBuilderCompatibility(); - const metaData = get( window, "wpseoScriptData.metabox.metaData", [] ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); // Avoid error when snippet metabox is not rendered. - if ( metaboxContainer.length === 0 && metaData.length === 0 ) { + if ( metaboxContainer.length === 0 && metadata.length === 0 ) { return; } @@ -523,7 +523,7 @@ export default function initPostScraper( $, store, editorData ) { // Set the initial snippet editor data. store.dispatch( updateData( snippetEditorData ) ); // This used to be a checkbox, then became a hidden input. For consistency, we set the value to '1'. - store.dispatch( setCornerstoneContent( get( window, "wpseoScriptData.metabox.metaData.is_cornerstone", 0 ) === "1" ) ); + store.dispatch( setCornerstoneContent( get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1" ) ); // Save the keyword, in order to compare it to store changes. let focusKeyword = store.getState().focusKeyword; diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index 45e2ae4f53a..a933545a55e 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -87,17 +87,17 @@ export const setWordProofTimestamp = ( value ) => { * @returns {object} The action object. */ export const loadAdvancedSettingsData = () => { - const advancedValue = get( window, "wpseoScriptData.metabox.metaData.meta-robots-adv", "" ); + const advancedValue = get( window, "wpseoScriptData.metabox.metadata.meta-robots-adv", "" ); const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; return { type: LOAD_ADVANCED_SETTINGS, settings: { - noIndex: get( window, "wpseoScriptData.metabox.metaData.meta-robots-noindex", "" ), - noFollow: get( window, "wpseoScriptData.metabox.metaData.meta-robots-nofollow", "0" ), + noIndex: get( window, "wpseoScriptData.metabox.metadata.meta-robots-noindex", "" ), + noFollow: get( window, "wpseoScriptData.metabox.metadata.meta-robots-nofollow", "0" ), advanced: advancedList, - breadcrumbsTitle: get( window, "wpseoScriptData.metabox.metaData.bctitle", "" ), - canonical: get( window, "wpseoScriptData.metabox.metaData.canonical", "" ), - wordproofTimestamp: get( window, "wpseoScriptData.metabox.metaData.wordproof_timestamp", "" ) === "1", + breadcrumbsTitle: get( window, "wpseoScriptData.metabox.metadata.bctitle", "" ), + canonical: get( window, "wpseoScriptData.metabox.metadata.canonical", "" ), + wordproofTimestamp: get( window, "wpseoScriptData.metabox.metadata.wordproof_timestamp", "" ) === "1", isLoading: false, }, }; From 206c561cdce5460c40280d39be096778ca14b4e6 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:09:19 +0100 Subject: [PATCH 086/344] cleanup sync from content analysis actions --- packages/js/src/redux/actions/contentAnalysis.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/js/src/redux/actions/contentAnalysis.js b/packages/js/src/redux/actions/contentAnalysis.js index 56398e23ede..b00ddcbb606 100644 --- a/packages/js/src/redux/actions/contentAnalysis.js +++ b/packages/js/src/redux/actions/contentAnalysis.js @@ -1,5 +1,3 @@ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; - /* * Action types */ @@ -148,7 +146,6 @@ export function updateInclusiveLanguageResult( result ) { * @returns {Object} A set overall score action. */ export function setOverallReadabilityScore( overallScore ) { - MetaboxFieldSync.setFieldValue( "content_score", overallScore ); return { type: SET_OVERALL_READABILITY_SCORE, overallScore: overallScore, @@ -164,7 +161,6 @@ export function setOverallReadabilityScore( overallScore ) { * @returns {Object} A set overall score action. */ export function setOverallSeoScore( overallScore, keyword ) { - MetaboxFieldSync.setFieldValue( "linkdex", overallScore ); return { type: SET_OVERALL_SEO_SCORE, keyword: keyword, @@ -180,7 +176,6 @@ export function setOverallSeoScore( overallScore, keyword ) { * @returns {Object} A set overall score action. */ export function setOverallInclusiveLanguageScore( overallScore ) { - MetaboxFieldSync.setFieldValue( "inclusive_language_score", overallScore ); return { type: SET_OVERALL_INCLUSIVE_LANGUAGE_SCORE, overallScore: overallScore, From bfd38bf578bf563f726bc2f34141e7453911d68d Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:09:51 +0100 Subject: [PATCH 087/344] add content analysis to hidden fields sync --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index b0bc57f07a9..8760f81ff67 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -97,10 +97,10 @@ export const hiddenFieldsrSync = () => { // "twitter-image-id": getTwitterImageId, // schema_page_type: getPageType, // schema_article_type: getArticleType, - is_cornerstone: isCornerstoneContent, - // content_score: getReadabilityScore, - // linkdex: getSeoScore, - // inclusive_language_score: getInclusiveLanguageScore, + is_cornerstone: isCornerstoneContent, + content_score: getReadabilityScore, + linkdex: getSeoScore, + inclusive_language_score: getInclusiveLanguageScore, // "meta-robots-adv": getAdvanced, // bctitle: getBreadcrumbsTitle, // wpseo_canonical: getCanonical, From 3cc915af13d1ae3dc874520269eb7bf8d76fe40f Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 10:10:32 +0100 Subject: [PATCH 088/344] remove analysis fields side effect class --- .../js/src/helpers/fields/AnalysisFields.js | 159 ------------------ 1 file changed, 159 deletions(-) delete mode 100644 packages/js/src/helpers/fields/AnalysisFields.js diff --git a/packages/js/src/helpers/fields/AnalysisFields.js b/packages/js/src/helpers/fields/AnalysisFields.js deleted file mode 100644 index f1fbd442c3a..00000000000 --- a/packages/js/src/helpers/fields/AnalysisFields.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for the analysis. - */ -export default class AnalysisFields { - /** - * Getter for the keyphraseElement. - * - * @returns {HTMLElement|null} The keyphraseElement. - */ - static get keyphraseElement() { - return document.getElementById( window.wpseoScriptData?.isPost ? "yoast_wpseo_focuskw" : "hidden_wpseo_focuskw" ); - } - - /** - * Getter for the isCornerstoneElement. - * - * @returns {HTMLElement|null} The isCornerstoneElement. - */ - static get isCornerstoneElement() { - return document.getElementById( window.wpseoScriptData?.isPost ? "yoast_wpseo_is_cornerstone" : "hidden_wpseo_is_cornerstone" ); - } - - /** - * Getter for the SEO (overall) score hidden field. - * - * @returns {HTMLElement|null} The SEO score hidden field. - */ - static get seoScoreElement() { - return document.getElementById( window.wpseoScriptData?.isPost ? "yoast_wpseo_linkdex" : "hidden_wpseo_linkdex" ); - } - - /** - * Getter for the Readability (overall) score hidden field. - * - * @returns {HTMLElement|null} The Readability score hidden field. - */ - static get readabilityScoreElement() { - return document.getElementById( window.wpseoScriptData?.isPost ? "yoast_wpseo_content_score" : "hidden_wpseo_content_score" ); - } - - /** - * Getter for the inclusive language (overall) score hidden field. - * - * @returns {HTMLElement|null} The inclusive language score hidden field. - */ - static get inclusiveLanguageScoreElement() { - return document.getElementById( window.wpseoScriptData?.isPost ? "yoast_wpseo_inclusive_language_score" : "hidden_wpseo_inclusive_language_score" ); - } - - /** - * Setter for the keyphrase. - * - * @param {string} value The keyphrase. - * - * @returns {void} - */ - static set keyphrase( value ) { - if ( AnalysisFields.keyphraseElement ) { - AnalysisFields.keyphraseElement.value = value; - } - } - - /** - * Getter for the keyphrase. - * - * @returns {string} The keyphrase. - */ - static get keyphrase() { - return AnalysisFields.keyphraseElement?.value ?? ""; - } - - /** - * Setter for the isCornerstone. The element returns "true" and "false" but we should save "1" and "0". - * - * @param {boolean} value The isCornerstone. - * - * @returns {void} - */ - static set isCornerstone( value ) { - if ( AnalysisFields.isCornerstoneElement ) { - AnalysisFields.isCornerstoneElement.value = value ? "1" : "0"; - } - } - - /** - * Getter for the isCornerstone. True if value = "1". - * - * @returns {boolean} The isCornerstone. - */ - static get isCornerstone() { - return AnalysisFields.isCornerstoneElement?.value === "1"; - } - - /** - * Setter for the SEO (overall) score. - * - * @param {string} value The SEO (overall) score. - * - * @returns {void} - */ - static set seoScore( value ) { - if ( AnalysisFields.seoScoreElement ) { - AnalysisFields.seoScoreElement.value = value; - } - } - - /** - * Getter for the SEO (overall) score. - * - * @returns {string} The SEO (overall) score. - */ - static get seoScore() { - return AnalysisFields.seoScoreElement?.value ?? ""; - } - - /** - * Setter for the Readability (overall) score. - * - * @param {string} value The Readability (overall) score. - * - * @returns {void} - */ - static set readabilityScore( value ) { - if ( AnalysisFields.readabilityScoreElement ) { - AnalysisFields.readabilityScoreElement.value = value; - } - } - - /** - * Getter for the Readability (overall) score. - * - * @returns {string} The Readability (overall) score. - */ - static get readabilityScore() { - return AnalysisFields.readabilityScoreElement?.value ?? ""; - } - - /** - * Setter for the inclusive language (overall) score. - * - * @param {string} value The inclusive language (overall) score. - * - * @returns {void} - */ - static set inclusiveLanguageScore( value ) { - if ( AnalysisFields.inclusiveLanguageScoreElement ) { - AnalysisFields.inclusiveLanguageScoreElement.value = value; - } - } - - /** - * Getter for the inclusive language (overall) score. - * - * @returns {string} The inclusive language (overall) score. - */ - static get inclusiveLanguageScore() { - return AnalysisFields.inclusiveLanguageScoreElement?.value ?? ""; - } -} From 91398699005d111b2069b023e716134d46419d39 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 12:54:02 +0100 Subject: [PATCH 089/344] cleanup advanced fields --- .../js/src/helpers/fields/AdvancedFields.js | 178 ------------------ .../js/src/helpers/fields/hiddenFieldsSync.js | 44 ++--- .../js/src/redux/actions/advancedSettings.js | 7 - 3 files changed, 23 insertions(+), 206 deletions(-) delete mode 100644 packages/js/src/helpers/fields/AdvancedFields.js diff --git a/packages/js/src/helpers/fields/AdvancedFields.js b/packages/js/src/helpers/fields/AdvancedFields.js deleted file mode 100644 index 3831809de80..00000000000 --- a/packages/js/src/helpers/fields/AdvancedFields.js +++ /dev/null @@ -1,178 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for Advanced Settings. - */ -export default class AdvancedFields { - /** - * Getter for the noIndexElement. - * - * @returns {HTMLElement} The noIndexElement. - */ - static get noIndexElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_meta-robots-noindex" : "hidden_wpseo_noindex" ); - } - - /** - * Getter for the noFollowElement. - * - * @returns {HTMLElement} The noFollowElement. - */ - static get noFollowElement() { - return document.getElementById( "yoast_wpseo_meta-robots-nofollow" ); - } - - /** - * Getter for the advancedElement. - * - * @returns {HTMLElement} The advancedElement. - */ - static get advancedElement() { - return document.getElementById( "yoast_wpseo_meta-robots-adv" ); - } - - /** - * Getter for the breadcrumbsTitleElement. - * - * @returns {HTMLElement} The breadcrumbsTitleElement. - */ - static get breadcrumbsTitleElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_bctitle" : "hidden_wpseo_bctitle" ); - } - - /** - * Getter for the canonicalElement. - * - * @returns {HTMLElement} The canonicalElement. - */ - static get canonicalElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_canonical" : "hidden_wpseo_canonical" ); - } - - /** - * Getter for the wordproofTimestampElement. - * - * @returns {HTMLElement} The wordproofTimestampElement. - */ - static get wordproofTimestampElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_wordproof_timestamp" : "hidden_wpseo_wordproof_timestamp" ); - } - - /** - * Getter for the No Index setting. - * - * @returns {string} The No Index setting. - */ - static get noIndex() { - return AdvancedFields.noIndexElement && AdvancedFields.noIndexElement.value || ""; - } - - /** - * Setter for the No Index setting. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set noIndex( value ) { - AdvancedFields.noIndexElement.value = value; - } - - /** - * Getter for the No Follow setting. - * - * @returns {string} The No Follow setting. - */ - static get noFollow() { - return AdvancedFields.noFollowElement && AdvancedFields.noFollowElement.value || ""; - } - - /** - * Setter for the No Follow setting. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set noFollow( value ) { - AdvancedFields.noFollowElement.value = value; - } - - /** - * Getter for the Advanced (metarobots) setting. - * - * @returns {string} The Advanced (metarobots) setting. - */ - static get advanced() { - return AdvancedFields.advancedElement && AdvancedFields.advancedElement.value || ""; - } - - /** - * Setter for the Advanced (metarobots) setting. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set advanced( value ) { - AdvancedFields.advancedElement.value = value; - } - - /** - * Getter for the BreadCrumbsTitle setting. - * - * @returns {string} The BreadCrumbsTitle setting. - */ - static get breadcrumbsTitle() { - return AdvancedFields.breadcrumbsTitleElement && AdvancedFields.breadcrumbsTitleElement.value || ""; - } - - /** - * Setter for the BreadCrumbsTitle setting. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set breadcrumbsTitle( value ) { - AdvancedFields.breadcrumbsTitleElement.value = value; - } - - /** - * Getter for the Canonical URL setting. - * - * @returns {string} The Canonical URL setting. - */ - static get canonical() { - return AdvancedFields.canonicalElement && AdvancedFields.canonicalElement.value || ""; - } - - /** - * Setter for the Canonical URL setting. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set canonical( value ) { - AdvancedFields.canonicalElement.value = value; - } - - /** - * Getter for the Timestamp setting. - * - * @returns {boolean} The Timestamp setting. - */ - static get wordproofTimestamp() { - return AdvancedFields.wordproofTimestampElement && AdvancedFields.wordproofTimestampElement.value === "1" || false; - } - - /** - * Setter for the Timestamp setting. - * - * @param {boolean} value The value to set. - * - * @returns {void} - */ - static set wordproofTimestamp( value ) { - AdvancedFields.wordproofTimestampElement.value = value ? "1" : "0"; - } -} diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 8760f81ff67..4ca45b4b2fa 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -26,6 +26,7 @@ const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId */ const prepareValue = ( key, value ) => { switch ( key ) { + case "wordproof_timestamp": case "is_cornerstone": return value ? "1" : "0"; default: @@ -48,8 +49,7 @@ const createUpdater = () => { // Get the values from hidden fields. const hiddenFieldsData = {}; const wpseoMetaElement = document.getElementById( "wpseo_meta" ); - const inside = wpseoMetaElement?.querySelector( ".inside" ); - const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); + const hiddenFields = wpseoMetaElement?.querySelectorAll( "input[type=hidden]" ); forEach( hiddenFields, ( field ) => { if ( field.id ) { hiddenFieldsData[ field.id ] = field.value; @@ -65,11 +65,12 @@ const createUpdater = () => { const isPost = get( window, "wpseoScriptData.isPost", false ); const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; - const changedData = pickBy( data, ( value, key ) => hiddenFieldsData[ prefix + key ] && value !== hiddenFieldsData[ prefix + key ] ); + const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); console.log( { changedData } ); if ( changedData ) { forEach( changedData, ( value, key ) => { + console.log( prepareValue( key, value ) ); document.getElementById( prefix + key ).value = prepareValue( key, value ); } ); } @@ -84,28 +85,29 @@ export const hiddenFieldsrSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { focuskw: getFocusKeyphrase, - // "meta-robots-noindex": getNoIndex, - // "meta-robots-nofollow": getNoFollow, - // primary_category: getPrimaryCategoryId, - // "opengraph-title": getFacebookTitle, - // "opengraph-description": getFacebookDescription, - // "opengraph-image": getFacebookImageUrl, - // "opengraph-image-id": getFacebookImageId, - // "twitter-title": getTwitterTitle, - // "twitter-description": getTwitterDescription, - // "twitter-image": getTwitterImageUrl, - // "twitter-image-id": getTwitterImageId, - // schema_page_type: getPageType, - // schema_article_type: getArticleType, + "meta-robots-noindex": getNoIndex, + // Same as meta-robots-noindex for term metabox. + noindex: getNoIndex, + "meta-robots-nofollow": getNoFollow, + "meta-robots-adv": getAdvanced, + bctitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordproof_timestamp: getWordProofTimestamp, + primary_category_term: getPrimaryCategoryId, + "opengraph-title": getFacebookTitle, + "opengraph-description": getFacebookDescription, + "opengraph-image": getFacebookImageUrl, + "opengraph-image-id": getFacebookImageId, + "twitter-title": getTwitterTitle, + "twitter-description": getTwitterDescription, + "twitter-image": getTwitterImageUrl, + "twitter-image-id": getTwitterImageId, + schema_page_type: getPageType, + schema_article_type: getArticleType, is_cornerstone: isCornerstoneContent, content_score: getReadabilityScore, linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, - // "meta-robots-adv": getAdvanced, - // bctitle: getBreadcrumbsTitle, - // wpseo_canonical: getCanonical, - // wordproof_timestamp: getWordProofTimestamp, - } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index a933545a55e..e6ba3451741 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -1,4 +1,3 @@ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; import { get } from "lodash"; export const SET_NO_INDEX = "SET_NO_INDEX"; @@ -17,7 +16,6 @@ export const LOAD_ADVANCED_SETTINGS = "LOAD_ADVANCED_SETTINGS"; * @returns {Object} The action object. */ export const setNoIndex = ( value ) => { - MetaboxFieldSync.setNoIndex( value ); return { type: SET_NO_INDEX, value }; }; @@ -29,7 +27,6 @@ export const setNoIndex = ( value ) => { * @returns {Object} The action object. */ export const setNoFollow = ( value ) => { - MetaboxFieldSync.setFieldValue( "meta-robots-nofollow", value ); return { type: SET_NO_FOLLOW, value }; }; @@ -41,7 +38,6 @@ export const setNoFollow = ( value ) => { * @returns {Object} The action object. */ export const setAdvanced = ( value ) => { - MetaboxFieldSync.setFieldValue( "meta-robots-adv", value.join( "," ) ); return { type: SET_ADVANCED, value }; }; @@ -53,7 +49,6 @@ export const setAdvanced = ( value ) => { * @returns {Object} The action object. */ export const setBreadcrumbsTitle = ( value ) => { - MetaboxFieldSync.setFieldValue( "bctitle", value ); return { type: SET_BREADCRUMBS_TITLE, value }; }; @@ -65,7 +60,6 @@ export const setBreadcrumbsTitle = ( value ) => { * @returns {Object} The action object. */ export const setCanonical = ( value ) => { - MetaboxFieldSync.setFieldValue( "canonical", value ); return { type: SET_CANONICAL_URL, value }; }; @@ -77,7 +71,6 @@ export const setCanonical = ( value ) => { * @returns {Object} The action object. */ export const setWordProofTimestamp = ( value ) => { - MetaboxFieldSync.setBooleanFieldValue( "wordproof_timestamp", value ); return { type: SET_WORDPROOF_TIMESTAMP, value }; }; From b24478f3345ad2c2ee27327c8e990e033ff84c86 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 14:03:52 +0100 Subject: [PATCH 090/344] Fix social preview sync --- .../js/src/helpers/fields/hiddenFieldsSync.js | 45 ++++++++++++++++--- packages/js/src/initializers/editor-store.js | 6 ++- .../js/src/redux/actions/facebookEditor.js | 29 +++--------- .../js/src/redux/actions/twitterEditor.js | 28 +++--------- .../js/src/redux/reducers/facebookEditor.js | 2 +- .../js/src/redux/reducers/twitterEditor.js | 2 +- 6 files changed, 55 insertions(+), 57 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 4ca45b4b2fa..540c2f669d3 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,3 +1,4 @@ +/* eslint-disable complexity */ /* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; @@ -16,6 +17,30 @@ import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical */ const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); +/** + * Prepare twitter title to be saved in hidden field. + * @param {string} value The value to be saved. + * @returns {string} The value to be saved. + */ +const prepareSocialTitle = ( value ) => { + if ( value.trim() === select( STORE ).getSocialTitleTemplate().trim() ) { + return ""; + } + return value; +}; + +/** + * Prepare twitter and facebook description to be saved in hidden field. + * @param {string} value The value to be saved. + * @returns {string} The value to be saved. + */ +const prepareSocialDescription = ( value ) => { + if ( value.trim() === select( STORE ).getSocialDescriptionTemplate().trim() ) { + return ""; + } + return value; +}; + /** * Prepare value to be saved in hidden field. * @@ -29,6 +54,12 @@ const prepareValue = ( key, value ) => { case "wordproof_timestamp": case "is_cornerstone": return value ? "1" : "0"; + case "twitter-title": + case "opengraph-title": + return prepareSocialTitle( value ); + case "twitter-description": + case "opengraph-description": + return prepareSocialDescription( value ); default: return value; } @@ -70,7 +101,7 @@ const createUpdater = () => { if ( changedData ) { forEach( changedData, ( value, key ) => { - console.log( prepareValue( key, value ) ); + console.log( typeof prepareValue( key, value ), prepareValue( key, value ) ); document.getElementById( prefix + key ).value = prepareValue( key, value ); } ); } @@ -93,7 +124,7 @@ export const hiddenFieldsrSync = () => { bctitle: getBreadcrumbsTitle, canonical: getCanonical, wordproof_timestamp: getWordProofTimestamp, - primary_category_term: getPrimaryCategoryId, + // primary_category_term: getPrimaryCategoryId, "opengraph-title": getFacebookTitle, "opengraph-description": getFacebookDescription, "opengraph-image": getFacebookImageUrl, @@ -102,12 +133,12 @@ export const hiddenFieldsrSync = () => { "twitter-description": getTwitterDescription, "twitter-image": getTwitterImageUrl, "twitter-image-id": getTwitterImageId, - schema_page_type: getPageType, - schema_article_type: getArticleType, + // schema_page_type: getPageType, + // schema_article_type: getArticleType, is_cornerstone: isCornerstoneContent, - content_score: getReadabilityScore, - linkdex: getSeoScore, - inclusive_language_score: getInclusiveLanguageScore, + // content_score: getReadabilityScore, + // linkdex: getSeoScore, + // inclusive_language_score: getInclusiveLanguageScore, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 293cf77064b..451ac9ccd5f 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -28,7 +28,7 @@ const populateStore = store => { } ) ); - const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); @@ -37,6 +37,10 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); + // Set intial values for social preview. + store.dispatch( actions.loadTwitterPreviewData() ); + store.dispatch( actions.loadFacebookPreviewData() ); + store.dispatch( actions.loadAdvancedSettingsData() ); store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); diff --git a/packages/js/src/redux/actions/facebookEditor.js b/packages/js/src/redux/actions/facebookEditor.js index f7d4fc1a724..5cd11215e09 100644 --- a/packages/js/src/redux/actions/facebookEditor.js +++ b/packages/js/src/redux/actions/facebookEditor.js @@ -1,9 +1,6 @@ /* External dependencies */ import { select } from "@wordpress/data"; - -/* Internal dependencies */ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; - +import { get } from "lodash"; export const SET_FACEBOOK_TITLE = "SET_FACEBOOK_TITLE"; export const SET_FACEBOOK_DESCRIPTION = "SET_FACEBOOK_DESCRIPTION"; @@ -19,12 +16,6 @@ export const LOAD_FACEBOOK_PREVIEW = "LOAD_FACEBOOK_PREVIEW"; * @returns {object} The action object. */ export const setFacebookPreviewTitle = ( title ) => { - if ( title.trim() === select( "yoast-seo/editor" ).getSocialTitleTemplate().trim() ) { - MetaboxFieldSync.setFieldValue( "opengraph-title", "" ); - } else { - MetaboxFieldSync.setFieldValue( "opengraph-title", title ); - } - return { type: SET_FACEBOOK_TITLE, title }; }; @@ -36,12 +27,6 @@ export const setFacebookPreviewTitle = ( title ) => { * @returns {object} The action object. */ export const setFacebookPreviewDescription = ( description ) => { - if ( description.trim() === select( "yoast-seo/editor" ).getSocialDescriptionTemplate().trim() ) { - MetaboxFieldSync.setFieldValue( "opengraph-description", "" ); - } else { - MetaboxFieldSync.setFieldValue( "opengraph-description", description ); - } - return { type: SET_FACEBOOK_DESCRIPTION, description }; }; @@ -53,8 +38,6 @@ export const setFacebookPreviewDescription = ( description ) => { * @returns {object} The action object. */ export const setFacebookPreviewImage = ( image ) => { - MetaboxFieldSync.setFieldValue( "opengraph-image", image.url ); - MetaboxFieldSync.setFieldValue( "opengraph-image-id", image.id ); return { type: SET_FACEBOOK_IMAGE, image }; }; @@ -64,8 +47,6 @@ export const setFacebookPreviewImage = ( image ) => { * @returns {object} The action object. */ export const clearFacebookPreviewImage = () => { - MetaboxFieldSync.setFieldValue( "opengraph-image", "" ); - MetaboxFieldSync.setFieldValue( "opengraph-image-id", "" ); return { type: CLEAR_FACEBOOK_IMAGE }; }; @@ -82,9 +63,9 @@ export const loadFacebookPreviewData = () => { return { type: LOAD_FACEBOOK_PREVIEW, - imageId: Number( MetaboxFieldSync.getInitialValue( "opengraph-image-id" ) ), - imageUrl: MetaboxFieldSync.getInitialValue( "opengraph-image" ), - description: MetaboxFieldSync.getInitialValue( "opengraph-description" ) || getSocialDescriptionTemplate(), - title: MetaboxFieldSync.getInitialValue( "opengraph-title" ) || getSocialTitleTemplate(), + imageId: get( window, "wpseoScriptData.metabox.metadata.opengraph-image-id", "" ), + imageUrl: get( window, "wpseoScriptData.metabox.metadata.opengraph-image", "" ), + description: get( window, "wpseoScriptData.metabox.metadata.opengraph-description", "" ) || getSocialDescriptionTemplate(), + title: get( window, "wpseoScriptData.metabox.metadata.opengraph-title", "" ) || getSocialTitleTemplate(), }; }; diff --git a/packages/js/src/redux/actions/twitterEditor.js b/packages/js/src/redux/actions/twitterEditor.js index 2554cf71214..11a5009b3e7 100644 --- a/packages/js/src/redux/actions/twitterEditor.js +++ b/packages/js/src/redux/actions/twitterEditor.js @@ -1,8 +1,6 @@ /* External dependencies */ import { select } from "@wordpress/data"; - -/* Internal dependencies */ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { get } from "lodash"; export const SET_TWITTER_TITLE = "SET_TWITTER_TITLE"; export const SET_TWITTER_DESCRIPTION = "SET_TWITTER_DESCRIPTION"; @@ -18,12 +16,6 @@ export const LOAD_TWITTER_PREVIEW = "LOAD_TWITTER_PREVIEW"; * @returns {Object} The action object. */ export const setTwitterPreviewTitle = ( title ) => { - if ( title.trim() === select( "yoast-seo/editor" ).getSocialTitleTemplate().trim() ) { - MetaboxFieldSync.setFieldValue( "twitter-title", "" ); - } else { - MetaboxFieldSync.setFieldValue( "twitter-title", title ); - } - return { type: SET_TWITTER_TITLE, title }; }; @@ -35,12 +27,6 @@ export const setTwitterPreviewTitle = ( title ) => { * @returns {Object} The action object. */ export const setTwitterPreviewDescription = ( description ) => { - if ( description.trim() === select( "yoast-seo/editor" ).getSocialDescriptionTemplate().trim() ) { - MetaboxFieldSync.setFieldValue( "twitter-description", "" ); - } else { - MetaboxFieldSync.setFieldValue( "twitter-description", description ); - } - return { type: SET_TWITTER_DESCRIPTION, description }; }; @@ -52,8 +38,6 @@ export const setTwitterPreviewDescription = ( description ) => { * @returns {Object} The action object. */ export const setTwitterPreviewImage = ( image ) => { - MetaboxFieldSync.setFieldValue( "twitter-image-id", image.id ); - MetaboxFieldSync.setFieldValue( "twitter-image", image.url ); return { type: SET_TWITTER_IMAGE, image }; }; @@ -63,8 +47,6 @@ export const setTwitterPreviewImage = ( image ) => { * @returns {Object} The action object. */ export const clearTwitterPreviewImage = () => { - MetaboxFieldSync.setFieldValue( "twitter-image-id", "" ); - MetaboxFieldSync.setFieldValue( "twitter-image", "" ); return { type: CLEAR_TWITTER_IMAGE }; }; @@ -81,9 +63,9 @@ export const loadTwitterPreviewData = () => { return { type: LOAD_TWITTER_PREVIEW, - imageId: MetaboxFieldSync.getInitialValue( "twitter-image-id" ), - imageUrl: MetaboxFieldSync.getInitialValue( "twitter-image" ), - description: MetaboxFieldSync.getInitialValue( "twitter-description" ) || getSocialDescriptionTemplate(), - title: MetaboxFieldSync.getInitialValue( "twitter-title" ) || getSocialTitleTemplate(), + imageId: get( window, "wpseoScriptData.metabox.metadata.twitter-image-id", "" ), + imageUrl: get( window, "wpseoScriptData.metabox.metadata.twitter-image", "" ), + description: get( window, "wpseoScriptData.metabox.metadata.twitter-description", "" ) || getSocialDescriptionTemplate(), + title: get( window, "wpseoScriptData.metabox.metadata.twitter-title", "" ) || getSocialTitleTemplate(), }; }; diff --git a/packages/js/src/redux/reducers/facebookEditor.js b/packages/js/src/redux/reducers/facebookEditor.js index 34e7ab01507..b5ac6d2c8d8 100644 --- a/packages/js/src/redux/reducers/facebookEditor.js +++ b/packages/js/src/redux/reducers/facebookEditor.js @@ -37,7 +37,7 @@ const facebookReducer = ( state = initialState, action ) => { ...state, title: action.title, description: action.description, - image: { id: action.id, url: action.imageUrl }, + image: { id: action.imageId, url: action.imageUrl }, }; case SET_FACEBOOK_TITLE: return { ...state, title: action.title }; diff --git a/packages/js/src/redux/reducers/twitterEditor.js b/packages/js/src/redux/reducers/twitterEditor.js index 8d4e8806331..ddc7e64fde2 100644 --- a/packages/js/src/redux/reducers/twitterEditor.js +++ b/packages/js/src/redux/reducers/twitterEditor.js @@ -31,7 +31,7 @@ const twitterReducer = ( state = initialState, action ) => { ...state, title: action.title, description: action.description, - image: { id: action.id, url: action.imageUrl }, + image: { id: action.imageId, url: action.imageUrl }, }; case SET_TWITTER_TITLE: return { ...state, title: action.title }; From e7e44b129c14ae7a7ae82ae79e6ecdc141e1fc46 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 14:05:40 +0100 Subject: [PATCH 091/344] cleanup social side effect classes --- .../js/src/helpers/fields/FacebookFields.js | 120 ------------------ .../js/src/helpers/fields/TwitterFields.js | 120 ------------------ 2 files changed, 240 deletions(-) delete mode 100644 packages/js/src/helpers/fields/FacebookFields.js delete mode 100644 packages/js/src/helpers/fields/TwitterFields.js diff --git a/packages/js/src/helpers/fields/FacebookFields.js b/packages/js/src/helpers/fields/FacebookFields.js deleted file mode 100644 index 02f12321154..00000000000 --- a/packages/js/src/helpers/fields/FacebookFields.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for Facebook. - */ -export default class FacebookFields { - /** - * Getter for the titleElement. - * - * @returns {HTMLElement} The titleElement. - */ - static get titleElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_opengraph-title" : "hidden_wpseo_opengraph-title" ); - } - - /** - * Getter for the descriptionElement. - * - * @returns {HTMLElement} The descriptionElement. - */ - static get descriptionElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_opengraph-description" : "hidden_wpseo_opengraph-description" ); - } - - /** - * Getter for the imageIdElement. - * - * @returns {HTMLElement} The imageIdElement. - */ - static get imageIdElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_opengraph-image-id" : "hidden_wpseo_opengraph-image-id" ); - } - - /** - * Getter for the imageUrlElement. - * - * @returns {HTMLElement} The imageUrlElement. - */ - static get imageUrlElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_opengraph-image" : "hidden_wpseo_opengraph-image" ); - } - - /** - * Getter for the Facebook title. - * - * @returns {string} The Facebook title. - */ - static get title() { - return FacebookFields.titleElement.value; - } - - /** - * Setter for the Facebook title. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set title( value ) { - FacebookFields.titleElement.value = value; - } - - /** - * Setter for the Facebook description. - * - * @param {string} value The Facebook description. - * - * @returns {void} - */ - static set description( value ) { - FacebookFields.descriptionElement.value = value; - } - - /** - * Getter for the Facebook description. - * - * @returns {string} The Facebook description. - */ - static get description() { - return FacebookFields.descriptionElement.value; - } - - /** - * Setter for the Facebook imageId. - * - * @param {string} value The Facebook imageId. - * - * @returns {void} - */ - static set imageId( value ) { - FacebookFields.imageIdElement.value = value; - } - - /** - * Getter for the Facebook imageId. - * - * @returns {string} The Facebook imageId. - */ - static get imageId() { - return FacebookFields.imageIdElement.value; - } - - /** - * Setter for the Facebook imageUrl. - * - * @param {string} value The Facebook imageUrl. - * - * @returns {void} - */ - static set imageUrl( value ) { - FacebookFields.imageUrlElement.value = value; - } - - /** - * Getter for the Facebook imageUrl. - * - * @returns {string} The Facebook imageUrl. - */ - static get imageUrl() { - return FacebookFields.imageUrlElement.value; - } -} diff --git a/packages/js/src/helpers/fields/TwitterFields.js b/packages/js/src/helpers/fields/TwitterFields.js deleted file mode 100644 index 609b8b02500..00000000000 --- a/packages/js/src/helpers/fields/TwitterFields.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for Twitter. - */ -export default class TwitterFields { - /** - * Getter for the titleElement. - * - * @returns {HTMLElement} The titleElement. - */ - static get titleElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_twitter-title" : "hidden_wpseo_twitter-title" ); - } - - /** - * Getter for the descriptionElement. - * - * @returns {HTMLElement} The descriptionElement. - */ - static get descriptionElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_twitter-description" : "hidden_wpseo_twitter-description" ); - } - - /** - * Getter for the imageIdElement. - * - * @returns {HTMLElement} The imageIdElement. - */ - static get imageIdElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_twitter-image-id" : "hidden_wpseo_twitter-image-id" ); - } - - /** - * Getter for the imageUrlElement. - * - * @returns {HTMLElement} The imageUrlElement. - */ - static get imageUrlElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_twitter-image" : "hidden_wpseo_twitter-image" ); - } - - /** - * Getter for the Twitter title. - * - * @returns {string} The Twitter title. - */ - static get title() { - return TwitterFields.titleElement.value; - } - - /** - * Setter for the Twitter title. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set title( value ) { - TwitterFields.titleElement.value = value; - } - - /** - * Setter for the Twitter description. - * - * @param {string} value The Twitter description. - * - * @returns {void} - */ - static set description( value ) { - TwitterFields.descriptionElement.value = value; - } - - /** - * Getter for the Twitter description. - * - * @returns {string} The Twitter description. - */ - static get description() { - return TwitterFields.descriptionElement.value; - } - - /** - * Setter for the Twitter imageId. - * - * @param {string} value The Twitter imageId. - * - * @returns {void} - */ - static set imageId( value ) { - TwitterFields.imageIdElement.value = value; - } - - /** - * Getter for the Twitter imageId. - * - * @returns {string} The Twitter imageId. - */ - static get imageId() { - return TwitterFields.imageIdElement.value; - } - - /** - * Setter for the Twitter imageUrl. - * - * @param {string} value The Twitter imageUrl. - * - * @returns {void} - */ - static set imageUrl( value ) { - TwitterFields.imageUrlElement.value = value; - } - - /** - * Getter for the Twitter imageUrl. - * - * @returns {string} The Twitter imageUrl. - */ - static get imageUrl() { - return TwitterFields.imageUrlElement.value; - } -} From 94f49175140c20ff1a058d0cd5c13bd6bc8c6d8e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 14:09:09 +0100 Subject: [PATCH 092/344] sync schema fields --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 4 ++-- packages/js/src/redux/actions/schemaTab.js | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 540c2f669d3..22ae7a3ff75 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -133,8 +133,8 @@ export const hiddenFieldsrSync = () => { "twitter-description": getTwitterDescription, "twitter-image": getTwitterImageUrl, "twitter-image-id": getTwitterImageId, - // schema_page_type: getPageType, - // schema_article_type: getArticleType, + schema_page_type: getPageType, + schema_article_type: getArticleType, is_cornerstone: isCornerstoneContent, // content_score: getReadabilityScore, // linkdex: getSeoScore, diff --git a/packages/js/src/redux/actions/schemaTab.js b/packages/js/src/redux/actions/schemaTab.js index 1ef197dd479..4b1b42d4e9f 100644 --- a/packages/js/src/redux/actions/schemaTab.js +++ b/packages/js/src/redux/actions/schemaTab.js @@ -1,4 +1,4 @@ -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { get } from "lodash"; export const SET_PAGE_TYPE = "SET_PAGE_TYPE"; export const SET_ARTICLE_TYPE = "SET_ARTICLE_TYPE"; @@ -13,7 +13,6 @@ export const GET_SCHEMA_ARTICLE_DATA = "GET_SCHEMA_ARTICLE_DATA"; * @returns {object} The action object. */ export const setPageType = ( pageType ) => { - MetaboxFieldSync.setFieldValue( "schema_page_type", pageType ); return { type: SET_PAGE_TYPE, pageType }; }; @@ -25,7 +24,6 @@ export const setPageType = ( pageType ) => { * @returns {object} The action object. */ export const setArticleType = ( articleType ) => { - MetaboxFieldSync.setFieldValue( "schema_article_type", articleType ); return { type: SET_ARTICLE_TYPE, articleType }; }; @@ -37,8 +35,8 @@ export const setArticleType = ( articleType ) => { export const getSchemaPageData = () => { return { type: GET_SCHEMA_PAGE_DATA, - pageType: MetaboxFieldSync.getInitialValue( "schema_page_type" ), - defaultPageType: MetaboxFieldSync.getInitialValue( "schema_page_type_default" ), + pageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type", "" ), + defaultPageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type_default", "" ), }; }; @@ -50,7 +48,7 @@ export const getSchemaPageData = () => { export const getSchemaArticleData = () => { return { type: GET_SCHEMA_ARTICLE_DATA, - articleType: MetaboxFieldSync.getInitialValue( "schema_article_type" ), - defaultArticleType: MetaboxFieldSync.getInitialValue( "schema_article_type_default" ), + articleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", "" ), + defaultArticleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type_default", "" ), }; }; From e4eaaf2e488b67e9019a4807552f69dcff24d2c5 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 14:15:31 +0100 Subject: [PATCH 093/344] sync seo scores --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 22ae7a3ff75..028ebd5d5a4 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -101,7 +101,6 @@ const createUpdater = () => { if ( changedData ) { forEach( changedData, ( value, key ) => { - console.log( typeof prepareValue( key, value ), prepareValue( key, value ) ); document.getElementById( prefix + key ).value = prepareValue( key, value ); } ); } @@ -136,9 +135,9 @@ export const hiddenFieldsrSync = () => { schema_page_type: getPageType, schema_article_type: getArticleType, is_cornerstone: isCornerstoneContent, - // content_score: getReadabilityScore, - // linkdex: getSeoScore, - // inclusive_language_score: getInclusiveLanguageScore, + content_score: getReadabilityScore, + linkdex: getSeoScore, + inclusive_language_score: getInclusiveLanguageScore, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); From 4f3af56b7d4b36267d4ce55e9e1f4f484be0375f Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 14:35:39 +0100 Subject: [PATCH 094/344] sync estimate reading times --- packages/js/src/constants/sync.js | 1 + packages/js/src/helpers/fields/additionalFieldsStore.js | 8 ++++++++ packages/js/src/helpers/fields/blockEditorSync.js | 4 +++- packages/js/src/helpers/fields/hiddenFieldsSync.js | 9 ++------- packages/js/src/insights/redux/actions.js | 6 ++---- 5 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 packages/js/src/helpers/fields/additionalFieldsStore.js diff --git a/packages/js/src/constants/sync.js b/packages/js/src/constants/sync.js index a8325d7ef2d..32b4a829582 100644 --- a/packages/js/src/constants/sync.js +++ b/packages/js/src/constants/sync.js @@ -22,6 +22,7 @@ export const METADATA_KEYS = { wordProofTimestamp: "_yoast_wpseo_wordproof_timestamp", seoTitle: "_yoast_wpseo_title", seoDescription: "_yoast_wpseo_metadesc", + readingTime: "_yoast_wpseo_estimated-reading-time-minutes", }; export const SYNC_TIME = { diff --git a/packages/js/src/helpers/fields/additionalFieldsStore.js b/packages/js/src/helpers/fields/additionalFieldsStore.js new file mode 100644 index 00000000000..6af12b33d12 --- /dev/null +++ b/packages/js/src/helpers/fields/additionalFieldsStore.js @@ -0,0 +1,8 @@ +import { select } from "@wordpress/data"; +import { STORE } from "../../constants"; + +/** + * Retrieves the estimated reading time from the store. + * @returns {string} The estimated reading time. + */ +export const getEstimatedReadingTime = () => select( STORE ).getEstimatedReadingTime().toString(); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 58a77965e6f..7da6c5c9ff2 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -8,6 +8,7 @@ import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; +import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** * Retrieves primary terms from store methods. @@ -15,7 +16,7 @@ import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; * @returns {integer} The no index value. */ const getPrimaryTerms = () => { - const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", [] ); + const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); const getPrimaryTermsStore = {}; const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { @@ -94,6 +95,7 @@ export const blockEditorSync = () => { wordProofTimestamp: getWordProofTimestamp, seoTitle: getSeoTitle, seoDescription: getSeoDescription, + readingTime: getEstimatedReadingTime, ...getPrimaryTerms(), } ), diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 028ebd5d5a4..ab6be57baff 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -9,13 +9,7 @@ import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterIm import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; - -/** - * Retrieves the no index value. - * - * @returns {integer} The no index value. - */ -const getPrimaryCategoryId = () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ); +import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** * Prepare twitter title to be saved in hidden field. @@ -138,6 +132,7 @@ export const hiddenFieldsrSync = () => { content_score: getReadabilityScore, linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, + "estimated-reading-time-minutes": getEstimatedReadingTime, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); diff --git a/packages/js/src/insights/redux/actions.js b/packages/js/src/insights/redux/actions.js index 0756ddd0f03..3fc229a6a3a 100644 --- a/packages/js/src/insights/redux/actions.js +++ b/packages/js/src/insights/redux/actions.js @@ -1,5 +1,4 @@ -import { toSafeInteger } from "lodash"; -import MetaboxFieldSync from "../../helpers/fields/MetaboxFieldSync"; +import { toSafeInteger, get } from "lodash"; export const SET_ESTIMATED_READING_TIME = "SET_ESTIMATED_READING_TIME"; export const LOAD_ESTIMATED_READING_TIME = "LOAD_ESTIMATED_READING_TIME"; @@ -15,7 +14,6 @@ export const SET_TEXT_LENGTH = "SET_TEXT_LENGTH"; * @returns {Object} The SET_ESTIMATED_READING_TIME action. */ export const setEstimatedReadingTime = estimatedReadingTime => { - MetaboxFieldSync.setFieldValueBySingleId( "yoast_wpseo_estimated-reading-time-minutes", estimatedReadingTime.toString() ); return { type: SET_ESTIMATED_READING_TIME, payload: estimatedReadingTime, @@ -29,7 +27,7 @@ export const setEstimatedReadingTime = estimatedReadingTime => { */ export const loadEstimatedReadingTime = () => ( { type: LOAD_ESTIMATED_READING_TIME, - payload: toSafeInteger( MetaboxFieldSync.getInitialValue( "estimated-reading-time-minutes" ) ), + payload: toSafeInteger( get( window, "wpseoScriptData.metabox.metadata.estimated-reading-time-minutes", 0 ) ), } ); /** From 1223f8d9ad7c9411f17452ff696fb9ac5b447f4e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 15:10:56 +0100 Subject: [PATCH 095/344] rename id for primary category --- admin/class-primary-term-admin.php | 2 +- packages/js/src/analysis/PostDataCollector.js | 2 +- packages/js/src/initializers/primary-category.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 85c0c888e2c..a8da8c9df51 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -80,7 +80,7 @@ protected function primary_term_field( $taxonomy_name ) { * @return string The field id. */ protected function generate_field_id( $taxonomy_name ) { - return 'yoast-wpseo-primary-' . $taxonomy_name; + return 'yoast_wpseo_primary_' . $taxonomy_name; } /** diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 4e2d63487b3..bfc7e91d4ad 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -347,7 +347,7 @@ PostDataCollector.prototype.bindElementEvents = function( refreshAnalysis ) { * @returns {void} */ PostDataCollector.prototype.changeElementEventBinder = function( refreshAnalysis ) { - var elems = [ "#yoast-wpseo-primary-category", '.categorychecklist input[name="post_category[]"]' ]; + var elems = [ "#yoast_wpseo_primary_category", '.categorychecklist input[name="post_category[]"]' ]; for ( var i = 0; i < elems.length; i++ ) { $( elems[ i ] ).on( "change", refreshAnalysis ); } diff --git a/packages/js/src/initializers/primary-category.js b/packages/js/src/initializers/primary-category.js index 15250e6c3d7..007af1d6b11 100644 --- a/packages/js/src/initializers/primary-category.js +++ b/packages/js/src/initializers/primary-category.js @@ -45,7 +45,7 @@ export default function initPrimaryCategory( $ ) { function getPrimaryTerm( taxonomyName ) { var primaryTermInput; - primaryTermInput = $( "#yoast-wpseo-primary-" + taxonomyName ); + primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName ); return primaryTermInput.val(); } @@ -76,7 +76,7 @@ export default function initPrimaryCategory( $ ) { * @returns {void} */ function setPrimaryTerm( taxonomyName, termId ) { - const primaryTermInput = $( "#yoast-wpseo-primary-" + taxonomyName ); + const primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName ); primaryTermInput.val( termId ).trigger( "change" ); const yoastEditor = dispatch( "yoast-seo/editor" ); From 34fb758734fca828c75f8ae9499464d67118071d Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 15:11:18 +0100 Subject: [PATCH 096/344] cleanup console logs --- packages/js/src/helpers/fields/blockEditorSync.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 7da6c5c9ff2..37fe709612b 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -45,10 +45,8 @@ const createUpdater = () => { if ( ! metadata || ! data ) { return; } - console.log( { data } ); - console.log( { metadata } ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); - console.log( { changedData } ); if ( changedData ) { const newMetadata = {}; @@ -56,8 +54,6 @@ const createUpdater = () => { newMetadata[ METADATA_KEYS[ key ] ] = value; } ); - console.log( { newMetadata } ); - editPost( { meta: newMetadata, } ); From 45c286f415330cc58aa066122c6232ad58608e24 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 6 Mar 2024 16:00:30 +0100 Subject: [PATCH 097/344] sync primary category and terms --- .../js/src/helpers/fields/hiddenFieldsSync.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index ab6be57baff..fc97c3fc30e 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -11,6 +11,22 @@ import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoSco import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; import { getEstimatedReadingTime } from "./additionalFieldsStore"; +/** + * Retrieves primary terms from store methods. + * + * @returns {integer} The no index value. + */ +const getPrimaryTerms = () => { + const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); + const getPrimaryTermsStore = {}; + const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( STORE )?.getPrimaryTaxonomyId( taxonomy ) ); + } ); + return getPrimaryTermsStore; +}; + /** * Prepare twitter title to be saved in hidden field. * @param {string} value The value to be saved. @@ -84,14 +100,13 @@ const createUpdater = () => { if ( ! hiddenFieldsData || ! data ) { return; } - console.log( { data } ); console.log( { hiddenFieldsData } ); const isPost = get( window, "wpseoScriptData.isPost", false ); const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); - console.log( { changedData } ); + console.log( changedData ); if ( changedData ) { forEach( changedData, ( value, key ) => { @@ -133,6 +148,8 @@ export const hiddenFieldsrSync = () => { linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, "estimated-reading-time-minutes": getEstimatedReadingTime, + primary_category: () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ), + ...getPrimaryTerms(), } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); From 6078d5fb52c2e6fefaeb97f1aefdabe1a4d80990 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 16:42:10 +0100 Subject: [PATCH 098/344] cleanup side effecto from primary term action and added sync --- packages/js/src/components/PrimaryTaxonomyPicker.js | 3 --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index 5e6ceb871ce..9a6067a949b 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -6,7 +6,6 @@ import apiFetch from "@wordpress/api-fetch"; import { addQueryArgs } from "@wordpress/url"; import styled from "styled-components"; import { difference, noop } from "lodash"; -import MetaboxFieldSync from "../helpers/fields/MetaboxFieldSync"; /* Internal dependencies */ import TaxonomyPicker from "./TaxonomyPicker"; @@ -191,8 +190,6 @@ class PrimaryTaxonomyPicker extends Component { this.updateReplacementVariable( termId ); this.props.setPrimaryTaxonomyId( name, termId ); - - MetaboxFieldSync.setFieldValue( `primary_${name}`, termId === -1 ? "" : termId ); } /** diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index fc97c3fc30e..1b5b92d5460 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -71,6 +71,9 @@ const prepareValue = ( key, value ) => { case "opengraph-description": return prepareSocialDescription( value ); default: + if ( /^primary_/.test( key ) ) { + return value === -1 ? "" : String( value ); + } return value; } }; From 14cc9b038d2007cac30966bc59f668d063bd3cd8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 16:42:22 +0100 Subject: [PATCH 099/344] cleanup side effect classes --- .../fields/EstimatedReadingTimeFields.js | 36 ------ .../js/src/helpers/fields/MetaboxFieldSync.js | 114 ------------------ 2 files changed, 150 deletions(-) delete mode 100644 packages/js/src/helpers/fields/EstimatedReadingTimeFields.js delete mode 100644 packages/js/src/helpers/fields/MetaboxFieldSync.js diff --git a/packages/js/src/helpers/fields/EstimatedReadingTimeFields.js b/packages/js/src/helpers/fields/EstimatedReadingTimeFields.js deleted file mode 100644 index 01264eb6e35..00000000000 --- a/packages/js/src/helpers/fields/EstimatedReadingTimeFields.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for Estimated Reading Time (ert). - */ -export default class EstimatedReadingTimeFields { - /** - * Getter for the estimated reading time element. - * - * @returns {HTMLElement} The estimatedReadingTimeElement. - */ - static get estimatedReadingTimeElement() { - return document.getElementById( "yoast_wpseo_estimated-reading-time-minutes" ); - } - - /** - * Getter for the estimated reading time. - * - * @returns {string} The estimated reading time. - */ - static get estimatedReadingTime() { - return EstimatedReadingTimeFields.estimatedReadingTimeElement && - EstimatedReadingTimeFields.estimatedReadingTimeElement.value || ""; - } - - /** - * Setter for the estimated reading time. - * - * @param {string} value The value to set. - * - * @returns {void} - */ - static set estimatedReadingTime( value ) { - if ( EstimatedReadingTimeFields.estimatedReadingTimeElement ) { - EstimatedReadingTimeFields.estimatedReadingTimeElement.value = value; - } - } -} diff --git a/packages/js/src/helpers/fields/MetaboxFieldSync.js b/packages/js/src/helpers/fields/MetaboxFieldSync.js deleted file mode 100644 index 6f52ed72796..00000000000 --- a/packages/js/src/helpers/fields/MetaboxFieldSync.js +++ /dev/null @@ -1,114 +0,0 @@ -import { get } from "lodash"; -/** - * This class is responsible for syncing hidden fields with store. - */ -export default class MetaboxFieldSync { - static isPost = get( window, "wpseoScriptData.isPost", false ); - static metaPrefix = "_yoast_wpseo_"; - - // Whether we are handling a post or a term. - static idPrefix = this.isPost ? "yoast_wpseo_" : "hidden_wpseo_"; - - static booleanFields = [ "isCornerstone", "wordproof_timestamp" ]; - - /** - * Get input element by key. - * - * @param {string} fieldKey The key of the input element. - * @returns {HTMLElement} The input element. - */ - static getInputElement( fieldKey ) { - return document.getElementById( this.idPrefix + fieldKey ); - } - - /** - * Get the initial value of a field. Same location in window object for post and term. - * - * @param {string} fieldKey The field key. - * @returns {value} The initial value of the field. - */ - static getInitialValue( fieldKey ) { - return window.wpseoScriptData?.metabox?.metadata[ fieldKey ]; - } - - /** - * Get no index value. - * @param {string} value The value. - * @returns {void} - */ - static getNoIndex() { - if ( this.isPost ) { - return get( window, "wpseoScriptData.metabox.metadata.meta-robots-noindex", "" ); - } - return get( window, "wpseoScriptData.metabox.metadata.noindex", "" ); - } - - /** - * Toggle the hidden field value. - * - * @param {string} fieldkey The field key. - * @returns {void} - */ - static toggleFieldValue( fieldkey ) { - const inputElement = this.getInputElement( fieldkey ); - if ( inputElement ) { - const newValue = inputElement.value === "1" ? "0" : "1"; - this.setFieldValue( fieldkey, newValue ); - } - } - - /** - * Set the value of a boolean field. - * @param {string} fieldKey The field key. - * @param {value} value The value of the field. - * @returns {value} The prepared value of the field. - */ - static setBooleanFieldValue( fieldKey, value ) { - const inputElement = this.getInputElement( fieldKey ); - - if ( inputElement ) { - inputElement.value = value ? "1" : "0"; - } - } - - /** - * Set the value of a field. - * @param {string} fieldId The field id. - * @param {value} value The value of the field. - * @returns {void} - */ - static setFieldValueBySingleId( fieldId, value ) { - const inputElement = document.getElementById( fieldId ); - - if ( inputElement ) { - inputElement.value = value ?? ""; - } - } - - /** - * Set no index value. - * @param {string} value The value. - * @returns {void} - */ - static setNoIndex( value ) { - const inputElement = document.getElementById( this.isPost ? "yoast_wpseo_meta-robots-noindex" : "hidden_wpseo_noindex" ); - if ( inputElement ) { - inputElement.value = value; - } - } - - /** - * Set the value of a field. - * @param {string} fieldKey The field key. - * @param {value} value The value of the field. - * @returns {void} - */ - static setFieldValue( fieldKey, value ) { - const inputElement = this.getInputElement( fieldKey ); - - if ( inputElement && inputElement.value ) { - inputElement.value = value ?? ""; - return; - } - } -} From 68b918ca584eb5ce2ec50fa70413947738cba56e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 16:49:58 +0100 Subject: [PATCH 100/344] relocate initialise of core editor store sync --- packages/js/src/block-editor.js | 9 --------- packages/js/src/initializers/block-editor-integration.js | 5 +++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/js/src/block-editor.js b/packages/js/src/block-editor.js index 7341007eb9a..f4824c479e1 100644 --- a/packages/js/src/block-editor.js +++ b/packages/js/src/block-editor.js @@ -1,16 +1,7 @@ /* eslint-disable no-unused-vars */ import initBlockEditorIntegration from "./initializers/block-editor-integration"; import BlockEditorData from "./analysis/blockEditorData"; -import { blockEditorSync, hasHiddenFields } from "./helpers/fields"; -import domReady from "@wordpress/dom-ready"; window.yoast = window.yoast || {}; window.yoast.initEditorIntegration = initBlockEditorIntegration; window.yoast.EditorData = BlockEditorData; - -domReady( () => { - if ( ! hasHiddenFields() ) { - blockEditorSync(); - } -} ); - diff --git a/packages/js/src/initializers/block-editor-integration.js b/packages/js/src/initializers/block-editor-integration.js index d81f1f052a1..3a01593023e 100644 --- a/packages/js/src/initializers/block-editor-integration.js +++ b/packages/js/src/initializers/block-editor-integration.js @@ -28,6 +28,7 @@ import WincherPostPublish from "../containers/WincherPostPublish"; import { isAnnotationAvailable } from "../decorator/gutenberg"; import { isWordProofIntegrationActive } from "../helpers/wordproof"; import { link } from "../inline-links/edit-link"; +import { hasHiddenFields, blockEditorSync } from "../helpers/fields"; /** * Registers the Yoast inline link format. @@ -226,4 +227,8 @@ export default function initBlockEditorIntegration( store ) { if ( isWordProofIntegrationActive() ) { initializeWordProofForBlockEditor(); } + + if ( ! hasHiddenFields() ) { + blockEditorSync(); + } } From 3c7f336f4c7e11b1096c81e887879d594dbfa040 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 16:58:16 +0100 Subject: [PATCH 101/344] fix get metadata default --- packages/js/src/elementor/initializers/editor-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 0334dc278f6..7342ae52f1e 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -46,7 +46,7 @@ const populateStore = store => { store.dispatch( actions.loadTwitterPreviewData() ); } - const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); From a235a90bfb2a99b5488245417949bf0e121343f3 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 16:59:33 +0100 Subject: [PATCH 102/344] fix js docs types --- packages/js/src/helpers/fields/advancedFieldsStore.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index 659dbccee8b..99e25aa59d1 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -4,14 +4,14 @@ import { STORE } from "../../constants"; /** * Retrieves the no index value. * - * @returns {integer} The no index value. + * @returns {string} The no index value. */ export const getNoIndex = () => String( select( STORE )?.getNoIndex() ); /** * Retrieves the no follow value. * - * @returns {integer} The no follow value. + * @returns {string} The no follow value. */ export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); @@ -20,7 +20,7 @@ export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); * * @param {Object} state The state. * - * @returns {String} Twitter image URL. + * @returns {string} Twitter image URL. */ export const getAdvanced = () => select( STORE )?.getAdvanced().join( "," ); @@ -29,7 +29,7 @@ export const getAdvanced = () => select( STORE )?.getAdvanced().join( "," ); * * @param {Object} state The state. * - * @returns {String} Twitter image type. + * @returns {string} Twitter image type. */ export const getBreadcrumbsTitle = () => select( STORE )?.getBreadcrumbsTitle(); @@ -47,6 +47,6 @@ export const getCanonical = () => select( STORE )?.getCanonical(); * * @param {Object} state The state. * - * @returns {Boolean} WordProof timestamp value. + * @returns {string} WordProof timestamp value. */ export const getWordProofTimestamp = () => select( STORE )?.getWordProofTimestamp() ? "1" : "0"; From ca254e26cbc56f439045e879ef3c18d5ba72a732 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 6 Mar 2024 17:13:53 +0100 Subject: [PATCH 103/344] add defensive coding to ensure string --- .../src/helpers/fields/advancedFieldsStore.js | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index 99e25aa59d1..e09d2d5fe40 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -6,14 +6,22 @@ import { STORE } from "../../constants"; * * @returns {string} The no index value. */ -export const getNoIndex = () => String( select( STORE )?.getNoIndex() ); +export const getNoIndex = () => select( STORE )?.getNoIndex() ? String( select( STORE ).getNoIndex() ) : "0"; /** * Retrieves the no follow value. * * @returns {string} The no follow value. */ -export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); +export const getNoFollow = () => { + const noFollow = select( STORE )?.getNoFollow(); + if ( noFollow && typeof noFollow === "string" ) { + return noFollow; + } else if ( typeof noFollow === "number" ) { + return String( noFollow ); + } + return "0"; +}; /** * Gets the twitter image URL from the state. @@ -22,7 +30,15 @@ export const getNoFollow = () => String( select( STORE )?.getNoFollow() ); * * @returns {string} Twitter image URL. */ -export const getAdvanced = () => select( STORE )?.getAdvanced().join( "," ); +export const getAdvanced = () => { + const advanced = select( STORE )?.getAdvanced(); + if ( Array.isArray( advanced ) ) { + return advanced.join( "," ); + } else if ( typeof advanced === "string" ) { + return advanced; + } + return ""; +}; /** * Gets the twitter image type from the state. From 92b2b9529fc2c87ad02e0c38b64ff777db796cd3 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 09:24:50 +0100 Subject: [PATCH 104/344] moves constants to shared-admin folder --- packages/js/src/constants/index.js | 2 -- packages/js/src/helpers/fields/additionalFieldsStore.js | 2 +- packages/js/src/helpers/fields/advancedFieldsStore.js | 2 +- packages/js/src/helpers/fields/analysisFieldsStore.js | 2 +- packages/js/src/helpers/fields/blockEditorSync.js | 2 +- packages/js/src/helpers/fields/facebookFieldsStore.js | 2 +- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- packages/js/src/helpers/fields/schemaFieldsStore.js | 2 +- packages/js/src/helpers/fields/snippetEditorFieldsStore.js | 2 +- packages/js/src/helpers/fields/twitterFieldsStore.js | 2 +- packages/js/src/shared-admin/constants/index.js | 3 +++ packages/js/src/{ => shared-admin}/constants/stores.js | 0 packages/js/src/{ => shared-admin}/constants/sync.js | 0 13 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 packages/js/src/constants/index.js rename packages/js/src/{ => shared-admin}/constants/stores.js (100%) rename packages/js/src/{ => shared-admin}/constants/sync.js (100%) diff --git a/packages/js/src/constants/index.js b/packages/js/src/constants/index.js deleted file mode 100644 index 6fcf3304728..00000000000 --- a/packages/js/src/constants/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./stores"; -export * from "./sync"; diff --git a/packages/js/src/helpers/fields/additionalFieldsStore.js b/packages/js/src/helpers/fields/additionalFieldsStore.js index 6af12b33d12..b8d917537da 100644 --- a/packages/js/src/helpers/fields/additionalFieldsStore.js +++ b/packages/js/src/helpers/fields/additionalFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Retrieves the estimated reading time from the store. diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index e09d2d5fe40..fde3a485af9 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Retrieves the no index value. diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index 4f0bb32c522..0d443746a0e 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Retrieves the focus keyphrase. diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 37fe709612b..34031e78eee 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../constants"; +import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js index 40f1137c5e3..885128ad9ef 100644 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Retrieve facebook image id. diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 1b5b92d5460..65406b8d58f 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -3,7 +3,7 @@ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE, SYNC_TIME } from "../../constants"; +import { STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index 65a4df202df..1638fead85b 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Gets the pageType from the state. diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js index bd768e1b93c..12e1390a7cc 100644 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Gets the snippet editor title. diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js index e407aa6314d..a6aff619fed 100644 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../constants"; +import { STORE } from "../../shared-admin/constants"; /** * Retrieve twitter image id. diff --git a/packages/js/src/shared-admin/constants/index.js b/packages/js/src/shared-admin/constants/index.js index 2d2d680b7da..02a2e701948 100644 --- a/packages/js/src/shared-admin/constants/index.js +++ b/packages/js/src/shared-admin/constants/index.js @@ -19,3 +19,6 @@ export const VIDEO_FLOW = { askPermission: "askPermission", isPlaying: "isPlaying", }; + +export * from "./stores"; +export * from "./sync"; diff --git a/packages/js/src/constants/stores.js b/packages/js/src/shared-admin/constants/stores.js similarity index 100% rename from packages/js/src/constants/stores.js rename to packages/js/src/shared-admin/constants/stores.js diff --git a/packages/js/src/constants/sync.js b/packages/js/src/shared-admin/constants/sync.js similarity index 100% rename from packages/js/src/constants/sync.js rename to packages/js/src/shared-admin/constants/sync.js From 73c7e2b6738143bfad18b0b1881d6a5c55a51129 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 09:41:06 +0100 Subject: [PATCH 105/344] rename constants for stores name --- .../js/src/helpers/fields/additionalFieldsStore.js | 4 ++-- .../js/src/helpers/fields/advancedFieldsStore.js | 14 +++++++------- .../js/src/helpers/fields/analysisFieldsStore.js | 12 ++++++------ packages/js/src/helpers/fields/blockEditorSync.js | 6 +++--- .../js/src/helpers/fields/facebookFieldsStore.js | 10 +++++----- packages/js/src/helpers/fields/hiddenFieldsSync.js | 12 ++++++------ .../js/src/helpers/fields/schemaFieldsStore.js | 6 +++--- .../src/helpers/fields/snippetEditorFieldsStore.js | 6 +++--- .../js/src/helpers/fields/twitterFieldsStore.js | 10 +++++----- packages/js/src/shared-admin/constants/stores.js | 2 +- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/js/src/helpers/fields/additionalFieldsStore.js b/packages/js/src/helpers/fields/additionalFieldsStore.js index b8d917537da..7663d6779b3 100644 --- a/packages/js/src/helpers/fields/additionalFieldsStore.js +++ b/packages/js/src/helpers/fields/additionalFieldsStore.js @@ -1,8 +1,8 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Retrieves the estimated reading time from the store. * @returns {string} The estimated reading time. */ -export const getEstimatedReadingTime = () => select( STORE ).getEstimatedReadingTime().toString(); +export const getEstimatedReadingTime = () => select( EDITOR_STORE ).getEstimatedReadingTime().toString(); diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index fde3a485af9..17cef0c7527 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -1,12 +1,12 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Retrieves the no index value. * * @returns {string} The no index value. */ -export const getNoIndex = () => select( STORE )?.getNoIndex() ? String( select( STORE ).getNoIndex() ) : "0"; +export const getNoIndex = () => select( EDITOR_STORE )?.getNoIndex() ? String( select( EDITOR_STORE ).getNoIndex() ) : "0"; /** * Retrieves the no follow value. @@ -14,7 +14,7 @@ export const getNoIndex = () => select( STORE )?.getNoIndex() ? String( select( * @returns {string} The no follow value. */ export const getNoFollow = () => { - const noFollow = select( STORE )?.getNoFollow(); + const noFollow = select( EDITOR_STORE )?.getNoFollow(); if ( noFollow && typeof noFollow === "string" ) { return noFollow; } else if ( typeof noFollow === "number" ) { @@ -31,7 +31,7 @@ export const getNoFollow = () => { * @returns {string} Twitter image URL. */ export const getAdvanced = () => { - const advanced = select( STORE )?.getAdvanced(); + const advanced = select( EDITOR_STORE )?.getAdvanced(); if ( Array.isArray( advanced ) ) { return advanced.join( "," ); } else if ( typeof advanced === "string" ) { @@ -47,7 +47,7 @@ export const getAdvanced = () => { * * @returns {string} Twitter image type. */ -export const getBreadcrumbsTitle = () => select( STORE )?.getBreadcrumbsTitle(); +export const getBreadcrumbsTitle = () => select( EDITOR_STORE )?.getBreadcrumbsTitle(); /** * Gets the Twitter image src from the state. @@ -56,7 +56,7 @@ export const getBreadcrumbsTitle = () => select( STORE )?.getBreadcrumbsTitle(); * * @returns {String} Twitter image src. */ -export const getCanonical = () => select( STORE )?.getCanonical(); +export const getCanonical = () => select( EDITOR_STORE )?.getCanonical(); /** * Gets the WordProof timestamp value. @@ -65,4 +65,4 @@ export const getCanonical = () => select( STORE )?.getCanonical(); * * @returns {string} WordProof timestamp value. */ -export const getWordProofTimestamp = () => select( STORE )?.getWordProofTimestamp() ? "1" : "0"; +export const getWordProofTimestamp = () => select( EDITOR_STORE )?.getWordProofTimestamp() ? "1" : "0"; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index 0d443746a0e..0354a69e8df 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -1,36 +1,36 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Retrieves the focus keyphrase. * @returns {string} The focus keyphrase. */ -export const getFocusKeyphrase = () => select( STORE )?.getFocusKeyphrase(); +export const getFocusKeyphrase = () => select( EDITOR_STORE )?.getFocusKeyphrase(); /** * Returns whether the current content is cornerstone content. * * @returns {string} Whether the current content is cornerstone content. */ -export const isCornerstoneContent = () => select( STORE )?.isCornerstoneContent() ? "1" : "0"; +export const isCornerstoneContent = () => select( EDITOR_STORE )?.isCornerstoneContent() ? "1" : "0"; /** * Retrieves the readability score. * * @returns {string} The content score. */ -export const getReadabilityScore = () => select( STORE )?.getReadabilityResults()?.overallScore ? String( select( STORE )?.getReadabilityResults()?.overallScore ) : ""; +export const getReadabilityScore = () => select( EDITOR_STORE )?.getReadabilityResults()?.overallScore ? String( select( EDITOR_STORE )?.getReadabilityResults()?.overallScore ) : ""; /** * Retrieves the inclusive language score. * * @returns {string} The content score. */ -export const getInclusiveLanguageScore = () => select( STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( STORE )?.getInclusiveLanguageResults()?.overallScore ) : ""; +export const getInclusiveLanguageScore = () => select( EDITOR_STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( EDITOR_STORE )?.getInclusiveLanguageResults()?.overallScore ) : ""; /** * Retrieves the seo score. * * @returns {string} The content score. */ -export const getSeoScore = () => select( STORE )?.getSeoResults().overallScore ? String( select( STORE )?.getSeoResults().overallScore ) : ""; +export const getSeoScore = () => select( EDITOR_STORE )?.getSeoResults().overallScore ? String( select( EDITOR_STORE )?.getSeoResults().overallScore ) : ""; diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 34031e78eee..7eaf2f5c882 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../shared-admin/constants"; +import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -21,7 +21,7 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( STORE )?.getPrimaryTaxonomyId( taxonomy ) ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ) ); METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; } ); return getPrimaryTermsStore; @@ -96,5 +96,5 @@ export const blockEditorSync = () => { } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); }; diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js index 885128ad9ef..be8b2e9be0f 100644 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -1,27 +1,27 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Retrieve facebook image id. * @returns {integer} The facebook image id. */ -export const getFacebookImageId = () => select( STORE )?.getFacebookImageId(); +export const getFacebookImageId = () => select( EDITOR_STORE )?.getFacebookImageId(); /** * Get facebook title. * @returns {string} The facebook title. */ -export const getFacebookTitle = () => select( STORE )?.getFacebookTitle(); +export const getFacebookTitle = () => select( EDITOR_STORE )?.getFacebookTitle(); /** * Get facebook description. * @returns {string} The facebook description. */ -export const getFacebookDescription = () => select( STORE )?.getFacebookDescription(); +export const getFacebookDescription = () => select( EDITOR_STORE )?.getFacebookDescription(); /** * Get facebook image Url. * @returns {string} The facebook image Url. */ -export const getFacebookImageUrl = () => select( STORE )?.getFacebookImageUrl(); +export const getFacebookImageUrl = () => select( EDITOR_STORE )?.getFacebookImageUrl(); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 65406b8d58f..86846e4e0ad 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -3,7 +3,7 @@ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE, SYNC_TIME } from "../../shared-admin/constants"; +import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -22,7 +22,7 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( STORE )?.getPrimaryTaxonomyId( taxonomy ) ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ) ); } ); return getPrimaryTermsStore; }; @@ -33,7 +33,7 @@ const getPrimaryTerms = () => { * @returns {string} The value to be saved. */ const prepareSocialTitle = ( value ) => { - if ( value.trim() === select( STORE ).getSocialTitleTemplate().trim() ) { + if ( value.trim() === select( EDITOR_STORE ).getSocialTitleTemplate().trim() ) { return ""; } return value; @@ -45,7 +45,7 @@ const prepareSocialTitle = ( value ) => { * @returns {string} The value to be saved. */ const prepareSocialDescription = ( value ) => { - if ( value.trim() === select( STORE ).getSocialDescriptionTemplate().trim() ) { + if ( value.trim() === select( EDITOR_STORE ).getSocialDescriptionTemplate().trim() ) { return ""; } return value; @@ -151,9 +151,9 @@ export const hiddenFieldsrSync = () => { linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, "estimated-reading-time-minutes": getEstimatedReadingTime, - primary_category: () => String( select( STORE )?.getPrimaryTaxonomyId( "category" ) ), + primary_category: () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( "category" ) ), ...getPrimaryTerms(), } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); }; diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index 1638fead85b..be84b7dde0d 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Gets the pageType from the state. @@ -8,7 +8,7 @@ import { STORE } from "../../shared-admin/constants"; * * @returns {String} Page type. */ -export const getPageType = () => select( STORE )?.getPageType(); +export const getPageType = () => select( EDITOR_STORE )?.getPageType(); /** * Gets the articleType from the state. @@ -17,4 +17,4 @@ export const getPageType = () => select( STORE )?.getPageType(); * * @returns {String} Article type. */ -export const getArticleType = () => select( STORE )?.getArticleType(); +export const getArticleType = () => select( EDITOR_STORE )?.getArticleType(); diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js index 12e1390a7cc..aca2033e929 100644 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Gets the snippet editor title. @@ -8,7 +8,7 @@ import { STORE } from "../../shared-admin/constants"; * * @returns {string} The snippet editor title. */ -export const getSeoTitle = () => select( STORE )?.getSnippetEditorTitle(); +export const getSeoTitle = () => select( EDITOR_STORE )?.getSnippetEditorTitle(); /** * Gets the snippet editor description. @@ -17,4 +17,4 @@ export const getSeoTitle = () => select( STORE )?.getSnippetEditorTitle(); * * @returns {string} The snippet editor description. */ -export const getSeoDescription = () => select( STORE )?.getSnippetEditorDescription(); +export const getSeoDescription = () => select( EDITOR_STORE )?.getSnippetEditorDescription(); diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js index a6aff619fed..6e220b27a8f 100644 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -1,27 +1,27 @@ import { select } from "@wordpress/data"; -import { STORE } from "../../shared-admin/constants"; +import { EDITOR_STORE } from "../../shared-admin/constants"; /** * Retrieve twitter image id. * @returns {integer} The twitter image id. */ -export const getTwitterImageId = () => select( STORE )?.getTwitterImageId(); +export const getTwitterImageId = () => select( EDITOR_STORE )?.getTwitterImageId(); /** * Get twitter title. * @returns {string} The twitter title. */ -export const getTwitterTitle = () => select( STORE )?.getTwitterTitle(); +export const getTwitterTitle = () => select( EDITOR_STORE )?.getTwitterTitle(); /** * Get twitter description. * @returns {string} The twitter description. */ -export const getTwitterDescription = () => select( STORE )?.getTwitterDescription(); +export const getTwitterDescription = () => select( EDITOR_STORE )?.getTwitterDescription(); /** * Get twitter image Url. * @returns {string} The twitter image Url. */ -export const getTwitterImageUrl = () => select( STORE )?.getTwitterImageUrl(); +export const getTwitterImageUrl = () => select( EDITOR_STORE )?.getTwitterImageUrl(); diff --git a/packages/js/src/shared-admin/constants/stores.js b/packages/js/src/shared-admin/constants/stores.js index 41605a3f524..cf42bbd61dc 100644 --- a/packages/js/src/shared-admin/constants/stores.js +++ b/packages/js/src/shared-admin/constants/stores.js @@ -1,3 +1,3 @@ -export const STORE = "yoast-seo/editor"; +export const EDITOR_STORE = "yoast-seo/editor"; export const CORE_EDITOR_STORE = "core/editor"; From f763e608c77429962b81bac4d8e8beeac21190e6 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 11:00:49 +0100 Subject: [PATCH 106/344] rename constant for post metadata keys --- packages/js/src/shared-admin/constants/sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/shared-admin/constants/sync.js b/packages/js/src/shared-admin/constants/sync.js index 32b4a829582..f751477ba7c 100644 --- a/packages/js/src/shared-admin/constants/sync.js +++ b/packages/js/src/shared-admin/constants/sync.js @@ -1,4 +1,4 @@ -export const METADATA_KEYS = { +export const POST_METADATA_KEYS = { focusKeyphrase: "_yoast_wpseo_focuskw", noIndex: "_yoast_wpseo_meta-robots-noindex", noFollow: "_yoast_wpseo_meta-robots-nofollow", From 40606a40a20863f05225ae2ce08da523b7b2fdcf Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 11:01:48 +0100 Subject: [PATCH 107/344] fix constants and added defensive coding for primary term id function --- .../js/src/helpers/fields/blockEditorSync.js | 20 +++++++++++++------ .../js/src/helpers/fields/hiddenFieldsSync.js | 15 ++++++++++---- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 7eaf2f5c882..631de6f902a 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; -import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, METADATA_KEYS } from "../../shared-admin/constants"; +import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -13,7 +13,7 @@ import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** * Retrieves primary terms from store methods. * - * @returns {integer} The no index value. + * @returns {object} An object with taxonomies keys and their primary term id. */ const getPrimaryTerms = () => { const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); @@ -21,8 +21,16 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ) ); - METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { + const termId = select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ); + if ( ! termId || termId === -1 ) { + return ""; + } else if ( typeof termId === "number" ) { + return termId.toString(); + } + return termId; + }; + POST_METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; } ); return getPrimaryTermsStore; }; @@ -46,12 +54,12 @@ const createUpdater = () => { return; } - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ POST_METADATA_KEYS[ key ] ] ); if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { - newMetadata[ METADATA_KEYS[ key ] ] = value; + newMetadata[ POST_METADATA_KEYS[ key ] ] = value; } ); editPost( { diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 86846e4e0ad..a93a97c410d 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -12,9 +12,9 @@ import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** - * Retrieves primary terms from store methods. + * Retrieves an object with taxonomies keys and their primary term id. * - * @returns {integer} The no index value. + * @returns {object} An object with primary taxonomies keys and it's primary term id. */ const getPrimaryTerms = () => { const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); @@ -22,7 +22,15 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ) ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { + const termId = select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ); + if ( ! termId || termId === -1 ) { + return ""; + } else if ( typeof termId === "number" ) { + return termId.toString(); + } + return termId; + }; } ); return getPrimaryTermsStore; }; @@ -151,7 +159,6 @@ export const hiddenFieldsrSync = () => { linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, "estimated-reading-time-minutes": getEstimatedReadingTime, - primary_category: () => String( select( EDITOR_STORE )?.getPrimaryTaxonomyId( "category" ) ), ...getPrimaryTerms(), } ), createUpdater() From febbd591be839f36adabcc9f1dde46dbc408325d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 12:23:44 +0100 Subject: [PATCH 108/344] fix store name and import --- packages/js/src/analysis/PostDataCollector.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index bfc7e91d4ad..3fa36775f36 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -17,7 +17,7 @@ import getIndicatorForScore from "./getIndicatorForScore"; import isKeywordAnalysisActive from "./isKeywordAnalysisActive"; import isContentAnalysisActive from "./isContentAnalysisActive"; -import { STORE } from "../constants"; +import { EDITOR_STORE } from "../shared-admin/constants"; const { tmceId } = tmceHelper; const $ = jQuery; @@ -83,7 +83,7 @@ PostDataCollector.prototype.getData = function() { * @returns {string} The keyword. */ PostDataCollector.prototype.getKeyword = function() { - const keyword = select( STORE ).getFocusKeyphrase(); + const keyword = select( EDITOR_STORE ).getFocusKeyphrase(); return keyword; }; @@ -108,7 +108,7 @@ PostDataCollector.prototype.getMetaDescForAnalysis = function( state ) { * @returns {string} The meta description. */ PostDataCollector.prototype.getMeta = function() { - return select( STORE ).getDescription(); + return select( EDITOR_STORE ).getDescription(); }; /** From 3c4d0407f974e4b6c1dbe17d16f6cbe972a135fd Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 12:23:59 +0100 Subject: [PATCH 109/344] use defaultTo --- packages/js/src/helpers/fields/analysisFieldsStore.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index 0354a69e8df..a9bace6fe08 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -1,11 +1,12 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** * Retrieves the focus keyphrase. * @returns {string} The focus keyphrase. */ -export const getFocusKeyphrase = () => select( EDITOR_STORE )?.getFocusKeyphrase(); +export const getFocusKeyphrase = () => defaultTo( select( EDITOR_STORE ).getFocusKeyphrase(), "" ); /** * Returns whether the current content is cornerstone content. @@ -33,4 +34,4 @@ export const getInclusiveLanguageScore = () => select( EDITOR_STORE )?.getInclus * * @returns {string} The content score. */ -export const getSeoScore = () => select( EDITOR_STORE )?.getSeoResults().overallScore ? String( select( EDITOR_STORE )?.getSeoResults().overallScore ) : ""; +export const getSeoScore = () => String( select( EDITOR_STORE ).getSeoResults().overallScore ); From d33f6c7da5de23b07b92163ef2af3ce5c5d67328 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:04:06 +0100 Subject: [PATCH 110/344] Add defensive coding to analysis scores --- packages/js/src/helpers/fields/analysisFieldsStore.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index a9bace6fe08..ee46307f4cf 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -20,18 +20,18 @@ export const isCornerstoneContent = () => select( EDITOR_STORE )?.isCornerstoneC * * @returns {string} The content score. */ -export const getReadabilityScore = () => select( EDITOR_STORE )?.getReadabilityResults()?.overallScore ? String( select( EDITOR_STORE )?.getReadabilityResults()?.overallScore ) : ""; +export const getReadabilityScore = () => String( defaultTo( select( EDITOR_STORE ).getReadabilityResults().overallScore, "0" ) ); /** * Retrieves the inclusive language score. * * @returns {string} The content score. */ -export const getInclusiveLanguageScore = () => select( EDITOR_STORE )?.getInclusiveLanguageResults()?.overallScore ? String( select( EDITOR_STORE )?.getInclusiveLanguageResults()?.overallScore ) : ""; +export const getInclusiveLanguageScore = () => String( defaultTo( select( EDITOR_STORE ).getInclusiveLanguageResults().overallScore, "0" ) ); /** * Retrieves the seo score. * * @returns {string} The content score. */ -export const getSeoScore = () => String( select( EDITOR_STORE ).getSeoResults().overallScore ); +export const getSeoScore = () => String( defaultTo( select( EDITOR_STORE ).getSeoResults().overallScore, "0" ) ); From c1858eef388a6a76be9f705447e54817689d2cc9 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:04:37 +0100 Subject: [PATCH 111/344] add defensive coding to reading time --- packages/js/src/helpers/fields/additionalFieldsStore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/additionalFieldsStore.js b/packages/js/src/helpers/fields/additionalFieldsStore.js index 7663d6779b3..ada43d2723e 100644 --- a/packages/js/src/helpers/fields/additionalFieldsStore.js +++ b/packages/js/src/helpers/fields/additionalFieldsStore.js @@ -1,8 +1,9 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** * Retrieves the estimated reading time from the store. * @returns {string} The estimated reading time. */ -export const getEstimatedReadingTime = () => select( EDITOR_STORE ).getEstimatedReadingTime().toString(); +export const getEstimatedReadingTime = () => String( defaultTo( select( EDITOR_STORE ).getEstimatedReadingTime(), "0" ) ); From 7a766a637398f58582d7a2add5ab26555832b3fb Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:29:41 +0100 Subject: [PATCH 112/344] add defensive coding and move reading time to analysis file --- .../helpers/fields/additionalFieldsStore.js | 9 ------- .../src/helpers/fields/advancedFieldsStore.js | 25 ++++++------------- .../src/helpers/fields/analysisFieldsStore.js | 7 ++++++ .../js/src/helpers/fields/blockEditorSync.js | 3 +-- .../js/src/helpers/fields/hiddenFieldsSync.js | 5 ++-- 5 files changed, 18 insertions(+), 31 deletions(-) delete mode 100644 packages/js/src/helpers/fields/additionalFieldsStore.js diff --git a/packages/js/src/helpers/fields/additionalFieldsStore.js b/packages/js/src/helpers/fields/additionalFieldsStore.js deleted file mode 100644 index ada43d2723e..00000000000 --- a/packages/js/src/helpers/fields/additionalFieldsStore.js +++ /dev/null @@ -1,9 +0,0 @@ -import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; - -/** - * Retrieves the estimated reading time from the store. - * @returns {string} The estimated reading time. - */ -export const getEstimatedReadingTime = () => String( defaultTo( select( EDITOR_STORE ).getEstimatedReadingTime(), "0" ) ); diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index 17cef0c7527..554aded5ccd 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -1,27 +1,20 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** * Retrieves the no index value. * * @returns {string} The no index value. */ -export const getNoIndex = () => select( EDITOR_STORE )?.getNoIndex() ? String( select( EDITOR_STORE ).getNoIndex() ) : "0"; +export const getNoIndex = () => String( defaultTo( select( EDITOR_STORE ).getNoIndex(), "0" ) ); /** * Retrieves the no follow value. * * @returns {string} The no follow value. */ -export const getNoFollow = () => { - const noFollow = select( EDITOR_STORE )?.getNoFollow(); - if ( noFollow && typeof noFollow === "string" ) { - return noFollow; - } else if ( typeof noFollow === "number" ) { - return String( noFollow ); - } - return "0"; -}; +export const getNoFollow = () => String( defaultTo( select( EDITOR_STORE ).getNoFollow(), "0" ) ); /** * Gets the twitter image URL from the state. @@ -31,13 +24,11 @@ export const getNoFollow = () => { * @returns {string} Twitter image URL. */ export const getAdvanced = () => { - const advanced = select( EDITOR_STORE )?.getAdvanced(); + const advanced = select( EDITOR_STORE ).getAdvanced(); if ( Array.isArray( advanced ) ) { return advanced.join( "," ); - } else if ( typeof advanced === "string" ) { - return advanced; } - return ""; + return defaultTo( advanced, "" ); }; /** @@ -47,7 +38,7 @@ export const getAdvanced = () => { * * @returns {string} Twitter image type. */ -export const getBreadcrumbsTitle = () => select( EDITOR_STORE )?.getBreadcrumbsTitle(); +export const getBreadcrumbsTitle = () => defaultTo( select( EDITOR_STORE ).getBreadcrumbsTitle(), "" ); /** * Gets the Twitter image src from the state. @@ -56,7 +47,7 @@ export const getBreadcrumbsTitle = () => select( EDITOR_STORE )?.getBreadcrumbsT * * @returns {String} Twitter image src. */ -export const getCanonical = () => select( EDITOR_STORE )?.getCanonical(); +export const getCanonical = () => defaultTo( select( EDITOR_STORE ).getCanonical(), "" ); /** * Gets the WordProof timestamp value. @@ -65,4 +56,4 @@ export const getCanonical = () => select( EDITOR_STORE )?.getCanonical(); * * @returns {string} WordProof timestamp value. */ -export const getWordProofTimestamp = () => select( EDITOR_STORE )?.getWordProofTimestamp() ? "1" : "0"; +export const getWordProofTimestamp = () => select( EDITOR_STORE ).getWordProofTimestamp() ? "1" : "0"; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index ee46307f4cf..a13ede83ef2 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -35,3 +35,10 @@ export const getInclusiveLanguageScore = () => String( defaultTo( select( EDITOR * @returns {string} The content score. */ export const getSeoScore = () => String( defaultTo( select( EDITOR_STORE ).getSeoResults().overallScore, "0" ) ); + +/** + * Retrieves the estimated reading time from the store. + * @returns {string} The estimated reading time. + */ +export const getEstimatedReadingTime = () => String( defaultTo( select( EDITOR_STORE ).getEstimatedReadingTime(), "0" ) ); + diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 631de6f902a..57a3da314d1 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -5,10 +5,9 @@ import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from " import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; +import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; -import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** * Retrieves primary terms from store methods. diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index a93a97c410d..73e99824351 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -7,9 +7,8 @@ import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore } from "./analysisFieldsStore"; +import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; -import { getEstimatedReadingTime } from "./additionalFieldsStore"; /** * Retrieves an object with taxonomies keys and their primary term id. @@ -131,7 +130,7 @@ const createUpdater = () => { * Initializes the sync: from Yoast editor store to product metadata. * @returns {function} The un-subscriber. */ -export const hiddenFieldsrSync = () => { +export const hiddenFieldsSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { focuskw: getFocusKeyphrase, From 15bd734c31f3a45e0d4b6400a08f7eeaba343fec Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:32:38 +0100 Subject: [PATCH 113/344] add defensive coding to primary term id --- packages/js/src/helpers/fields/blockEditorSync.js | 12 ++---------- packages/js/src/helpers/fields/hiddenFieldsSync.js | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 57a3da314d1..9e8adac1c5f 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get } from "lodash"; +import { debounce, forEach, pickBy, get, defaultTo } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -20,15 +20,7 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { - const termId = select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ); - if ( ! termId || termId === -1 ) { - return ""; - } else if ( typeof termId === "number" ) { - return termId.toString(); - } - return termId; - }; + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); POST_METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; } ); return getPrimaryTermsStore; diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 73e99824351..784318f6109 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,7 +1,7 @@ /* eslint-disable complexity */ /* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get } from "lodash"; +import { debounce, forEach, pickBy, get, defaultTo } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -21,15 +21,7 @@ const getPrimaryTerms = () => { const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { - const termId = select( EDITOR_STORE )?.getPrimaryTaxonomyId( taxonomy ); - if ( ! termId || termId === -1 ) { - return ""; - } else if ( typeof termId === "number" ) { - return termId.toString(); - } - return termId; - }; + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); } ); return getPrimaryTermsStore; }; From d53069a42c546270f68b7140f4852ec1cf9b2f12 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:34:46 +0100 Subject: [PATCH 114/344] Add defensive coding to opengraph fields --- packages/js/src/helpers/fields/facebookFieldsStore.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js index be8b2e9be0f..67a30a37d08 100644 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -1,27 +1,28 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** * Retrieve facebook image id. * @returns {integer} The facebook image id. */ -export const getFacebookImageId = () => select( EDITOR_STORE )?.getFacebookImageId(); +export const getFacebookImageId = () => String( defaultTo( select( EDITOR_STORE ).getFacebookImageId(), "" ) ); /** * Get facebook title. * @returns {string} The facebook title. */ -export const getFacebookTitle = () => select( EDITOR_STORE )?.getFacebookTitle(); +export const getFacebookTitle = () => defaultTo( select( EDITOR_STORE ).getFacebookTitle(), "" ); /** * Get facebook description. * @returns {string} The facebook description. */ -export const getFacebookDescription = () => select( EDITOR_STORE )?.getFacebookDescription(); +export const getFacebookDescription = () => defaultTo( select( EDITOR_STORE ).getFacebookDescription(), "" ); /** * Get facebook image Url. * @returns {string} The facebook image Url. */ -export const getFacebookImageUrl = () => select( EDITOR_STORE )?.getFacebookImageUrl(); +export const getFacebookImageUrl = () => defaultTo( select( EDITOR_STORE )?.getFacebookImageUrl(), "" ); From ffafab728fdfd4202946d46bcd2f394e88398eb2 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:36:22 +0100 Subject: [PATCH 115/344] Add defensive coding to schema fields --- packages/js/src/helpers/fields/schemaFieldsStore.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index be84b7dde0d..015fefe6e44 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,20 +1,17 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** - * Gets the pageType from the state. - * - * @param {Object} state The state. + * Gets the pageType from the store. * * @returns {String} Page type. */ -export const getPageType = () => select( EDITOR_STORE )?.getPageType(); +export const getPageType = () => defaultTo( select( EDITOR_STORE ).getPageType(), "" ); /** - * Gets the articleType from the state. - * - * @param {Object} state The state. + * Gets the articleType from the store. * * @returns {String} Article type. */ -export const getArticleType = () => select( EDITOR_STORE )?.getArticleType(); +export const getArticleType = () => defaultTo( select( EDITOR_STORE ).getArticleType(), "" ); From 4ce28227a49d8ed4a4353a65728ea17855038034 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:39:57 +0100 Subject: [PATCH 116/344] add defensive coding for snippet editor fields --- .../src/helpers/fields/snippetEditorFieldsStore.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js index aca2033e929..8644594199d 100644 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -1,20 +1,17 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** - * Gets the snippet editor title. - * - * @param {Object} state The state object. + * Gets the snippet editor title from the store. * * @returns {string} The snippet editor title. */ -export const getSeoTitle = () => select( EDITOR_STORE )?.getSnippetEditorTitle(); +export const getSeoTitle = () => defaultTo( select( EDITOR_STORE ).getSnippetEditorTitle(), "" ); /** - * Gets the snippet editor description. - * - * @param {Object} state The state object. + * Gets the snippet editor description from the store. * * @returns {string} The snippet editor description. */ -export const getSeoDescription = () => select( EDITOR_STORE )?.getSnippetEditorDescription(); +export const getSeoDescription = () => defaultTo( select( EDITOR_STORE ).getSnippetEditorDescription(), "" ); From 011378d265549f8694421c511b388cf641560516 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:42:11 +0100 Subject: [PATCH 117/344] add defensive coding to twitter fields --- .../src/helpers/fields/twitterFieldsStore.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js index 6e220b27a8f..da9827cd5c5 100644 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -1,27 +1,32 @@ import { select } from "@wordpress/data"; import { EDITOR_STORE } from "../../shared-admin/constants"; +import { defaultTo } from "lodash"; /** - * Retrieve twitter image id. - * @returns {integer} The twitter image id. + * Retrieve twitter image id from the store. + * + * @returns {string} The twitter image id. */ -export const getTwitterImageId = () => select( EDITOR_STORE )?.getTwitterImageId(); +export const getTwitterImageId = () => String( defaultTo( select( EDITOR_STORE ).getTwitterImageId(), "" ) ); /** - * Get twitter title. + * Get twitter title from the store. + * * @returns {string} The twitter title. */ -export const getTwitterTitle = () => select( EDITOR_STORE )?.getTwitterTitle(); +export const getTwitterTitle = () => defaultTo( select( EDITOR_STORE ).getTwitterTitle(), "" ); /** - * Get twitter description. + * Get twitter description from the store. + * * @returns {string} The twitter description. */ -export const getTwitterDescription = () => select( EDITOR_STORE )?.getTwitterDescription(); +export const getTwitterDescription = () => defaultTo( select( EDITOR_STORE ).getTwitterDescription(), "" ); /** - * Get twitter image Url. + * Get twitter image Url from the store. + * * @returns {string} The twitter image Url. */ -export const getTwitterImageUrl = () => select( EDITOR_STORE )?.getTwitterImageUrl(); +export const getTwitterImageUrl = () => defaultTo( select( EDITOR_STORE ).getTwitterImageUrl(), "" ); From a0b6e38a33dd6f2219be7405ddeab3ac98adced2 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 16:44:29 +0100 Subject: [PATCH 118/344] fix js docs comments --- packages/js/src/helpers/fields/analysisFieldsStore.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index a13ede83ef2..21ef7eb006c 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -3,7 +3,8 @@ import { EDITOR_STORE } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** - * Retrieves the focus keyphrase. + * Retrieves the focus keyphrase from store. + * * @returns {string} The focus keyphrase. */ export const getFocusKeyphrase = () => defaultTo( select( EDITOR_STORE ).getFocusKeyphrase(), "" ); @@ -16,21 +17,21 @@ export const getFocusKeyphrase = () => defaultTo( select( EDITOR_STORE ).getFocu export const isCornerstoneContent = () => select( EDITOR_STORE )?.isCornerstoneContent() ? "1" : "0"; /** - * Retrieves the readability score. + * Retrieves the readability score from the store. * * @returns {string} The content score. */ export const getReadabilityScore = () => String( defaultTo( select( EDITOR_STORE ).getReadabilityResults().overallScore, "0" ) ); /** - * Retrieves the inclusive language score. + * Retrieves the inclusive language score from the store. * * @returns {string} The content score. */ export const getInclusiveLanguageScore = () => String( defaultTo( select( EDITOR_STORE ).getInclusiveLanguageResults().overallScore, "0" ) ); /** - * Retrieves the seo score. + * Retrieves the seo score from the store. * * @returns {string} The content score. */ @@ -38,7 +39,7 @@ export const getSeoScore = () => String( defaultTo( select( EDITOR_STORE ).getSe /** * Retrieves the estimated reading time from the store. + * * @returns {string} The estimated reading time. */ export const getEstimatedReadingTime = () => String( defaultTo( select( EDITOR_STORE ).getEstimatedReadingTime(), "0" ) ); - From 410dae962e47543b685ffa4d11d02998b30b2d5e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 17:16:39 +0100 Subject: [PATCH 119/344] fix type for hidden fields sync function --- packages/js/src/post-edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/post-edit.js b/packages/js/src/post-edit.js index 0e80a50971d..4bf3af791c7 100644 --- a/packages/js/src/post-edit.js +++ b/packages/js/src/post-edit.js @@ -11,7 +11,7 @@ import initTabs from "./initializers/metabox-tabs"; import initPostScraper from "./initializers/post-scraper"; import initPrimaryCategory from "./initializers/primary-category"; import initializeInsights from "./insights/initializer"; -import { hiddenFieldsrSync } from "./helpers/fields/hiddenFieldsSync"; +import { hiddenFieldsSync } from "./helpers/fields/hiddenFieldsSync"; // Backwards compatibility globals. window.wpseoPostScraperL10n = window.wpseoScriptData.metabox; @@ -32,7 +32,7 @@ domReady( () => { const store = initEditorStore(); // Initialize the hidden fields sync. - hiddenFieldsrSync(); + hiddenFieldsSync(); // Initialize the editor integration window.yoast.initEditorIntegration( store ); From 8a13f6c7a3c4dd36ec0019345a1a140129a04e1a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 17:21:19 +0100 Subject: [PATCH 120/344] fix type comment --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 2b3dc8007ed..a5af6ac3ed6 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -35,7 +35,7 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface * Constructor. * * @param WP_Post $post Post object. - * @param array $options Title options to use. + * @param array $options Title options to use. * @param string $structure The permalink to follow. */ public function __construct( $post, array $options, $structure ) { From 4236a9f83e1f076903113025aa7d79e7dd67da17 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 17:26:22 +0100 Subject: [PATCH 121/344] fix array type comments --- admin/formatter/class-post-metabox-formatter.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index a5af6ac3ed6..8de65fb28e0 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -57,7 +57,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array,array> + * @return array|array> */ public function get_values() { @@ -92,8 +92,8 @@ public function get_values() { /** * Filter: 'wpseo_post_edit_values' - Allows changing the values Yoast SEO uses inside the post editor. * - * @param array $values The key-value map Yoast SEO uses inside the post editor. - * @param WP_Post $post The post opened in the editor. + * @param array> $values The key-value map Yoast SEO uses inside the post editor. + * @param WP_Post $post The post opened in the editor. */ return apply_filters( 'wpseo_post_edit_values', $values, $this->post ); } @@ -156,7 +156,7 @@ private function base_url_for_js() { /** * Counts the number of given keywords used for other posts other than the given post_id. * - * @return array> The keyword and the associated posts that use it. + * @return array> The keyword and the associated posts that use it. */ private function get_focus_keyword_usage() { $keyword = WPSEO_Meta::get_value( 'focuskw', $this->post->ID ); @@ -174,7 +174,7 @@ private function get_focus_keyword_usage() { /** * Retrieves the post types for the given post IDs. * - * @param array> $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. + * @param array> $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. * @return array The post types for the given post IDs. */ private function get_post_types_for_all_ids( $post_ids_per_keyword ) { From 0b30a3c952c6b8d1dd82ccff9352c3cd57e2d834 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 17:28:39 +0100 Subject: [PATCH 122/344] fix array type comment --- admin/formatter/class-term-metabox-formatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index e0fc076e0a0..f05be917536 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -34,7 +34,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Array with the WPSEO_Titles options. * - * @var array + * @var array */ protected $options; @@ -63,7 +63,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array,array> + * @return array|array> */ public function get_values() { $values = []; From d6b76f294af49714dc92cfb5b78a8b59eb5d8a7e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 7 Mar 2024 17:39:34 +0100 Subject: [PATCH 123/344] remove to string rom twitter id, handled in twitter fields store file --- packages/js/src/redux/selectors/twitterEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/redux/selectors/twitterEditor.js b/packages/js/src/redux/selectors/twitterEditor.js index 8b1095a5b54..d50812ac90c 100644 --- a/packages/js/src/redux/selectors/twitterEditor.js +++ b/packages/js/src/redux/selectors/twitterEditor.js @@ -64,7 +64,7 @@ export const getTwitterImageSrc = state => get( state, "twitterEditor.image.src" * * @returns {integer} Twitter image id. */ -export const getTwitterImageId = state => get( state, "twitterEditor.image.id", "" ).toString(); +export const getTwitterImageId = state => get( state, "twitterEditor.image.id", "" ); /** * Gets the Twitter alt text from the state. From de68a2208746c0df4d6506e3bc2ba63efabd6a00 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 10:44:24 +0100 Subject: [PATCH 124/344] Listen to the original field like in classic editor, and not the hidden field --- packages/js/src/analysis/PostDataCollector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 3fa36775f36..fb5fef77a39 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -347,7 +347,7 @@ PostDataCollector.prototype.bindElementEvents = function( refreshAnalysis ) { * @returns {void} */ PostDataCollector.prototype.changeElementEventBinder = function( refreshAnalysis ) { - var elems = [ "#yoast_wpseo_primary_category", '.categorychecklist input[name="post_category[]"]' ]; + var elems = [ "#yoast-primary-category-picker", '.categorychecklist input[name="post_category[]"]' ]; for ( var i = 0; i < elems.length; i++ ) { $( elems[ i ] ).on( "change", refreshAnalysis ); } From 6cca4f4162b2dd6011e2ac2dfe3bb792362d8566 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 10:49:32 +0100 Subject: [PATCH 125/344] remove check for metabox container and check for metadata in window object instead --- packages/js/src/initializers/post-scraper.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index 8bedf1f9bee..edff463b42a 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -4,7 +4,7 @@ // External dependencies. import { App } from "yoastseo"; -import { debounce, isUndefined, get } from "lodash"; +import { debounce, isUndefined, get, isEmpty } from "lodash"; import { isShallowEqualObjects } from "@wordpress/is-shallow-equal"; import { select, subscribe } from "@wordpress/data"; @@ -79,7 +79,7 @@ export default function initPostScraper( $, store, editorData ) { if ( typeof wpseoScriptData === "undefined" ) { return; } - let metaboxContainer; + let titleElement; let app; let postDataCollector; @@ -403,17 +403,15 @@ export default function initPostScraper( $, store, editorData ) { * @returns {void} */ function initializePostAnalysis() { - metaboxContainer = $( "#wpseo_meta" ); - tinyMCEHelper.setStore( store ); tinyMCEHelper.wpTextViewOnInitCheck(); handlePageBuilderCompatibility(); - const metadata = get( window, "wpseoScriptData.metabox.metadata", [] ); + const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); // Avoid error when snippet metabox is not rendered. - if ( metaboxContainer.length === 0 && metadata.length === 0 ) { + if ( isEmpty( metadata ) ) { return; } From a3d34df5e625fb3fc46716273833e671703e926d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 10:54:18 +0100 Subject: [PATCH 126/344] restore side effect with defensive coding --- packages/js/src/components/PrimaryTaxonomyPicker.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index 9a6067a949b..ae0c0372090 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -190,6 +190,10 @@ class PrimaryTaxonomyPicker extends Component { this.updateReplacementVariable( termId ); this.props.setPrimaryTaxonomyId( name, termId ); + + if ( this.input ) { + this.input.value = termId === -1 ? "" : termId; + } } /** From 6991c8b059171b2a83f3fe8fca972dfa755ef469 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 10:54:42 +0100 Subject: [PATCH 127/344] cleanup sync of primary category --- .../js/src/helpers/fields/hiddenFieldsSync.js | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 784318f6109..958819859d2 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,7 +1,7 @@ /* eslint-disable complexity */ /* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get, defaultTo } from "lodash"; +import { debounce, forEach, pickBy, get } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -10,21 +10,6 @@ import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; -/** - * Retrieves an object with taxonomies keys and their primary term id. - * - * @returns {object} An object with primary taxonomies keys and it's primary term id. - */ -const getPrimaryTerms = () => { - const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); - const getPrimaryTermsStore = {}; - const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); - forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); - } ); - return getPrimaryTermsStore; -}; /** * Prepare twitter title to be saved in hidden field. @@ -70,9 +55,6 @@ const prepareValue = ( key, value ) => { case "opengraph-description": return prepareSocialDescription( value ); default: - if ( /^primary_/.test( key ) ) { - return value === -1 ? "" : String( value ); - } return value; } }; @@ -102,13 +84,11 @@ const createUpdater = () => { if ( ! hiddenFieldsData || ! data ) { return; } - console.log( { hiddenFieldsData } ); const isPost = get( window, "wpseoScriptData.isPost", false ); const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); - console.log( changedData ); if ( changedData ) { forEach( changedData, ( value, key ) => { @@ -134,7 +114,6 @@ export const hiddenFieldsSync = () => { bctitle: getBreadcrumbsTitle, canonical: getCanonical, wordproof_timestamp: getWordProofTimestamp, - // primary_category_term: getPrimaryCategoryId, "opengraph-title": getFacebookTitle, "opengraph-description": getFacebookDescription, "opengraph-image": getFacebookImageUrl, @@ -150,7 +129,6 @@ export const hiddenFieldsSync = () => { linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, "estimated-reading-time-minutes": getEstimatedReadingTime, - ...getPrimaryTerms(), } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); From 36726de9b68c05b80f1fc904ce7b889366595260 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 13:58:32 +0100 Subject: [PATCH 128/344] no need for estimate reading time class and conditional. the field is hidden and we need to register the metadata. --- inc/class-wpseo-meta.php | 6 ++ .../estimated-reading-time-conditional.php | 60 ------------------- src/integrations/estimated-reading-time.php | 49 --------------- 3 files changed, 6 insertions(+), 109 deletions(-) delete mode 100644 src/conditionals/admin/estimated-reading-time-conditional.php delete mode 100644 src/integrations/estimated-reading-time.php diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index c84a1cf178d..345475c09f6 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -149,6 +149,12 @@ class WPSEO_Meta { 'default_value' => 'false', 'description' => '', ], + 'estimated-reading-time-minutes' => [ + 'type' => 'hidden', + 'title' => 'estimated-reading-time-minutes', + 'default_value' => '0', + 'description' => '', + ] ], 'advanced' => [ 'meta-robots-noindex' => [ diff --git a/src/conditionals/admin/estimated-reading-time-conditional.php b/src/conditionals/admin/estimated-reading-time-conditional.php deleted file mode 100644 index 1e4f7d51549..00000000000 --- a/src/conditionals/admin/estimated-reading-time-conditional.php +++ /dev/null @@ -1,60 +0,0 @@ -post_conditional = $post_conditional; - } - - /** - * Returns whether this conditional is met. - * - * @return bool Whether the conditional is met. - */ - public function is_met() { - // phpcs:disable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing -- Reason: Nonce verification should not be done in a conditional but rather in the classes using the conditional. - // Check if we are in our Elementor ajax request (for saving). - if ( \wp_doing_ajax() && isset( $_POST['action'] ) && \is_string( $_POST['action'] ) ) { - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are only strictly comparing the variable. - $post_action = \wp_unslash( $_POST['action'] ); - if ( $post_action === 'wpseo_elementor_save' ) { - return true; - } - } - - if ( ! $this->post_conditional->is_met() ) { - return false; - } - - // We don't support Estimated Reading Time on the attachment post type. - if ( isset( $_GET['post'] ) && \is_string( $_GET['post'] ) ) { - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are casting to an integer. - $post_id = (int) \wp_unslash( $_GET['post'] ); - if ( $post_id !== 0 && \get_post_type( $post_id ) === 'attachment' ) { - return false; - } - } - - return true; - // phpcs:enable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing - } -} diff --git a/src/integrations/estimated-reading-time.php b/src/integrations/estimated-reading-time.php deleted file mode 100644 index 01b514e86e4..00000000000 --- a/src/integrations/estimated-reading-time.php +++ /dev/null @@ -1,49 +0,0 @@ - 'hidden', - 'title' => 'estimated-reading-time-minutes', - ]; - } - - return $field_defs; - } -} From 5849a01559ceebfd7f18a8df7f92cb5b247c4c37 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 13:59:00 +0100 Subject: [PATCH 129/344] simplify adding primery term to be registered as metadata --- inc/class-wpseo-meta.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 345475c09f6..c9e7811d5e7 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -302,13 +302,14 @@ public static function init() { if ( is_array( $extra_fields ) ) { self::$meta_fields = self::array_merge_recursive_distinct( $extra_fields, self::$meta_fields ); } + unset( $extra_fields ); + // register meta data for taxonomies. - $primay_terms = []; - $primay_terms['primary_terms'] = []; + self::$meta_fields['primary_terms'] = []; $taxonomies = get_taxonomies( [ 'hierarchical' => true ], 'names' ); foreach ( $taxonomies as $taxonomy_name ) { - $primay_terms['primary_terms'][ 'primary_' . $taxonomy_name ] = [ + self::$meta_fields['primary_terms'][ 'primary_' . $taxonomy_name ] = [ 'type' => 'hidden', 'title' => '', 'default_value' => '', @@ -316,12 +317,6 @@ public static function init() { ]; } - if ( $primay_terms && is_array( $primay_terms ) ) { - self::$meta_fields = self::array_merge_recursive_distinct( $primay_terms, self::$meta_fields ); - } - - unset( $extra_fields ); - foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { @@ -333,6 +328,7 @@ public static function init() { 'show_in_rest' => true, 'type' => 'string', 'single' => true, + 'default' => $field_def['default_value'] ?? '', ] ); From 30b84dcd46fb0dbe0b8486994a1607781a8c305e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 16:12:34 +0100 Subject: [PATCH 130/344] we want to listen to the metadata even when there is no value --- packages/js/src/helpers/fields/blockEditorSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 9e8adac1c5f..840cd994272 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -17,7 +17,7 @@ import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; const getPrimaryTerms = () => { const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); const getPrimaryTermsStore = {}; - const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) && value ); + const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); From 4ff3efcb78bd4162e0b1b715f047a432dc7512a6 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 16:14:21 +0100 Subject: [PATCH 131/344] if there is no primary term, return an empty string --- admin/formatter/class-post-metabox-formatter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 8de65fb28e0..3b9da84d455 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -357,7 +357,8 @@ protected function get_post_meta_data() { foreach ( $taxonomies as $taxonomy ) { if ( $taxonomy->hierarchical ) { $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); - $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term_object->get_primary_term(); + $primary_term = $primary_term_object->get_primary_term(); + $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term ?? ""; } } From 50c94cc6e06b188d9a50195de6c89193999efd3a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 16:34:52 +0100 Subject: [PATCH 132/344] zero and empty string are saved the same, with empty string we avoid change --- packages/js/src/helpers/fields/advancedFieldsStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index 554aded5ccd..c0518eed802 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -56,4 +56,4 @@ export const getCanonical = () => defaultTo( select( EDITOR_STORE ).getCanonical * * @returns {string} WordProof timestamp value. */ -export const getWordProofTimestamp = () => select( EDITOR_STORE ).getWordProofTimestamp() ? "1" : "0"; +export const getWordProofTimestamp = () => select( EDITOR_STORE ).getWordProofTimestamp() ? "1" : ""; From 0d3234d459b288d33f86004b156d4c27350ca162 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 8 Mar 2024 16:49:12 +0100 Subject: [PATCH 133/344] cleanup estimate reading time tests --- ...stimated_Reading_Time_Conditional_Test.php | 249 ------------------ .../Estimated_Reading_Time_Test.php | 98 ------- 2 files changed, 347 deletions(-) delete mode 100644 tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php delete mode 100644 tests/Unit/Integrations/Estimated_Reading_Time_Test.php diff --git a/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php b/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php deleted file mode 100644 index 8ff0b3683cb..00000000000 --- a/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php +++ /dev/null @@ -1,249 +0,0 @@ -post_conditional = Mockery::mock( Post_Conditional::class ); - - $this->instance = new Estimated_Reading_Time_Conditional( - $this->post_conditional - ); - } - - /** - * Tests that the conditional is met when we are saving for Elementor. - * - * @covers ::is_met - * - * @return void - */ - public function test_ajax_elementor_save() { - // We are in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( true ); - - $_POST['action'] = 'wpseo_elementor_save'; - - $this->assertEquals( true, $this->instance->is_met() ); - } - - /** - * Tests is_met when the action is null. - * - * @covers ::is_met - * - * @return void - */ - public function test_ajax_elementor_save_action_null() { - // We are in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( true ); - - $_POST['action'] = null; - - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( false ); - - $this->assertEquals( false, $this->instance->is_met() ); - } - - /** - * Tests is_met when the action is not a string. - * - * @covers ::is_met - * - * @return void - */ - public function test_ajax_elementor_save_action_not_a_string() { - // We are in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( true ); - - $_POST['action'] = 9; - - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( false ); - - $this->assertEquals( false, $this->instance->is_met() ); - } - - /** - * Tests that the conditional is not met when we are not on a post, and also not in an Elementor save. - * - * @covers ::is_met - * - * @return void - */ - public function test_not_post_not_elementor_save() { - // We are in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( true ); - - $_POST['action'] = 'some_other_value'; - - // We are not on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( false ); - - $this->assertEquals( false, $this->instance->is_met() ); - } - - /** - * Tests that the conditional is not met when we are not on a post, and also not in an Elementor save. - * - * @covers ::is_met - * - * @return void - */ - public function test_post_is_attachment() { - // We are not in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( false ); - - // We are on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( true ); - - $_GET['post'] = '1'; - - // Returns the attachment post type. - Monkey\Functions\expect( 'get_post_type' ) - ->with( 1 ) - ->andReturn( 'attachment' ); - - $this->assertEquals( false, $this->instance->is_met() ); - } - - /** - * Tests is_met when post is null. - * - * @covers ::is_met - * - * @return void - */ - public function test_post_is_null() { - // We are not in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( false ); - - // We are on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( true ); - - $_GET['post'] = null; - - $this->assertEquals( true, $this->instance->is_met() ); - } - - /** - * Tests is_met when post is not a string. - * - * @covers ::is_met - * - * @return void - */ - public function test_post_is_not_string() { - // We are not in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( false ); - - // We are on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( true ); - - $_GET['post'] = 5; - - $this->assertEquals( true, $this->instance->is_met() ); - } - - /** - * Tests is_met when post can not be converted to an integer. - * - * @covers ::is_met - * - * @return void - */ - public function test_post_can_not_be_converted_to_int() { - // We are not in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( false ); - - // We are on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( true ); - - $_GET['post'] = 'this_is_not_an_int'; - - $this->assertEquals( true, $this->instance->is_met() ); - } - - /** - * Tests that the conditional is not met when we are not on a post, and also not in an Elementor save. - * - * @covers ::is_met - * - * @return void - */ - public function test_post() { - // We are not in an Ajax request. - Monkey\Functions\expect( 'wp_doing_ajax' )->andReturn( false ); - - // We are on a post according to the post conditional. - $this->post_conditional - ->expects( 'is_met' ) - ->once() - ->andReturn( true ); - - $_GET['post'] = '1'; - - // Returns post type. - Monkey\Functions\expect( 'get_post_type' ) - ->with( 1 ) - ->andReturn( 'post' ); - - $this->assertEquals( true, $this->instance->is_met() ); - } -} diff --git a/tests/Unit/Integrations/Estimated_Reading_Time_Test.php b/tests/Unit/Integrations/Estimated_Reading_Time_Test.php deleted file mode 100644 index b9e0147ff1f..00000000000 --- a/tests/Unit/Integrations/Estimated_Reading_Time_Test.php +++ /dev/null @@ -1,98 +0,0 @@ -instance = new Estimated_Reading_Time(); - } - - /** - * Tests the registration of the hooks. - * - * @covers ::register_hooks - * - * @return void - */ - public function test_register_hooks() { - Monkey\Filters\expectAdded( 'wpseo_metabox_entries_general' ) - ->with( [ $this->instance, 'add_estimated_reading_time_hidden_fields' ] ); - - $this->instance->register_hooks(); - } - - /** - * Tests the retrieval of the conditionals. - * - * @covers ::get_conditionals - * - * @return void - */ - public function test_get_conditionals() { - $this->assertEquals( - [ Estimated_Reading_Time_Conditional::class ], - Estimated_Reading_Time::get_conditionals() - ); - } - - /** - * Tests the adding of the hidden fields. - * - * @covers ::add_estimated_reading_time_hidden_fields - * - * @return void - */ - public function test_add_estimated_reading_time_hidden_fields() { - $actual = $this->instance->add_estimated_reading_time_hidden_fields( [] ); - - $this->assertIsArray( $actual ); - $this->assertArrayHasKey( 'estimated-reading-time-minutes', $actual ); - $this->assertEquals( - [ - 'type' => 'hidden', - 'title' => 'estimated-reading-time-minutes', - ], - $actual['estimated-reading-time-minutes'] - ); - } - - /** - * Tests only adding when the fields value is an array. - * - * @covers ::add_estimated_reading_time_hidden_fields - * - * @return void - */ - public function test_add_estimated_reading_time_hidden_fields_only_when_array() { - $actual = $this->instance->add_estimated_reading_time_hidden_fields( 'not-an-array' ); - - $this->assertSame( 'not-an-array', $actual ); - } -} From 4b70f09c8badd1da0ae912be2a9b275bc77bf5db Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 12:01:08 +0100 Subject: [PATCH 134/344] wordproof metadata is not registered by that filter --- src/integrations/third-party/wordproof.php | 23 ---------------------- 1 file changed, 23 deletions(-) diff --git a/src/integrations/third-party/wordproof.php b/src/integrations/third-party/wordproof.php index 1c670c1fe26..327d262ffce 100644 --- a/src/integrations/third-party/wordproof.php +++ b/src/integrations/third-party/wordproof.php @@ -127,11 +127,6 @@ static function () { * Called by the WordProof WordPress SDK to determine if the certificate should be shown. */ \add_filter( 'wordproof_timestamp_show_certificate', [ $this, 'show_certificate' ], 10, 2 ); - - /** - * Called by WPSEO_Meta to add extra meta fields to the ones defined there. - */ - \add_filter( 'add_extra_wpseo_meta_fields', [ $this, 'add_meta_field' ] ); } /** @@ -203,24 +198,6 @@ public function show_certificate( $value, $post ) { return \boolval( PostMetaHelper::get( $post->ID, $this->post_meta_key ) ); } - /** - * Adds the WordProof integration toggle to the array. - * - * @param array $fields The currently registered meta fields. - * - * @return array A new array with meta fields. - */ - public function add_meta_field( $fields ) { - $fields['advanced']['wordproof_timestamp'] = [ - 'type' => 'hidden', - 'title' => '', - 'default_value' => '', - 'description' => '0', - ]; - - return $fields; - } - /** * Enqueue the uikit script. * From ee282b9508f40e4a5a19e25e43b607bc275067c4 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 12:01:28 +0100 Subject: [PATCH 135/344] register metadata --- inc/class-wpseo-meta.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index c9e7811d5e7..eb38b5c85d1 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -205,6 +205,16 @@ class WPSEO_Meta { 'default_value' => '', 'description' => '', // Translation added later. ], + 'wordproof_timestamp' => [ + 'type' => 'hidden', + 'title' => '', // Translation added later. + 'default_value' => '0', + 'description' => '', // Translation added later. + 'options' => [ + '0' => '', // Off - translation added later. + '1' => '', // On - translation added later. + ], + ], ], 'social' => [], 'schema' => [ From 6731e7dadb1eedb01211f5dece29053e0693c5d4 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 12:01:44 +0100 Subject: [PATCH 136/344] Hidden is not translation --- admin/metabox/class-metabox.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/metabox/class-metabox.php b/admin/metabox/class-metabox.php index 7dc1329ff3d..011e630c9be 100644 --- a/admin/metabox/class-metabox.php +++ b/admin/metabox/class-metabox.php @@ -213,7 +213,6 @@ public static function translate_meta_boxes() { WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['description'] = __( 'Use WordProof to timestamp this page to comply with legal regulations and join the fight for a more transparant and accountable internet.', 'wordpress-seo' ); WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['0'] = __( 'Off', 'wordpress-seo' ); WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['1'] = __( 'On', 'wordpress-seo' ); - WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['type'] = 'hidden'; WPSEO_Meta::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' ); WPSEO_Meta::$meta_fields['advanced']['redirect']['description'] = __( 'The URL that this page should redirect to.', 'wordpress-seo' ); From 69579dbd03587416c1376c766ad7ca72de2d582a Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 12:36:15 +0100 Subject: [PATCH 137/344] php fix-cs --- admin/formatter/class-post-metabox-formatter.php | 4 ++-- inc/class-wpseo-meta.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 3b9da84d455..54b70173343 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -357,8 +357,8 @@ protected function get_post_meta_data() { foreach ( $taxonomies as $taxonomy ) { if ( $taxonomy->hierarchical ) { $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); - $primary_term = $primary_term_object->get_primary_term(); - $meta_data[ 'primary_' . $taxonomy->name ] = $primary_term ?? ""; + $primary_term = $primary_term_object->get_primary_term(); + $meta_data[ 'primary_' . $taxonomy->name ] = ( $primary_term ?? '' ); } } diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index eb38b5c85d1..ac61d619c95 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -154,7 +154,7 @@ class WPSEO_Meta { 'title' => 'estimated-reading-time-minutes', 'default_value' => '0', 'description' => '', - ] + ], ], 'advanced' => [ 'meta-robots-noindex' => [ @@ -338,7 +338,7 @@ public static function init() { 'show_in_rest' => true, 'type' => 'string', 'single' => true, - 'default' => $field_def['default_value'] ?? '', + 'default' => ( $field_def['default_value'] ?? '' ), ] ); From 9c5dedeb27a0d4764e10f10c5fea00b491365f93 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 13:31:26 +0100 Subject: [PATCH 138/344] remove tests from removed class --- .../helpers/fields/AnalysisFields.test.js | 404 ------------------ 1 file changed, 404 deletions(-) delete mode 100644 packages/js/tests/helpers/fields/AnalysisFields.test.js diff --git a/packages/js/tests/helpers/fields/AnalysisFields.test.js b/packages/js/tests/helpers/fields/AnalysisFields.test.js deleted file mode 100644 index a9a6acf6ccf..00000000000 --- a/packages/js/tests/helpers/fields/AnalysisFields.test.js +++ /dev/null @@ -1,404 +0,0 @@ -import AnalysisFields from "../../../src/helpers/fields/AnalysisFields"; - -/** - * Creates an input element. - * @param {string} id The ID. - * @returns {HTMLInputElement} The input element. - */ -const createInputElement = ( id ) => { - const inputElement = document.createElement( "input" ); - inputElement.id = id; - document.body.appendChild( inputElement ); - - return inputElement; -}; - -/** - * Mocks the window to override specific data. - * @param {Object} data The data to set on the window. - * @returns {jest.SpyInstance} The spy. Be sure to restore at the end of the test. - */ -const mockWindow = ( data ) => { - const original = { ...window }; - const spy = jest.spyOn( global, "window", "get" ); - spy.mockImplementation( () => ( { - ...original, - ...data, - } ) ); - - return spy; -}; - -describe( "keyphrase", () => { - const id = { - terms: "hidden_wpseo_focuskw", - posts: "yoast_wpseo_focuskw", - }; - - describe( "get keyphraseElement", () => { - it( "returns null when no element is present", () => { - expect( AnalysisFields.keyphraseElement ).toBeNull(); - } ); - - it( "gets the element for non-posts by default", () => { - const inputElement = createInputElement( id.terms ); - - expect( AnalysisFields.keyphraseElement ).toBe( inputElement ); - - inputElement.remove(); - } ); - - it( "gets the element for posts", () => { - const inputElement = createInputElement( id.posts ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: true } } ); - - expect( AnalysisFields.keyphraseElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - - it( "gets the element for non-posts", () => { - const inputElement = createInputElement( id.terms ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: false } } ); - - expect( AnalysisFields.keyphraseElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - } ); - - describe( "get keyphrase", () => { - it( "returns an empty string when no element is present", () => { - expect( AnalysisFields.keyphrase ).toBe( "" ); - } ); - - it( "gets the keyphrase", () => { - const inputElement = createInputElement( id.terms ); - inputElement.value = "foo"; - - expect( AnalysisFields.keyphrase ).toBe( "foo" ); - - inputElement.remove(); - } ); - } ); - - describe( "set keyphrase", () => { - it( "does nothing when no element is present", () => { - AnalysisFields.keyphrase = "foo"; - expect( AnalysisFields.keyphraseElement ).toBeNull(); - } ); - - it( "sets the keyphrase", () => { - const inputElement = createInputElement( id.terms ); - - AnalysisFields.keyphrase = "foo"; - expect( AnalysisFields.keyphrase ).toBe( "foo" ); - - inputElement.remove(); - } ); - } ); -} ); - -describe( "isCornerstone", () => { - const id = { - terms: "hidden_wpseo_is_cornerstone", - posts: "yoast_wpseo_is_cornerstone", - }; - - describe( "get isCornerstoneElement", () => { - it( "returns null when no element is present", () => { - expect( AnalysisFields.isCornerstoneElement ).toBeNull(); - } ); - - it( "gets the element for non-posts by default", () => { - const inputElement = createInputElement( id.terms ); - - expect( AnalysisFields.isCornerstoneElement ).toBe( inputElement ); - - inputElement.remove(); - } ); - - it( "gets the element for posts", () => { - const inputElement = createInputElement( id.posts ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: true } } ); - - expect( AnalysisFields.isCornerstoneElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - - it( "gets the element for non-posts", () => { - const inputElement = createInputElement( id.terms ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: false } } ); - - expect( AnalysisFields.isCornerstoneElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - } ); - - describe( "get isCornerstone", () => { - it( "returns false when no element is present", () => { - expect( AnalysisFields.isCornerstone ).toBe( false ); - } ); - - it( "gets isCornerstone", () => { - const inputElement = createInputElement( id.terms ); - inputElement.value = "1"; - - expect( AnalysisFields.isCornerstone ).toBe( true ); - - inputElement.remove(); - } ); - } ); - - describe( "set isCornerstone", () => { - it( "does nothing when no element is present", () => { - AnalysisFields.isCornerstone = true; - expect( AnalysisFields.isCornerstoneElement ).toBeNull(); - } ); - - test.each( [ - // Happy path with boolean. - [ true, "1", true ], - [ false, "0", false ], - // Truthy with different types. - [ true, "1", "string" ], - [ true, "1", {} ], - [ true, "1", [] ], - [ true, "1", Object ], - // Falsy with different types. - [ false, "0", "" ], - [ false, "0", null ], - [ false, "0", undefined ], - ] )( "should return %s with the value %s when setting %s", ( expected, expectedValue, input ) => { - const inputElement = createInputElement( id.terms ); - - AnalysisFields.isCornerstone = input; - expect( AnalysisFields.isCornerstone ).toBe( expected ); - expect( AnalysisFields.isCornerstoneElement?.value ).toBe( expectedValue ); - - inputElement.remove(); - } ); - } ); -} ); - -describe( "seoScore", () => { - const id = { - terms: "hidden_wpseo_linkdex", - posts: "yoast_wpseo_linkdex", - }; - - describe( "get seoScoreElement", () => { - it( "returns null when no element is present", () => { - expect( AnalysisFields.seoScoreElement ).toBeNull(); - } ); - - it( "gets the element for non-posts by default", () => { - const inputElement = createInputElement( id.terms ); - - expect( AnalysisFields.seoScoreElement ).toBe( inputElement ); - - inputElement.remove(); - } ); - - it( "gets the element for posts", () => { - const inputElement = createInputElement( id.posts ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: true } } ); - - expect( AnalysisFields.seoScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - - it( "gets the element for non-posts", () => { - const inputElement = createInputElement( id.terms ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: false } } ); - - expect( AnalysisFields.seoScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - } ); - - describe( "get seoScore", () => { - it( "returns an empty string when no element is present", () => { - expect( AnalysisFields.seoScore ).toBe( "" ); - } ); - - it( "gets the seoScore", () => { - const inputElement = createInputElement( id.terms ); - inputElement.value = "9"; - - expect( AnalysisFields.seoScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); - - describe( "set seoScore", () => { - it( "does nothing when no element is present", () => { - AnalysisFields.seoScore = "9"; - expect( AnalysisFields.seoScoreElement ).toBeNull(); - } ); - - it( "sets the seoScore", () => { - const inputElement = createInputElement( id.terms ); - - AnalysisFields.seoScore = "9"; - expect( AnalysisFields.seoScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); -} ); - -describe( "readabilityScore", () => { - const id = { - terms: "hidden_wpseo_content_score", - posts: "yoast_wpseo_content_score", - }; - - describe( "get readabilityScoreElement", () => { - it( "returns null when no element is present", () => { - expect( AnalysisFields.readabilityScoreElement ).toBeNull(); - } ); - - it( "gets the element for non-posts by default", () => { - const inputElement = createInputElement( id.terms ); - - expect( AnalysisFields.readabilityScoreElement ).toBe( inputElement ); - - inputElement.remove(); - } ); - - it( "gets the element for posts", () => { - const inputElement = createInputElement( id.posts ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: true } } ); - - expect( AnalysisFields.readabilityScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - - it( "gets the element for non-posts", () => { - const inputElement = createInputElement( id.terms ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: false } } ); - - expect( AnalysisFields.readabilityScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - } ); - - describe( "get readabilityScore", () => { - it( "returns an empty string when no element is present", () => { - expect( AnalysisFields.readabilityScore ).toBe( "" ); - } ); - - it( "gets the readabilityScore", () => { - const inputElement = createInputElement( id.terms ); - inputElement.value = "9"; - - expect( AnalysisFields.readabilityScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); - - describe( "set readabilityScore", () => { - it( "does nothing when no element is present", () => { - AnalysisFields.readabilityScore = "9"; - expect( AnalysisFields.readabilityScoreElement ).toBeNull(); - } ); - - it( "sets the readabilityScore", () => { - const inputElement = createInputElement( id.terms ); - - AnalysisFields.readabilityScore = "9"; - expect( AnalysisFields.readabilityScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); -} ); - -describe( "inclusiveLanguageScore", () => { - const id = { - terms: "hidden_wpseo_inclusive_language_score", - posts: "yoast_wpseo_inclusive_language_score", - }; - - describe( "get inclusiveLanguageScoreElement", () => { - it( "returns null when no element is present", () => { - expect( AnalysisFields.inclusiveLanguageScoreElement ).toBeNull(); - } ); - - it( "gets the element for non-posts by default", () => { - const inputElement = createInputElement( id.terms ); - - expect( AnalysisFields.inclusiveLanguageScoreElement ).toBe( inputElement ); - - inputElement.remove(); - } ); - - it( "gets the element for posts", () => { - const inputElement = createInputElement( id.posts ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: true } } ); - - expect( AnalysisFields.inclusiveLanguageScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - - it( "gets the element for non-posts", () => { - const inputElement = createInputElement( id.terms ); - const windowSpy = mockWindow( { wpseoScriptData: { isPost: false } } ); - - expect( AnalysisFields.inclusiveLanguageScoreElement ).toBe( inputElement ); - - inputElement.remove(); - windowSpy.mockRestore(); - } ); - } ); - - describe( "get inclusiveLanguageScore", () => { - it( "returns an empty string when no element is present", () => { - expect( AnalysisFields.inclusiveLanguageScore ).toBe( "" ); - } ); - - it( "gets the inclusiveLanguageScore", () => { - const inputElement = createInputElement( id.terms ); - inputElement.value = "9"; - - expect( AnalysisFields.inclusiveLanguageScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); - - describe( "set inclusiveLanguageScore", () => { - it( "does nothing when no element is present", () => { - AnalysisFields.inclusiveLanguageScore = "9"; - expect( AnalysisFields.inclusiveLanguageScoreElement ).toBeNull(); - } ); - - it( "sets the inclusiveLanguageScore", () => { - const inputElement = createInputElement( id.terms ); - - AnalysisFields.inclusiveLanguageScore = "9"; - expect( AnalysisFields.inclusiveLanguageScore ).toBe( "9" ); - - inputElement.remove(); - } ); - } ); -} ); From bb67ad2623409620f8822ec979342283ee33b125 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 13:47:02 +0100 Subject: [PATCH 139/344] no need to trigger change on the hidden field. I changed the listener to listen to the actual change like in the classic editor. --- packages/js/src/initializers/primary-category.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/js/src/initializers/primary-category.js b/packages/js/src/initializers/primary-category.js index 007af1d6b11..be1dd7caab4 100644 --- a/packages/js/src/initializers/primary-category.js +++ b/packages/js/src/initializers/primary-category.js @@ -76,9 +76,6 @@ export default function initPrimaryCategory( $ ) { * @returns {void} */ function setPrimaryTerm( taxonomyName, termId ) { - const primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName ); - primaryTermInput.val( termId ).trigger( "change" ); - const yoastEditor = dispatch( "yoast-seo/editor" ); if ( yoastEditor ) { const termIdInt = parseInt( termId, 10 ); From b52f05c502f0e1521a2b431b9d96778d8e6e8423 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 13:48:28 +0100 Subject: [PATCH 140/344] initial editor store the same way in elementor, added also comments --- .../js/src/elementor/initializers/editor-store.js | 13 +++++++++++-- packages/js/src/initializers/editor-store.js | 7 +++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 7342ae52f1e..d8fb0a6ae11 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -46,15 +46,24 @@ const populateStore = store => { store.dispatch( actions.loadTwitterPreviewData() ); } - const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); - store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); + // Set initial value for focus keyphrase. + store.dispatch( actions.setFocusKeyword( get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ) ) ); + // Set initial value for primary terms. + const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); + // Set intial values for social preview. + store.dispatch( actions.loadTwitterPreviewData() ); + store.dispatch( actions.loadFacebookPreviewData() ); + + // Set initial values for the advanced settings. + store.dispatch( actions.loadAdvancedSettingsData() ); + store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 451ac9ccd5f..803ecec1c99 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -28,9 +28,11 @@ const populateStore = store => { } ) ); - const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); - store.dispatch( actions.setFocusKeyword( metadata.focuskw ) ); + // Set initial value for focus keyphrase. + store.dispatch( actions.setFocusKeyword( get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ) ) ); + // Set initial value for primary terms. + const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); @@ -41,6 +43,7 @@ const populateStore = store => { store.dispatch( actions.loadTwitterPreviewData() ); store.dispatch( actions.loadFacebookPreviewData() ); + // Set initial values for the advanced settings. store.dispatch( actions.loadAdvancedSettingsData() ); store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); From 1912305d51829781d382e574074e9b351e2ee16c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 13:54:04 +0100 Subject: [PATCH 141/344] used WPSEO_Taxonomy_Meta for getting term meta --- admin/formatter/class-term-metabox-formatter.php | 2 +- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index f05be917536..55b8cc7dd75 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -111,7 +111,7 @@ protected function get_metadata() { } if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { foreach ( $field_definitions->get( 'settings' ) as $key => $field ) { - $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); + $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); } } diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index c0a3dce0116..7e0504dc36e 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -163,7 +163,7 @@ private function get_field( $field_type, $field_name, $field_value, array $optio * * @return string */ - public function get_field_value( $field_name ) { + 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 ]; } From b19aed0b90f2405002c616abbbd81fb0038db20c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 11 Mar 2024 14:10:19 +0100 Subject: [PATCH 142/344] // Score is updated to the hidden field though the sync function. --- packages/js/src/analysis/PostDataCollector.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index fb5fef77a39..f2732349cf1 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -386,6 +386,8 @@ PostDataCollector.prototype.saveScores = function( score, keyword ) { publishBox.updateScore( "content", indicator.className ); + // Score is updated to the hidden field though the sync function. + if ( "" === keyword ) { indicator.className = "na"; indicator.screenReaderText = __( @@ -417,6 +419,8 @@ PostDataCollector.prototype.saveContentScore = function( score ) { updateTrafficLight( indicator ); updateAdminBar( indicator ); } + + // Score is updated to the hidden field though the sync function. }; /** @@ -434,6 +438,8 @@ PostDataCollector.prototype.saveInclusiveLanguageScore = function( score ) { updateTrafficLight( indicator ); updateAdminBar( indicator ); } + + // Score is updated to the hidden field though the sync function. }; From 47f6a81a08e0a4439343c59bc4ed19f9efc4c8fe Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 12 Mar 2024 10:12:25 +0100 Subject: [PATCH 143/344] register metadata wordproof in an initialiser --- admin/metabox/class-metabox.php | 6 +-- inc/class-wpseo-meta.php | 10 ---- src/initializers/wordproof-metadata.php | 63 +++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/initializers/wordproof-metadata.php diff --git a/admin/metabox/class-metabox.php b/admin/metabox/class-metabox.php index 011e630c9be..dff602e095a 100644 --- a/admin/metabox/class-metabox.php +++ b/admin/metabox/class-metabox.php @@ -208,11 +208,7 @@ public static function translate_meta_boxes() { '', WPSEO_Admin_Utils::get_new_tab_message() . '' ); - /* translators: %s expands to the post type name. */ - WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['title'] = __( 'Timestamp this %s', 'wordpress-seo' ); - WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['description'] = __( 'Use WordProof to timestamp this page to comply with legal regulations and join the fight for a more transparant and accountable internet.', 'wordpress-seo' ); - WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['0'] = __( 'Off', 'wordpress-seo' ); - WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['1'] = __( 'On', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' ); WPSEO_Meta::$meta_fields['advanced']['redirect']['description'] = __( 'The URL that this page should redirect to.', 'wordpress-seo' ); diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index ac61d619c95..e2a05f66681 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -205,16 +205,6 @@ class WPSEO_Meta { 'default_value' => '', 'description' => '', // Translation added later. ], - 'wordproof_timestamp' => [ - 'type' => 'hidden', - 'title' => '', // Translation added later. - 'default_value' => '0', - 'description' => '', // Translation added later. - 'options' => [ - '0' => '', // Off - translation added later. - '1' => '', // On - translation added later. - ], - ], ], 'social' => [], 'schema' => [ diff --git a/src/initializers/wordproof-metadata.php b/src/initializers/wordproof-metadata.php new file mode 100644 index 00000000000..4af61095e8b --- /dev/null +++ b/src/initializers/wordproof-metadata.php @@ -0,0 +1,63 @@ + + */ + public static function get_conditionals() { + return [ + Wordproof_Plugin_Inactive_Conditional::class, + Non_Multisite_Conditional::class, + Wordproof_Integration_Active_Conditional::class, + ]; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function initialize() { + /** + * Called by WPSEO_Meta to add extra meta fields to the ones defined there. + */ + \add_filter( 'add_extra_wpseo_meta_fields', [ $this, 'add_meta_field' ] ); + } + + /** + * Adds the WordProof integration toggle to the array. + * + * @param array> $fields The currently registered meta fields. + * + * @return array> A new array with meta fields. + */ + public function add_meta_field( $fields ) { + $fields['advanced']['wordproof_timestamp'] = [ + 'type' => 'hidden', + /* translators: %s expands to the post type name. */ + 'title' => \__( 'Timestamp this %s', 'wordpress-seo' ), + 'default_value' => '0', + 'description' => \__( 'Use WordProof to timestamp this page to comply with legal regulations and join the fight for a more transparant and accountable internet.', 'wordpress-seo' ), + 'options' => [ + '0' => \__( 'Off', 'wordpress-seo' ), + '1' => \__( 'On', 'wordpress-seo' ), + ], + ]; + + return $fields; + } +} From e43b3dfca53d9ed8e2bd73913bd1125e40ec3ee0 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 12 Mar 2024 10:12:59 +0100 Subject: [PATCH 144/344] get term metadata with wpseo taxonomy meta class --- admin/formatter/class-term-metabox-formatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 55b8cc7dd75..c6c3346e680 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -107,7 +107,7 @@ protected function get_metadata() { $meta_prefix = 'wpseo_'; foreach ( $field_definitions->get( 'content' ) as $key => $field ) { - $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); + $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); } if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { foreach ( $field_definitions->get( 'settings' ) as $key => $field ) { @@ -117,7 +117,7 @@ protected function get_metadata() { if ( $is_social_enabled ) { foreach ( $field_definitions->get( 'social' ) as $key => $field ) { - $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); + $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); } } From 442a63d53790938991c3aa95d6af9b8b20e45abd Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 12 Mar 2024 14:05:57 +0100 Subject: [PATCH 145/344] restore to match the hidden fields --- admin/formatter/class-term-metabox-formatter.php | 6 +++--- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index c6c3346e680..f05be917536 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -107,17 +107,17 @@ protected function get_metadata() { $meta_prefix = 'wpseo_'; foreach ( $field_definitions->get( 'content' ) as $key => $field ) { - $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { foreach ( $field_definitions->get( 'settings' ) as $key => $field ) { - $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } } if ( $is_social_enabled ) { foreach ( $field_definitions->get( 'social' ) as $key => $field ) { - $metadata[ $key ] = WPSEO_Taxonomy_Meta::get_term_meta( $meta_prefix . $key ); + $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } } diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index 7e0504dc36e..c0a3dce0116 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -163,7 +163,7 @@ private function get_field( $field_type, $field_name, $field_value, array $optio * * @return string */ - private function get_field_value( $field_name ) { + public function get_field_value( $field_name ) { if ( isset( $this->tax_meta[ $field_name ] ) && $this->tax_meta[ $field_name ] !== '' ) { return $this->tax_meta[ $field_name ]; } From 8757d06d7f0de1fe9548a1533a7ac632af9a6aa2 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 18 Mar 2024 16:41:14 +0100 Subject: [PATCH 146/344] The default is true in WPSEO_Option_Social in inc/options/class-wpseo-option-social.php lines 39 and 42 --- inc/class-wpseo-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index e2a05f66681..e1cc8182af2 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -281,7 +281,7 @@ class WPSEO_Meta { */ public static function init() { foreach ( self::$social_networks as $option => $network ) { - if ( WPSEO_Options::get( $option, false ) === true ) { + if ( WPSEO_Options::get( $option, true ) === true ) { foreach ( self::$social_fields as $box => $type ) { self::$meta_fields['social'][ $network . '-' . $box ] = [ 'type' => $type, From bab7f5dc2020a1a1a0f626911aec81a614654e8e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 18 Mar 2024 17:17:53 +0100 Subject: [PATCH 147/344] reverting name change --- packages/js/src/redux/actions/facebookEditor.js | 2 +- packages/js/src/redux/reducers/facebookEditor.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/actions/facebookEditor.js b/packages/js/src/redux/actions/facebookEditor.js index 5cd11215e09..26b72e9a76c 100644 --- a/packages/js/src/redux/actions/facebookEditor.js +++ b/packages/js/src/redux/actions/facebookEditor.js @@ -63,7 +63,7 @@ export const loadFacebookPreviewData = () => { return { type: LOAD_FACEBOOK_PREVIEW, - imageId: get( window, "wpseoScriptData.metabox.metadata.opengraph-image-id", "" ), + id: get( window, "wpseoScriptData.metabox.metadata.opengraph-image-id", "" ), imageUrl: get( window, "wpseoScriptData.metabox.metadata.opengraph-image", "" ), description: get( window, "wpseoScriptData.metabox.metadata.opengraph-description", "" ) || getSocialDescriptionTemplate(), title: get( window, "wpseoScriptData.metabox.metadata.opengraph-title", "" ) || getSocialTitleTemplate(), diff --git a/packages/js/src/redux/reducers/facebookEditor.js b/packages/js/src/redux/reducers/facebookEditor.js index b5ac6d2c8d8..34e7ab01507 100644 --- a/packages/js/src/redux/reducers/facebookEditor.js +++ b/packages/js/src/redux/reducers/facebookEditor.js @@ -37,7 +37,7 @@ const facebookReducer = ( state = initialState, action ) => { ...state, title: action.title, description: action.description, - image: { id: action.imageId, url: action.imageUrl }, + image: { id: action.id, url: action.imageUrl }, }; case SET_FACEBOOK_TITLE: return { ...state, title: action.title }; From fc46bdbb592dd24bc3410a7394c49e5463014458 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 18 Mar 2024 17:20:59 +0100 Subject: [PATCH 148/344] Check if hidden fields are present before adding syncing --- packages/js/src/helpers/fields/index.js | 1 + packages/js/src/post-edit.js | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index e90ed53451d..c3cdcc34660 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,3 +1,4 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; +export * from "./hiddenFieldsSync"; diff --git a/packages/js/src/post-edit.js b/packages/js/src/post-edit.js index 4bf3af791c7..7a5d39bd8f4 100644 --- a/packages/js/src/post-edit.js +++ b/packages/js/src/post-edit.js @@ -1,3 +1,4 @@ +/* eslint-disable complexity */ import domReady from "@wordpress/dom-ready"; import jQuery from "jquery"; @@ -11,7 +12,7 @@ import initTabs from "./initializers/metabox-tabs"; import initPostScraper from "./initializers/post-scraper"; import initPrimaryCategory from "./initializers/primary-category"; import initializeInsights from "./insights/initializer"; -import { hiddenFieldsSync } from "./helpers/fields/hiddenFieldsSync"; +import { hiddenFieldsSync, hasHiddenFields } from "./helpers/fields"; // Backwards compatibility globals. window.wpseoPostScraperL10n = window.wpseoScriptData.metabox; @@ -32,7 +33,9 @@ domReady( () => { const store = initEditorStore(); // Initialize the hidden fields sync. - hiddenFieldsSync(); + if ( hasHiddenFields() ) { + hiddenFieldsSync(); + } // Initialize the editor integration window.yoast.initEditorIntegration( store ); From 65115e8db82b959b33e62f7b10d6ac600d3abceb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 18 Mar 2024 17:23:55 +0100 Subject: [PATCH 149/344] restore naming --- packages/js/src/redux/actions/twitterEditor.js | 2 +- packages/js/src/redux/reducers/twitterEditor.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/actions/twitterEditor.js b/packages/js/src/redux/actions/twitterEditor.js index 11a5009b3e7..ba584b26453 100644 --- a/packages/js/src/redux/actions/twitterEditor.js +++ b/packages/js/src/redux/actions/twitterEditor.js @@ -63,7 +63,7 @@ export const loadTwitterPreviewData = () => { return { type: LOAD_TWITTER_PREVIEW, - imageId: get( window, "wpseoScriptData.metabox.metadata.twitter-image-id", "" ), + id: get( window, "wpseoScriptData.metabox.metadata.twitter-image-id", "" ), imageUrl: get( window, "wpseoScriptData.metabox.metadata.twitter-image", "" ), description: get( window, "wpseoScriptData.metabox.metadata.twitter-description", "" ) || getSocialDescriptionTemplate(), title: get( window, "wpseoScriptData.metabox.metadata.twitter-title", "" ) || getSocialTitleTemplate(), diff --git a/packages/js/src/redux/reducers/twitterEditor.js b/packages/js/src/redux/reducers/twitterEditor.js index ddc7e64fde2..8d4e8806331 100644 --- a/packages/js/src/redux/reducers/twitterEditor.js +++ b/packages/js/src/redux/reducers/twitterEditor.js @@ -31,7 +31,7 @@ const twitterReducer = ( state = initialState, action ) => { ...state, title: action.title, description: action.description, - image: { id: action.imageId, url: action.imageUrl }, + image: { id: action.id, url: action.imageUrl }, }; case SET_TWITTER_TITLE: return { ...state, title: action.title }; From cc2cd14b0fc859f4634c024fe9adebda102a56e6 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 12:52:40 +0100 Subject: [PATCH 150/344] Add initial states for social appearance --- .../src/components/social/FacebookWrapper.js | 4 --- .../src/components/social/TwitterWrapper.js | 7 ----- packages/js/src/containers/FacebookEditor.js | 2 -- packages/js/src/containers/TwitterEditor.js | 2 -- .../elementor/containers/FacebookEditor.js | 2 -- .../src/elementor/containers/TwitterEditor.js | 2 -- packages/js/src/initializers/editor-store.js | 6 ++-- .../js/src/redux/actions/facebookEditor.js | 24 --------------- .../js/src/redux/actions/twitterEditor.js | 25 ---------------- packages/js/src/redux/initialState/index.js | 9 ++++++ .../redux/initialState/socialAppearance.js | 29 +++++++++++++++++++ .../js/src/redux/reducers/facebookEditor.js | 8 ----- 12 files changed, 40 insertions(+), 80 deletions(-) create mode 100644 packages/js/src/redux/initialState/index.js create mode 100644 packages/js/src/redux/initialState/socialAppearance.js diff --git a/packages/js/src/components/social/FacebookWrapper.js b/packages/js/src/components/social/FacebookWrapper.js index 407be60a037..87733779598 100644 --- a/packages/js/src/components/social/FacebookWrapper.js +++ b/packages/js/src/components/social/FacebookWrapper.js @@ -21,9 +21,6 @@ const FacebookWrapper = ( props ) => { }, [ setActiveMetaTabId ] ); useEffect( () => { - // Load on the next cycle because the editor inits asynchronously, and we need to load the data after the component is fully loaded. - setTimeout( props.onLoad ); - // Add event listener for meta section tab change. window.addEventListener( "YoastSEO:metaTabChange", handleMetaTabChange ); @@ -47,7 +44,6 @@ const FacebookWrapper = ( props ) => { FacebookWrapper.propTypes = { isPremium: PropTypes.bool.isRequired, - onLoad: PropTypes.func.isRequired, location: PropTypes.string.isRequired, }; diff --git a/packages/js/src/components/social/TwitterWrapper.js b/packages/js/src/components/social/TwitterWrapper.js index 056e35a49c6..8e17983f771 100644 --- a/packages/js/src/components/social/TwitterWrapper.js +++ b/packages/js/src/components/social/TwitterWrapper.js @@ -1,4 +1,3 @@ -import { useEffect } from "@wordpress/element"; import { Slot } from "@wordpress/components"; import PropTypes from "prop-types"; @@ -13,11 +12,6 @@ import SocialForm from "../social/SocialForm"; * @returns {JSX.Element} The TwitterWrapper. */ const TwitterWrapper = ( props ) => { - useEffect( () => { - // Load on the next cycle because the editor inits asynchronously, and we need to load the data after the component is fully loaded. - setTimeout( props.onLoad ); - }, [] ); - return props.isPremium ? : ; @@ -25,7 +19,6 @@ const TwitterWrapper = ( props ) => { TwitterWrapper.propTypes = { isPremium: PropTypes.bool.isRequired, - onLoad: PropTypes.func.isRequired, location: PropTypes.string.isRequired, }; diff --git a/packages/js/src/containers/FacebookEditor.js b/packages/js/src/containers/FacebookEditor.js index 124b73d81ac..f11f818736b 100644 --- a/packages/js/src/containers/FacebookEditor.js +++ b/packages/js/src/containers/FacebookEditor.js @@ -79,7 +79,6 @@ export default compose( [ setFacebookPreviewTitle, setFacebookPreviewDescription, clearFacebookPreviewImage, - loadFacebookPreviewData, findCustomFields, } = dispatch( "yoast-seo/editor" ); @@ -90,7 +89,6 @@ export default compose( [ onRemoveImageClick: clearFacebookPreviewImage, onDescriptionChange: setFacebookPreviewDescription, onTitleChange: setFacebookPreviewTitle, - onLoad: loadFacebookPreviewData, onReplacementVariableSearchChange: getMemoizedFindCustomFields( postId, findCustomFields ), }; } ), diff --git a/packages/js/src/containers/TwitterEditor.js b/packages/js/src/containers/TwitterEditor.js index 542c0fdc0bc..0bf6d4acaa6 100644 --- a/packages/js/src/containers/TwitterEditor.js +++ b/packages/js/src/containers/TwitterEditor.js @@ -86,7 +86,6 @@ export default compose( [ setTwitterPreviewTitle, setTwitterPreviewDescription, clearTwitterPreviewImage, - loadTwitterPreviewData, findCustomFields, } = dispatch( "yoast-seo/editor" ); @@ -97,7 +96,6 @@ export default compose( [ onRemoveImageClick: clearTwitterPreviewImage, onDescriptionChange: setTwitterPreviewDescription, onTitleChange: setTwitterPreviewTitle, - onLoad: loadTwitterPreviewData, onReplacementVariableSearchChange: getMemoizedFindCustomFields( postId, findCustomFields ), }; } ), diff --git a/packages/js/src/elementor/containers/FacebookEditor.js b/packages/js/src/elementor/containers/FacebookEditor.js index e6bd5b0e167..a9a40b75c85 100644 --- a/packages/js/src/elementor/containers/FacebookEditor.js +++ b/packages/js/src/elementor/containers/FacebookEditor.js @@ -78,14 +78,12 @@ export default compose( [ setFacebookPreviewTitle, setFacebookPreviewDescription, clearFacebookPreviewImage, - loadFacebookPreviewData, } = dispatch( "yoast-seo/editor" ); return { onSelectImageClick: selectMedia, onRemoveImageClick: clearFacebookPreviewImage, onDescriptionChange: setFacebookPreviewDescription, onTitleChange: setFacebookPreviewTitle, - onLoad: loadFacebookPreviewData, }; } ), diff --git a/packages/js/src/elementor/containers/TwitterEditor.js b/packages/js/src/elementor/containers/TwitterEditor.js index b7c6087015b..8041c6bf428 100644 --- a/packages/js/src/elementor/containers/TwitterEditor.js +++ b/packages/js/src/elementor/containers/TwitterEditor.js @@ -85,7 +85,6 @@ export default compose( [ setTwitterPreviewTitle, setTwitterPreviewDescription, clearTwitterPreviewImage, - loadTwitterPreviewData, } = dispatch( "yoast-seo/editor" ); return { @@ -93,7 +92,6 @@ export default compose( [ onRemoveImageClick: clearTwitterPreviewImage, onDescriptionChange: setTwitterPreviewDescription, onTitleChange: setTwitterPreviewTitle, - onLoad: loadTwitterPreviewData, }; } ), diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 803ecec1c99..22523fbc0c3 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -2,6 +2,7 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; import { get, pickBy, forEach } from "lodash"; import * as controls from "../redux/controls"; +import initialState from "../redux/initialState"; /** * Populates the store. @@ -39,10 +40,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - // Set intial values for social preview. - store.dispatch( actions.loadTwitterPreviewData() ); - store.dispatch( actions.loadFacebookPreviewData() ); - // Set initial values for the advanced settings. store.dispatch( actions.loadAdvancedSettingsData() ); @@ -73,6 +70,7 @@ export default function initEditorStore() { selectors, actions: pickBy( actions, x => typeof x === "function" ), controls, + initialState, } ); populateStore( store ); diff --git a/packages/js/src/redux/actions/facebookEditor.js b/packages/js/src/redux/actions/facebookEditor.js index 26b72e9a76c..e09361dbdd8 100644 --- a/packages/js/src/redux/actions/facebookEditor.js +++ b/packages/js/src/redux/actions/facebookEditor.js @@ -1,12 +1,7 @@ -/* External dependencies */ -import { select } from "@wordpress/data"; -import { get } from "lodash"; - export const SET_FACEBOOK_TITLE = "SET_FACEBOOK_TITLE"; export const SET_FACEBOOK_DESCRIPTION = "SET_FACEBOOK_DESCRIPTION"; export const SET_FACEBOOK_IMAGE = "SET_FACEBOOK_IMAGE"; export const CLEAR_FACEBOOK_IMAGE = "CLEAR_FACEBOOK_IMAGE"; -export const LOAD_FACEBOOK_PREVIEW = "LOAD_FACEBOOK_PREVIEW"; /** * An action creator for setting the socialPreview title. @@ -50,22 +45,3 @@ export const clearFacebookPreviewImage = () => { return { type: CLEAR_FACEBOOK_IMAGE }; }; -/** - * An action creator for loading all Facebook preview data. - * - * @returns {object} The action object. - */ -export const loadFacebookPreviewData = () => { - const { - getSocialDescriptionTemplate, - getSocialTitleTemplate, - } = select( "yoast-seo/editor" ); - - return { - type: LOAD_FACEBOOK_PREVIEW, - id: get( window, "wpseoScriptData.metabox.metadata.opengraph-image-id", "" ), - imageUrl: get( window, "wpseoScriptData.metabox.metadata.opengraph-image", "" ), - description: get( window, "wpseoScriptData.metabox.metadata.opengraph-description", "" ) || getSocialDescriptionTemplate(), - title: get( window, "wpseoScriptData.metabox.metadata.opengraph-title", "" ) || getSocialTitleTemplate(), - }; -}; diff --git a/packages/js/src/redux/actions/twitterEditor.js b/packages/js/src/redux/actions/twitterEditor.js index ba584b26453..7a38cc855fa 100644 --- a/packages/js/src/redux/actions/twitterEditor.js +++ b/packages/js/src/redux/actions/twitterEditor.js @@ -1,12 +1,7 @@ -/* External dependencies */ -import { select } from "@wordpress/data"; -import { get } from "lodash"; - export const SET_TWITTER_TITLE = "SET_TWITTER_TITLE"; export const SET_TWITTER_DESCRIPTION = "SET_TWITTER_DESCRIPTION"; export const SET_TWITTER_IMAGE = "SET_TWITTER_IMAGE"; export const CLEAR_TWITTER_IMAGE = "CLEAR_TWITTER_IMAGE"; -export const LOAD_TWITTER_PREVIEW = "LOAD_TWITTER_PREVIEW"; /** * An action creator for setting the socialPreview title. @@ -49,23 +44,3 @@ export const setTwitterPreviewImage = ( image ) => { export const clearTwitterPreviewImage = () => { return { type: CLEAR_TWITTER_IMAGE }; }; - -/** - * An action creator for loading all Twitter preview data. - * - * @returns {object} The action object. - */ -export const loadTwitterPreviewData = () => { - const { - getSocialDescriptionTemplate, - getSocialTitleTemplate, - } = select( "yoast-seo/editor" ); - - return { - type: LOAD_TWITTER_PREVIEW, - id: get( window, "wpseoScriptData.metabox.metadata.twitter-image-id", "" ), - imageUrl: get( window, "wpseoScriptData.metabox.metadata.twitter-image", "" ), - description: get( window, "wpseoScriptData.metabox.metadata.twitter-description", "" ) || getSocialDescriptionTemplate(), - title: get( window, "wpseoScriptData.metabox.metadata.twitter-title", "" ) || getSocialTitleTemplate(), - }; -}; diff --git a/packages/js/src/redux/initialState/index.js b/packages/js/src/redux/initialState/index.js new file mode 100644 index 00000000000..7ecdd947d08 --- /dev/null +++ b/packages/js/src/redux/initialState/index.js @@ -0,0 +1,9 @@ +import { facebookInitialState, twitterInitialState } from "./socialAppearance"; +export * from "./socialAppearance"; + +const initialState = { + facebookEditor: facebookInitialState, + twitterEditor: twitterInitialState, +}; + +export default initialState; diff --git a/packages/js/src/redux/initialState/socialAppearance.js b/packages/js/src/redux/initialState/socialAppearance.js new file mode 100644 index 00000000000..a01e1c62d36 --- /dev/null +++ b/packages/js/src/redux/initialState/socialAppearance.js @@ -0,0 +1,29 @@ +import { get } from "lodash"; +import { selectors } from "@yoast/externals/redux"; + +const { + getSocialTitleTemplate, + getSocialDescriptionTemplate, +} = selectors; + +export const facebookInitialState = { + title: get( window, "wpseoScriptData.metabox.metadata.opengraph-title", "" ) || getSocialTitleTemplate(), + description: get( window, "wpseoScriptData.metabox.metadata.opengraph-description", "" ) || getSocialDescriptionTemplate(), + warnings: [], + image: { + url: get( window, "wpseoScriptData.metabox.metadata.opengraph-image", "" ), + id: get( window, "wpseoScriptData.metabox.metadata.opengraph-image-id", "" ), + alt: "", + }, +}; + +export const twitterInitialState = { + title: get( window, "wpseoScriptData.metabox.metadata.twitter-title", "" ) || getSocialTitleTemplate(), + description: get( window, "wpseoScriptData.metabox.metadata.twitter-description", "" ) || getSocialDescriptionTemplate(), + warnings: [], + image: { + url: get( window, "wpseoScriptData.metabox.metadata.twitter-image", "" ), + id: get( window, "wpseoScriptData.metabox.metadata.twitter-image-id", "" ), + alt: "", + }, +}; diff --git a/packages/js/src/redux/reducers/facebookEditor.js b/packages/js/src/redux/reducers/facebookEditor.js index 34e7ab01507..9ea652cf910 100644 --- a/packages/js/src/redux/reducers/facebookEditor.js +++ b/packages/js/src/redux/reducers/facebookEditor.js @@ -1,6 +1,5 @@ import { CLEAR_FACEBOOK_IMAGE, - LOAD_FACEBOOK_PREVIEW, SET_FACEBOOK_DESCRIPTION, SET_FACEBOOK_IMAGE, SET_FACEBOOK_TITLE, @@ -32,13 +31,6 @@ const initialState = { */ const facebookReducer = ( state = initialState, action ) => { switch ( action.type ) { - case LOAD_FACEBOOK_PREVIEW: - return { - ...state, - title: action.title, - description: action.description, - image: { id: action.id, url: action.imageUrl }, - }; case SET_FACEBOOK_TITLE: return { ...state, title: action.title }; case SET_FACEBOOK_DESCRIPTION : From 21c23385b97cf4965d78cff20f5b4416056ab9fb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 12:54:31 +0100 Subject: [PATCH 151/344] adds initial state to the elementor editor --- packages/js/src/elementor/initializers/editor-store.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index d8fb0a6ae11..50fdb134773 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -4,6 +4,7 @@ import { get, pickBy, forEach } from "lodash"; import * as controls from "../../redux/controls"; import * as snippetEditorActions from "../redux/actions/snippetEditor"; import * as analysisSelectors from "../redux/selectors/analysis"; +import initialState from "../../redux/initialState"; /** * Populates the store. @@ -99,6 +100,7 @@ export default function initEditorStore() { ...snippetEditorActions, }, x => typeof x === "function" ), controls, + initialState, } ); populateStore( store ); From a6d9f5f6411c30f6230b007e188f42b89a5d04b6 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 13:02:10 +0100 Subject: [PATCH 152/344] remove load from twitter reducer --- packages/js/src/redux/reducers/twitterEditor.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/js/src/redux/reducers/twitterEditor.js b/packages/js/src/redux/reducers/twitterEditor.js index 8d4e8806331..fc6ba6e0857 100644 --- a/packages/js/src/redux/reducers/twitterEditor.js +++ b/packages/js/src/redux/reducers/twitterEditor.js @@ -1,4 +1,4 @@ -import { CLEAR_TWITTER_IMAGE, LOAD_TWITTER_PREVIEW, SET_TWITTER_DESCRIPTION, SET_TWITTER_IMAGE, SET_TWITTER_TITLE } from "../actions/twitterEditor"; +import { CLEAR_TWITTER_IMAGE, SET_TWITTER_DESCRIPTION, SET_TWITTER_IMAGE, SET_TWITTER_TITLE } from "../actions/twitterEditor"; /** * Initial state @@ -26,13 +26,6 @@ const initialState = { */ const twitterReducer = ( state = initialState, action ) => { switch ( action.type ) { - case LOAD_TWITTER_PREVIEW: - return { - ...state, - title: action.title, - description: action.description, - image: { id: action.id, url: action.imageUrl }, - }; case SET_TWITTER_TITLE: return { ...state, title: action.title }; case SET_TWITTER_DESCRIPTION : @@ -62,6 +55,4 @@ const twitterReducer = ( state = initialState, action ) => { } }; -/* eslint-enable complexity */ - export default twitterReducer; From 4ccf7fe271db7c340d2cebd5645f3414b301dfa9 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 13:21:14 +0100 Subject: [PATCH 153/344] add sync to term edit --- packages/js/src/term-edit.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/js/src/term-edit.js b/packages/js/src/term-edit.js index ba65dbfa384..b01c3bc8587 100644 --- a/packages/js/src/term-edit.js +++ b/packages/js/src/term-edit.js @@ -9,6 +9,7 @@ import initTermScraper from "./initializers/term-scraper"; import initializeInsights from "./insights/initializer"; import { termsTmceId } from "./lib/tinymce"; import initializeAiGenerator from "./ai-generator/initialize"; +import { hiddenFieldsSync, hasHiddenFields } from "./helpers/fields"; domReady( () => { // Backwards compatibility globals. @@ -23,6 +24,11 @@ domReady( () => { // Initialize the editor store. const store = initEditorStore(); + // Initialize the hidden fields sync. + if ( hasHiddenFields() ) { + hiddenFieldsSync(); + } + // Initialize the editor integration window.yoast.initEditorIntegration( store ); const editorData = new window.yoast.EditorData( noop, store, termsTmceId ); From 5d79d63e80f3c21b751cd94855f424c8adc2b7ed Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 16:24:13 +0100 Subject: [PATCH 154/344] add support for elementor --- packages/js/src/elementor.js | 4 ++++ .../src/elementor/initializers/editor-store.js | 12 ++++-------- .../js/src/helpers/fields/hiddenFieldsSync.js | 17 +++++++++++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/js/src/elementor.js b/packages/js/src/elementor.js index 0a4885b38e8..1b7a002b476 100644 --- a/packages/js/src/elementor.js +++ b/packages/js/src/elementor.js @@ -13,6 +13,7 @@ import initAnalysis, { collectData } from "./initializers/analysis"; import initElementorEditorIntegration from "./initializers/elementor-editor-integration"; import initializeInsights from "./insights/initializer"; import initElementorWatcher from "./watchers/elementorWatcher"; +import { hiddenFieldsSync } from "./helpers/fields"; /* eslint-disable complexity */ /** @@ -25,6 +26,9 @@ function initialize() { window.YoastSEO = window.YoastSEO || {}; window.YoastSEO.store = initEditorStore(); + // Initialize the hidden fields sync if there are hidden fiels. + hiddenFieldsSync(); + // Initialize the editor data watcher. initElementorWatcher(); diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 50fdb134773..5d58ac087c8 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -40,11 +40,11 @@ const populateStore = store => { // Initialize the Social Preview data depending on which platform should be present const { facebook: showFacebook, twitter: showTwitter } = window.wpseoScriptData.metabox.showSocial; - if ( showFacebook ) { - store.dispatch( actions.loadFacebookPreviewData() ); + if ( ! showFacebook ) { + delete initialState.facebookEditor; } - if ( showTwitter ) { - store.dispatch( actions.loadTwitterPreviewData() ); + if ( ! showTwitter ) { + delete initialState.twitterEditor; } // Set initial value for focus keyphrase. @@ -58,10 +58,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - // Set intial values for social preview. - store.dispatch( actions.loadTwitterPreviewData() ); - store.dispatch( actions.loadFacebookPreviewData() ); - // Set initial values for the advanced settings. store.dispatch( actions.loadAdvancedSettingsData() ); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 958819859d2..6ff91059866 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -73,13 +73,18 @@ const createUpdater = () => { return ( data ) => { // Get the values from hidden fields. const hiddenFieldsData = {}; - const wpseoMetaElement = document.getElementById( "wpseo_meta" ); - const hiddenFields = wpseoMetaElement?.querySelectorAll( "input[type=hidden]" ); - forEach( hiddenFields, ( field ) => { - if ( field.id ) { - hiddenFieldsData[ field.id ] = field.value; + const yoastFormElement = document.getElementById( "yoast-form" ) || document.getElementById( "wpseo_meta" ); + + if ( yoastFormElement ) { + const hiddenFields = yoastFormElement?.querySelectorAll( "input[type=hidden]" ); + if ( hiddenFields ) { + forEach( hiddenFields, ( field ) => { + if ( field.id ) { + hiddenFieldsData[ field.id ] = field.value; + } + } ); } - } ); + } if ( ! hiddenFieldsData || ! data ) { return; From 246bf34291cb9b62fd13c75c261ae1f325db6922 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 16:42:11 +0100 Subject: [PATCH 155/344] cleanup tests from old code --- .../redux/actions/advancedSetings.test.js | 31 --------------- .../redux/actions/contentAnalysis.test.js | 38 ------------------- 2 files changed, 69 deletions(-) diff --git a/packages/js/tests/redux/actions/advancedSetings.test.js b/packages/js/tests/redux/actions/advancedSetings.test.js index 50e53129780..847375fa7ed 100644 --- a/packages/js/tests/redux/actions/advancedSetings.test.js +++ b/packages/js/tests/redux/actions/advancedSetings.test.js @@ -1,9 +1,4 @@ import * as actions from "../../../src/redux/actions/advancedSettings"; -import AdvancedFields from "../../../src/helpers/fields/AdvancedFields.js"; - -jest.mock( "../../../src/helpers/fields/AdvancedFields.js", () => { - return {}; -} ); const populatedFields = { noIndex: "testNoIndex", @@ -22,7 +17,6 @@ describe( "setNoIndex", () => { }; const actual = actions.setNoIndex( "testNoIndex" ); - expect( AdvancedFields.noIndex ).toEqual( "testNoIndex" ); expect( actual ).toEqual( expected ); } ); } ); @@ -35,7 +29,6 @@ describe( "setNoFollow", () => { }; const actual = actions.setNoFollow( "testNoFollow" ); - expect( AdvancedFields.noFollow ).toEqual( "testNoFollow" ); expect( actual ).toEqual( expected ); } ); } ); @@ -52,7 +45,6 @@ describe( "setAdvanced", () => { } ); it( "Joins the passed array into a comma separated string", () => { actions.setAdvanced( [ "testAdvanced1", "testAdvanced2" ] ); - expect( AdvancedFields.advanced ).toEqual( "testAdvanced1,testAdvanced2" ); } ); } ); describe( "setBreadcrumbsTitle", () => { @@ -64,7 +56,6 @@ describe( "setBreadcrumbsTitle", () => { }; const actual = actions.setBreadcrumbsTitle( "testBcTitle" ); - expect( AdvancedFields.breadcrumbsTitle ).toEqual( "testBcTitle" ); expect( actual ).toEqual( expected ); } ); } ); @@ -77,29 +68,7 @@ describe( "setCanonical", () => { }; const actual = actions.setCanonical( "www.testCanonicalUrl.com" ); - expect( AdvancedFields.canonical ).toEqual( "www.testCanonicalUrl.com" ); - expect( actual ).toEqual( expected ); - } ); -} ); -describe( "loadAdvancedSettingsData", () => { - it( "Returns a loadAdvancedSettings action and populates the advanced hidden fields", () => { - const expected = { - type: "LOAD_ADVANCED_SETTINGS", - settings: { - ...populatedFields, - isLoading: false, - advanced: populatedFields.advanced.split( "," ), - }, - - }; - - const actual = actions.loadAdvancedSettingsData(); expect( actual ).toEqual( expected ); } ); - it( "Retrieves the advanced settings string, and splits it into an array", () => { - const actual = actions.loadAdvancedSettingsData().settings.advanced; - expect( typeof AdvancedFields.advanced ).toEqual( "string" ); - expect( Array.isArray( actual ) ).toBeTruthy(); - } ); } ); diff --git a/packages/js/tests/redux/actions/contentAnalysis.test.js b/packages/js/tests/redux/actions/contentAnalysis.test.js index 1c8f3ddc13c..f19b6c7f7e2 100644 --- a/packages/js/tests/redux/actions/contentAnalysis.test.js +++ b/packages/js/tests/redux/actions/contentAnalysis.test.js @@ -1,4 +1,3 @@ -import AnalysisFields from "../../../src/helpers/fields/AnalysisFields"; import { REMOVE_KEYWORD, removeKeyword, @@ -116,19 +115,6 @@ describe( "SEO", () => { const actual = setOverallSeoScore( overallScore, keyword ); expect( actual ).toEqual( expected ); } ); - - it( "updates the SEO score element's value", () => { - const keyword = "keyword1"; - const overallScore = 3; - - const inputElement = createInputElement( "hidden_wpseo_linkdex" ); - - setOverallSeoScore( overallScore, keyword ); - expect( AnalysisFields.seoScore ).toEqual( "3" ); - expect( inputElement.value ).toEqual( "3" ); - - inputElement.remove(); - } ); } ); } ); @@ -170,18 +156,6 @@ describe( "Readability", () => { const actual = setOverallReadabilityScore( overallScore ); expect( actual ).toEqual( expected ); } ); - - it( "updates the readability score element's value", () => { - const overallScore = 3; - - const inputElement = createInputElement( "hidden_wpseo_content_score" ); - - setOverallReadabilityScore( overallScore ); - expect( AnalysisFields.readabilityScore ).toEqual( "3" ); - expect( inputElement.value ).toEqual( "3" ); - - inputElement.remove(); - } ); } ); } ); @@ -223,17 +197,5 @@ describe( "Inclusive language", () => { const actual = setOverallInclusiveLanguageScore( overallScore ); expect( actual ).toEqual( expected ); } ); - - it( "updates the inclusive language score element's value", () => { - const overallScore = 3; - - const inputElement = createInputElement( "hidden_wpseo_inclusive_language_score" ); - - setOverallInclusiveLanguageScore( overallScore ); - expect( AnalysisFields.inclusiveLanguageScore ).toEqual( "3" ); - expect( inputElement.value ).toEqual( "3" ); - - inputElement.remove(); - } ); } ); } ); From 7da3833464f6d75d5be6beac29f7466ccb3f5b32 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 19 Mar 2024 16:43:37 +0100 Subject: [PATCH 156/344] cleanup old code from tests --- .../js/tests/redux/actions/advancedSetings.test.js | 8 -------- .../js/tests/redux/actions/contentAnalysis.test.js | 13 ------------- 2 files changed, 21 deletions(-) diff --git a/packages/js/tests/redux/actions/advancedSetings.test.js b/packages/js/tests/redux/actions/advancedSetings.test.js index 847375fa7ed..030e40a9be4 100644 --- a/packages/js/tests/redux/actions/advancedSetings.test.js +++ b/packages/js/tests/redux/actions/advancedSetings.test.js @@ -1,13 +1,5 @@ import * as actions from "../../../src/redux/actions/advancedSettings"; -const populatedFields = { - noIndex: "testNoIndex", - noFollow: "testNoFollow", - advanced: "testAdvanced1,testAdvanced2", - breadcrumbsTitle: "testBcTitle", - canonical: "www.testCanonicalUrl.com", -}; - describe( "setNoIndex", () => { it( "Returns a setNoIndex action and populates the advanced hidden fields", () => { const expected = { diff --git a/packages/js/tests/redux/actions/contentAnalysis.test.js b/packages/js/tests/redux/actions/contentAnalysis.test.js index f19b6c7f7e2..4d2e41f70cf 100644 --- a/packages/js/tests/redux/actions/contentAnalysis.test.js +++ b/packages/js/tests/redux/actions/contentAnalysis.test.js @@ -23,19 +23,6 @@ import { updateSeoResult, } from "../../../src/redux/actions/contentAnalysis"; -/** - * Creates an input element. - * @param {string} id The ID. - * @returns {HTMLInputElement} The input element. - */ -const createInputElement = ( id ) => { - const inputElement = document.createElement( "input" ); - inputElement.id = id; - document.body.appendChild( inputElement ); - - return inputElement; -}; - describe( "SEO", () => { describe( "setSeoResultsForKeyword action creator", () => { it( "creates the setSeoResultsForKeyword action", () => { From 5aa0b013a5962d5d7054bd72b613a733a693164b Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 20 Mar 2024 09:24:25 +0100 Subject: [PATCH 157/344] cleanup tests --- packages/js/tests/redux/actions/cornerstoneContent.test.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/js/tests/redux/actions/cornerstoneContent.test.js b/packages/js/tests/redux/actions/cornerstoneContent.test.js index a23af20739f..20eb76a3435 100644 --- a/packages/js/tests/redux/actions/cornerstoneContent.test.js +++ b/packages/js/tests/redux/actions/cornerstoneContent.test.js @@ -1,9 +1,5 @@ import * as actions from "../../../src/redux/actions/cornerstoneContent"; -jest.mock( "../../../src/helpers/fields/AnalysisFields.js", () => { - return {}; -} ); - describe( "cornerstone actions", () => { it( "toggleCornerstoneContent should return an action with the TOGGLE_CORNERSTONE_CONTENT type", () => { const expected = { From f02f904d9a2679cfb9037f2f87c1525dd690b118 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 20 Mar 2024 10:42:14 +0100 Subject: [PATCH 158/344] Add tests to social appearance methods to get values from store to be synced --- .../SocialAppearanceFieldsStore.test.js | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js diff --git a/packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js b/packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js new file mode 100644 index 00000000000..8530ab0ead8 --- /dev/null +++ b/packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js @@ -0,0 +1,88 @@ +import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "../../../src/helpers/fields/facebookFieldsStore"; +import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "../../../src/helpers/fields/twitterFieldsStore"; +import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { select } from "@wordpress/data"; + +// Tests for the facebookFieldsStore.js and twitterFieldsStore.js files. + +jest.mock( "@wordpress/data", () => ( { + select: jest.fn(), +} ) ); + +const testCasesInteger = [ + { method: "getFacebookImageId", getFunction: getFacebookImageId }, + { method: "getTwitterImageId", getFunction: getTwitterImageId }, +]; + +describe.each( testCasesInteger )( "$method", ( { method, getFunction } ) => { + it( `should return string from ${method} when the id is an integer`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => 5, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "5" ); + } ); +} ); + + +const testCases = [ + { method: "getFacebookImageId", getFunction: getFacebookImageId }, + { method: "getFacebookTitle", getFunction: getFacebookTitle }, + { method: "getFacebookDescription", getFunction: getFacebookDescription }, + { method: "getFacebookImageUrl", getFunction: getFacebookImageUrl }, + { method: "getTwitterImageId", getFunction: getTwitterImageId }, + { method: "getTwitterTitle", getFunction: getTwitterTitle }, + { method: "getTwitterDescription", getFunction: getTwitterDescription }, + { method: "getTwitterImageUrl", getFunction: getTwitterImageUrl }, +]; + +describe.each( testCases )( "$method", ( { method, getFunction } ) => { + it( `should return empty string from ${method} when null`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => "string_result", + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "string_result" ); + } ); +} ); + + +describe.each( testCases )( "$method", ( { method, getFunction } ) => { + it( `should return empty string from ${method} when null`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => null, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "" ); + } ); +} ); + +describe.each( testCases )( "$method", ( { method, getFunction } ) => { + it( `should return empty string from ${method} when undefined`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => undefined, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "" ); + } ); +} ); From 49d5f7bcd816f19f6a48c5d70315bc8fbc8fcdae Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 20 Mar 2024 14:57:35 +0100 Subject: [PATCH 159/344] Check the right values are used for sync --- .../js/src/helpers/fields/hiddenFieldsSync.js | 65 +++++++++++-------- packages/js/src/helpers/fields/index.js | 6 ++ .../helpers/fields/hiddenFieldsSync.test.js | 55 ++++++++++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) create mode 100644 packages/js/tests/helpers/fields/hiddenFieldsSync.test.js diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 6ff91059866..8aec22736b7 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -64,7 +64,7 @@ const prepareValue = ( key, value ) => { * Creates an updater. * @returns {function} The updater. */ -const createUpdater = () => { +export const createUpdater = () => { /** * Syncs the data to the WP entity record. * @param {Object} data The collected data. @@ -94,7 +94,9 @@ const createUpdater = () => { const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); - + console.log( { hiddenFieldsData } ); + console.log( { data } ); + console.log( { changedData } ); if ( changedData ) { forEach( changedData, ( value, key ) => { document.getElementById( prefix + key ).value = prepareValue( key, value ); @@ -103,38 +105,45 @@ const createUpdater = () => { }; }; +/** + * The values to sync. + * + * Add values to sync from Yoast editor store to hidden fields. + */ +export const valuesToSync = { + focuskw: getFocusKeyphrase, + "meta-robots-noindex": getNoIndex, + // Same as meta-robots-noindex for term metabox. + noindex: getNoIndex, + "meta-robots-nofollow": getNoFollow, + "meta-robots-adv": getAdvanced, + bctitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordproof_timestamp: getWordProofTimestamp, + "opengraph-title": getFacebookTitle, + "opengraph-description": getFacebookDescription, + "opengraph-image": getFacebookImageUrl, + "opengraph-image-id": getFacebookImageId, + "twitter-title": getTwitterTitle, + "twitter-description": getTwitterDescription, + "twitter-image": getTwitterImageUrl, + "twitter-image-id": getTwitterImageId, + schema_page_type: getPageType, + schema_article_type: getArticleType, + is_cornerstone: isCornerstoneContent, + content_score: getReadabilityScore, + linkdex: getSeoScore, + inclusive_language_score: getInclusiveLanguageScore, + "estimated-reading-time-minutes": getEstimatedReadingTime, +}; + /** * Initializes the sync: from Yoast editor store to product metadata. * @returns {function} The un-subscriber. */ export const hiddenFieldsSync = () => { return subscribe( debounce( createWatcher( - createCollectorFromObject( { - focuskw: getFocusKeyphrase, - "meta-robots-noindex": getNoIndex, - // Same as meta-robots-noindex for term metabox. - noindex: getNoIndex, - "meta-robots-nofollow": getNoFollow, - "meta-robots-adv": getAdvanced, - bctitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordproof_timestamp: getWordProofTimestamp, - "opengraph-title": getFacebookTitle, - "opengraph-description": getFacebookDescription, - "opengraph-image": getFacebookImageUrl, - "opengraph-image-id": getFacebookImageId, - "twitter-title": getTwitterTitle, - "twitter-description": getTwitterDescription, - "twitter-image": getTwitterImageUrl, - "twitter-image-id": getTwitterImageId, - schema_page_type: getPageType, - schema_article_type: getArticleType, - is_cornerstone: isCornerstoneContent, - content_score: getReadabilityScore, - linkdex: getSeoScore, - inclusive_language_score: getInclusiveLanguageScore, - "estimated-reading-time-minutes": getEstimatedReadingTime, - } ), + createCollectorFromObject( valuesToSync ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); }; diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index c3cdcc34660..2633ef9d71b 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,4 +1,10 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; export * from "./hiddenFieldsSync"; +export * from "./facebookFieldsStore"; +export * from "./twitterFieldsStore"; +export * from "./analysisFieldsStore"; +export * from "./schemaFieldsStore"; +export * from "./advancedFieldsStore"; +export * from "./snippetEditorFieldsStore"; diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js new file mode 100644 index 00000000000..6dffe968e61 --- /dev/null +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -0,0 +1,55 @@ +import { valuesToSync } from "../../../src/helpers/fields/hiddenFieldsSync"; + +import { + getFocusKeyphrase, + getNoIndex, + getNoFollow, + getAdvanced, + getBreadcrumbsTitle, + getCanonical, + getWordProofTimestamp, + getFacebookTitle, + getFacebookDescription, + getFacebookImageUrl, + getFacebookImageId, + getTwitterTitle, + getTwitterDescription, + getTwitterImageUrl, + getTwitterImageId, + getPageType, + getArticleType, + isCornerstoneContent, + getReadabilityScore, + getSeoScore, + getInclusiveLanguageScore, + getEstimatedReadingTime } from "../../../src/helpers/fields"; + +describe( "hiddenFieldsSync", () => { + it( "should call createCollectorFromObject with the correct parameters", () => { + expect( valuesToSync ).toMatchObject( { + focuskw: getFocusKeyphrase, + "meta-robots-noindex": getNoIndex, + noindex: getNoIndex, + "meta-robots-nofollow": getNoFollow, + "meta-robots-adv": getAdvanced, + bctitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordproof_timestamp: getWordProofTimestamp, + "opengraph-title": getFacebookTitle, + "opengraph-description": getFacebookDescription, + "opengraph-image": getFacebookImageUrl, + "opengraph-image-id": getFacebookImageId, + "twitter-title": getTwitterTitle, + "twitter-description": getTwitterDescription, + "twitter-image": getTwitterImageUrl, + "twitter-image-id": getTwitterImageId, + schema_page_type: getPageType, + schema_article_type: getArticleType, + is_cornerstone: isCornerstoneContent, + content_score: getReadabilityScore, + linkdex: getSeoScore, + inclusive_language_score: getInclusiveLanguageScore, + "estimated-reading-time-minutes": getEstimatedReadingTime, + } ); + } ); +} ); From 026696e1769034df13b989a769f5da83aabb688e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 20 Mar 2024 15:01:28 +0100 Subject: [PATCH 160/344] fix tests comments --- packages/js/tests/helpers/fields/hiddenFieldsSync.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index 6dffe968e61..c034dd2a7f7 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -24,8 +24,8 @@ import { getInclusiveLanguageScore, getEstimatedReadingTime } from "../../../src/helpers/fields"; -describe( "hiddenFieldsSync", () => { - it( "should call createCollectorFromObject with the correct parameters", () => { +describe( "should sync the right values", () => { + it( "valuesToSync should include the correct parameters", () => { expect( valuesToSync ).toMatchObject( { focuskw: getFocusKeyphrase, "meta-robots-noindex": getNoIndex, From 98153979b7428f9515c7e31c0748b7b73bd2507d Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 20 Mar 2024 16:05:39 +0100 Subject: [PATCH 161/344] fix advanced settings loading and add tests --- .../js/src/components/AdvancedSettings.js | 6 -- .../js/src/containers/AdvancedSettings.js | 2 - .../elementor/initializers/editor-store.js | 3 - packages/js/src/initializers/editor-store.js | 3 - .../js/src/redux/actions/advancedSettings.js | 25 ----- .../redux/initialState/advancedSettings.js | 18 ++++ packages/js/src/redux/initialState/index.js | 2 + .../js/src/redux/reducers/advancedSettings.js | 7 -- .../src/redux/selectors/advancedSettings.js | 8 -- ...st.js => getValuesFromStoreToSync.test.js} | 95 ++++++++++++++++++- .../redux/reducers/advancedSettings.test.js | 1 - 11 files changed, 113 insertions(+), 57 deletions(-) create mode 100644 packages/js/src/redux/initialState/advancedSettings.js rename packages/js/tests/helpers/fields/{SocialAppearanceFieldsStore.test.js => getValuesFromStoreToSync.test.js} (50%) diff --git a/packages/js/src/components/AdvancedSettings.js b/packages/js/src/components/AdvancedSettings.js index 3bf558ef73f..a3964d2e7a1 100644 --- a/packages/js/src/components/AdvancedSettings.js +++ b/packages/js/src/components/AdvancedSettings.js @@ -282,7 +282,6 @@ const AdvancedSettings = ( props ) => { onBreadcrumbsTitleChange, onCanonicalChange, onWordProofTimestampChange, - isLoading, editorContext, isBreadcrumbsDisabled, isPrivateBlog, @@ -321,10 +320,6 @@ const AdvancedSettings = ( props ) => { postTypeName: editorContext.postTypeNameSingular, }; - if ( isLoading ) { - return null; - } - return ( @@ -346,7 +341,6 @@ AdvancedSettings.propTypes = { onNoIndexChange: PropTypes.func.isRequired, onCanonicalChange: PropTypes.func.isRequired, onWordProofTimestampChange: PropTypes.func, - isLoading: PropTypes.bool.isRequired, editorContext: PropTypes.object.isRequired, isBreadcrumbsDisabled: PropTypes.bool.isRequired, isPrivateBlog: PropTypes.bool, diff --git a/packages/js/src/containers/AdvancedSettings.js b/packages/js/src/containers/AdvancedSettings.js index 66a099b0c6f..581038cc39b 100644 --- a/packages/js/src/containers/AdvancedSettings.js +++ b/packages/js/src/containers/AdvancedSettings.js @@ -14,7 +14,6 @@ export default compose( [ getBreadcrumbsTitle, getCanonical, getWordProofTimestamp, - getIsLoading, getEditorContext, getPreferences, } = select( "yoast-seo/editor" ); @@ -28,7 +27,6 @@ export default compose( [ breadcrumbsTitle: getBreadcrumbsTitle(), canonical: getCanonical(), wordproofTimestamp: getWordProofTimestamp(), - isLoading: getIsLoading(), editorContext: getEditorContext(), isBreadcrumbsDisabled, isPrivateBlog, diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 5d58ac087c8..c9c378d9151 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -58,9 +58,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - // Set initial values for the advanced settings. - store.dispatch( actions.loadAdvancedSettingsData() ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 22523fbc0c3..8dbb1de0b26 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -40,9 +40,6 @@ const populateStore = store => { store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); } ); - // Set initial values for the advanced settings. - store.dispatch( actions.loadAdvancedSettingsData() ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/redux/actions/advancedSettings.js b/packages/js/src/redux/actions/advancedSettings.js index e6ba3451741..139363ecb71 100644 --- a/packages/js/src/redux/actions/advancedSettings.js +++ b/packages/js/src/redux/actions/advancedSettings.js @@ -1,12 +1,9 @@ -import { get } from "lodash"; - export const SET_NO_INDEX = "SET_NO_INDEX"; export const SET_NO_FOLLOW = "SET_NO_FOLLOW"; export const SET_ADVANCED = "SET_ADVANCED"; export const SET_BREADCRUMBS_TITLE = "SET_BREADCRUMBS_TITLE"; export const SET_CANONICAL_URL = "SET_CANONICAL_URL"; export const SET_WORDPROOF_TIMESTAMP = "SET_WORDPROOF_TIMESTAMP"; -export const LOAD_ADVANCED_SETTINGS = "LOAD_ADVANCED_SETTINGS"; /** * An action creator for setting the No Index value (Advanced Settings). @@ -73,25 +70,3 @@ export const setCanonical = ( value ) => { export const setWordProofTimestamp = ( value ) => { return { type: SET_WORDPROOF_TIMESTAMP, value }; }; - -/** - * An action creator for loading all Advanced Settings data. - * - * @returns {object} The action object. - */ -export const loadAdvancedSettingsData = () => { - const advancedValue = get( window, "wpseoScriptData.metabox.metadata.meta-robots-adv", "" ); - const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; - return { - type: LOAD_ADVANCED_SETTINGS, - settings: { - noIndex: get( window, "wpseoScriptData.metabox.metadata.meta-robots-noindex", "" ), - noFollow: get( window, "wpseoScriptData.metabox.metadata.meta-robots-nofollow", "0" ), - advanced: advancedList, - breadcrumbsTitle: get( window, "wpseoScriptData.metabox.metadata.bctitle", "" ), - canonical: get( window, "wpseoScriptData.metabox.metadata.canonical", "" ), - wordproofTimestamp: get( window, "wpseoScriptData.metabox.metadata.wordproof_timestamp", "" ) === "1", - isLoading: false, - }, - }; -}; diff --git a/packages/js/src/redux/initialState/advancedSettings.js b/packages/js/src/redux/initialState/advancedSettings.js new file mode 100644 index 00000000000..7c1be02d014 --- /dev/null +++ b/packages/js/src/redux/initialState/advancedSettings.js @@ -0,0 +1,18 @@ +import { get } from "lodash"; + +const advancedValue = get( window, "wpseoScriptData.metabox.metadata.meta-robots-adv", "" ); +const advancedList = typeof advancedValue === "string" ? advancedValue.split( "," ) : []; + +/** + * Initial state + */ +export const advancedSettingsInitialState = { + noIndex: get( window, "wpseoScriptData.metabox.metadata.meta-robots-noindex", "" ), + noFollow: get( window, "wpseoScriptData.metabox.metadata.meta-robots-nofollow", "0" ), + advanced: advancedList, + breadcrumbsTitle: get( window, "wpseoScriptData.metabox.metadata.bctitle", "" ), + canonical: get( window, "wpseoScriptData.metabox.metadata.canonical", "" ), + wordproofTimestamp: get( window, "wpseoScriptData.metabox.metadata.wordproof_timestamp", "" ) === "1", +}; + + diff --git a/packages/js/src/redux/initialState/index.js b/packages/js/src/redux/initialState/index.js index 7ecdd947d08..cd74e301390 100644 --- a/packages/js/src/redux/initialState/index.js +++ b/packages/js/src/redux/initialState/index.js @@ -1,9 +1,11 @@ import { facebookInitialState, twitterInitialState } from "./socialAppearance"; +import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; const initialState = { facebookEditor: facebookInitialState, twitterEditor: twitterInitialState, + advancedSettings: advancedSettingsInitialState, }; export default initialState; diff --git a/packages/js/src/redux/reducers/advancedSettings.js b/packages/js/src/redux/reducers/advancedSettings.js index ac85e09d769..eb7373f2ba7 100644 --- a/packages/js/src/redux/reducers/advancedSettings.js +++ b/packages/js/src/redux/reducers/advancedSettings.js @@ -5,7 +5,6 @@ import { SET_ADVANCED, SET_BREADCRUMBS_TITLE, SET_CANONICAL_URL, - LOAD_ADVANCED_SETTINGS, SET_WORDPROOF_TIMESTAMP, } from "../actions/advancedSettings"; @@ -19,7 +18,6 @@ const initialState = { breadcrumbsTitle: "", canonical: "", wordproofTimestamp: false, - isLoading: true, }; /** @@ -32,11 +30,6 @@ const initialState = { */ const advancedSettingsReducer = ( state = initialState, action ) => { switch ( action.type ) { - case LOAD_ADVANCED_SETTINGS: - return { - ...state, - ...action.settings, - }; case SET_NO_INDEX: return { ...state, noIndex: action.value }; case SET_NO_FOLLOW: diff --git a/packages/js/src/redux/selectors/advancedSettings.js b/packages/js/src/redux/selectors/advancedSettings.js index 15d02fbec92..e89dae8a7d9 100644 --- a/packages/js/src/redux/selectors/advancedSettings.js +++ b/packages/js/src/redux/selectors/advancedSettings.js @@ -53,11 +53,3 @@ export const getCanonical = state => get( state, "advancedSettings.canonical", " * @returns {Boolean} WordProof timestamp value. */ export const getWordProofTimestamp = state => get( state, "advancedSettings.wordproofTimestamp", false ); - -/** Gets the Twitter image src from the state. - * - * @param {Object} state The state. - * - * @returns {String} Twitter image src. - */ -export const getIsLoading = state => get( state, "advancedSettings.isLoading", true ); diff --git a/packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js similarity index 50% rename from packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js rename to packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js index 8530ab0ead8..d4a9ecacd46 100644 --- a/packages/js/tests/helpers/fields/SocialAppearanceFieldsStore.test.js +++ b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js @@ -1,5 +1,19 @@ -import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "../../../src/helpers/fields/facebookFieldsStore"; -import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "../../../src/helpers/fields/twitterFieldsStore"; +import { + getFacebookImageId, + getFacebookTitle, + getFacebookDescription, + getFacebookImageUrl, + getTwitterImageId, + getTwitterTitle, + getTwitterDescription, + getTwitterImageUrl, + getNoIndex, + getNoFollow, + getAdvanced, + getBreadcrumbsTitle, + getCanonical, + getWordProofTimestamp, +} from "../../../src/helpers/fields"; import { EDITOR_STORE } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; @@ -12,6 +26,8 @@ jest.mock( "@wordpress/data", () => ( { const testCasesInteger = [ { method: "getFacebookImageId", getFunction: getFacebookImageId }, { method: "getTwitterImageId", getFunction: getTwitterImageId }, + { method: "getNoIndex", getFunction: getNoIndex }, + { method: "getNoFollow", getFunction: getNoFollow }, ]; describe.each( testCasesInteger )( "$method", ( { method, getFunction } ) => { @@ -39,6 +55,9 @@ const testCases = [ { method: "getTwitterTitle", getFunction: getTwitterTitle }, { method: "getTwitterDescription", getFunction: getTwitterDescription }, { method: "getTwitterImageUrl", getFunction: getTwitterImageUrl }, + { method: "getAdvanced", getFunction: getAdvanced }, + { method: "getBreadcrumbsTitle", getFunction: getBreadcrumbsTitle }, + { method: "getCanonical", getFunction: getCanonical }, ]; describe.each( testCases )( "$method", ( { method, getFunction } ) => { @@ -86,3 +105,75 @@ describe.each( testCases )( "$method", ( { method, getFunction } ) => { expect( result ).toBe( "" ); } ); } ); + +const testCasesWithDefaultZero = [ + { method: "getNoIndex", getFunction: getNoIndex }, + { method: "getNoFollow", getFunction: getNoFollow }, +]; + +describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { + it( `should return zero string from ${method} when null`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => null, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "0" ); + } ); +} ); + +describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { + it( `should return zero string from ${method} when null`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => undefined, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "0" ); + } ); +} ); + +describe( "getWordProofTimestamp", () => { + it( "should return '1' when true", () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + getWordProofTimestamp: () => true, + }; + } + } ); + + const result = getWordProofTimestamp(); + expect( result ).toBe( "1" ); + } ); +} ); + +const getWordProofTimestampTestCases = [ + { value: true, expected: "1" }, + { value: false, expected: "" }, + { value: null, expected: "" }, + { value: undefined, expected: "" }, +]; +describe.each( getWordProofTimestampTestCases )( "$method", ( { value, expected } ) => { + it( `should return ${expected} from getWordProofTimestamp when value is ${value}`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + getWordProofTimestamp: () => value, + }; + } + } ); + + const result = getWordProofTimestamp(); + expect( result ).toBe( expected ); + } ); +} ); + diff --git a/packages/js/tests/redux/reducers/advancedSettings.test.js b/packages/js/tests/redux/reducers/advancedSettings.test.js index a6d2c7b3210..3f8bc241ef7 100644 --- a/packages/js/tests/redux/reducers/advancedSettings.test.js +++ b/packages/js/tests/redux/reducers/advancedSettings.test.js @@ -8,7 +8,6 @@ describe( "Analysis data reducer", () => { advanced: [], breadcrumbsTitle: "", canonical: "", - isLoading: true, }; it( "has a default state", () => { From 25fa048fba682e036f7cbcef3bf121e782447f22 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Thu, 21 Mar 2024 14:39:43 +0100 Subject: [PATCH 162/344] fix wordproof conditional --- ...rdproof-integration-active-conditional.php | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/conditionals/third-party/wordproof-integration-active-conditional.php b/src/conditionals/third-party/wordproof-integration-active-conditional.php index 9ee6bf27630..f4f75e68079 100644 --- a/src/conditionals/third-party/wordproof-integration-active-conditional.php +++ b/src/conditionals/third-party/wordproof-integration-active-conditional.php @@ -3,7 +3,6 @@ namespace Yoast\WP\SEO\Conditionals\Third_Party; use Yoast\WP\SEO\Conditionals\Conditional; -use Yoast\WP\SEO\Helpers\Wordproof_Helper; /** * Conditional that is met when the WordProof integration is toggled on. @@ -11,27 +10,12 @@ class Wordproof_Integration_Active_Conditional implements Conditional { /** - * The WordProof helper. + * Returns whether or not the WordProof Timestamp integration is active. * - * @var Wordproof_Helper - */ - private $wordproof; - - /** - * WordProof integration active constructor. - * - * @param Wordproof_Helper $wordproof The options helper. - */ - public function __construct( Wordproof_Helper $wordproof ) { - $this->wordproof = $wordproof; - } - - /** - * Returns whether or not the WordProof Timestamp plugin is active. - * - * @return bool Whether or not the WordProof Timestamp plugin is active. + * @return bool Whether or not the WordProof Timestamp integration is active. */ public function is_met() { - return $this->wordproof->integration_is_active(); + $options = \get_option( 'wpseo' ); + return $options['wordproof_integration_active']; } } From 78965075b68c97e902627511fecfa6843b2ef7a4 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Thu, 21 Mar 2024 16:14:23 +0100 Subject: [PATCH 163/344] add initial state for analysis fields --- .../elementor/initializers/editor-store.js | 3 --- packages/js/src/initializers/editor-store.js | 3 --- .../js/src/redux/initialState/analysis.js | 24 +++++++++++++++++++ packages/js/src/redux/initialState/index.js | 5 ++++ 4 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 packages/js/src/redux/initialState/analysis.js diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index c9c378d9151..8c7abe6fb03 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -47,9 +47,6 @@ const populateStore = store => { delete initialState.twitterEditor; } - // Set initial value for focus keyphrase. - store.dispatch( actions.setFocusKeyword( get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ) ) ); - // Set initial value for primary terms. const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 8dbb1de0b26..f48b81111fc 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -29,9 +29,6 @@ const populateStore = store => { } ) ); - // Set initial value for focus keyphrase. - store.dispatch( actions.setFocusKeyword( get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ) ) ); - // Set initial value for primary terms. const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); diff --git a/packages/js/src/redux/initialState/analysis.js b/packages/js/src/redux/initialState/analysis.js new file mode 100644 index 00000000000..b82cb11df1c --- /dev/null +++ b/packages/js/src/redux/initialState/analysis.js @@ -0,0 +1,24 @@ +import { get } from "lodash"; + +const inclusiveLanguageResultsInitialState = { + results: [], + overallScore: get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 ), +}; + +const readabilityResultsInitialState = { + results: [], + overallScore: get( window, "wpseoScriptData.metabox.metadata.content_score", 0 ), +}; + +const seoResultsInitialState = { + results: [], + overallScore: get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 ), +}; + +const analysis = { + seo: seoResultsInitialState, + readability: readabilityResultsInitialState, + inclusiveLanguage: inclusiveLanguageResultsInitialState, +}; + +export default analysis; diff --git a/packages/js/src/redux/initialState/index.js b/packages/js/src/redux/initialState/index.js index cd74e301390..7e118b3c335 100644 --- a/packages/js/src/redux/initialState/index.js +++ b/packages/js/src/redux/initialState/index.js @@ -1,11 +1,16 @@ +import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; +import analysis from "./analysis"; const initialState = { facebookEditor: facebookInitialState, twitterEditor: twitterInitialState, advancedSettings: advancedSettingsInitialState, + analysis, + focusKeyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), + isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", }; export default initialState; From 18328d71acd6ca14a0770b4ad8e10ad7e1f6b183 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Thu, 21 Mar 2024 16:21:35 +0100 Subject: [PATCH 164/344] no need for onload function when we have initial state --- .../js/src/elementor/initializers/editor-store.js | 4 ---- .../js/src/redux/actions/cornerstoneContent.js | 14 -------------- packages/js/src/redux/actions/focusKeyword.js | 14 -------------- 3 files changed, 32 deletions(-) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 8c7abe6fb03..ec0ccf32516 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -14,10 +14,6 @@ import initialState from "../../redux/initialState"; * @returns {void} */ const populateStore = store => { - // Initialize the cornerstone content. - store.dispatch( actions.loadCornerstoneContent() ); - // Initialize the focus keyphrase. - store.dispatch( actions.loadFocusKeyword() ); // Show marker buttons. store.dispatch( actions.setMarkerStatus( window.wpseoScriptData.metabox.elementorMarkerStatus ) ); diff --git a/packages/js/src/redux/actions/cornerstoneContent.js b/packages/js/src/redux/actions/cornerstoneContent.js index 3ceb15a3fb4..a0858fe066b 100644 --- a/packages/js/src/redux/actions/cornerstoneContent.js +++ b/packages/js/src/redux/actions/cornerstoneContent.js @@ -1,23 +1,9 @@ -import { get } from "lodash"; - const PREFIX = "WPSEO_"; export const LOAD_CORNERSTONE_CONTENT = `${ PREFIX }LOAD_CORNERSTONE_CONTENT`; export const TOGGLE_CORNERSTONE_CONTENT = `${ PREFIX }TOGGLE_CORNERSTONE_CONTENT`; export const SET_CORNERSTONE_CONTENT = `${ PREFIX }SET_CORNERSTONE_CONTENT`; -/** - * An action creator for loading the cornerstone content. - * - * @returns {Object} The load cornerstone content action. - */ -export const loadCornerstoneContent = () => { - return { - type: SET_CORNERSTONE_CONTENT, - isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", "0" ) === "1", - }; -}; - /** * An action creator for setting the cornerstone content toggle. * diff --git a/packages/js/src/redux/actions/focusKeyword.js b/packages/js/src/redux/actions/focusKeyword.js index f8450289d89..0afc268e661 100644 --- a/packages/js/src/redux/actions/focusKeyword.js +++ b/packages/js/src/redux/actions/focusKeyword.js @@ -1,22 +1,8 @@ -import { get } from "lodash"; - const PREFIX = "WPSEO_"; export const LOAD_FOCUS_KEYWORD = `${ PREFIX }LOAD_FOCUS_KEYWORD`; export const SET_FOCUS_KEYWORD = `${ PREFIX }SET_FOCUS_KEYWORD`; -/** - * Loads the focus keyphrase. - * - * @returns {object} The action object. - */ -export const loadFocusKeyword = () => { - return { - type: LOAD_FOCUS_KEYWORD, - keyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), - }; -}; - /** * An action creator for setting the focus keyword. * From bea6f2acbcfb70b2021c1eec4fe6e26084bcf8d3 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 13:56:35 +0100 Subject: [PATCH 165/344] Added tests to analysisFieldsStore.js --- .../fields/analysisFieldsStore.test.js | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 packages/js/tests/helpers/fields/analysisFieldsStore.test.js diff --git a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js new file mode 100644 index 00000000000..f02769961ba --- /dev/null +++ b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js @@ -0,0 +1,130 @@ +import { + getFocusKeyphrase, + getReadabilityScore, + getInclusiveLanguageScore, + getSeoScore, + getEstimatedReadingTime, + isCornerstoneContent, +} from "../../../src/helpers/fields"; +import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { select } from "@wordpress/data"; + +jest.mock( "@wordpress/data", () => ( { + select: jest.fn(), +} ) ); + + +const testCasesScoresInteger = [ + { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: 5 } }, + { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: 5 } }, + { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: 5 } }, + { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: 5 }, +]; + +describe.each( testCasesScoresInteger )( "$method", ( { method, getFunction, returnValueSelect } ) => { + it( `should return string from ${method} when the score is an integer`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => { + return returnValueSelect; + }, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "5" ); + } ); +} ); + +const testCasesScoresNull = [ + { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: null } }, + { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: null } }, + { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: null } }, + { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: null }, +]; + +describe.each( testCasesScoresNull )( "$method", ( { method, getFunction, returnValueSelect } ) => { + it( `should return zero string from ${method} when null`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => { + return returnValueSelect; + }, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "0" ); + } ); +} ); + +const testCasesScoresUndefined = [ + { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: undefined } }, + { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: undefined } }, + { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: undefined } }, + { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: undefined }, +]; + +describe.each( testCasesScoresUndefined )( "$method", ( { method, getFunction, returnValueSelect } ) => { + it( `should return zero string from ${method} when undefined`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + [ method ]: () => { + return returnValueSelect; + }, + }; + } + } ); + + const result = getFunction(); + expect( result ).toBe( "0" ); + } ); +} ); + + +const boolenaTestCases = [ + { value: true, expected: "1" }, + { value: false, expected: "0" }, + { value: null, expected: "0" }, + { value: undefined, expected: "0" }, +]; +describe.each( boolenaTestCases )( "$method", ( { value, expected } ) => { + it( `should return ${expected} from isCornerstoneContent when value is ${value}`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + isCornerstoneContent: () => value, + }; + } + } ); + + const result = isCornerstoneContent(); + expect( result ).toBe( expected ); + } ); +} ); + +const focusKeyphraseTestCases = [ + { value: "test", expected: "test" }, + { value: null, expected: "" }, + { value: undefined, expected: "" }, +]; + +describe.each( focusKeyphraseTestCases )( "$value", ( { value, expected } ) => { + it( `should return ${expected} from getFocusKeyphrase when value is ${value}`, () => { + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + getFocusKeyphrase: () => value, + }; + } + } ); + + const result = getFocusKeyphrase(); + expect( result ).toBe( expected ); + } ); +} ); From 9ece15f60b28c8764b6df44781e49daef053e774 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 14:03:49 +0100 Subject: [PATCH 166/344] fix tests --- .../tests/helpers/fields/analysisFieldsStore.test.js | 4 ++-- .../helpers/fields/getValuesFromStoreToSync.test.js | 10 ++++++---- .../js/tests/helpers/fields/hiddenFieldsSync.test.js | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js index f02769961ba..a17edf4e1fd 100644 --- a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js +++ b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js @@ -93,7 +93,7 @@ const boolenaTestCases = [ { value: null, expected: "0" }, { value: undefined, expected: "0" }, ]; -describe.each( boolenaTestCases )( "$method", ( { value, expected } ) => { +describe.each( boolenaTestCases )( "isCornerstoneContent", ( { value, expected } ) => { it( `should return ${expected} from isCornerstoneContent when value is ${value}`, () => { select.mockImplementation( ( store ) => { if ( store === EDITOR_STORE ) { @@ -114,7 +114,7 @@ const focusKeyphraseTestCases = [ { value: undefined, expected: "" }, ]; -describe.each( focusKeyphraseTestCases )( "$value", ( { value, expected } ) => { +describe.each( focusKeyphraseTestCases )( "getFocusKeyphrase", ( { value, expected } ) => { it( `should return ${expected} from getFocusKeyphrase when value is ${value}`, () => { select.mockImplementation( ( store ) => { if ( store === EDITOR_STORE ) { diff --git a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js index d4a9ecacd46..feb590b1392 100644 --- a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js +++ b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js @@ -17,7 +17,7 @@ import { import { EDITOR_STORE } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; -// Tests for the facebookFieldsStore.js and twitterFieldsStore.js files. +// Tests for the facebookFieldsStore.js, twitterFieldsStore.js and adnacedSettingsFieldsStore.js files. jest.mock( "@wordpress/data", () => ( { select: jest.fn(), @@ -31,7 +31,7 @@ const testCasesInteger = [ ]; describe.each( testCasesInteger )( "$method", ( { method, getFunction } ) => { - it( `should return string from ${method} when the id is an integer`, () => { + it( `should return string from ${method} when the value is an integer`, () => { select.mockImplementation( ( store ) => { if ( store === EDITOR_STORE ) { return { @@ -58,10 +58,11 @@ const testCases = [ { method: "getAdvanced", getFunction: getAdvanced }, { method: "getBreadcrumbsTitle", getFunction: getBreadcrumbsTitle }, { method: "getCanonical", getFunction: getCanonical }, + ]; describe.each( testCases )( "$method", ( { method, getFunction } ) => { - it( `should return empty string from ${method} when null`, () => { + it( `should return string from ${method} when value is string`, () => { select.mockImplementation( ( store ) => { if ( store === EDITOR_STORE ) { return { @@ -162,7 +163,7 @@ const getWordProofTimestampTestCases = [ { value: null, expected: "" }, { value: undefined, expected: "" }, ]; -describe.each( getWordProofTimestampTestCases )( "$method", ( { value, expected } ) => { +describe.each( getWordProofTimestampTestCases )( "getWordProofTimestamp", ( { value, expected } ) => { it( `should return ${expected} from getWordProofTimestamp when value is ${value}`, () => { select.mockImplementation( ( store ) => { if ( store === EDITOR_STORE ) { @@ -177,3 +178,4 @@ describe.each( getWordProofTimestampTestCases )( "$method", ( { value, expected } ); } ); + diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index c034dd2a7f7..ea26037ee77 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ import { valuesToSync } from "../../../src/helpers/fields/hiddenFieldsSync"; import { @@ -25,7 +26,7 @@ import { getEstimatedReadingTime } from "../../../src/helpers/fields"; describe( "should sync the right values", () => { - it( "valuesToSync should include the correct parameters", () => { + it( "valuesToSync should include the correct properties", () => { expect( valuesToSync ).toMatchObject( { focuskw: getFocusKeyphrase, "meta-robots-noindex": getNoIndex, From 78ffe67b8275700bd0b384067f488a7281be955b Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 14:23:04 +0100 Subject: [PATCH 167/344] rename initial state folder and fixed prepareValue --- packages/js/src/elementor/initializers/editor-store.js | 2 +- packages/js/src/helpers/fields/hiddenFieldsSync.js | 1 - packages/js/src/initializers/editor-store.js | 2 +- .../redux/{initialState => initial-state}/advancedSettings.js | 0 .../js/src/redux/{initialState => initial-state}/analysis.js | 0 packages/js/src/redux/{initialState => initial-state}/index.js | 2 -- .../redux/{initialState => initial-state}/socialAppearance.js | 0 7 files changed, 2 insertions(+), 5 deletions(-) rename packages/js/src/redux/{initialState => initial-state}/advancedSettings.js (100%) rename packages/js/src/redux/{initialState => initial-state}/analysis.js (100%) rename packages/js/src/redux/{initialState => initial-state}/index.js (92%) rename packages/js/src/redux/{initialState => initial-state}/socialAppearance.js (100%) diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index ec0ccf32516..01a6c27cd53 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -4,7 +4,7 @@ import { get, pickBy, forEach } from "lodash"; import * as controls from "../../redux/controls"; import * as snippetEditorActions from "../redux/actions/snippetEditor"; import * as analysisSelectors from "../redux/selectors/analysis"; -import initialState from "../../redux/initialState"; +import initialState from "../../redux/initial-state"; /** * Populates the store. diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 8aec22736b7..9167506f14f 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -46,7 +46,6 @@ const prepareSocialDescription = ( value ) => { const prepareValue = ( key, value ) => { switch ( key ) { case "wordproof_timestamp": - case "is_cornerstone": return value ? "1" : "0"; case "twitter-title": case "opengraph-title": diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index f48b81111fc..8b72b3cf127 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -2,7 +2,7 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; import { get, pickBy, forEach } from "lodash"; import * as controls from "../redux/controls"; -import initialState from "../redux/initialState"; +import initialState from "../redux/initial-state"; /** * Populates the store. diff --git a/packages/js/src/redux/initialState/advancedSettings.js b/packages/js/src/redux/initial-state/advancedSettings.js similarity index 100% rename from packages/js/src/redux/initialState/advancedSettings.js rename to packages/js/src/redux/initial-state/advancedSettings.js diff --git a/packages/js/src/redux/initialState/analysis.js b/packages/js/src/redux/initial-state/analysis.js similarity index 100% rename from packages/js/src/redux/initialState/analysis.js rename to packages/js/src/redux/initial-state/analysis.js diff --git a/packages/js/src/redux/initialState/index.js b/packages/js/src/redux/initial-state/index.js similarity index 92% rename from packages/js/src/redux/initialState/index.js rename to packages/js/src/redux/initial-state/index.js index 7e118b3c335..a21732292eb 100644 --- a/packages/js/src/redux/initialState/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -2,13 +2,11 @@ import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; -import analysis from "./analysis"; const initialState = { facebookEditor: facebookInitialState, twitterEditor: twitterInitialState, advancedSettings: advancedSettingsInitialState, - analysis, focusKeyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", }; diff --git a/packages/js/src/redux/initialState/socialAppearance.js b/packages/js/src/redux/initial-state/socialAppearance.js similarity index 100% rename from packages/js/src/redux/initialState/socialAppearance.js rename to packages/js/src/redux/initial-state/socialAppearance.js From dae0866e2528d19f6753431e6ff213d9dab7c88d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 14:55:15 +0100 Subject: [PATCH 168/344] seo analysis is being calculated onload --- .../js/src/redux/initial-state/analysis.js | 24 ------------------- packages/js/src/redux/initial-state/index.js | 1 + 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 packages/js/src/redux/initial-state/analysis.js diff --git a/packages/js/src/redux/initial-state/analysis.js b/packages/js/src/redux/initial-state/analysis.js deleted file mode 100644 index b82cb11df1c..00000000000 --- a/packages/js/src/redux/initial-state/analysis.js +++ /dev/null @@ -1,24 +0,0 @@ -import { get } from "lodash"; - -const inclusiveLanguageResultsInitialState = { - results: [], - overallScore: get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 ), -}; - -const readabilityResultsInitialState = { - results: [], - overallScore: get( window, "wpseoScriptData.metabox.metadata.content_score", 0 ), -}; - -const seoResultsInitialState = { - results: [], - overallScore: get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 ), -}; - -const analysis = { - seo: seoResultsInitialState, - readability: readabilityResultsInitialState, - inclusiveLanguage: inclusiveLanguageResultsInitialState, -}; - -export default analysis; diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index a21732292eb..377e966d88e 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -2,6 +2,7 @@ import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; +import analysis from "./analysis"; const initialState = { facebookEditor: facebookInitialState, From 822b5ec09fcb6733f7f2289d88c90db45a876e38 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 15:08:06 +0100 Subject: [PATCH 169/344] remove analysis from initial state --- packages/js/src/redux/initial-state/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index 377e966d88e..a21732292eb 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -2,7 +2,6 @@ import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; -import analysis from "./analysis"; const initialState = { facebookEditor: facebookInitialState, From 694cd8729aecb2c8dbbf5269b27f6ac94f9c5fd6 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 26 Mar 2024 15:53:04 +0100 Subject: [PATCH 170/344] add initial state to primary term --- .../js/src/elementor/initializers/editor-store.js | 10 +--------- packages/js/src/initializers/editor-store.js | 10 +--------- packages/js/src/redux/initial-state/index.js | 2 ++ .../js/src/redux/initial-state/primaryTaxonomies.js | 12 ++++++++++++ 4 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 packages/js/src/redux/initial-state/primaryTaxonomies.js diff --git a/packages/js/src/elementor/initializers/editor-store.js b/packages/js/src/elementor/initializers/editor-store.js index 01a6c27cd53..a3bd66c8a65 100644 --- a/packages/js/src/elementor/initializers/editor-store.js +++ b/packages/js/src/elementor/initializers/editor-store.js @@ -1,6 +1,6 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; -import { get, pickBy, forEach } from "lodash"; +import { get, pickBy } from "lodash"; import * as controls from "../../redux/controls"; import * as snippetEditorActions from "../redux/actions/snippetEditor"; import * as analysisSelectors from "../redux/selectors/analysis"; @@ -43,14 +43,6 @@ const populateStore = store => { delete initialState.twitterEditor; } - // Set initial value for primary terms. - const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); - const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); - forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); - } ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index 8b72b3cf127..e6fad1d8915 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -1,6 +1,6 @@ import { combineReducers, registerStore } from "@wordpress/data"; import { actions, reducers, selectors } from "@yoast/externals/redux"; -import { get, pickBy, forEach } from "lodash"; +import { get, pickBy } from "lodash"; import * as controls from "../redux/controls"; import initialState from "../redux/initial-state"; @@ -29,14 +29,6 @@ const populateStore = store => { } ) ); - // Set initial value for primary terms. - const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); - const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); - forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - store.dispatch( actions.setPrimaryTaxonomyId( taxonomy, value ) ); - } ); - store.dispatch( actions.setSEMrushChangeCountry( window.wpseoScriptData.metabox.countryCode ) ); store.dispatch( actions.setSEMrushLoginStatus( window.wpseoScriptData.metabox.SEMrushLoginStatus ) ); store.dispatch( actions.setWincherLoginStatus( window.wpseoScriptData.metabox.wincherLoginStatus, false ) ); diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index a21732292eb..0f01035c147 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -2,6 +2,7 @@ import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; import { advancedSettingsInitialState } from "./advancedSettings"; export * from "./socialAppearance"; +import primaryTaxonomies from "./primaryTaxonomies"; const initialState = { facebookEditor: facebookInitialState, @@ -9,6 +10,7 @@ const initialState = { advancedSettings: advancedSettingsInitialState, focusKeyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", + primaryTaxonomies, }; export default initialState; diff --git a/packages/js/src/redux/initial-state/primaryTaxonomies.js b/packages/js/src/redux/initial-state/primaryTaxonomies.js new file mode 100644 index 00000000000..7e740664b7d --- /dev/null +++ b/packages/js/src/redux/initial-state/primaryTaxonomies.js @@ -0,0 +1,12 @@ +import { get, pickBy, forEach } from "lodash"; + +const primaryTaxonomies = {}; + +const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); +const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); +forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + primaryTaxonomies[ taxonomy ] = value; +} ); + +export default primaryTaxonomies; From 5dd5f3bc27509fbbc7fefd190159d7e00df614a8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 27 Mar 2024 11:10:13 +0100 Subject: [PATCH 171/344] add tests to getPrimaryTerms and refactor getPrimaryTerms --- .../js/src/helpers/fields/blockEditorSync.js | 28 +++---- .../js/src/helpers/fields/hiddenFieldsSync.js | 7 +- .../fields/primaryTaxonomiesFieldsStore.js | 27 +++++++ .../js/src/initializers/primary-category.js | 13 ++-- .../helpers/fields/getPrimaryTerms.test.js | 74 +++++++++++++++++++ 5 files changed, 121 insertions(+), 28 deletions(-) create mode 100644 packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js create mode 100644 packages/js/tests/helpers/fields/getPrimaryTerms.test.js diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 840cd994272..2d030d030a0 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get, defaultTo } from "lodash"; +import { debounce, forEach, pickBy, map } from "lodash"; import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; @@ -8,24 +8,14 @@ import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; +import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; -/** - * Retrieves primary terms from store methods. - * - * @returns {object} An object with taxonomies keys and their primary term id. - */ -const getPrimaryTerms = () => { - const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); - const getPrimaryTermsStore = {}; - const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) ); - forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); - POST_METADATA_KEYS[ `primary_${taxonomy}` ] = `_yoast_wpseo_primary_${taxonomy}`; - } ); - return getPrimaryTermsStore; -}; +const taxonomiesKeys = map( getPrimaryTerms(), ( value, key ) => { + return { [ key ]: `_yoast_wpseo_${key}` }; +} ); + +const METADATA_KEYS = { ...POST_METADATA_KEYS, ...taxonomiesKeys }; /** * Creates an updater. * @returns {function} The updater. @@ -45,12 +35,12 @@ const createUpdater = () => { return; } - const changedData = pickBy( data, ( value, key ) => value !== metadata[ POST_METADATA_KEYS[ key ] ] ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); if ( changedData ) { const newMetadata = {}; forEach( changedData, ( value, key ) => { - newMetadata[ POST_METADATA_KEYS[ key ] ] = value; + newMetadata[ METADATA_KEYS[ key ] ] = value; } ); editPost( { diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 9167506f14f..27c8227fb57 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -9,7 +9,7 @@ import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterIm import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; - +import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; /** * Prepare twitter title to be saved in hidden field. @@ -93,9 +93,7 @@ export const createUpdater = () => { const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); - console.log( { hiddenFieldsData } ); - console.log( { data } ); - console.log( { changedData } ); + if ( changedData ) { forEach( changedData, ( value, key ) => { document.getElementById( prefix + key ).value = prepareValue( key, value ); @@ -134,6 +132,7 @@ export const valuesToSync = { linkdex: getSeoScore, inclusive_language_score: getInclusiveLanguageScore, "estimated-reading-time-minutes": getEstimatedReadingTime, + ...getPrimaryTerms(), }; /** diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js new file mode 100644 index 00000000000..b5b6f526ac3 --- /dev/null +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -0,0 +1,27 @@ +import { get, pickBy, forEach, defaultTo } from "lodash"; +import { select } from "@wordpress/data"; +import { EDITOR_STORE } from "../../shared-admin/constants"; + +/** + * Retrieves primary terms from store methods. + * + * @returns {object} An object with taxonomies keys and their primary term id. + */ +const getPrimaryTerms = () => { + const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); + const getPrimaryTermsStore = {}; + const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) ); + forEach( primaryTerms, ( value, key ) => { + const taxonomy = key.replace( "primary_", "" ); + getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { + const termId = String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); + if ( termId === "0" || termId === "-1" ) { + return ""; + } + return termId; + }; + } ); + return getPrimaryTermsStore; +}; + +export default getPrimaryTerms; diff --git a/packages/js/src/initializers/primary-category.js b/packages/js/src/initializers/primary-category.js index be1dd7caab4..ab7b1680537 100644 --- a/packages/js/src/initializers/primary-category.js +++ b/packages/js/src/initializers/primary-category.js @@ -1,6 +1,6 @@ /* global wp, _, wpseoPrimaryCategoryL10n */ /* External dependencies */ -import { dispatch } from "@wordpress/data"; +import { dispatch, select } from "@wordpress/data"; import { Component } from "@wordpress/element"; import { get, @@ -43,10 +43,13 @@ export default function initPrimaryCategory( $ ) { * @returns {string} The value of the primary term. */ function getPrimaryTerm( taxonomyName ) { - var primaryTermInput; + const store = select( "yoast-seo/editor" ); + if ( store ) { + return store.getPrimaryTaxonomyId( taxonomyName ); + } - primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName ); - return primaryTermInput.val(); + const primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName ); + return primaryTermInput ? primaryTermInput.val() : ""; } /** @@ -79,7 +82,7 @@ export default function initPrimaryCategory( $ ) { const yoastEditor = dispatch( "yoast-seo/editor" ); if ( yoastEditor ) { const termIdInt = parseInt( termId, 10 ); - yoastEditor.setPrimaryTaxonomyId( taxonomyName, termIdInt ); + yoastEditor.setPrimaryTaxonomyId( taxonomyName, termId ); // If the taxonomy is category update the replacement variable. if ( taxonomyName === "category" ) { yoastEditor.updateReplacementVariable( diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js new file mode 100644 index 00000000000..265daa67ebc --- /dev/null +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -0,0 +1,74 @@ +import getPrimaryTerms from "../../../src/helpers/fields/primaryTaxonomiesFieldsStore"; +import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { select } from "@wordpress/data"; + +jest.mock( "@wordpress/data", () => ( { + select: jest.fn(), +} ) ); + +let windowSpy; + +beforeEach( + () => { + windowSpy = jest.spyOn( global, "window", "get" ); + } +); + +afterEach( + () => { + windowSpy.mockRestore(); + } +); + +const testCases = [ + { termId: 1, expected: "1" }, + { termId: -1, expected: "" }, + { termId: 0, expected: "" }, + { termId: null, expected: "" }, + { termId: undefined, expected: "" }, +]; + +describe.each( testCases )( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", ( { termId, expected } ) => { + it( `should returns ${expected ? expected : "empty string"} when the primary term id is ${termId}`, () => { + const wpseoScriptDataMetaData = { + // eslint-disable-next-line camelcase + primary_category: 1, + // eslint-disable-next-line camelcase + primary_post_tag: 2, + }; + + const getPrimaryTaxonomyId = jest.fn(); + getPrimaryTaxonomyId.mockReturnValue( termId ); + + select.mockImplementation( ( store ) => { + if ( store === EDITOR_STORE ) { + return { + getPrimaryTaxonomyId, + }; + } + } ); + + windowSpy.mockImplementation( + () => ( + { + wpseoScriptData: { + metabox: { + metadata: wpseoScriptDataMetaData, + }, + }, + } + ) + ); + + const actual = getPrimaryTerms(); + + expect( actual ).toHaveProperty( "primary_category" ); + expect( actual ).toHaveProperty( "primary_post_tag" ); + + const primaryCategory = actual.primary_category(); + const primaryPostTag = actual.primary_post_tag(); + + expect( primaryCategory ).toEqual( expected ); + expect( primaryPostTag ).toEqual( expected ); + } ); +} ); From 0239878e86f98dc8665289c70d5e37d38e053072 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 27 Mar 2024 13:33:48 +0100 Subject: [PATCH 172/344] schema initial state and cleanup --- inc/class-wpseo-meta.php | 4 +- packages/js/src/components/SchemaTab.js | 18 ++--- packages/js/src/containers/SchemaTab.js | 18 ----- packages/js/src/helpers/SchemaFields.js | 80 ------------------- packages/js/src/redux/actions/schemaTab.js | 30 ------- packages/js/src/redux/initial-state/index.js | 2 + .../js/src/redux/initial-state/schemaTab.js | 10 +++ packages/js/src/redux/reducers/schemaTab.js | 12 --- 8 files changed, 20 insertions(+), 154 deletions(-) delete mode 100644 packages/js/src/helpers/SchemaFields.js create mode 100644 packages/js/src/redux/initial-state/schemaTab.js diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index e1cc8182af2..0a37655dfba 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -418,7 +418,7 @@ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { return []; } - $field_defs['schema_page_type']['default'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); + $field_defs['schema_page_type']['default_value'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); $article_helper = new Article_Helper(); if ( $article_helper->is_article_post_type( $post_type ) ) { @@ -430,7 +430,7 @@ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { if ( ! array_key_exists( $default_schema_article_type, $allowed_article_types ) ) { $default_schema_article_type = WPSEO_Options::get_default( 'wpseo_titles', 'schema-article-type-' . $post_type ); } - $field_defs['schema_article_type']['default'] = $default_schema_article_type; + $field_defs['schema_article_type']['default_value'] = $default_schema_article_type; } else { unset( $field_defs['schema_article_type'] ); diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index 29d58236612..87a3de1fd4b 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -8,6 +8,7 @@ import styled from "styled-components"; import WooCommerceUpsell from "./WooCommerceUpsell"; import { get } from "lodash"; import { useSelect } from "@wordpress/data"; +import { EDITOR_STORE } from "../shared-admin/constants"; const NewsLandingPageLink = makeOutboundLink(); @@ -15,8 +16,6 @@ const SchemaContainer = styled.div` padding: 16px; `; -const STORE = "yoast-seo/editor"; - /** * The NewsAlert upsell. * @@ -69,8 +68,8 @@ NewsAlert.propTypes = { * @returns {Object[]} A copy of the schema type options. */ const getSchemaTypeOptions = ( schemaTypeOptions, defaultType, postTypeName ) => { - const isProduct = useSelect( ( select ) => select( STORE ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( STORE ).getIsWooSeoActive(), [] ); + const isProduct = useSelect( ( select ) => select( EDITOR_STORE ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( EDITOR_STORE ).getIsWooSeoActive(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const schemaOption = disablePageTypeSelect ? { name: __( "Item Page", "wordpress-seo" ), value: "ItemPage" } : schemaTypeOptions.find( option => option.value === defaultType ); return [ @@ -170,8 +169,8 @@ const Content = ( props ) => { const woocommerceUpsell = get( window, "wpseoScriptData.woocommerceUpsell", "" ); const [ focusedArticleType, setFocusedArticleType ] = useState( props.schemaArticleTypeSelected ); const woocommerceUpsellText = __( "Want your products stand out in search results with rich results like price, reviews and more?", "wordpress-seo" ); - const isProduct = useSelect( ( select ) => select( STORE ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( STORE ).getIsWooSeoActive(), [] ); + const isProduct = useSelect( ( select ) => select( EDITOR_STORE ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( EDITOR_STORE ).getIsWooSeoActive(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; @@ -205,7 +204,7 @@ const Content = ( props ) => { selected={ disablePageTypeSelect ? "ItemPage" : props.schemaPageTypeSelected } disabled={ disablePageTypeSelect } /> - { props.showArticleTypeInput && ' . "\n"; + $output .= '' . "\n"; } return $output; From d562bcd9c8d1200b5d6990bc80648d7115dcb502 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 12:21:04 +0200 Subject: [PATCH 181/344] Check also for hidden fields in elementor --- packages/js/src/helpers/fields/hasHiddenFields.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/hasHiddenFields.js b/packages/js/src/helpers/fields/hasHiddenFields.js index b409b0e8a28..439a59776e9 100644 --- a/packages/js/src/helpers/fields/hasHiddenFields.js +++ b/packages/js/src/helpers/fields/hasHiddenFields.js @@ -4,7 +4,7 @@ * @returns {boolean} True if the element has hidden fields. */ export const hasHiddenFields = () => { - const element = document.getElementById( "wpseo_meta" ); + const element = document.getElementById( "wpseo_meta" ) || document.getElementById( "yoast-form" ); const inside = element?.querySelector( ".inside" ); const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); if ( hiddenFields && hiddenFields.length ) { From a6aeac1a946a3a9474a40a10d7e2eca33c272542 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 12:21:42 +0200 Subject: [PATCH 182/344] check for hidden fields in default before check for elementor --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 223c1187796..1b0fd272be9 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -72,7 +72,7 @@ export const createUpdater = () => { return ( data ) => { // Get the values from hidden fields. const hiddenFieldsData = {}; - const yoastFormElement = document.getElementById( "yoast-form" ) || document.getElementById( "wpseo_meta" ); + const yoastFormElement = document.getElementById( "wpseo_meta" ) || document.getElementById( "yoast-form" ); if ( yoastFormElement ) { const hiddenFields = yoastFormElement?.querySelectorAll( "input[type=hidden]" ); From b8eec475fd3f11923621ab43c693d0392f66f676 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 12:22:20 +0200 Subject: [PATCH 183/344] Add auth call back to metadata --- inc/class-wpseo-meta.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index d281d548a0f..44c312964c6 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -327,6 +327,9 @@ public static function init() { [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], 'show_in_rest' => $field_def['type'] ? true : false, + 'auth_callback' => function() { + return current_user_can('edit_posts'); + }, 'type' => 'string', 'single' => true, 'default' => ( $field_def['default_value'] ?? '' ), From a8b8caecc06a886d9389ebfe3e723187e5aece3d Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 13:11:23 +0200 Subject: [PATCH 184/344] hidden fields would be synced automatically --- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- src/presenters/admin/meta-fields-presenter.php | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index c0a3dce0116..86f428c8959 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -149,7 +149,7 @@ private function get_field( $field_type, $field_name, $field_value, array $optio } break; case 'hidden': - $field .= ''; + $field .= ''; break; } diff --git a/src/presenters/admin/meta-fields-presenter.php b/src/presenters/admin/meta-fields-presenter.php index af4483e10ff..00653a9d021 100644 --- a/src/presenters/admin/meta-fields-presenter.php +++ b/src/presenters/admin/meta-fields-presenter.php @@ -49,12 +49,6 @@ public function present() { foreach ( $this->meta_fields as $key => $meta_field ) { $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); - $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); - - $default = ''; - if ( isset( $meta_field['default'] ) ) { - $default = \sprintf( ' data-default="%s"', \esc_attr( $meta_field['default'] ) ); - } $output .= '' . "\n"; } From e4031e8464a11124aef3ab910928cf7052e86d3d Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 14:52:23 +0200 Subject: [PATCH 185/344] check if we shouls show article type input --- inc/class-wpseo-meta.php | 22 +++++++++++++++++++ packages/js/src/components/SchemaTab.js | 6 ++--- .../js/src/redux/initial-state/schemaTab.js | 1 + packages/js/src/redux/selectors/schemaTab.js | 9 ++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 44c312964c6..2ce28c229ab 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -1116,4 +1116,26 @@ public static function filter_schema_article_types() { /** This filter is documented in inc/options/class-wpseo-option-titles.php */ self::$meta_fields['schema']['schema_article_type']['options'] = apply_filters( 'wpseo_schema_article_types', self::$meta_fields['schema']['schema_article_type']['options'] ); } + + /** + * Hide data in rest API for users who can't edit posts. + * + * @param WP_REST_Response $response The response object. + * @param WP_Post $post The post object. + * @param WP_REST_Request $request The request object. + * + * @return WP_REST_Response + */ + public function view_metadata_permission_check($response, $post, $request) { + if (!current_user_can('edit_posts')) { + $data = $response->get_data(); + foreach ( WPSEO_Meta::$meta_fields as $subset => $field_group ) { + foreach ( $field_group as $key => $field_def ) { + unset($data['meta'][WPSEO_Meta::$meta_prefix . $key]); + } + } + $response->set_data($data); + } + return $response; + } } diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index 87a3de1fd4b..287859effee 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -171,7 +171,7 @@ const Content = ( props ) => { const woocommerceUpsellText = __( "Want your products stand out in search results with rich results like price, reviews and more?", "wordpress-seo" ); const isProduct = useSelect( ( select ) => select( EDITOR_STORE ).getIsProduct(), [] ); const isWooSeoActive = useSelect( select => select( EDITOR_STORE ).getIsWooSeoActive(), [] ); - + const showArticleTypeInput = useSelect( select => select( EDITOR_STORE ).getShowArticleTypeInput(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const handleOptionChange = useCallback( @@ -204,7 +204,7 @@ const Content = ( props ) => { selected={ disablePageTypeSelect ? "ItemPage" : props.schemaPageTypeSelected } disabled={ disablePageTypeSelect } /> - { props.postTypeName !== "Pages" && ' . "\n"; } From dcd8fd5ecf7c2d7462e815a51b38628a87bd5908 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 16:44:29 +0200 Subject: [PATCH 189/344] php fix cs --- composer.json | 2 +- inc/class-wpseo-meta.php | 22 ---------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/composer.json b/composer.json index d2c1ef58a59..3de2e5f419b 100644 --- a/composer.json +++ b/composer.json @@ -91,7 +91,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2561", + "@putenv YOASTCS_THRESHOLD_ERRORS=2528", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 36e60fdeb3b..cd9462def11 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -1115,26 +1115,4 @@ public static function filter_schema_article_types() { /** This filter is documented in inc/options/class-wpseo-option-titles.php */ self::$meta_fields['schema']['schema_article_type']['options'] = apply_filters( 'wpseo_schema_article_types', self::$meta_fields['schema']['schema_article_type']['options'] ); } - - /** - * Hide data in rest API for users who can't edit posts. - * - * @param WP_REST_Response $response The response object. - * @param WP_Post $post The post object. - * @param WP_REST_Request $request The request object. - * - * @return WP_REST_Response - */ - public function view_metadata_permission_check( $response, $post, $request ) { - if ( ! current_user_can( 'edit_posts' ) ) { - $data = $response->get_data(); - foreach ( self::$meta_fields as $subset => $field_group ) { - foreach ( $field_group as $key => $field_def ) { - unset( $data['meta'][ self::$meta_prefix . $key ] ); - } - } - $response->set_data( $data ); - } - return $response; - } } From 4ecf1aa2bf069fc6705bde268ed9906ea1b4b3aa Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 16:50:05 +0200 Subject: [PATCH 190/344] fix tests for taxonomy fields presenter --- tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php index 21bd0255514..fa96e4db92c 100644 --- a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php +++ b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php @@ -186,7 +186,7 @@ public function test_display_fields_hidden() { ); $this->assertStringContainsString( - '', + '', $output ); } From 77288be7b742b6249c9820cd5390280336e908be Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:42:42 +0200 Subject: [PATCH 191/344] Update packages/js/src/elementor.js Co-authored-by: Leonidas Milosis --- packages/js/src/elementor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/elementor.js b/packages/js/src/elementor.js index 1b7a002b476..6fa6a8601a7 100644 --- a/packages/js/src/elementor.js +++ b/packages/js/src/elementor.js @@ -26,7 +26,7 @@ function initialize() { window.YoastSEO = window.YoastSEO || {}; window.YoastSEO.store = initEditorStore(); - // Initialize the hidden fields sync if there are hidden fiels. + // Initialize the hidden fields sync if there are hidden fields. hiddenFieldsSync(); // Initialize the editor data watcher. From edcb22d9faef449c36947471df6e65e9ab638dd0 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 17:51:14 +0200 Subject: [PATCH 192/344] remove default because we are not using it --- inc/class-wpseo-meta.php | 1 - 1 file changed, 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index cd9462def11..dd38de25d76 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -331,7 +331,6 @@ public static function init() { }, 'type' => 'string', 'single' => true, - 'default' => ( $field_def['default_value'] ?? '' ), ] ); From 728d7dfbbc2ca244e2df563f884f95827929b823 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 9 Apr 2024 17:52:12 +0200 Subject: [PATCH 193/344] change the export and import of create watcher --- packages/js/src/editor-modules.js | 2 +- packages/js/src/helpers/create-watcher.js | 4 ++-- packages/js/src/helpers/fields/blockEditorSync.js | 2 +- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- packages/js/tests/helpers/fields/hiddenFieldsSync.test.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/js/src/editor-modules.js b/packages/js/src/editor-modules.js index f2f3eded531..e1e3e81fc2a 100644 --- a/packages/js/src/editor-modules.js +++ b/packages/js/src/editor-modules.js @@ -24,7 +24,7 @@ import Results from "./containers/Results"; import SEMrushRelatedKeyphrases from "./containers/SEMrushRelatedKeyphrases"; import WincherSEOPerformance from "./containers/WincherSEOPerformance"; import * as ajaxHelper from "./helpers/ajaxHelper"; -import createWatcher from "./helpers/create-watcher"; +import { createWatcher } from "./helpers/create-watcher"; import createInterpolateElement from "./helpers/createInterpolateElement"; import * as i18n from "./helpers/i18n"; import isBlockEditor from "./helpers/isBlockEditor"; diff --git a/packages/js/src/helpers/create-watcher.js b/packages/js/src/helpers/create-watcher.js index 4eef8fa89b3..432bd7b8e20 100644 --- a/packages/js/src/helpers/create-watcher.js +++ b/packages/js/src/helpers/create-watcher.js @@ -20,7 +20,7 @@ export const createCollector = ( ...getters ) => () => getters.map( getData => g * * @returns {function} The watcher. */ -const createWatcher = ( getData, onChange ) => { +export const createWatcher = ( getData, onChange ) => { // Save the current data for comparison. let previous = getData(); @@ -57,4 +57,4 @@ export const createCollectorFromObject = ( getters ) => () => reduce( {} ); -export default createWatcher; + diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 2d030d030a0..2d8654d2924 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,6 +1,6 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, map } from "lodash"; -import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 1b0fd272be9..0ac883dc11a 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -2,7 +2,7 @@ /* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get } from "lodash"; -import createWatcher, { createCollectorFromObject } from "../../helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index aed41677b9f..b3398dce715 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,6 +1,6 @@ /* eslint-disable camelcase */ import { hiddenFieldsSync } from "../../../src/helpers/fields/hiddenFieldsSync"; -import createWatcher, { createCollectorFromObject } from "../../../src/helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "../../../src/helpers/create-watcher"; import { EDITOR_STORE, SYNC_TIME } from "../../../src/shared-admin/constants"; import { select, subscribe } from "@wordpress/data"; import { debounce } from "lodash"; From c71ffe75036a5d3f9b961244a72f4901dc542f7c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 09:09:25 +0200 Subject: [PATCH 194/344] fix js tests for hidden fields sync --- .../helpers/fields/hiddenFieldsSync.test.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index b3398dce715..b7bf37265ae 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -36,10 +36,19 @@ jest.mock( "@wordpress/data", () => ( { } ) ); jest.mock( "lodash", () => ( { - ...jest.requireActual( "lodash" ), - debounce: jest.fn( fn => fn ), + debounce: jest.fn(), + get: jest.fn( ()=> { + return { primary_category: "5" }; + } ), + pickBy: jest.fn( () => [] ), + forEach: jest.fn(), + map: jest.fn(), } ) ); +jest.mock( "../../../src/helpers/create-watcher", () => ( { + createWatcher: jest.fn(), + createCollectorFromObject: jest.fn(), +} ) ); describe( "hiddenFieldsSync", () => { it( "should subscribe to changes and sync the right values", () => { @@ -82,10 +91,10 @@ describe( "hiddenFieldsSync", () => { hiddenFieldsSync(); // Assertions - expect( subscribe ).toHaveBeenCalledWith( expect.any( Function ), EDITOR_STORE ); - expect( debounce ).toHaveBeenCalledWith( expect.any( Function ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ); - expect( select ).toHaveBeenCalledWith( EDITOR_STORE ); - expect( createWatcher ).toHaveBeenCalledWith( expect.any( Function ), expect.any( Function ) ); + // expect( subscribe ).toHaveBeenCalledWith( expect.any( Function ), EDITOR_STORE ); + // expect( debounce ).toHaveBeenCalledWith( expect.any( Function ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ); + // expect( select ).toHaveBeenCalledWith( EDITOR_STORE ); + // expect( createWatcher ).toHaveBeenCalledWith( expect.any( Function ), expect.any( Function ) ); expect( createCollectorFromObject ).toHaveBeenCalledWith( { focuskw: getFocusKeyphrase, "meta-robots-noindex": getNoIndex, From dd96a066b3edeaa9cbb3770449f3027b1eba32cb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 09:37:18 +0200 Subject: [PATCH 195/344] remove unused prop types checks --- packages/js/src/components/SchemaTab.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index 287859effee..ba1dbd31b9d 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -242,9 +242,6 @@ Content.propTypes = { schemaArticleTypeSelected: PropTypes.string, articleTypeOptions: schemaTypeOptionsPropType.isRequired, additionalHelpTextLink: PropTypes.string.isRequired, - helpTextLink: PropTypes.string.isRequired, - helpTextTitle: PropTypes.string.isRequired, - helpTextDescription: PropTypes.string.isRequired, postTypeName: PropTypes.string.isRequired, displayFooter: PropTypes.bool, defaultPageType: PropTypes.string.isRequired, From 2ee27748a802ac9a6bfa96028e0e2facfd8983af Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 09:53:26 +0200 Subject: [PATCH 196/344] fix create watcher import --- packages/js/tests/helpers/create-watcher.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/tests/helpers/create-watcher.test.js b/packages/js/tests/helpers/create-watcher.test.js index 0879dc18dcd..226233921e0 100644 --- a/packages/js/tests/helpers/create-watcher.test.js +++ b/packages/js/tests/helpers/create-watcher.test.js @@ -1,4 +1,4 @@ -import createWatcher, { createCollectorFromObject, createCollector } from "../../src/helpers/create-watcher"; +import { createWatcher, createCollectorFromObject, createCollector } from "../../src/helpers/create-watcher"; describe( "createCollectorFromObject", () => { From 4821f1b1bb6ef390c820d9fa49f8ac06836b6581 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 09:56:58 +0200 Subject: [PATCH 197/344] fix Jsdoc comment --- packages/js/src/helpers/fields/blockEditorSync.js | 2 +- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 2d8654d2924..880b9ea8ec3 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -51,7 +51,7 @@ const createUpdater = () => { }; /** - * Initializes the sync: from Yoast editor store to product metadata. + * Initializes the sync: from Yoast editor store to core editor store. * @returns {function} The un-subscriber. */ export const blockEditorSync = () => { diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 0ac883dc11a..3adedb43afd 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -103,7 +103,7 @@ export const createUpdater = () => { }; /** - * Initializes the sync: from Yoast editor store to product metadata. + * Initializes the sync: from Yoast editor store to the hidden fields. * @returns {function} The un-subscriber. */ export const hiddenFieldsSync = () => { From 9cb62a937bb8b626f947afbfe17e06c80578c1eb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 10:27:48 +0200 Subject: [PATCH 198/344] fix import of create watcher --- packages/js/src/insights/initializer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/insights/initializer.js b/packages/js/src/insights/initializer.js index 9c8b21169aa..f6215bb0b26 100644 --- a/packages/js/src/insights/initializer.js +++ b/packages/js/src/insights/initializer.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, get, noop } from "lodash"; import { Paper } from "yoastseo"; -import createWatcher, { createCollector } from "../helpers/create-watcher"; +import { createWatcher, createCollector } from "../helpers/create-watcher"; import { collectData } from "../initializers/analysis"; /** From 1d93ca4e349475ab6601474f20f106afe406a3d0 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 10:27:56 +0200 Subject: [PATCH 199/344] cleanup tests --- .../tests/helpers/fields/hiddenFieldsSync.test.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index b7bf37265ae..13a61697071 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,9 +1,8 @@ /* eslint-disable camelcase */ import { hiddenFieldsSync } from "../../../src/helpers/fields/hiddenFieldsSync"; -import { createWatcher, createCollectorFromObject } from "../../../src/helpers/create-watcher"; -import { EDITOR_STORE, SYNC_TIME } from "../../../src/shared-admin/constants"; -import { select, subscribe } from "@wordpress/data"; -import { debounce } from "lodash"; +import { createCollectorFromObject } from "../../../src/helpers/create-watcher"; +import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { select } from "@wordpress/data"; import { getFocusKeyphrase, getNoIndex, @@ -87,14 +86,9 @@ describe( "hiddenFieldsSync", () => { } } ); - // Call the hiddenFieldsSync function + // Call the hiddenFieldsSync function. hiddenFieldsSync(); - // Assertions - // expect( subscribe ).toHaveBeenCalledWith( expect.any( Function ), EDITOR_STORE ); - // expect( debounce ).toHaveBeenCalledWith( expect.any( Function ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ); - // expect( select ).toHaveBeenCalledWith( EDITOR_STORE ); - // expect( createWatcher ).toHaveBeenCalledWith( expect.any( Function ), expect.any( Function ) ); expect( createCollectorFromObject ).toHaveBeenCalledWith( { focuskw: getFocusKeyphrase, "meta-robots-noindex": getNoIndex, From 9cc70e1a7cc78cc836ae1d44caac76ec65d33198 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 10:46:31 +0200 Subject: [PATCH 200/344] restore social option fallback --- inc/class-wpseo-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index dd38de25d76..6bb5c511355 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -281,7 +281,7 @@ class WPSEO_Meta { */ public static function init() { foreach ( self::$social_networks as $option => $network ) { - if ( WPSEO_Options::get( $option, true ) === true ) { + if ( WPSEO_Options::get( $option, false ) === true ) { foreach ( self::$social_fields as $box => $type ) { self::$meta_fields['social'][ $network . '-' . $box ] = [ 'type' => $type, From 008daa3f5081aea3c6254c19359aac1fd6079aeb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 10:53:37 +0200 Subject: [PATCH 201/344] fix php type comment --- admin/formatter/class-post-metabox-formatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 54b70173343..8169a5d7dc0 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -57,7 +57,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array|array> + * @return array> */ public function get_values() { @@ -92,7 +92,7 @@ public function get_values() { /** * Filter: 'wpseo_post_edit_values' - Allows changing the values Yoast SEO uses inside the post editor. * - * @param array> $values The key-value map Yoast SEO uses inside the post editor. + * @param array> $values The key-value map Yoast SEO uses inside the post editor. * @param WP_Post $post The post opened in the editor. */ return apply_filters( 'wpseo_post_edit_values', $values, $this->post ); From e53fa386c6176610970cb0e59ac6843d0cac89bd Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 11:06:28 +0200 Subject: [PATCH 202/344] rename method --- admin/formatter/class-term-metabox-formatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index f05be917536..157b6505ec8 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -86,7 +86,7 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metadata' => $this->get_metadata(), + 'metadata' => $this->get_term_metadata(), ]; } @@ -98,7 +98,7 @@ public function get_values() { * * @return array */ - protected function get_metadata() { + protected function get_term_metadata() { $metadata = []; $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); From e919e2e150d5e20ca1a64ffed31ce32c69185e09 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 11:54:20 +0200 Subject: [PATCH 203/344] fix defensive coding --- packages/js/src/helpers/fields/advancedFieldsStore.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index c0518eed802..cf25a3a8286 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -24,11 +24,11 @@ export const getNoFollow = () => String( defaultTo( select( EDITOR_STORE ).getNo * @returns {string} Twitter image URL. */ export const getAdvanced = () => { - const advanced = select( EDITOR_STORE ).getAdvanced(); + const advanced = defaultTo( select( EDITOR_STORE ).getAdvanced(), "" ); if ( Array.isArray( advanced ) ) { return advanced.join( "," ); } - return defaultTo( advanced, "" ); + return advanced; }; /** From 11129a9bf7a77bcf5ff1bfd128e357e3d8e42dd1 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 15:05:46 +0200 Subject: [PATCH 204/344] check we have meta in current post --- packages/js/src/helpers/fields/blockEditorSync.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 880b9ea8ec3..66bf3280591 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -22,6 +22,7 @@ const METADATA_KEYS = { ...POST_METADATA_KEYS, ...taxonomiesKeys }; */ const createUpdater = () => { const { editPost } = dispatch( CORE_EDITOR_STORE ); + const { getCurrentPost } = select( CORE_EDITOR_STORE ); /** * Syncs the data to the WP entity record. @@ -29,12 +30,14 @@ const createUpdater = () => { * @returns {void} */ return ( data ) => { - const metadata = select( CORE_EDITOR_STORE ).getCurrentPost().meta; + const currentPost = getCurrentPost(); - if ( ! metadata || ! data ) { + if ( ! currentPost.hasOwnProperty( "meta" ) || ! data ) { return; } + const metadata = currentPost.meta; + const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); if ( changedData ) { From 24580dcfade556e2d5087066f704341c2ce8ed0e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 17:06:10 +0200 Subject: [PATCH 205/344] I will use createCollectorFromObject in the addons --- packages/js/src/editor-modules.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/js/src/editor-modules.js b/packages/js/src/editor-modules.js index e1e3e81fc2a..b3ae061568e 100644 --- a/packages/js/src/editor-modules.js +++ b/packages/js/src/editor-modules.js @@ -24,7 +24,7 @@ import Results from "./containers/Results"; import SEMrushRelatedKeyphrases from "./containers/SEMrushRelatedKeyphrases"; import WincherSEOPerformance from "./containers/WincherSEOPerformance"; import * as ajaxHelper from "./helpers/ajaxHelper"; -import { createWatcher } from "./helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "./helpers/create-watcher"; import createInterpolateElement from "./helpers/createInterpolateElement"; import * as i18n from "./helpers/i18n"; import isBlockEditor from "./helpers/isBlockEditor"; @@ -82,6 +82,7 @@ window.yoast.editorModules = { ajaxHelper, createInterpolateElement, createWatcher, + createCollectorFromObject, isBlockEditor, i18n, replacementVariableHelpers, From 809affbdcea05de171bdc0545641990be1dd5f8a Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 10 Apr 2024 17:06:23 +0200 Subject: [PATCH 206/344] refactor check for hidden fields --- packages/js/src/helpers/fields/hasHiddenFields.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/hasHiddenFields.js b/packages/js/src/helpers/fields/hasHiddenFields.js index 439a59776e9..32d90014c65 100644 --- a/packages/js/src/helpers/fields/hasHiddenFields.js +++ b/packages/js/src/helpers/fields/hasHiddenFields.js @@ -5,10 +5,16 @@ */ export const hasHiddenFields = () => { const element = document.getElementById( "wpseo_meta" ) || document.getElementById( "yoast-form" ); - const inside = element?.querySelector( ".inside" ); - const hiddenFields = inside?.querySelectorAll( "input[type=hidden]" ); + + if ( ! element ) { + return false; + } + + const hiddenFields = element.querySelectorAll( "input[type=hidden]" ); + if ( hiddenFields && hiddenFields.length ) { return true; } + return false; }; From 7c03aee9326fd57a85e66957516db4b7e295f35f Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Thu, 11 Apr 2024 10:46:33 +0200 Subject: [PATCH 207/344] add_extra_wpseo_meta_fields should be used in an initialiser --- inc/class-wpseo-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 6bb5c511355..7964d9f2384 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -296,7 +296,7 @@ public static function init() { /** * Allow add-on plugins to register their meta fields for management by this class. - * Calls to add_filter() must be made before plugins_loaded prio 14. + * Calls to add_filter() must be made before plugins_loaded prio 14, use in an initialzer class. */ $extra_fields = apply_filters( 'add_extra_wpseo_meta_fields', [] ); if ( is_array( $extra_fields ) ) { From 8e9128694bbc0ac92644cbbd078f9a3c9fa5cff1 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Thu, 11 Apr 2024 15:43:01 +0200 Subject: [PATCH 208/344] fix mapping of metadata keys --- .../js/src/helpers/fields/blockEditorSync.js | 76 +++++++++---------- .../js/src/helpers/fields/hiddenFieldsSync.js | 69 +++++++++-------- .../js/src/shared-admin/constants/sync.js | 56 ++++++++------ 3 files changed, 102 insertions(+), 99 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 66bf3280591..de2af43ed18 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, map } from "lodash"; +import { debounce, pickBy, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, POST_METADATA_KEYS } from "../../shared-admin/constants"; +import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -10,12 +10,6 @@ import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; - -const taxonomiesKeys = map( getPrimaryTerms(), ( value, key ) => { - return { [ key ]: `_yoast_wpseo_${key}` }; -} ); - -const METADATA_KEYS = { ...POST_METADATA_KEYS, ...taxonomiesKeys }; /** * Creates an updater. * @returns {function} The updater. @@ -38,21 +32,45 @@ const createUpdater = () => { const metadata = currentPost.meta; - const changedData = pickBy( data, ( value, key ) => value !== metadata[ METADATA_KEYS[ key ] ] ); + const changedData = pickBy( data, ( value, key ) => value !== metadata[ key ] ); if ( changedData ) { - const newMetadata = {}; - forEach( changedData, ( value, key ) => { - newMetadata[ METADATA_KEYS[ key ] ] = value; - } ); - editPost( { - meta: newMetadata, + meta: changedData, } ); } }; }; +const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => POST_META_KEY_PREFIX + key ); + +const getters = mapKeys( { + focusKeyphrase: getFocusKeyphrase, + robotsNoIndex: getNoIndex, + robotsNoFollow: getNoFollow, + robotsAdvanced: getAdvanced, + facebookTitle: getFacebookTitle, + facebookDescription: getFacebookDescription, + facebookImageUrl: getFacebookImageUrl, + facebookImageId: getFacebookImageId, + twitterTitle: getTwitterTitle, + twitterDescription: getTwitterDescription, + twitterImageUrl: getTwitterImageUrl, + twitterImageId: getTwitterImageId, + schemaPageType: getPageType, + schemaArticleType: getArticleType, + isCornerstone: isCornerstoneContent, + readabilityScore: getReadabilityScore, + seoScore: getSeoScore, + inclusiveLanguageScore: getInclusiveLanguageScore, + breadcrumbsTitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordProofTimestamp: getWordProofTimestamp, + seoTitle: getSeoTitle, + seoDescription: getSeoDescription, + readingTime: getEstimatedReadingTime, +}, ( value, key ) => POST_META_KEY_PREFIX + META_KEYS[ key ] ); + /** * Initializes the sync: from Yoast editor store to core editor store. * @returns {function} The un-subscriber. @@ -60,32 +78,8 @@ const createUpdater = () => { export const blockEditorSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { - focusKeyphrase: getFocusKeyphrase, - noIndex: getNoIndex, - noFollow: getNoFollow, - facebookTitle: getFacebookTitle, - facebookDescription: getFacebookDescription, - facebookImageUrl: getFacebookImageUrl, - facebookImageId: getFacebookImageId, - twitterTitle: getTwitterTitle, - twitterDescription: getTwitterDescription, - twitterImageUrl: getTwitterImageUrl, - twitterImageId: getTwitterImageId, - pageType: getPageType, - articleType: getArticleType, - isCornerstone: isCornerstoneContent, - readabilityScore: getReadabilityScore, - seoScore: getSeoScore, - inclusiveLanguageScore: getInclusiveLanguageScore, - advanced: getAdvanced, - breadcrumbsTitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordProofTimestamp: getWordProofTimestamp, - seoTitle: getSeoTitle, - seoDescription: getSeoDescription, - readingTime: getEstimatedReadingTime, - ...getPrimaryTerms(), - + ...getters, + ...primaryTaxonomiesGetters, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 3adedb43afd..2deadf757c5 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,9 +1,8 @@ /* eslint-disable complexity */ -/* eslint-disable camelcase */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get } from "lodash"; +import { debounce, forEach, pickBy, get, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { EDITOR_STORE, SYNC_TIME } from "../../shared-admin/constants"; +import { EDITOR_STORE, SYNC_TIME, META_KEYS, POST_FORM_IDS_PREFIX, TERM_FORM_IDS_PREFIX } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -89,19 +88,46 @@ export const createUpdater = () => { return; } - const isPost = get( window, "wpseoScriptData.isPost", false ); - const prefix = isPost ? "yoast_wpseo_" : "hidden_wpseo_"; - - const changedData = pickBy( data, ( value, key ) => ( prefix + key ) in hiddenFieldsData && value !== hiddenFieldsData[ prefix + key ] ); + const changedData = pickBy( data, ( value, key ) => ( key ) in hiddenFieldsData && value !== hiddenFieldsData[ key ] ); if ( changedData ) { forEach( changedData, ( value, key ) => { - document.getElementById( prefix + key ).value = prepareValue( key, value ); + document.getElementById( key ).value = prepareValue( key, value ); } ); } }; }; +const isPost = get( window, "wpseoScriptData.isPost", false ); +const prefix = isPost ? POST_FORM_IDS_PREFIX : TERM_FORM_IDS_PREFIX; + +const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => prefix + key ); + +const getters = mapKeys( { + focusKeyphrase: getFocusKeyphrase, + robotsNoIndex: getNoIndex, + robotsNoFollow: getNoFollow, + robotsAdvanced: getAdvanced, + facebookTitle: getFacebookTitle, + facebookDescription: getFacebookDescription, + facebookImageUrl: getFacebookImageUrl, + facebookImageId: getFacebookImageId, + twitterTitle: getTwitterTitle, + twitterDescription: getTwitterDescription, + twitterImageUrl: getTwitterImageUrl, + twitterImageId: getTwitterImageId, + schemaPageType: getPageType, + schemaArticleType: getArticleType, + isCornerstone: isCornerstoneContent, + readabilityScore: getReadabilityScore, + seoScore: getSeoScore, + inclusiveLanguageScore: getInclusiveLanguageScore, + breadcrumbsTitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordProofTimestamp: getWordProofTimestamp, + readingTime: getEstimatedReadingTime, +}, ( value, key ) => prefix + META_KEYS[ key ] ); + /** * Initializes the sync: from Yoast editor store to the hidden fields. * @returns {function} The un-subscriber. @@ -109,31 +135,8 @@ export const createUpdater = () => { export const hiddenFieldsSync = () => { return subscribe( debounce( createWatcher( createCollectorFromObject( { - focuskw: getFocusKeyphrase, - "meta-robots-noindex": getNoIndex, - // Same as meta-robots-noindex for term metabox. - noindex: getNoIndex, - "meta-robots-nofollow": getNoFollow, - "meta-robots-adv": getAdvanced, - bctitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordproof_timestamp: getWordProofTimestamp, - "opengraph-title": getFacebookTitle, - "opengraph-description": getFacebookDescription, - "opengraph-image": getFacebookImageUrl, - "opengraph-image-id": getFacebookImageId, - "twitter-title": getTwitterTitle, - "twitter-description": getTwitterDescription, - "twitter-image": getTwitterImageUrl, - "twitter-image-id": getTwitterImageId, - schema_page_type: getPageType, - schema_article_type: getArticleType, - is_cornerstone: isCornerstoneContent, - content_score: getReadabilityScore, - linkdex: getSeoScore, - inclusive_language_score: getInclusiveLanguageScore, - "estimated-reading-time-minutes": getEstimatedReadingTime, - ...getPrimaryTerms(), + ...getters, + ...primaryTaxonomiesGetters, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); diff --git a/packages/js/src/shared-admin/constants/sync.js b/packages/js/src/shared-admin/constants/sync.js index ebf2697bc60..0b02604171b 100644 --- a/packages/js/src/shared-admin/constants/sync.js +++ b/packages/js/src/shared-admin/constants/sync.js @@ -1,30 +1,36 @@ -export const POST_METADATA_KEYS = { - focusKeyphrase: "_yoast_wpseo_focuskw", - noIndex: "_yoast_wpseo_meta-robots-noindex", - noFollow: "_yoast_wpseo_meta-robots-nofollow", - facebookTitle: "_yoast_wpseo_opengraph-title", - facebookDescription: "_yoast_wpseo_opengraph-description", - facebookImageUrl: "_yoast_wpseo_opengraph-image", - facebookImageId: "_yoast_wpseo_opengraph-image-id", - twitterTitle: "_yoast_wpseo_twitter-title", - twitterDescription: "_yoast_wpseo_twitter-description", - twitterImageUrl: "_yoast_wpseo_twitter-image", - twitterImageId: "_yoast_wpseo_twitter-image-id", - pageType: "_yoast_wpseo_schema_page_type", - articleType: "_yoast_wpseo_schema_article_type", - isCornerstone: "_yoast_wpseo_is_cornerstone", - readabilityScore: "_yoast_wpseo_content_score", - seoScore: "_yoast_wpseo_linkdex", - inclusiveLanguageScore: "_yoast_wpseo_inclusive_language_score", - advanced: "_yoast_wpseo_meta-robots-adv", - breadcrumbsTitle: "_yoast_wpseo_bctitle", - canonical: "_yoast_wpseo_canonical", - wordProofTimestamp: "_yoast_wpseo_wordproof_timestamp", - seoTitle: "_yoast_wpseo_title", - seoDescription: "_yoast_wpseo_metadesc", - readingTime: "_yoast_wpseo_estimated-reading-time-minutes", +export const META_KEYS = { + focusKeyphrase: "focuskw", + robotsNoIndex: "meta-robots-noindex", + robotsNoFollow: "meta-robots-nofollow", + robotsAdvanced: "meta-robots-adv", + facebookTitle: "opengraph-title", + facebookDescription: "opengraph-description", + facebookImageUrl: "opengraph-image", + facebookImageId: "opengraph-image-id", + twitterTitle: "twitter-title", + twitterDescription: "twitter-description", + twitterImageUrl: "twitter-image", + twitterImageId: "twitter-image-id", + schemaPageType: "schema_page_type", + schemaArticleType: "schema_article_type", + isCornerstone: "is_cornerstone", + readabilityScore: "content_score", + seoScore: "linkdex", + inclusiveLanguageScore: "inclusive_language_score", + breadcrumbsTitle: "bctitle", + canonical: "canonical", + wordProofTimestamp: "wordproof_timestamp", + seoTitle: "title", + seoDescription: "metadesc", + readingTime: "estimated-reading-time-minutes", }; +export const POST_META_KEY_PREFIX = "_yoast_wpseo_"; + +export const POST_FORM_IDS_PREFIX = "yoast_wpseo_"; + +export const TERM_FORM_IDS_PREFIX = "yoast_wpseo_"; + export const SYNC_TIME = { wait: 500, max: 1500, From 8eaa0dec4eccb4746a32c7c5cc88736c0ad66374 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 12 Apr 2024 13:38:31 +0200 Subject: [PATCH 209/344] hide metadata from users that don't have edit post capabilities --- inc/class-wpseo-meta.php | 49 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 7964d9f2384..f83881f3b13 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -325,7 +325,7 @@ public static function init() { self::$meta_prefix . $key, [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], - 'show_in_rest' => ( $field_def['type'] ) ? true : false, + 'show_in_rest' => self::get_show_in_rest_args( $field_def['type'] ), 'auth_callback' => static function () { return current_user_can( 'edit_posts' ); }, @@ -358,6 +358,53 @@ public static function init() { add_filter( 'add_post_metadata', [ self::class, 'dont_save_meta_if_default' ], 10, 4 ); } + /** + * Get show_in_rest args for a meta field. + * + * @param string|null $type The type of the field. + * @return bool|array|callable|int> $args The show_in_rest args. + */ + public static function get_show_in_rest_args( $type ) { + if ( ! $type ) { + return false; + } + return [ + 'schema' => [ + 'type' => 'string', + ], + 'prepare_callback' => [ self::class, 'prepare_value_for_rest_request' ], + 'user_id' => get_current_user_id(), + ]; + } + + /** + * Prepare value for rest api. Replaces the default `prepare_value` mathod in core file wp-includes/rest-api/fields/class-wp-rest-meta-fields.php. + * + * @param string $value The value. + * @param WP_REST_Request $request The request object. + * @param array> $args The show_in_rest args. + * + * @return string The metadata value. + */ + public static function prepare_value_for_rest_request( $value, $request, $args ) { + if ( ! $args['user_id'] ) { + return null; + } + + $current_user = get_userdata( $args['user_id'] ); + + if ( ! $current_user || ! $current_user->allcaps['edit_posts'] ) { + return null; + } + $schema = $args['schema']; + + if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) { + return null; + } + + return rest_sanitize_value_from_schema( $value, $schema ); + } + /** * Retrieve the meta box form field definitions for the given tab and post type. * From 4dab37ae636934beda6264311aea0f056ca5096c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 12 Apr 2024 13:39:03 +0200 Subject: [PATCH 210/344] php fix-cs --- composer.json | 2 +- inc/class-wpseo-meta.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index e4a9da9060e..24d884b5939 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2528", + "@putenv YOASTCS_THRESHOLD_ERRORS=2525", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index f83881f3b13..27e0f490e5b 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -1071,7 +1071,7 @@ public static function array_merge_recursive_distinct() { * @param string $keyword The keyword to be counted. * @param int $post_id The id of the post to which the keyword belongs. * - * @return array + * @return array */ public static function keyword_usage( $keyword, $post_id ) { @@ -1121,9 +1121,9 @@ public static function keyword_usage( $keyword, $post_id ) { /** * Returns the post types for the given post ids. * - * @param array $post_ids The post ids to get the post types for. + * @param array $post_ids The post ids to get the post types for. * - * @return array The post types. + * @return array The post types. */ public static function post_types_for_ids( $post_ids ) { From 704dbad46c953fdb261403de44913df1d54237b2 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 12 Apr 2024 13:49:39 +0200 Subject: [PATCH 211/344] decreased cs threshold --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 24d884b5939..f30491d780d 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2525", + "@putenv YOASTCS_THRESHOLD_ERRORS=2523", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From cefc54f46d3cf42b7a3a363ef6f5b4069e9ce2ac Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 12 Apr 2024 15:15:28 +0200 Subject: [PATCH 212/344] fix prefix for terms --- packages/js/src/shared-admin/constants/sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/shared-admin/constants/sync.js b/packages/js/src/shared-admin/constants/sync.js index 0b02604171b..5d6cb4921b0 100644 --- a/packages/js/src/shared-admin/constants/sync.js +++ b/packages/js/src/shared-admin/constants/sync.js @@ -29,7 +29,7 @@ export const POST_META_KEY_PREFIX = "_yoast_wpseo_"; export const POST_FORM_IDS_PREFIX = "yoast_wpseo_"; -export const TERM_FORM_IDS_PREFIX = "yoast_wpseo_"; +export const TERM_FORM_IDS_PREFIX = "hidden_wpseo_"; export const SYNC_TIME = { wait: 500, From 9e55cf9873212f538eae49c7d163645b7664604b Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 12 Apr 2024 16:00:16 +0200 Subject: [PATCH 213/344] fix js tests --- .../helpers/fields/hiddenFieldsSync.test.js | 110 +++--------------- 1 file changed, 14 insertions(+), 96 deletions(-) diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index 13a61697071..21d0f10fc32 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,33 +1,7 @@ -/* eslint-disable camelcase */ import { hiddenFieldsSync } from "../../../src/helpers/fields/hiddenFieldsSync"; -import { createCollectorFromObject } from "../../../src/helpers/create-watcher"; -import { EDITOR_STORE } from "../../../src/shared-admin/constants"; -import { select } from "@wordpress/data"; -import { - getFocusKeyphrase, - getNoIndex, - getNoFollow, - getAdvanced, - getBreadcrumbsTitle, - getCanonical, - getWordProofTimestamp, - getFacebookTitle, - getFacebookDescription, - getFacebookImageUrl, - getFacebookImageId, - getTwitterTitle, - getTwitterDescription, - getTwitterImageUrl, - getTwitterImageId, - getPageType, - getArticleType, - isCornerstoneContent, - getReadabilityScore, - getSeoScore, - getInclusiveLanguageScore, - getEstimatedReadingTime, -} from "../../../src/helpers/fields"; - +import { createCollectorFromObject, createWatcher } from "../../../src/helpers/create-watcher"; +import { mapKeys, debounce } from "lodash"; +import { subscribe } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { select: jest.fn(), @@ -36,12 +10,12 @@ jest.mock( "@wordpress/data", () => ( { jest.mock( "lodash", () => ( { debounce: jest.fn(), - get: jest.fn( ()=> { - return { primary_category: "5" }; - } ), - pickBy: jest.fn( () => [] ), + get: jest.fn( ()=> true ), + pickBy: jest.fn( () => {} ), forEach: jest.fn(), - map: jest.fn(), + mapKeys: jest.fn( ()=>{ + return { test: "test" }; + } ), } ) ); jest.mock( "../../../src/helpers/create-watcher", () => ( { @@ -50,69 +24,13 @@ jest.mock( "../../../src/helpers/create-watcher", () => ( { } ) ); describe( "hiddenFieldsSync", () => { - it( "should subscribe to changes and sync the right values", () => { - select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { - return { - getFocusKeyphrase: jest.fn(), - getNoIndex: jest.fn(), - getNoFollow: jest.fn(), - getAdvanced: jest.fn(), - getBreadcrumbsTitle: jest.fn(), - getCanonical: jest.fn(), - getWordProofTimestamp: jest.fn(), - getFacebookTitle: jest.fn(), - getFacebookDescription: jest.fn(), - getFacebookImageUrl: jest.fn(), - getFacebookImageId: jest.fn(), - getTwitterTitle: jest.fn(), - getTwitterDescription: jest.fn(), - getTwitterImageUrl: jest.fn(), - getTwitterImageId: jest.fn(), - getPageType: jest.fn(), - getArticleType: jest.fn(), - isCornerstoneContent: jest.fn(), - getReadabilityResults: jest.fn( () => { - return { overallScore: 5 }; - } ), - getSeoResults: jest.fn( () => { - return { overallScore: 5 }; - } ), - getInclusiveLanguageResults: jest.fn( () => { - return { overallScore: 5 }; - } ), - getEstimatedReadingTime: jest.fn(), - }; - } - } ); - - // Call the hiddenFieldsSync function. + it( "should subscribe to changes, debounce, create watcher and createCollectorFromObject", () => { hiddenFieldsSync(); - expect( createCollectorFromObject ).toHaveBeenCalledWith( { - focuskw: getFocusKeyphrase, - "meta-robots-noindex": getNoIndex, - noindex: getNoIndex, - "meta-robots-nofollow": getNoFollow, - "meta-robots-adv": getAdvanced, - bctitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordproof_timestamp: getWordProofTimestamp, - "opengraph-title": getFacebookTitle, - "opengraph-description": getFacebookDescription, - "opengraph-image": getFacebookImageUrl, - "opengraph-image-id": getFacebookImageId, - "twitter-title": getTwitterTitle, - "twitter-description": getTwitterDescription, - "twitter-image": getTwitterImageUrl, - "twitter-image-id": getTwitterImageId, - schema_page_type: getPageType, - schema_article_type: getArticleType, - is_cornerstone: isCornerstoneContent, - content_score: getReadabilityScore, - linkdex: getSeoScore, - inclusive_language_score: getInclusiveLanguageScore, - "estimated-reading-time-minutes": getEstimatedReadingTime, - } ); + expect( subscribe ).toHaveBeenCalled(); + expect( debounce ).toHaveBeenCalled(); + expect( createWatcher ).toHaveBeenCalled(); + expect( mapKeys ).toHaveBeenCalledTimes( 2 ); + expect( createCollectorFromObject ).toHaveBeenCalledWith( { test: "test" } ); } ); } ); From 76f82926cd31999cc5b240d367d2b88ad2b5b254 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 15 Apr 2024 09:52:07 +0200 Subject: [PATCH 214/344] replace prepare callback with schema context --- inc/class-wpseo-meta.php | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 27e0f490e5b..dfb202f10e2 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -362,49 +362,20 @@ public static function init() { * Get show_in_rest args for a meta field. * * @param string|null $type The type of the field. - * @return bool|array|callable|int> $args The show_in_rest args. + * @return bool|array|string> $args The show_in_rest args. */ public static function get_show_in_rest_args( $type ) { if ( ! $type ) { return false; } return [ - 'schema' => [ - 'type' => 'string', + 'schema' => [ + 'type' => 'string', + 'context' => [ 'edit' ], ], - 'prepare_callback' => [ self::class, 'prepare_value_for_rest_request' ], - 'user_id' => get_current_user_id(), ]; } - /** - * Prepare value for rest api. Replaces the default `prepare_value` mathod in core file wp-includes/rest-api/fields/class-wp-rest-meta-fields.php. - * - * @param string $value The value. - * @param WP_REST_Request $request The request object. - * @param array> $args The show_in_rest args. - * - * @return string The metadata value. - */ - public static function prepare_value_for_rest_request( $value, $request, $args ) { - if ( ! $args['user_id'] ) { - return null; - } - - $current_user = get_userdata( $args['user_id'] ); - - if ( ! $current_user || ! $current_user->allcaps['edit_posts'] ) { - return null; - } - $schema = $args['schema']; - - if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) { - return null; - } - - return rest_sanitize_value_from_schema( $value, $schema ); - } - /** * Retrieve the meta box form field definitions for the given tab and post type. * From 26cde705e2613ae1240f9f5539917490c12ce6ea Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 15 Apr 2024 14:59:53 +0200 Subject: [PATCH 215/344] schema defaults are not metadata. Moved them to a separate window object. --- admin/formatter/class-post-metabox-formatter.php | 15 ++++++--------- packages/js/src/redux/initial-state/schemaTab.js | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 8169a5d7dc0..77c1709e5f9 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -84,6 +84,10 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), 'metadata' => $this->get_post_meta_data(), + 'schemaDefaults' => [ + 'defaultPageType' => WPSEO_Options::get( 'schema-page-type-' . $this->post->post_type ), + 'defaultArticleType' => WPSEO_Options::get( 'schema-article-type-' . $this->post->post_type ), + ], ]; $values = ( $values_to_set + $values ); @@ -342,15 +346,8 @@ protected function get_post_meta_data() { } foreach ( $fields as $key => $meta_field ) { - $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); - - $default = ''; - if ( isset( $meta_field['default_value'] ) ) { - $default = $meta_field['default_value']; - $meta_data[ $key . '_default' ] = $default; - } - - $meta_data[ $key ] = esc_attr( $meta_value ) ? esc_attr( $meta_value ) : $default; + $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); + $meta_data[ $key ] = $meta_value; } $taxonomies = get_object_taxonomies( $post_type, 'objects' ); diff --git a/packages/js/src/redux/initial-state/schemaTab.js b/packages/js/src/redux/initial-state/schemaTab.js index f9dc24ae1f1..b8a82cc2183 100644 --- a/packages/js/src/redux/initial-state/schemaTab.js +++ b/packages/js/src/redux/initial-state/schemaTab.js @@ -2,9 +2,9 @@ import { get } from "lodash"; const schemaTab = { pageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type", "" ), - defaultPageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type_default", "" ), + defaultPageType: get( window, "wpseoScriptData.metabox.schemaDefaults.defaultPageType", "" ), articleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", "" ), - defaultArticleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type_default", "" ), + defaultArticleType: get( window, "wpseoScriptData.metabox.schemaDefaults.defaultArticleType", "" ), showArticleTypeInput: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", false ) !== false, }; From 9b0e57c6fccd382fb5386476b0c41e2eb83c7109 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 15 Apr 2024 15:29:32 +0200 Subject: [PATCH 216/344] remove variable --- admin/formatter/class-post-metabox-formatter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 77c1709e5f9..c0931a336b1 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -346,8 +346,7 @@ protected function get_post_meta_data() { } foreach ( $fields as $key => $meta_field ) { - $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); - $meta_data[ $key ] = $meta_value; + $meta_data[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); } $taxonomies = get_object_taxonomies( $post_type, 'objects' ); From 935a988c14018b2475b1a9dd352ba4ee67f3d866 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 15 Apr 2024 16:16:19 +0200 Subject: [PATCH 217/344] moving schema defaults to post metabox formatter --- .../class-post-metabox-formatter.php | 37 +++++++++++++++++-- inc/class-wpseo-meta.php | 17 +-------- .../js/src/redux/initial-state/schemaTab.js | 4 +- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index c0931a336b1..e80e63d1b2d 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -5,6 +5,8 @@ * @package WPSEO\Admin\Formatter */ +use Yoast\WP\SEO\Config\Schema_Types; +use Yoast\WP\SEO\Helpers\Schema\Article_Helper; /** * This class provides data for the post metabox by return its values for localization. */ @@ -84,10 +86,7 @@ public function get_values() { 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), 'metadata' => $this->get_post_meta_data(), - 'schemaDefaults' => [ - 'defaultPageType' => WPSEO_Options::get( 'schema-page-type-' . $this->post->post_type ), - 'defaultArticleType' => WPSEO_Options::get( 'schema-article-type-' . $this->post->post_type ), - ], + 'schemaDefaults' => $this->get_schema_defaults( $this->post->post_type ), ]; $values = ( $values_to_set + $values ); @@ -360,4 +359,34 @@ protected function get_post_meta_data() { return $meta_data; } + + /** + * Get schema defaults. + * + * @param string $post_type The post type. + * @return array The schema defaults. + */ + public function get_schema_defaults( $post_type ) { + if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) && WPSEO_Options::get( 'disableadvanced_meta' ) ) { + return []; + } + $schema_defaults = []; + + $schema_defaults['pageType'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); + + $article_helper = new Article_Helper(); + if ( $article_helper->is_article_post_type( $post_type ) ) { + $default_schema_article_type = WPSEO_Options::get( 'schema-article-type-' . $post_type ); + + /** This filter is documented in inc/options/class-wpseo-option-titles.php */ + $allowed_article_types = apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); + + if ( ! array_key_exists( $default_schema_article_type, $allowed_article_types ) ) { + $default_schema_article_type = WPSEO_Options::get_default( 'wpseo_titles', 'schema-article-type-' . $post_type ); + } + + $schema_defaults['articleType'] = $default_schema_article_type; + } + return $schema_defaults; + } } diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index dfb202f10e2..75d3eabc3d0 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -437,25 +437,10 @@ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) && WPSEO_Options::get( 'disableadvanced_meta' ) ) { return []; } - - $field_defs['schema_page_type']['default_value'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); - $article_helper = new Article_Helper(); - if ( $article_helper->is_article_post_type( $post_type ) ) { - $default_schema_article_type = WPSEO_Options::get( 'schema-article-type-' . $post_type ); - - /** This filter is documented in inc/options/class-wpseo-option-titles.php */ - $allowed_article_types = apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); - - if ( ! array_key_exists( $default_schema_article_type, $allowed_article_types ) ) { - $default_schema_article_type = WPSEO_Options::get_default( 'wpseo_titles', 'schema-article-type-' . $post_type ); - } - $field_defs['schema_article_type']['default_value'] = $default_schema_article_type; - } - else { + if ( ! $article_helper->is_article_post_type( $post_type ) ) { unset( $field_defs['schema_article_type'] ); } - break; } diff --git a/packages/js/src/redux/initial-state/schemaTab.js b/packages/js/src/redux/initial-state/schemaTab.js index b8a82cc2183..7223f614131 100644 --- a/packages/js/src/redux/initial-state/schemaTab.js +++ b/packages/js/src/redux/initial-state/schemaTab.js @@ -2,9 +2,9 @@ import { get } from "lodash"; const schemaTab = { pageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type", "" ), - defaultPageType: get( window, "wpseoScriptData.metabox.schemaDefaults.defaultPageType", "" ), + defaultPageType: get( window, "wpseoScriptData.metabox.schemaDefaults.pageType", "" ), articleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", "" ), - defaultArticleType: get( window, "wpseoScriptData.metabox.schemaDefaults.defaultArticleType", "" ), + defaultArticleType: get( window, "wpseoScriptData.metabox.schemaDefaults.articleType", "" ), showArticleTypeInput: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", false ) !== false, }; From 689ad1ca18b0cc6727d9e6392266b159d77d8816 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 17 Apr 2024 10:46:35 +0200 Subject: [PATCH 218/344] rename constants --- packages/js/src/analysis/PostDataCollector.js | 6 +++--- packages/js/src/components/SchemaTab.js | 12 ++++++------ .../src/helpers/fields/advancedFieldsStore.js | 14 +++++++------- .../src/helpers/fields/analysisFieldsStore.js | 14 +++++++------- .../js/src/helpers/fields/blockEditorSync.js | 8 ++++---- .../src/helpers/fields/facebookFieldsStore.js | 10 +++++----- .../js/src/helpers/fields/hiddenFieldsSync.js | 10 +++++----- .../fields/primaryTaxonomiesFieldsStore.js | 4 ++-- .../js/src/helpers/fields/schemaFieldsStore.js | 6 +++--- .../helpers/fields/snippetEditorFieldsStore.js | 6 +++--- .../src/helpers/fields/twitterFieldsStore.js | 10 +++++----- .../js/src/shared-admin/constants/index.js | 6 +++++- .../js/src/shared-admin/constants/stores.js | 3 --- packages/js/src/shared-admin/constants/sync.js | 6 +++--- .../helpers/fields/analysisFieldsStore.test.js | 12 ++++++------ .../helpers/fields/getPrimaryTerms.test.js | 4 ++-- .../fields/getValuesFromStoreToSync.test.js | 18 +++++++++--------- 17 files changed, 75 insertions(+), 74 deletions(-) delete mode 100644 packages/js/src/shared-admin/constants/stores.js diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index f2732349cf1..5fa844f8a11 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -17,7 +17,7 @@ import getIndicatorForScore from "./getIndicatorForScore"; import isKeywordAnalysisActive from "./isKeywordAnalysisActive"; import isContentAnalysisActive from "./isContentAnalysisActive"; -import { EDITOR_STORE } from "../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../shared-admin/constants"; const { tmceId } = tmceHelper; const $ = jQuery; @@ -83,7 +83,7 @@ PostDataCollector.prototype.getData = function() { * @returns {string} The keyword. */ PostDataCollector.prototype.getKeyword = function() { - const keyword = select( EDITOR_STORE ).getFocusKeyphrase(); + const keyword = select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(); return keyword; }; @@ -108,7 +108,7 @@ PostDataCollector.prototype.getMetaDescForAnalysis = function( state ) { * @returns {string} The meta description. */ PostDataCollector.prototype.getMeta = function() { - return select( EDITOR_STORE ).getDescription(); + return select( STORE_NAME_EDITOR.free ).getDescription(); }; /** diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index ba1dbd31b9d..de0d9915c31 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -8,7 +8,7 @@ import styled from "styled-components"; import WooCommerceUpsell from "./WooCommerceUpsell"; import { get } from "lodash"; import { useSelect } from "@wordpress/data"; -import { EDITOR_STORE } from "../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../shared-admin/constants"; const NewsLandingPageLink = makeOutboundLink(); @@ -68,8 +68,8 @@ NewsAlert.propTypes = { * @returns {Object[]} A copy of the schema type options. */ const getSchemaTypeOptions = ( schemaTypeOptions, defaultType, postTypeName ) => { - const isProduct = useSelect( ( select ) => select( EDITOR_STORE ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( EDITOR_STORE ).getIsWooSeoActive(), [] ); + const isProduct = useSelect( ( select ) => select( STORE_NAME_EDITOR.free ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( STORE_NAME_EDITOR.free ).getIsWooSeoActive(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const schemaOption = disablePageTypeSelect ? { name: __( "Item Page", "wordpress-seo" ), value: "ItemPage" } : schemaTypeOptions.find( option => option.value === defaultType ); return [ @@ -169,9 +169,9 @@ const Content = ( props ) => { const woocommerceUpsell = get( window, "wpseoScriptData.woocommerceUpsell", "" ); const [ focusedArticleType, setFocusedArticleType ] = useState( props.schemaArticleTypeSelected ); const woocommerceUpsellText = __( "Want your products stand out in search results with rich results like price, reviews and more?", "wordpress-seo" ); - const isProduct = useSelect( ( select ) => select( EDITOR_STORE ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( EDITOR_STORE ).getIsWooSeoActive(), [] ); - const showArticleTypeInput = useSelect( select => select( EDITOR_STORE ).getShowArticleTypeInput(), [] ); + const isProduct = useSelect( ( select ) => select( STORE_NAME_EDITOR.free ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( STORE_NAME_EDITOR.free ).getIsWooSeoActive(), [] ); + const showArticleTypeInput = useSelect( select => select( STORE_NAME_EDITOR.free ).getShowArticleTypeInput(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const handleOptionChange = useCallback( diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index cf25a3a8286..e937a72a9f9 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** @@ -7,14 +7,14 @@ import { defaultTo } from "lodash"; * * @returns {string} The no index value. */ -export const getNoIndex = () => String( defaultTo( select( EDITOR_STORE ).getNoIndex(), "0" ) ); +export const getNoIndex = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getNoIndex(), "0" ) ); /** * Retrieves the no follow value. * * @returns {string} The no follow value. */ -export const getNoFollow = () => String( defaultTo( select( EDITOR_STORE ).getNoFollow(), "0" ) ); +export const getNoFollow = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getNoFollow(), "0" ) ); /** * Gets the twitter image URL from the state. @@ -24,7 +24,7 @@ export const getNoFollow = () => String( defaultTo( select( EDITOR_STORE ).getNo * @returns {string} Twitter image URL. */ export const getAdvanced = () => { - const advanced = defaultTo( select( EDITOR_STORE ).getAdvanced(), "" ); + const advanced = defaultTo( select( STORE_NAME_EDITOR.free ).getAdvanced(), "" ); if ( Array.isArray( advanced ) ) { return advanced.join( "," ); } @@ -38,7 +38,7 @@ export const getAdvanced = () => { * * @returns {string} Twitter image type. */ -export const getBreadcrumbsTitle = () => defaultTo( select( EDITOR_STORE ).getBreadcrumbsTitle(), "" ); +export const getBreadcrumbsTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getBreadcrumbsTitle(), "" ); /** * Gets the Twitter image src from the state. @@ -47,7 +47,7 @@ export const getBreadcrumbsTitle = () => defaultTo( select( EDITOR_STORE ).getBr * * @returns {String} Twitter image src. */ -export const getCanonical = () => defaultTo( select( EDITOR_STORE ).getCanonical(), "" ); +export const getCanonical = () => defaultTo( select( STORE_NAME_EDITOR.free ).getCanonical(), "" ); /** * Gets the WordProof timestamp value. @@ -56,4 +56,4 @@ export const getCanonical = () => defaultTo( select( EDITOR_STORE ).getCanonical * * @returns {string} WordProof timestamp value. */ -export const getWordProofTimestamp = () => select( EDITOR_STORE ).getWordProofTimestamp() ? "1" : ""; +export const getWordProofTimestamp = () => select( STORE_NAME_EDITOR.free ).getWordProofTimestamp() ? "1" : ""; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index 21ef7eb006c..c341f2c97e8 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** @@ -7,39 +7,39 @@ import { defaultTo } from "lodash"; * * @returns {string} The focus keyphrase. */ -export const getFocusKeyphrase = () => defaultTo( select( EDITOR_STORE ).getFocusKeyphrase(), "" ); +export const getFocusKeyphrase = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(), "" ); /** * Returns whether the current content is cornerstone content. * * @returns {string} Whether the current content is cornerstone content. */ -export const isCornerstoneContent = () => select( EDITOR_STORE )?.isCornerstoneContent() ? "1" : "0"; +export const isCornerstoneContent = () => select( STORE_NAME_EDITOR.free )?.isCornerstoneContent() ? "1" : "0"; /** * Retrieves the readability score from the store. * * @returns {string} The content score. */ -export const getReadabilityScore = () => String( defaultTo( select( EDITOR_STORE ).getReadabilityResults().overallScore, "0" ) ); +export const getReadabilityScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getReadabilityResults().overallScore, "0" ) ); /** * Retrieves the inclusive language score from the store. * * @returns {string} The content score. */ -export const getInclusiveLanguageScore = () => String( defaultTo( select( EDITOR_STORE ).getInclusiveLanguageResults().overallScore, "0" ) ); +export const getInclusiveLanguageScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getInclusiveLanguageResults().overallScore, "0" ) ); /** * Retrieves the seo score from the store. * * @returns {string} The content score. */ -export const getSeoScore = () => String( defaultTo( select( EDITOR_STORE ).getSeoResults().overallScore, "0" ) ); +export const getSeoScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getSeoResults().overallScore, "0" ) ); /** * Retrieves the estimated reading time from the store. * * @returns {string} The estimated reading time. */ -export const getEstimatedReadingTime = () => String( defaultTo( select( EDITOR_STORE ).getEstimatedReadingTime(), "0" ) ); +export const getEstimatedReadingTime = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getEstimatedReadingTime(), "0" ) ); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index de2af43ed18..bd9f21e4201 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,7 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, pickBy, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { EDITOR_STORE, CORE_EDITOR_STORE, SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR, SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -15,8 +15,8 @@ import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; * @returns {function} The updater. */ const createUpdater = () => { - const { editPost } = dispatch( CORE_EDITOR_STORE ); - const { getCurrentPost } = select( CORE_EDITOR_STORE ); + const { editPost } = dispatch( STORE_NAME_EDITOR.core ); + const { getCurrentPost } = select( STORE_NAME_EDITOR.core ); /** * Syncs the data to the WP entity record. @@ -82,5 +82,5 @@ export const blockEditorSync = () => { ...primaryTaxonomiesGetters, } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE_NAME_EDITOR.free ); }; diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js index 67a30a37d08..e93a4f86f3d 100644 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -1,28 +1,28 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** * Retrieve facebook image id. * @returns {integer} The facebook image id. */ -export const getFacebookImageId = () => String( defaultTo( select( EDITOR_STORE ).getFacebookImageId(), "" ) ); +export const getFacebookImageId = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookImageId(), "" ) ); /** * Get facebook title. * @returns {string} The facebook title. */ -export const getFacebookTitle = () => defaultTo( select( EDITOR_STORE ).getFacebookTitle(), "" ); +export const getFacebookTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookTitle(), "" ); /** * Get facebook description. * @returns {string} The facebook description. */ -export const getFacebookDescription = () => defaultTo( select( EDITOR_STORE ).getFacebookDescription(), "" ); +export const getFacebookDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookDescription(), "" ); /** * Get facebook image Url. * @returns {string} The facebook image Url. */ -export const getFacebookImageUrl = () => defaultTo( select( EDITOR_STORE )?.getFacebookImageUrl(), "" ); +export const getFacebookImageUrl = () => defaultTo( select( STORE_NAME_EDITOR.free )?.getFacebookImageUrl(), "" ); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 2deadf757c5..77797aeb4d2 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -2,7 +2,7 @@ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, pickBy, get, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { EDITOR_STORE, SYNC_TIME, META_KEYS, POST_FORM_IDS_PREFIX, TERM_FORM_IDS_PREFIX } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR, SYNC_TIME, META_KEYS, POST_INPUT_ID_PREFIX, TERM_INPUT_ID_PREFIX } from "../../shared-admin/constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -16,7 +16,7 @@ import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; * @returns {string} The value to be saved. */ const prepareSocialTitle = ( value ) => { - if ( value.trim() === select( EDITOR_STORE ).getSocialTitleTemplate().trim() ) { + if ( value.trim() === select( STORE_NAME_EDITOR.free ).getSocialTitleTemplate().trim() ) { return ""; } return value; @@ -28,7 +28,7 @@ const prepareSocialTitle = ( value ) => { * @returns {string} The value to be saved. */ const prepareSocialDescription = ( value ) => { - if ( value.trim() === select( EDITOR_STORE ).getSocialDescriptionTemplate().trim() ) { + if ( value.trim() === select( STORE_NAME_EDITOR.free ).getSocialDescriptionTemplate().trim() ) { return ""; } return value; @@ -99,7 +99,7 @@ export const createUpdater = () => { }; const isPost = get( window, "wpseoScriptData.isPost", false ); -const prefix = isPost ? POST_FORM_IDS_PREFIX : TERM_FORM_IDS_PREFIX; +const prefix = isPost ? POST_INPUT_ID_PREFIX : TERM_INPUT_ID_PREFIX; const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => prefix + key ); @@ -139,5 +139,5 @@ export const hiddenFieldsSync = () => { ...primaryTaxonomiesGetters, } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), EDITOR_STORE ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE_NAME_EDITOR.free ); }; diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index b5b6f526ac3..1ee79234860 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -1,6 +1,6 @@ import { get, pickBy, forEach, defaultTo } from "lodash"; import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; /** * Retrieves primary terms from store methods. @@ -14,7 +14,7 @@ const getPrimaryTerms = () => { forEach( primaryTerms, ( value, key ) => { const taxonomy = key.replace( "primary_", "" ); getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { - const termId = String( defaultTo( select( EDITOR_STORE ).getPrimaryTaxonomyId( taxonomy ), "" ) ); + const termId = String( defaultTo( select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( taxonomy ), "" ) ); if ( termId === "0" || termId === "-1" ) { return ""; } diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index 015fefe6e44..6d9bd17d920 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** @@ -7,11 +7,11 @@ import { defaultTo } from "lodash"; * * @returns {String} Page type. */ -export const getPageType = () => defaultTo( select( EDITOR_STORE ).getPageType(), "" ); +export const getPageType = () => defaultTo( select( STORE_NAME_EDITOR.free ).getPageType(), "" ); /** * Gets the articleType from the store. * * @returns {String} Article type. */ -export const getArticleType = () => defaultTo( select( EDITOR_STORE ).getArticleType(), "" ); +export const getArticleType = () => defaultTo( select( STORE_NAME_EDITOR.free ).getArticleType(), "" ); diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js index 8644594199d..9986d3eebf8 100644 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** @@ -7,11 +7,11 @@ import { defaultTo } from "lodash"; * * @returns {string} The snippet editor title. */ -export const getSeoTitle = () => defaultTo( select( EDITOR_STORE ).getSnippetEditorTitle(), "" ); +export const getSeoTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getSnippetEditorTitle(), "" ); /** * Gets the snippet editor description from the store. * * @returns {string} The snippet editor description. */ -export const getSeoDescription = () => defaultTo( select( EDITOR_STORE ).getSnippetEditorDescription(), "" ); +export const getSeoDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getSnippetEditorDescription(), "" ); diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js index da9827cd5c5..8a95f2b882e 100644 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -1,5 +1,5 @@ import { select } from "@wordpress/data"; -import { EDITOR_STORE } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; import { defaultTo } from "lodash"; /** @@ -7,26 +7,26 @@ import { defaultTo } from "lodash"; * * @returns {string} The twitter image id. */ -export const getTwitterImageId = () => String( defaultTo( select( EDITOR_STORE ).getTwitterImageId(), "" ) ); +export const getTwitterImageId = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterImageId(), "" ) ); /** * Get twitter title from the store. * * @returns {string} The twitter title. */ -export const getTwitterTitle = () => defaultTo( select( EDITOR_STORE ).getTwitterTitle(), "" ); +export const getTwitterTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterTitle(), "" ); /** * Get twitter description from the store. * * @returns {string} The twitter description. */ -export const getTwitterDescription = () => defaultTo( select( EDITOR_STORE ).getTwitterDescription(), "" ); +export const getTwitterDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterDescription(), "" ); /** * Get twitter image Url from the store. * * @returns {string} The twitter image Url. */ -export const getTwitterImageUrl = () => defaultTo( select( EDITOR_STORE ).getTwitterImageUrl(), "" ); +export const getTwitterImageUrl = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterImageUrl(), "" ); diff --git a/packages/js/src/shared-admin/constants/index.js b/packages/js/src/shared-admin/constants/index.js index 02a2e701948..d5f7f018440 100644 --- a/packages/js/src/shared-admin/constants/index.js +++ b/packages/js/src/shared-admin/constants/index.js @@ -20,5 +20,9 @@ export const VIDEO_FLOW = { isPlaying: "isPlaying", }; -export * from "./stores"; +export const STORE_NAME_EDITOR = { + free: "yoast-seo/editor", + core: "core/editor", +}; + export * from "./sync"; diff --git a/packages/js/src/shared-admin/constants/stores.js b/packages/js/src/shared-admin/constants/stores.js deleted file mode 100644 index cf42bbd61dc..00000000000 --- a/packages/js/src/shared-admin/constants/stores.js +++ /dev/null @@ -1,3 +0,0 @@ -export const EDITOR_STORE = "yoast-seo/editor"; - -export const CORE_EDITOR_STORE = "core/editor"; diff --git a/packages/js/src/shared-admin/constants/sync.js b/packages/js/src/shared-admin/constants/sync.js index 5d6cb4921b0..4946385e72a 100644 --- a/packages/js/src/shared-admin/constants/sync.js +++ b/packages/js/src/shared-admin/constants/sync.js @@ -25,11 +25,11 @@ export const META_KEYS = { readingTime: "estimated-reading-time-minutes", }; -export const POST_META_KEY_PREFIX = "_yoast_wpseo_"; +export const POST_INPUT_ID_PREFIX = "yoast_wpseo_"; -export const POST_FORM_IDS_PREFIX = "yoast_wpseo_"; +export const POST_META_KEY_PREFIX = `_${ POST_INPUT_ID_PREFIX }`; -export const TERM_FORM_IDS_PREFIX = "hidden_wpseo_"; +export const TERM_INPUT_ID_PREFIX = "hidden_wpseo_"; export const SYNC_TIME = { wait: 500, diff --git a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js index a17edf4e1fd..9d32555f290 100644 --- a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js +++ b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js @@ -6,7 +6,7 @@ import { getEstimatedReadingTime, isCornerstoneContent, } from "../../../src/helpers/fields"; -import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { @@ -24,7 +24,7 @@ const testCasesScoresInteger = [ describe.each( testCasesScoresInteger )( "$method", ( { method, getFunction, returnValueSelect } ) => { it( `should return string from ${method} when the score is an integer`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => { return returnValueSelect; @@ -48,7 +48,7 @@ const testCasesScoresNull = [ describe.each( testCasesScoresNull )( "$method", ( { method, getFunction, returnValueSelect } ) => { it( `should return zero string from ${method} when null`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => { return returnValueSelect; @@ -72,7 +72,7 @@ const testCasesScoresUndefined = [ describe.each( testCasesScoresUndefined )( "$method", ( { method, getFunction, returnValueSelect } ) => { it( `should return zero string from ${method} when undefined`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => { return returnValueSelect; @@ -96,7 +96,7 @@ const boolenaTestCases = [ describe.each( boolenaTestCases )( "isCornerstoneContent", ( { value, expected } ) => { it( `should return ${expected} from isCornerstoneContent when value is ${value}`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { isCornerstoneContent: () => value, }; @@ -117,7 +117,7 @@ const focusKeyphraseTestCases = [ describe.each( focusKeyphraseTestCases )( "getFocusKeyphrase", ( { value, expected } ) => { it( `should return ${expected} from getFocusKeyphrase when value is ${value}`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { getFocusKeyphrase: () => value, }; diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index 265daa67ebc..d243b2f4d13 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -1,5 +1,5 @@ import getPrimaryTerms from "../../../src/helpers/fields/primaryTaxonomiesFieldsStore"; -import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { @@ -41,7 +41,7 @@ describe.each( testCases )( "getPrimaryTerm - should returns an object with taxo getPrimaryTaxonomyId.mockReturnValue( termId ); select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { getPrimaryTaxonomyId, }; diff --git a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js index bd574e10d5d..879fe5cf4f1 100644 --- a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js +++ b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js @@ -16,7 +16,7 @@ import { getPageType, getArticleType, } from "../../../src/helpers/fields"; -import { EDITOR_STORE } from "../../../src/shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; // Tests for the facebookFieldsStore.js, twitterFieldsStore.js and adnacedSettingsFieldsStore.js files. @@ -35,7 +35,7 @@ const testCasesInteger = [ describe.each( testCasesInteger )( "$method", ( { method, getFunction } ) => { it( `should return string from ${method} when the value is an integer`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => 5, }; @@ -67,7 +67,7 @@ const testCases = [ describe.each( testCases )( "$method", ( { method, getFunction } ) => { it( `should return string from ${method} when value is string`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => "string_result", }; @@ -83,7 +83,7 @@ describe.each( testCases )( "$method", ( { method, getFunction } ) => { describe.each( testCases )( "$method", ( { method, getFunction } ) => { it( `should return empty string from ${method} when null`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => null, }; @@ -98,7 +98,7 @@ describe.each( testCases )( "$method", ( { method, getFunction } ) => { describe.each( testCases )( "$method", ( { method, getFunction } ) => { it( `should return empty string from ${method} when undefined`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => undefined, }; @@ -118,7 +118,7 @@ const testCasesWithDefaultZero = [ describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { it( `should return zero string from ${method} when null`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => null, }; @@ -133,7 +133,7 @@ describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { it( `should return zero string from ${method} when null`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { [ method ]: () => undefined, }; @@ -148,7 +148,7 @@ describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } describe( "getWordProofTimestamp", () => { it( "should return '1' when true", () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { getWordProofTimestamp: () => true, }; @@ -169,7 +169,7 @@ const getWordProofTimestampTestCases = [ describe.each( getWordProofTimestampTestCases )( "getWordProofTimestamp", ( { value, expected } ) => { it( `should return ${expected ? expected : "empty string" } from getWordProofTimestamp when value is ${value}`, () => { select.mockImplementation( ( store ) => { - if ( store === EDITOR_STORE ) { + if ( store === STORE_NAME_EDITOR.free ) { return { getWordProofTimestamp: () => value, }; From f9049613bc69b80bdff418000730cd0e99924c59 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Wed, 17 Apr 2024 14:16:27 +0200 Subject: [PATCH 219/344] remove default to since it is done in the selectors --- .../js/src/helpers/fields/advancedFieldsStore.js | 13 ++++++------- .../js/src/helpers/fields/analysisFieldsStore.js | 4 ++-- .../js/src/helpers/fields/facebookFieldsStore.js | 9 ++++----- packages/js/src/helpers/fields/schemaFieldsStore.js | 5 ++--- .../src/helpers/fields/snippetEditorFieldsStore.js | 5 ++--- .../js/src/helpers/fields/twitterFieldsStore.js | 9 ++++----- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js index e937a72a9f9..e31e0458304 100644 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ b/packages/js/src/helpers/fields/advancedFieldsStore.js @@ -1,20 +1,19 @@ import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; /** * Retrieves the no index value. * * @returns {string} The no index value. */ -export const getNoIndex = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getNoIndex(), "0" ) ); +export const getNoIndex = () => String( select( STORE_NAME_EDITOR.free ).getNoIndex() ); /** * Retrieves the no follow value. * * @returns {string} The no follow value. */ -export const getNoFollow = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getNoFollow(), "0" ) ); +export const getNoFollow = () => String( select( STORE_NAME_EDITOR.free ).getNoFollow() ); /** * Gets the twitter image URL from the state. @@ -24,9 +23,9 @@ export const getNoFollow = () => String( defaultTo( select( STORE_NAME_EDITOR.fr * @returns {string} Twitter image URL. */ export const getAdvanced = () => { - const advanced = defaultTo( select( STORE_NAME_EDITOR.free ).getAdvanced(), "" ); + const advanced = select( STORE_NAME_EDITOR.free ).getAdvanced(); if ( Array.isArray( advanced ) ) { - return advanced.join( "," ); + return advanced.join(); } return advanced; }; @@ -38,7 +37,7 @@ export const getAdvanced = () => { * * @returns {string} Twitter image type. */ -export const getBreadcrumbsTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getBreadcrumbsTitle(), "" ); +export const getBreadcrumbsTitle = () => select( STORE_NAME_EDITOR.free ).getBreadcrumbsTitle(); /** * Gets the Twitter image src from the state. @@ -47,7 +46,7 @@ export const getBreadcrumbsTitle = () => defaultTo( select( STORE_NAME_EDITOR.fr * * @returns {String} Twitter image src. */ -export const getCanonical = () => defaultTo( select( STORE_NAME_EDITOR.free ).getCanonical(), "" ); +export const getCanonical = () => select( STORE_NAME_EDITOR.free ).getCanonical(); /** * Gets the WordProof timestamp value. diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js index c341f2c97e8..ebd13f1e7b8 100644 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ b/packages/js/src/helpers/fields/analysisFieldsStore.js @@ -7,14 +7,14 @@ import { defaultTo } from "lodash"; * * @returns {string} The focus keyphrase. */ -export const getFocusKeyphrase = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(), "" ); +export const getFocusKeyphrase = () => select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(); /** * Returns whether the current content is cornerstone content. * * @returns {string} Whether the current content is cornerstone content. */ -export const isCornerstoneContent = () => select( STORE_NAME_EDITOR.free )?.isCornerstoneContent() ? "1" : "0"; +export const isCornerstoneContent = () => select( STORE_NAME_EDITOR.free ).isCornerstoneContent() ? "1" : "0"; /** * Retrieves the readability score from the store. diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js index e93a4f86f3d..f5854041ecd 100644 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ b/packages/js/src/helpers/fields/facebookFieldsStore.js @@ -1,28 +1,27 @@ import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; /** * Retrieve facebook image id. * @returns {integer} The facebook image id. */ -export const getFacebookImageId = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookImageId(), "" ) ); +export const getFacebookImageId = () => String( select( STORE_NAME_EDITOR.free ).getFacebookImageId() ); /** * Get facebook title. * @returns {string} The facebook title. */ -export const getFacebookTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookTitle(), "" ); +export const getFacebookTitle = () => select( STORE_NAME_EDITOR.free ).getFacebookTitle(); /** * Get facebook description. * @returns {string} The facebook description. */ -export const getFacebookDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getFacebookDescription(), "" ); +export const getFacebookDescription = () => select( STORE_NAME_EDITOR.free ).getFacebookDescription(); /** * Get facebook image Url. * @returns {string} The facebook image Url. */ -export const getFacebookImageUrl = () => defaultTo( select( STORE_NAME_EDITOR.free )?.getFacebookImageUrl(), "" ); +export const getFacebookImageUrl = () => select( STORE_NAME_EDITOR.free )?.getFacebookImageUrl(); diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js index 6d9bd17d920..e4d4cd14d1b 100644 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ b/packages/js/src/helpers/fields/schemaFieldsStore.js @@ -1,17 +1,16 @@ import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; /** * Gets the pageType from the store. * * @returns {String} Page type. */ -export const getPageType = () => defaultTo( select( STORE_NAME_EDITOR.free ).getPageType(), "" ); +export const getPageType = () => select( STORE_NAME_EDITOR.free ).getPageType(); /** * Gets the articleType from the store. * * @returns {String} Article type. */ -export const getArticleType = () => defaultTo( select( STORE_NAME_EDITOR.free ).getArticleType(), "" ); +export const getArticleType = () => select( STORE_NAME_EDITOR.free ).getArticleType(); diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js index 9986d3eebf8..ce4418c8fac 100644 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js @@ -1,17 +1,16 @@ import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; /** * Gets the snippet editor title from the store. * * @returns {string} The snippet editor title. */ -export const getSeoTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getSnippetEditorTitle(), "" ); +export const getSeoTitle = () => select( STORE_NAME_EDITOR.free ).getSnippetEditorTitle(); /** * Gets the snippet editor description from the store. * * @returns {string} The snippet editor description. */ -export const getSeoDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getSnippetEditorDescription(), "" ); +export const getSeoDescription = () => select( STORE_NAME_EDITOR.free ).getSnippetEditorDescription(); diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js index 8a95f2b882e..c48280d0267 100644 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ b/packages/js/src/helpers/fields/twitterFieldsStore.js @@ -1,32 +1,31 @@ import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; /** * Retrieve twitter image id from the store. * * @returns {string} The twitter image id. */ -export const getTwitterImageId = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterImageId(), "" ) ); +export const getTwitterImageId = () => String( select( STORE_NAME_EDITOR.free ).getTwitterImageId() ); /** * Get twitter title from the store. * * @returns {string} The twitter title. */ -export const getTwitterTitle = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterTitle(), "" ); +export const getTwitterTitle = () => select( STORE_NAME_EDITOR.free ).getTwitterTitle(); /** * Get twitter description from the store. * * @returns {string} The twitter description. */ -export const getTwitterDescription = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterDescription(), "" ); +export const getTwitterDescription = () => select( STORE_NAME_EDITOR.free ).getTwitterDescription(); /** * Get twitter image Url from the store. * * @returns {string} The twitter image Url. */ -export const getTwitterImageUrl = () => defaultTo( select( STORE_NAME_EDITOR.free ).getTwitterImageUrl(), "" ); +export const getTwitterImageUrl = () => select( STORE_NAME_EDITOR.free ).getTwitterImageUrl(); From 54ef0324edb9c30610c78df445f5285fbb5848d1 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 19 Apr 2024 16:32:59 +0200 Subject: [PATCH 220/344] refactor hidden fields sync and constants --- .../js/src/helpers/fields/blockEditorSync.js | 61 ++++++------ .../sync.js => helpers/fields/constants.js} | 9 +- .../js/src/helpers/fields/hiddenFieldsSync.js | 95 ++++++++----------- packages/js/src/redux/initial-state/index.js | 4 + .../js/src/shared-admin/constants/index.js | 2 - 5 files changed, 77 insertions(+), 94 deletions(-) rename packages/js/src/{shared-admin/constants/sync.js => helpers/fields/constants.js} (84%) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index bd9f21e4201..d7002ca1dbb 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,7 +1,8 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, pickBy, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE_NAME_EDITOR, SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; +import { SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "./constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -42,40 +43,40 @@ const createUpdater = () => { }; }; -const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => POST_META_KEY_PREFIX + key ); - -const getters = mapKeys( { - focusKeyphrase: getFocusKeyphrase, - robotsNoIndex: getNoIndex, - robotsNoFollow: getNoFollow, - robotsAdvanced: getAdvanced, - facebookTitle: getFacebookTitle, - facebookDescription: getFacebookDescription, - facebookImageUrl: getFacebookImageUrl, - facebookImageId: getFacebookImageId, - twitterTitle: getTwitterTitle, - twitterDescription: getTwitterDescription, - twitterImageUrl: getTwitterImageUrl, - twitterImageId: getTwitterImageId, - schemaPageType: getPageType, - schemaArticleType: getArticleType, - isCornerstone: isCornerstoneContent, - readabilityScore: getReadabilityScore, - seoScore: getSeoScore, - inclusiveLanguageScore: getInclusiveLanguageScore, - breadcrumbsTitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordProofTimestamp: getWordProofTimestamp, - seoTitle: getSeoTitle, - seoDescription: getSeoDescription, - readingTime: getEstimatedReadingTime, -}, ( value, key ) => POST_META_KEY_PREFIX + META_KEYS[ key ] ); - /** * Initializes the sync: from Yoast editor store to core editor store. * @returns {function} The un-subscriber. */ export const blockEditorSync = () => { + const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => POST_META_KEY_PREFIX + key ); + + const getters = mapKeys( { + focusKeyphrase: getFocusKeyphrase, + robotsNoIndex: getNoIndex, + robotsNoFollow: getNoFollow, + robotsAdvanced: getAdvanced, + facebookTitle: getFacebookTitle, + facebookDescription: getFacebookDescription, + facebookImageUrl: getFacebookImageUrl, + facebookImageId: getFacebookImageId, + twitterTitle: getTwitterTitle, + twitterDescription: getTwitterDescription, + twitterImageUrl: getTwitterImageUrl, + twitterImageId: getTwitterImageId, + schemaPageType: getPageType, + schemaArticleType: getArticleType, + isCornerstone: isCornerstoneContent, + readabilityScore: getReadabilityScore, + seoScore: getSeoScore, + inclusiveLanguageScore: getInclusiveLanguageScore, + breadcrumbsTitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordProofTimestamp: getWordProofTimestamp, + seoTitle: getSeoTitle, + seoDescription: getSeoDescription, + readingTime: getEstimatedReadingTime, + }, ( value, key ) => POST_META_KEY_PREFIX + META_KEYS[ key ] ); + return subscribe( debounce( createWatcher( createCollectorFromObject( { ...getters, diff --git a/packages/js/src/shared-admin/constants/sync.js b/packages/js/src/helpers/fields/constants.js similarity index 84% rename from packages/js/src/shared-admin/constants/sync.js rename to packages/js/src/helpers/fields/constants.js index 4946385e72a..d5c3d01b8f9 100644 --- a/packages/js/src/shared-admin/constants/sync.js +++ b/packages/js/src/helpers/fields/constants.js @@ -25,11 +25,12 @@ export const META_KEYS = { readingTime: "estimated-reading-time-minutes", }; -export const POST_INPUT_ID_PREFIX = "yoast_wpseo_"; - -export const POST_META_KEY_PREFIX = `_${ POST_INPUT_ID_PREFIX }`; +export const HIDDEN_INPUT_ID_PREFIX = { + post: "yoast_wpseo_", + term: "hidden_wpseo_", +}; -export const TERM_INPUT_ID_PREFIX = "hidden_wpseo_"; +export const POST_META_KEY_PREFIX = `_${ HIDDEN_INPUT_ID_PREFIX.post }`; export const SYNC_TIME = { wait: 500, diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 77797aeb4d2..f662a71e472 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,8 +1,9 @@ /* eslint-disable complexity */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, pickBy, get, mapKeys } from "lodash"; +import { debounce, forEach, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE_NAME_EDITOR, SYNC_TIME, META_KEYS, POST_INPUT_ID_PREFIX, TERM_INPUT_ID_PREFIX } from "../../shared-admin/constants"; +import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; +import { HIDDEN_INPUT_ID_PREFIX, SYNC_TIME, META_KEYS } from "./constants"; import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; import { getPageType, getArticleType } from "./schemaFieldsStore"; @@ -57,7 +58,6 @@ const prepareValue = ( key, value ) => { } }; - /** * Creates an updater. * @returns {function} The updater. @@ -69,70 +69,49 @@ export const createUpdater = () => { * @returns {void} */ return ( data ) => { - // Get the values from hidden fields. - const hiddenFieldsData = {}; - const yoastFormElement = document.getElementById( "wpseo_meta" ) || document.getElementById( "yoast-form" ); - - if ( yoastFormElement ) { - const hiddenFields = yoastFormElement?.querySelectorAll( "input[type=hidden]" ); - if ( hiddenFields ) { - forEach( hiddenFields, ( field ) => { - if ( field.id ) { - hiddenFieldsData[ field.id ] = field.value; - } - } ); + forEach( data, ( value, key ) => { + const field = document.getElementById( key ); + if ( field && field.value !== value ) { + field.value = prepareValue( key, value ); } - } - - if ( ! hiddenFieldsData || ! data ) { - return; - } - - const changedData = pickBy( data, ( value, key ) => ( key ) in hiddenFieldsData && value !== hiddenFieldsData[ key ] ); - - if ( changedData ) { - forEach( changedData, ( value, key ) => { - document.getElementById( key ).value = prepareValue( key, value ); - } ); - } + } ); }; }; -const isPost = get( window, "wpseoScriptData.isPost", false ); -const prefix = isPost ? POST_INPUT_ID_PREFIX : TERM_INPUT_ID_PREFIX; - -const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => prefix + key ); - -const getters = mapKeys( { - focusKeyphrase: getFocusKeyphrase, - robotsNoIndex: getNoIndex, - robotsNoFollow: getNoFollow, - robotsAdvanced: getAdvanced, - facebookTitle: getFacebookTitle, - facebookDescription: getFacebookDescription, - facebookImageUrl: getFacebookImageUrl, - facebookImageId: getFacebookImageId, - twitterTitle: getTwitterTitle, - twitterDescription: getTwitterDescription, - twitterImageUrl: getTwitterImageUrl, - twitterImageId: getTwitterImageId, - schemaPageType: getPageType, - schemaArticleType: getArticleType, - isCornerstone: isCornerstoneContent, - readabilityScore: getReadabilityScore, - seoScore: getSeoScore, - inclusiveLanguageScore: getInclusiveLanguageScore, - breadcrumbsTitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordProofTimestamp: getWordProofTimestamp, - readingTime: getEstimatedReadingTime, -}, ( value, key ) => prefix + META_KEYS[ key ] ); - /** * Initializes the sync: from Yoast editor store to the hidden fields. * @returns {function} The un-subscriber. */ export const hiddenFieldsSync = () => { + const isPost = select( STORE_NAME_EDITOR.free ).getIsPost(); + const prefix = isPost ? HIDDEN_INPUT_ID_PREFIX.post : HIDDEN_INPUT_ID_PREFIX.term; + const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => prefix + key ); + + const getters = mapKeys( { + focusKeyphrase: getFocusKeyphrase, + robotsNoIndex: getNoIndex, + robotsNoFollow: getNoFollow, + robotsAdvanced: getAdvanced, + facebookTitle: getFacebookTitle, + facebookDescription: getFacebookDescription, + facebookImageUrl: getFacebookImageUrl, + facebookImageId: getFacebookImageId, + twitterTitle: getTwitterTitle, + twitterDescription: getTwitterDescription, + twitterImageUrl: getTwitterImageUrl, + twitterImageId: getTwitterImageId, + schemaPageType: getPageType, + schemaArticleType: getArticleType, + isCornerstone: isCornerstoneContent, + readabilityScore: getReadabilityScore, + seoScore: getSeoScore, + inclusiveLanguageScore: getInclusiveLanguageScore, + breadcrumbsTitle: getBreadcrumbsTitle, + canonical: getCanonical, + wordProofTimestamp: getWordProofTimestamp, + readingTime: getEstimatedReadingTime, + }, ( value, key ) => prefix + META_KEYS[ key ] ); + return subscribe( debounce( createWatcher( createCollectorFromObject( { ...getters, diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index f50ae20383e..851a3e2a5f1 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -13,6 +13,10 @@ const initialState = { isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", primaryTaxonomies, schemaTab, + post: { + isPost: get( window, "wpseoScriptData.isPost", false ), + id: Number( get( window, "wpseoScriptData.postId", null ) ), + }, }; export default initialState; diff --git a/packages/js/src/shared-admin/constants/index.js b/packages/js/src/shared-admin/constants/index.js index d5f7f018440..2108f6cec9a 100644 --- a/packages/js/src/shared-admin/constants/index.js +++ b/packages/js/src/shared-admin/constants/index.js @@ -24,5 +24,3 @@ export const STORE_NAME_EDITOR = { free: "yoast-seo/editor", core: "core/editor", }; - -export * from "./sync"; From eda57cdff832d84543db3e4083bd4f6a4ce91407 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Fri, 19 Apr 2024 16:33:25 +0200 Subject: [PATCH 221/344] refactor postId selector and added a selector if it's a post --- packages/js/src/initializers/editor-store.js | 1 - packages/js/src/redux/selectors/post.js | 13 +++++++++++++ packages/js/src/redux/selectors/postId.js | 7 ------- 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 packages/js/src/redux/selectors/post.js delete mode 100644 packages/js/src/redux/selectors/postId.js diff --git a/packages/js/src/initializers/editor-store.js b/packages/js/src/initializers/editor-store.js index e6fad1d8915..9dc7c7b5718 100644 --- a/packages/js/src/initializers/editor-store.js +++ b/packages/js/src/initializers/editor-store.js @@ -38,7 +38,6 @@ const populateStore = store => { store.dispatch( actions.setDismissedAlerts( get( window, "wpseoScriptData.dismissedAlerts", {} ) ) ); store.dispatch( actions.setCurrentPromotions( get( window, "wpseoScriptData.currentPromotions", [] ) ) ); store.dispatch( actions.setIsPremium( Boolean( get( window, "wpseoScriptData.metabox.isPremium", false ) ) ) ); - store.dispatch( actions.setPostId( Number( get( window, "wpseoScriptData.postId", null ) ) ) ); store.dispatch( actions.setLinkParams( get( window, "wpseoScriptData.linkParams", {} ) ) ); store.dispatch( actions.setPluginUrl( get( window, "wpseoScriptData.pluginUrl", "" ) ) ); diff --git a/packages/js/src/redux/selectors/post.js b/packages/js/src/redux/selectors/post.js new file mode 100644 index 00000000000..d59c64583f3 --- /dev/null +++ b/packages/js/src/redux/selectors/post.js @@ -0,0 +1,13 @@ +import { get } from "lodash"; + +/** + * @param {Ojbect} state The current Redux state. + * @returns {number} The post ID. + */ +export const getPostId = ( state ) => get( state, "post.id", null ); + +/** + * @param {Ojbect} state The current Redux state. + * @returns {string} Is post or term. + */ +export const getIsPost = ( state ) => get( state, "post.isPost", null ); diff --git a/packages/js/src/redux/selectors/postId.js b/packages/js/src/redux/selectors/postId.js deleted file mode 100644 index 59b5562291a..00000000000 --- a/packages/js/src/redux/selectors/postId.js +++ /dev/null @@ -1,7 +0,0 @@ -import { get } from "lodash"; - -/** - * @param {Ojbect} state The current Redux state. - * @returns {number} The post ID. - */ -export const getPostId = ( state ) => get( state, "postId", null ); From fd45e25a27f1a6f6d0f3079b66197306c81cc1eb Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 10:20:18 +0200 Subject: [PATCH 222/344] rename selector import --- packages/js/src/redux/selectors/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/redux/selectors/index.js b/packages/js/src/redux/selectors/index.js index 2293c15e696..e8b58fce5d8 100644 --- a/packages/js/src/redux/selectors/index.js +++ b/packages/js/src/redux/selectors/index.js @@ -38,4 +38,4 @@ export * from "./WincherRequest"; export * from "./WincherSEOPerformance"; export * from "./isPremium"; export * from "./isWooSEO"; -export * from "./postId"; +export * from "./post"; From 7011d8e9813ba5862aeb68ecf4b3461cd3a84b5e Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:21:57 +0200 Subject: [PATCH 223/344] Update admin/class-primary-term-admin.php Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index ef386e92680..d42920d93e4 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -80,7 +80,7 @@ protected function primary_term_field( $taxonomy_name ) { * @return string The field id. */ protected function generate_field_id( $taxonomy_name ) { - return 'yoast_wpseo_primary_' . $taxonomy_name; + return WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy_name; } /** From ad589815e8cd579a78dd7eae82ca52796bbba802 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 10:32:26 +0200 Subject: [PATCH 224/344] fix param comment --- admin/class-primary-term-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index d42920d93e4..a87fcfc5bdd 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -225,7 +225,7 @@ protected function get_mapped_taxonomies_for_js( $taxonomies ) { * * @param stdClass $taxonomy The taxonomy to map. * - * @return array The mapped taxonomy. + * @return array> The mapped taxonomy. */ private function map_taxonomies_for_js( $taxonomy ) { $primary_term = $this->get_primary_term( $taxonomy->name ); From 9c6f3407eeecc2d9acf4006ecd3e9cfdbd5cfd65 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 10:34:33 +0200 Subject: [PATCH 225/344] fix param comment --- admin/formatter/class-term-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 157b6505ec8..80e3f47737c 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -63,7 +63,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array|array> + * @return array> */ public function get_values() { $values = []; From e7af60ee53e39e5519c27c50279c82dff7dafa05 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 11:16:05 +0200 Subject: [PATCH 226/344] fix comments for return type --- admin/formatter/class-term-metabox-formatter.php | 2 +- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 80e3f47737c..96fb2fb9bf3 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -171,7 +171,7 @@ private function base_url_for_js() { /** * Counting the number of given keyword used for other term than given term_id. * - * @return array + * @return array> */ private function get_focus_keyword_usage() { $focuskw = WPSEO_Taxonomy_Meta::get_term_meta( $this->term, $this->term->taxonomy, 'focuskw' ); diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index 86f428c8959..ad3555a7611 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -13,7 +13,7 @@ class WPSEO_Taxonomy_Fields_Presenter { /** * The taxonomy meta data for the current term. * - * @var array + * @var array> */ private $tax_meta; From f7857b8ac257dbd3f85123a1e59699643ce5d89b Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 11:52:22 +0200 Subject: [PATCH 227/344] removed the value from the primary taxonomy field, would be populated by the hidden fields sync --- admin/class-primary-term-admin.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index a87fcfc5bdd..09e773d79b4 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -65,10 +65,9 @@ public function add_input_fields( $content ) { */ protected function primary_term_field( $taxonomy_name ) { return sprintf( - '', + '', esc_attr( $this->generate_field_id( $taxonomy_name ) ), esc_attr( $this->generate_field_name( $taxonomy_name ) ), - esc_attr( $this->get_primary_term( $taxonomy_name ) ) ); } From 6c23bd76425f554087d4869ada49c550cf477fd1 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 13:17:18 +0200 Subject: [PATCH 228/344] cleanup duplication of code --- admin/class-primary-term-admin.php | 31 ++++-------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 09e773d79b4..2f363385dc6 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -5,13 +5,14 @@ * @package WPSEO\Admin */ + use Yoast\WP\SEO\Helpers\Primary_Term_Helper; /** * Adds the UI to change the primary term for a post. */ class WPSEO_Primary_Term_Admin implements WPSEO_WordPress_Integration { /** - * Constructor. + * Register hooks. * * @return void */ @@ -167,7 +168,8 @@ protected function get_primary_term_taxonomies( $post_id = null ) { return $taxonomies; } - $taxonomies = $this->generate_primary_term_taxonomies( $post_id ); + $primary_term_helper = new Primary_Term_Helper(); + $taxonomies = $primary_term_helper->get_primary_term_taxonomies( $post_id ); wp_cache_set( 'primary_term_taxonomies_' . $post_id, $taxonomies, 'wpseo' ); @@ -183,31 +185,6 @@ protected function include_js_templates() { include_once WPSEO_PATH . 'admin/views/js-templates-primary-term.php'; } - /** - * Generates the primary term taxonomies. - * - * @param int $post_id ID of the post. - * - * @return array The primary term taxonomies. - */ - protected function generate_primary_term_taxonomies( $post_id ) { - $post_type = get_post_type( $post_id ); - $all_taxonomies = get_object_taxonomies( $post_type, 'objects' ); - $all_taxonomies = array_filter( $all_taxonomies, [ $this, 'filter_hierarchical_taxonomies' ] ); - - /** - * Filters which taxonomies for which the user can choose the primary term. - * - * @param array $taxonomies An array of taxonomy objects that are primary_term enabled. - * @param string $post_type The post type for which to filter the taxonomies. - * @param array $all_taxonomies All taxonomies for this post types, even ones that don't have primary term - * enabled. - */ - $taxonomies = (array) apply_filters( 'wpseo_primary_term_taxonomies', $all_taxonomies, $post_type, $all_taxonomies ); - - return $taxonomies; - } - /** * Creates a map of taxonomies for localization. * From 81ff1b4a9b01f4995c0a48166cead8e60c6ae7a3 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 13:24:11 +0200 Subject: [PATCH 229/344] primary taxonomies are already part of the window object --- admin/formatter/class-post-metabox-formatter.php | 9 --------- packages/js/src/redux/initial-state/primaryTaxonomies.js | 9 ++++----- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index e80e63d1b2d..ad29396b6ea 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -348,15 +348,6 @@ protected function get_post_meta_data() { $meta_data[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); } - $taxonomies = get_object_taxonomies( $post_type, 'objects' ); - foreach ( $taxonomies as $taxonomy ) { - if ( $taxonomy->hierarchical ) { - $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $this->post->ID ); - $primary_term = $primary_term_object->get_primary_term(); - $meta_data[ 'primary_' . $taxonomy->name ] = ( $primary_term ?? '' ); - } - } - return $meta_data; } diff --git a/packages/js/src/redux/initial-state/primaryTaxonomies.js b/packages/js/src/redux/initial-state/primaryTaxonomies.js index 7e740664b7d..00029480a82 100644 --- a/packages/js/src/redux/initial-state/primaryTaxonomies.js +++ b/packages/js/src/redux/initial-state/primaryTaxonomies.js @@ -1,12 +1,11 @@ -import { get, pickBy, forEach } from "lodash"; +import { get, forEach } from "lodash"; const primaryTaxonomies = {}; -const metadata = get( window, "wpseoScriptData.metabox.metadata", {} ); -const primaryTerms = pickBy( metadata, ( value, key ) => key.startsWith( "primary_" ) && value ); +const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); + forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - primaryTaxonomies[ taxonomy ] = value; + primaryTaxonomies[ key ] = value.primary; } ); export default primaryTaxonomies; From 62864b4c1a7b01a34cb52bad2e1963623471e563 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 13:46:01 +0200 Subject: [PATCH 230/344] get primary terms from the right window object and add get check --- packages/js/src/components/PrimaryTaxonomyPicker.js | 7 ++----- .../helpers/fields/primaryTaxonomiesFieldsStore.js | 11 +++++------ packages/js/src/redux/selectors/primaryTaxonomies.js | 3 ++- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index ae0c0372090..197be3f75d1 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -29,12 +29,9 @@ class PrimaryTaxonomyPicker extends Component { this.onChange = this.onChange.bind( this ); this.updateReplacementVariable = this.updateReplacementVariable.bind( this ); - const { fieldId, name } = props.taxonomy; + const { fieldId } = props.taxonomy; this.input = document.getElementById( fieldId ); - if ( this.input ) { - props.setPrimaryTaxonomyId( name, parseInt( this.input.value, 10 ) ); - } this.state = { selectedTerms: [], @@ -192,7 +189,7 @@ class PrimaryTaxonomyPicker extends Component { this.props.setPrimaryTaxonomyId( name, termId ); if ( this.input ) { - this.input.value = termId === -1 ? "" : termId; + this.input.value = termId === -1 ? "" : String( termId ); } } diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index 1ee79234860..e9187215079 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -1,4 +1,4 @@ -import { get, pickBy, forEach, defaultTo } from "lodash"; +import { get, forEach } from "lodash"; import { select } from "@wordpress/data"; import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; @@ -8,19 +8,18 @@ import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; * @returns {object} An object with taxonomies keys and their primary term id. */ const getPrimaryTerms = () => { - const wpseoScriptDataMetaData = get( window, "wpseoScriptData.metabox.metadata", {} ); + const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); const getPrimaryTermsStore = {}; - const primaryTerms = pickBy( wpseoScriptDataMetaData, ( value, key ) => key.startsWith( "primary_" ) ); forEach( primaryTerms, ( value, key ) => { - const taxonomy = key.replace( "primary_", "" ); - getPrimaryTermsStore[ `primary_${taxonomy}` ] = () => { - const termId = String( defaultTo( select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( taxonomy ), "" ) ); + getPrimaryTermsStore[ `primary_${key}` ] = () => { + const termId = select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( key ); if ( termId === "0" || termId === "-1" ) { return ""; } return termId; }; } ); + return getPrimaryTermsStore; }; diff --git a/packages/js/src/redux/selectors/primaryTaxonomies.js b/packages/js/src/redux/selectors/primaryTaxonomies.js index a5705d3c16e..256a22f1858 100644 --- a/packages/js/src/redux/selectors/primaryTaxonomies.js +++ b/packages/js/src/redux/selectors/primaryTaxonomies.js @@ -1,3 +1,4 @@ +import { get } from "lodash"; /** * Gets the primary taxonomy term id for the give taxonomy. * @@ -7,5 +8,5 @@ * @returns {number} Primary taxonomy term id. */ export function getPrimaryTaxonomyId( state, taxonomy ) { - return state.primaryTaxonomies[ taxonomy ]; + return get( state, `primaryTaxonomies.${taxonomy}`, "" ); } From c11a43350eec5c36c6272e1e43b8a0ab4e5500fe Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 14:28:25 +0200 Subject: [PATCH 231/344] changed post reducer --- packages/js/src/redux/reducers/index.js | 4 ++-- packages/js/src/redux/reducers/{postId.js => post.js} | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename packages/js/src/redux/reducers/{postId.js => post.js} (76%) diff --git a/packages/js/src/redux/reducers/index.js b/packages/js/src/redux/reducers/index.js index 316c170c224..96a174fb9ca 100644 --- a/packages/js/src/redux/reducers/index.js +++ b/packages/js/src/redux/reducers/index.js @@ -23,7 +23,7 @@ import focusKeyword from "./focusKeyword"; import isPremium from "./isPremium"; import marksButtonStatus from "./markerButtons"; import isMarkerPaused from "./markerPauseStatus"; -import postId from "./postId"; +import post from "./post"; import preferences from "./preferences"; import primaryTaxonomies from "./primaryTaxonomies"; import schemaTab from "./schemaTab"; @@ -57,7 +57,7 @@ export default { isPremium, [ LINK_PARAMS_NAME ]: linkParamsReducer, [ PLUGIN_URL_NAME ]: pluginUrlReducer, - postId, + post, marksButtonStatus, preferences, primaryTaxonomies, diff --git a/packages/js/src/redux/reducers/postId.js b/packages/js/src/redux/reducers/post.js similarity index 76% rename from packages/js/src/redux/reducers/postId.js rename to packages/js/src/redux/reducers/post.js index 408ea2911e9..67ca848daad 100644 --- a/packages/js/src/redux/reducers/postId.js +++ b/packages/js/src/redux/reducers/post.js @@ -8,12 +8,12 @@ import { SET_POST_ID } from "../actions/postId"; * * @returns {boolean} The state. */ -const postId = ( state = false, action ) => { +const post = ( state = false, action ) => { switch ( action.type ) { case SET_POST_ID: - return action.payload; + return { id: action.payload }; default: return state; } }; -export default postId; +export default post; From cd9be89c524fbd167469a79c16da13ba37725cc0 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 15:01:10 +0200 Subject: [PATCH 232/344] fix primary term initial state default --- packages/js/src/redux/initial-state/primaryTaxonomies.js | 2 +- packages/js/src/redux/selectors/primaryTaxonomies.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/initial-state/primaryTaxonomies.js b/packages/js/src/redux/initial-state/primaryTaxonomies.js index 00029480a82..08f2768a435 100644 --- a/packages/js/src/redux/initial-state/primaryTaxonomies.js +++ b/packages/js/src/redux/initial-state/primaryTaxonomies.js @@ -5,7 +5,7 @@ const primaryTaxonomies = {}; const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); forEach( primaryTerms, ( value, key ) => { - primaryTaxonomies[ key ] = value.primary; + primaryTaxonomies[ key ] = value.primary || -1; } ); export default primaryTaxonomies; diff --git a/packages/js/src/redux/selectors/primaryTaxonomies.js b/packages/js/src/redux/selectors/primaryTaxonomies.js index 256a22f1858..8fb5607b617 100644 --- a/packages/js/src/redux/selectors/primaryTaxonomies.js +++ b/packages/js/src/redux/selectors/primaryTaxonomies.js @@ -8,5 +8,5 @@ import { get } from "lodash"; * @returns {number} Primary taxonomy term id. */ export function getPrimaryTaxonomyId( state, taxonomy ) { - return get( state, `primaryTaxonomies.${taxonomy}`, "" ); + return get( state, `primaryTaxonomies.${taxonomy}`, -1 ); } From 8d35eca1d949420733ac67be6cf532c41279a10a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 15:16:11 +0200 Subject: [PATCH 233/344] restore selectors --- packages/js/src/redux/selectors/advancedSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/redux/selectors/advancedSettings.js b/packages/js/src/redux/selectors/advancedSettings.js index e89dae8a7d9..3409c285a7c 100644 --- a/packages/js/src/redux/selectors/advancedSettings.js +++ b/packages/js/src/redux/selectors/advancedSettings.js @@ -7,7 +7,7 @@ import { get } from "lodash"; * * @returns {String} Twitter title. */ -export const getNoIndex = state => get( state, "advancedSettings.noIndex", "0" ); +export const getNoIndex = state => get( state, "advancedSettings.noIndex", "" ); /** * Gets the twitter description from the state. @@ -16,7 +16,7 @@ export const getNoIndex = state => get( state, "advancedSettings.noIndex", "0" ) * * @returns {String} Twitter description. */ -export const getNoFollow = state => get( state, "advancedSettings.noFollow", "0" ); +export const getNoFollow = state => get( state, "advancedSettings.noFollow", "" ); /** * Gets the twitter image URL from the state. From b793070601473356c004f1f76ad103b50462366f Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Mon, 22 Apr 2024 15:16:32 +0200 Subject: [PATCH 234/344] convert to string the taxonomy id --- packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index e9187215079..f715918a82b 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -12,7 +12,7 @@ const getPrimaryTerms = () => { const getPrimaryTermsStore = {}; forEach( primaryTerms, ( value, key ) => { getPrimaryTermsStore[ `primary_${key}` ] = () => { - const termId = select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( key ); + const termId = String( select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( key ) ); if ( termId === "0" || termId === "-1" ) { return ""; } From 19ac603d9f603db2d6c39a44eea64962eb4d6a51 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:28:51 +0200 Subject: [PATCH 235/344] Update inc/class-wpseo-meta.php Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- inc/class-wpseo-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 75d3eabc3d0..a0a32b0ed1f 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -296,7 +296,7 @@ public static function init() { /** * Allow add-on plugins to register their meta fields for management by this class. - * Calls to add_filter() must be made before plugins_loaded prio 14, use in an initialzer class. + * Calls to add_filter() must be made before plugins_loaded priority 14. You could implement the Initializer_Interface (but the Integration_Interface is too late). */ $extra_fields = apply_filters( 'add_extra_wpseo_meta_fields', [] ); if ( is_array( $extra_fields ) ) { From 9cc93b278d36d86f55ce8c06de41623ca6196c56 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 16:31:29 +0200 Subject: [PATCH 236/344] changing visibility to private --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index ad29396b6ea..7c3ed31efb9 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -357,7 +357,7 @@ protected function get_post_meta_data() { * @param string $post_type The post type. * @return array The schema defaults. */ - public function get_schema_defaults( $post_type ) { + private function get_schema_defaults( $post_type ) { if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) && WPSEO_Options::get( 'disableadvanced_meta' ) ) { return []; } From bf9e8d57033afa6de5b86339d1689e743803e4fc Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 17:02:49 +0200 Subject: [PATCH 237/344] fix param type comment --- admin/taxonomy/class-taxonomy-fields-presenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index ad3555a7611..56fb7f0388a 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -29,7 +29,7 @@ public function __construct( $term ) { /** * Displaying the form fields. * - * @param array> $fields Array with the fields that will be displayed. + * @param array> $fields Array with the fields that will be displayed. * * @return string */ From e99cb9c58d46cf48913a4f1a65e7a381bd08c47e Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 17:16:42 +0200 Subject: [PATCH 238/344] php fix-cs --- admin/class-primary-term-admin.php | 4 ++-- composer.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 2f363385dc6..f5883adf3c1 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -5,7 +5,7 @@ * @package WPSEO\Admin */ - use Yoast\WP\SEO\Helpers\Primary_Term_Helper; +use Yoast\WP\SEO\Helpers\Primary_Term_Helper; /** * Adds the UI to change the primary term for a post. */ @@ -169,7 +169,7 @@ protected function get_primary_term_taxonomies( $post_id = null ) { } $primary_term_helper = new Primary_Term_Helper(); - $taxonomies = $primary_term_helper->get_primary_term_taxonomies( $post_id ); + $taxonomies = $primary_term_helper->get_primary_term_taxonomies( $post_id ); wp_cache_set( 'primary_term_taxonomies_' . $post_id, $taxonomies, 'wpseo' ); diff --git a/composer.json b/composer.json index f30491d780d..eda7027bb41 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2523", + "@putenv YOASTCS_THRESHOLD_ERRORS=2520", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From 4370e8e203572db29616389b68cd33ed1bca75a1 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 22 Apr 2024 17:20:53 +0200 Subject: [PATCH 239/344] php cs fix --- inc/class-wpseo-meta.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index a0a32b0ed1f..e096775962c 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -73,7 +73,7 @@ class WPSEO_Meta { * in the relevant child classes (WPSEO_Metabox and WPSEO_Social_admin) as they are only needed there. * - Beware: even though the meta keys are divided into subsets, they still have to be uniquely named!}} * - * @var array>> + * @var array>> * Array format: * (required) 'type' => (string) field type. i.e. text / textarea / checkbox / * radio / select / multiselect / upload etc. @@ -240,7 +240,7 @@ class WPSEO_Meta { * ['subset'] => (string) primary index * ['key'] => (string) internal key * - * @var array> + * @var array> */ public static $fields_index = []; From 6d0dc0174374e4a6de448ec19e0397610e0ece1b Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 23 Apr 2024 10:10:34 +0200 Subject: [PATCH 240/344] php fix cs --- admin/class-primary-term-admin.php | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index f5883adf3c1..dbc473aba1a 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -68,7 +68,7 @@ protected function primary_term_field( $taxonomy_name ) { return sprintf( '', esc_attr( $this->generate_field_id( $taxonomy_name ) ), - esc_attr( $this->generate_field_name( $taxonomy_name ) ), + esc_attr( $this->generate_field_name( $taxonomy_name ) ) ); } diff --git a/composer.json b/composer.json index eda7027bb41..9cd7226a7b2 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2520", + "@putenv YOASTCS_THRESHOLD_ERRORS=2519", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From 090bab80c875f3ba5429a595ce66b1c1fc560c23 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 23 Apr 2024 10:12:25 +0200 Subject: [PATCH 241/344] fix php cs threshold --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9cd7226a7b2..a98a229a138 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2519", + "@putenv YOASTCS_THRESHOLD_ERRORS=2518", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From 68c7346d70d6d2b0764babac2620b1fa22a0c05c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Tue, 23 Apr 2024 10:41:03 +0200 Subject: [PATCH 242/344] fix js tests --- .../fields/analysisFieldsStore.test.js | 4 -- .../helpers/fields/getPrimaryTerms.test.js | 42 ++++++++---- .../fields/getValuesFromStoreToSync.test.js | 65 ------------------- .../helpers/fields/hiddenFieldsSync.test.js | 6 +- 4 files changed, 35 insertions(+), 82 deletions(-) diff --git a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js index 9d32555f290..23e460661e1 100644 --- a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js +++ b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js @@ -90,8 +90,6 @@ describe.each( testCasesScoresUndefined )( "$method", ( { method, getFunction, r const boolenaTestCases = [ { value: true, expected: "1" }, { value: false, expected: "0" }, - { value: null, expected: "0" }, - { value: undefined, expected: "0" }, ]; describe.each( boolenaTestCases )( "isCornerstoneContent", ( { value, expected } ) => { it( `should return ${expected} from isCornerstoneContent when value is ${value}`, () => { @@ -110,8 +108,6 @@ describe.each( boolenaTestCases )( "isCornerstoneContent", ( { value, expected } const focusKeyphraseTestCases = [ { value: "test", expected: "test" }, - { value: null, expected: "" }, - { value: undefined, expected: "" }, ]; describe.each( focusKeyphraseTestCases )( "getFocusKeyphrase", ( { value, expected } ) => { diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index d243b2f4d13..314ff25d6af 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -24,19 +24,10 @@ const testCases = [ { termId: 1, expected: "1" }, { termId: -1, expected: "" }, { termId: 0, expected: "" }, - { termId: null, expected: "" }, - { termId: undefined, expected: "" }, ]; describe.each( testCases )( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", ( { termId, expected } ) => { it( `should returns ${expected ? expected : "empty string"} when the primary term id is ${termId}`, () => { - const wpseoScriptDataMetaData = { - // eslint-disable-next-line camelcase - primary_category: 1, - // eslint-disable-next-line camelcase - primary_post_tag: 2, - }; - const getPrimaryTaxonomyId = jest.fn(); getPrimaryTaxonomyId.mockReturnValue( termId ); @@ -51,9 +42,36 @@ describe.each( testCases )( "getPrimaryTerm - should returns an object with taxo windowSpy.mockImplementation( () => ( { - wpseoScriptData: { - metabox: { - metadata: wpseoScriptDataMetaData, + wpseoPrimaryCategoryL10n: { + taxonomies: { + category: { + title: "Category", + name: "category", + primary: 1, + singularLabel: "Category", + fieldId: "yoast_wpseo_primary_category", + restBase: "categories", + terms: [ + { + id: 1, + name: "Uncategorized", + }, + ], + }, + post_tag: { + title: "Post tag", + name: "post_tag", + primary: 5, + singularLabel: "Tag", + fieldId: "yoast_wpseo_primary_post_tag", + restBase: "tags", + terms: [ + { + id: 5, + name: "Test Tag", + }, + ], + }, }, }, } diff --git a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js index 879fe5cf4f1..35e6b217e22 100644 --- a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js +++ b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js @@ -80,71 +80,6 @@ describe.each( testCases )( "$method", ( { method, getFunction } ) => { } ); -describe.each( testCases )( "$method", ( { method, getFunction } ) => { - it( `should return empty string from ${method} when null`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => null, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "" ); - } ); -} ); - -describe.each( testCases )( "$method", ( { method, getFunction } ) => { - it( `should return empty string from ${method} when undefined`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => undefined, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "" ); - } ); -} ); - -const testCasesWithDefaultZero = [ - { method: "getNoIndex", getFunction: getNoIndex }, - { method: "getNoFollow", getFunction: getNoFollow }, -]; - -describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { - it( `should return zero string from ${method} when null`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => null, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "0" ); - } ); -} ); - -describe.each( testCasesWithDefaultZero )( "$method", ( { method, getFunction } ) => { - it( `should return zero string from ${method} when null`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => undefined, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "0" ); - } ); -} ); - describe( "getWordProofTimestamp", () => { it( "should return '1' when true", () => { select.mockImplementation( ( store ) => { diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index 21d0f10fc32..141747c1d8c 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,7 +1,7 @@ import { hiddenFieldsSync } from "../../../src/helpers/fields/hiddenFieldsSync"; import { createCollectorFromObject, createWatcher } from "../../../src/helpers/create-watcher"; import { mapKeys, debounce } from "lodash"; -import { subscribe } from "@wordpress/data"; +import { subscribe, select } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { select: jest.fn(), @@ -25,6 +25,10 @@ jest.mock( "../../../src/helpers/create-watcher", () => ( { describe( "hiddenFieldsSync", () => { it( "should subscribe to changes, debounce, create watcher and createCollectorFromObject", () => { + select.mockImplementation( () => ( { + getIsPost: jest.fn( () => "1" ), + } ) ); + hiddenFieldsSync(); expect( subscribe ).toHaveBeenCalled(); From ae39ad4800679d7f9974a907f662036675ed3418 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 23 Apr 2024 14:33:00 +0200 Subject: [PATCH 243/344] cleanup side effect from primary taxonomy picker --- packages/js/src/components/PrimaryTaxonomyPicker.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/js/src/components/PrimaryTaxonomyPicker.js b/packages/js/src/components/PrimaryTaxonomyPicker.js index 197be3f75d1..a4343373866 100644 --- a/packages/js/src/components/PrimaryTaxonomyPicker.js +++ b/packages/js/src/components/PrimaryTaxonomyPicker.js @@ -29,10 +29,6 @@ class PrimaryTaxonomyPicker extends Component { this.onChange = this.onChange.bind( this ); this.updateReplacementVariable = this.updateReplacementVariable.bind( this ); - const { fieldId } = props.taxonomy; - - this.input = document.getElementById( fieldId ); - this.state = { selectedTerms: [], terms: [], @@ -187,10 +183,6 @@ class PrimaryTaxonomyPicker extends Component { this.updateReplacementVariable( termId ); this.props.setPrimaryTaxonomyId( name, termId ); - - if ( this.input ) { - this.input.value = termId === -1 ? "" : String( termId ); - } } /** From 1ddd210e8cff1c31688d39651ff89033a9da9fb3 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 23 Apr 2024 14:50:15 +0200 Subject: [PATCH 244/344] add the comment from the post scrapper --- packages/js/src/initializers/post-scraper.js | 3 +-- packages/js/src/redux/initial-state/index.js | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index 990be24f0cd..d56b66d63d8 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -237,6 +237,7 @@ export default function initPostScraper( $, store, editorData ) { elementTarget: [ tinyMCEHelper.tmceId, "yoast_wpseo_focuskw_text_input", + "yoast_wpseo_metadesc", "excerpt", "editable-post-name", "editable-post-name-full", @@ -519,8 +520,6 @@ export default function initPostScraper( $, store, editorData ) { // Set the initial snippet editor data. store.dispatch( updateData( snippetEditorData ) ); - // This used to be a checkbox, then became a hidden input. For consistency, we set the value to '1'. - store.dispatch( setCornerstoneContent( get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1" ) ); // Save the keyword, in order to compare it to store changes. let focusKeyword = store.getState().focusKeyword; diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index 851a3e2a5f1..a85d2f489df 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -10,6 +10,7 @@ const initialState = { twitterEditor: twitterInitialState, advancedSettings: advancedSettingsInitialState, focusKeyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), + // This used to be a checkbox, then became a hidden input. For consistency, we set the value to '1'. isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", primaryTaxonomies, schemaTab, From 9e9a10c75e60d37b81a4f42b53462f42b8b863e4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 23 Apr 2024 14:50:48 +0200 Subject: [PATCH 245/344] add sync to meta description and title --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index f662a71e472..f10e3c2fc4f 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -10,6 +10,7 @@ import { getPageType, getArticleType } from "./schemaFieldsStore"; import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; +import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; /** * Prepare twitter title to be saved in hidden field. @@ -110,6 +111,8 @@ export const hiddenFieldsSync = () => { canonical: getCanonical, wordProofTimestamp: getWordProofTimestamp, readingTime: getEstimatedReadingTime, + seoTitle: getSeoTitle, + seoDescription: getSeoDescription, }, ( value, key ) => prefix + META_KEYS[ key ] ); return subscribe( debounce( createWatcher( From ff086113e425b28ee605ea4efb66b94279e015b8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 23 Apr 2024 14:57:24 +0200 Subject: [PATCH 246/344] removed "yoast_wpseo_metadesc", because it's hidden field. I added a refresh app method to the subscribe --- packages/js/src/initializers/post-scraper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index d56b66d63d8..ed724d90c49 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -237,7 +237,6 @@ export default function initPostScraper( $, store, editorData ) { elementTarget: [ tinyMCEHelper.tmceId, "yoast_wpseo_focuskw_text_input", - "yoast_wpseo_metadesc", "excerpt", "editable-post-name", "editable-post-name-full", From 63830a6d7377de9c459cd717ed0244fad555c21e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 23 Apr 2024 17:57:00 +0200 Subject: [PATCH 247/344] add sanitization for primary terms, wordproof time stamp and estimated reading time --- composer.json | 2 +- inc/class-wpseo-meta.php | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index a98a229a138..4bd28f66e3c 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2518", + "@putenv YOASTCS_THRESHOLD_ERRORS=2517", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index e096775962c..2338598234a 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -459,8 +459,8 @@ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { /** * Validate the post meta values. * - * @param mixed $meta_value The new value. - * @param string $meta_key The full meta key (including prefix). + * @param string|int|bool $meta_value The new value. + * @param string $meta_key The full meta key (including prefix). * * @return string Validated meta value. */ @@ -469,12 +469,27 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = self::$defaults[ $meta_key ]; switch ( true ) { + case ( $meta_key === self::$meta_prefix . 'estimated-reading-time-minutes' ): case ( $meta_key === self::$meta_prefix . 'linkdex' ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int >= 0 ) { $clean = strval( $int ); // Convert to string to make sure default check works. } break; + // Primary term ids are always integers. + case ( strpos( $meta_key, self::$meta_prefix . 'primary' ) === 0 ): + $int = WPSEO_Utils::validate_int( $meta_value ); + if ( $int !== false && $int > 0 ) { + $clean = strval( $int ); + } + break; + + case ( $meta_key === self::$meta_prefix . 'wordproof_timestamp' ): + $sanitized_timestamp = filter_var( $meta_value, FILTER_SANITIZE_NUMBER_INT ); + if ( $sanitized_timestamp !== false && $sanitized_timestamp > 0 ) { + $clean = $meta_value; + } + break; case ( $field_def['type'] === 'checkbox' ): // Only allow value if it's one of the predefined options. From 1bc3a1a8000c84ecf2b14ad441023ad4e266d413 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 09:51:21 +0200 Subject: [PATCH 248/344] add sanitization to other values that are numerical --- inc/class-wpseo-meta.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 2338598234a..6348e2f1c81 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -469,6 +469,8 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = self::$defaults[ $meta_key ]; switch ( true ) { + case ( $meta_key === self::$meta_prefix . 'inclusive_language_score' ): + case ( $meta_key === self::$meta_prefix . 'content_score' ): case ( $meta_key === self::$meta_prefix . 'estimated-reading-time-minutes' ): case ( $meta_key === self::$meta_prefix . 'linkdex' ): $int = WPSEO_Utils::validate_int( $meta_value ); @@ -476,7 +478,8 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { $clean = strval( $int ); // Convert to string to make sure default check works. } break; - // Primary term ids are always integers. + // Ids are always integers that are greater then 0. + case ( strpos( $meta_key, 'image-id' ) !== false ): case ( strpos( $meta_key, self::$meta_prefix . 'primary' ) === 0 ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int > 0 ) { @@ -484,13 +487,6 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { } break; - case ( $meta_key === self::$meta_prefix . 'wordproof_timestamp' ): - $sanitized_timestamp = filter_var( $meta_value, FILTER_SANITIZE_NUMBER_INT ); - if ( $sanitized_timestamp !== false && $sanitized_timestamp > 0 ) { - $clean = $meta_value; - } - break; - case ( $field_def['type'] === 'checkbox' ): // Only allow value if it's one of the predefined options. if ( in_array( $meta_value, [ 'on', 'off' ], true ) ) { From f7f246eabf23e498719d2928f298c489c422fad5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 12:04:12 +0200 Subject: [PATCH 249/344] add metadata group class --- .../class-post-metabox-formatter.php | 25 +- .../class-term-metabox-formatter.php | 21 +- admin/metabox/class-metabox.php | 16 +- admin/taxonomy/class-taxonomy-metabox.php | 14 +- src/editors/framework/metadata-groups.php | 93 +++++++ .../Framework/Metadata_Groups_Test.php | 239 ++++++++++++++++++ 6 files changed, 361 insertions(+), 47 deletions(-) create mode 100644 src/editors/framework/metadata-groups.php create mode 100644 tests/Unit/Editors/Framework/Metadata_Groups_Test.php diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 7c3ed31efb9..9b0630f6190 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -6,6 +6,7 @@ */ use Yoast\WP\SEO\Config\Schema_Types; +use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; use Yoast\WP\SEO\Helpers\Schema\Article_Helper; /** * This class provides data for the post metabox by return its values for localization. @@ -38,6 +39,7 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface * * @param WP_Post $post Post object. * @param array $options Title options to use. + * * @param string $structure The permalink to follow. */ public function __construct( $post, array $options, $structure ) { @@ -327,25 +329,16 @@ protected function is_insights_enabled() { protected function get_post_meta_data() { $post_type = $this->post->post_type; $meta_data = []; - $fields = []; - - $social_is_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); - $is_advanced_metadata_enabled = WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false; - $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'general', $post_type ) ); - - if ( $is_advanced_metadata_enabled ) { - $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'advanced', $post_type ) ); - } + $metadata_groups = YoastSEO()->classes->get( Metadata_Groups::class ); - $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'schema', $post_type ) ); + $groups = $metadata_groups->get_post_metadata_groups(); - if ( $social_is_enabled ) { - $fields = array_merge( $fields, WPSEO_Meta::get_meta_field_defs( 'social', $post_type ) ); - } - - foreach ( $fields as $key => $meta_field ) { - $meta_data[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); + foreach ( $groups as $group ) { + $fields = WPSEO_Meta::get_meta_field_defs( $group, $post_type ); + foreach ( $fields as $key => $meta_field ) { + $meta_data[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); + } } return $meta_data; diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 96fb2fb9bf3..db856415643 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -4,7 +4,7 @@ * * @package WPSEO\Admin\Formatter */ - +use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; /** * This class provides data for the term metabox by return its values for localization. */ @@ -99,24 +99,17 @@ public function get_values() { * @return array */ protected function get_term_metadata() { - $metadata = []; - + $metadata = []; $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); $field_definitions = new WPSEO_Taxonomy_Fields(); - $is_social_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); $meta_prefix = 'wpseo_'; - foreach ( $field_definitions->get( 'content' ) as $key => $field ) { - $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); - } - if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { - foreach ( $field_definitions->get( 'settings' ) as $key => $field ) { - $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); - } - } + $metadata_groups = YoastSEO()->classes->get( Metadata_Groups::class ); + + $groups = $metadata_groups->get_term_metadata_groups(); - if ( $is_social_enabled ) { - foreach ( $field_definitions->get( 'social' ) as $key => $field ) { + foreach ( $groups as $group ) { + foreach ( $field_definitions->get( $group ) as $key => $field ) { $metadata[ $key ] = $fields_presenter->get_field_value( $meta_prefix . $key ); } } diff --git a/admin/metabox/class-metabox.php b/admin/metabox/class-metabox.php index 9316bf3e39d..c5ce6607fa4 100644 --- a/admin/metabox/class-metabox.php +++ b/admin/metabox/class-metabox.php @@ -9,6 +9,7 @@ use Yoast\WP\SEO\Conditionals\Third_Party\Jetpack_Boost_Active_Conditional; use Yoast\WP\SEO\Conditionals\Third_Party\Jetpack_Boost_Not_Premium_Conditional; use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional; +use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; use Yoast\WP\SEO\Introductions\Infrastructure\Wistia_Embed_Permission_Repository; use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter; use Yoast\WP\SEO\Presenters\Admin\Meta_Fields_Presenter; @@ -351,20 +352,13 @@ public function meta_box() { protected function render_hidden_fields() { wp_nonce_field( 'yoast_free_metabox', 'yoast_free_metabox_nonce' ); - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'general' ); + $metadata_groups = YoastSEO()->classes->get( Metadata_Groups::class ); - if ( $this->is_advanced_metadata_enabled ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'advanced' ); - } + $groups = $metadata_groups->get_post_metadata_groups(); - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'schema', $this->get_metabox_post()->post_type ); - - if ( $this->social_is_enabled ) { + foreach ( $groups as $group ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'social' ); + echo new Meta_Fields_Presenter( $this->get_metabox_post(), $group, $this->get_metabox_post()->post_type ); } /** diff --git a/admin/taxonomy/class-taxonomy-metabox.php b/admin/taxonomy/class-taxonomy-metabox.php index d7b1fff69be..ee313ba037f 100644 --- a/admin/taxonomy/class-taxonomy-metabox.php +++ b/admin/taxonomy/class-taxonomy-metabox.php @@ -5,6 +5,8 @@ * @package WPSEO\Admin */ +use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; + /** * This class generates the metabox on the edit term page. */ @@ -96,13 +98,13 @@ protected function render_hidden_fields() { $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); $field_definitions = new WPSEO_Taxonomy_Fields(); - echo $fields_presenter->html( $field_definitions->get( 'content' ) ); - if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { - echo $fields_presenter->html( $field_definitions->get( 'settings' ) ); - } + $metadata_groups = YoastSEO()->classes->get( Metadata_Groups::class ); - if ( $this->is_social_enabled ) { - echo $fields_presenter->html( $field_definitions->get( 'social' ) ); + $groups = $metadata_groups->get_term_metadata_groups(); + + foreach ( $groups as $group ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo $fields_presenter->html( $field_definitions->get( $group ) ); } } diff --git a/src/editors/framework/metadata-groups.php b/src/editors/framework/metadata-groups.php new file mode 100644 index 00000000000..e680d70898e --- /dev/null +++ b/src/editors/framework/metadata-groups.php @@ -0,0 +1,93 @@ +options_helper = $options_helper; + $this->capability_helper = $capability_helper; + $this->is_social_enabled = $this->options_helper->get( 'opengraph', false ) || $this->options_helper->get( 'twitter', false ); + $this->is_advanced_enabled = $this->capability_helper->current_user_can( 'wpseo_edit_advanced_metadata' ) || $this->options_helper->get( 'disableadvanced_meta' ) === false; + } + + /** + * Get list of groups of metadata for a post editor. + * + * @return array List of metadata groups. + */ + public function get_post_metadata_groups(): array { + $groups = [ 'general', 'schema' ]; + + if ( $this->is_advanced_enabled ) { + $groups[] = 'advanced'; + } + + if ( $this->is_social_enabled ) { + $groups[] = 'social'; + } + + return $groups; + } + + /** + * Get term metadata groups. + * + * @return array List of metadata groups. + */ + public function get_term_metadata_groups(): array { + $groups = [ 'content' ]; + + if ( $this->is_advanced_enabled ) { + $groups[] = 'settings'; + } + + if ( $this->is_social_enabled ) { + $groups[] = 'social'; + } + + return $groups; + } +} diff --git a/tests/Unit/Editors/Framework/Metadata_Groups_Test.php b/tests/Unit/Editors/Framework/Metadata_Groups_Test.php new file mode 100644 index 00000000000..393758151a2 --- /dev/null +++ b/tests/Unit/Editors/Framework/Metadata_Groups_Test.php @@ -0,0 +1,239 @@ +options_helper = Mockery::mock( Options_Helper::class ); + $this->capability_helper = Mockery::mock( Capability_Helper::class ); + } + + /** + * Data provider for test_get_post_metadata_groups. + * + * @return array> + */ + public static function data_provider_get_post_metadata_groups(): array { + return [ + 'opengraph_enabled' => [ + 'opengraph_enabled' => true, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'general', 'schema', 'advanced', 'social' ], + ], + 'opengraph_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'general', 'schema', 'advanced' ], + ], + 'twitter_enabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => true, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'general', 'schema', 'advanced', 'social' ], + ], + 'twitter_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => true, + 'expected' => [ 'general', 'schema', 'advanced' ], + ], + 'advanced_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => true, + 'user_can_edit' => false, + 'expected' => [ 'general', 'schema' ], + ], + 'user_cannot_edit' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => true, + 'user_can_edit' => true, + 'expected' => [ 'general', 'schema', 'advanced' ], + ], + ]; + } + + /** + * Tests the get_post_metadata_groups method. + * + * @covers ::get_post_metadata_groups + * @dataProvider data_provider_get_post_metadata_groups + * + * @param bool $opengraph_enabled Whether opengraph is enabled. + * @param bool $twitter_enabled Whether twitter is enabled. + * @param bool $advanced_enabled Whether advanced is enabled. + * @param bool $user_can_edit Whether the user can edit. + * @param array $expected The expected result. + * @return void + */ + public function test_get_post_metadata_groups( $opengraph_enabled, $twitter_enabled, $advanced_enabled, $user_can_edit, $expected ): void { + + $this->options_helper->expects( 'get' ) + ->with( 'opengraph', false ) + ->andReturn( $opengraph_enabled ); + + $twitter_times = ( $opengraph_enabled ) ? 0 : 1; + + $this->options_helper->expects( 'get' ) + ->with( 'twitter', false ) + ->times( $twitter_times ) + ->andReturn( $twitter_enabled ); + + $this->capability_helper->expects( 'current_user_can' ) + ->with( 'wpseo_edit_advanced_metadata' ) + ->andReturn( $user_can_edit ); + + $advanced_enabled_times = ( $user_can_edit ) ? 0 : 1; + + $this->options_helper->expects( 'get' ) + ->with( 'disableadvanced_meta' ) + ->times( $advanced_enabled_times ) + ->andReturn( $advanced_enabled ); + + $instance = new Metadata_Groups( $this->options_helper, $this->capability_helper ); + + $this->assertSame( $expected, $instance->get_post_metadata_groups() ); + } + + /** + * Data provider for test_get_term_metadata_groups. + * + * @return array> + */ + public static function data_provider_get_term_metadata_groups() { + return [ + 'opengraph_enabled' => [ + 'opengraph_enabled' => true, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'content', 'settings', 'social' ], + ], + 'opengraph_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'content', 'settings' ], + ], + 'twitter_enabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => true, + 'advanced_enabled' => false, + 'user_can_edit' => false, + 'expected' => [ 'content', 'settings', 'social' ], + ], + 'twitter_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => false, + 'user_can_edit' => true, + 'expected' => [ 'content', 'settings' ], + ], + 'advanced_disabled' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => true, + 'user_can_edit' => false, + 'expected' => [ 'content' ], + ], + 'user_cannot_edit' => [ + 'opengraph_enabled' => false, + 'twitter_enabled' => false, + 'advanced_enabled' => true, + 'user_can_edit' => true, + 'expected' => [ 'content', 'settings' ], + ], + ]; + } + + /** + * Tests the get_term_metadata_groups method. + * + * @covers ::get_term_metadata_groups + * + * @dataProvider data_provider_get_term_metadata_groups + * + * @param bool $opengraph_enabled Whether opengraph is enabled. + * @param bool $twitter_enabled Whether twitter is enabled. + * @param bool $advanced_enabled Whether advanced is enabled. + * @param bool $user_can_edit Whether the user can edit. + * @param array $expected The expected result. + * @return void + */ + public function test_get_term_metadata_groups( $opengraph_enabled, $twitter_enabled, $advanced_enabled, $user_can_edit, $expected ) { + $this->options_helper->expects( 'get' ) + ->with( 'opengraph', false ) + ->andReturn( $opengraph_enabled ); + + $twitter_times = ( $opengraph_enabled ) ? 0 : 1; + + $this->options_helper->expects( 'get' ) + ->with( 'twitter', false ) + ->times( $twitter_times ) + ->andReturn( $twitter_enabled ); + + $this->capability_helper->expects( 'current_user_can' ) + ->with( 'wpseo_edit_advanced_metadata' ) + ->andReturn( $user_can_edit ); + + $advanced_enabled_times = ( $user_can_edit ) ? 0 : 1; + + $this->options_helper->expects( 'get' ) + ->with( 'disableadvanced_meta' ) + ->times( $advanced_enabled_times ) + ->andReturn( $advanced_enabled ); + + $instance = new Metadata_Groups( $this->options_helper, $this->capability_helper ); + + $this->assertSame( $expected, $instance->get_term_metadata_groups() ); + } +} From 71f977f0e7c7bd7aee68c460cc81c16eb0856af1 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 12:07:41 +0200 Subject: [PATCH 250/344] update thresholds --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4bd28f66e3c..7bbfe99a77b 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2517", + "@putenv YOASTCS_THRESHOLD_ERRORS=2515", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From af660e2fa999ba0456328a26bd223672760af10a Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 13:27:38 +0200 Subject: [PATCH 251/344] no other logic should be in the construct --- src/editors/framework/metadata-groups.php | 46 ++++++++++--------- .../Framework/Metadata_Groups_Test.php | 5 ++ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/editors/framework/metadata-groups.php b/src/editors/framework/metadata-groups.php index e680d70898e..9412c27a69d 100644 --- a/src/editors/framework/metadata-groups.php +++ b/src/editors/framework/metadata-groups.php @@ -26,20 +26,6 @@ class Metadata_Groups { */ protected $capability_helper; - /** - * Social is enabled. - * - * @var bool - */ - protected $is_social_enabled; - - /** - * Should show advanced settings. - * - * @var bool - */ - protected $is_advanced_enabled; - /** * Integrations_Action constructor. * @@ -47,10 +33,8 @@ class Metadata_Groups { * @param Capability_Helper $capability_helper The capability helper. */ public function __construct( Options_Helper $options_helper, Capability_Helper $capability_helper ) { - $this->options_helper = $options_helper; - $this->capability_helper = $capability_helper; - $this->is_social_enabled = $this->options_helper->get( 'opengraph', false ) || $this->options_helper->get( 'twitter', false ); - $this->is_advanced_enabled = $this->capability_helper->current_user_can( 'wpseo_edit_advanced_metadata' ) || $this->options_helper->get( 'disableadvanced_meta' ) === false; + $this->options_helper = $options_helper; + $this->capability_helper = $capability_helper; } /** @@ -61,11 +45,11 @@ public function __construct( Options_Helper $options_helper, Capability_Helper $ public function get_post_metadata_groups(): array { $groups = [ 'general', 'schema' ]; - if ( $this->is_advanced_enabled ) { + if ( $this->is_advanced_enabled() ) { $groups[] = 'advanced'; } - if ( $this->is_social_enabled ) { + if ( $this->is_social_enabled() ) { $groups[] = 'social'; } @@ -80,14 +64,32 @@ public function get_post_metadata_groups(): array { public function get_term_metadata_groups(): array { $groups = [ 'content' ]; - if ( $this->is_advanced_enabled ) { + if ( $this->is_advanced_enabled() ) { $groups[] = 'settings'; } - if ( $this->is_social_enabled ) { + if ( $this->is_social_enabled() ) { $groups[] = 'social'; } return $groups; } + + /** + * Get is social enabled. + * + * @return bool + */ + public function is_social_enabled(): bool { + return $this->options_helper->get( 'opengraph', false ) || $this->options_helper->get( 'twitter', false ); + } + + /** + * Get is advanced enabled. + * + * @return bool + */ + public function is_advanced_enabled(): bool { + return $this->capability_helper->current_user_can( 'wpseo_edit_advanced_metadata' ) || $this->options_helper->get( 'disableadvanced_meta' ) === false; + } } diff --git a/tests/Unit/Editors/Framework/Metadata_Groups_Test.php b/tests/Unit/Editors/Framework/Metadata_Groups_Test.php index 393758151a2..ba6a0aa19cd 100644 --- a/tests/Unit/Editors/Framework/Metadata_Groups_Test.php +++ b/tests/Unit/Editors/Framework/Metadata_Groups_Test.php @@ -105,6 +105,9 @@ public static function data_provider_get_post_metadata_groups(): array { * Tests the get_post_metadata_groups method. * * @covers ::get_post_metadata_groups + * @covers ::is_advanced_enabled + * @covers ::is_social_enabled + * * @dataProvider data_provider_get_post_metadata_groups * * @param bool $opengraph_enabled Whether opengraph is enabled. @@ -199,6 +202,8 @@ public static function data_provider_get_term_metadata_groups() { * Tests the get_term_metadata_groups method. * * @covers ::get_term_metadata_groups + * @covers ::is_advanced_enabled + * @covers ::is_social_enabled * * @dataProvider data_provider_get_term_metadata_groups * From 4f0946110169610d6fb6f7e6445a35bcf216a5e1 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 13:27:49 +0200 Subject: [PATCH 252/344] removed class without tests --- tests/Unit/Admin/User_Profile_Test.php | 35 -------------------------- 1 file changed, 35 deletions(-) delete mode 100644 tests/Unit/Admin/User_Profile_Test.php diff --git a/tests/Unit/Admin/User_Profile_Test.php b/tests/Unit/Admin/User_Profile_Test.php deleted file mode 100644 index 9f70d799c26..00000000000 --- a/tests/Unit/Admin/User_Profile_Test.php +++ /dev/null @@ -1,35 +0,0 @@ -instance = new WPSEO_Admin_User_Profile(); - } -} From 78901b6c3fa19bcb029b8d29add66cec4ce27854 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 13:30:09 +0200 Subject: [PATCH 253/344] fix thresholds --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7bbfe99a77b..05a45e18038 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2515", + "@putenv YOASTCS_THRESHOLD_ERRORS=2514", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], From e5f35365cd7d8dfad24e6a2c6684dc3abc05d619 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 13:52:52 +0200 Subject: [PATCH 254/344] use metadata groups class in elementor --- src/integrations/third-party/elementor.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/integrations/third-party/elementor.php b/src/integrations/third-party/elementor.php index d024dd3529b..ed5fb2d2d88 100644 --- a/src/integrations/third-party/elementor.php +++ b/src/integrations/third-party/elementor.php @@ -21,6 +21,7 @@ use Yoast\WP\SEO\Actions\Alert_Dismissal_Action; use Yoast\WP\SEO\Conditionals\Third_Party\Elementor_Edit_Conditional; use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional; +use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Helpers\Options_Helper; use Yoast\WP\SEO\Integrations\Integration_Interface; @@ -507,20 +508,14 @@ protected function render_hidden_fields() { ); \wp_nonce_field( 'wpseo_elementor_save', '_wpseo_elementor_nonce' ); - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'general' ); - if ( $this->is_advanced_metadata_enabled ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'advanced' ); - } + $metadata_groups = \YoastSEO()->classes->get( Metadata_Groups::class ); - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'schema', $this->get_metabox_post()->post_type ); + $groups = $metadata_groups->get_post_metadata_groups(); - if ( $this->social_is_enabled ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. - echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'social' ); + foreach ( $groups as $group ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), $group, $this->get_metabox_post()->post_type ); } \printf( From 46b899715212c640d17934e48bd6be65e8164244 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 24 Apr 2024 14:14:53 +0200 Subject: [PATCH 255/344] refined the sanitisation of id's to be more precise --- inc/class-wpseo-meta.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 6348e2f1c81..2d1a28bd4cb 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -479,8 +479,9 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { } break; // Ids are always integers that are greater then 0. - case ( strpos( $meta_key, 'image-id' ) !== false ): - case ( strpos( $meta_key, self::$meta_prefix . 'primary' ) === 0 ): + case ( $meta_key === self::$meta_prefix . 'opengraph-image-id' ): + case ( $meta_key === self::$meta_prefix . 'twitter-image-id' ): + case ( strpos( $meta_key, self::$meta_prefix . 'primary_' ) === 0 ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int > 0 ) { $clean = strval( $int ); From f33dcd376edbb4331827510ef03e6576b99eccd4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 13:43:11 +0200 Subject: [PATCH 256/344] refactor mapping and added initial state --- .../class-taxonomy-fields-presenter.php | 2 +- packages/js/src/analysis/PostDataCollector.js | 6 +- packages/js/src/components/SchemaTab.js | 12 +- .../components/fills/ElementorFill.js | 18 +-- .../src/elementor/containers/ElementorFill.js | 11 +- .../src/elementor/containers/SnippetEditor.js | 21 +-- .../elementor/initializers/editor-store.js | 3 - .../elementor/redux/actions/snippetEditor.js | 70 ---------- .../helpers/fields/SearchMetadataFields.js | 91 ------------ .../src/helpers/fields/advancedFieldsStore.js | 58 -------- .../src/helpers/fields/analysisFieldsStore.js | 45 ------ .../js/src/helpers/fields/blockEditorSync.js | 62 +++------ packages/js/src/helpers/fields/constants.js | 38 ------ .../src/helpers/fields/facebookFieldsStore.js | 27 ---- .../js/src/helpers/fields/hiddenFieldsSync.js | 113 ++++----------- packages/js/src/helpers/fields/index.js | 9 +- .../fields/primaryTaxonomiesFieldsStore.js | 23 +--- .../src/helpers/fields/schemaFieldsStore.js | 16 --- .../fields/snippetEditorFieldsStore.js | 16 --- .../helpers/fields/transform-meta-value.js | 36 +++++ .../src/helpers/fields/twitterFieldsStore.js | 31 ----- .../js/src/redux/actions/snippetEditor.js | 1 - .../js/src/redux/initial-state/analysis.js | 16 +++ packages/js/src/redux/initial-state/index.js | 15 +- .../js/src/redux/initial-state/schemaTab.js | 4 +- .../src/redux/initial-state/snippetEditor.js | 54 ++++++++ .../js/src/redux/reducers/snippetEditor.js | 18 --- .../js/src/redux/selectors/facebookEditor.js | 49 +++++++ packages/js/src/redux/selectors/results.js | 33 +++++ .../js/src/redux/selectors/snippetEditor.js | 9 -- .../js/src/redux/selectors/twitterEditor.js | 27 +++- .../js/src/shared-admin/constants/index.js | 21 ++- .../src/shared-admin/constants/meta-fields.js | 129 ++++++++++++++++++ .../fields/analysisFieldsStore.test.js | 126 ----------------- .../helpers/fields/getPrimaryTerms.test.js | 12 +- .../fields/getValuesFromStoreToSync.test.js | 119 ---------------- .../admin/meta-fields-presenter.php | 3 +- 37 files changed, 444 insertions(+), 900 deletions(-) delete mode 100644 packages/js/src/elementor/redux/actions/snippetEditor.js delete mode 100644 packages/js/src/helpers/fields/SearchMetadataFields.js delete mode 100644 packages/js/src/helpers/fields/advancedFieldsStore.js delete mode 100644 packages/js/src/helpers/fields/analysisFieldsStore.js delete mode 100644 packages/js/src/helpers/fields/constants.js delete mode 100644 packages/js/src/helpers/fields/facebookFieldsStore.js delete mode 100644 packages/js/src/helpers/fields/schemaFieldsStore.js delete mode 100644 packages/js/src/helpers/fields/snippetEditorFieldsStore.js create mode 100644 packages/js/src/helpers/fields/transform-meta-value.js delete mode 100644 packages/js/src/helpers/fields/twitterFieldsStore.js create mode 100644 packages/js/src/redux/initial-state/analysis.js create mode 100644 packages/js/src/redux/initial-state/snippetEditor.js create mode 100644 packages/js/src/shared-admin/constants/meta-fields.js delete mode 100644 packages/js/tests/helpers/fields/analysisFieldsStore.test.js delete mode 100644 packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index 56fb7f0388a..c26ccbef00d 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -149,7 +149,7 @@ private function get_field( $field_type, $field_name, $field_value, array $optio } break; case 'hidden': - $field .= ''; + $field .= ''; break; } diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index 5fa844f8a11..fb62b642633 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -17,7 +17,7 @@ import getIndicatorForScore from "./getIndicatorForScore"; import isKeywordAnalysisActive from "./isKeywordAnalysisActive"; import isContentAnalysisActive from "./isContentAnalysisActive"; -import { STORE_NAME_EDITOR } from "../shared-admin/constants"; +import { STORES } from "../shared-admin/constants"; const { tmceId } = tmceHelper; const $ = jQuery; @@ -83,7 +83,7 @@ PostDataCollector.prototype.getData = function() { * @returns {string} The keyword. */ PostDataCollector.prototype.getKeyword = function() { - const keyword = select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(); + const keyword = select( STORES.editor ).getFocusKeyphrase(); return keyword; }; @@ -108,7 +108,7 @@ PostDataCollector.prototype.getMetaDescForAnalysis = function( state ) { * @returns {string} The meta description. */ PostDataCollector.prototype.getMeta = function() { - return select( STORE_NAME_EDITOR.free ).getDescription(); + return select( STORES.editor ).getDescription(); }; /** diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index de0d9915c31..40c82a8eb98 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -8,7 +8,7 @@ import styled from "styled-components"; import WooCommerceUpsell from "./WooCommerceUpsell"; import { get } from "lodash"; import { useSelect } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../shared-admin/constants"; +import { STORES } from "../shared-admin/constants"; const NewsLandingPageLink = makeOutboundLink(); @@ -68,8 +68,8 @@ NewsAlert.propTypes = { * @returns {Object[]} A copy of the schema type options. */ const getSchemaTypeOptions = ( schemaTypeOptions, defaultType, postTypeName ) => { - const isProduct = useSelect( ( select ) => select( STORE_NAME_EDITOR.free ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( STORE_NAME_EDITOR.free ).getIsWooSeoActive(), [] ); + const isProduct = useSelect( ( select ) => select( STORES.editor ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( STORES.editor ).getIsWooSeoActive(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const schemaOption = disablePageTypeSelect ? { name: __( "Item Page", "wordpress-seo" ), value: "ItemPage" } : schemaTypeOptions.find( option => option.value === defaultType ); return [ @@ -169,9 +169,9 @@ const Content = ( props ) => { const woocommerceUpsell = get( window, "wpseoScriptData.woocommerceUpsell", "" ); const [ focusedArticleType, setFocusedArticleType ] = useState( props.schemaArticleTypeSelected ); const woocommerceUpsellText = __( "Want your products stand out in search results with rich results like price, reviews and more?", "wordpress-seo" ); - const isProduct = useSelect( ( select ) => select( STORE_NAME_EDITOR.free ).getIsProduct(), [] ); - const isWooSeoActive = useSelect( select => select( STORE_NAME_EDITOR.free ).getIsWooSeoActive(), [] ); - const showArticleTypeInput = useSelect( select => select( STORE_NAME_EDITOR.free ).getShowArticleTypeInput(), [] ); + const isProduct = useSelect( ( select ) => select( STORES.editor ).getIsProduct(), [] ); + const isWooSeoActive = useSelect( select => select( STORES.editor ).getIsWooSeoActive(), [] ); + const showArticleTypeInput = useSelect( select => select( STORES.editor ).getShowArticleTypeInput(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const handleOptionChange = useCallback( diff --git a/packages/js/src/elementor/components/fills/ElementorFill.js b/packages/js/src/elementor/components/fills/ElementorFill.js index 48d851103e8..c5cb4062cb4 100644 --- a/packages/js/src/elementor/components/fills/ElementorFill.js +++ b/packages/js/src/elementor/components/fills/ElementorFill.js @@ -1,6 +1,6 @@ // External dependencies. import { Fill } from "@wordpress/components"; -import { Fragment, useEffect } from "@wordpress/element"; +import { Fragment } from "@wordpress/element"; import { __ } from "@wordpress/i18n"; import { get } from "lodash"; import PropTypes from "prop-types"; @@ -37,22 +37,10 @@ import { ElementorErrorFallback } from "../elementor-error-fallback"; * * @constructor */ -export default function ElementorFill( { isLoading, onLoad, settings } ) { +export default function ElementorFill( { settings } ) { const webinarIntroUrl = get( window, "wpseoScriptData.webinarIntroElementorUrl", "https://yoa.st/webinar-intro-elementor" ); const FirstEligibleNotification = useFirstEligibleNotification( { webinarIntroUrl } ); - useEffect( () => { - setTimeout( () => { - if ( isLoading ) { - onLoad(); - } - } ); - } ); - - if ( isLoading ) { - return null; - } - return ( <> { isWordProofIntegrationActive() && } @@ -138,8 +126,6 @@ export default function ElementorFill( { isLoading, onLoad, settings } ) { } ElementorFill.propTypes = { - isLoading: PropTypes.bool.isRequired, - onLoad: PropTypes.func.isRequired, settings: PropTypes.object.isRequired, }; /* eslint-enable complexity */ diff --git a/packages/js/src/elementor/containers/ElementorFill.js b/packages/js/src/elementor/containers/ElementorFill.js index b4ad80b9605..393974f32df 100644 --- a/packages/js/src/elementor/containers/ElementorFill.js +++ b/packages/js/src/elementor/containers/ElementorFill.js @@ -1,5 +1,5 @@ import { compose } from "@wordpress/compose"; -import { withDispatch, withSelect } from "@wordpress/data"; +import { withSelect } from "@wordpress/data"; import ElementorFill from "../components/fills/ElementorFill"; /* eslint-disable complexity */ @@ -7,19 +7,10 @@ export default compose( [ withSelect( select => { const { getPreferences, - getSnippetEditorIsLoading, } = select( "yoast-seo/editor" ); return { settings: getPreferences(), - isLoading: getSnippetEditorIsLoading(), - }; - } ), - withDispatch( dispatch => { - const { loadSnippetEditorData } = dispatch( "yoast-seo/editor" ); - - return { - onLoad: loadSnippetEditorData, }; } ), ] )( ElementorFill ); diff --git a/packages/js/src/elementor/containers/SnippetEditor.js b/packages/js/src/elementor/containers/SnippetEditor.js index dcce1af12c8..b3d268b5158 100644 --- a/packages/js/src/elementor/containers/SnippetEditor.js +++ b/packages/js/src/elementor/containers/SnippetEditor.js @@ -1,6 +1,5 @@ import { compose } from "@wordpress/compose"; import { select as wpSelect, withSelect, withDispatch } from "@wordpress/data"; -import { useEffect } from "@wordpress/element"; import { SnippetEditor } from "@yoast/search-metadata-previews"; import { __ } from "@wordpress/i18n"; import PropTypes from "prop-types"; @@ -69,19 +68,7 @@ const mapEditorDataToPreview = ( data, context ) => { * * @returns {wp.Element} The component. */ -const SnippetEditorWrapper = ( { isLoading, onLoad, location, ...restProps } ) => { - useEffect( () => { - setTimeout( () => { - if ( isLoading ) { - onLoad(); - } - } ); - } ); - - if ( isLoading ) { - return null; - } - +const SnippetEditorWrapper = ( { location, ...restProps } ) => { return ( typeof x === "function" ), controls, initialState, diff --git a/packages/js/src/elementor/redux/actions/snippetEditor.js b/packages/js/src/elementor/redux/actions/snippetEditor.js deleted file mode 100644 index 435cecffc45..00000000000 --- a/packages/js/src/elementor/redux/actions/snippetEditor.js +++ /dev/null @@ -1,70 +0,0 @@ -import { get } from "lodash"; -import SearchMetadataFields from "../../../helpers/fields/SearchMetadataFields"; -import { actions } from "@yoast/externals/redux"; - -const { UPDATE_DATA, LOAD_SNIPPET_EDITOR_DATA } = actions; - -/** - * Updates the data of the snippet editor. - * - * @param {Object} data The snippet editor data. - * @param {string} [data.title] The title in the snippet editor. - * @param {string} [data.slug] The slug in the snippet editor. - * @param {string} [data.description] The description in the snippet editor. - * - * @returns {Object} An action for redux. - */ -export function updateData( data ) { - /* - * Update the appropriate field. - * Using a truthy check (e.g. `data.title`) does not work, as it would be false when the string is empty. - */ - if ( data.hasOwnProperty( "title" ) ) { - let titleToBeSaved = data.title; - // Test whether this is actually the template, which we don't want to save. - if ( data.title === get( window, "wpseoScriptData.metabox.title_template", "" ) ) { - titleToBeSaved = ""; - } - - SearchMetadataFields.title = titleToBeSaved; - } - if ( data.hasOwnProperty( "description" ) ) { - let metaDescToBeSaved = data.description; - // Test whether this is actually the template, which we don't want to save. - if ( data.description === get( window, "wpseoScriptData.metabox.metadesc_template", "" ) ) { - metaDescToBeSaved = ""; - } - SearchMetadataFields.description = metaDescToBeSaved; - } - if ( data.hasOwnProperty( "slug" ) ) { - SearchMetadataFields.slug = data.slug; - } - - return { - type: UPDATE_DATA, - data, - }; -} - -/** - * Loads the snippet editor data. - * - * @returns {Object} The load cornerstone content action. - */ -export const loadSnippetEditorData = () => { - const titleTemplate = get( window, "wpseoScriptData.metabox.title_template", "" ); - const descriptionTemplate = get( window, "wpseoScriptData.metabox.metadesc_template", "" ); - - return { - type: LOAD_SNIPPET_EDITOR_DATA, - data: { - title: SearchMetadataFields.title || titleTemplate, - description: SearchMetadataFields.description || descriptionTemplate, - slug: SearchMetadataFields.slug, - }, - templates: { - title: titleTemplate, - description: descriptionTemplate, - }, - }; -}; diff --git a/packages/js/src/helpers/fields/SearchMetadataFields.js b/packages/js/src/helpers/fields/SearchMetadataFields.js deleted file mode 100644 index 68b4deb18dd..00000000000 --- a/packages/js/src/helpers/fields/SearchMetadataFields.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * This class is responsible for handling the interaction with the hidden fields for the search metadata. - */ -export default class SearchMetadataFields { - /** - * Getter for the titleElement. - * - * @returns {HTMLElement} The titleElement. - */ - static get titleElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_title" : "hidden_wpseo_title" ); - } - - /** - * Getter for the descriptionElement. - * - * @returns {HTMLElement} The descriptionElement. - */ - static get descriptionElement() { - return document.getElementById( window.wpseoScriptData.isPost ? "yoast_wpseo_metadesc" : "hidden_wpseo_desc" ); - } - - /** - * Getter for the slugElement. - * - * @returns {HTMLElement} The slugElement. - */ - static get slugElement() { - return document.getElementById( "yoast_wpseo_slug" ); - } - - /** - * Getter for the title. - * - * @returns {string} The title. - */ - static get title() { - return SearchMetadataFields.titleElement.value; - } - - /** - * Setter for the title. - * - * @param {string} value The title. - * - * @returns {void} - */ - static set title( value ) { - SearchMetadataFields.titleElement.value = value; - } - - /** - * Getter for the description. - * - * @returns {string} The description. - */ - static get description() { - return SearchMetadataFields.descriptionElement.value; - } - - /** - * Setter for the description. - * - * @param {string} value The description. - * - * @returns {void} - */ - static set description( value ) { - SearchMetadataFields.descriptionElement.value = value; - } - - /** - * Getter for the slug. - * - * @returns {string} The slug. - */ - static get slug() { - return SearchMetadataFields.slugElement.value; - } - - /** - * Setter for the slug. - * - * @param {string} value The slug. - * - * @returns {void} - */ - static set slug( value ) { - SearchMetadataFields.slugElement.value = value; - } -} diff --git a/packages/js/src/helpers/fields/advancedFieldsStore.js b/packages/js/src/helpers/fields/advancedFieldsStore.js deleted file mode 100644 index e31e0458304..00000000000 --- a/packages/js/src/helpers/fields/advancedFieldsStore.js +++ /dev/null @@ -1,58 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; - -/** - * Retrieves the no index value. - * - * @returns {string} The no index value. - */ -export const getNoIndex = () => String( select( STORE_NAME_EDITOR.free ).getNoIndex() ); - -/** - * Retrieves the no follow value. - * - * @returns {string} The no follow value. - */ -export const getNoFollow = () => String( select( STORE_NAME_EDITOR.free ).getNoFollow() ); - -/** - * Gets the twitter image URL from the state. - * - * @param {Object} state The state. - * - * @returns {string} Twitter image URL. - */ -export const getAdvanced = () => { - const advanced = select( STORE_NAME_EDITOR.free ).getAdvanced(); - if ( Array.isArray( advanced ) ) { - return advanced.join(); - } - return advanced; -}; - -/** - * Gets the twitter image type from the state. - * - * @param {Object} state The state. - * - * @returns {string} Twitter image type. - */ -export const getBreadcrumbsTitle = () => select( STORE_NAME_EDITOR.free ).getBreadcrumbsTitle(); - -/** - * Gets the Twitter image src from the state. - * - * @param {Object} state The state. - * - * @returns {String} Twitter image src. - */ -export const getCanonical = () => select( STORE_NAME_EDITOR.free ).getCanonical(); - -/** - * Gets the WordProof timestamp value. - * - * @param {Object} state The state. - * - * @returns {string} WordProof timestamp value. - */ -export const getWordProofTimestamp = () => select( STORE_NAME_EDITOR.free ).getWordProofTimestamp() ? "1" : ""; diff --git a/packages/js/src/helpers/fields/analysisFieldsStore.js b/packages/js/src/helpers/fields/analysisFieldsStore.js deleted file mode 100644 index ebd13f1e7b8..00000000000 --- a/packages/js/src/helpers/fields/analysisFieldsStore.js +++ /dev/null @@ -1,45 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { defaultTo } from "lodash"; - -/** - * Retrieves the focus keyphrase from store. - * - * @returns {string} The focus keyphrase. - */ -export const getFocusKeyphrase = () => select( STORE_NAME_EDITOR.free ).getFocusKeyphrase(); - -/** - * Returns whether the current content is cornerstone content. - * - * @returns {string} Whether the current content is cornerstone content. - */ -export const isCornerstoneContent = () => select( STORE_NAME_EDITOR.free ).isCornerstoneContent() ? "1" : "0"; - -/** - * Retrieves the readability score from the store. - * - * @returns {string} The content score. - */ -export const getReadabilityScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getReadabilityResults().overallScore, "0" ) ); - -/** - * Retrieves the inclusive language score from the store. - * - * @returns {string} The content score. - */ -export const getInclusiveLanguageScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getInclusiveLanguageResults().overallScore, "0" ) ); - -/** - * Retrieves the seo score from the store. - * - * @returns {string} The content score. - */ -export const getSeoScore = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getSeoResults().overallScore, "0" ) ); - -/** - * Retrieves the estimated reading time from the store. - * - * @returns {string} The estimated reading time. - */ -export const getEstimatedReadingTime = () => String( defaultTo( select( STORE_NAME_EDITOR.free ).getEstimatedReadingTime(), "0" ) ); diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index d7002ca1dbb..f90189e9e03 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,23 +1,18 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, pickBy, mapKeys } from "lodash"; +import { debounce, pickBy, mapKeys, reduce } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { SYNC_TIME, META_KEYS, POST_META_KEY_PREFIX } from "./constants"; -import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; -import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; -import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; -import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; -import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; -import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; +import { STORES, META_FIELDS, SYNC_TIME, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; +import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; +import { transformMetaValue } from "./transform-meta-value"; /** * Creates an updater. * @returns {function} The updater. */ const createUpdater = () => { - const { editPost } = dispatch( STORE_NAME_EDITOR.core ); - const { getCurrentPost } = select( STORE_NAME_EDITOR.core ); + const { editPost } = dispatch( STORES.wp.editor ); + const { getCurrentPost } = select( STORES.wp.core ); + const { getEditedEntityRecord } = select( "core" ); /** * Syncs the data to the WP entity record. @@ -27,13 +22,14 @@ const createUpdater = () => { return ( data ) => { const currentPost = getCurrentPost(); - if ( ! currentPost.hasOwnProperty( "meta" ) || ! data ) { + if ( ! ( "meta" in currentPost ) || ! data ) { return; } - const metadata = currentPost.meta; - - const changedData = pickBy( data, ( value, key ) => value !== metadata[ key ] ); + const metadata = getEditedEntityRecord( "postType", currentPost.type, currentPost.id ).meta; + console.log( metadata ); + const changedData = pickBy( data, ( value, key ) => transformMetaValue( key, value ) !== metadata[ POST_META_KEY_PREFIX + key ] ); + console.log( { changedData } ); if ( changedData ) { editPost( { @@ -48,34 +44,12 @@ const createUpdater = () => { * @returns {function} The un-subscriber. */ export const blockEditorSync = () => { - const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => POST_META_KEY_PREFIX + key ); + const primaryTaxonomiesGetters = getPrimaryTerms(); - const getters = mapKeys( { - focusKeyphrase: getFocusKeyphrase, - robotsNoIndex: getNoIndex, - robotsNoFollow: getNoFollow, - robotsAdvanced: getAdvanced, - facebookTitle: getFacebookTitle, - facebookDescription: getFacebookDescription, - facebookImageUrl: getFacebookImageUrl, - facebookImageId: getFacebookImageId, - twitterTitle: getTwitterTitle, - twitterDescription: getTwitterDescription, - twitterImageUrl: getTwitterImageUrl, - twitterImageId: getTwitterImageId, - schemaPageType: getPageType, - schemaArticleType: getArticleType, - isCornerstone: isCornerstoneContent, - readabilityScore: getReadabilityScore, - seoScore: getSeoScore, - inclusiveLanguageScore: getInclusiveLanguageScore, - breadcrumbsTitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordProofTimestamp: getWordProofTimestamp, - seoTitle: getSeoTitle, - seoDescription: getSeoDescription, - readingTime: getEstimatedReadingTime, - }, ( value, key ) => POST_META_KEY_PREFIX + META_KEYS[ key ] ); + const getters = reduce( META_FIELDS, ( acc, value ) => { + acc[ value.key ] = select( STORES.editor )[ value.get ]; + return acc; + }, {} ); return subscribe( debounce( createWatcher( createCollectorFromObject( { @@ -83,5 +57,5 @@ export const blockEditorSync = () => { ...primaryTaxonomiesGetters, } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE_NAME_EDITOR.free ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORES.editor ); }; diff --git a/packages/js/src/helpers/fields/constants.js b/packages/js/src/helpers/fields/constants.js deleted file mode 100644 index d5c3d01b8f9..00000000000 --- a/packages/js/src/helpers/fields/constants.js +++ /dev/null @@ -1,38 +0,0 @@ -export const META_KEYS = { - focusKeyphrase: "focuskw", - robotsNoIndex: "meta-robots-noindex", - robotsNoFollow: "meta-robots-nofollow", - robotsAdvanced: "meta-robots-adv", - facebookTitle: "opengraph-title", - facebookDescription: "opengraph-description", - facebookImageUrl: "opengraph-image", - facebookImageId: "opengraph-image-id", - twitterTitle: "twitter-title", - twitterDescription: "twitter-description", - twitterImageUrl: "twitter-image", - twitterImageId: "twitter-image-id", - schemaPageType: "schema_page_type", - schemaArticleType: "schema_article_type", - isCornerstone: "is_cornerstone", - readabilityScore: "content_score", - seoScore: "linkdex", - inclusiveLanguageScore: "inclusive_language_score", - breadcrumbsTitle: "bctitle", - canonical: "canonical", - wordProofTimestamp: "wordproof_timestamp", - seoTitle: "title", - seoDescription: "metadesc", - readingTime: "estimated-reading-time-minutes", -}; - -export const HIDDEN_INPUT_ID_PREFIX = { - post: "yoast_wpseo_", - term: "hidden_wpseo_", -}; - -export const POST_META_KEY_PREFIX = `_${ HIDDEN_INPUT_ID_PREFIX.post }`; - -export const SYNC_TIME = { - wait: 500, - max: 1500, -}; diff --git a/packages/js/src/helpers/fields/facebookFieldsStore.js b/packages/js/src/helpers/fields/facebookFieldsStore.js deleted file mode 100644 index f5854041ecd..00000000000 --- a/packages/js/src/helpers/fields/facebookFieldsStore.js +++ /dev/null @@ -1,27 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; - -/** - * Retrieve facebook image id. - * @returns {integer} The facebook image id. - */ -export const getFacebookImageId = () => String( select( STORE_NAME_EDITOR.free ).getFacebookImageId() ); - -/** - * Get facebook title. - * @returns {string} The facebook title. - */ -export const getFacebookTitle = () => select( STORE_NAME_EDITOR.free ).getFacebookTitle(); - -/** - * Get facebook description. - * @returns {string} The facebook description. - */ -export const getFacebookDescription = () => select( STORE_NAME_EDITOR.free ).getFacebookDescription(); - -/** - * Get facebook image Url. - * @returns {string} The facebook image Url. - */ -export const getFacebookImageUrl = () => select( STORE_NAME_EDITOR.free )?.getFacebookImageUrl(); - diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index f10e3c2fc4f..dcdfd0ac433 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,63 +1,10 @@ /* eslint-disable complexity */ import { select, subscribe } from "@wordpress/data"; -import { debounce, forEach, mapKeys } from "lodash"; +import { debounce, forEach, reduce } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; -import { HIDDEN_INPUT_ID_PREFIX, SYNC_TIME, META_KEYS } from "./constants"; -import { getFacebookImageId, getFacebookTitle, getFacebookDescription, getFacebookImageUrl } from "./facebookFieldsStore"; -import { getTwitterImageId, getTwitterTitle, getTwitterDescription, getTwitterImageUrl } from "./twitterFieldsStore"; -import { getPageType, getArticleType } from "./schemaFieldsStore"; -import { getFocusKeyphrase, isCornerstoneContent, getReadabilityScore, getSeoScore, getInclusiveLanguageScore, getEstimatedReadingTime } from "./analysisFieldsStore"; -import { getNoIndex, getNoFollow, getAdvanced, getBreadcrumbsTitle, getCanonical, getWordProofTimestamp } from "./advancedFieldsStore"; -import getPrimaryTerms from "./primaryTaxonomiesFieldsStore"; -import { getSeoTitle, getSeoDescription } from "./snippetEditorFieldsStore"; - -/** - * Prepare twitter title to be saved in hidden field. - * @param {string} value The value to be saved. - * @returns {string} The value to be saved. - */ -const prepareSocialTitle = ( value ) => { - if ( value.trim() === select( STORE_NAME_EDITOR.free ).getSocialTitleTemplate().trim() ) { - return ""; - } - return value; -}; - -/** - * Prepare twitter and facebook description to be saved in hidden field. - * @param {string} value The value to be saved. - * @returns {string} The value to be saved. - */ -const prepareSocialDescription = ( value ) => { - if ( value.trim() === select( STORE_NAME_EDITOR.free ).getSocialDescriptionTemplate().trim() ) { - return ""; - } - return value; -}; - -/** - * Prepare value to be saved in hidden field. - * - * @param {string} key The key of the value. - * @param {string} value The value to be saved. - * - * @returns {string} The value to be saved. - */ -const prepareValue = ( key, value ) => { - switch ( key ) { - case "wordproof_timestamp": - return value ? "1" : "0"; - case "twitter-title": - case "opengraph-title": - return prepareSocialTitle( value ); - case "twitter-description": - case "opengraph-description": - return prepareSocialDescription( value ); - default: - return value; - } -}; +import { STORES, HIDDEN_INPUT_ID_PREFIX, SYNC_TIME, META_FIELDS } from "../../shared-admin/constants"; +import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; +import { transformMetaValue } from "./transform-meta-value"; /** * Creates an updater. @@ -70,10 +17,15 @@ export const createUpdater = () => { * @returns {void} */ return ( data ) => { + const isPost = select( STORES.editor ).getIsPost(); + const prefix = isPost ? HIDDEN_INPUT_ID_PREFIX.post : HIDDEN_INPUT_ID_PREFIX.term; + forEach( data, ( value, key ) => { - const field = document.getElementById( key ); - if ( field && field.value !== value ) { - field.value = prepareValue( key, value ); + const field = document.getElementById( prefix + key ); + const tranformedValue = transformMetaValue( key, value ); + if ( field && field.value !== tranformedValue ) { + console.log( field.value, value, key, tranformedValue ) + field.value = tranformedValue; } } ); }; @@ -84,42 +36,23 @@ export const createUpdater = () => { * @returns {function} The un-subscriber. */ export const hiddenFieldsSync = () => { - const isPost = select( STORE_NAME_EDITOR.free ).getIsPost(); - const prefix = isPost ? HIDDEN_INPUT_ID_PREFIX.post : HIDDEN_INPUT_ID_PREFIX.term; - const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => prefix + key ); + const primaryTaxonomiesGetters = getPrimaryTerms(); - const getters = mapKeys( { - focusKeyphrase: getFocusKeyphrase, - robotsNoIndex: getNoIndex, - robotsNoFollow: getNoFollow, - robotsAdvanced: getAdvanced, - facebookTitle: getFacebookTitle, - facebookDescription: getFacebookDescription, - facebookImageUrl: getFacebookImageUrl, - facebookImageId: getFacebookImageId, - twitterTitle: getTwitterTitle, - twitterDescription: getTwitterDescription, - twitterImageUrl: getTwitterImageUrl, - twitterImageId: getTwitterImageId, - schemaPageType: getPageType, - schemaArticleType: getArticleType, - isCornerstone: isCornerstoneContent, - readabilityScore: getReadabilityScore, - seoScore: getSeoScore, - inclusiveLanguageScore: getInclusiveLanguageScore, - breadcrumbsTitle: getBreadcrumbsTitle, - canonical: getCanonical, - wordProofTimestamp: getWordProofTimestamp, - readingTime: getEstimatedReadingTime, - seoTitle: getSeoTitle, - seoDescription: getSeoDescription, - }, ( value, key ) => prefix + META_KEYS[ key ] ); + const getters = reduce( META_FIELDS, ( acc, value ) => { + // check if value.get is a function in select( STORES.editor ) store + if ( typeof select( STORES.editor )[ value.get ] === "function" ) { + acc[ value.key ] = select( STORES.editor )[ value.get ]; + } + return acc; + }, {} ); return subscribe( debounce( createWatcher( createCollectorFromObject( { ...getters, ...primaryTaxonomiesGetters, + // Slug is added for elementor editor. + slug: select( STORES.editor ).getSnippetEditorSlug } ), createUpdater() - ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORE_NAME_EDITOR.free ); + ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORES.editor ); }; diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index 2633ef9d71b..ddcc120270c 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,10 +1,3 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; -export * from "./hiddenFieldsSync"; -export * from "./facebookFieldsStore"; -export * from "./twitterFieldsStore"; -export * from "./analysisFieldsStore"; -export * from "./schemaFieldsStore"; -export * from "./advancedFieldsStore"; -export * from "./snippetEditorFieldsStore"; - +export * from "./hiddenFieldsSync"; \ No newline at end of file diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index f715918a82b..dfa9ad6928b 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -1,26 +1,17 @@ -import { get, forEach } from "lodash"; +import { get, reduce } from "lodash"; import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; +import { STORES } from "../../shared-admin/constants"; /** * Retrieves primary terms from store methods. * * @returns {object} An object with taxonomies keys and their primary term id. */ -const getPrimaryTerms = () => { +export const getPrimaryTerms = () => { const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); - const getPrimaryTermsStore = {}; - forEach( primaryTerms, ( value, key ) => { - getPrimaryTermsStore[ `primary_${key}` ] = () => { - const termId = String( select( STORE_NAME_EDITOR.free ).getPrimaryTaxonomyId( key ) ); - if ( termId === "0" || termId === "-1" ) { - return ""; - } - return termId; + return reduce( primaryTerms, ( primaryTermGetters, value, key ) => { + primaryTermGetters[ `primary_${key}` ] = () => { + return select( STORES.editor ).getPrimaryTaxonomyId( key ); }; - } ); - - return getPrimaryTermsStore; + }, {} ); }; - -export default getPrimaryTerms; diff --git a/packages/js/src/helpers/fields/schemaFieldsStore.js b/packages/js/src/helpers/fields/schemaFieldsStore.js deleted file mode 100644 index e4d4cd14d1b..00000000000 --- a/packages/js/src/helpers/fields/schemaFieldsStore.js +++ /dev/null @@ -1,16 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; - -/** - * Gets the pageType from the store. - * - * @returns {String} Page type. - */ -export const getPageType = () => select( STORE_NAME_EDITOR.free ).getPageType(); - -/** - * Gets the articleType from the store. - * - * @returns {String} Article type. - */ -export const getArticleType = () => select( STORE_NAME_EDITOR.free ).getArticleType(); diff --git a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js b/packages/js/src/helpers/fields/snippetEditorFieldsStore.js deleted file mode 100644 index ce4418c8fac..00000000000 --- a/packages/js/src/helpers/fields/snippetEditorFieldsStore.js +++ /dev/null @@ -1,16 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; - -/** - * Gets the snippet editor title from the store. - * - * @returns {string} The snippet editor title. - */ -export const getSeoTitle = () => select( STORE_NAME_EDITOR.free ).getSnippetEditorTitle(); - -/** - * Gets the snippet editor description from the store. - * - * @returns {string} The snippet editor description. - */ -export const getSeoDescription = () => select( STORE_NAME_EDITOR.free ).getSnippetEditorDescription(); diff --git a/packages/js/src/helpers/fields/transform-meta-value.js b/packages/js/src/helpers/fields/transform-meta-value.js new file mode 100644 index 00000000000..28fdcee3c42 --- /dev/null +++ b/packages/js/src/helpers/fields/transform-meta-value.js @@ -0,0 +1,36 @@ +/* eslint-disable complexity */ + +/** + * Prepare value to be saved in hidden field. + * + * @param {string} key The key of the value. + * @param {string} value The value to be saved. + * + * @returns {string} The value to be saved. + */ +export const transformMetaValue = ( key, value ) => { + switch ( true ) { + case key === "content_score": + case key === "linkdex": + case key === "inclusive_language_score": + case key === "estimated-reading-time-minutes": + if ( value >= 0 ) { + return String( value ); + } + return "0"; + case key === "is_cornerstone": + case key === "wordproof_timestamp": + return value ? "1" : "0"; + case key.startsWith( "primary_" ): + case key === "open_graph-image-id": + case key === "twitter-image-id": + if ( value > 0 ) { + return String( value ); + } + return ""; + case key === "meta-robots-adv": + return Array.isArray( value ) ? value.join() : value; + default: + return value; + } +}; diff --git a/packages/js/src/helpers/fields/twitterFieldsStore.js b/packages/js/src/helpers/fields/twitterFieldsStore.js deleted file mode 100644 index c48280d0267..00000000000 --- a/packages/js/src/helpers/fields/twitterFieldsStore.js +++ /dev/null @@ -1,31 +0,0 @@ -import { select } from "@wordpress/data"; -import { STORE_NAME_EDITOR } from "../../shared-admin/constants"; - -/** - * Retrieve twitter image id from the store. - * - * @returns {string} The twitter image id. - */ -export const getTwitterImageId = () => String( select( STORE_NAME_EDITOR.free ).getTwitterImageId() ); - -/** - * Get twitter title from the store. - * - * @returns {string} The twitter title. - */ -export const getTwitterTitle = () => select( STORE_NAME_EDITOR.free ).getTwitterTitle(); - -/** - * Get twitter description from the store. - * - * @returns {string} The twitter description. - */ -export const getTwitterDescription = () => select( STORE_NAME_EDITOR.free ).getTwitterDescription(); - -/** - * Get twitter image Url from the store. - * - * @returns {string} The twitter image Url. - */ -export const getTwitterImageUrl = () => select( STORE_NAME_EDITOR.free ).getTwitterImageUrl(); - diff --git a/packages/js/src/redux/actions/snippetEditor.js b/packages/js/src/redux/actions/snippetEditor.js index e253368200b..7febbb1b547 100644 --- a/packages/js/src/redux/actions/snippetEditor.js +++ b/packages/js/src/redux/actions/snippetEditor.js @@ -10,7 +10,6 @@ export const HIDE_REPLACEMENT_VARIABLES = "SNIPPET_EDITOR_HIDE_REPLACEMENT_VARIA export const REMOVE_REPLACEMENT_VARIABLE = "SNIPPET_EDITOR_REMOVE_REPLACEMENT_VARIABLE"; export const REFRESH = "SNIPPET_EDITOR_REFRESH"; export const UPDATE_WORDS_TO_HIGHLIGHT = "SNIPPET_EDITOR_UPDATE_WORDS_TO_HIGHLIGHT"; -export const LOAD_SNIPPET_EDITOR_DATA = "LOAD_SNIPPET_EDITOR_DATA"; /** * Switches mode of the snippet editor. diff --git a/packages/js/src/redux/initial-state/analysis.js b/packages/js/src/redux/initial-state/analysis.js new file mode 100644 index 00000000000..2c752866d59 --- /dev/null +++ b/packages/js/src/redux/initial-state/analysis.js @@ -0,0 +1,16 @@ +import { get } from "lodash"; + +export const analysisInitialState = { + seo: { + results: [], + overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 )), + }, + readability: { + results: [], + overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.content_score", 0 )), + }, + inclusiveLanguage: { + results: [], + overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 )), + }, +}; \ No newline at end of file diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index a85d2f489df..dc873027bf6 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -1,14 +1,16 @@ import get from "lodash/get"; import { facebookInitialState, twitterInitialState } from "./socialAppearance"; -import { advancedSettingsInitialState } from "./advancedSettings"; -export * from "./socialAppearance"; +import { advancedSettingsInitialState as advancedSettings } from "./advancedSettings"; import primaryTaxonomies from "./primaryTaxonomies"; -import schemaTab from "./schemaTab"; +import { schemaInitialState as schemaTab } from "./schemaTab"; +import { snippetEditorInitialState as snippetEditor } from "./snippetEditor"; +import { analysisInitialState as analysis } from "./analysis"; const initialState = { facebookEditor: facebookInitialState, twitterEditor: twitterInitialState, - advancedSettings: advancedSettingsInitialState, + advancedSettings, + snippetEditor, focusKeyword: get( window, "wpseoScriptData.metabox.metadata.focuskw", "" ), // This used to be a checkbox, then became a hidden input. For consistency, we set the value to '1'. isCornerstone: get( window, "wpseoScriptData.metabox.metadata.is_cornerstone", 0 ) === "1", @@ -18,6 +20,11 @@ const initialState = { isPost: get( window, "wpseoScriptData.isPost", false ), id: Number( get( window, "wpseoScriptData.postId", null ) ), }, + analysis, + insights: { + estimatedReadingTime: Number( get( window, "wpseoScriptData.metabox.metadata.estimated-reading-time-minutes", 0 ) ), + textLength: {}, + } }; export default initialState; diff --git a/packages/js/src/redux/initial-state/schemaTab.js b/packages/js/src/redux/initial-state/schemaTab.js index 7223f614131..37c08467933 100644 --- a/packages/js/src/redux/initial-state/schemaTab.js +++ b/packages/js/src/redux/initial-state/schemaTab.js @@ -1,11 +1,9 @@ import { get } from "lodash"; -const schemaTab = { +export const schemaInitialState = { pageType: get( window, "wpseoScriptData.metabox.metadata.schema_page_type", "" ), defaultPageType: get( window, "wpseoScriptData.metabox.schemaDefaults.pageType", "" ), articleType: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", "" ), defaultArticleType: get( window, "wpseoScriptData.metabox.schemaDefaults.articleType", "" ), showArticleTypeInput: get( window, "wpseoScriptData.metabox.metadata.schema_article_type", false ) !== false, }; - -export default schemaTab; diff --git a/packages/js/src/redux/initial-state/snippetEditor.js b/packages/js/src/redux/initial-state/snippetEditor.js new file mode 100644 index 00000000000..ad23cdffa9d --- /dev/null +++ b/packages/js/src/redux/initial-state/snippetEditor.js @@ -0,0 +1,54 @@ +import { select } from "@wordpress/data"; +import { get } from "lodash"; +import { STORES } from "../../shared-admin/constants"; +import getDefaultReplacementVariables from "../../values/defaultReplaceVariables"; + +const titleTemplate = get( window, "wpseoScriptData.metabox.title_template", "" ); +const descriptionTemplate = get( window, "wpseoScriptData.metabox.metadesc_template", "" ); +const title = get( window, "wpseoScriptData.metabox.metadata.title", "" ); + +const termDescription = get( window, "wpseoScriptData.metabox.metadata.desc", "" ); +const description = get( window, "wpseoScriptData.metabox.metadata.metadesc", termDescription ); + +/** + * Gets the slug. + * + * @returns {string} The slug. + */ +const getSlug = () => { + // Get the slug from the editor store. + const editorSelectors = select( STORES.wp.editor ); + if ( editorSelectors && editorSelectors.getCurrentPostAttribute( "slug" ) ) { + return editorSelectors.getCurrentPostAttribute( "slug" ); + } + + var url = ""; + + var newPostSlug = document.getElementById( "new-post-slug" ); + if ( newPostSlug ) { + url = newPostSlug.val(); + } else if ( document.getElementById( "editable-post-name-full" ) !== null ) { + url = document.getElementById( "editable-post-name-full" ).textContent; + }else if ( document.getElementById( "yoast_wpseo_slug" ) !== null ) { + // Get the slug from hidden fields in elementor editor. + url = document.getElementById( "yoast_wpseo_slug" ).value; + } + + return url; +}; + +export const snippetEditorInitialState = { + mode: "mobile", + data: { + title: title || titleTemplate, + description: description || descriptionTemplate, + slug: getSlug(), + }, + wordsToHighlight: [], + replacementVariables: getDefaultReplacementVariables(), + uniqueRefreshValue: "", + templates: { + title: titleTemplate, + description: descriptionTemplate, + }, +}; diff --git a/packages/js/src/redux/reducers/snippetEditor.js b/packages/js/src/redux/reducers/snippetEditor.js index e872541ba76..10b2efb464b 100644 --- a/packages/js/src/redux/reducers/snippetEditor.js +++ b/packages/js/src/redux/reducers/snippetEditor.js @@ -9,7 +9,6 @@ import { CUSTOM_FIELD_RESULTS, REFRESH, UPDATE_WORDS_TO_HIGHLIGHT, - LOAD_SNIPPET_EDITOR_DATA, } from "../actions/snippetEditor"; import { pushNewReplaceVar, replaceSpaces, createLabelFromName } from "../../helpers/replacementVariableHelpers"; import { firstToUpperCase } from "../../helpers/stringHelpers"; @@ -220,23 +219,6 @@ function snippetEditorReducer( state = getInitialState(), action ) { wordsToHighlight: action.wordsToHighlight, }; } - - case LOAD_SNIPPET_EDITOR_DATA: - return { - ...state, - data: { - ...state.data, - title: action.data.title, - description: action.data.description, - slug: action.data.slug, - }, - templates: { - ...state.templates, - title: action.templates.title, - description: action.templates.description, - }, - isLoading: false, - }; } return state; diff --git a/packages/js/src/redux/selectors/facebookEditor.js b/packages/js/src/redux/selectors/facebookEditor.js index 792ea9521e3..bad45865324 100644 --- a/packages/js/src/redux/selectors/facebookEditor.js +++ b/packages/js/src/redux/selectors/facebookEditor.js @@ -11,6 +11,30 @@ import { getSocialTitleTemplate, } from "./fallbacks"; +/** + * Prepare twitter title to be saved in hidden field. + * @param {string} value The value to be saved. + * @returns {string} The value to be saved. + */ +export const getSocialTitleWithoutTemplate = ( value ) => { + if ( value.trim() === getSocialTitleTemplate().trim() ) { + return ""; + } + return value; +}; + +/** + * Prepare twitter and facebook description to be saved in hidden field. + * @param {string} value The value to be saved. + * @returns {string} The value to be saved. + */ +export const getSocialDescriptionWithoutTemplate = ( value ) => { + if ( value.trim() === getSocialDescriptionTemplate().trim() ) { + return ""; + } + return value; +}; + /** * Gets the facebook title from the state. * @@ -20,6 +44,18 @@ import { */ export const getFacebookTitle = state => get( state, "facebookEditor.title", "" ); +/** + * Gets the facebook title from the state. + * + * @param {Object} state The state. + * + * @returns {String} Facebook title. + */ +export const getFacebookTitleWithoutTemplate = state => { + const title = getFacebookTitle( state ); + return getSocialTitleWithoutTemplate( title ); +}; + /** * Gets the facebook description from the state. * @@ -29,6 +65,19 @@ export const getFacebookTitle = state => get( state, "facebookEditor.title", "" */ export const getFacebookDescription = state => get( state, "facebookEditor.description", "" ); +/** + * Gets the facebook description from the state. + * + * @param {Object} state The state. + * + * @returns {String} Facebook description. + */ +export const getFacebookDescriptionWithoutTemplate = state => { + const description = getFacebookDescription( state ); + return getSocialDescriptionWithoutTemplate( description ); +}; + + /** * Gets the facebook image URL from the state. * diff --git a/packages/js/src/redux/selectors/results.js b/packages/js/src/redux/selectors/results.js index e51591efd40..af535ecc54c 100644 --- a/packages/js/src/redux/selectors/results.js +++ b/packages/js/src/redux/selectors/results.js @@ -43,6 +43,17 @@ export function getReadabilityResults( state ) { return isEmpty( results ) ? { results: emptyArray, overallScore: null } : results; } +/** + * Get readability score. + * + * @param {Object} state The state. + * + * @returns {Number} The readability score. + */ +export function getReadabilityScore( state ) { + return get( getReadabilityResults( state ), "overallScore", 0 ); +} + /** * Gets the inclusive language results. * @@ -97,3 +108,25 @@ export function getResultById( state, id ) { export function getMarkButtonStatus( state ) { return state.marksButtonStatus; } + + +/** + * Get seo score. + * + * @param {object} state The state. + * + * @returns {number} The seo score. + */ +export function getScoreForFocusKeyword( state ) { + return get( getSeoResults( state ), "overallScore", 0 ); +} + +/** + * Get inclusive language score. + * + * @param {object} state The state. + * @returns {number} The inclusive language score. + */ +export function getInclusiveLanguageScore( state ) { + return get( getInclusiveLanguageResults( state ), "overallScore", 0 ); +} diff --git a/packages/js/src/redux/selectors/snippetEditor.js b/packages/js/src/redux/selectors/snippetEditor.js index b9c7bdefbab..6161d485e03 100644 --- a/packages/js/src/redux/selectors/snippetEditor.js +++ b/packages/js/src/redux/selectors/snippetEditor.js @@ -99,15 +99,6 @@ export const getSnippetEditorData = state => get( state, "snippetEditor.data", { */ export const getSnippetEditorWordsToHighlight = state => get( state, "snippetEditor.wordsToHighlight", [] ); -/** - * Gets the snippet editor is loading. - * - * @param {Object} state The state. - * - * @returns {String} Whether the snippet editor is loading. - */ -export const getSnippetEditorIsLoading = state => get( state, "snippetEditor.isLoading", true ); - /** * Gets the snippet editor preview image URL. * diff --git a/packages/js/src/redux/selectors/twitterEditor.js b/packages/js/src/redux/selectors/twitterEditor.js index d50812ac90c..68199528073 100644 --- a/packages/js/src/redux/selectors/twitterEditor.js +++ b/packages/js/src/redux/selectors/twitterEditor.js @@ -2,7 +2,7 @@ import { createSelector } from "@reduxjs/toolkit"; import { get } from "lodash"; import { getDescription, getSeoTitle } from "./analysis"; import { getEditorDataExcerptWithFallback } from "./editorData"; -import { getFacebookDescription, getFacebookTitle } from "./facebookEditor"; +import { getFacebookDescription, getFacebookTitle, getSocialDescriptionWithoutTemplate, getSocialTitleWithoutTemplate } from "./facebookEditor"; import { getReplacedExcerpt, getSeoDescriptionTemplate, @@ -21,6 +21,18 @@ import { */ export const getTwitterTitle = state => get( state, "twitterEditor.title", "" ); +/** + * Gets the X title from the state. + * + * @param {object} state The state. + * + * @returns {string} X title. + */ +export const getTwitterTitleWithoutTemplate = state => { + const title = getTwitterTitle( state ); + return getSocialTitleWithoutTemplate( title ); +}; + /** * Gets the twitter description from the state. * @@ -30,6 +42,19 @@ export const getTwitterTitle = state => get( state, "twitterEditor.title", "" ); */ export const getTwitterDescription = state => get( state, "twitterEditor.description", "" ); + +/** + * Gets the X description from the state. + * + * @param {object} state The state. + * + * @returns {string} X description. + */ +export const getTwitterDescriptionWithoutTemplate = state => { + const description = getTwitterDescription( state ); + return getSocialDescriptionWithoutTemplate( description ); +}; + /** * Gets the twitter image URL from the state. * diff --git a/packages/js/src/shared-admin/constants/index.js b/packages/js/src/shared-admin/constants/index.js index 2108f6cec9a..587e5542af4 100644 --- a/packages/js/src/shared-admin/constants/index.js +++ b/packages/js/src/shared-admin/constants/index.js @@ -1,3 +1,9 @@ +export { + META_FIELDS, + HIDDEN_INPUT_ID_PREFIX, + POST_META_KEY_PREFIX, +} from "./meta-fields"; + /** * Keep constants centralized to avoid circular dependency problems. */ @@ -20,7 +26,16 @@ export const VIDEO_FLOW = { isPlaying: "isPlaying", }; -export const STORE_NAME_EDITOR = { - free: "yoast-seo/editor", - core: "core/editor", +export const STORES = { + editor: "yoast-seo/editor", + wp: { + editor: "core/editor", + core: "core", + }, +}; + +export const SYNC_TIME = { + wait: 500, + max: 1500, }; + diff --git a/packages/js/src/shared-admin/constants/meta-fields.js b/packages/js/src/shared-admin/constants/meta-fields.js new file mode 100644 index 00000000000..ad721519307 --- /dev/null +++ b/packages/js/src/shared-admin/constants/meta-fields.js @@ -0,0 +1,129 @@ +export const META_FIELDS = { + focusKeyphrase: { + key: "focuskw", + get: "getFocusKeyphrase", + set: "setFocusKeyword", + }, + robotsNoIndex: { + key: "meta-robots-noindex", + get: "getNoIndex", + set: "setNoIndex", + }, + robotsNoFollow: { + key: "meta-robots-nofollow", + get: "getNoFollow", + set: "setNoFollow", + }, + robotsAdvanced: { + key: "meta-robots-adv", + get: "getAdvanced", + set: "setAdvanced", + }, + facebookTitle: { + key: "opengraph-title", + get: "getFacebookTitleWithoutTemplate", + set: "setFacebookPreviewTitle", + }, + facebookDescription: { + key: "opengraph-description", + get: "getFacebookDescriptionWithoutTemplate", + set: "setFacebookPreviewDescription", + }, + facebookImageUrl: { + key: "opengraph-image", + get: "getFacebookImageUrl", + set: "setFacebookPreviewImage", + }, + facebookImageId: { + key: "opengraph-image-id", + get: "getFacebookImageId", + set: "setFacebookPreviewImage", + }, + twitterTitle: { + key: "twitter-title", + get: "getTwitterTitleWithoutTemplate", + set: "setTwitterPreviewTitle", + }, + twitterDescription: { + key: "twitter-description", + get: "getTwitterDescriptionWithoutTemplate", + set: "setTwitterPreviewDescription", + }, + twitterImageUrl: { + key: "twitter-image", + get: "getTwitterImageUrl", + set: "setTwitterPreviewImage", + }, + twitterImageId: { + key: "twitter-image-id", + get: "getTwitterImageId", + set: "setTwitterPreviewImage", + }, + schemaPageType: { + key: "schema_page_type", + get: "getPageType", + set: "setPageType", + }, + schemaArticleType: { + key: "schema_article_type", + get: "getArticleType", + set: "setArticleType", + }, + isCornerstone: { + key: "is_cornerstone", + get: "isCornerstoneContent", + set: "setCornerstoneContent", + }, + readabilityScore: { + key: "content_score", + get: "getReadabilityScore", + set: "setOverallReadabilityScore", + }, + seoScore: { + key: "linkdex", + get: "getScoreForFocusKeyword", + set: "setOverallSeoScore", + }, + inclusiveLanguageScore: { + key: "inclusive_language_score", + get: "getInclusiveLanguageScore", + set: "setOverallInclusiveLanguageScore", + }, + breadcrumbsTitle: { + key: "bctitle", + get: "getBreadcrumbsTitle", + set: "setBreadcrumbsTitle", + }, + canonical: { + key: "canonical", + get: "getCanonical", + set: "setCanonical", + }, + wordProofTimestamp: { + key: "wordproof_timestamp", + get: "getWordProofTimestamp", + set: "setWordProofTimestamp", + }, + seoTitle: { + key: "title", + get: "getSnippetEditorTitle", + set: "updateData", + }, + seoDescription: { + key: "metadesc", + get: "getSnippetEditorDescription", + set: "updateData", + }, + readingTime: { + key: "estimated-reading-time-minutes", + get: "getEstimatedReadingTime", + set: "setEstimatedReadingTime", + }, +}; + +export const HIDDEN_INPUT_ID_PREFIX = { + post: "yoast_wpseo_", + term: "hidden_wpseo_", +}; + +export const POST_META_KEY_PREFIX = `_${ HIDDEN_INPUT_ID_PREFIX.post }`; diff --git a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js b/packages/js/tests/helpers/fields/analysisFieldsStore.test.js deleted file mode 100644 index 23e460661e1..00000000000 --- a/packages/js/tests/helpers/fields/analysisFieldsStore.test.js +++ /dev/null @@ -1,126 +0,0 @@ -import { - getFocusKeyphrase, - getReadabilityScore, - getInclusiveLanguageScore, - getSeoScore, - getEstimatedReadingTime, - isCornerstoneContent, -} from "../../../src/helpers/fields"; -import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; -import { select } from "@wordpress/data"; - -jest.mock( "@wordpress/data", () => ( { - select: jest.fn(), -} ) ); - - -const testCasesScoresInteger = [ - { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: 5 } }, - { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: 5 } }, - { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: 5 } }, - { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: 5 }, -]; - -describe.each( testCasesScoresInteger )( "$method", ( { method, getFunction, returnValueSelect } ) => { - it( `should return string from ${method} when the score is an integer`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => { - return returnValueSelect; - }, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "5" ); - } ); -} ); - -const testCasesScoresNull = [ - { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: null } }, - { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: null } }, - { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: null } }, - { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: null }, -]; - -describe.each( testCasesScoresNull )( "$method", ( { method, getFunction, returnValueSelect } ) => { - it( `should return zero string from ${method} when null`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => { - return returnValueSelect; - }, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "0" ); - } ); -} ); - -const testCasesScoresUndefined = [ - { method: "getReadabilityResults", getFunction: getReadabilityScore, returnValueSelect: { overallScore: undefined } }, - { method: "getInclusiveLanguageResults", getFunction: getInclusiveLanguageScore, returnValueSelect: { overallScore: undefined } }, - { method: "getSeoResults", getFunction: getSeoScore, returnValueSelect: { overallScore: undefined } }, - { method: "getEstimatedReadingTime", getFunction: getEstimatedReadingTime, returnValueSelect: undefined }, -]; - -describe.each( testCasesScoresUndefined )( "$method", ( { method, getFunction, returnValueSelect } ) => { - it( `should return zero string from ${method} when undefined`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => { - return returnValueSelect; - }, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "0" ); - } ); -} ); - - -const boolenaTestCases = [ - { value: true, expected: "1" }, - { value: false, expected: "0" }, -]; -describe.each( boolenaTestCases )( "isCornerstoneContent", ( { value, expected } ) => { - it( `should return ${expected} from isCornerstoneContent when value is ${value}`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - isCornerstoneContent: () => value, - }; - } - } ); - - const result = isCornerstoneContent(); - expect( result ).toBe( expected ); - } ); -} ); - -const focusKeyphraseTestCases = [ - { value: "test", expected: "test" }, -]; - -describe.each( focusKeyphraseTestCases )( "getFocusKeyphrase", ( { value, expected } ) => { - it( `should return ${expected} from getFocusKeyphrase when value is ${value}`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - getFocusKeyphrase: () => value, - }; - } - } ); - - const result = getFocusKeyphrase(); - expect( result ).toBe( expected ); - } ); -} ); diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index 314ff25d6af..48503788a8d 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -1,5 +1,5 @@ -import getPrimaryTerms from "../../../src/helpers/fields/primaryTaxonomiesFieldsStore"; -import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; +import { getPrimaryTerms } from "../../../src/helpers/fields/primaryTaxonomiesFieldsStore"; +import { STORES } from "../../../src/shared-admin/constants"; import { select } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { @@ -21,9 +21,9 @@ afterEach( ); const testCases = [ - { termId: 1, expected: "1" }, - { termId: -1, expected: "" }, - { termId: 0, expected: "" }, + { termId: 1, expected: 1 }, + { termId: -1, expected: -1 }, + { termId: 0, expected: 0 }, ]; describe.each( testCases )( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", ( { termId, expected } ) => { @@ -32,7 +32,7 @@ describe.each( testCases )( "getPrimaryTerm - should returns an object with taxo getPrimaryTaxonomyId.mockReturnValue( termId ); select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { + if ( store === STORES.editor ) { return { getPrimaryTaxonomyId, }; diff --git a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js b/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js deleted file mode 100644 index 35e6b217e22..00000000000 --- a/packages/js/tests/helpers/fields/getValuesFromStoreToSync.test.js +++ /dev/null @@ -1,119 +0,0 @@ -import { - getFacebookImageId, - getFacebookTitle, - getFacebookDescription, - getFacebookImageUrl, - getTwitterImageId, - getTwitterTitle, - getTwitterDescription, - getTwitterImageUrl, - getNoIndex, - getNoFollow, - getAdvanced, - getBreadcrumbsTitle, - getCanonical, - getWordProofTimestamp, - getPageType, - getArticleType, -} from "../../../src/helpers/fields"; -import { STORE_NAME_EDITOR } from "../../../src/shared-admin/constants"; -import { select } from "@wordpress/data"; - -// Tests for the facebookFieldsStore.js, twitterFieldsStore.js and adnacedSettingsFieldsStore.js files. - -jest.mock( "@wordpress/data", () => ( { - select: jest.fn(), -} ) ); - -const testCasesInteger = [ - { method: "getFacebookImageId", getFunction: getFacebookImageId }, - { method: "getTwitterImageId", getFunction: getTwitterImageId }, - { method: "getNoIndex", getFunction: getNoIndex }, - { method: "getNoFollow", getFunction: getNoFollow }, -]; - -describe.each( testCasesInteger )( "$method", ( { method, getFunction } ) => { - it( `should return string from ${method} when the value is an integer`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => 5, - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "5" ); - } ); -} ); - - -const testCases = [ - { method: "getFacebookImageId", getFunction: getFacebookImageId }, - { method: "getFacebookTitle", getFunction: getFacebookTitle }, - { method: "getFacebookDescription", getFunction: getFacebookDescription }, - { method: "getFacebookImageUrl", getFunction: getFacebookImageUrl }, - { method: "getTwitterImageId", getFunction: getTwitterImageId }, - { method: "getTwitterTitle", getFunction: getTwitterTitle }, - { method: "getTwitterDescription", getFunction: getTwitterDescription }, - { method: "getTwitterImageUrl", getFunction: getTwitterImageUrl }, - { method: "getAdvanced", getFunction: getAdvanced }, - { method: "getBreadcrumbsTitle", getFunction: getBreadcrumbsTitle }, - { method: "getCanonical", getFunction: getCanonical }, - { method: "getPageType", getFunction: getPageType }, - { method: "getArticleType", getFunction: getArticleType }, -]; - -describe.each( testCases )( "$method", ( { method, getFunction } ) => { - it( `should return string from ${method} when value is string`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - [ method ]: () => "string_result", - }; - } - } ); - - const result = getFunction(); - expect( result ).toBe( "string_result" ); - } ); -} ); - - -describe( "getWordProofTimestamp", () => { - it( "should return '1' when true", () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - getWordProofTimestamp: () => true, - }; - } - } ); - - const result = getWordProofTimestamp(); - expect( result ).toBe( "1" ); - } ); -} ); - -const getWordProofTimestampTestCases = [ - { value: true, expected: "1" }, - { value: false, expected: "" }, - { value: null, expected: "" }, - { value: undefined, expected: "" }, -]; -describe.each( getWordProofTimestampTestCases )( "getWordProofTimestamp", ( { value, expected } ) => { - it( `should return ${expected ? expected : "empty string" } from getWordProofTimestamp when value is ${value}`, () => { - select.mockImplementation( ( store ) => { - if ( store === STORE_NAME_EDITOR.free ) { - return { - getWordProofTimestamp: () => value, - }; - } - } ); - - const result = getWordProofTimestamp(); - expect( result ).toBe( expected ); - } ); -} ); - - diff --git a/src/presenters/admin/meta-fields-presenter.php b/src/presenters/admin/meta-fields-presenter.php index 32477e4bdc0..92b2dc1df30 100644 --- a/src/presenters/admin/meta-fields-presenter.php +++ b/src/presenters/admin/meta-fields-presenter.php @@ -49,8 +49,9 @@ public function present() { foreach ( $this->meta_fields as $key => $meta_field ) { $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); + $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); - $output .= '' . "\n"; + $output .= '' . "\n"; } return $output; From 438c89c60acddf80c869220bf84cf73931cf7e89 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:13:01 +0200 Subject: [PATCH 257/344] fix tests and primary taxonomy getters method --- .../fields/primaryTaxonomiesFieldsStore.js | 9 ++++----- .../tests/helpers/fields/getPrimaryTerms.test.js | 16 ++++++++-------- .../helpers/fields/hiddenFieldsSync.test.js | 6 +++--- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index dfa9ad6928b..07edc8961a3 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -9,9 +9,8 @@ import { STORES } from "../../shared-admin/constants"; */ export const getPrimaryTerms = () => { const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); - return reduce( primaryTerms, ( primaryTermGetters, value, key ) => { - primaryTermGetters[ `primary_${key}` ] = () => { - return select( STORES.editor ).getPrimaryTaxonomyId( key ); - }; - }, {} ); + return reduce(primaryTerms, (acc, value, key) => { + acc[`primary_${key}`] = () => select(STORES.editor).getPrimaryTaxonomyId(key); + return acc; + }, {}); }; diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index 48503788a8d..521c0f42365 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -21,15 +21,15 @@ afterEach( ); const testCases = [ - { termId: 1, expected: 1 }, - { termId: -1, expected: -1 }, - { termId: 0, expected: 0 }, + { termId: 1 }, + { termId: -1 }, + { termId: 0 }, ]; -describe.each( testCases )( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", ( { termId, expected } ) => { - it( `should returns ${expected ? expected : "empty string"} when the primary term id is ${termId}`, () => { +describe( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", () => { + it( `should returns when the primary term id`, () => { const getPrimaryTaxonomyId = jest.fn(); - getPrimaryTaxonomyId.mockReturnValue( termId ); + getPrimaryTaxonomyId.mockReturnValue( 1 ); select.mockImplementation( ( store ) => { if ( store === STORES.editor ) { @@ -86,7 +86,7 @@ describe.each( testCases )( "getPrimaryTerm - should returns an object with taxo const primaryCategory = actual.primary_category(); const primaryPostTag = actual.primary_post_tag(); - expect( primaryCategory ).toEqual( expected ); - expect( primaryPostTag ).toEqual( expected ); + expect( primaryCategory ).toEqual( 1 ); + expect( primaryPostTag ).toEqual( 1 ); } ); } ); diff --git a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js index 141747c1d8c..8c6357c6b2f 100644 --- a/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js +++ b/packages/js/tests/helpers/fields/hiddenFieldsSync.test.js @@ -1,6 +1,6 @@ import { hiddenFieldsSync } from "../../../src/helpers/fields/hiddenFieldsSync"; import { createCollectorFromObject, createWatcher } from "../../../src/helpers/create-watcher"; -import { mapKeys, debounce } from "lodash"; +import { reduce, debounce } from "lodash"; import { subscribe, select } from "@wordpress/data"; jest.mock( "@wordpress/data", () => ( { @@ -13,7 +13,7 @@ jest.mock( "lodash", () => ( { get: jest.fn( ()=> true ), pickBy: jest.fn( () => {} ), forEach: jest.fn(), - mapKeys: jest.fn( ()=>{ + reduce: jest.fn( ()=>{ return { test: "test" }; } ), } ) ); @@ -34,7 +34,7 @@ describe( "hiddenFieldsSync", () => { expect( subscribe ).toHaveBeenCalled(); expect( debounce ).toHaveBeenCalled(); expect( createWatcher ).toHaveBeenCalled(); - expect( mapKeys ).toHaveBeenCalledTimes( 2 ); + expect( reduce ).toHaveBeenCalledTimes( 2 ); expect( createCollectorFromObject ).toHaveBeenCalledWith( { test: "test" } ); } ); } ); From 85c0cdcaf517cf84649c97f942954fcd190eb85e Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:24:54 +0200 Subject: [PATCH 258/344] fix js eslint errors --- .../helpers/fields/getPrimaryTerms.test.js | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index 521c0f42365..16842421abb 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -20,14 +20,8 @@ afterEach( } ); -const testCases = [ - { termId: 1 }, - { termId: -1 }, - { termId: 0 }, -]; - describe( "getPrimaryTerm - should returns an object with taxonomies keys and fuctions that returns primary term id", () => { - it( `should returns when the primary term id`, () => { + it( "should return primary id from the primary term getter", () => { const getPrimaryTaxonomyId = jest.fn(); getPrimaryTaxonomyId.mockReturnValue( 1 ); @@ -58,20 +52,6 @@ describe( "getPrimaryTerm - should returns an object with taxonomies keys and fu }, ], }, - post_tag: { - title: "Post tag", - name: "post_tag", - primary: 5, - singularLabel: "Tag", - fieldId: "yoast_wpseo_primary_post_tag", - restBase: "tags", - terms: [ - { - id: 5, - name: "Test Tag", - }, - ], - }, }, }, } @@ -79,14 +59,9 @@ describe( "getPrimaryTerm - should returns an object with taxonomies keys and fu ); const actual = getPrimaryTerms(); - expect( actual ).toHaveProperty( "primary_category" ); - expect( actual ).toHaveProperty( "primary_post_tag" ); - const primaryCategory = actual.primary_category(); - const primaryPostTag = actual.primary_post_tag(); - expect( primaryCategory ).toEqual( 1 ); - expect( primaryPostTag ).toEqual( 1 ); + } ); } ); From 67437d9d17176590677a42ae7997c95f195495b5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:35:40 +0200 Subject: [PATCH 259/344] fix js eslint --- .../fields/primaryTaxonomiesFieldsStore.js | 6 ++--- .../js/src/redux/initial-state/analysis.js | 22 +++++++++---------- packages/js/src/redux/initial-state/index.js | 2 +- .../src/redux/initial-state/snippetEditor.js | 20 ++++++++--------- .../helpers/fields/getPrimaryTerms.test.js | 1 - 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js index 07edc8961a3..83f13b6c6d6 100644 --- a/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js +++ b/packages/js/src/helpers/fields/primaryTaxonomiesFieldsStore.js @@ -9,8 +9,8 @@ import { STORES } from "../../shared-admin/constants"; */ export const getPrimaryTerms = () => { const primaryTerms = get( window, "wpseoPrimaryCategoryL10n.taxonomies", {} ); - return reduce(primaryTerms, (acc, value, key) => { - acc[`primary_${key}`] = () => select(STORES.editor).getPrimaryTaxonomyId(key); + return reduce( primaryTerms, ( acc, value, key ) => { + acc[ `primary_${key}` ] = () => select( STORES.editor ).getPrimaryTaxonomyId( key ); return acc; - }, {}); + }, {} ); }; diff --git a/packages/js/src/redux/initial-state/analysis.js b/packages/js/src/redux/initial-state/analysis.js index 2c752866d59..4a30ca39b8c 100644 --- a/packages/js/src/redux/initial-state/analysis.js +++ b/packages/js/src/redux/initial-state/analysis.js @@ -1,16 +1,16 @@ import { get } from "lodash"; export const analysisInitialState = { - seo: { - results: [], - overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 )), - }, + seo: { + results: [], + overallScore: Number( get( window, "wpseoScriptData.metabox.metadata.linkdex", 0 ) ), + }, readability: { - results: [], - overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.content_score", 0 )), - }, + results: [], + overallScore: Number( get( window, "wpseoScriptData.metabox.metadata.content_score", 0 ) ), + }, inclusiveLanguage: { - results: [], - overallScore: Number(get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 )), - }, -}; \ No newline at end of file + results: [], + overallScore: Number( get( window, "wpseoScriptData.metabox.metadata.inclusive_language_score", 0 ) ), + }, +}; diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index dc873027bf6..cb97938a39d 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -24,7 +24,7 @@ const initialState = { insights: { estimatedReadingTime: Number( get( window, "wpseoScriptData.metabox.metadata.estimated-reading-time-minutes", 0 ) ), textLength: {}, - } + }, }; export default initialState; diff --git a/packages/js/src/redux/initial-state/snippetEditor.js b/packages/js/src/redux/initial-state/snippetEditor.js index ad23cdffa9d..372cd7e9c47 100644 --- a/packages/js/src/redux/initial-state/snippetEditor.js +++ b/packages/js/src/redux/initial-state/snippetEditor.js @@ -22,19 +22,17 @@ const getSlug = () => { return editorSelectors.getCurrentPostAttribute( "slug" ); } - var url = ""; - - var newPostSlug = document.getElementById( "new-post-slug" ); + const newPostSlug = document.getElementById( "new-post-slug" ); + const postSlug = document.getElementById( "editable-post-name-full" ); + const elementorSlugInput = document.getElementById( "yoast_wpseo_slug" ); + if ( newPostSlug ) { - url = newPostSlug.val(); - } else if ( document.getElementById( "editable-post-name-full" ) !== null ) { - url = document.getElementById( "editable-post-name-full" ).textContent; - }else if ( document.getElementById( "yoast_wpseo_slug" ) !== null ) { - // Get the slug from hidden fields in elementor editor. - url = document.getElementById( "yoast_wpseo_slug" ).value; + return newPostSlug.val(); + } else if ( postSlug !== null ) { + return postSlug.textContent; + } else if ( elementorSlugInput ) { + return elementorSlugInput.value; } - - return url; }; export const snippetEditorInitialState = { diff --git a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js index 16842421abb..ae5ed8ce13c 100644 --- a/packages/js/tests/helpers/fields/getPrimaryTerms.test.js +++ b/packages/js/tests/helpers/fields/getPrimaryTerms.test.js @@ -62,6 +62,5 @@ describe( "getPrimaryTerm - should returns an object with taxonomies keys and fu expect( actual ).toHaveProperty( "primary_category" ); const primaryCategory = actual.primary_category(); expect( primaryCategory ).toEqual( 1 ); - } ); } ); From 6e1afb0011d477bb4331983c1f29176003fddd9b Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:37:33 +0200 Subject: [PATCH 260/344] eslint fix cs --- packages/js/src/helpers/fields/blockEditorSync.js | 5 +---- packages/js/src/helpers/fields/hiddenFieldsSync.js | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index f90189e9e03..01529284100 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, pickBy, mapKeys, reduce } from "lodash"; +import { debounce, pickBy, reduce } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; import { STORES, META_FIELDS, SYNC_TIME, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; @@ -27,10 +27,7 @@ const createUpdater = () => { } const metadata = getEditedEntityRecord( "postType", currentPost.type, currentPost.id ).meta; - console.log( metadata ); const changedData = pickBy( data, ( value, key ) => transformMetaValue( key, value ) !== metadata[ POST_META_KEY_PREFIX + key ] ); - console.log( { changedData } ); - if ( changedData ) { editPost( { meta: changedData, diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index dcdfd0ac433..3b47002d4a0 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -24,7 +24,6 @@ export const createUpdater = () => { const field = document.getElementById( prefix + key ); const tranformedValue = transformMetaValue( key, value ); if ( field && field.value !== tranformedValue ) { - console.log( field.value, value, key, tranformedValue ) field.value = tranformedValue; } } ); @@ -39,7 +38,7 @@ export const hiddenFieldsSync = () => { const primaryTaxonomiesGetters = getPrimaryTerms(); const getters = reduce( META_FIELDS, ( acc, value ) => { - // check if value.get is a function in select( STORES.editor ) store + // check if value.get is a function in select( STORES.editor ) store if ( typeof select( STORES.editor )[ value.get ] === "function" ) { acc[ value.key ] = select( STORES.editor )[ value.get ]; } @@ -51,7 +50,7 @@ export const hiddenFieldsSync = () => { ...getters, ...primaryTaxonomiesGetters, // Slug is added for elementor editor. - slug: select( STORES.editor ).getSnippetEditorSlug + slug: select( STORES.editor ).getSnippetEditorSlug, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORES.editor ); From f17786d595747f3c0d24914d439ca7bf52ede903 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:43:03 +0200 Subject: [PATCH 261/344] fix php test --- tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php index fa96e4db92c..21bd0255514 100644 --- a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php +++ b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php @@ -186,7 +186,7 @@ public function test_display_fields_hidden() { ); $this->assertStringContainsString( - '', + '', $output ); } From 6bf99e2a5fac5abf41428cbf8b0aade86f37eb4f Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:51:05 +0200 Subject: [PATCH 262/344] fix eslint --- packages/js/src/helpers/fields/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/index.js b/packages/js/src/helpers/fields/index.js index ddcc120270c..a5291996a3c 100644 --- a/packages/js/src/helpers/fields/index.js +++ b/packages/js/src/helpers/fields/index.js @@ -1,3 +1,3 @@ export * from "./hasHiddenFields"; export * from "./blockEditorSync"; -export * from "./hiddenFieldsSync"; \ No newline at end of file +export * from "./hiddenFieldsSync"; From 0732a1cd3526280deab9dbe28c3bfb8c8bff4ac5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 14:57:31 +0200 Subject: [PATCH 263/344] fix php cs --- src/presenters/admin/meta-fields-presenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/presenters/admin/meta-fields-presenter.php b/src/presenters/admin/meta-fields-presenter.php index 92b2dc1df30..dd5f082a547 100644 --- a/src/presenters/admin/meta-fields-presenter.php +++ b/src/presenters/admin/meta-fields-presenter.php @@ -48,7 +48,7 @@ public function present() { $output = ''; foreach ( $this->meta_fields as $key => $meta_field ) { - $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); + $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); $output .= '' . "\n"; From dbb1985f6ee6e7f1e0460fa362a4ed9064c9ad14 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 16:37:26 +0200 Subject: [PATCH 264/344] refactor transforming values before comparing --- .../js/src/helpers/fields/blockEditorSync.js | 21 ++++++++++++++----- .../js/src/helpers/fields/hiddenFieldsSync.js | 6 +++--- .../helpers/fields/transform-meta-value.js | 11 ++++++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 01529284100..5e48082e465 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, pickBy, reduce } from "lodash"; +import { debounce, reduce, mapKeys } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; import { STORES, META_FIELDS, SYNC_TIME, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; @@ -11,7 +11,7 @@ import { transformMetaValue } from "./transform-meta-value"; */ const createUpdater = () => { const { editPost } = dispatch( STORES.wp.editor ); - const { getCurrentPost } = select( STORES.wp.core ); + const { getCurrentPost } = select( STORES.wp.editor ); const { getEditedEntityRecord } = select( "core" ); /** @@ -27,7 +27,18 @@ const createUpdater = () => { } const metadata = getEditedEntityRecord( "postType", currentPost.type, currentPost.id ).meta; - const changedData = pickBy( data, ( value, key ) => transformMetaValue( key, value ) !== metadata[ POST_META_KEY_PREFIX + key ] ); + + const changedData = reduce( data, ( acc, value, key ) => { + const fieldKey = key.replace( POST_META_KEY_PREFIX, "" ); + const transformedValue = transformMetaValue( fieldKey, value ); + const transformMetadataValue = transformMetaValue( fieldKey, metadata[ key ] ); + + if ( transformedValue !== transformMetadataValue ) { + acc[ key ] = transformedValue; + } + return acc; + }, data ); + if ( changedData ) { editPost( { meta: changedData, @@ -41,10 +52,10 @@ const createUpdater = () => { * @returns {function} The un-subscriber. */ export const blockEditorSync = () => { - const primaryTaxonomiesGetters = getPrimaryTerms(); + const primaryTaxonomiesGetters = mapKeys( getPrimaryTerms(), ( value, key ) => POST_META_KEY_PREFIX + key ); const getters = reduce( META_FIELDS, ( acc, value ) => { - acc[ value.key ] = select( STORES.editor )[ value.get ]; + acc[ POST_META_KEY_PREFIX + value.key ] = select( STORES.editor )[ value.get ]; return acc; }, {} ); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 3b47002d4a0..e93165b10ea 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -22,9 +22,9 @@ export const createUpdater = () => { forEach( data, ( value, key ) => { const field = document.getElementById( prefix + key ); - const tranformedValue = transformMetaValue( key, value ); - if ( field && field.value !== tranformedValue ) { - field.value = tranformedValue; + const transformedValue = transformMetaValue( key, value ); + if ( field && field.value !== transformedValue && ( transformedValue && field.value !== "0" ) ) { + field.value = transformedValue; } } ); }; diff --git a/packages/js/src/helpers/fields/transform-meta-value.js b/packages/js/src/helpers/fields/transform-meta-value.js index 28fdcee3c42..d8c1310c5bd 100644 --- a/packages/js/src/helpers/fields/transform-meta-value.js +++ b/packages/js/src/helpers/fields/transform-meta-value.js @@ -14,13 +14,10 @@ export const transformMetaValue = ( key, value ) => { case key === "linkdex": case key === "inclusive_language_score": case key === "estimated-reading-time-minutes": - if ( value >= 0 ) { + if ( value && value >= 0 ) { return String( value ); } return "0"; - case key === "is_cornerstone": - case key === "wordproof_timestamp": - return value ? "1" : "0"; case key.startsWith( "primary_" ): case key === "open_graph-image-id": case key === "twitter-image-id": @@ -28,8 +25,14 @@ export const transformMetaValue = ( key, value ) => { return String( value ); } return ""; + case key === "is_cornerstone": + case key === "wordproof_timestamp": + return value ? "1" : "0"; case key === "meta-robots-adv": return Array.isArray( value ) ? value.join() : value; + case value === "0": + case ! value: + return ""; default: return value; } From 06387067c6ec57486909999a17fcabce55d3dda5 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 16:37:47 +0200 Subject: [PATCH 265/344] restore primary term to avoid trigger of unsaved values --- admin/class-primary-term-admin.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index dbc473aba1a..5632b18c337 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -66,9 +66,10 @@ public function add_input_fields( $content ) { */ protected function primary_term_field( $taxonomy_name ) { return sprintf( - '', + '', esc_attr( $this->generate_field_id( $taxonomy_name ) ), - esc_attr( $this->generate_field_name( $taxonomy_name ) ) + esc_attr( $this->generate_field_name( $taxonomy_name ) ), + esc_attr( $this->get_primary_term( $taxonomy_name ) ) ); } From 9fd2b02d6321262651c670f4508faf1f5aab60e8 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 26 Apr 2024 16:51:04 +0200 Subject: [PATCH 266/344] fix comparing values in blockeditor sync --- packages/js/src/helpers/fields/blockEditorSync.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 5e48082e465..1310c29fc6e 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,5 +1,5 @@ import { dispatch, select, subscribe } from "@wordpress/data"; -import { debounce, reduce, mapKeys } from "lodash"; +import { debounce, reduce, mapKeys, forEach } from "lodash"; import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; import { STORES, META_FIELDS, SYNC_TIME, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; @@ -28,16 +28,17 @@ const createUpdater = () => { const metadata = getEditedEntityRecord( "postType", currentPost.type, currentPost.id ).meta; - const changedData = reduce( data, ( acc, value, key ) => { + const changedData = {}; + + forEach( data, ( value, key ) => { const fieldKey = key.replace( POST_META_KEY_PREFIX, "" ); const transformedValue = transformMetaValue( fieldKey, value ); const transformMetadataValue = transformMetaValue( fieldKey, metadata[ key ] ); if ( transformedValue !== transformMetadataValue ) { - acc[ key ] = transformedValue; + changedData[ key ] = transformedValue; } - return acc; - }, data ); + } ); if ( changedData ) { editPost( { From eaf30bf82a627157c3b3a38d2cf1852d92450bca Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 29 Apr 2024 13:33:44 +0200 Subject: [PATCH 267/344] Add defaults --- inc/class-wpseo-meta.php | 1 + packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- packages/js/src/helpers/fields/transform-meta-value.js | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 2d1a28bd4cb..20e79f5f401 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -331,6 +331,7 @@ public static function init() { }, 'type' => 'string', 'single' => true, + 'default' => $field_def['default_value'], ] ); diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index e93165b10ea..d5d2d9b3080 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -23,7 +23,7 @@ export const createUpdater = () => { forEach( data, ( value, key ) => { const field = document.getElementById( prefix + key ); const transformedValue = transformMetaValue( key, value ); - if ( field && field.value !== transformedValue && ( transformedValue && field.value !== "0" ) ) { + if ( field && field.value !== transformedValue ) { field.value = transformedValue; } } ); diff --git a/packages/js/src/helpers/fields/transform-meta-value.js b/packages/js/src/helpers/fields/transform-meta-value.js index d8c1310c5bd..2a8627fdc41 100644 --- a/packages/js/src/helpers/fields/transform-meta-value.js +++ b/packages/js/src/helpers/fields/transform-meta-value.js @@ -30,9 +30,6 @@ export const transformMetaValue = ( key, value ) => { return value ? "1" : "0"; case key === "meta-robots-adv": return Array.isArray( value ) ? value.join() : value; - case value === "0": - case ! value: - return ""; default: return value; } From 5a5f4b398b4770c8a068ca923f1e9747e47a4c73 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 29 Apr 2024 15:11:26 +0200 Subject: [PATCH 268/344] add slug to window object and initial state --- .../class-post-metabox-formatter.php | 6 ++++ packages/js/src/analysis/PostDataCollector.js | 2 +- .../helpers/fields/transform-meta-value.js | 3 ++ packages/js/src/initializers/post-scraper.js | 9 ++---- packages/js/src/redux/initial-state/index.js | 6 ++-- .../src/redux/initial-state/snippetEditor.js | 31 ++----------------- packages/js/src/redux/selectors/post.js | 6 ++++ 7 files changed, 24 insertions(+), 39 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 9b0630f6190..76647191879 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -89,6 +89,12 @@ public function get_values() { 'isInsightsEnabled' => $this->is_insights_enabled(), 'metadata' => $this->get_post_meta_data(), 'schemaDefaults' => $this->get_schema_defaults( $this->post->post_type ), + 'post' => [ + 'id' => $this->post->ID, + 'type' => $this->post->post_type, + 'slug' => $this->post->post_name, + 'status' => $this->post->post_status, + ], ]; $values = ( $values_to_set + $values ); diff --git a/packages/js/src/analysis/PostDataCollector.js b/packages/js/src/analysis/PostDataCollector.js index fb62b642633..d898af31621 100644 --- a/packages/js/src/analysis/PostDataCollector.js +++ b/packages/js/src/analysis/PostDataCollector.js @@ -126,7 +126,7 @@ PostDataCollector.prototype.getText = function() { * @returns {string} The title. */ PostDataCollector.prototype.getTitle = function() { - return document.getElementById( "title" ) && document.getElementById( "title" ).value || ""; + return ( document.getElementById( "title" ) && document.getElementById( "title" ).value ) || ""; }; /** diff --git a/packages/js/src/helpers/fields/transform-meta-value.js b/packages/js/src/helpers/fields/transform-meta-value.js index 2a8627fdc41..44e32c0f802 100644 --- a/packages/js/src/helpers/fields/transform-meta-value.js +++ b/packages/js/src/helpers/fields/transform-meta-value.js @@ -1,4 +1,5 @@ /* eslint-disable complexity */ +import { trim } from "lodash"; /** * Prepare value to be saved in hidden field. @@ -30,6 +31,8 @@ export const transformMetaValue = ( key, value ) => { return value ? "1" : "0"; case key === "meta-robots-adv": return Array.isArray( value ) ? value.join() : value; + case key === "title": + return trim( value ); default: return value; } diff --git a/packages/js/src/initializers/post-scraper.js b/packages/js/src/initializers/post-scraper.js index ed724d90c49..2d451b9c235 100644 --- a/packages/js/src/initializers/post-scraper.js +++ b/packages/js/src/initializers/post-scraper.js @@ -34,10 +34,8 @@ import isKeywordAnalysisActive from "../analysis/isKeywordAnalysisActive"; import isContentAnalysisActive from "../analysis/isContentAnalysisActive"; import isInclusiveLanguageAnalysisActive from "../analysis/isInclusiveLanguageAnalysisActive"; import { - getDataFromCollector, getDataFromStore, getDataWithoutTemplates, - getDataWithTemplates, getTemplatesFromL10n, } from "../analysis/snippetEditor"; import CustomAnalysisData from "../analysis/CustomAnalysisData"; @@ -513,12 +511,9 @@ export default function initPostScraper( $, store, editorData ) { } // Initialize the snippet editor data. - let snippetEditorData = getDataFromCollector( postDataCollector ); - const snippetEditorTemplates = getTemplatesFromL10n( wpseoScriptData.metabox ); - snippetEditorData = getDataWithTemplates( snippetEditorData, snippetEditorTemplates ); - // Set the initial snippet editor data. - store.dispatch( updateData( snippetEditorData ) ); + const snippetEditorTemplates = getTemplatesFromL10n( wpseoScriptData.metabox ); + const snippetEditorData = store.getState().snippetEditor.data; // Save the keyword, in order to compare it to store changes. let focusKeyword = store.getState().focusKeyword; diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index cb97938a39d..a0fb6860ace 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -17,8 +17,10 @@ const initialState = { primaryTaxonomies, schemaTab, post: { - isPost: get( window, "wpseoScriptData.isPost", false ), - id: Number( get( window, "wpseoScriptData.postId", null ) ), + isPost: get( window, "wpseoScriptData.metabox.post", false ), + id: Number( get( window, "wpseoScriptData.metabox.post.id", null ) ), + type: get( window, "wpseoScriptData.metabox.post.type", "" ), + status: get( window, "wpseoScriptData.metabox.post.status", "" ), }, analysis, insights: { diff --git a/packages/js/src/redux/initial-state/snippetEditor.js b/packages/js/src/redux/initial-state/snippetEditor.js index 372cd7e9c47..41cbded8c38 100644 --- a/packages/js/src/redux/initial-state/snippetEditor.js +++ b/packages/js/src/redux/initial-state/snippetEditor.js @@ -1,46 +1,19 @@ -import { select } from "@wordpress/data"; import { get } from "lodash"; -import { STORES } from "../../shared-admin/constants"; + import getDefaultReplacementVariables from "../../values/defaultReplaceVariables"; const titleTemplate = get( window, "wpseoScriptData.metabox.title_template", "" ); const descriptionTemplate = get( window, "wpseoScriptData.metabox.metadesc_template", "" ); const title = get( window, "wpseoScriptData.metabox.metadata.title", "" ); - const termDescription = get( window, "wpseoScriptData.metabox.metadata.desc", "" ); const description = get( window, "wpseoScriptData.metabox.metadata.metadesc", termDescription ); -/** - * Gets the slug. - * - * @returns {string} The slug. - */ -const getSlug = () => { - // Get the slug from the editor store. - const editorSelectors = select( STORES.wp.editor ); - if ( editorSelectors && editorSelectors.getCurrentPostAttribute( "slug" ) ) { - return editorSelectors.getCurrentPostAttribute( "slug" ); - } - - const newPostSlug = document.getElementById( "new-post-slug" ); - const postSlug = document.getElementById( "editable-post-name-full" ); - const elementorSlugInput = document.getElementById( "yoast_wpseo_slug" ); - - if ( newPostSlug ) { - return newPostSlug.val(); - } else if ( postSlug !== null ) { - return postSlug.textContent; - } else if ( elementorSlugInput ) { - return elementorSlugInput.value; - } -}; - export const snippetEditorInitialState = { mode: "mobile", data: { title: title || titleTemplate, description: description || descriptionTemplate, - slug: getSlug(), + slug: get( window, "wpseoScriptData.metabox.post.slug", "" ), }, wordsToHighlight: [], replacementVariables: getDefaultReplacementVariables(), diff --git a/packages/js/src/redux/selectors/post.js b/packages/js/src/redux/selectors/post.js index d59c64583f3..f14c0d882f5 100644 --- a/packages/js/src/redux/selectors/post.js +++ b/packages/js/src/redux/selectors/post.js @@ -11,3 +11,9 @@ export const getPostId = ( state ) => get( state, "post.id", null ); * @returns {string} Is post or term. */ export const getIsPost = ( state ) => get( state, "post.isPost", null ); + +/** + * @param {Ojbect} state The current Redux state. + * @returns {string} Is post or term. + */ +export const getPostType = ( state ) => get( state, "post.type", null ); From 730bd9dde46488587689a4d1cd7ce18d08220a22 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 30 Apr 2024 10:51:51 +0200 Subject: [PATCH 269/344] make sure post ID is the same in post and term --- admin/formatter/class-post-metabox-formatter.php | 11 ++++++----- admin/formatter/class-term-metabox-formatter.php | 4 ++++ packages/js/src/redux/initial-state/index.js | 8 ++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 76647191879..120754cb091 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -89,11 +89,12 @@ public function get_values() { 'isInsightsEnabled' => $this->is_insights_enabled(), 'metadata' => $this->get_post_meta_data(), 'schemaDefaults' => $this->get_schema_defaults( $this->post->post_type ), - 'post' => [ - 'id' => $this->post->ID, - 'type' => $this->post->post_type, - 'slug' => $this->post->post_name, - 'status' => $this->post->post_status, + 'entity' => [ + 'id' => $this->post->ID, + 'type' => $this->post->post_type, + 'slug' => $this->post->post_name, + 'status' => $this->post->post_status, + 'entityType' => 'post', ], ]; diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index db856415643..c14b6521158 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -87,6 +87,10 @@ public function get_values() { 'wincherIntegrationActive' => 0, 'isInsightsEnabled' => $this->is_insights_enabled(), 'metadata' => $this->get_term_metadata(), + 'entity' => [ + 'id' => $this->term->term_id, + 'entityType' => 'term', + ], ]; } diff --git a/packages/js/src/redux/initial-state/index.js b/packages/js/src/redux/initial-state/index.js index a0fb6860ace..7ae23a98211 100644 --- a/packages/js/src/redux/initial-state/index.js +++ b/packages/js/src/redux/initial-state/index.js @@ -17,10 +17,10 @@ const initialState = { primaryTaxonomies, schemaTab, post: { - isPost: get( window, "wpseoScriptData.metabox.post", false ), - id: Number( get( window, "wpseoScriptData.metabox.post.id", null ) ), - type: get( window, "wpseoScriptData.metabox.post.type", "" ), - status: get( window, "wpseoScriptData.metabox.post.status", "" ), + isPost: get( window, "wpseoScriptData.metabox.entity.entityType", false ) === "post", + id: Number( get( window, "wpseoScriptData.metabox.entity.id", null ) ), + type: get( window, "wpseoScriptData.metabox.entity.type", "" ), + status: get( window, "wpseoScriptData.metabox.entity.status", "" ), }, analysis, insights: { From 7321f50b9e0264f08fea6e6ac2ce65f5fe6488e4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 30 Apr 2024 14:47:25 +0200 Subject: [PATCH 270/344] change type in the method comment --- inc/class-wpseo-primary-term.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-primary-term.php b/inc/class-wpseo-primary-term.php index f5a5ccc22e5..3b5c17bf901 100644 --- a/inc/class-wpseo-primary-term.php +++ b/inc/class-wpseo-primary-term.php @@ -60,7 +60,7 @@ public function get_primary_term() { /** * Sets the new primary term ID. * - * @param int $new_primary_term New primary term ID. + * @param string $new_primary_term New primary term ID. * * @return void */ From 0f739890f9a331ba5079b7c2b4a9ef0d233f756d Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Tue, 30 Apr 2024 17:08:34 +0200 Subject: [PATCH 271/344] restore integer primary id after adding case for sanitazing meta data callback method --- tests/WP/Inc/Primary_Term_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP/Inc/Primary_Term_Test.php b/tests/WP/Inc/Primary_Term_Test.php index e0f02b83ede..107fe26d095 100644 --- a/tests/WP/Inc/Primary_Term_Test.php +++ b/tests/WP/Inc/Primary_Term_Test.php @@ -30,7 +30,7 @@ final class Primary_Term_Test extends TestCase { * * @var int */ - private $primary_term_id = '54'; + private $primary_term_id = 54; /** * Return the correct primary term when primary term already exists. From 41d6c67d4b60c8b97faa0ee9b633477d2b28dc83 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:42:06 +0200 Subject: [PATCH 272/344] Update admin/class-primary-term-admin.php Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 5632b18c337..19c03e86c03 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -6,6 +6,7 @@ */ use Yoast\WP\SEO\Helpers\Primary_Term_Helper; + /** * Adds the UI to change the primary term for a post. */ From 7c5ba0f4dd1915a9648a3aaddd021a81263a040c Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:42:27 +0200 Subject: [PATCH 273/344] Update admin/class-primary-term-admin.php Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 19c03e86c03..0ba4a692368 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -170,8 +170,7 @@ protected function get_primary_term_taxonomies( $post_id = null ) { return $taxonomies; } - $primary_term_helper = new Primary_Term_Helper(); - $taxonomies = $primary_term_helper->get_primary_term_taxonomies( $post_id ); + $taxonomies = YoastSEO()->helpers->primary_term->get_primary_term_taxonomies( $post_id ); wp_cache_set( 'primary_term_taxonomies_' . $post_id, $taxonomies, 'wpseo' ); From 9447178414696abb38d97cfc7793fa632edbe41a Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:42:47 +0200 Subject: [PATCH 274/344] Update admin/class-primary-term-admin.php typo fix Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 0ba4a692368..85b1c06afcf 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -189,7 +189,7 @@ protected function include_js_templates() { /** * Creates a map of taxonomies for localization. * - * @param array $taxonomies The taxononmies that should be mapped. + * @param array $taxonomies The taxonomies that should be mapped. * * @return array The mapped taxonomies. */ From 0f4a61b59bd26ad5b750f402c3fe5c6db9b77759 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:43:11 +0200 Subject: [PATCH 275/344] Update admin/class-primary-term-admin.php annotation fix Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 85b1c06afcf..71824b90005 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -191,7 +191,7 @@ protected function include_js_templates() { * * @param array $taxonomies The taxonomies that should be mapped. * - * @return array The mapped taxonomies. + * @return array>> The mapped taxonomies. */ protected function get_mapped_taxonomies_for_js( $taxonomies ) { return array_map( [ $this, 'map_taxonomies_for_js' ], $taxonomies ); From 42eb1854707f5b82dd85a8e221982b3a42e92518 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:43:46 +0200 Subject: [PATCH 276/344] Update admin/class-primary-term-admin.php annotation fix Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/class-primary-term-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 71824b90005..52435a15213 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -202,7 +202,7 @@ protected function get_mapped_taxonomies_for_js( $taxonomies ) { * * @param stdClass $taxonomy The taxonomy to map. * - * @return array> The mapped taxonomy. + * @return array> The mapped taxonomy. */ private function map_taxonomies_for_js( $taxonomy ) { $primary_term = $this->get_primary_term( $taxonomy->name ); From 722e6cab9b429cfb37e034c7f30ec98039f601fe Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 16:47:14 +0200 Subject: [PATCH 277/344] fix type annotation Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/formatter/class-term-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index c14b6521158..3db4b953e7a 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -168,7 +168,7 @@ private function base_url_for_js() { /** * Counting the number of given keyword used for other term than given term_id. * - * @return array> + * @return array> */ private function get_focus_keyword_usage() { $focuskw = WPSEO_Taxonomy_Meta::get_term_meta( $this->term, $this->term->taxonomy, 'focuskw' ); From e841d9860125b2e59418b3bbbf2b5250e6928df5 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 17:04:09 +0200 Subject: [PATCH 278/344] Update inc/class-wpseo-primary-term.php Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- inc/class-wpseo-primary-term.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-wpseo-primary-term.php b/inc/class-wpseo-primary-term.php index 3b5c17bf901..f5a5ccc22e5 100644 --- a/inc/class-wpseo-primary-term.php +++ b/inc/class-wpseo-primary-term.php @@ -60,7 +60,7 @@ public function get_primary_term() { /** * Sets the new primary term ID. * - * @param string $new_primary_term New primary term ID. + * @param int $new_primary_term New primary term ID. * * @return void */ From 8cfe4f826a2ab70ab54dda9fd57d2b03580ad8a4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 2 May 2024 17:15:58 +0200 Subject: [PATCH 279/344] restore the array type annotation to reduce testing scope and typo mistakes --- admin/class-primary-term-admin.php | 2 -- .../class-post-metabox-formatter.php | 29 +++++++++---------- .../class-term-metabox-formatter.php | 8 ++--- .../class-taxonomy-fields-presenter.php | 18 ++++++------ composer.json | 2 +- inc/class-wpseo-meta.php | 18 ++++++------ src/integrations/third-party/wordproof.php | 10 +++---- 7 files changed, 42 insertions(+), 45 deletions(-) diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 52435a15213..93cfc481f40 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -5,8 +5,6 @@ * @package WPSEO\Admin */ -use Yoast\WP\SEO\Helpers\Primary_Term_Helper; - /** * Adds the UI to change the primary term for a post. */ diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 120754cb091..8a4d544650f 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -37,10 +37,9 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Constructor. * - * @param WP_Post $post Post object. - * @param array $options Title options to use. - * - * @param string $structure The permalink to follow. + * @param WP_Post|array $post Post object. + * @param array $options Title options to use. + * @param string $structure The permalink to follow. */ public function __construct( $post, array $options, $structure ) { $this->post = $post; @@ -61,7 +60,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array> + * @return array */ public function get_values() { @@ -87,7 +86,7 @@ public function get_values() { 'social_description_template' => $this->get_social_description_template(), 'social_image_template' => $this->get_social_image_template(), 'isInsightsEnabled' => $this->is_insights_enabled(), - 'metadata' => $this->get_post_meta_data(), + 'metadata' => $this->get_post_metadata(), 'schemaDefaults' => $this->get_schema_defaults( $this->post->post_type ), 'entity' => [ 'id' => $this->post->ID, @@ -104,7 +103,7 @@ public function get_values() { /** * Filter: 'wpseo_post_edit_values' - Allows changing the values Yoast SEO uses inside the post editor. * - * @param array> $values The key-value map Yoast SEO uses inside the post editor. + * @param array $values The key-value map Yoast SEO uses inside the post editor. * @param WP_Post $post The post opened in the editor. */ return apply_filters( 'wpseo_post_edit_values', $values, $this->post ); @@ -168,7 +167,7 @@ private function base_url_for_js() { /** * Counts the number of given keywords used for other posts other than the given post_id. * - * @return array> The keyword and the associated posts that use it. + * @return array The keyword and the associated posts that use it. */ private function get_focus_keyword_usage() { $keyword = WPSEO_Meta::get_value( 'focuskw', $this->post->ID ); @@ -186,8 +185,8 @@ private function get_focus_keyword_usage() { /** * Retrieves the post types for the given post IDs. * - * @param array> $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. - * @return array The post types for the given post IDs. + * @param array $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used. + * @return array The post types for the given post IDs. */ private function get_post_types_for_all_ids( $post_ids_per_keyword ) { @@ -204,7 +203,7 @@ private function get_post_types_for_all_ids( $post_ids_per_keyword ) { * * @param string $keyword The keyword to check the usage of. * - * @return array The post IDs which use the passed keyword. + * @return array The post IDs which use the passed keyword. */ protected function get_keyword_usage_for_current_post( $keyword ) { return WPSEO_Meta::keyword_usage( $keyword, $this->post->ID ); @@ -333,9 +332,9 @@ protected function is_insights_enabled() { * * @return array */ - protected function get_post_meta_data() { + private function get_post_metadata() { $post_type = $this->post->post_type; - $meta_data = []; + $metadata = []; $metadata_groups = YoastSEO()->classes->get( Metadata_Groups::class ); @@ -344,11 +343,11 @@ protected function get_post_meta_data() { foreach ( $groups as $group ) { $fields = WPSEO_Meta::get_meta_field_defs( $group, $post_type ); foreach ( $fields as $key => $meta_field ) { - $meta_data[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); + $metadata[ $key ] = WPSEO_Meta::get_value( $key, $this->post->ID ); } } - return $meta_data; + return $metadata; } /** diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 3db4b953e7a..945b4472a1f 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -34,7 +34,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Array with the WPSEO_Titles options. * - * @var array + * @var array */ protected $options; @@ -63,7 +63,7 @@ public function use_social_templates() { /** * Returns the translated values. * - * @return array> + * @return array */ public function get_values() { $values = []; @@ -102,7 +102,7 @@ public function get_values() { * * @return array */ - protected function get_term_metadata() { + private function get_term_metadata() { $metadata = []; $fields_presenter = new WPSEO_Taxonomy_Fields_Presenter( $this->term ); $field_definitions = new WPSEO_Taxonomy_Fields(); @@ -168,7 +168,7 @@ private function base_url_for_js() { /** * Counting the number of given keyword used for other term than given term_id. * - * @return array> + * @return array */ private function get_focus_keyword_usage() { $focuskw = WPSEO_Taxonomy_Meta::get_term_meta( $this->term, $this->term->taxonomy, 'focuskw' ); diff --git a/admin/taxonomy/class-taxonomy-fields-presenter.php b/admin/taxonomy/class-taxonomy-fields-presenter.php index c26ccbef00d..dbef6711b79 100644 --- a/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -13,7 +13,7 @@ class WPSEO_Taxonomy_Fields_Presenter { /** * The taxonomy meta data for the current term. * - * @var array> + * @var array */ private $tax_meta; @@ -29,7 +29,7 @@ public function __construct( $term ) { /** * Displaying the form fields. * - * @param array> $fields Array with the fields that will be displayed. + * @param array $fields Array with the fields that will be displayed. * * @return string */ @@ -44,8 +44,8 @@ public function html( array $fields ) { /** * Create a row in the form table. * - * @param string $field_name Variable the row controls. - * @param array $field_configuration Array with the field configuration. + * @param string $field_name Variable the row controls. + * @param array $field_configuration Array with the field configuration. * * @return string */ @@ -70,10 +70,10 @@ private function form_row( $field_name, array $field_configuration ) { /** * 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. + * @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 */ @@ -174,7 +174,7 @@ public function get_field_value( $field_name ) { /** * Getting the class attributes if $options contains a class key. * - * @param array $options The array with field options. + * @param array $options The array with field options. * * @return string */ diff --git a/composer.json b/composer.json index 05a45e18038..82fb11f3652 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2514", + "@putenv YOASTCS_THRESHOLD_ERRORS=2542", "@putenv YOASTCS_THRESHOLD_WARNINGS=267", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 20e79f5f401..64430a34789 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -73,7 +73,7 @@ class WPSEO_Meta { * in the relevant child classes (WPSEO_Metabox and WPSEO_Social_admin) as they are only needed there. * - Beware: even though the meta keys are divided into subsets, they still have to be uniquely named!}} * - * @var array>> + * @var array * Array format: * (required) 'type' => (string) field type. i.e. text / textarea / checkbox / * radio / select / multiselect / upload etc. @@ -240,7 +240,7 @@ class WPSEO_Meta { * ['subset'] => (string) primary index * ['key'] => (string) internal key * - * @var array> + * @var array */ public static $fields_index = []; @@ -248,7 +248,7 @@ class WPSEO_Meta { * Helper property - array containing only the defaults in the format: * [full meta key including prefix] => (string) default value * - * @var array + * @var array */ public static $defaults = []; @@ -383,7 +383,7 @@ public static function get_show_in_rest_args( $type ) { * @param string $tab Tab for which to retrieve the field definitions. * @param string $post_type Post type of the current post. * - * @return array>> Array containing the meta box field definitions. + * @return array Array containing the meta box field definitions. */ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { if ( ! isset( self::$meta_fields[ $tab ] ) ) { @@ -460,8 +460,8 @@ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { /** * Validate the post meta values. * - * @param string|int|bool $meta_value The new value. - * @param string $meta_key The full meta key (including prefix). + * @param mixed $meta_value The new value. + * @param string $meta_key The full meta key (including prefix). * * @return string Validated meta value. */ @@ -1040,7 +1040,7 @@ public static function array_merge_recursive_distinct() { * @param string $keyword The keyword to be counted. * @param int $post_id The id of the post to which the keyword belongs. * - * @return array + * @return array */ public static function keyword_usage( $keyword, $post_id ) { @@ -1090,9 +1090,9 @@ public static function keyword_usage( $keyword, $post_id ) { /** * Returns the post types for the given post ids. * - * @param array $post_ids The post ids to get the post types for. + * @param array $post_ids The post ids to get the post types for. * - * @return array The post types. + * @return array The post types. */ public static function post_types_for_ids( $post_ids ) { diff --git a/src/integrations/third-party/wordproof.php b/src/integrations/third-party/wordproof.php index 819b62fc244..9c11fcd7227 100644 --- a/src/integrations/third-party/wordproof.php +++ b/src/integrations/third-party/wordproof.php @@ -61,7 +61,7 @@ public function __construct( Wordproof_Helper $wordproof, ?WPSEO_Admin_Asset_Man /** * Returns the conditionals based in which this loadable should be active. * - * @return array + * @return array */ public static function get_conditionals() { return [ @@ -162,8 +162,8 @@ public function disable_timestamp_for_previous_legal_page( $old_post_id, $new_po /** * Return the Yoast post meta key for the SDK to determine if the post should be timestamped. * - * @param array $meta_keys The array containing meta keys that should be used. - * @return array + * @param array $meta_keys The array containing meta keys that should be used. + * @return array */ public function add_post_meta_key( $meta_keys ) { return [ $this->post_meta_key ]; @@ -172,8 +172,8 @@ public function add_post_meta_key( $meta_keys ) { /** * Return an empty array to disable automatically timestamping selected post types. * - * @param array $post_types The array containing post types that should be automatically timestamped. - * @return array Empty array. + * @param array $post_types The array containing post types that should be automatically timestamped. + * @return array Empty array. */ public function wordproof_timestamp_post_types( $post_types ) { return []; From a554778fe5063f981c4f080187833da55027f4df Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Thu, 2 May 2024 17:17:42 +0200 Subject: [PATCH 280/344] fix spaces --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 8a4d544650f..bb56ddcf75f 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -104,7 +104,7 @@ public function get_values() { * Filter: 'wpseo_post_edit_values' - Allows changing the values Yoast SEO uses inside the post editor. * * @param array $values The key-value map Yoast SEO uses inside the post editor. - * @param WP_Post $post The post opened in the editor. + * @param WP_Post $post The post opened in the editor. */ return apply_filters( 'wpseo_post_edit_values', $values, $this->post ); } From 83a99eaf5f6e8aeea1c91d0625ac133fe2bea562 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Thu, 2 May 2024 17:18:57 +0200 Subject: [PATCH 281/344] use di container Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- admin/formatter/class-post-metabox-formatter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index bb56ddcf75f..ba9130cce29 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -364,8 +364,7 @@ private function get_schema_defaults( $post_type ) { $schema_defaults['pageType'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); - $article_helper = new Article_Helper(); - if ( $article_helper->is_article_post_type( $post_type ) ) { + if ( YoastSEO()->helpers->schema->article->is_article_post_type( $post_type ) ) { $default_schema_article_type = WPSEO_Options::get( 'schema-article-type-' . $post_type ); /** This filter is documented in inc/options/class-wpseo-option-titles.php */ From cd853300aad7c70bca0a4444f9d38f1281147b6b Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 09:42:11 +0200 Subject: [PATCH 282/344] add comment for entity type --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index ba9130cce29..07b4184d3c6 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -93,7 +93,7 @@ public function get_values() { 'type' => $this->post->post_type, 'slug' => $this->post->post_name, 'status' => $this->post->post_status, - 'entityType' => 'post', + 'entityType' => 'post', // Entity type either post or term. ], ]; From 0aa4c63fe3d1b9b30c6c095c4dfd1a2ebc1c7d2c Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 09:53:59 +0200 Subject: [PATCH 283/344] fix slug initial state --- packages/js/src/redux/initial-state/snippetEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/redux/initial-state/snippetEditor.js b/packages/js/src/redux/initial-state/snippetEditor.js index 41cbded8c38..aaa1db52b54 100644 --- a/packages/js/src/redux/initial-state/snippetEditor.js +++ b/packages/js/src/redux/initial-state/snippetEditor.js @@ -13,7 +13,7 @@ export const snippetEditorInitialState = { data: { title: title || titleTemplate, description: description || descriptionTemplate, - slug: get( window, "wpseoScriptData.metabox.post.slug", "" ), + slug: get( window, "wpseoScriptData.metabox.entity.slug", "" ), }, wordsToHighlight: [], replacementVariables: getDefaultReplacementVariables(), From b054061befae6b1a076ebc528e2afeb3e8cafef4 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 11:12:39 +0200 Subject: [PATCH 284/344] bail when getData is not a function, defensive coding add defensive coding add defensive coding --- packages/js/src/helpers/create-watcher.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/js/src/helpers/create-watcher.js b/packages/js/src/helpers/create-watcher.js index 432bd7b8e20..19432c4bbae 100644 --- a/packages/js/src/helpers/create-watcher.js +++ b/packages/js/src/helpers/create-watcher.js @@ -21,6 +21,12 @@ export const createCollector = ( ...getters ) => () => getters.map( getData => g * @returns {function} The watcher. */ export const createWatcher = ( getData, onChange ) => { + // Bail if getData is not a function. + if ( typeof getData !== "function" ) { + console.error( "Getter is not a function." ); + return; + } + // Save the current data for comparison. let previous = getData(); @@ -51,6 +57,11 @@ export const createWatcher = ( getData, onChange ) => { export const createCollectorFromObject = ( getters ) => () => reduce( getters, ( result, getData, key ) => { + // Bail if getData is not a function. + if ( typeof getData !== "function" ) { + console.error( `${key} getter is not a function.` ); + return; + } result[ key ] = getData(); return result; }, From c80b7bb747641beb7041380430fafce4741ec273 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 11:27:27 +0200 Subject: [PATCH 285/344] fix sync of slug to hidden fields --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index d5d2d9b3080..ebfb925289b 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -49,8 +49,8 @@ export const hiddenFieldsSync = () => { createCollectorFromObject( { ...getters, ...primaryTaxonomiesGetters, - // Slug is added for elementor editor. - slug: select( STORES.editor ).getSnippetEditorSlug, + // Slug is added for elementor editor, used only when hidden field for slug exist. + slug: select( STORES.editor ).getEditorDataSlug, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORES.editor ); From 057ec64a7e60c5e8a2c7a2fc316fa9e3639110c9 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 14:51:22 +0200 Subject: [PATCH 286/344] restore the usage of snippet editor slug selector --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index ebfb925289b..44f97c80050 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -50,7 +50,7 @@ export const hiddenFieldsSync = () => { ...getters, ...primaryTaxonomiesGetters, // Slug is added for elementor editor, used only when hidden field for slug exist. - slug: select( STORES.editor ).getEditorDataSlug, + slug: select( STORES.editor ).getSnippetEditorSlug, } ), createUpdater() ), SYNC_TIME.wait, { maxWait: SYNC_TIME.max } ), STORES.editor ); From b12a2c48579297fbdb680b31de26cabc2d21cd86 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 14:59:54 +0200 Subject: [PATCH 287/344] sync seo description in term editor --- packages/js/src/shared-admin/constants/meta-fields.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/js/src/shared-admin/constants/meta-fields.js b/packages/js/src/shared-admin/constants/meta-fields.js index ad721519307..f41d456f356 100644 --- a/packages/js/src/shared-admin/constants/meta-fields.js +++ b/packages/js/src/shared-admin/constants/meta-fields.js @@ -114,6 +114,11 @@ export const META_FIELDS = { get: "getSnippetEditorDescription", set: "updateData", }, + seoDescriptionTerm: { + key: "desc", + get: "getSnippetEditorDescription", + set: "updateData", + }, readingTime: { key: "estimated-reading-time-minutes", get: "getEstimatedReadingTime", From a6f04b1bcc0c2c269399c0da8aafdb326077ff25 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 15:00:13 +0200 Subject: [PATCH 288/344] fix snippet editor slug in term editor --- admin/formatter/class-term-metabox-formatter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index 945b4472a1f..a2b61567f3e 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -89,6 +89,7 @@ public function get_values() { 'metadata' => $this->get_term_metadata(), 'entity' => [ 'id' => $this->term->term_id, + 'slug' => $this->term->slug, 'entityType' => 'term', ], ]; From 3d195c6d59ca412549d54036af8847cb7e883b18 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 15:15:19 +0200 Subject: [PATCH 289/344] remove import --- admin/formatter/class-post-metabox-formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/formatter/class-post-metabox-formatter.php b/admin/formatter/class-post-metabox-formatter.php index 07b4184d3c6..dd21d575a15 100644 --- a/admin/formatter/class-post-metabox-formatter.php +++ b/admin/formatter/class-post-metabox-formatter.php @@ -7,7 +7,7 @@ use Yoast\WP\SEO\Config\Schema_Types; use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; -use Yoast\WP\SEO\Helpers\Schema\Article_Helper; + /** * This class provides data for the post metabox by return its values for localization. */ From 2d63760d31179473aa17d8a69f50b8ce01342213 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 15:19:58 +0200 Subject: [PATCH 290/344] remove complexity disable comment --- packages/js/src/elementor/containers/ElementorFill.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/js/src/elementor/containers/ElementorFill.js b/packages/js/src/elementor/containers/ElementorFill.js index 393974f32df..41a9138b9cb 100644 --- a/packages/js/src/elementor/containers/ElementorFill.js +++ b/packages/js/src/elementor/containers/ElementorFill.js @@ -2,7 +2,6 @@ import { compose } from "@wordpress/compose"; import { withSelect } from "@wordpress/data"; import ElementorFill from "../components/fills/ElementorFill"; -/* eslint-disable complexity */ export default compose( [ withSelect( select => { const { @@ -14,4 +13,3 @@ export default compose( [ }; } ), ] )( ElementorFill ); -/* eslint-enable complexity */ From 35647498673ae121b14c89d055599089d1eeceb9 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 15:34:44 +0200 Subject: [PATCH 291/344] I removed the slug case because sync is taken take of by the hidden fields sync --- packages/js/src/elementor/containers/SnippetEditor.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/js/src/elementor/containers/SnippetEditor.js b/packages/js/src/elementor/containers/SnippetEditor.js index b3d268b5158..3ba2b650a38 100644 --- a/packages/js/src/elementor/containers/SnippetEditor.js +++ b/packages/js/src/elementor/containers/SnippetEditor.js @@ -136,9 +136,6 @@ export default compose( [ case "mode": switchMode( value ); break; - case "slug": - updateData( { slug: value } ); - break; default: updateData( { [ key ]: value, From 513f6415be25d1d096e1c2f7bb47fd53719d6dac Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Fri, 3 May 2024 16:07:34 +0200 Subject: [PATCH 292/344] add space --- admin/formatter/class-term-metabox-formatter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/formatter/class-term-metabox-formatter.php b/admin/formatter/class-term-metabox-formatter.php index a2b61567f3e..d1c8b69f12e 100644 --- a/admin/formatter/class-term-metabox-formatter.php +++ b/admin/formatter/class-term-metabox-formatter.php @@ -5,6 +5,7 @@ * @package WPSEO\Admin\Formatter */ use Yoast\WP\SEO\Editors\Framework\Metadata_Groups; + /** * This class provides data for the term metabox by return its values for localization. */ From c7278445f4a06ebe0959b6918fbcce33d2db8188 Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Mon, 6 May 2024 16:47:41 +0200 Subject: [PATCH 293/344] Update packages/js/src/helpers/fields/blockEditorSync.js Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- packages/js/src/helpers/fields/blockEditorSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/blockEditorSync.js b/packages/js/src/helpers/fields/blockEditorSync.js index 1310c29fc6e..378e9aef5ee 100644 --- a/packages/js/src/helpers/fields/blockEditorSync.js +++ b/packages/js/src/helpers/fields/blockEditorSync.js @@ -1,6 +1,6 @@ import { dispatch, select, subscribe } from "@wordpress/data"; import { debounce, reduce, mapKeys, forEach } from "lodash"; -import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "../create-watcher"; import { STORES, META_FIELDS, SYNC_TIME, POST_META_KEY_PREFIX } from "../../shared-admin/constants"; import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; import { transformMetaValue } from "./transform-meta-value"; From 27ae693338bbd1bf333529fd3532ce1d3f380f3f Mon Sep 17 00:00:00 2001 From: Vraja Das <65466507+vraja-pro@users.noreply.github.com> Date: Mon, 6 May 2024 16:47:48 +0200 Subject: [PATCH 294/344] Update packages/js/src/helpers/fields/hiddenFieldsSync.js Co-authored-by: Igor <35524806+igorschoester@users.noreply.github.com> --- packages/js/src/helpers/fields/hiddenFieldsSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/helpers/fields/hiddenFieldsSync.js b/packages/js/src/helpers/fields/hiddenFieldsSync.js index 44f97c80050..3b3e32c0bcb 100644 --- a/packages/js/src/helpers/fields/hiddenFieldsSync.js +++ b/packages/js/src/helpers/fields/hiddenFieldsSync.js @@ -1,7 +1,7 @@ /* eslint-disable complexity */ import { select, subscribe } from "@wordpress/data"; import { debounce, forEach, reduce } from "lodash"; -import { createWatcher, createCollectorFromObject } from "../../helpers/create-watcher"; +import { createWatcher, createCollectorFromObject } from "../create-watcher"; import { STORES, HIDDEN_INPUT_ID_PREFIX, SYNC_TIME, META_FIELDS } from "../../shared-admin/constants"; import { getPrimaryTerms } from "./primaryTaxonomiesFieldsStore"; import { transformMetaValue } from "./transform-meta-value"; From 507b9f93cf2570a580e943bc4826f7b1fb49c970 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 6 May 2024 16:30:33 +0200 Subject: [PATCH 295/344] remove the function check --- packages/js/src/helpers/create-watcher.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/js/src/helpers/create-watcher.js b/packages/js/src/helpers/create-watcher.js index 19432c4bbae..432bd7b8e20 100644 --- a/packages/js/src/helpers/create-watcher.js +++ b/packages/js/src/helpers/create-watcher.js @@ -21,12 +21,6 @@ export const createCollector = ( ...getters ) => () => getters.map( getData => g * @returns {function} The watcher. */ export const createWatcher = ( getData, onChange ) => { - // Bail if getData is not a function. - if ( typeof getData !== "function" ) { - console.error( "Getter is not a function." ); - return; - } - // Save the current data for comparison. let previous = getData(); @@ -57,11 +51,6 @@ export const createWatcher = ( getData, onChange ) => { export const createCollectorFromObject = ( getters ) => () => reduce( getters, ( result, getData, key ) => { - // Bail if getData is not a function. - if ( typeof getData !== "function" ) { - console.error( `${key} getter is not a function.` ); - return; - } result[ key ] = getData(); return result; }, From 88821e0ccf2149836f5a5d13134078ec21d0e044 Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 6 May 2024 16:43:17 +0200 Subject: [PATCH 296/344] don't show in rest if type is null --- inc/class-wpseo-meta.php | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 64430a34789..58b3e6339de 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -325,13 +325,16 @@ public static function init() { self::$meta_prefix . $key, [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ], - 'show_in_rest' => self::get_show_in_rest_args( $field_def['type'] ), - 'auth_callback' => static function () { - return current_user_can( 'edit_posts' ); - }, + 'show_in_rest' => isset( $field_def['type'] ) ? [ + 'schema' => [ + 'type' => 'string', + 'context' => [ 'edit' ], + ], + ] : false, + 'auth_callback' => [ self, 'auth_callback' ], 'type' => 'string', 'single' => true, - 'default' => $field_def['default_value'], + 'default' => ( $field_def['default_value'] ?? '' ), ] ); @@ -360,21 +363,12 @@ public static function init() { } /** - * Get show_in_rest args for a meta field. + * Call back function for auth_callback in register_meta. * - * @param string|null $type The type of the field. - * @return bool|array|string> $args The show_in_rest args. + * @return bool */ - public static function get_show_in_rest_args( $type ) { - if ( ! $type ) { - return false; - } - return [ - 'schema' => [ - 'type' => 'string', - 'context' => [ 'edit' ], - ], - ]; + public function auth_callback() { + return current_user_can( 'edit_posts' ); } /** From 82f243aa4808876c28527a8791478f6be9f1333c Mon Sep 17 00:00:00 2001 From: vraja-pro Date: Mon, 6 May 2024 16:45:58 +0200 Subject: [PATCH 297/344] rename show article type action and property in the store --- packages/js/src/components/SchemaTab.js | 4 ++-- packages/js/src/redux/initial-state/schemaTab.js | 2 +- packages/js/src/redux/selectors/schemaTab.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js/src/components/SchemaTab.js b/packages/js/src/components/SchemaTab.js index 40c82a8eb98..381f7a63df8 100644 --- a/packages/js/src/components/SchemaTab.js +++ b/packages/js/src/components/SchemaTab.js @@ -171,7 +171,7 @@ const Content = ( props ) => { const woocommerceUpsellText = __( "Want your products stand out in search results with rich results like price, reviews and more?", "wordpress-seo" ); const isProduct = useSelect( ( select ) => select( STORES.editor ).getIsProduct(), [] ); const isWooSeoActive = useSelect( select => select( STORES.editor ).getIsWooSeoActive(), [] ); - const showArticleTypeInput = useSelect( select => select( STORES.editor ).getShowArticleTypeInput(), [] ); + const showArticleType = useSelect( select => select( STORES.editor ).getShowArticleType(), [] ); const disablePageTypeSelect = isProduct && isWooSeoActive; const handleOptionChange = useCallback( @@ -204,7 +204,7 @@ const Content = ( props ) => { selected={ disablePageTypeSelect ? "ItemPage" : props.schemaPageTypeSelected } disabled={ disablePageTypeSelect } /> - { showArticleTypeInput &&