Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/tools/model/_wp.funcs.php
<?php
/**
 * This file implements the functions to work with WordPress importer.
 *
 * b2evolution - {@link http://b2evolution.net/}
 * Released under GNU GPL License - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
 *
 * @package admin
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );


/**
 * Get data to start import from wordpress XML/ZIP file or from Item Type XML file
 *
 * @param string Path of XML/ZIP file
 * @param boolean TRUE to allow to use already extracted ZIP archive
 * @return array Data array:
 *                 'error' - FALSE on success OR error message,
 *                 'XML_file_path' - Path to XML file,
 *                 'attached_files_path' - Path to attachments folder,
 *                 'ZIP_folder_path' - Path of the extracted ZIP files.
 */
function wpxml_get_import_data( & $XML_file_path, $allow_use_extracted_folder = false )
{
   
$error_type = NULL;

   
// Start to collect all printed errors from buffer:
   
ob_start();

   
$XML_file_name = basename( $XML_file_path );
   
$ZIP_folder_path = NULL;
   
$zip_file_name = NULL;

   
// Do NOT use first found folder for attachments:
   
$use_first_folder_for_attachments = false;

    if(
preg_match( '/\.(xml|txt)$/i', $XML_file_name ) )
    {    
// XML format
        // Check WordPress XML file:
       
wpxml_check_xml_file( $XML_file_path );
    }
    else if(
preg_match( '/\.zip$/i', $XML_file_name ) )
    {    
// ZIP format
        // Extract ZIP and check WordPress XML file
       
global $media_path;

       
$zip_file_name = $XML_file_name;

       
$ZIP_folder_name = substr( $XML_file_name, 0, -4 );
       
$ZIP_folder_path = $media_path.'import/'.$ZIP_folder_name;

       
$zip_folder_exists = ( file_exists( $ZIP_folder_path ) && is_dir( $ZIP_folder_path ) );

        if( !
$allow_use_extracted_folder && $zip_folder_exists )
        {    
// Don't try to extract into already existing folder:
           
$error_type = 'folder_exists';
            echo
'<p class="text-danger">'.sprintf( 'The destination folder %s already exists. If you want to unzip %s again, delete %s first.',
                   
'<code>'.$ZIP_folder_path.'/</code>',
                   
'<code>'.$XML_file_name.'</code>',
                   
'<code>'.$ZIP_folder_path.'/</code>'
               
).'</p>';
        }
        elseif( (
$allow_use_extracted_folder && $zip_folder_exists ) ||
               
unpack_archive( $XML_file_path, $ZIP_folder_path, true, $XML_file_name ) )
        {    
// If we can use already extracted ZIP archive or it is unpacked successfully now:

            // Move all files and sub-folders of single top level folder to top/root level of the folder:
           
move_single_dir_to_top_level( $ZIP_folder_path );

           
// Reset path and set only if XML file is found in ZIP archive:
           
$XML_file_path = false;

           
// Find valid XML file in ZIP package:
           
$ZIP_files_list = scandir( $ZIP_folder_path );
           
$xml_exists_in_zip = false;
            for(
$i = 1; $i <= 2; $i++ )
            {    
// Run searcher 1st time to find XML file in a root of ZIP archive
                // and 2nd time to find XML file in 1 level subfolders of the root:
               
foreach( $ZIP_files_list as $ZIP_file )
                {
                    if(
$ZIP_file == '.' || $ZIP_file == '..' )
                    {    
// Skip reserved dir names of the current path:
                       
continue;
                    }
                    if(
$i == 2 )
                    {    
// This is 2nd time to find XML file in 1 level subfolders of the root:
                       
if( is_dir( $ZIP_folder_path.'/'.$ZIP_file ) )
                        {    
// This is a subfolder, Scan it to find XML files inside:
                           
$ZIP_folder_current_path = $ZIP_folder_path.'/'.$ZIP_file;
                           
$ZIP_folder_files = scandir( $ZIP_folder_current_path );
                        }
                        else
                        {    
// Skip files:
                           
continue;
                        }
                    }
                    else
                    {    
// This is a single file or folder:
                       
$ZIP_folder_files = array( $ZIP_file );
                       
$ZIP_folder_current_path = $ZIP_folder_path;
                    }
                    foreach(
$ZIP_folder_files as $ZIP_file )
                    {
                        if(
preg_match( '/\.(xml|txt)$/i', $ZIP_file ) )
                        {    
// XML file is found in ZIP package:
                           
$XML_file_path = $ZIP_folder_current_path.'/'.$ZIP_file;
                            if(
wpxml_check_xml_file( $XML_file_path ) )
                            {    
// XML file is valid:
                               
$xml_exists_in_zip = true;
                                break
3;
                            }
                        }
                    }
                }
            }
        }

       
// Use first found folder for attachments when no reserved folders not found in ZIP before:
       
$use_first_folder_for_attachments = true;
    }
    else
    {    
// Unrecognized extension:
       
$error_type = 'wrong_extension';
        echo
'<p class="text-danger">'.sprintf( '%s has an unrecognized extension.', '<code>'.$xml_file['name'].'</code>' ).'</p>';
    }

    if(
$XML_file_path )
    {    
// Get a path with attached files for the XML file:
       
$attached_files_path = get_import_attachments_folder( $XML_file_path, $use_first_folder_for_attachments );
       
$attached_files_folder = substr( $attached_files_path, strlen( dirname( $XML_file_path ) ) );
    }
    else
    {    
// Wrong source file:
       
$attached_files_path = false;
       
$attached_files_folder = false;
    }

    if( isset(
$xml_exists_in_zip ) && $xml_exists_in_zip === false && file_exists( $ZIP_folder_path ) )
    {    
// No XML is detected in ZIP package:
       
$error_type = 'no_xml';
        echo
'<p class="text-danger">'.'Correct XML file is not detected in your ZIP package.'.'</p>';
       
// Delete temporary folder that contains the files from extracted ZIP package:
       
rmdir_r( $ZIP_folder_path );
    }

   
// Get all printed errors:
   
$errors = ob_get_clean();

    global
$wpxml_file_path_renamed, $wpxml_file_path_orig;
    if( isset(
$wpxml_file_path_renamed ) )
    {    
// Display these messages only after $errors = ob_get_clean(); because they are not errors of XML parsing:
       
if( $wpxml_file_path_renamed === true )
        {    
// Success renaming:
           
echo '<p class="text-warning"><span class="label label-warning">WARNING</span> '.sprintf( 'We renamed %s to %s. The PHP XML parser doesn\'t support spaces in filenames.',
               
'<code>'.$wpxml_file_path_orig.'</code>',
               
'<code>'.$XML_file_path.'</code>' ).'</p>';
        }
    }

    return array(
           
'errors'               => empty( $errors ) ? false : $errors,
           
'error_type'           => $error_type,
           
'XML_file_path'        => $XML_file_path,
           
'attached_files_path'  => $attached_files_path,
           
'attached_files_folder'=> $attached_files_folder,
           
'ZIP_folder_path'      => $ZIP_folder_path,
        );
}


