+
+ { __( "Outputs a single graph the web can understand. Makes every person, product, organization, and piece of content consistently readable to search engines and language models.", "wordpress-seo" ) }
+
+
{
...indexablePagesActions,
...linkParamsActions,
...llmsTxtActions,
+ ...schemaFrameworkActions,
...mediaActions,
...notificationsActions,
...pageActions,
@@ -89,6 +96,7 @@ const createStore = ( { initialState } ) => {
...indexablePagesSelectors,
...linkParamsSelectors,
...llmsTxtSelectors,
+ ...schemaFrameworkSelectors,
...mediaSelectors,
...notificationsSelectors,
...pageSelectors,
@@ -116,6 +124,7 @@ const createStore = ( { initialState } ) => {
preferences: createInitialPreferencesState(),
replacementVariables: createInitialReplacementVariablesState(),
schema: createInitialSchemaState(),
+ [ SCHEMA_FRAMEWORK_NAME ]: createInitialSchemaFrameworkState(),
search: createInitialSearchState(),
taxonomies: createInitialTaxonomiesState(),
users: createInitialUsersState(),
@@ -137,6 +146,7 @@ const createStore = ( { initialState } ) => {
preferences,
replacementVariables,
schema,
+ schemaFramework,
search,
taxonomies,
users,
diff --git a/packages/js/src/settings/store/schema-framework.js b/packages/js/src/settings/store/schema-framework.js
new file mode 100644
index 00000000000..09ce9683e73
--- /dev/null
+++ b/packages/js/src/settings/store/schema-framework.js
@@ -0,0 +1,28 @@
+import { createSlice } from "@reduxjs/toolkit";
+import { get } from "lodash";
+
+// Action name constants
+export const SCHEMA_FRAMEWORK_NAME = "schemaFramework";
+
+/**
+ * @returns {Object} The initial schemaFramework state.
+ */
+export const createInitialSchemaFrameworkState = () =>(
+ {
+ isSchemaDisabled: false,
+ }
+);
+
+const slice = createSlice( {
+ name: SCHEMA_FRAMEWORK_NAME,
+ initialState: createInitialSchemaFrameworkState(),
+ reducers: {},
+} );
+
+export const schemaFrameworkActions = slice.actions;
+
+export const schemaFrameworkSelectors = {
+ selectSchemaIsSchemaDisabled: state => get( state, "schemaFramework.isSchemaDisabled", false ),
+};
+
+export default slice.reducer;
diff --git a/src/conditionals/schema-disabled-conditional.php b/src/conditionals/schema-disabled-conditional.php
new file mode 100644
index 00000000000..0244493d43a
--- /dev/null
+++ b/src/conditionals/schema-disabled-conditional.php
@@ -0,0 +1,36 @@
+options = $options;
+ }
+
+ /**
+ * Returns `true` whether the schema is disabled.
+ *
+ * @return bool `true` when the schema is disabled.
+ */
+ public function is_met() {
+ return ! $this->options->get( 'enable_schema', true );
+ }
+}
diff --git a/src/integrations/admin/integrations-page.php b/src/integrations/admin/integrations-page.php
index 56cb3950566..e701cd821fc 100644
--- a/src/integrations/admin/integrations-page.php
+++ b/src/integrations/admin/integrations-page.php
@@ -234,6 +234,7 @@ public function enqueue_assets() {
'plugin_url' => \plugins_url( '', \WPSEO_FILE ),
'site_kit_configuration' => $this->site_kit_integration_data->to_array(),
'site_kit_consent_management_url' => $this->site_kit_consent_management_endpoint->get_url(),
+ 'schema_framework_enabled' => $this->options_helper->get( 'enable_schema', true ),
]
);
}
diff --git a/src/integrations/settings-integration.php b/src/integrations/settings-integration.php
index 4f4cec22cd1..2ce0198d861 100644
--- a/src/integrations/settings-integration.php
+++ b/src/integrations/settings-integration.php
@@ -32,6 +32,7 @@
use Yoast\WP\SEO\Llms_Txt\Application\Health_Check\File_Runner;
use Yoast\WP\SEO\Llms_Txt\Infrastructure\Content\Manual_Post_Collection;
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager;
+use Yoast\WP\SEO\Schema\Application\Configuration\Schema_Configuration;
/**
* Class Settings_Integration.
@@ -199,6 +200,12 @@ class Settings_Integration implements Integration_Interface {
*/
protected $llms_txt_configuration;
+ /**
+ * Holds the Schema_Configuration instance.
+ *
+ * @var Schema_Configuration
+ */
+ protected $schema_configuration;
/**
* The manual post collection.
*
@@ -240,6 +247,7 @@ class Settings_Integration implements Integration_Interface {
* @param Manual_Post_Collection $manual_post_collection The manual post collection.
* @param File_Runner $runner The file runner.
* @param Route_Helper $route_helper The Route_Helper.
+ * @param Schema_Configuration $schema_configuration The Schema_Configuration.
*/
public function __construct(
WPSEO_Admin_Asset_Manager $asset_manager,
@@ -258,7 +266,8 @@ public function __construct(
Llms_Txt_Configuration $llms_txt_configuration,
Manual_Post_Collection $manual_post_collection,
File_Runner $runner,
- Route_Helper $route_helper
+ Route_Helper $route_helper,
+ Schema_Configuration $schema_configuration
) {
$this->asset_manager = $asset_manager;
$this->replace_vars = $replace_vars;
@@ -277,6 +286,7 @@ public function __construct(
$this->manual_post_collection = $manual_post_collection;
$this->runner = $runner;
$this->route_helper = $route_helper;
+ $this->schema_configuration = $schema_configuration;
}
/**
@@ -500,6 +510,7 @@ protected function get_script_data() {
'currentPromotions' => \YoastSEO()->classes->get( Promotion_Manager::class )->get_current_promotions(),
'llmsTxt' => $this->llms_txt_configuration->get_configuration(),
'initialLlmTxtPages' => $this->get_site_llms_txt_pages( $settings ),
+ 'schemaFrameworkConfiguration' => $this->schema_configuration->get_configuration(),
];
}
diff --git a/src/schema/application/configuration/schema-configuration.php b/src/schema/application/configuration/schema-configuration.php
new file mode 100644
index 00000000000..e6becd91eed
--- /dev/null
+++ b/src/schema/application/configuration/schema-configuration.php
@@ -0,0 +1,41 @@
+
+ */
+ public function get_configuration(): array {
+ $schema_filtered_output = $this->get_filtered_schema_output();
+
+ $configuration = [
+ 'isSchemaDisabled' => ( $schema_filtered_output === [] || $schema_filtered_output === false ),
+ ];
+
+ return $configuration;
+ }
+
+ /**
+ * Gets the filtered schema output.
+ *
+ * @return string|array The filtered schema output.
+ */
+ private function get_filtered_schema_output() {
+ $deprecated_data = [
+ '_deprecated' => 'Please use the "wpseo_schema_*" filters to extend the Yoast SEO schema data - see the WPSEO_Schema class.',
+ ];
+
+ /**
+ * Filter documented in Schema_Presenter::present().
+ */
+ return \apply_filters( 'wpseo_json_ld_output', $deprecated_data, '' );
+ }
+}
diff --git a/src/schema/infrastructure/disable-schema-integration.php b/src/schema/infrastructure/disable-schema-integration.php
new file mode 100644
index 00000000000..90a551b18eb
--- /dev/null
+++ b/src/schema/infrastructure/disable-schema-integration.php
@@ -0,0 +1,34 @@
+andReturn( 'https://www.example.com' );
Monkey\Functions\expect( 'admin_url' )->andReturn( 'https://www.example.com' );
- $this->options_helper->expects( 'get' )->times( 5 )->andReturnTrue();
+ $this->options_helper->expects( 'get' )->times( 6 )->andReturnTrue();
$this->elementor_conditional->expects( 'is_met' )->andReturnFalse();
$this->jetpack_conditional->expects( 'is_met' )->andReturnFalse();
@@ -218,6 +218,7 @@ public function test_enqueue_assets() {
'plugin_url' => 'https://www.example.com',
'site_kit_configuration' => $site_kit_config,
'site_kit_consent_management_url' => 'https://www.example.com/manage-consent',
+ 'schema_framework_enabled' => true,
]
);