Ticket #22435: export-api.diff
File export-api.diff, 36.2 KB (added by , 12 years ago) |
---|
-
wp-includes/Oxymel.php
1 <?php 2 class Oxymel { 3 private $xml; 4 private $dom; 5 private $current_element; 6 private $last_inserted; 7 private $go_deep_on_next_element = 0; 8 private $go_up_on_next_element = 0; 9 private $nesting_level = 0; 10 private $contains_nesting_level = 0; 11 private $indentation= ' '; 12 13 public function __construct() { 14 $this->xml = ''; 15 $this->init_new_dom(); 16 } 17 18 public function to_string() { 19 return $this->xml .= $this->indent( $this->xml_from_dom(), $this->nesting_level ); 20 } 21 22 public function __call( $name, $args ) { 23 array_unshift( $args, $name ); 24 return call_user_func_array( array( $this, 'tag' ), $args ); 25 } 26 27 public function __get( $name ) { 28 return $this->$name(); 29 } 30 31 public function contains() { 32 $this->contains_nesting_level++; 33 $this->nesting_level++; 34 if ( $this->go_deep_on_next_element ) { 35 throw new OxymelException( 'contains cannot be used consecutively more than once' ); 36 } 37 $this->go_deep_on_next_element++; 38 return $this; 39 } 40 41 public function end() { 42 $this->contains_nesting_level--; 43 $this->nesting_level--; 44 if ( $this->contains_nesting_level < 0 ) { 45 throw new OxymelException( 'end is used without a matching contains' ); 46 } 47 $this->go_up_on_next_element++; 48 return $this; 49 } 50 51 public function tag( $name, $content_or_attributes = null, $attributes = array() ) { 52 list( $content, $attributes ) = $this->get_content_and_attributes_from_tag_args( $content_or_attributes, $attributes ); 53 $is_opening = 0 === strpos( $name, 'open_' ); 54 $is_closing = 0 === strpos( $name, 'close_' ); 55 $name = preg_replace("/^(open|close)_/", '', $name ); 56 57 $element = $this->create_element( $name, $content, $attributes ); 58 59 if ( !$is_opening && !$is_closing ) 60 $this->add_element_to_dom( $element ); 61 elseif ( $is_opening ) 62 $this->add_opening_tag_from_element( $element ); 63 elseif ( $is_closing ) 64 $this->add_closing_tag_from_tag_name( $name ); 65 66 return $this; 67 } 68 69 public function cdata( $text ) { 70 $this->add_element_to_dom( $this->dom->createCDATASection( $text ) ); 71 return $this; 72 } 73 74 public function text( $text ) { 75 $this->add_element_to_dom( $this->dom->createTextNode( $text ) ); 76 return $this; 77 } 78 79 public function comment( $text ) { 80 $this->add_element_to_dom( $this->dom->createComment( $text ) ); 81 return $this; 82 } 83 84 public function xml() { 85 $this->add_element_to_dom( $this->dom->createProcessingInstruction( 'xml', 'version="1.0" encoding="UTF-8"' ) ); 86 return $this; 87 } 88 89 public function oxymel( Oxymel $other ) { 90 foreach( $other->dom->childNodes as $child ) { 91 $child = $this->dom->importNode( $child, true ); 92 $this->add_element_to_dom( $child ); 93 } 94 return $this; 95 } 96 97 public function raw( $raw_xml ) { 98 if ( !$raw_xml ) { 99 return $this; 100 } 101 $fragment = $this->dom->createDocumentFragment(); 102 $fragment->appendXML($raw_xml); 103 $this->add_element_to_dom( $fragment ); 104 return $this; 105 } 106 107 private function add_element_to_dom( $element ) { 108 $this->move_current_element_deep(); 109 $this->move_current_element_up(); 110 $this->last_inserted = $this->current_element->appendChild($element); 111 } 112 113 private function move_current_element_deep() { 114 if ( $this->go_deep_on_next_element ) { 115 if ( !$this->last_inserted ) { 116 throw new OxymelException( 'contains has been used before adding any tags' ); 117 } 118 $this->current_element = $this->last_inserted; 119 $this->go_deep_on_next_element--; 120 } 121 } 122 123 private function move_current_element_up() { 124 if ( $this->go_up_on_next_element ) { 125 while ( $this->go_up_on_next_element ) { 126 $this->current_element = $this->current_element->parentNode; 127 $this->go_up_on_next_element--; 128 } 129 } 130 } 131 132 private function get_content_and_attributes_from_tag_args( $content_or_attributes, array $attributes ) { 133 $content = null; 134 if ( !$attributes ) { 135 if ( is_array( $content_or_attributes ) ) 136 $attributes = $content_or_attributes; 137 else 138 $content = $content_or_attributes; 139 } else { 140 $content = $content_or_attributes; 141 } 142 return array( $content, $attributes ); 143 } 144 145 private function init_new_dom() { 146 unset( $this->dom, $this->current_element ); 147 $this->dom = new DOMDocument(); 148 $this->dom->formatOutput = true; 149 $this->current_element = $this->dom; 150 $this->last_inserted = null; 151 } 152 153 private function xml_from_dom() { 154 if ( 0 !== $this->contains_nesting_level ) { 155 throw new OxymelException( 'contains and end calls do not match' ); 156 } 157 $xml = ''; 158 foreach( $this->dom->childNodes as $child ) { 159 $xml .= $this->dom->saveXML( $child ) . "\n"; 160 } 161 return $xml; 162 } 163 164 private function create_element( $name, $content, $attributes ) { 165 if ( !is_null( $content ) ) 166 $element = $this->dom->createElement( $name, $content ); 167 else 168 $element = $this->dom->createElement( $name ); 169 170 foreach( $attributes as $attribute_name => $attribute_value ) { 171 $element->setAttribute( $attribute_name, $attribute_value ); 172 } 173 174 return $element; 175 } 176 177 private function add_opening_tag_from_element( $element ) { 178 $this->xml .= $this->indent( $this->xml_from_dom(), $this->nesting_level ); 179 $tag = $this->dom->saveXML($element); 180 $this->xml .= $this->indent( str_replace( '/>', '>', $tag ) . "\n", $this->nesting_level ); 181 $this->nesting_level++; 182 $this->init_new_dom(); 183 } 184 185 private function add_closing_tag_from_tag_name( $name ) { 186 $this->xml .= $this->xml_from_dom(); 187 $this->nesting_level--; 188 if ( $this->nesting_level < 0 ) { 189 $this->xml = $this->indent( $this->xml, -$this->nesting_level ); 190 $this->nesting_level = 0; 191 } 192 $this->xml .= $this->indent( "</$name>\n", $this->nesting_level ); 193 $this->init_new_dom(); 194 } 195 196 private function indent( $string, $level ) { 197 if ( !$level ) { 198 return $string; 199 } 200 $lines = explode( "\n", $string ); 201 foreach( $lines as &$line ) { 202 if ( !trim( $line ) ) 203 continue; 204 $line = str_repeat( $this->indentation, $level ) . $line; 205 } 206 return implode( "\n", $lines ); 207 } 208 } 209 210 class OxymelException extends Exception { 211 } -
wp-includes/default-constants.php
Property changes on: wp-includes/Oxymel.php ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
80 80 define( 'DAY_IN_SECONDS', 24 * HOUR_IN_SECONDS ); 81 81 define( 'WEEK_IN_SECONDS', 7 * DAY_IN_SECONDS ); 82 82 define( 'YEAR_IN_SECONDS', 365 * DAY_IN_SECONDS ); 83 84 // Constants for expressing human-readable data sizes 85 // in their respective number of bytes. 86 define( 'KB_IN_BYTES', 1024 ); 87 define( 'MB_IN_BYTES', 1024 * KB_IN_BYTES ); 88 define( 'GB_IN_BYTES', 1024 * MB_IN_BYTES ); 89 define( 'TB_IN_BYTES', 1024 * GB_IN_BYTES ); 90 define( 'PB_IN_BYTES', 1024 * TB_IN_BYTES ); 91 define( 'EB_IN_BYTES', 1024 * PB_IN_BYTES ); 92 define( 'ZB_IN_BYTES', 1024 * EB_IN_BYTES ); 93 define( 'YB_IN_BYTES', 1024 * ZB_IN_BYTES ); 83 94 } 84 95 85 96 /** -
wp-includes/export/class-wp-export-query.php
1 <?php 2 /** 3 * Represents a set of posts and other site data to be exported. 4 * 5 * An immutable object, which gathers all data needed for the export. 6 */ 7 class WP_Export_Query { 8 const QUERY_CHUNK = 100; 9 10 private static $defaults = array( 11 'post_ids' => null, 12 'post_type' => null, 13 'status' => null, 14 'author' => null, 15 'start_date' => null, 16 'end_date' => null, 17 'category' => null, 18 ); 19 20 private $post_ids; 21 private $filters; 22 private $xml_gen; 23 24 private $wheres = array(); 25 private $joins = array(); 26 27 private $author; 28 private $category; 29 30 public function __construct( $filters = array() ) { 31 $this->filters = wp_parse_args( $filters, self::$defaults ); 32 $this->post_ids = $this->calculate_post_ids(); 33 } 34 35 public function post_ids() { 36 return $this->post_ids; 37 } 38 39 public function charset() { 40 return get_bloginfo( 'charset' ); 41 } 42 43 public function site_metadata() { 44 $metadata = array( 45 'name' => $this->bloginfo_rss( 'name' ), 46 'url' => $this->bloginfo_rss( 'url' ), 47 'language' => $this->bloginfo_rss( 'language' ), 48 'description' => $this->bloginfo_rss( 'description' ), 49 'pubDate' => date( 'D, d M Y H:i:s +0000' ), 50 'site_url' => is_multisite()? network_home_url() : $this->bloginfo_rss( 'url' ), 51 'blog_url' => $this->bloginfo_rss( 'url' ), 52 ); 53 return $metadata; 54 } 55 56 public function wp_generator_tag() { 57 return apply_filters( 'the_generator', get_the_generator( 'export' ), 'export' ); 58 } 59 60 public function authors() { 61 global $wpdb; 62 $authors = array(); 63 $author_ids = $wpdb->get_col( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft'" ); 64 foreach ( (array) $author_ids as $author_id ) { 65 $authors[] = get_userdata( $author_id ); 66 } 67 $authors = array_filter( $authors ); 68 return $authors; 69 } 70 71 public function categories() { 72 if ( $this->category ) { 73 return $this->category; 74 } 75 if ( $this->filters['post_type'] ) { 76 return array(); 77 } 78 $categories = (array) get_categories( array( 'get' => 'all' ) ); 79 $categories = self::topologically_sort_terms( $categories ); 80 return $categories; 81 } 82 83 public function tags() { 84 if ( $this->filters['post_type'] ) { 85 return array(); 86 } 87 $tags = (array) get_tags( array( 'get' => 'all' ) ); 88 return $tags; 89 } 90 91 public function custom_taxonomies_terms() { 92 if ( $this->filters['post_type'] ) { 93 return array(); 94 } 95 $custom_taxonomies = get_taxonomies( array( '_builtin' => false ) ); 96 $custom_terms = (array) get_terms( $custom_taxonomies, array( 'get' => 'all' ) ); 97 $custom_terms = self::topologically_sort_terms( $custom_terms ); 98 return $custom_terms; 99 } 100 101 public function nav_menu_terms() { 102 $nav_menus = wp_get_nav_menus(); 103 foreach( $nav_menus as &$term ) { 104 $term->description = ''; 105 } 106 return $nav_menus; 107 } 108 109 public function exportify_post( $post ) { 110 $GLOBALS['wp_query']->in_the_loop = true; 111 $previous_global_post = isset( $GLOBALS['post'] )? $GLOBALS['post'] : null; 112 $GLOBALS['post'] = $post; 113 setup_postdata( $post ); 114 $post->post_content = apply_filters( 'the_content_export', $post->post_content ); 115 $post->post_excerpt = apply_filters( 'the_excerpt_export', $post->post_excerpt ); 116 $post->is_sticky = is_sticky( $post->ID ) ? 1 : 0; 117 $post->terms = self::get_terms_for_post( $post ); 118 $post->meta = self::get_meta_for_post( $post ); 119 $post->comments = self::get_comments_for_post( $post ); 120 $GLOBALS['post'] = $previous_global_post; 121 return $post; 122 } 123 124 public function posts() { 125 $posts_iterator = new WP_Post_IDs_Iterator( $this->post_ids, self::QUERY_CHUNK ); 126 return new WP_Map_Iterator( $posts_iterator, array( $this, 'exportify_post' ) ); 127 } 128 129 private function calculate_post_ids() { 130 global $wpdb; 131 if ( is_array( $this->filters['post_ids'] ) ) { 132 return $this->filters['post_ids']; 133 } 134 $this->post_type_where(); 135 $this->status_where(); 136 $this->author_where(); 137 $this->start_date_where(); 138 $this->end_date_where(); 139 $this->category_where(); 140 141 $where = implode( ' AND ', array_filter( $this->wheres ) ); 142 if ( $where ) $where = "WHERE $where"; 143 $join = implode( ' ', array_filter( $this->joins ) ); 144 145 $post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} AS p $join $where" ); 146 $post_ids = array_merge( $post_ids, $this->attachments_for_specific_post_types( $post_ids ) ); 147 return $post_ids; 148 } 149 150 private function post_type_where() { 151 global $wpdb; 152 $post_types_filters = array( 'can_export' => true ); 153 if ( $this->filters['post_type'] ) { 154 $post_types_filters = array_merge( $post_types_filters, array( 'name' => $this->filters['post_type'] ) ); 155 } 156 $post_types = get_post_types( $post_types_filters ); 157 if ( !$post_types ) { 158 $this->wheres[] = 'p.post_type IS NULL'; 159 return; 160 } 161 $this->wheres[] = $wpdb->build_IN_condition( 'p.post_type', $post_types ); 162 } 163 164 private function status_where() { 165 global $wpdb; 166 if ( !$this->filters['status'] ) { 167 $this->wheres[] = "p.post_status != 'auto-draft'"; 168 return; 169 } 170 $this->wheres[] = $wpdb->prepare( 'p.post_status = %s', $this->filters['status'] ); 171 } 172 173 private function author_where() { 174 global $wpdb; 175 $user = $this->find_user_from_any_object( $this->filters['author'] ); 176 if ( !$user || is_wp_error( $user ) ) { 177 return; 178 } 179 $this->author = $user; 180 $this->wheres[] = $wpdb->prepare( 'p.post_author = %d', $user->ID ); 181 } 182 183 private function start_date_where() { 184 global $wpdb; 185 $timestamp = strtotime( $this->filters['start_date'] ); 186 if ( !$timestamp ) { 187 return; 188 } 189 $this->wheres[] = $wpdb->prepare( 'p.post_date >= %s', date( 'Y-m-d 00:00:00', $timestamp ) ); 190 } 191 192 private function end_date_where() { 193 global $wpdb; 194 $timestamp = strtotime( $this->filters['end_date'] ); 195 if ( !$timestamp ) { 196 return; 197 } 198 $this->wheres[] = $wpdb->prepare( 'p.post_date <= %s', date( 'Y-m-d 23:59:59', $timestamp ) ); 199 } 200 201 private function category_where() { 202 global $wpdb; 203 if ( 'post' != $this->filters['post_type'] ) { 204 return; 205 } 206 $category = $this->find_category_from_any_object( $this->filters['category'] ); 207 if ( !$category ) { 208 return; 209 } 210 $this->category = $category; 211 $this->joins[] = "INNER JOIN {$wpdb->term_relationships} AS tr ON (p.ID = tr.object_id)"; 212 $this->wheres[] = $wpdb->prepare( 'tr.term_taxonomy_id = %d', $category->term_taxonomy_id ); 213 } 214 215 private function attachments_for_specific_post_types( $post_ids ) { 216 global $wpdb; 217 if ( !$this->filters['post_type'] ) { 218 return array(); 219 } 220 $attachment_ids = array(); 221 while ( $batch_of_post_ids = array_splice( $post_ids, 0, self::QUERY_CHUNK ) ) { 222 $post_parent_condition = $wpdb->build_IN_condition( 'post_parent', $batch_of_post_ids ); 223 $attachment_ids = array_merge( $attachment_ids, (array)$wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND $post_parent_condition" ) ); 224 } 225 return array_map( 'intval', $attachment_ids ); 226 } 227 228 private function bloginfo_rss( $section ) { 229 return apply_filters( 'bloginfo_rss', get_bloginfo_rss( $section ), $section ); 230 } 231 232 private function find_user_from_any_object( $user ) { 233 if ( is_numeric( $user ) ) { 234 return get_user_by( 'id', $user ); 235 } elseif ( is_string( $user ) ) { 236 return get_user_by( 'login', $user ); 237 } elseif ( isset( $user->ID ) ) { 238 return get_user_by( 'id', $user->ID ); 239 } 240 return false; 241 } 242 243 private function find_category_from_any_object( $category ) { 244 if ( is_numeric( $category ) ) { 245 return get_term( $category, 'category' ); 246 } elseif ( is_string( $category ) ) { 247 $term = term_exists( $category, 'category' ); 248 return isset( $term['term_id'] )? get_term( $term['term_id'], 'category' ) : false; 249 } elseif ( isset( $category->term_id ) ) { 250 return get_term( $category->term_id, 'category' ); 251 } 252 return false; 253 } 254 255 private static function topologically_sort_terms( $terms ) { 256 $sorted = array(); 257 while ( $term = array_shift( $terms ) ) { 258 if ( $term->parent == 0 || isset( $sorted[$term->parent] ) ) 259 $sorted[$term->term_id] = $term; 260 else 261 $terms[] = $term; 262 } 263 return $sorted; 264 } 265 266 private static function get_terms_for_post( $post ) { 267 $taxonomies = get_object_taxonomies( $post->post_type ); 268 if ( empty( $taxonomies ) ) 269 return array(); 270 $terms = wp_get_object_terms( $post->ID, $taxonomies ); 271 $terms = $terms? $terms : array(); 272 return $terms; 273 } 274 275 private static function get_meta_for_post( $post ) { 276 global $wpdb; 277 $meta_for_export = array(); 278 $meta_from_db = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID ) ); 279 foreach ( $meta_from_db as $meta ) { 280 if ( apply_filters( 'wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) ) 281 continue; 282 $meta_for_export[] = $meta; 283 } 284 return $meta_for_export; 285 } 286 287 private static function get_comments_for_post( $post ) { 288 global $wpdb; 289 $comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) ); 290 foreach( $comments as $comment ) { 291 $meta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $comment->comment_ID ) ); 292 $meta = $meta? $meta : array(); 293 $comment->meta = $meta; 294 } 295 return $comments; 296 } 297 } 298 299 class WP_Export_Exception extends RuntimeException { 300 } -
wp-includes/export/class-wp-export-wxr-formatter.php
Property changes on: wp-includes/export/class-wp-export-query.php ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 <?php 2 /** 3 * Version number for the export format. 4 * 5 * Bump this when something changes that might affect compatibility. 6 * 7 * @since 2.5.0 8 */ 9 define( 'WXR_VERSION', '1.2' ); 10 11 require_once ABSPATH . WPINC . '/Oxymel.php'; 12 13 class WP_Export_Oxymel extends Oxymel { 14 public function optional( $tag_name, $contents ) { 15 if ( $contents ) { 16 $this->$tag_name( $contents ); 17 } 18 return $this; 19 } 20 21 public function optional_cdata( $tag_name, $contents ) { 22 if ( $contents ) { 23 $this->$tag_name->contains->cdata( $contents )->end; 24 } 25 return $this; 26 } 27 } 28 29 /** 30 * Responsible for formatting the data in WP_Export_Query to WXR 31 */ 32 class WP_Export_WXR_Formatter { 33 function __construct( $export ) { 34 $this->export = $export; 35 $this->wxr_version = WXR_VERSION; 36 } 37 38 function before_posts() { 39 $before_posts_xml = ''; 40 $before_posts_xml .= $this->header(); 41 $before_posts_xml .= $this->site_metadata(); 42 $before_posts_xml .= $this->authors(); 43 $before_posts_xml .= $this->categories(); 44 $before_posts_xml .= $this->tags(); 45 $before_posts_xml .= $this->nav_menu_terms(); 46 $before_posts_xml .= $this->custom_taxonomies_terms(); 47 $before_posts_xml .= $this->rss2_head_action(); 48 return $before_posts_xml; 49 } 50 51 function posts() { 52 return new WP_Map_Iterator( $this->export->posts(), array( $this, 'post' ) ); 53 } 54 55 function after_posts() { 56 return $this->footer(); 57 } 58 59 function header() { 60 $oxymel = new Oxymel; 61 $charset = $this->export->charset(); 62 $wp_generator_tag = $this->export->wp_generator_tag(); 63 $comment = <<<COMMENT 64 65 This is a WordPress eXtended RSS file generated by WordPress as an export of your site. 66 It contains information about your site's posts, pages, comments, categories, and other content. 67 You may use this file to transfer that content from one site to another. 68 This file is not intended to serve as a complete backup of your site. 69 70 To import this information into a WordPress site follow these steps: 71 1. Log in to that site as an administrator. 72 2. Go to Tools: Import in the WordPress admin panel. 73 3. Install the "WordPress" importer from the list. 74 4. Activate & Run Importer. 75 5. Upload this file using the form provided on that page. 76 6. You will first be asked to map the authors in this export file to users 77 on the site. For each author, you may choose to map to an 78 existing user on the site or to create a new user. 79 7. WordPress will then import each of the posts, pages, comments, categories, etc. 80 contained in this file into your site. 81 82 COMMENT; 83 return $oxymel 84 ->xml 85 ->comment( $comment ) 86 ->raw( $wp_generator_tag ) 87 ->open_rss( array( 88 'version' => '2.0', 89 'xmlns:excerpt' => "http://wordpress.org/export/{$this->wxr_version}/excerpt/", 90 'xmlns:content' => "http://purl.org/rss/1.0/modules/content/", 91 'xmlns:wfw' => "http://wellformedweb.org/CommentAPI/", 92 'xmlns:dc' => "http://purl.org/dc/elements/1.1/", 93 'xmlns:wp' => "http://wordpress.org/export/{$this->wxr_version}/", 94 ) ) 95 ->open_channel 96 ->to_string(); 97 98 } 99 100 function site_metadata() { 101 $oxymel = new Oxymel; 102 $metadata = $this->export->site_metadata(); 103 return $oxymel 104 ->title( $metadata['name'] ) 105 ->link( $metadata['url'] ) 106 ->description( $metadata['description'] ) 107 ->pubDate( $metadata['pubDate'] ) 108 ->language( $metadata['language'] ) 109 ->tag( 'wp:wxr_version', $this->wxr_version ) 110 ->tag( 'wp:base_site_url', $metadata['site_url'] ) 111 ->tag( 'wp:base_blog_url', $metadata['blog_url'] ) 112 ->to_string(); 113 } 114 115 function authors() { 116 $oxymel = new Oxymel; 117 $authors = $this->export->authors(); 118 foreach ( $authors as $author ) { 119 $oxymel 120 ->tag( 'wp:wp_author' )->contains 121 ->tag( 'wp:author_login', $author->user_login ) 122 ->tag( 'wp:author_email', $author->user_email ) 123 ->tag( 'wp:author_display_name' )->contains->cdata( $author->display_name )->end 124 ->tag( 'wp:author_first_name' )->contains->cdata( $author->user_first_name )->end 125 ->tag( 'wp:author_last_name' )->contains->cdata( $author->user_last_name )->end 126 ->end; 127 } 128 return $oxymel->to_string(); 129 } 130 131 function categories() { 132 $oxymel = new WP_Export_Oxymel; 133 $categories = $this->export->categories(); 134 foreach( $categories as $term_id => $category ) { 135 $category->parent_slug = $category->parent? $categories[$category->parent]->slug : ''; 136 $oxymel->tag( 'wp:category' )->contains 137 ->tag( 'wp:term_id', $category->term_id ) 138 ->tag( 'wp:category_nicename', $category->slug ) 139 ->tag( 'wp:category_parent', $category->parent_slug ) 140 ->optional_cdata( 'wp:cat_name', $category->name ) 141 ->optional_cdata( 'wp:category_description', $category->description ) 142 ->end; 143 } 144 return $oxymel->to_string(); 145 } 146 147 function tags() { 148 $oxymel = new WP_Export_Oxymel; 149 $tags = $this->export->tags(); 150 foreach( $tags as $tag ) { 151 $oxymel->tag( 'wp:tag' )->contains 152 ->tag( 'wp:term_id', $tag->term_id ) 153 ->tag( 'wp:tag_slug', $tag->slug ) 154 ->optional_cdata( 'wp:tag_name', $tag->name ) 155 ->optional_cdata( 'wp:tag_description', $tag->description ) 156 ->end; 157 } 158 return $oxymel->to_string(); 159 } 160 161 function nav_menu_terms() { 162 return $this->terms( $this->export->nav_menu_terms() ); 163 } 164 165 function custom_taxonomies_terms() { 166 return $this->terms( $this->export->custom_taxonomies_terms() ); 167 } 168 169 function rss2_head_action() { 170 ob_start(); 171 do_action( 'rss2_head' ); 172 $action_output = ob_get_clean(); 173 return $action_output; 174 } 175 176 private function terms( $terms ) { 177 $oxymel = new WP_Export_Oxymel; 178 foreach( $terms as $term ) { 179 $term->parent_slug = $term->parent? $terms[$term->parent]->slug : ''; 180 $oxymel->tag( 'wp:term' )->contains 181 ->tag( 'wp:term_id', $term->term_id ) 182 ->tag( 'wp:term_taxonomy', $term->taxonomy ) 183 ->tag( 'wp:term_slug', $term->slug ); 184 if ( 'nav_menu' != $term->taxonomy ) { 185 $oxymel 186 ->tag( 'wp:term_parent', $term->parent_slug ); 187 } 188 $oxymel 189 ->optional_cdata( 'wp:term_name', $term->name ) 190 ->optional_cdata( 'wp:term_description', $term->description ) 191 ->end; 192 } 193 return $oxymel->to_string(); 194 } 195 196 function post( $post ) { 197 $oxymel = new WP_Export_Oxymel; 198 $GLOBALS['wp_query']->in_the_loop = true; 199 $GLOBALS['post'] = $post; 200 setup_postdata( $post ); 201 202 $oxymel->item->contains 203 ->title( apply_filters( 'the_title_rss', $post->post_title ) ) 204 ->link( apply_filters('the_permalink_rss', get_permalink() ) ) 205 ->pubDate( mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ) ) 206 ->tag( 'dc:creator', get_the_author_meta( 'login' ) ) 207 ->guid( get_the_guid(), array( 'isPermaLink' => 'false' ) ) 208 ->description( '' ) 209 ->tag( 'content:encoded' )->contains->cdata( $post->post_content )->end 210 ->tag( 'excerpt:encoded' )->contains->cdata( $post->post_excerpt )->end 211 ->tag( 'wp:post_id', $post->ID ) 212 ->tag( 'wp:post_date', $post->post_date ) 213 ->tag( 'wp:post_date_gmt', $post->post_date_gmt ) 214 ->tag( 'wp:comment_status', $post->comment_status ) 215 ->tag( 'wp:ping_status', $post->ping_status ) 216 ->tag( 'wp:post_name', $post->post_name ) 217 ->tag( 'wp:status', $post->post_status ) 218 ->tag( 'wp:post_parent', $post->post_parent ) 219 ->tag( 'wp:menu_order', $post->menu_order ) 220 ->tag( 'wp:post_type', $post->post_type ) 221 ->tag( 'wp:post_password', $post->post_password ) 222 ->tag( 'wp:is_sticky', $post->is_sticky ) 223 ->optional( 'wp:attachment_url', wp_get_attachment_url( $post->ID ) ); 224 foreach( $post->terms as $term ) { 225 $oxymel 226 ->category( array( 'domain' => $term->taxonomy, 'nicename' => $term->slug ) )->contains->cdata( $term->name )->end; 227 } 228 foreach( $post->meta as $meta ) { 229 $oxymel 230 ->tag( 'wp:postmeta' )->contains 231 ->tag( 'wp:meta_key', $meta->meta_key ) 232 ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end 233 ->end; 234 } 235 foreach( $post->comments as $comment ) { 236 $oxymel 237 ->tag( 'wp:comment' )->contains 238 ->tag( 'wp:comment_id', $comment->comment_ID ) 239 ->tag( 'wp:comment_author' )->contains->cdata( $comment->comment_author )->end 240 ->tag( 'wp:comment_author_email', $comment->comment_author_email ) 241 ->tag( 'wp:comment_author_url', $comment->comment_author_url ) 242 ->tag( 'wp:comment_author_IP', $comment->comment_author_IP ) 243 ->tag( 'wp:comment_date', $comment->comment_date ) 244 ->tag( 'wp:comment_date_gmt', $comment->comment_date_gmt ) 245 ->tag( 'wp:comment_content' )->contains->cdata( $comment->comment_content )->end 246 ->tag( 'wp:comment_approved', $comment->comment_approved ) 247 ->tag( 'wp:comment_type', $comment->comment_type ) 248 ->tag( 'wp:comment_parent', $comment->comment_parent ) 249 ->tag( 'wp:comment_user_id', $comment->user_id ) 250 ->oxymel( $this->comment_meta( $comment ) ) 251 ->end; 252 } 253 $oxymel 254 ->end; 255 return $oxymel->to_string(); 256 } 257 258 private function comment_meta( $comment ) { 259 global $wpdb; 260 $metas = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $comment->comment_ID ) ); 261 if ( !$metas ) { 262 return new Oxymel; 263 } 264 $oxymel = new WP_Export_Oxymel; 265 foreach( $metas as $meta ) { 266 $oxymel->tag( 'wp:commentmeta' )->contains 267 ->tag( 'wp:meta_key', $meta->meta_key ) 268 ->tag( 'wp:meta_value', $meta->meta_value ) 269 ->end; 270 } 271 return $oxymel; 272 } 273 274 275 function footer() { 276 $oxymel = new Oxymel; 277 return $oxymel->close_channel->close_rss->to_string(); 278 } 279 } -
wp-includes/export/functions.export.php
Property changes on: wp-includes/export/class-wp-export-wxr-formatter.php ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 <?php 2 3 function wp_export( $args = array() ) { 4 $defaults = array( 5 'filters' => array(), 6 'format' => 'WP_Export_WXR_Formatter', 7 'writer' => 'WP_Export_Returner', 8 'writer_args' => null, 9 ); 10 $args = wp_parse_args( $args, $defaults ); 11 $export_query = new WP_Export_Query( $args['filters'] ); 12 $formatter = new $args['format']( $export_query ); 13 $writer = new $args['writer']( $formatter, $args['writer_args'] ); 14 try { 15 return $writer->export(); 16 } catch ( WP_Export_Exception $e ) { 17 return new WP_Error( 'wp-export-error', $e->getMessage() ); 18 } 19 } -
wp-includes/export/writers.php
Property changes on: wp-includes/export/functions.export.php ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 <?php 2 abstract class WP_Export_Base_Writer { 3 protected $formatter; 4 5 function __construct( $formatter ) { 6 $this->formatter = $formatter; 7 } 8 9 public function export() { 10 $this->write( $this->formatter->before_posts() ); 11 foreach( $this->formatter->posts() as $post_in_wxr ) { 12 $this->write( $post_in_wxr ); 13 } 14 $this->write( $this->formatter->after_posts() ); 15 } 16 17 abstract protected function write( $xml ); 18 } 19 20 class WP_Export_XML_Over_HTTP extends WP_Export_Base_Writer { 21 private $file_name; 22 23 function __construct( $formatter, $file_name ) { 24 parent::__construct( $formatter ); 25 $this->file_name = $file_name; 26 } 27 28 public function export() { 29 header( 'Content-Description: File Transfer' ); 30 header( 'Content-Disposition: attachment; filename=' . $this->file_name ); 31 header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true ); 32 parent::export(); 33 } 34 35 protected function write( $xml ) { 36 echo $xml; 37 } 38 } 39 40 class WP_Export_Returner extends WP_Export_Base_Writer { 41 private $result = ''; 42 43 public function export() { 44 $this->private = ''; 45 parent::export(); 46 return $this->result; 47 } 48 protected function write( $xml ) { 49 $this->result .= $xml; 50 } 51 } 52 53 class WP_Export_File_Writer extends WP_Export_Base_Writer { 54 private $f; 55 private $file_name; 56 57 public function __construct( $formatter, $file_name ) { 58 parent::__construct( $formatter ); 59 $this->file_name = $file_name; 60 } 61 62 public function export() { 63 $this->f = fopen( $this->file_name, 'w' ); 64 if ( !$this->f ) { 65 throw new WP_Export_Exception( sprintf( __( 'WP Export: error opening %s for writing.' ), $this->file_name ) ); 66 } 67 parent::export(); 68 fclose( $this->f ); 69 } 70 71 protected function write( $xml ) { 72 $res = fwrite( $this->f, $xml); 73 if ( false === $res ) { 74 throw new WP_Export_Exception( __( 'WP Export: error writing to export file.' ) ); 75 } 76 } 77 } 78 79 class WP_Export_Split_Files_Writer extends WP_Export_Base_Writer { 80 private $result = ''; 81 private $f; 82 private $next_file_number = 0; 83 private $current_file_size = 0; 84 85 function __construct( $formatter, $writer_args = array() ) { 86 parent::__construct( $formatter ); 87 //TODO: check if args are not missing 88 $this->max_file_size = is_null( $writer_args['max_file_size'] ) ? 15 * MB_IN_BYTES : $max_file_size; 89 $this->destination_directory = $writer_args['destination_directory']; 90 $this->filename_template = $writer_args['filename_template']; 91 $this->before_posts_xml = $this->formatter->before_posts(); 92 $this->after_posts_xml = $this->formatter->after_posts(); 93 } 94 95 public function export() { 96 $this->start_new_file(); 97 foreach( $this->formatter->posts() as $post_xml ) { 98 if ( $this->current_file_size + strlen( $post_xml ) > $this->max_file_size ) { 99 $this->start_new_file(); 100 } 101 $this->write( $post_xml ); 102 } 103 $this->close_current_file(); 104 } 105 106 protected function write( $xml ) { 107 $res = fwrite( $this->f, $xml); 108 if ( false === $res ) { 109 throw new WP_Export_Exception( __( 'WP Export: error writing to export file.' ) ); 110 } 111 $this->current_file_size += strlen( $xml ); 112 } 113 114 private function start_new_file() { 115 if ( $this->f ) { 116 $this->close_current_file(); 117 } 118 $file_path = $this->next_file_path(); 119 $this->f = fopen( $file_path, 'w' ); 120 if ( !$this->f ) { 121 throw new WP_Export_Exception( sprintf( __( 'WP Export: error opening %s for writing.' ), $file_path ) ); 122 } 123 $this->current_file_size = 0; 124 $this->write( $this->before_posts_xml ); 125 } 126 127 private function close_current_file() { 128 if ( !$this->f ) { 129 return; 130 } 131 $this->write( $this->after_posts_xml ); 132 fclose( $this->f ); 133 } 134 135 private function next_file_name() { 136 $next_file_name = sprintf( $this->filename_template, $this->next_file_number ); 137 $this->next_file_number++; 138 return $next_file_name; 139 } 140 141 private function next_file_path() { 142 return untrailingslashit( $this->destination_directory ) . DIRECTORY_SEPARATOR . $this->next_file_name(); 143 } 144 145 } -
wp-includes/iterators.php
1 <?php 2 class WP_Map_Iterator extends IteratorIterator { 3 function __construct( $iterator, $callback ) { 4 $this->callback = $callback; 5 parent::__construct( $iterator ); 6 } 7 8 function current() { 9 $original_current = parent::current(); 10 return call_user_func( $this->callback, $original_current ); 11 } 12 } 13 14 class WP_Post_IDs_Iterator implements Iterator { 15 private $limit = 100; 16 private $post_ids; 17 private $ids_left; 18 private $results = array(); 19 20 public function __construct( $post_ids, $limit = null ) { 21 $this->db = $GLOBALS['wpdb']; 22 $this->post_ids = $post_ids; 23 $this->ids_left = $post_ids; 24 if ( !is_null( $limit ) ) { 25 $this->limit = $limit; 26 } 27 } 28 29 public function current() { 30 return $this->results[$this->index_in_results]; 31 } 32 33 public function key() { 34 return $this->global_index; 35 } 36 37 public function next() { 38 $this->index_in_results++; 39 $this->global_index++; 40 } 41 42 public function rewind() { 43 $this->results = array(); 44 $this->global_index = 0; 45 $this->index_in_results = 0; 46 $this->ids_left = $this->post_ids; 47 } 48 49 public function valid() { 50 if ( isset( $this->results[$this->index_in_results] ) ) { 51 return true; 52 } 53 if ( empty( $this->ids_left ) ) { 54 return false; 55 } 56 $has_posts = $this->load_next_posts_from_db(); 57 if ( !$has_posts ) { 58 return false; 59 } 60 $this->index_in_results = 0; 61 return true; 62 } 63 64 private function load_next_posts_from_db() { 65 $next_batch_post_ids = array_splice( $this->ids_left, 0, $this->limit ); 66 $in_post_ids_sql = $this->db->build_IN_condition( 'ID', $next_batch_post_ids ); 67 $this->results = $this->db->get_results( "SELECT * FROM {$this->db->posts} WHERE $in_post_ids_sql" ); 68 if ( !$this->results ) { 69 if ( $this->db->last_error ) { 70 throw new WP_Iterator_Exception( 'Database error: ' . $this->db->last_error ); 71 } else { 72 return false; 73 } 74 } 75 return true; 76 } 77 } 78 79 class WP_Iterator_Exception extends Exception { 80 } -
wp-includes/wp-db.php
1734 1734 function db_version() { 1735 1735 return preg_replace( '/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ) ); 1736 1736 } 1737 1738 /** 1739 * Builds a SQL condition in the form "post_id IN (1, 2, 3, 4)" 1740 * 1741 * @since 3.6.0 1742 * 1743 * @param string $column_name The name of the table column from the IN condition 1744 * @param array $values Array of values in which the column value should be 1745 * @param string $format Optional printf format specifier for the elements of the array. Defaults to %s. 1746 * @return string The IN condition, with escaped values. If there are no values, the return value is an empty string. 1747 */ 1748 function build_IN_condition( $column_name, $values, $format = '%s' ) { 1749 if ( !is_array( $values ) || empty( $values ) ) { 1750 return ''; 1751 } 1752 $formats = implode( ', ', array_fill( 0, count( $values ), $format ) ); 1753 return $this->prepare( "$column_name IN ($formats)", $values ); 1754 } 1737 1755 } -
wp-settings.php
123 123 require( ABSPATH . WPINC . '/comment.php' ); 124 124 require( ABSPATH . WPINC . '/comment-template.php' ); 125 125 require( ABSPATH . WPINC . '/rewrite.php' ); 126 require( ABSPATH . WPINC . '/iterators.php' ); 127 require( ABSPATH . WPINC . '/export/class-wp-export-query.php' ); 128 require( ABSPATH . WPINC . '/export/class-wp-export-wxr-formatter.php' ); 129 require( ABSPATH . WPINC . '/export/writers.php' ); 130 require( ABSPATH . WPINC . '/export/functions.export.php' ); 126 131 require( ABSPATH . WPINC . '/feed.php' ); 127 132 require( ABSPATH . WPINC . '/bookmark.php' ); 128 133 require( ABSPATH . WPINC . '/bookmark-template.php' );