/**
 * Get XML content from file
 *
 * @param string File path
 * @return object|FALSE SimpleXMLElement
 */
function wpxml_get_xml_from_file( & $file_path )
{
    global
$wpxml_file_path_renamed, $wpxml_file_path_orig;

   
// Register filter to avoid wrong chars in XML content:
   
stream_filter_register( 'xmlutf8', 'ValidUTF8XMLFilter' );

    if(
strpos( $file_path, ' ' ) !== false )
    {    
// Try to rename file:
       
$wpxml_file_path_orig = $file_path;
       
$new_file_path = str_replace( ' ', '-', $file_path );

        if( !
file_exists( $new_file_path ) )
        {    
// If file was not renamed yet:
           
if( $wpxml_file_path_renamed = @rename( $file_path, $new_file_path ) )
            {
               
$file_path = $new_file_path;
            }
            else
            {    
// Failed renaming:
               
echo '<p class="text-warning"><span class="label label-danger">ERROR</span> '.sprintf( 'Cannot rename %s to %s. The PHP XML parser doesn’t support spaces in filenames.',
                   
'<code>'.$file_path.'</code>',
                   
'<code>'.$new_file_path.'</code>' ).'</p>';
            }
        }
        else
        {
           
$file_path = $new_file_path;
        }
    }

    if( ! isset(
$wpxml_file_path_renamed ) || $wpxml_file_path_renamed === true )
    {    
// Load XML content from file with xmlutf8 filter:
       
$xml = simplexml_load_file( 'php://filter/read=xmlutf8/resource='.$file_path );
    }
    else
    {
       
$xml = false;
    }

    return
$xml;
}


/**
 * Parse WordPress XML file into array
 *
 * @param string File path
 * @return array XML data:
 *          authors
 *          posts
 *          categories
 *          tags
 *          terms
 *          base_url
 *          wxr_version
 */
