← All changes
|
includes/admin/importers/class-aioseo-exporter.php
+87
-13
2.6.0
→
2.14.2
View file →
| @@ -273,10 +273,10 @@ | ||
| 273 | 273 | 'object_id' => $post_id, |
| 274 | 274 | 'object_type' => 'post', |
| 275 | 275 | 'source_plugin' => $this->plugin_slug, |
| 276 | 276 | 'data' => [ |
| 277 | - 'seo_title' => $this->convert_template_variables($this->safe_column($row, 'title'), $post_id), | |
| 278 | - 'meta_description' => $this->convert_template_variables($this->safe_column($row, 'description'), $post_id), | |
| 277 | + 'seo_title' => $this->convert_post_value($this->safe_column($row, 'title'), $post_id), | |
| 278 | + 'meta_description' => $this->convert_post_value($this->safe_column($row, 'description'), $post_id), | |
| 279 | 279 | 'focus_keyword' => $focus_keyword, |
| 280 | 280 | 'focus_keywords' => $focus_keywords, |
| 281 | 281 | 'canonical_url' => $this->safe_column($row, 'canonical_url'), |
| 282 | 282 | 'noindex' => $noindex, |
| @@ -286,13 +286,13 @@ | ||
| 286 | 286 | 'nosnippet' => $robots_default ? null : $this->safe_column_int($row, 'robots_nosnippet'), |
| 287 | 287 | 'max_snippet' => $robots_default ? null : $this->robots_limit($row, 'robots_max_snippet'), |
| 288 | 288 | 'max_video_preview' => $robots_default ? null : $this->robots_limit($row, 'robots_max_videopreview'), |
| 289 | 289 | 'max_image_preview' => $max_image_preview, |
| 290 | - 'og_title' => $this->convert_template_variables($this->safe_column($row, 'og_title'), $post_id), | |
| 291 | - 'og_description' => $this->convert_template_variables($this->safe_column($row, 'og_description'), $post_id), | |
| 290 | + 'og_title' => $this->convert_post_value($this->safe_column($row, 'og_title'), $post_id), | |
| 291 | + 'og_description' => $this->convert_post_value($this->safe_column($row, 'og_description'), $post_id), | |
| 292 | 292 | 'og_image' => $this->safe_column($row, 'og_image_custom_url'), |
| 293 | - 'twitter_title' => $this->convert_template_variables($this->safe_column($row, 'twitter_title'), $post_id), | |
| 294 | - 'twitter_description' => $this->convert_template_variables($this->safe_column($row, 'twitter_description'), $post_id), | |
| 293 | + 'twitter_title' => $this->convert_post_value($this->safe_column($row, 'twitter_title'), $post_id), | |
| 294 | + 'twitter_description' => $this->convert_post_value($this->safe_column($row, 'twitter_description'), $post_id), | |
| 295 | 295 | 'twitter_image' => $this->safe_column($row, 'twitter_image_custom_url'), |
| 296 | 296 | 'primary_category' => $this->extract_primary_category($row), |
| 297 | 297 | 'schema_type' => $schema_type, |
| 298 | 298 | // AIOSEO pillar content maps directly to ThinkRank pillar content. |
| @@ -480,10 +480,10 @@ | ||
| 480 | 480 | 'object_id' => $term_id, |
| 481 | 481 | 'object_type' => 'term', |
| 482 | 482 | 'source_plugin' => $this->plugin_slug, |
| 483 | 483 | 'data' => [ |
| 484 | - 'seo_title' => $this->convert_template_variables((string) ($row['title'] ?? '')), | |
| 485 | - 'meta_description' => $this->convert_template_variables((string) ($row['description'] ?? '')), | |
| 484 | + 'seo_title' => $this->convert_term_value((string) ($row['title'] ?? '')), | |
| 485 | + 'meta_description' => $this->convert_term_value((string) ($row['description'] ?? '')), | |
| 486 | 486 | 'focus_keyword' => $focus_keyword, |
| 487 | 487 | 'focus_keywords' => array_values(array_filter( |
| 488 | 488 | array_merge([$focus_keyword], $additional), |
| 489 | 489 | static fn($keyword) => trim((string) $keyword) !== '' |
| @@ -490,13 +490,13 @@ | ||
| 490 | 490 | )), |
| 491 | 491 | 'canonical_url' => (string) ($row['canonical_url'] ?? ''), |
| 492 | 492 | 'noindex' => $robots_default ? null : (int) ($row['robots_noindex'] ?? 0), |
| 493 | 493 | 'nofollow' => $robots_default ? null : (int) ($row['robots_nofollow'] ?? 0), |
| 494 | - 'og_title' => $this->convert_template_variables((string) ($row['og_title'] ?? '')), | |
| 495 | - 'og_description' => $this->convert_template_variables((string) ($row['og_description'] ?? '')), | |
| 494 | + 'og_title' => $this->convert_term_value((string) ($row['og_title'] ?? '')), | |
| 495 | + 'og_description' => $this->convert_term_value((string) ($row['og_description'] ?? '')), | |
| 496 | 496 | 'og_image' => (string) ($row['og_image_custom_url'] ?? ''), |
| 497 | - 'twitter_title' => $this->convert_template_variables((string) ($row['twitter_title'] ?? '')), | |
| 498 | - 'twitter_description' => $this->convert_template_variables((string) ($row['twitter_description'] ?? '')), | |
| 497 | + 'twitter_title' => $this->convert_term_value((string) ($row['twitter_title'] ?? '')), | |
| 498 | + 'twitter_description' => $this->convert_term_value((string) ($row['twitter_description'] ?? '')), | |
| 499 | 499 | 'twitter_image' => (string) ($row['twitter_image_custom_url'] ?? ''), |
| 500 | 500 | ], |
| 501 | 501 | 'extended' => [], |
| 502 | 502 | ]; |
| @@ -1216,8 +1216,79 @@ | ||
| 1216 | 1216 | return $records; |
| 1217 | 1217 | } |
| 1218 | 1218 | |
| 1219 | 1219 | /** |
| 1220 | + * AIOSEO per-post tags ThinkRank resolves per request (#886): kept as | |
| 1221 | + * ThinkRank tags rather than frozen into text. Mirrors | |
| 1222 | + * convert_aioseo_global_template(). | |
| 1223 | + */ | |
| 1224 | + private const POST_TOKENS = [ | |
| 1225 | + '#post_title' => '%title%', | |
| 1226 | + '#site_title' => '%sitename%', | |
| 1227 | + '#separator_sa' => '%sep%', | |
| 1228 | + '#post_excerpt' => '%excerpt%', | |
| 1229 | + '#post_date' => '%date%', | |
| 1230 | + '#author_name' => '%author%', | |
| 1231 | + '#category_title' => '%category%', | |
| 1232 | + ]; | |
| 1233 | + | |
| 1234 | + /** | |
| 1235 | + * AIOSEO per-term tags ThinkRank resolves on a term archive. The literal | |
| 1236 | + * resolver only knows post context, so these were stripped. | |
| 1237 | + */ | |
| 1238 | + private const TERM_TOKENS = [ | |
| 1239 | + '#taxonomy_title' => '%term%', | |
| 1240 | + '#taxonomy_description' => '%excerpt%', | |
| 1241 | + '#site_title' => '%sitename%', | |
| 1242 | + '#separator_sa' => '%sep%', | |
| 1243 | + ]; | |
| 1244 | + | |
| 1245 | + /** | |
| 1246 | + * A per-post AIOSEO value: mapped tags as ThinkRank tags, the rest literal. | |
| 1247 | + * | |
| 1248 | + * @param mixed $value Raw AIOSEO value | |
| 1249 | + * @param int $post_id Post ID | |
| 1250 | + * @return string | |
| 1251 | + */ | |
| 1252 | + private function convert_post_value($value, int $post_id): string { | |
| 1253 | + return $this->tokenize_object_template( | |
| 1254 | + $this->stringify_template_value($value), | |
| 1255 | + self::aioseo_token_patterns(self::POST_TOKENS), | |
| 1256 | + fn(string $rest): string => $this->convert_template_variables($rest, $post_id) | |
| 1257 | + ); | |
| 1258 | + } | |
| 1259 | + | |
| 1260 | + /** | |
| 1261 | + * A per-term AIOSEO value: mapped tags as ThinkRank tags, the rest literal. | |
| 1262 | + * | |
| 1263 | + * @param mixed $value Raw AIOSEO value | |
| 1264 | + * @return string | |
| 1265 | + */ | |
| 1266 | + private function convert_term_value($value): string { | |
| 1267 | + return $this->tokenize_object_template( | |
| 1268 | + $this->stringify_template_value($value), | |
| 1269 | + self::aioseo_token_patterns(self::TERM_TOKENS), | |
| 1270 | + fn(string $rest): string => $this->convert_template_variables($rest) | |
| 1271 | + ); | |
| 1272 | + } | |
| 1273 | + | |
| 1274 | + /** | |
| 1275 | + * AIOSEO tags have no closing delimiter, so each one must end at a word | |
| 1276 | + * boundary — `#post_title` is not the start of `#post_titles`. | |
| 1277 | + * | |
| 1278 | + * @param array<string,string> $map AIOSEO tag => ThinkRank tag | |
| 1279 | + * @return array<string,string> Regex => ThinkRank tag | |
| 1280 | + */ | |
| 1281 | + private static function aioseo_token_patterns(array $map): array { | |
| 1282 | + $patterns = []; | |
| 1283 | + foreach ($map as $tag => $thinkrank_tag) { | |
| 1284 | + $patterns['/' . preg_quote((string) $tag, '/') . '\\b/'] = $thinkrank_tag; | |
| 1285 | + } | |
| 1286 | + | |
| 1287 | + return $patterns; | |
| 1288 | + } | |
| 1289 | + | |
| 1290 | + /** | |
| 1220 | 1291 | * {@inheritDoc} |
| 1221 | 1292 | */ |
| 1222 | 1293 | protected function convert_template_variables($value, ?int $post_id = null): string { |
| 1223 | 1294 | // Foreign data first: booleans/arrays in the source plugin's options |
| @@ -1244,9 +1315,12 @@ | ||
| 1244 | 1315 | if ($post_id) { |
| 1245 | 1316 | $post = get_post($post_id); |
| 1246 | 1317 | if ($post) { |
| 1247 | 1318 | $replacements['#post_title'] = $post->post_title; |
| 1248 | - $replacements['#post_excerpt'] = wp_trim_words($post->post_excerpt ?: wp_trim_words(wp_strip_all_tags($post->post_content), 55), 55); | |
| 1319 | + $replacements['#post_excerpt'] = \ThinkRank\Core\Seo_Text::trim_words( | |
| 1320 | + $post->post_excerpt ?: \ThinkRank\Core\Seo_Text::trim_words(wp_strip_all_tags($post->post_content), 55), | |
| 1321 | + 55 | |
| 1322 | + ); | |
| 1249 | 1323 | $replacements['#post_date'] = get_the_date('', $post); |
| 1250 | 1324 | $replacements['#author_name'] = get_the_author_meta('display_name', (int) $post->post_author); |
| 1251 | 1325 | |
| 1252 | 1326 | $post_type_obj = get_post_type_object($post->post_type); |