PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.14.2
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.14.2
2.14.2 2.14.1 2.14.0 2.13.0 2.12.0 2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 All 57 releases
← All changes | includes/seo/class-schema-management-system.php +51 -10 2.12.0 → 2.14.2 View file →
@@ -730,8 +730,27 @@
730 730 return $optimization;
731 731 }
732 732
733 733 /**
734 + * Deployed types an authoritative deploy takes off the page.
735 + *
736 + * Everything deployed that the payload left out, except the types the
737 + * caller sent but could not deploy: those failed validation, they were not
738 + * removed by the user, so their live copy stays. Retiring them took the
739 + * site's Organization down behind a success toast (#949).
740 + *
741 + * @since 2.14.1
742 + *
743 + * @param string[] $deployed Types deployed for the context now.
744 + * @param string[] $payload Types in this deploy.
745 + * @param string[] $retain_types Types sent but skipped by validation.
746 + * @return string[] Types to retire.
747 + */
748 + public static function types_to_retire(array $deployed, array $payload, array $retain_types = []): array {
749 + return array_values(array_diff($deployed, $payload, $retain_types));
750 + }
751 +
752 + /**
734 753 * Deploy schema markup with automated implementation
735 754 *
736 755 * @since 1.0.0
737 756 *
@@ -765,11 +784,12 @@
765 784 if (!empty($options['authoritative'])) {
766 785 $deployment['retired_schemas'] = $this->retire_schema_types(
767 786 $context_type,
768 787 $context_id,
769 - array_diff(
788 + self::types_to_retire(
770 789 array_keys($this->get_deployed_schemas($context_type, $context_id)),
771 - array_keys($schema_data)
790 + array_keys($schema_data),
791 + (array) ($options['retain_types'] ?? [])
772 792 )
773 793 );
774 794 }
775 795
@@ -1325,9 +1345,9 @@
1325 1345 $this->cache_manager->invalidate_all_cache();
1326 1346 }
1327 1347
1328 1348 // AUTO-DEPLOY: Automatically regenerate and deploy schema when settings change
1329 - if ($success && !empty($settings['auto_deploy'])) {
1349 + if ($success && self::should_auto_deploy($settings, $this->get_settings($context_type, $context_id))) {
1330 1350 $this->auto_deploy_schema_on_settings_change($context_type, $context_id, $settings);
1331 1351 }
1332 1352
1333 1353 return $success;
@@ -1332,9 +1352,35 @@
1332 1352
1333 1353 return $success;
1334 1354 }
1335 1355
1356 +
1336 1357 /**
1358 + * Whether a save should redeploy the schema it changed.
1359 + *
1360 + * `auto_deploy` is a stored setting (on by default), not something a save
1361 + * restates. Reading it off the incoming patch meant a partial save — which
1362 + * is what the admin screen sends, one field at a time — skipped
1363 + * auto-deploy on a site that had it switched on, and the deployed snapshot
1364 + * the front end serves kept the name, logo and sameAs it was deployed
1365 + * with, however often the user saved (#904, the gate #12 left in place).
1366 + *
1367 + * A patch that does carry the key still wins, so a caller can deploy or
1368 + * hold deliberately.
1369 + *
1370 + * @param array $patch Settings being saved
1371 + * @param array $stored Settings as stored, after the save
1372 + * @return bool
1373 + */
1374 + public static function should_auto_deploy(array $patch, array $stored): bool {
1375 + if (array_key_exists('auto_deploy', $patch)) {
1376 + return !empty($patch['auto_deploy']);
1377 + }
1378 +
1379 + return !empty($stored['auto_deploy']);
1380 + }
1381 +
1382 + /**
1337 1383 * Auto-deploy schema when settings change
1338 1384 *
1339 1385 * Automatically regenerates and deploys schema markup when organization or other
1340 1386 * schema settings are modified, ensuring the frontend output stays in sync.
@@ -2198,15 +2244,10 @@
2198 2244 if (!is_string($url) || '' === trim($url)) {
2199 2245 return false;
2200 2246 }
2201 2247
2202 - if (!filter_var($url, FILTER_VALIDATE_URL)) {
2203 - return false;
2204 - }
2205 -
2206 - $scheme = wp_parse_url($url, PHP_URL_SCHEME);
2207 -
2208 - return in_array(strtolower((string) $scheme), ['http', 'https'], true);
2248 + // IRI-aware: a non-ASCII path or IDN host is a real URL (#924).
2249 + return \ThinkRank\Core\Url_Validator::is_http_url($url);
2209 2250 }
2210 2251
2211 2252 /**
2212 2253 * Drop values that are not URLs from URL-typed properties.