Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/tools/model/_itemtypeimport.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.' );


/**
 * Import data from Item Type XML file into b2evolution database
 *
 * @param string Path of XML file
 */
function itxml_import( $XML_file_path )
{
    global
$DB, $admin_url;

   
// Get collections IDs from request:
   
$it_blog_IDs = param( 'it_blog_IDs', 'array:integer', NULL );
    if(
is_array( $it_blog_IDs ) && ! empty( $it_blog_IDs ) )
    {
       
$BlogCache = & get_BlogCache();
       
$BlogCache->load_list( $it_blog_IDs );
        foreach(
$it_blog_IDs as $it => $it_blog_ID )
        {
            if( ! (
$it_Blog = & $BlogCache->get_by_ID( $it_blog_ID, false, false ) ) )
            {    
// Exclude wrong collection:
               
unset( $it_blog_IDs[ $it_blog_ID ] );
            }
        }
    }

   
// The import type ( skip | update )
   
$import_type = param( 'import_type', 'string', 'skip' );

   
// Parse Item Type XML file into array:
   
echo 'Loading & parsing the XML file...'.'<br />';
   
evo_flush();
   
$xml_data = itxml_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();

   
$DB->begin();

   
/* Import Item Types */
   
if( isset( $xml_data['item_types'] ) && count( $xml_data['item_types'] ) > 0 )
    {
        echo
'<b>'.'Importing Item Types...'.' </b><br>';
       
evo_flush();

       
// Get existing item types:
       
$SQL = new SQL( 'Get existing item types before import' );
       
$SQL->SELECT( 'ityp_name, ityp_ID' );
       
$SQL->FROM( 'T_items__type' );
       
$existing_item_types = $DB->get_assoc( $SQL );

       
$new_item_types_num = 0;
       
$update_item_types_num = 0;
       
$skipped_item_types_num = 0;
       
$failed_item_types_num = 0;
        foreach(
$xml_data['item_types'] as $item_type )
        {
            echo
sprintf( 'Importing Item Type: %s', '"'.$item_type['name'].'"' ).'...';

            echo
'<ul class="list-default">';

           
$is_new_item_type = true;
            if( empty(
$existing_item_types[ $item_type['name'] ] ) )
            {    
// Create new Item Type in order to insert into DB:
               
$ItemType = new ItemType();
               
$ItemType->set( 'name', $item_type['name'] );
            }
            elseif(
$import_type == 'skip' )
            {    
// Skip existing Item Type:
               
echo '<li class="text-warning"><span class="label label-warning">WARNING</span> '.sprintf( 'Skipped because we already have an Item Type with the same name <a %s>%s</a>.', 'href="'.$admin_url.'?ctrl=itemtypes&amp;action=edit&amp;ityp_ID='.$existing_item_types[ $item_type['name'] ].'"', $item_type['name'] ).'</li>';
               
$skipped_item_types_num++;
                echo
'</ul>';
               
evo_flush();
                continue;
            }
            else
            {    
// Get the existing Item Type in order to update it:
               
$ItemTypeCache = & get_ItemTypeCache();
               
$ItemType = & $ItemTypeCache->get_by_ID( $existing_item_types[ $item_type['name'] ], false, false );
               
$is_new_item_type = false;
            }

            foreach(
$item_type as $item_type_field_key => $item_type_field_value )
            {
                if( !
in_array( $item_type_field_key, array( 'ID', 'name', 'custom_fields' ) ) &&
                   
property_exists( 'ItemType', $item_type_field_key ) )
                {    
// Update only proper itme type field:
                   
$ItemType->set( $item_type_field_key, $item_type_field_value, true );
                }
            }

           
$old_custom_fields = $ItemType->get_custom_fields();

            if( ! empty(
$item_type['custom_fields'] ) )
            {    
// Import custom fields:
               
$ItemType->update_custom_fields = array();
               
$ItemType->insert_custom_fields = array();
                foreach(
$item_type['custom_fields'] as $custom_field_name => $new_custom_field )
                {
                   
$custom_field_cols = array(
                           
'type',
                           
'label',
                           
'name',
                           
'schema_prop',
                           
'order',
                           
'note',
                           
'required',
                           
'meta',
                           
'public',
                           
'format',
                           
'formula',
                           
'cell_class',
                           
'disp_condition',
                           
'header_class',
                           
'link',
                           
'link_nofollow',
                           
'link_class',
                           
'line_highlight',
                           
'green_highlight',
                           
'red_highlight',
                           
'description',
                           
'merge',
                        );
                    foreach(
$custom_field_cols as $custom_field_col )
                    {    
// Check the imported custom field has all required columns:
                       
if( ! array_key_exists( $custom_field_col, $new_custom_field ) )
                        {    
// Skip wrong custom field:
                           
echo '<li class="text-danger"><span class="label label-danger">ERROR</span> '.sprintf( 'Skip custom field %s because no required property %s.', '<code>'.$custom_field_name.'</code>', '<code>'.$custom_field_col.'</code>' ).'</li>';
                           
evo_flush();
                            continue
2;
                        }
                        if(
in_array( $custom_field_col, array( 'required', 'meta', 'public', 'link_nofollow', 'merge' ) ) )
                        {    
// Format number fields in order to avoid error on insert/update data in DB:
                           
$new_custom_field[ $custom_field_col ] = empty( $new_custom_field[ $custom_field_col ] ) ? 0 : 1;
                        }
                    }

                    if( isset(
$old_custom_fields[ $custom_field_name ] ) )
                    {    
// If Item Type is found:
                       
if( $old_custom_fields[ $custom_field_name ]['type'] == $new_custom_field['type'] )
                        {    
// Update existing custom field only if type is the same:
                           
$ItemType->update_custom_fields[ $old_custom_fields[ $custom_field_name ]['ID'] ] = $new_custom_field;
                            echo
'<li>'.sprintf( 'Update custom field %s.', '<code>'.$custom_field_name.'</code>' ).'</li>';
                           
evo_flush();
                        }
                        else
                        {    
// Don't allow to update custom field with a different type:
                           
echo '<li class="text-danger"><span class="label label-danger">ERROR</span> '.sprintf( 'Cannot update custom field %s because it has type %s and we expect type %s', '<code>'.$custom_field_name.'</code>', '<code>'.$new_custom_field['type'].'</code>', '<code>'.$old_custom_fields[ $custom_field_name ]['type'].'</code>' ).'.</li>';
                           
evo_flush();
                        }
                    }
                    else
                    {    
// Insert new custom field:
                       
$ItemType->insert_custom_fields[] = $new_custom_field;
                        echo
'<li class="text-success">'.sprintf( 'Add new custom field %s.', '<code>'.$custom_field_name.'</code>' ).'</li>';
                       
evo_flush();
                    }
                }
            }

            if( ! empty(
$old_custom_fields ) )
            {    
// Find and delete old custom fields if they are not present in the imported Item Type:
               
$deleted_custom_fields = array();
               
$ItemType->delete_custom_fields = array();
                foreach(
$old_custom_fields as $old_custom_field_key => $old_custom_field )
                {
                    if( ! isset(
$item_type['custom_fields'][ $old_custom_field_key ] ) )
                    {    
// Delete custom field from DB:
                       
$deleted_custom_fields[] = $old_custom_field_key;
                       
$ItemType->delete_custom_fields[] = $old_custom_field['ID'];
                    }
                }
                if( ! empty(
$deleted_custom_fields ) )
                {    
// Display what custom fields will be deleted:
                   
echo '<li class="text-warning"><span class="label label-warning">WARNING</span> '.sprintf( 'Delete custom fields: %s.', '<code>'.implode( '</code>, <code>', $deleted_custom_fields ).'</code>' ).'</li>';
                   
evo_flush();
                }
            }

            if(
$ItemType && $ItemType->dbsave() )
            {    
// If Item Type is added/updated successfully:
               
if( ! empty( $it_blog_IDs ) )
                {    
// Enable the Item Type for the selected Collections:
                   
$it_colls_insert_sql_values = array();
                    foreach(
$it_blog_IDs as $it_blog_ID )
                    {
                       
$it_colls_insert_sql_values[] = '( '.$DB->quote( $ItemType->ID ).', '.$DB->quote( $it_blog_ID ).' )';
                    }
                   
$DB->query( 'REPLACE INTO T_items__type_coll
                               ( itc_ityp_ID, itc_coll_ID )
                        VALUES '
.implode( ', ', $it_colls_insert_sql_values ) );
                }

               
// Log success result:
               
if( $is_new_item_type )
                {
                   
$new_item_types_num++;
                    echo
'<li class="text-success">Item Type added.</li>';
                }
                else
                {
                   
$update_item_types_num++;
                    echo
'<li class="text-info">Item Type updated.</li>';
                }
            }
            else
            {    
// Log failed result:
               
$failed_item_types_num++;
                echo
'<li class="text-danger">'.sprintf( 'Item Type %s could not be imported.', '<code>'.$item_type['name'].'</code>' ).'</li>';
            }

            echo
'</ul>';
           
evo_flush();
        }

        if(
$new_item_types_num )
        {
            echo
'<b class="text-success">'.sprintf( '%d new Item Types', $new_item_types_num ).'</b><br />';
        }
        if(
$update_item_types_num )
        {
            echo
'<b class="text-info">'.sprintf( '%d updated Item Types', $update_item_types_num ).'</b><br />';
        }
        if(
$skipped_item_types_num )
        {
            echo
'<b class="text-warning">'.sprintf( '%d skipped Item Types', $skipped_item_types_num ).'</b><br />';
        }
        if(
$failed_item_types_num )
        {
            echo
'<b class="text-danger">'.sprintf( '%d Item Types could not be imported', $failed_item_types_num ).'</b>';
        }
    }

    echo
'<br><p class="text-success">'.'Import complete.'.'</p>';

   
$DB->commit();
}


