DemoSites.php
1 year ago
DemoSitesHelpers.php
1 month ago
DemoSitesImportBlockMap.php
1 year ago
DemoSitesImporter.php
1 year ago
DemoSitesLogger.php
4 years ago
DemoSitesRepository.php
1 year ago
WXRExporter.php
1 year ago
WXRImporter.php
1 year ago
WXRExporter.php
616 lines
| 1 | <?php |
| 2 | |
| 3 | // phpcs:disable WordPress.Security.EscapeOutput |
| 4 | // the escaping rule is disabled as the WXR generation require the raw database content |
| 5 | |
| 6 | namespace Kubio\DemoSites; |
| 7 | |
| 8 | class WXRExporter { |
| 9 | |
| 10 | const WXR_VERSION = '1.2'; |
| 11 | |
| 12 | public static function export( $args = array() ) { |
| 13 | global $wpdb; |
| 14 | |
| 15 | $defaults = array( |
| 16 | 'content' => 'all', |
| 17 | 'author' => false, |
| 18 | 'category' => false, |
| 19 | 'start_date' => false, |
| 20 | 'end_date' => false, |
| 21 | 'status' => false, |
| 22 | ); |
| 23 | $args = wp_parse_args( $args, $defaults ); |
| 24 | |
| 25 | $post_types = get_post_types( array( 'can_export' => true ) ); |
| 26 | |
| 27 | // remove colibri post types |
| 28 | foreach ( $post_types as $key => $post_type ) { |
| 29 | if ( strpos( $post_type, 'extb_post_' ) === 0 ) { |
| 30 | unset( $post_types[ $key ] ); |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | $esses = array_fill( 0, count( $post_types ), '%s' ); |
| 35 | |
| 36 | // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.NotPrepared |
| 37 | $where = $wpdb->prepare( "{$wpdb->posts}.post_type IN (" . implode( ',', $esses ) . ')', $post_types ); |
| 38 | |
| 39 | if ( $args['status'] && ( 'post' === $args['content'] || 'page' === $args['content'] ) ) { |
| 40 | $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_status = %s", $args['status'] ); |
| 41 | } else { |
| 42 | $where .= " AND {$wpdb->posts}.post_status != 'auto-draft'"; |
| 43 | } |
| 44 | |
| 45 | $join = ''; |
| 46 | if ( $args['category'] && 'post' === $args['content'] ) { |
| 47 | $term = term_exists( $args['category'], 'category' ); |
| 48 | if ( $term ) { |
| 49 | $join = "INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)"; |
| 50 | $where .= $wpdb->prepare( " AND {$wpdb->term_relationships}.term_taxonomy_id = %d", $term['term_taxonomy_id'] ); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | if ( in_array( $args['content'], array( 'post', 'page', 'attachment' ), true ) ) { |
| 55 | if ( $args['author'] ) { |
| 56 | $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $args['author'] ); |
| 57 | } |
| 58 | |
| 59 | if ( $args['start_date'] ) { |
| 60 | $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date >= %s", gmdate( 'Y-m-d', strtotime( $args['start_date'] ) ) ); |
| 61 | } |
| 62 | |
| 63 | if ( $args['end_date'] ) { |
| 64 | $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date < %s", gmdate( 'Y-m-d', strtotime( '+1 month', strtotime( $args['end_date'] ) ) ) ); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | // Grab a snapshot of post IDs, just in case it changes during the export. |
| 69 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 70 | $post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} $join WHERE $where" ); |
| 71 | |
| 72 | $cats = array(); |
| 73 | $tags = array(); |
| 74 | $terms = array(); |
| 75 | if ( isset( $term ) && $term ) { |
| 76 | $cat = get_term( $term['term_id'], 'category' ); |
| 77 | $cats = array( $cat->term_id => $cat ); |
| 78 | unset( $term, $cat ); |
| 79 | } elseif ( 'all' === $args['content'] ) { |
| 80 | $categories = (array) get_categories( array( 'get' => 'all' ) ); |
| 81 | $tags = (array) get_tags( array( 'get' => 'all' ) ); |
| 82 | |
| 83 | $custom_taxonomies = get_taxonomies( array( '_builtin' => false ) ); |
| 84 | $custom_terms = (array) get_terms( |
| 85 | array( |
| 86 | 'taxonomy' => $custom_taxonomies, |
| 87 | 'get' => 'all', |
| 88 | ) |
| 89 | ); |
| 90 | |
| 91 | // Put categories in order with no child going before its parent. |
| 92 | while ( $cat = array_shift( $categories ) ) { |
| 93 | if ( ! $cat->parent || isset( $cats[ $cat->parent ] ) ) { |
| 94 | $cats[ $cat->term_id ] = $cat; |
| 95 | } else { |
| 96 | $categories[] = $cat; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | // Put terms in order with no child going before its parent. |
| 101 | while ( $t = array_shift( $custom_terms ) ) { |
| 102 | if ( ! $t->parent || isset( $terms[ $t->parent ] ) ) { |
| 103 | $terms[ $t->term_id ] = $t; |
| 104 | } else { |
| 105 | $custom_terms[] = $t; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | unset( $categories, $custom_taxonomies, $custom_terms ); |
| 110 | } |
| 111 | |
| 112 | add_filter( 'wxr_export_skip_postmeta', array( WXRExporter::class, 'skipPostMeta' ), 10, 2 ); |
| 113 | |
| 114 | $content = static::getContent( $post_ids, $cats, $tags, $terms ); |
| 115 | |
| 116 | remove_filter( 'wxr_export_skip_postmeta', array( WXRExporter::class, 'skipPostMeta' ) ); |
| 117 | |
| 118 | return trim( $content ); |
| 119 | } |
| 120 | |
| 121 | private static function getContent( $post_ids, $cats, $tags, $terms ) { |
| 122 | global $wpdb; |
| 123 | ob_start(); ?> |
| 124 | |
| 125 | <?php the_generator( 'export' ); ?> |
| 126 | <rss version="2.0" |
| 127 | xmlns:excerpt="http://wordpress.org/export/<?php echo WXRExporter::WXR_VERSION; ?>/excerpt/" |
| 128 | xmlns:content="http://purl.org/rss/1.0/modules/content/" |
| 129 | xmlns:dc="http://purl.org/dc/elements/1.1/" |
| 130 | xmlns:wp="http://wordpress.org/export/<?php echo WXRExporter::WXR_VERSION; ?>/" |
| 131 | > |
| 132 | |
| 133 | <channel> |
| 134 | <title><?php bloginfo_rss( 'name' ); ?></title> |
| 135 | <link><?php bloginfo_rss( 'url' ); ?></link> |
| 136 | <description><?php bloginfo_rss( 'description' ); ?></description> |
| 137 | <pubDate><?php echo gmdate( 'D, d M Y H:i:s +0000' ); ?></pubDate> |
| 138 | <language><?php bloginfo_rss( 'language' ); ?></language> |
| 139 | <wp:wxr_version><?php echo WXRExporter::WXR_VERSION; ?></wp:wxr_version> |
| 140 | <wp:base_site_url><?php echo static::getSiteURL(); ?></wp:base_site_url> |
| 141 | <wp:base_blog_url><?php bloginfo_rss( 'url' ); ?></wp:base_blog_url> |
| 142 | |
| 143 | <?php static::printAuthorsList( $post_ids ); ?> |
| 144 | |
| 145 | <?php foreach ( $cats as $c ) : ?> |
| 146 | <wp:category> |
| 147 | <wp:term_id><?php echo (int) $c->term_id; ?></wp:term_id> |
| 148 | <wp:category_nicename><?php echo static::getCData( $c->slug ); ?></wp:category_nicename> |
| 149 | <wp:category_parent><?php echo static::getCData( $c->parent ? $cats[ $c->parent ]->slug : '' ); ?></wp:category_parent> |
| 150 | <?php |
| 151 | static::printCatName( $c ); |
| 152 | static::printCatDescription( $c ); |
| 153 | static::printTermMeta( $c ); |
| 154 | ?> |
| 155 | </wp:category> |
| 156 | <?php endforeach; ?> |
| 157 | <?php foreach ( $tags as $t ) : ?> |
| 158 | <wp:tag> |
| 159 | <wp:term_id><?php echo (int) $t->term_id; ?></wp:term_id> |
| 160 | <wp:tag_slug><?php echo static::getCData( $t->slug ); ?></wp:tag_slug> |
| 161 | <?php |
| 162 | static::printTagName( $t ); |
| 163 | static::printTagDescription( $t ); |
| 164 | static::printTermMeta( $t ); |
| 165 | ?> |
| 166 | </wp:tag> |
| 167 | <?php endforeach; ?> |
| 168 | <?php foreach ( $terms as $t ) : ?> |
| 169 | <wp:term> |
| 170 | <wp:term_id><?php echo (int) $t->term_id; ?></wp:term_id> |
| 171 | <wp:term_taxonomy><?php echo static::getCData( $t->taxonomy ); ?></wp:term_taxonomy> |
| 172 | <wp:term_slug><?php echo static::getCData( $t->slug ); ?></wp:term_slug> |
| 173 | <wp:term_parent><?php echo static::getCData( $t->parent ? $terms[ $t->parent ]->slug : '' ); ?></wp:term_parent> |
| 174 | <?php |
| 175 | static::printTermName( $t ); |
| 176 | static::printTermDescription( $t ); |
| 177 | static::printTermMeta( $t ); |
| 178 | ?> |
| 179 | </wp:term> |
| 180 | <?php endforeach; ?> |
| 181 | <?php static::printNavTerms(); ?> |
| 182 | |
| 183 | <?php |
| 184 | /** This action is documented in wp-includes/feed-rss2.php */ |
| 185 | do_action( 'rss2_head' ); |
| 186 | ?> |
| 187 | |
| 188 | <?php |
| 189 | if ( $post_ids ) { |
| 190 | /** |
| 191 | * @global WP_Query $wp_query WordPress Query object. |
| 192 | */ |
| 193 | global $wp_query; |
| 194 | |
| 195 | // Fake being in the loop. |
| 196 | $wp_query->in_the_loop = true; |
| 197 | |
| 198 | // Fetch 20 posts at a time rather than loading the entire table into memory. |
| 199 | while ( $next_posts = array_splice( $post_ids, 0, 20 ) ) { |
| 200 | $where = 'WHERE ID IN (' . implode( ',', $next_posts ) . ')'; |
| 201 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 202 | $posts = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} $where" ); |
| 203 | |
| 204 | // Begin Loop. |
| 205 | foreach ( $posts as $post ) { |
| 206 | setup_postdata( $post ); |
| 207 | |
| 208 | /** |
| 209 | * Filters the post title used for WXR exports. |
| 210 | * |
| 211 | * @param string $post_title Title of the current post. |
| 212 | * |
| 213 | * @since 5.7.0 |
| 214 | * |
| 215 | */ |
| 216 | $title = static::getCData( apply_filters( 'the_title_export', $post->post_title ) ); |
| 217 | |
| 218 | /** |
| 219 | * Filters the post content used for WXR exports. |
| 220 | * |
| 221 | * @param string $post_content Content of the current post. |
| 222 | * |
| 223 | * @since 2.5.0 |
| 224 | * |
| 225 | */ |
| 226 | $content = static::getCData( apply_filters( 'the_content_export', $post->post_content ) ); |
| 227 | |
| 228 | /** |
| 229 | * Filters the post excerpt used for WXR exports. |
| 230 | * |
| 231 | * @param string $post_excerpt Excerpt for the current post. |
| 232 | * |
| 233 | * @since 2.6.0 |
| 234 | * |
| 235 | */ |
| 236 | $excerpt = static::getCData( apply_filters( 'the_excerpt_export', $post->post_excerpt ) ); |
| 237 | |
| 238 | $is_sticky = is_sticky( $post->ID ) ? 1 : 0; |
| 239 | ?> |
| 240 | <item> |
| 241 | <title><?php echo $title; ?></title> |
| 242 | <link><?php the_permalink_rss(); ?></link> |
| 243 | <pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); ?></pubDate> |
| 244 | <dc:creator><?php echo static::getCData( get_the_author_meta( 'login' ) ); ?></dc:creator> |
| 245 | <guid isPermaLink="false"><?php the_guid(); ?></guid> |
| 246 | <description></description> |
| 247 | <content:encoded><?php echo $content; ?></content:encoded> |
| 248 | <excerpt:encoded><?php echo $excerpt; ?></excerpt:encoded> |
| 249 | <wp:post_id><?php echo (int) $post->ID; ?></wp:post_id> |
| 250 | <wp:post_date><?php echo static::getCData( $post->post_date ); ?></wp:post_date> |
| 251 | <wp:post_date_gmt><?php echo static::getCData( $post->post_date_gmt ); ?></wp:post_date_gmt> |
| 252 | <wp:post_modified><?php echo static::getCData( $post->post_modified ); ?></wp:post_modified> |
| 253 | <wp:post_modified_gmt><?php echo static::getCData( $post->post_modified_gmt ); ?></wp:post_modified_gmt> |
| 254 | <wp:comment_status><?php echo static::getCData( $post->comment_status ); ?></wp:comment_status> |
| 255 | <wp:ping_status><?php echo static::getCData( $post->ping_status ); ?></wp:ping_status> |
| 256 | <wp:post_name><?php echo static::getCData( $post->post_name ); ?></wp:post_name> |
| 257 | <wp:status><?php echo static::getCData( $post->post_status ); ?></wp:status> |
| 258 | <wp:post_parent><?php echo (int) $post->post_parent; ?></wp:post_parent> |
| 259 | <wp:menu_order><?php echo (int) $post->menu_order; ?></wp:menu_order> |
| 260 | <wp:post_type><?php echo static::getCData( $post->post_type ); ?></wp:post_type> |
| 261 | <wp:post_password><?php echo static::getCData( $post->post_password ); ?></wp:post_password> |
| 262 | <wp:is_sticky><?php echo (int) $is_sticky; ?></wp:is_sticky> |
| 263 | <?php if ( 'attachment' === $post->post_type ) : ?> |
| 264 | <wp:attachment_url><?php echo static::getCData( wp_get_attachment_url( $post->ID ) ); ?></wp:attachment_url> |
| 265 | <?php endif; ?> |
| 266 | <?php static::printPostTaxonomy( $post ); ?> |
| 267 | <?php |
| 268 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 269 | $postmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID ) ); |
| 270 | foreach ( $postmeta as $meta ) : |
| 271 | /** |
| 272 | * Filters whether to selectively skip post meta used for WXR exports. |
| 273 | * |
| 274 | * Returning a truthy value from the filter will skip the current meta |
| 275 | * object from being exported. |
| 276 | * |
| 277 | * @param bool $skip Whether to skip the current post meta. Default false. |
| 278 | * @param string $meta_key Current meta key. |
| 279 | * @param object $meta Current meta object. |
| 280 | * |
| 281 | * @since 3.3.0 |
| 282 | * |
| 283 | */ |
| 284 | if ( ! apply_filters( 'wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) ) { |
| 285 | ?> |
| 286 | <wp:postmeta> |
| 287 | <wp:meta_key><?php echo static::getCData( $meta->meta_key ); ?></wp:meta_key> |
| 288 | <wp:meta_value><?php echo static::getCData( $meta->meta_value ); ?></wp:meta_value> |
| 289 | </wp:postmeta> |
| 290 | <?php |
| 291 | } |
| 292 | |
| 293 | endforeach; |
| 294 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 295 | $_comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) ); |
| 296 | $comments = array_map( 'get_comment', $_comments ); |
| 297 | foreach ( $comments as $c ) : |
| 298 | ?> |
| 299 | <wp:comment> |
| 300 | <wp:comment_id><?php echo (int) $c->comment_ID; ?></wp:comment_id> |
| 301 | <wp:comment_author><?php echo static::getCData( $c->comment_author ); ?></wp:comment_author> |
| 302 | <wp:comment_author_email><?php echo static::getCData( $c->comment_author_email ); ?></wp:comment_author_email> |
| 303 | <wp:comment_author_url><?php echo esc_url_raw( $c->comment_author_url ); ?></wp:comment_author_url> |
| 304 | <wp:comment_author_IP><?php echo static::getCData( $c->comment_author_IP ); ?></wp:comment_author_IP> |
| 305 | <wp:comment_date><?php echo static::getCData( $c->comment_date ); ?></wp:comment_date> |
| 306 | <wp:comment_date_gmt><?php echo static::getCData( $c->comment_date_gmt ); ?></wp:comment_date_gmt> |
| 307 | <wp:comment_content><?php echo static::getCData( $c->comment_content ); ?></wp:comment_content> |
| 308 | <wp:comment_approved><?php echo static::getCData( $c->comment_approved ); ?></wp:comment_approved> |
| 309 | <wp:comment_type><?php echo static::getCData( $c->comment_type ); ?></wp:comment_type> |
| 310 | <wp:comment_parent><?php echo (int) $c->comment_parent; ?></wp:comment_parent> |
| 311 | <wp:comment_user_id><?php echo (int) $c->user_id; ?></wp:comment_user_id> |
| 312 | <?php |
| 313 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 314 | $c_meta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $c->comment_ID ) ); |
| 315 | foreach ( $c_meta as $meta ) : |
| 316 | /** |
| 317 | * Filters whether to selectively skip comment meta used for WXR exports. |
| 318 | * |
| 319 | * Returning a truthy value from the filter will skip the current meta |
| 320 | * object from being exported. |
| 321 | * |
| 322 | * @param bool $skip Whether to skip the current comment meta. Default false. |
| 323 | * @param string $meta_key Current meta key. |
| 324 | * @param object $meta Current meta object. |
| 325 | * |
| 326 | * @since 4.0.0 |
| 327 | * |
| 328 | */ |
| 329 | if ( apply_filters( 'static::wxr_export_skip_commentmeta', false, $meta->meta_key, $meta ) ) { |
| 330 | continue; |
| 331 | } |
| 332 | ?> |
| 333 | <wp:commentmeta> |
| 334 | <wp:meta_key><?php echo static::getCData( $meta->meta_key ); ?></wp:meta_key> |
| 335 | <wp:meta_value><?php echo static::getCData( $meta->meta_value ); ?></wp:meta_value> |
| 336 | </wp:commentmeta> |
| 337 | <?php endforeach; ?> |
| 338 | </wp:comment> |
| 339 | <?php endforeach; ?> |
| 340 | </item> |
| 341 | <?php |
| 342 | } |
| 343 | } |
| 344 | } |
| 345 | ?> |
| 346 | </channel> |
| 347 | </rss> |
| 348 | <?php |
| 349 | |
| 350 | return ob_get_clean(); |
| 351 | } |
| 352 | |
| 353 | /** |
| 354 | * Return the URL of the site |
| 355 | * |
| 356 | * @return string Site URL. |
| 357 | * @since 2.5.0 |
| 358 | * |
| 359 | */ |
| 360 | public static function getSiteURL() { |
| 361 | if ( is_multisite() ) { |
| 362 | // Multisite: the base URL. |
| 363 | return network_home_url(); |
| 364 | } else { |
| 365 | // WordPress (single site): the blog URL. |
| 366 | return get_bloginfo_rss( 'url' ); |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | /** |
| 371 | * Output list of authors with posts |
| 372 | * |
| 373 | * @param int[] $post_ids Optional. Array of post IDs to filter the query by. |
| 374 | * |
| 375 | * @global wpdb $wpdb WordPress database abstraction object. |
| 376 | * |
| 377 | * @since 3.1.0 |
| 378 | * |
| 379 | */ |
| 380 | private static function printAuthorsList( array $post_ids = null ) { |
| 381 | global $wpdb; |
| 382 | |
| 383 | if ( ! empty( $post_ids ) ) { |
| 384 | $post_ids = array_map( 'absint', $post_ids ); |
| 385 | $and = 'AND ID IN ( ' . implode( ', ', $post_ids ) . ')'; |
| 386 | } else { |
| 387 | $and = ''; |
| 388 | } |
| 389 | |
| 390 | $authors = array(); |
| 391 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 392 | $results = $wpdb->get_results( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft' $and" ); |
| 393 | foreach ( (array) $results as $result ) { |
| 394 | $authors[] = get_userdata( $result->post_author ); |
| 395 | } |
| 396 | |
| 397 | $authors = array_filter( $authors ); |
| 398 | |
| 399 | foreach ( $authors as $author ) { |
| 400 | echo "\t<wp:author>"; |
| 401 | echo '<wp:author_id>' . (int) $author->ID . '</wp:author_id>'; |
| 402 | echo '<wp:author_login>' . static::getCData( $author->user_login ) . '</wp:author_login>'; |
| 403 | echo '<wp:author_email>' . static::getCData( $author->user_email ) . '</wp:author_email>'; |
| 404 | echo '<wp:author_display_name>' . static::getCData( $author->display_name ) . '</wp:author_display_name>'; |
| 405 | echo '<wp:author_first_name>' . static::getCData( $author->first_name ) . '</wp:author_first_name>'; |
| 406 | echo '<wp:author_last_name>' . static::getCData( $author->last_name ) . '</wp:author_last_name>'; |
| 407 | echo "</wp:author>\n"; |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | /** |
| 412 | * Wrap given string in XML CDATA tag. |
| 413 | * |
| 414 | * @param string $str String to wrap in XML CDATA tag. |
| 415 | * |
| 416 | * @return string |
| 417 | * @since 2.1.0 |
| 418 | * |
| 419 | */ |
| 420 | private static function getCData( $str ) { |
| 421 | if ( ! seems_utf8( $str ) ) { |
| 422 | $str = utf8_encode( $str ); |
| 423 | } |
| 424 | |
| 425 | $str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>'; |
| 426 | |
| 427 | return $str; |
| 428 | } |
| 429 | |
| 430 | /** |
| 431 | * Output a cat_name XML tag from a given category object |
| 432 | * |
| 433 | * @param WP_Term $category Category Object |
| 434 | * |
| 435 | * @since 2.1.0 |
| 436 | * |
| 437 | */ |
| 438 | private static function printCatName( $category ) { |
| 439 | if ( empty( $category->name ) ) { |
| 440 | return; |
| 441 | } |
| 442 | |
| 443 | echo '<wp:cat_name>' . static::getCData( $category->name ) . "</wp:cat_name>\n"; |
| 444 | } |
| 445 | |
| 446 | /** |
| 447 | * Output a category_description XML tag from a given category object |
| 448 | * |
| 449 | * @param WP_Term $category Category Object |
| 450 | * |
| 451 | * @since 2.1.0 |
| 452 | * |
| 453 | */ |
| 454 | private static function printCatDescription( $category ) { |
| 455 | if ( empty( $category->description ) ) { |
| 456 | return; |
| 457 | } |
| 458 | |
| 459 | echo '<wp:category_description>' . static::getCData( $category->description ) . "</wp:category_description>\n"; |
| 460 | } |
| 461 | |
| 462 | /** |
| 463 | * Output term meta XML tags for a given term object. |
| 464 | * |
| 465 | * @param WP_Term $term Term object. |
| 466 | * |
| 467 | * @since 4.6.0 |
| 468 | * |
| 469 | */ |
| 470 | private static function printTermMeta( $term ) { |
| 471 | global $wpdb; |
| 472 | |
| 473 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
| 474 | $termmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->termmeta WHERE term_id = %d", $term->term_id ) ); |
| 475 | |
| 476 | foreach ( $termmeta as $meta ) { |
| 477 | /** |
| 478 | * Filters whether to selectively skip term meta used for WXR exports. |
| 479 | * |
| 480 | * Returning a truthy value from the filter will skip the current meta |
| 481 | * object from being exported. |
| 482 | * |
| 483 | * @param bool $skip Whether to skip the current piece of term meta. Default false. |
| 484 | * @param string $meta_key Current meta key. |
| 485 | * @param object $meta Current meta object. |
| 486 | * |
| 487 | * @since 4.6.0 |
| 488 | * |
| 489 | */ |
| 490 | if ( ! apply_filters( 'wxr_export_skip_termmeta', false, $meta->meta_key, $meta ) ) { |
| 491 | printf( "\t\t<wp:termmeta>\n\t\t\t<wp:meta_key>%s</wp:meta_key>\n\t\t\t<wp:meta_value>%s</wp:meta_value>\n\t\t</wp:termmeta>\n", wxr_cdata( $meta->meta_key ), wxr_cdata( $meta->meta_value ) ); |
| 492 | } |
| 493 | } |
| 494 | } |
| 495 | |
| 496 | /** |
| 497 | * Output a tag_name XML tag from a given tag object |
| 498 | * |
| 499 | * @param WP_Term $tag Tag Object |
| 500 | * |
| 501 | * @since 2.3.0 |
| 502 | * |
| 503 | */ |
| 504 | private static function printTagName( $tag ) { |
| 505 | if ( empty( $tag->name ) ) { |
| 506 | return; |
| 507 | } |
| 508 | |
| 509 | echo '<wp:tag_name>' . static::getCData( $tag->name ) . "</wp:tag_name>\n"; |
| 510 | } |
| 511 | |
| 512 | /** |
| 513 | * Output a tag_description XML tag from a given tag object |
| 514 | * |
| 515 | * @param WP_Term $tag Tag Object |
| 516 | * |
| 517 | * @since 2.3.0 |
| 518 | * |
| 519 | */ |
| 520 | private static function printTagDescription( $tag ) { |
| 521 | if ( empty( $tag->description ) ) { |
| 522 | return; |
| 523 | } |
| 524 | |
| 525 | echo '<wp:tag_description>' . static::getCData( $tag->description ) . "</wp:tag_description>\n"; |
| 526 | } |
| 527 | |
| 528 | /** |
| 529 | * Output a term_name XML tag from a given term object |
| 530 | * |
| 531 | * @param WP_Term $term Term Object |
| 532 | * |
| 533 | * @since 2.9.0 |
| 534 | * |
| 535 | */ |
| 536 | private static function printTermName( $term ) { |
| 537 | if ( empty( $term->name ) ) { |
| 538 | return; |
| 539 | } |
| 540 | |
| 541 | echo '<wp:term_name>' . static::getCData( $term->name ) . "</wp:term_name>\n"; |
| 542 | } |
| 543 | |
| 544 | /** |
| 545 | * Output a term_description XML tag from a given term object |
| 546 | * |
| 547 | * @param WP_Term $term Term Object |
| 548 | * |
| 549 | * @since 2.9.0 |
| 550 | * |
| 551 | */ |
| 552 | private static function printTermDescription( $term ) { |
| 553 | if ( empty( $term->description ) ) { |
| 554 | return; |
| 555 | } |
| 556 | |
| 557 | echo "\t\t<wp:term_description>" . static::getCData( $term->description ) . "</wp:term_description>\n"; |
| 558 | } |
| 559 | |
| 560 | /** |
| 561 | * Output all navigation menu terms |
| 562 | * |
| 563 | * @since 3.1.0 |
| 564 | */ |
| 565 | private static function printNavTerms() { |
| 566 | $nav_menus = wp_get_nav_menus(); |
| 567 | if ( empty( $nav_menus ) || ! is_array( $nav_menus ) ) { |
| 568 | return; |
| 569 | } |
| 570 | |
| 571 | foreach ( $nav_menus as $menu ) { |
| 572 | echo "\t<wp:term>"; |
| 573 | echo '<wp:term_id>' . (int) $menu->term_id . '</wp:term_id>'; |
| 574 | echo '<wp:term_taxonomy>nav_menu</wp:term_taxonomy>'; |
| 575 | echo '<wp:term_slug>' . static::getCData( $menu->slug ) . '</wp:term_slug>'; |
| 576 | static::printTermName( $menu ); |
| 577 | echo "</wp:term>\n"; |
| 578 | } |
| 579 | } |
| 580 | |
| 581 | /** |
| 582 | * Output list of taxonomy terms, in XML tag format, associated with a post |
| 583 | * |
| 584 | * @since 2.3.0 |
| 585 | */ |
| 586 | private static function printPostTaxonomy( $post ) { |
| 587 | |
| 588 | $taxonomies = get_object_taxonomies( $post->post_type ); |
| 589 | if ( empty( $taxonomies ) ) { |
| 590 | return; |
| 591 | } |
| 592 | $terms = wp_get_object_terms( $post->ID, $taxonomies ); |
| 593 | |
| 594 | foreach ( (array) $terms as $term ) { |
| 595 | echo "\t\t<category domain=\"{$term->taxonomy}\" nicename=\"{$term->slug}\">" . static::getCData( $term->name ) . "</category>\n"; |
| 596 | } |
| 597 | } |
| 598 | |
| 599 | /** |
| 600 | * @param bool $return_me |
| 601 | * @param string $meta_key |
| 602 | * |
| 603 | * @return bool |
| 604 | */ |
| 605 | public static function skipPostMeta( $return_me, $meta_key ) { |
| 606 | |
| 607 | $skipped = array( '_edit_lock', 'extend_builder' ); |
| 608 | |
| 609 | if ( in_array( $meta_key, $skipped ) ) { |
| 610 | $return_me = true; |
| 611 | } |
| 612 | |
| 613 | return $return_me; |
| 614 | } |
| 615 | } |
| 616 |