function wpxml_parser( $file )
{
   
$authors = array();
   
$posts = array();
   
$categories = array();
   
$tags = array();
   
$terms = array();
   
$files = array();
   
$memory = array();

   
// Start to get amount of memory for parsing:
   
$memory_usage = memory_get_usage();

   
// Load XML content from file with xmlutf8 filter:
   
$xml = wpxml_get_xml_from_file( $file );

   
// Store here what memory was used for XML parsing:
   
$memory['parsing'] = memory_get_usage() - $memory_usage;

   
// Get WXR version
   
$wxr_version = $xml->xpath( '/rss/channel/wp:wxr_version' );
   
$wxr_version = isset( $wxr_version[0] ) ? (string) trim( $wxr_version[0] ) : '';

   
$base_url = $xml->xpath( '/rss/channel/wp:base_site_url' );
   
$base_url = isset( $base_url[0] ) ? (string) trim( $base_url[0] ) : '';

   
// Check language
   
global $evo_charset, $xml_import_convert_to_latin;
   
$language = $xml->xpath( '/rss/channel/language' );
   
$language = isset( $language[0] ) ? (string) trim( $language[0] ) : '';
    if(
$evo_charset != 'utf-8' && ( strpos( $language, 'utf8' ) !== false ) )
    {
// We should convert the text values from utf8 to latin1
       
$xml_import_convert_to_latin = true;
    }
    else
    {
// Don't convert, it is correct encoding
       
$xml_import_convert_to_latin = false;
    }

   
$namespaces = $xml->getDocNamespaces();
    if( !isset(
$namespaces['wp'] ) )
    {
       
$namespaces['wp'] = 'http://wordpress.org/export/1.1/';
    }
    if( !isset(
$namespaces['evo'] ) )
    {
       
$namespaces['evo'] = 'http://b2evolution.net/export/2.0/';
    }
    if( !isset(
$namespaces['excerpt'] ) )
    {
       
$namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/';
    }

   
// Start to get amount of memory for temporary arrays:
   
$memory_usage = memory_get_usage();

   
// Get authors:
   
$authors_data = $xml->xpath( '/rss/channel/wp:author' );
    if(
is_array( $authors_data ) )
    {
        foreach(
$authors_data as $author_arr )
        {
           
$a = $author_arr->children( $namespaces['wp'] );
           
$ae = $author_arr->children( $namespaces['evo'] );
           
$login = (string) $a->author_login;
           
$author = array(
               
'author_id'                   => (int) $a->author_id,
               
'author_login'                => $login,
               
'author_email'                => (string) $a->author_email,
               
'author_display_name'         => wpxml_convert_value( $a->author_display_name ),
               
'author_first_name'           => wpxml_convert_value( $a->author_first_name ),
               
'author_last_name'            => wpxml_convert_value( $a->author_last_name ),
               
'author_pass'                 => (string) $ae->author_pass,
               
'author_salt'                 => isset( $ae->author_salt ) ? (string) $ae->author_salt : '',
               
'author_pass_driver'          => isset( $ae->author_pass_driver ) ? (string) $ae->author_pass_driver : 'evo$md5',
               
'author_group'                => (string) $ae->author_group,
               
'author_status'               => (string) $ae->author_status,
               
'author_nickname'             => wpxml_convert_value( $ae->author_nickname ),
               
'author_url'                  => (string) $ae->author_url,
               
'author_level'                => (int) $ae->author_level,
               
'author_locale'               => (string) $ae->author_locale,
               
'author_gender'               => (string) $ae->author_gender,
               
'author_age_min'              => (int) $ae->author_age_min,
               
'author_age_max'              => (int) $ae->author_age_max,
               
'author_created_from_country' => (string) $ae->author_created_from_country,
               
'author_country'              => (string) $ae->author_country,
               
'author_region'               => (string) $ae->author_region,
               
'author_subregion'            => (string) $ae->author_subregion,
               
'author_city'                 => (string) $ae->author_city,
               
'author_source'               => (string) $ae->author_source,
               
'author_created_ts'           => (string) $ae->author_created_ts,
               
'author_lastseen_ts'          => (string) $ae->author_lastseen_ts,
               
'author_created_fromIPv4'     => (string) $ae->author_created_fromIPv4,
               
'author_profileupdate_date'   => (string) $ae->author_profileupdate_date,
               
'author_avatar_file_ID'       => (int) $ae->author_avatar_file_ID,
            );

            foreach(
$ae->link as $link )
            {    
// Get the links:
               
$author['links'][] = array(
                   
'link_ID'               => (int) $link->link_ID,
                   
'link_datecreated'      => (string) $link->link_datecreated,
                   
'link_datemodified'     => (string) $link->link_datemodified,
                   
'link_creator_user_ID'  => (int) $link->link_creator_user_ID,
                   
'link_lastedit_user_ID' => (int) $link->link_lastedit_user_ID,
                   
'link_itm_ID'           => (int) $link->link_itm_ID,
                   
'link_cmt_ID'           => (int) $link->link_cmt_ID,
                   
'link_usr_ID'           => (int) $link->link_usr_ID,
                   
'link_file_ID'          => (int) $link->link_file_ID,
                   
'link_position'         => (string) $link->link_position,
                   
'link_order'            => (int) $link->link_order,
                );
            }

           
$authors[ $login ] = $author;
        }
    }

   
// Get files:
   
$files_data = $xml->xpath( $namespaces['evo'] == 'http://b2evolution.net/export/2.0/'
       
? '/rss/channel/evo:file' // ver 2.0
       
: '/rss/channel/file' ); // ver 1.0
   
if( is_array( $files_data ) )
    {
        foreach(
$files_data as $file_arr )
        {
           
$t = $file_arr->children( $namespaces['evo'] );
           
$files[] = array(
               
'file_ID'        => (int) $t->file_ID,
               
'file_root_type' => (string) $t->file_root_type,
               
'file_root_ID'   => (int) $t->file_root_ID,
               
'file_path'      => (string) $t->file_path,
               
'file_title'     => wpxml_convert_value( $t->file_title ),
               
'file_alt'       => wpxml_convert_value( $t->file_alt ),
               
'file_desc'      => wpxml_convert_value( $t->file_desc ),
               
'zip_path'       => (string) $t->zip_path,
            );
        }
    }

   
// Get categories:
   
$categories_data = $xml->xpath( '/rss/channel/wp:category' );
    if(
is_array( $categories_data ) )
    {
        foreach(
$categories_data as $term_arr )
        {
           
$t = $term_arr->children( $namespaces['wp'] );
           
$categories[] = array(
               
'term_id'              => (int) $t->term_id,
               
'category_nicename'    => wpxml_convert_value( $t->category_nicename ),
               
'category_parent'      => (string) $t->category_parent,
               
'cat_name'             => wpxml_convert_value( $t->cat_name ),
               
'cat_description'      => wpxml_convert_value( $t->cat_description ),
               
'cat_order'            => wpxml_convert_value( $t->cat_order ),
            );
        }
    }

   
// Get tags:
   
$tags_data = $xml->xpath( '/rss/channel/wp:tag' );
    if(
is_array( $tags_data ) )
    {
        foreach(
$tags_data as $term_arr )
        {
           
$t = $term_arr->children( $namespaces['wp'] );
           
$tags[] = array(
               
'term_id'         => (int) $t->term_id,
               
'tag_slug'        => (string) $t->tag_slug,
               
'tag_name'        => wpxml_convert_value( $t->tag_name ),
               
'tag_description' => wpxml_convert_value( $t->tag_description )
            );
        }
    }

   
// Get terms:
   
$terms_data = $xml->xpath( '/rss/channel/wp:term' );
    if(
is_array( $terms_data ) )
    {
        foreach(
$terms_data as $term_arr )
        {
           
$t = $term_arr->children( $namespaces['wp'] );
           
$terms[] = array(
               
'term_id'          => (int) $t->term_id,
               
'term_taxonomy'    => (string) $t->term_taxonomy,
               
'slug'             => (string) $t->term_slug,
               
'term_parent'      => (string) $t->term_parent,
               
'term_name'        => wpxml_convert_value( $t->term_name ),
               
'term_description' => wpxml_convert_value( $t->term_description )
            );
        }
    }

   
// Get posts
   
foreach( $xml->channel->item as $item )
    {
       
$post = array(
           
'post_title' => wpxml_convert_value( $item->title ),
           
'post_link'  => ( isset( $item->link ) ? wpxml_convert_value( $item->link ) : '' ),
           
'guid'       => (string) $item->guid,
        );

       
$dc = $item->children( 'http://purl.org/dc/elements/1.1/' );
       
$post['post_author'] = (string) $dc->creator;

       
$content = $item->children( 'http://purl.org/rss/1.0/modules/content/' );
       
$excerpt = $item->children( $namespaces['excerpt'] );
       
$post['post_content'] = wpxml_convert_value( $content->encoded );
       
$post['post_excerpt'] = wpxml_convert_value( $excerpt->encoded );

       
$wp = $item->children( $namespaces['wp'] );
       
$evo = $item->children( $namespaces['evo'] );

       
$post['post_id']        = (int) $wp->post_id;
       
$post['post_date']      = (string) $wp->post_date;
       
$post['post_date_gmt']  = (string) $wp->post_date_gmt;
       
$post['comment_status'] = (string) $wp->comment_status;
       
$post['ping_status']    = (string) $wp->ping_status;
       
$post['post_name']      = (string) $wp->post_name;
       
$post['status']         = (string) $wp->status;
       
$post['post_parent']    = (int) $wp->post_parent;
       
$post['menu_order']     = (int) $wp->menu_order;
       
$post['post_type']      = (string) $wp->post_type;
       
$post['post_password']  = (string) $wp->post_password;
       
$post['is_sticky']      = (int) $wp->is_sticky;
       
$post['itemtype']       = (string) $evo->itemtype;
       
$post['post_date_mode']     = (string) $evo->post_date_mode;
       
$post['post_lastedit_user'] = (string) $evo->post_lastedit_user;
       
$post['post_assigned_user'] = (string) $evo->post_assigned_user;
       
$post['post_datedeadline']  = (string) $evo->post_datedeadline;
       
$post['post_datecreated']   = (string) $evo->post_datecreated;
       
$post['post_datemodified']  = (string) $evo->post_datemodified;
       
$post['post_locale']        = (string) $evo->post_locale;
       
$post['post_excerpt_autogenerated'] = (int) $evo->post_excerpt_autogenerated;
       
$post['post_urltitle']      = (string) $evo->post_urltitle;
       
$post['post_titletag']      = (string) $evo->post_titletag;
       
$post['post_url']           = (string) $evo->post_url;
       
$post['post_notifications_status'] = (string) $evo->post_notifications_status;
       
$post['post_renderers']     = ( $evo->post_renderers->getName() == 'post_renderers' ? /*If renderer plugins are provided use them*/(string) $evo->post_renderers : /*Otherwise use default plugins*/'default' );
       
$post['post_priority']      = (int) $evo->post_priority;
       
$post['post_featured']      = (int) $evo->post_featured;
       
$post['post_order']         = (int) $evo->post_order;
       
$post['post_country']       = (string) $evo->post_country;
       
$post['post_region']        = (string) $evo->post_region;
       
$post['post_subregion']     = (string) $evo->post_subregion;
       
$post['post_city']          = (string) $evo->post_city;
       
$post['switchable']         = (int) $evo->switchable;
       
$post['switchable_params']  = (string) $evo->switchable_params;

        if( isset(
$wp->attachment_url ) )
        {
           
$post['attachment_url'] = (string) $wp->attachment_url;
        }

        if( isset(
$evo->post_extra_urltitle ) )
        {    
// Extra slugs:
           
$post['extra_slugs'] = (array)$evo->post_extra_urltitle;
        }

        foreach(
$item->category as $c )
        {
           
$att = $c->attributes();
            if( isset(
$att['nicename'] ) )
            {
               
$post['terms'][] = array(
                   
'name'   => (string) $c,
                   
'slug'   => wpxml_convert_value( $att['nicename'] ),
                   
'domain' => (string) $att['domain']
                );
            }
        }

        if( isset(
$evo->custom_field ) )
        {    
// Parse values of custom fields of the Item:
           
foreach( $evo->custom_field as $custom_field )
            {
               
$custom_field_attrs = $custom_field->attributes();
               
$post['custom_fields'][ wpxml_convert_value( $custom_field_attrs->name ) ] = array(
                       
'type'  => wpxml_convert_value( $custom_field_attrs->type ),
                       
'value' => wpxml_convert_value( $custom_field ),
                    );
            }
        }

        foreach(
$wp->postmeta as $meta )
        {
           
$post['postmeta'][] = array(
               
'key'   => (string) $meta->meta_key,
               
'value' => isset( $meta->meta_value) ? wpxml_convert_value( $meta->meta_value ) : NULL,
            );
        }

        foreach(
$wp->comment as $comment )
        {
           
$evo_comment = $comment->children( $namespaces['evo'] );

           
$meta = array();
            if( isset(
$comment->commentmeta ) )
            {
                foreach(
$comment->commentmeta as $m )
                {
                   
$meta[] = array(
                       
'key'   => (string) $m->meta_key,
                       
'value' => wpxml_convert_value( $m->meta_value )
                    );
                }
            }

           
$post['comments'][] = array(
               
'comment_id'           => (int) $comment->comment_id,
               
'comment_author'       => wpxml_convert_value( $comment->comment_author ),
               
'comment_author_email' => (string) $comment->comment_author_email,
               
'comment_author_IP'    => (string) $comment->comment_author_IP,
               
'comment_author_url'   => (string) $comment->comment_author_url,
               
'comment_date'         => (string) $comment->comment_date,
               
'comment_date_gmt'     => (string) $comment->comment_date_gmt,
               
'comment_content'      => wpxml_convert_value( $comment->comment_content ),
               
'comment_approved'     => (string) $comment->comment_approved,
               
'comment_type'         => (string) $comment->comment_type,
               
'comment_parent'       => (string) $comment->comment_parent,
               
'comment_user_id'      => (int) $comment->comment_user_id,
               
'comment_user_login'   => (string) $evo_comment->comment_user_login,
               
'comment_status'             => (string) $evo_comment->comment_status,
               
'comment_IP_country'         => (string) $evo_comment->comment_IP_country,
               
'comment_rating'             => (int) $evo_comment->comment_rating,
               
'comment_featured'           => (int) $evo_comment->comment_featured,
               
'comment_author_url_nofollow'  => isset( $evo_comment->comment_author_url_nofollow ) ? (int) $evo_comment->comment_author_url_nofollow : (int) $evo_comment->comment_nofollow,
               
'comment_author_url_ugc'       => isset( $evo_comment->comment_author_url_ugc ) ? (int) $evo_comment->comment_author_url_ugc : 1,
               
'comment_author_url_sponsored' => isset( $evo_comment->comment_author_url_sponsored ) ? (int) $evo_comment->comment_author_url_sponsored : 0,
               
'comment_helpful_addvotes'   => (int) $evo_comment->comment_helpful_addvotes,
               
'comment_helpful_countvotes' => (int) $evo_comment->comment_helpful_countvotes,
               
'comment_spam_addvotes'      => (int) $evo_comment->comment_spam_addvotes,
               
'comment_spam_countvotes'    => (int) $evo_comment->comment_spam_countvotes,
               
'comment_karma'              => (int) $evo_comment->comment_comment_karma,
               
'comment_spam_karma'         => (int) $evo_comment->comment_spam_karma,
               
'comment_allow_msgform'      => (int) $evo_comment->comment_allow_msgform,
               
'comment_notif_status'       => (string) $evo_comment->comment_notif_status,
               
'commentmeta'                => $meta,
            );
        }

        foreach(
$evo->link as $link )
        {
// Get the links
           
$post['links'][] = array(
               
'link_ID'               => (int) $link->link_ID,
               
'link_datecreated'      => (string) $link->link_datecreated,
               
'link_datemodified'     => (string) $link->link_datemodified,
               
'link_creator_user_ID'  => (int) $link->link_creator_user_ID,
               
'link_lastedit_user_ID' => (int) $link->link_lastedit_user_ID,
               
'link_itm_ID'           => (int) $link->link_itm_ID,
               
'link_cmt_ID'           => (int) $link->link_cmt_ID,
               
'link_usr_ID'           => (int) $link->link_usr_ID,
               
'link_file_ID'          => (int) $link->link_file_ID,
               
'link_position'         => (string) $link->link_position,
               
'link_order'            => (int) $link->link_order,
            );
        }

       
$posts[] = $post;
    }

   
// Store here what memory was used for temporary arrays:
   
$memory['arrays'] = memory_get_usage() - $memory_usage;

    return array(
       
'authors'    => $authors,
       
'files'      => $files,
       
'posts'      => $posts,
       
'categories' => $categories,
       
'tags'       => $tags,
       
'terms'      => $terms,
       
'base_url'   => $base_url,
       
'version'    => $wxr_version,
       
'memory'     => $memory,
    );
}