/**
 * Parse WordPress XML file into array
 *
 * @param string File path
 * @return array XML data:
 *          item_type
 *          base_url
 *          app_version
 *          memory
 */
function itxml_parser( $file )
{
   
$item_types = 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:
   
$app_version = $xml->xpath( '/rss/channel/evo:app_version' );
   
$app_version = isset( $app_version[0] ) ? (string) trim( $app_version[0] ) : '';

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

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

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

   
// Get item types:
   
foreach( $xml->xpath( '/rss/channel/evo:itemtype' ) as $item_type_data )
    {
       
$evo = (array)$item_type_data->children( $namespaces['evo'] );

       
$item_type = array();
        foreach(
$evo as $evo_key => $evo_data )
        {
            if(
is_array( $evo_data ) )
            {    
// Skip array data like custom field:
               
continue;
            }
           
$item_type[ $evo_key ] = (string) $evo_data;
        }

        if( isset(
$evo['customfield'] ) )
        {
           
$item_type['custom_fields'] = array();
            foreach(
$evo['customfield'] as $custom_field_data )
            {    
// Get the custom fields:
               
$custom_field_data = (array) $custom_field_data;
                foreach(
$custom_field_data as $custom_field_key => $custom_field_value )
                {
                   
$item_type['custom_fields'][ ( string )$custom_field_data['name'] ][ $custom_field_key ] = ( string )$custom_field_value;
                }
            }
        }

       
$item_types[] = $item_type;
    }

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

    return array(
       
'item_types'  => $item_types,
       
'base_url'    => $base_url,
       
'app_version' => $app_version,
       
'memory'      => $memory,
    );
}
?>