class-auxels-admin-assets.php
1 year ago
class-auxels-archive-menu-links.php
1 year ago
class-auxels-envato-elements.php
1 year ago
class-auxels-import-parser.php
3 years ago
class-auxels-import.php
3 years ago
class-auxels-search-post-type.php
6 months ago
class-auxels-wc-attribute-nav-menu.php
1 year ago
class-auxin-admin-dashboard.php
1 year ago
class-auxin-demo-importer.php
6 months ago
class-auxin-dependency-sorting.php
3 years ago
class-auxin-import.php
1 year ago
class-auxin-install.php
1 year ago
class-auxin-master-nav-menu-admin.php
1 year ago
class-auxin-page-template.php
1 year ago
class-auxin-permalink.php
1 year ago
class-auxin-plugin-requirements.php
3 years ago
class-auxin-post-type-base.php
1 year ago
class-auxin-svg-support-allowedattributes.php
7 years ago
class-auxin-svg-support-allowedtags.php
7 years ago
class-auxin-svg-support.php
1 year ago
class-auxin-walker-nav-menu-back.php
1 year ago
class-auxin-welcome-sections.php
1 year ago
class-auxin-welcome.php
6 months ago
class-auxin-whitelabel.php
3 years ago
class-auxin-widget-indie.php
1 year ago
class-auxin-widget-shortcode-map.php
11 months ago
class-auxin-widget.php
1 year ago
class-auxels-import-parser.php
313 lines
| 1 | <?php |
| 2 | /** |
| 3 | * WordPress eXtended RSS file parser implementations |
| 4 | * |
| 5 | * @package WordPress |
| 6 | * @subpackage Importer |
| 7 | */ |
| 8 | |
| 9 | /** |
| 10 | * WordPress Importer class for managing parsing of WXR files. |
| 11 | */ |
| 12 | class Auxels_Import_Parser { |
| 13 | public function parse( $file ) { |
| 14 | // Attempt to use proper XML parsers first |
| 15 | if ( extension_loaded( 'simplexml' ) ) { |
| 16 | $parser = new AUXELS_WXR_Parser_SimpleXML; |
| 17 | $result = $parser->parse( $file ); |
| 18 | |
| 19 | // If SimpleXML succeeds or this is an invalid WXR file then return the results |
| 20 | if ( ! is_wp_error( $result ) || 'SimpleXML_parse_error' != $result->get_error_code() ) |
| 21 | return $result; |
| 22 | } elseif ( extension_loaded( 'xml' ) ) { |
| 23 | $parser = new AUXELS_WXR_Parser_XML; |
| 24 | $result = $parser->parse( $file ); |
| 25 | |
| 26 | // If XMLParser succeeds or this is an invalid WXR file then return the results |
| 27 | if ( ! is_wp_error( $result ) || 'XML_parse_error' != $result->get_error_code() ) |
| 28 | return $result; |
| 29 | } |
| 30 | |
| 31 | // We have a malformed XML file, so display the error and fallthrough to regex |
| 32 | if ( isset($result) && defined('IMPORT_DEBUG') && IMPORT_DEBUG ) { |
| 33 | echo '<pre>'; |
| 34 | if ( 'SimpleXML_parse_error' == $result->get_error_code() ) { |
| 35 | foreach ( $result->get_error_data() as $error ) |
| 36 | echo esc_html( $error->line ) . ':' . esc_html( $error->column ) . ' ' . esc_html( $error->message ) . "\n"; |
| 37 | } elseif ( 'XML_parse_error' == $result->get_error_code() ) { |
| 38 | $error = $result->get_error_data(); |
| 39 | echo esc_html( $error[0] ) . ':' . esc_html( $error[1] ) . ' ' . esc_html( $error[2] ); |
| 40 | } |
| 41 | echo '</pre>'; |
| 42 | echo '<p><strong>' . esc_html__( 'There was an error when reading this WXR file', 'auxin-elements' ) . '</strong><br />'; |
| 43 | echo esc_html__( 'Details are shown above. The importer will now try again with a different parser...', 'auxin-elements' ) . '</p>'; |
| 44 | } |
| 45 | |
| 46 | // use regular expressions if nothing else available or this is bad XML |
| 47 | $parser = new AUXELS_WXR_Parser_Regex; |
| 48 | return $parser->parse( $file ); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | /** |
| 53 | * WXR Parser that makes use of the SimpleXML PHP extension. |
| 54 | */ |
| 55 | class AUXELS_WXR_Parser_SimpleXML { |
| 56 | |
| 57 | public function parse( $file ) { |
| 58 | |
| 59 | $options = $option = array(); |
| 60 | |
| 61 | $internal_errors = libxml_use_internal_errors(true); |
| 62 | |
| 63 | $dom = new DOMDocument; |
| 64 | $old_value = null; |
| 65 | if ( function_exists( 'libxml_disable_entity_loader' ) ) { |
| 66 | $old_value = libxml_disable_entity_loader( true ); |
| 67 | } |
| 68 | $success = $dom->loadXML( file_get_contents( $file ) ); |
| 69 | if ( ! is_null( $old_value ) ) { |
| 70 | libxml_disable_entity_loader( $old_value ); |
| 71 | } |
| 72 | |
| 73 | if ( ! $success || isset( $dom->doctype ) ) { |
| 74 | return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'auxin-elements' ), libxml_get_errors() ); |
| 75 | } |
| 76 | |
| 77 | $xml = simplexml_import_dom( $dom ); |
| 78 | unset( $dom ); |
| 79 | |
| 80 | // halt if loading produces an error |
| 81 | if ( ! $xml ) |
| 82 | return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'auxin-elements' ), libxml_get_errors() ); |
| 83 | |
| 84 | $wxr_version = $xml->xpath('/rss/channel/wp:wxr_version'); |
| 85 | if ( ! $wxr_version ) |
| 86 | return new WP_Error( 'AUXELS_WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'auxin-elements' ) ); |
| 87 | |
| 88 | $wxr_version = (string) trim( $wxr_version[0] ); |
| 89 | // confirm that we are dealing with the correct file format |
| 90 | if ( ! preg_match( '/^\d+\.\d+$/', $wxr_version ) ) |
| 91 | return new WP_Error( 'AUXELS_WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'auxin-elements' ) ); |
| 92 | |
| 93 | $base_url = $xml->xpath('/rss/channel/wp:base_site_url'); |
| 94 | $base_url = (string) trim( $base_url[0] ); |
| 95 | |
| 96 | $namespaces = $xml->getDocNamespaces(); |
| 97 | if ( ! isset( $namespaces['wp'] ) ) |
| 98 | $namespaces['wp'] = 'http://wordpress.org/export/1.1/'; |
| 99 | if ( ! isset( $namespaces['excerpt'] ) ) |
| 100 | $namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/'; |
| 101 | |
| 102 | $wp = $xml->channel->children( $namespaces['wp'] ); |
| 103 | // grab cats, tags and terms |
| 104 | |
| 105 | foreach ( $wp->option as $option ) { |
| 106 | $options[ $option->option_key[0]->__toString() ] = $option->option_value[0]->__toString(); |
| 107 | } |
| 108 | |
| 109 | return $options; |
| 110 | } |
| 111 | |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * WXR Parser that makes use of the XML Parser PHP extension. |
| 116 | */ |
| 117 | class AUXELS_WXR_Parser_XML { |
| 118 | |
| 119 | var $wp_tags = array( |
| 120 | 'wp:option' |
| 121 | ); |
| 122 | var $wp_sub_tags = array( |
| 123 | 'wp:option_name', 'wp:option_value' |
| 124 | ); |
| 125 | |
| 126 | public function parse( $file ) { |
| 127 | |
| 128 | $this->wxr_version = $this->in_post = $this->cdata = $this->data = $this->sub_data = $this->in_tag = $this->in_sub_tag = false; |
| 129 | $this->authors = $this->posts = $this->term = $this->category = $this->tag = array(); |
| 130 | |
| 131 | $xml = xml_parser_create( 'UTF-8' ); |
| 132 | xml_parser_set_option( $xml, XML_OPTION_SKIP_WHITE, 1 ); |
| 133 | xml_parser_set_option( $xml, XML_OPTION_CASE_FOLDING, 0 ); |
| 134 | xml_set_object( $xml, $this ); |
| 135 | xml_set_character_data_handler( $xml, 'cdata' ); |
| 136 | xml_set_element_handler( $xml, 'tag_open', 'tag_close' ); |
| 137 | |
| 138 | if ( ! xml_parse( $xml, file_get_contents( $file ), true ) ) { |
| 139 | $current_line = xml_get_current_line_number( $xml ); |
| 140 | $current_column = xml_get_current_column_number( $xml ); |
| 141 | $error_code = xml_get_error_code( $xml ); |
| 142 | $error_string = xml_error_string( $error_code ); |
| 143 | return new WP_Error( 'XML_parse_error', 'There was an error when reading this WXR file', array( $current_line, $current_column, $error_string ) ); |
| 144 | } |
| 145 | xml_parser_free( $xml ); |
| 146 | |
| 147 | if ( ! preg_match( '/^\d+\.\d+$/', $this->wxr_version ) ) |
| 148 | return new WP_Error( 'AUXELS_WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'auxin-elements' ) ); |
| 149 | |
| 150 | return array( |
| 151 | 'authors' => $this->authors, |
| 152 | 'posts' => $this->posts, |
| 153 | 'categories' => $this->category, |
| 154 | 'tags' => $this->tag, |
| 155 | 'terms' => $this->term, |
| 156 | 'base_url' => $this->base_url, |
| 157 | 'version' => $this->wxr_version |
| 158 | ); |
| 159 | } |
| 160 | |
| 161 | public function tag_open( $parse, $tag, $attr ) { |
| 162 | if ( in_array( $tag, $this->wp_tags ) ) { |
| 163 | $this->in_tag = substr( $tag, 3 ); |
| 164 | return; |
| 165 | } |
| 166 | |
| 167 | if ( in_array( $tag, $this->wp_sub_tags ) ) { |
| 168 | $this->in_sub_tag = substr( $tag, 3 ); |
| 169 | return; |
| 170 | } |
| 171 | |
| 172 | switch ( $tag ) { |
| 173 | case 'category': |
| 174 | if ( isset($attr['domain'], $attr['nicename']) ) { |
| 175 | $this->sub_data['domain'] = $attr['domain']; |
| 176 | $this->sub_data['slug'] = $attr['nicename']; |
| 177 | } |
| 178 | break; |
| 179 | case 'item': $this->in_post = true; |
| 180 | case 'title': if ( $this->in_post ) $this->in_tag = 'post_title'; break; |
| 181 | case 'guid': $this->in_tag = 'guid'; break; |
| 182 | case 'dc:creator': $this->in_tag = 'post_author'; break; |
| 183 | case 'content:encoded': $this->in_tag = 'post_content'; break; |
| 184 | case 'excerpt:encoded': $this->in_tag = 'post_excerpt'; break; |
| 185 | |
| 186 | case 'wp:term_slug': $this->in_tag = 'slug'; break; |
| 187 | case 'wp:meta_key': $this->in_sub_tag = 'key'; break; |
| 188 | case 'wp:meta_value': $this->in_sub_tag = 'value'; break; |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | public function cdata( $parser, $cdata ) { |
| 193 | if ( ! trim( $cdata ) ) |
| 194 | return; |
| 195 | |
| 196 | if ( false !== $this->in_tag || false !== $this->in_sub_tag ) { |
| 197 | $this->cdata .= $cdata; |
| 198 | } else { |
| 199 | $this->cdata .= trim( $cdata ); |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | public function tag_close( $parser, $tag ) { |
| 204 | switch ( $tag ) { |
| 205 | case 'wp:option': |
| 206 | $n = substr( $tag, 3 ); |
| 207 | array_push( $this->$n, $this->data ); |
| 208 | $this->data = false; |
| 209 | break; |
| 210 | } |
| 211 | |
| 212 | $this->cdata = false; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | /** |
| 217 | * WXR Parser that uses regular expressions. Fallback for installs without an XML parser. |
| 218 | */ |
| 219 | class AUXELS_WXR_Parser_Regex { |
| 220 | |
| 221 | var $options = array(); |
| 222 | |
| 223 | public function __construct() { |
| 224 | $this->has_gzip = is_callable( 'gzopen' ); |
| 225 | } |
| 226 | |
| 227 | public function parse( $file ) { |
| 228 | $wxr_version = $in_post = false; |
| 229 | |
| 230 | $fp = $this->fopen( $file, 'r' ); |
| 231 | if ( $fp ) { |
| 232 | while ( ! $this->feof( $fp ) ) { |
| 233 | $importline = rtrim( $this->fgets( $fp ) ); |
| 234 | |
| 235 | if ( false !== strpos( $importline, '<wp:option>' ) ) { |
| 236 | preg_match( '|<wp:option>(.*?)</wp:option>|is', $importline, $option ); |
| 237 | $this->options[] = $this->process_option( $option[1] ); |
| 238 | continue; |
| 239 | } |
| 240 | if ( $in_post ) { |
| 241 | $post .= $importline . "\n"; |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | $this->fclose($fp); |
| 246 | } |
| 247 | |
| 248 | if ( ! $wxr_version ) |
| 249 | return new WP_Error( 'AUXELS_WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'auxin-elements' ) ); |
| 250 | |
| 251 | return array( |
| 252 | 'options' => $this->options |
| 253 | ); |
| 254 | } |
| 255 | |
| 256 | public function get_tag( $string, $tag ) { |
| 257 | preg_match( "|<$tag.*?>(.*?)</$tag>|is", $string, $return ); |
| 258 | if ( isset( $return[1] ) ) { |
| 259 | if ( substr( $return[1], 0, 9 ) == '<![CDATA[' ) { |
| 260 | if ( strpos( $return[1], ']]]]><![CDATA[>' ) !== false ) { |
| 261 | preg_match_all( '|<!\[CDATA\[(.*?)\]\]>|s', $return[1], $matches ); |
| 262 | $return = ''; |
| 263 | foreach( $matches[1] as $match ) |
| 264 | $return .= $match; |
| 265 | } else { |
| 266 | $return = preg_replace( '|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1] ); |
| 267 | } |
| 268 | } else { |
| 269 | $return = $return[1]; |
| 270 | } |
| 271 | } else { |
| 272 | $return = ''; |
| 273 | } |
| 274 | return $return; |
| 275 | } |
| 276 | |
| 277 | public function process_option( $t ) { |
| 278 | return array( |
| 279 | 'option_name' => $this->get_tag( $t, 'wp:option_name' ), |
| 280 | 'option_value' => $this->get_tag( $t, 'wp:option_value' ) |
| 281 | ); |
| 282 | } |
| 283 | |
| 284 | public function _normalize_tag( $matches ) { |
| 285 | return '<' . strtolower( $matches[1] ); |
| 286 | } |
| 287 | |
| 288 | public function fopen( $filename, $mode = 'r' ) { |
| 289 | if ( $this->has_gzip ) |
| 290 | return gzopen( $filename, $mode ); |
| 291 | return fopen( $filename, $mode ); |
| 292 | } |
| 293 | |
| 294 | public function feof( $fp ) { |
| 295 | if ( $this->has_gzip ) |
| 296 | return gzeof( $fp ); |
| 297 | return feof( $fp ); |
| 298 | } |
| 299 | |
| 300 | public function fgets( $fp, $len = 8192 ) { |
| 301 | if ( $this->has_gzip ) |
| 302 | return gzgets( $fp, $len ); |
| 303 | return fgets( $fp, $len ); |
| 304 | } |
| 305 | |
| 306 | public function fclose( $fp ) { |
| 307 | if ( $this->has_gzip ) |
| 308 | return gzclose( $fp ); |
| 309 | return fclose( $fp ); |
| 310 | } |
| 311 | |
| 312 | } |
| 313 |