| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | <?php |
| 2 | +// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- inherited WordPress WXR exporter hook contract (wxr_export_*, the_*_export, rss2_head) preserved for compatibility with WP/feed consumers. | |
| 2 | 3 | namespace WPDeveloper\BetterDocs\Admin; |
| 3 | 4 | |
| 4 | 5 | use WPDeveloper\BetterDocs\Admin\ExportDefaults; |
| 5 | 6 | use WPDeveloper\BetterDocs\Admin\WPExporter; |
| @@ -71,9 +72,9 @@ | ||
| 71 | 72 | |
| 72 | 73 | return [ |
| 73 | 74 | 'success' => true, |
| 74 | 75 | 'data' => [ |
| 75 | - 'filename' => 'betterdocs.' . date('Y-m-d') . '.xml', | |
| 76 | + 'filename' => 'betterdocs.' . gmdate( 'Y-m-d' ) . '.xml', | |
| 76 | 77 | 'filetype' => 'text/xml', |
| 77 | 78 | 'download' => $this->get_xml_export($this->wpexporter->exporter_ids()), |
| 78 | 79 | ] |
| 79 | 80 | ]; |
| @@ -79,9 +80,9 @@ | ||
| 79 | 80 | ]; |
| 80 | 81 | } |
| 81 | 82 | |
| 82 | 83 | public function handle_glossaries_export(): array { |
| 83 | - $filename = 'betterdocs.' . date( 'Y-m-d' ) . '.xml'; | |
| 84 | + $filename = 'betterdocs.' . gmdate( 'Y-m-d' ) . '.xml'; | |
| 84 | 85 | return [ |
| 85 | 86 | 'success' => true, |
| 86 | 87 | 'data' => [ |
| 87 | 88 | 'filename' => $filename, |
| @@ -114,10 +115,19 @@ | ||
| 114 | 115 | */ |
| 115 | 116 | private function wxr_cdata( $str ): string { |
| 116 | 117 | $str = (string) $str; |
| 117 | 118 | |
| 118 | - if ( ! seems_utf8( $str ) ) { | |
| 119 | - $str = utf8_encode( $str ); | |
| 119 | + // wp_is_valid_utf8() only exists on WP 6.9+. Call it via a variable (still | |
| 120 | + // guarded by function_exists) so Plugin Check's static "requires WP" | |
| 121 | + // analysis doesn't flag a function that is never invoked on older cores; | |
| 122 | + // on those, fall back to mb_check_encoding(). | |
| 123 | + $utf8_validator = 'wp_is_valid_utf8'; | |
| 124 | + $is_utf8 = function_exists( $utf8_validator ) | |
| 125 | + ? $utf8_validator( $str ) | |
| 126 | + : ( function_exists( 'mb_check_encoding' ) ? mb_check_encoding( $str, 'UTF-8' ) : true ); | |
| 127 | + | |
| 128 | + if ( ! $is_utf8 ) { | |
| 129 | + $str = mb_convert_encoding( $str, 'UTF-8', 'ISO-8859-1' ); | |
| 120 | 130 | } |
| 121 | 131 | |
| 122 | 132 | $str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>'; |
| 123 | 133 | |
| @@ -268,9 +278,9 @@ | ||
| 268 | 278 | * @param int[] $post_ids Optional. Array of post IDs to filter the query by. |
| 269 | 279 | * |
| 270 | 280 | * @return string |
| 271 | 281 | */ |
| 272 | - private function wxr_authors_list( array $post_ids = null ): string { | |
| 282 | + private function wxr_authors_list( ?array $post_ids = null ): string { | |
| 273 | 283 | $result = ''; |
| 274 | 284 | |
| 275 | 285 | if ( ! empty( $post_ids ) ) { |
| 276 | 286 | $post_ids = array_map( 'absint', $post_ids ); |
| @@ -512,8 +522,23 @@ | ||
| 512 | 522 | |
| 513 | 523 | $result .= $this->indent( 3 ) . '</wp:postmeta>' . PHP_EOL; |
| 514 | 524 | } |
| 515 | 525 | |
| 526 | + $wpml_meta = WPMLSupport::get_post_language_meta( (int) $post->ID ); | |
| 527 | + if ( $wpml_meta !== null ) { | |
| 528 | + $result .= $this->indent( 3 ) . '<wp:postmeta>' . PHP_EOL; | |
| 529 | + $result .= $this->indent( 4 ) . '<wp:meta_key>' . $this->wxr_cdata( WPMLSupport::META_LANG ) . '</wp:meta_key>' . PHP_EOL; | |
| 530 | + $result .= $this->indent( 4 ) . '<wp:meta_value>' . $this->wxr_cdata( $wpml_meta['language_code'] ) . '</wp:meta_value>' . PHP_EOL; | |
| 531 | + $result .= $this->indent( 3 ) . '</wp:postmeta>' . PHP_EOL; | |
| 532 | + | |
| 533 | + if ( $wpml_meta['source_slug'] !== '' ) { | |
| 534 | + $result .= $this->indent( 3 ) . '<wp:postmeta>' . PHP_EOL; | |
| 535 | + $result .= $this->indent( 4 ) . '<wp:meta_key>' . $this->wxr_cdata( WPMLSupport::META_SOURCE_SLUG ) . '</wp:meta_key>' . PHP_EOL; | |
| 536 | + $result .= $this->indent( 4 ) . '<wp:meta_value>' . $this->wxr_cdata( $wpml_meta['source_slug'] ) . '</wp:meta_value>' . PHP_EOL; | |
| 537 | + $result .= $this->indent( 3 ) . '</wp:postmeta>' . PHP_EOL; | |
| 538 | + } | |
| 539 | + } | |
| 540 | + | |
| 516 | 541 | $_comments = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->comments} WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) );// phpcs:ignore |
| 517 | 542 | $comments = array_map( 'get_comment', $_comments ); |
| 518 | 543 | foreach ( $comments as $c ) { |
| 519 | 544 | |
| @@ -624,47 +649,44 @@ | ||
| 624 | 649 | |
| 625 | 650 | $dynamic .= $this->wxr_terms_list( $this->wpexporter->get_terms( $post_ids ) ); |
| 626 | 651 | $dynamic .= $this->wxr_posts_list( $post_ids ); |
| 627 | 652 | |
| 628 | - $result = <<<EOT | |
| 629 | -<?xml version="1.0" encoding="$charset" ?> | |
| 630 | -<!-- This is a WordPress eXtended RSS file generated by WordPress as an export of your site. --> | |
| 631 | -<!-- It contains information about your site's posts, pages, comments, categories, and other content. --> | |
| 632 | -<!-- You may use this file to transfer that content from one site to another. --> | |
| 633 | -<!-- This file is not intended to serve as a complete backup of your site. --> | |
| 634 | - | |
| 635 | -<!-- To import this information into a WordPress site follow these steps: --> | |
| 636 | -<!-- 1. Log in to that site as an administrator. --> | |
| 637 | -<!-- 2. Go to Tools: Import in the WordPress admin panel. --> | |
| 638 | -<!-- 3. Install the "WordPress" importer from the list. --> | |
| 639 | -<!-- 4. Activate & Run Importer. --> | |
| 640 | -<!-- 5. Upload this file using the form provided on that page. --> | |
| 641 | -<!-- 6. You will first be asked to map the authors in this export file to users --> | |
| 642 | -<!-- on the site. For each author, you may choose to map to an --> | |
| 643 | -<!-- existing user on the site or to create a new user. --> | |
| 644 | -<!-- 7. WordPress will then import each of the posts, pages, comments, categories, etc. --> | |
| 645 | -<!-- contained in this file into your site. --> | |
| 646 | -$generator | |
| 647 | -<rss version="2.0" | |
| 648 | - xmlns:excerpt="http://wordpress.org/export/$wxr_version/excerpt/" | |
| 649 | - xmlns:content="http://purl.org/rss/1.0/modules/content/" | |
| 650 | - xmlns:wfw="http://wellformedweb.org/CommentAPI/" | |
| 651 | - xmlns:dc="http://purl.org/dc/elements/1.1/" | |
| 652 | - xmlns:wp="http://wordpress.org/export/$wxr_version/" | |
| 653 | -> | |
| 654 | - <channel> | |
| 655 | - <title>$rss_info_name</title> | |
| 656 | - <link>$rss_info_url</link> | |
| 657 | - <description>$rss_info_description</description> | |
| 658 | - <pubDate>$pub_date</pubDate> | |
| 659 | - <language>$rss_info_language</language> | |
| 660 | - <wp:wxr_version>$wxr_version</wp:wxr_version> | |
| 661 | - <wp:base_site_url>$wxr_site_url</wp:base_site_url> | |
| 662 | - <wp:base_blog_url>$rss_info_url</wp:base_blog_url> | |
| 663 | - $dynamic | |
| 664 | - </channel> | |
| 665 | -</rss> | |
| 666 | -EOT; | |
| 653 | + $result = '<?xml version="1.0" encoding="' . $charset . '" ?>' . "\n"; | |
| 654 | + $result .= "<!-- This is a WordPress eXtended RSS file generated by WordPress as an export of your site. -->\n"; | |
| 655 | + $result .= "<!-- It contains information about your site's posts, pages, comments, categories, and other content. -->\n"; | |
| 656 | + $result .= "<!-- You may use this file to transfer that content from one site to another. -->\n"; | |
| 657 | + $result .= "<!-- This file is not intended to serve as a complete backup of your site. -->\n\n"; | |
| 658 | + $result .= "<!-- To import this information into a WordPress site follow these steps: -->\n"; | |
| 659 | + $result .= "<!-- 1. Log in to that site as an administrator. -->\n"; | |
| 660 | + $result .= "<!-- 2. Go to Tools: Import in the WordPress admin panel. -->\n"; | |
| 661 | + $result .= "<!-- 3. Install the \"WordPress\" importer from the list. -->\n"; | |
| 662 | + $result .= "<!-- 4. Activate & Run Importer. -->\n"; | |
| 663 | + $result .= "<!-- 5. Upload this file using the form provided on that page. -->\n"; | |
| 664 | + $result .= "<!-- 6. You will first be asked to map the authors in this export file to users -->\n"; | |
| 665 | + $result .= "<!-- on the site. For each author, you may choose to map to an -->\n"; | |
| 666 | + $result .= "<!-- existing user on the site or to create a new user. -->\n"; | |
| 667 | + $result .= "<!-- 7. WordPress will then import each of the posts, pages, comments, categories, etc. -->\n"; | |
| 668 | + $result .= "<!-- contained in this file into your site. -->\n"; | |
| 669 | + $result .= $generator . "\n"; | |
| 670 | + $result .= '<rss version="2.0"' . "\n"; | |
| 671 | + $result .= "\txmlns:excerpt=\"http://wordpress.org/export/{$wxr_version}/excerpt/\"\n"; | |
| 672 | + $result .= "\txmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\n"; | |
| 673 | + $result .= "\txmlns:wfw=\"http://wellformedweb.org/CommentAPI/\"\n"; | |
| 674 | + $result .= "\txmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n"; | |
| 675 | + $result .= "\txmlns:wp=\"http://wordpress.org/export/{$wxr_version}/\"\n"; | |
| 676 | + $result .= ">\n"; | |
| 677 | + $result .= "\t<channel>\n"; | |
| 678 | + $result .= "\t\t<title>{$rss_info_name}</title>\n"; | |
| 679 | + $result .= "\t\t<link>{$rss_info_url}</link>\n"; | |
| 680 | + $result .= "\t\t<description>{$rss_info_description}</description>\n"; | |
| 681 | + $result .= "\t\t<pubDate>{$pub_date}</pubDate>\n"; | |
| 682 | + $result .= "\t\t<language>{$rss_info_language}</language>\n"; | |
| 683 | + $result .= "\t\t<wp:wxr_version>{$wxr_version}</wp:wxr_version>\n"; | |
| 684 | + $result .= "\t\t<wp:base_site_url>{$wxr_site_url}</wp:base_site_url>\n"; | |
| 685 | + $result .= "\t\t<wp:base_blog_url>{$rss_info_url}</wp:base_blog_url>\n"; | |
| 686 | + $result .= "\t\t" . $dynamic . "\n"; | |
| 687 | + $result .= "\t</channel>\n"; | |
| 688 | + $result .= "</rss>\n"; | |
| 667 | 689 | |
| 668 | 690 | return $result; |
| 669 | 691 | } |
| 670 | 692 | } |