/**
 * Check WordPress XML file for correct format
 *
 * @param string File path
 * @param boolean TRUE to halt process of error, FALSE to print out error
 * @return boolean TRUE on success, FALSE or HALT on errors
 */
function wpxml_check_xml_file( & $file, $halt = false )
{
    global
$wpxml_file_path_renamed;

   
// Enable XML error handling:
   
$internal_errors = libxml_use_internal_errors( true );

   
// Clear error of previous XML file (e.g. when ZIP archive has several XML files):
   
libxml_clear_errors();

   
// Load XML content from file with xmlutf8 filter:
   
$xml = wpxml_get_xml_from_file( $file );

    if( isset(
$wpxml_file_path_renamed ) && $wpxml_file_path_renamed === false )
    {    
// Don't display errors messages here, because they arready were displayed inside wpxml_get_xml_from_file():
       
return false;
    }

    if( !
$xml )
    {    
// Halt/Display if loading produces an error:
       
$errors = array();
        if(
$halt )
        {    
// Halt on error:
           
foreach( libxml_get_errors() as $error )
            {
               
$errors[] = 'Line '.$error->line.' - "'.format_to_output( $error->message, 'htmlspecialchars' ).'"';
            }
           
debug_die( 'There was an error when reading XML file "'.$file.'".'
               
.' Error: '.implode( ', ', $errors ) );
        }
        else
        {    
// Display error:
           
foreach( libxml_get_errors() as $error )
            {
               
$errors[] = sprintf( 'Line %s', '<code>'.$error->line.'</code>' ).' - '.'"'.format_to_output( $error->message, 'htmlspecialchars' ).'"';
            }
            echo
'<p class="text-danger">'.sprintf( 'There was an error when reading XML file %s.', '<code>'.$file.'</code>' ).'<br />'
               
.sprintf( 'Error: %s', implode( ',<br />', $errors ) ).'</p>';
            return
false;
        }
    }

   
$r = false;
    if(
$wxr_version = $xml->xpath( '/rss/channel/wp:wxr_version' ) )
    {    
// Check WXR version for correct format:
       
$wxr_version = (string) trim( $wxr_version[0] );
       
$r = preg_match( '/^\d+\.\d+$/', $wxr_version );
    }
    elseif(
$app_version = $xml->xpath( '/rss/channel/evo:app_version' ) )
    {    
// Check application version for correct format:
       
$app_version = (string) trim( $app_version[0] );
       
$r = preg_match( '/^[\d\.]+(-[a-z]+)?$/i', $app_version );
    }
   

    if( !
$r )
    {    
// If file format is wrong:
       
if( $halt )
        {    
// Halt on error:
           
debug_die( 'This does not appear to be a XML file, missing/invalid WXR version number.' );
        }
        else
        {    
// Display error:
           
echo '<p class="text-danger">'.'This does not appear to be a XML file, missing/invalid WXR version number.'.'</p>';
            return
false;
        }
    }

    return
true;
}


/**
 * Get the unique url name
 *
 * @param string Source text
 * @param string Table name
 * @param string Field name
 * @return string category's url name
 */
function wp_unique_urlname( $source, $table, $field )
{
    global
$DB;

   
// Replace special chars/umlauts, if we can convert charsets:
   
load_funcs( 'locales/_charset.funcs.php' );
   
$url_name = strtolower( replace_special_chars( $source ) );

   
$url_number = 1;
   
$url_name_correct = $url_name;
    do
    {    
// Check for unique url name in DB
       
$SQL = new SQL( 'WordPress import: Check for unique url name in DB' );
       
$SQL->SELECT( $field );
       
$SQL->FROM( $table );
       
$SQL->WHERE( $field.' = '.$DB->quote( $url_name_correct ) );
       
$category = $DB->get_var( $SQL );
        if(
$category )
        {    
// Category already exists with such url name; Change it
           
$url_name_correct = $url_name.'-'.$url_number;
           
$url_number++;
        }
    }
    while( !empty(
$category ) );

    return
$url_name_correct;
}


/**
 * Get regional data (Used to get regional IDs for user & item by regional names)
 *
 * @param string Country code
 * @param string Region name
 * @param string Subregion name
 * @param string City name
 * @return array Regional data
 */
function wp_get_regional_data( $country_code, $region, $subregion, $city )
{
   
$data = array(
           
'country' => 0,
           
'region' => 0,
           
'subregion' => 0,
           
'city' => 0,
        );

    if( !empty(
$country_code ) )
    {    
// Get country ID from DB by code
       
$CountryCache = & get_CountryCache();
        if(
$Country = & $CountryCache->get_by_name( $country_code, false ) )
        {
           
$data['country'] = $Country->ID;

            if( !empty(
$region ) )
            {    
// Get region ID from DB by name
               
$RegionCache = & get_RegionCache();
                if(
$Region = & $RegionCache->get_by_name( $region, false ) )
                {
                    if(
$Region->ctry_ID == $data['country'] )
                    {
                       
$data['region'] = $Region->ID;

                        if( !empty(
$subregion ) )
                        {    
// Get subregion ID from DB by name
                           
$SubregionCache = & get_SubregionCache();
                            if(
$Subregion = & $SubregionCache->get_by_name( $subregion, false ) )
                            {
                                if(
$Subregion->rgn_ID == $data['region'] )
                                {
                                   
$data['subregion'] = $Subregion->ID;
                                }
                            }
                        }

                        if( !empty(
$city ) )
                        {    
// Get city ID from DB by name
                           
$CityCache = & get_CityCache();
                            if(
$City = & $CityCache->get_by_name( $city, false ) )
                            {
                                if(
$City->rgn_ID == $data['region'] )
                                {
                                   
$data['city'] = $City->ID;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return
$data;
}


/**
 * Convert string value to normal encoding
 *
 * @param string Value
 * @return string A converted value
 */
function wpxml_convert_value( $value )
{
    global
$xml_import_convert_to_latin;

   
$value = (string) $value;

    if(
$xml_import_convert_to_latin )
    {
// We should convert a value from utf8 to latin1
       
if( function_exists( 'iconv' ) )
        {
// Convert by iconv extenssion
           
$value = iconv( 'utf-8', 'iso-8859-1', $value );
        }
        elseif(
function_exists( 'mb_convert_encoding' ) )
        {
// Convert by mb extenssion
           
$value = mb_convert_encoding( $value, 'iso-8859-1', 'utf-8' );
        }
    }

    return
$value;
}


/**
 * This class is used to avoid wrong chars in XML files on import
 *
 * @see wpxml_parser()
 * @see wpxml_check_xml_file()
 */
class ValidUTF8XMLFilter extends php_user_filter
{
    protected static
$pattern = '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u';

    function
filter( $in, $out, & $consumed, $closing )
    {
        while(
$bucket = stream_bucket_make_writeable( $in ) )
        {
           
$bucket->data = preg_replace( self::$pattern, '', $bucket->data );
           
$consumed += $bucket->datalen;
           
stream_bucket_append( $out, $bucket );
        }
        return
PSFS_PASS_ON;
    }
}


/**
 * Display a selector for Item Types
 *
 * @param string XML file path
 * @param string|NULL Temporary folder of unpacked ZIP archive
 */
function wpxml_item_types_selector( $XML_file_path, $ZIP_folder_path = NULL )
{
   
// Parse WordPress XML file into array
   
echo 'Loading & parsing the XML file...'.'<br />';
   
evo_flush();
   
$xml_data = wpxml_parser( $XML_file_path );
    echo
'<ul class="list-default">';
        echo
'<li>'.'Memory used by XML parsing (difference between free RAM before loading XML and after)'.': <b>'.bytesreadable( $xml_data['memory']['parsing'] ).'</b></li>';
        echo
'<li>'.'Memory used by temporary arrays (difference between free RAM after loading XML and after copying all the various data into temporary arrays)'.': <b>'.bytesreadable( $xml_data['memory']['arrays'] ).'</b></li>';
    echo
'</ul>';
   
evo_flush();

   
$item_type_names = array();
   
$item_type_usages = array();
   
$no_item_types = 0;
    if( ! empty(
$xml_data['posts'] ) )
    {    
// Count items number per item type:
       
foreach( $xml_data['posts'] as $post )
        {
            if(
$post['post_type'] == 'attachment' || $post['post_type'] == 'revision' )
            {    
// Skip reserved post type:
               
continue;
            }

            if( ! empty(
$post['itemtype'] ) )
            {    
// Use evo field Item Type name as first priority:
               
if( ! isset( $item_type_names[ $post['itemtype'] ] ) )
                {
                   
$item_type_names[ $post['itemtype'] ] = 1;
                }
                else
                {
                   
$item_type_names[ $post['itemtype'] ]++;
                }
            }
            elseif( ! empty(
$post['post_type'] ) )
            {    
// Use wp field Item Type usage as second priority:
               
if( ! isset( $item_type_usages[ $post['post_type'] ] ) )
                {
                   
$item_type_usages[ $post['post_type'] ] = 1;
                }
                else
                {
                   
$item_type_usages[ $post['post_type'] ]++;
                }
            }
            else
            {    
// If Item Type is not defined at all:
               
$no_item_types++;
            }
        }
    }

    if( empty(
$item_type_names ) && empty( $item_type_usages ) && $no_item_types == 0 )
    {    
// No posts:
       
echo '<p>No posts found in XML file, you can try to import other data like catefories and etc.</p>';
    }
    else
    {    
// Display Item Types selectors:
       
$ItemTypeCache = & get_ItemTypeCache();
       
$ItemTypeCache->clear();
       
$SQL = $ItemTypeCache->get_SQL_object();
       
$SQL->FROM_add( 'INNER JOIN T_items__type_coll ON itc_ityp_ID = ityp_ID' );
       
$SQL->WHERE( 'itc_coll_ID = '.get_param( 'wp_blog_ID' ) );
       
$ItemTypeCache->load_by_sql( $SQL );

        echo
'<b>'.TB_('Select item types:').'</b>';
        echo
'<ul class="list-default controls">';
       
// Selector for Item Types by name:
       
wpxml_display_item_type_selector( $item_type_names, 'name' );
       
// Selector for Item Types by usage:
       
wpxml_display_item_type_selector( $item_type_usages, 'usage' );
        if(
$no_item_types > 0 )
        {    
// Selector for without provided Item Types:
           
wpxml_display_item_type_selector( array( $no_item_types ), 'none' );
        }
        echo
'</ul>';
    }
}


/**
 * Display item type selector
 *
 * @param array
 */
function wpxml_display_item_type_selector( $item_types, $item_type_field )
{
   
$ItemTypeCache = & get_ItemTypeCache();

    foreach(
$item_types as $item_type => $items_num )
    {
        echo
'<li>';
        switch(
$item_type_field )
        {
            case
'name':
               
printf( '%d items with %s -> import as', $items_num, '<code>&lt;evo:itemtype&gt;</code> = <code>'.$item_type.'</code>' );
               
$form_field_name = 'item_type_names['.$item_type.']';
                break;
            case
'usage':
               
printf( '%d items with %s -> import as', $items_num, '<code>&lt;wp:post_type&gt;</code> = <code>'.$item_type.'</code>' );
               
$form_field_name = 'item_type_usages['.$item_type.']';
                break;
            case
'none':
               
printf( '%d items without provided item type -> import as', $items_num );
               
$form_field_name = 'item_type_none';
                break;
        }
        echo
' <select name="'.$form_field_name.'" class="form-control" style="margin:2px">'
                   
.'<option value="0">'.format_to_output( TB_('Do not import') ).'</option>';
       
$is_auto_selected = false;
       
$is_first_selected = false;
        foreach(
$ItemTypeCache->cache as $ItemType )
        {
            if(
$item_type_field != 'none' &&
                !
$is_first_selected &&
               
$ItemType->get( $item_type_field ) == $item_type )
            {
               
$is_auto_selected = true;
               
$is_first_selected = true;
            }
            else
            {
               
$is_auto_selected = false;
            }
            echo
'<option value="'.$ItemType->ID.'"'.( $is_auto_selected ? ' selected="selected"' : '' ).'>'.format_to_output( $ItemType->get( 'name' ) ).'</option>';
        }
        echo
'</select>'
           
.'</li>';
    }
}
?>