Вход Регистрация
Файл: admin/sources/classes/skins/skinImportExport.php
Строк: 1325
<?php

/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.3.3
 * Skin Functions
 * Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
 * </pre>
 *
 * Owner: Matt
 * @author         $Author: bfarber $
 * @copyright    (c) 2001 - 2009 Invision Power Services, Inc.
 * @license        http://www.invisionpower.com/company/standards.php#license
 * @package        IP.Board
 * @link        http://www.invisionpower.com
 * @since        9th March 2005 11:03
 * @version        $Revision: 10721 $
 *
 */

if ( ! defined( 'IN_IPB' ) )
{
    print 
"<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
    exit();
}

class 
skinImportExport extends skinCaching
{
    
/**#@+
     * Registry objects
     *
     * @access    protected
     * @var        object
     */    
    
protected $registry;
    protected 
$DB;
    protected 
$settings;
    protected 
$request;
    protected 
$lang;
    protected 
$member;
    protected 
$memberData;
    protected 
$cache;
    protected 
$caches;
    
/**#@-*/
    
    /**
     * Constructor
     *
     * @access    public
     * @param    object        Registry object
     * @return    @e void
     */
    
public function __construct( ipsRegistry $registry )
    {
        
/* Make object */
        
parent::__construct( $registry );
    }
    
    
/**
     * Imports a replacements XMLArchive
     *
     * @access    public
     * @param    string        XMLArchive content to import
     * @param    int            Set ID to apply to (if desired)
     * @return    int            Number of items added
     */
    
public function importReplacementsXMLArchive( $content, $setID=0 )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$addedCount        = 0;
        
$masterKeys     = $this->fetchMasterKeys();
        
$skinMasterKey    = '';
        
        
//-----------------------------------------
        // Got anything?
        //-----------------------------------------
        
        
$replacements = $this->parseReplacementsXML( $content );
        
$where        = ( is_numeric( $setID ) ) ? 'replacement_set_id=' . $setID : 'replacement_master_key='' . $setID . ''';
        
        
/* If this is a 'master' skin, then reset master key */
        
if ( in_array( $setID, $masterKeys ) )
        {
            
$skinMasterKey = $setID;
            
$setID         = 0;
        }

        
//-----------------------------------------
        // Replacements...
        //-----------------------------------------
        
        
if ( is_array( $replacements ) )
        {
            
/* Get all the keys for this set id */
            
$this->DB->build( array( 'select' => 'replacement_key', 'from' => 'skin_replacements', 'where' => $where ) );
            
$this->DB->execute();
            
            
$repKeyCache = array();
            while( 
$r = $this->DB->fetch() )
            {
                
$repKeyCache[] = $r['replacement_key'];
            }

            foreach( 
$replacements as $replacement )
            {
                if ( 
$replacement['replacement_key'] )
                {
                    
/* Until this function is reworked, both update and insert count as 'added' */
                    
$addedCount++;

                    if( 
in_array( $replacement['replacement_key'], $repKeyCache ) )
                    {
                        
$this->DB->update( 'skin_replacements', array( 'replacement_content'  => $replacement['replacement_content'] ), "replacement_key='{$replacement['replacement_key']}' AND " . $where );    
                    }
                    else
                    {
                        
$this->DB->insert( 'skin_replacements', array(  'replacement_key'        => $replacement['replacement_key'],
                                                                        
'replacement_content'    => $replacement['replacement_content'],
                                                                        
'replacement_set_id'     => $setID,
                                                                        
'replacement_added_to'   => $setID,
                                                                        
'replacement_master_key' => $skinMasterKey
                                                                    
) );
                    }
                }
            }
        }

        
$this->rebuildReplacementsCache( $setID );
        
$this->rebuildSkinSetsCache( $setID );
        
        return 
$addedCount;
    }
    
    
/**
     * Imports a set XMLArchive
     *
     * @access    public
     * @param    string        XMLArchive content to import
     * @param    string        Images directory name to use.
     * @param    int            [ Set ID to apply to (if desired) ]
     * @return    mixed        Number of items added, or bool
     */
    
public function importImagesXMLArchive( $content, $imageSetName, $setID=0 )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$addedCount  = 0;
                            
        
//-----------------------------------------
        // Got anything?
        //-----------------------------------------
        
        
if ( ! strstr( $content, "<xmlarchive" ) )
        {
            
$this->_addErrorMessage( $this->lang->words['invalidxmlarchivei'] );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Grab the XMLArchive class
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
        
$xmlArchive = new classXMLArchive();
        
        
$xmlArchive->readXML( $content );
        
        if ( ! 
$xmlArchive->countFileArray() )
        {
            
$this->_addErrorMessage( $this->lang->words['emptyxmlarchivei'] );
            return 
FALSE;
        }
        
        
$added = $xmlArchive->countFileArray();
        
        
//-----------------------------------------
        // Checks...
        //-----------------------------------------
        
        
if ( $this->checkImageDirectoryExists( $imageSetName ) === TRUE )
        {
            
/* Already exists... */
            
$this->_addErrorMessage( sprintf( $this->lang->words['imagediralreadyexists'], $imageSetName ) );
            return 
FALSE;
        }
        
        if ( 
$this->createNewImageDirectory( $imageSetName ) !== TRUE )
        {
            
$this->_addErrorMessage( sprintf( $this->lang->words['imagedircannotcreate'], $imageSetName ) );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // OK, write it...
        //-----------------------------------------
        
        /* Find the name of the folder */
        //preg_match( "#<path>([^/]+?)</path>#", $content, $match );
        //$_strip = $match[1];
        
        /* Strip the path */
        //$xmlArchive->setStripPath( $_strip );

        /* Write it */
        
if ( $xmlArchive->write( $content, $this->fetchImageDirectoryPath( $imageSetName ) ) === FALSE )
        {
            
$this->_addErrorMessage( $this->lang->words['cannotwriteimageset'] );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Update set?
        //-----------------------------------------
        
        
if ( $setID )
        {
            
$this->DB->update( 'skin_collections', array( 'set_image_dir' => $imageSetName ), 'set_id=' . $setID );
            
            
/* Rebuild trees */
            
$this->rebuildTreeInformation( $setID );
            
            
/* Now re-load to fetch the tree information */
            
$newSet = $this->DB->buildAndFetch( array( 'select' => '*',
                                                       
'from'   => 'skin_collections',
                                                       
'where'  => 'set_id=' . $setID ) );
                                                    
            
/* Add to allSkins array for caching functions below */
            
$newSet['_parentTree']     = unserialize( $newSet['set_parent_array'] );
            
$newSet['_childTree']      = unserialize( $newSet['set_child_array'] );
            
$newSet['_userAgents']     = unserialize( $newSet['set_locked_uagent'] );
            
$newSet['_cssGroupsArray'] = unserialize( $newSet['set_css_groups'] );
            
            
$this->registry->output->allSkins[ $setID ] = $newSet;
            
            
$this->rebuildSkinSetsCache( $setID );
            
$this->rebuildCSS( $setID );
            
$this->rebuildReplacementsCache( $setID );
        }
        
        return 
$added;
    }
    
    
/**
     * Imports a set XMLArchive
     *
     * @access    public
     * @param    string        XMLArchive content to import
     * @param    int         [ Skin set parent. If omitted, it will be made a root skin ]
     * @param    string        [ Images directory to use. If omitted, default skin's image dir is used ]
     * @param    string        [ Name of skin to create. If omitted, name from skin set is used ]
     * @param    bool        [ Whether or not we are attempting to upgrade an existing skin ]
     * @return    mixed        bool, or number of items added
     */
    
public function importSetXMLArchive( $content, $parentID=0, $imageDir='', $setName='', $upgrading=FALSE )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$templates    = array();
        
$csss          = array();
        
$groups       = array();
        
$defaultSkin  = array();
        
$return       = array( 'replacements' => 0,
                               
'css'          => 0,
                               
'templates'    => 0,
                               
'upgrade'      => FALSE );
                            
        
//-----------------------------------------
        // Got anything?
        //-----------------------------------------
        
        
if ( ! strstr( $content, "<xmlarchive" ) )
        {
            
$this->_addErrorMessage( $this->lang->words['invalidxmlarchivei'] );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Make admin group list
        //-----------------------------------------
        
        
foreach( $this->caches['group_cache'] as $id => $data )
        {
            if ( 
$data['g_access_cp'] )
            {
                
$groups[] = $id;
            }
        }
        
        
//-----------------------------------------
        // Grab the XMLArchive class
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
        
$xmlArchive = new classXMLArchive();
        
        
$xmlArchive->readXML( $content );
        
        if ( ! 
$xmlArchive->countFileArray() )
        {
            
$this->_addErrorMessage( $this->lang->words['emptyxmlarchivei'] );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Gather data
        //-----------------------------------------
        
        /* Info */
        
$infoXml    = $xmlArchive->getFile('info.xml');
        
        if( !
$infoXml )
        {
            
$this->_addErrorMessage( $this->lang->words['noinfoxml'] );
            return 
FALSE;
        }
        
        
$info        = $this->parseInfoXML( $infoXml );
        
        
/* Are we attempting to upgrade? */
        
$setID     = 0;
        
$doUpgrade = FALSE;
        
$new_items = array( 'replacements' => array(),
                            
'css'          => array(),
                            
'templates'    => array(),
                          );
        
        if ( 
$info['set_key'] && $upgrading )
        {
            foreach ( 
$this->caches['skinsets'] as $set_id => $set_data )
            {
                if ( 
$set_data['set_key'] == $info['set_key'] )
                {
                    
$setID             = $set_id;
                    
$doUpgrade         = TRUE;
                    
$return['upgrade'] = TRUE;
                    break;
                }
            }
        }
        
        
/* Replacements */
        
$replacements = $this->parseReplacementsXML( $xmlArchive->getFile( 'replacements.xml' ) );

        
/* Templates */
        
foreach( $xmlArchive->asArray() as $path => $fileData )
        {
            if ( 
$fileData['path'] == 'templates' && $fileData['content'] )
            {
                
$templates[ str_replace( '.xml', '', $fileData['filename'] ) ] = $this->parseTemplatesXML( $fileData['content'] );
            }
        }

        
/* Templates */
        
foreach( $xmlArchive->asArray() as $path => $fileData )
        {
            if ( 
$fileData['path'] == 'css' )
            {
                
$csss[ str_replace( '.xml', '', $fileData['filename'] ) ] = $this->parseCSSXML( $fileData['content'] );
            }
        }
        
        if ( ! 
is_array( $info ) )
        {
            
$this->_addErrorMessage( $this->lang->words['noinfoxml'] );
            return 
FALSE;
        }
        
        
$info['set_output_format'] = ( $info['set_output_format'] ) ? $info['set_output_format'] : 'html';
        
        
//-----------------------------------------
        // Find default skin
        //-----------------------------------------
        
        
foreach( $this->registry->output->allSkins as $id => $data )
        {
            if ( 
$data['set_is_default'] AND $data['set_output_format'] == $info['set_output_format'] )
            {
                
$defaultSkin = $data;
                break;
            }
        }
        
        
/* Make sure key in unique */
        
$test = $this->DB->buildAndFetch( array( 'select' => '*',
                                                 
'from'   => 'skin_collections',
                                                 
'where'  => 'set_key='' . $this->DB->addSlashes( $info['set_key'] ) . '' AND set_id != ' . intval( $setID ) ) );
                                                 
        if ( 
$test['set_id'] )
        {
            
$info['set_key'] .= '_' . time();
        }

        
//-----------------------------------------
        // Build Set Array
        //-----------------------------------------
        
        
$newSet = array('set_name'                => ( $setName ) ? $setName : $info['set_name'] . ' (Import)',
                        
'set_key'                => $info['set_key'],
                        
'set_parent_id'          => $parentID,
                        
'set_permissions'        => implode( ",", $groups ),
                        
'set_is_default'        => 0,
                        
'set_author_name'        => $info['set_author_name'],
                        
'set_author_url'        => $info['set_author_url'],
                        
'set_image_dir'            => ( $imageDir ) ? $imageDir : $defaultSkin['set_image_dir'],
                        
'set_emo_dir'            => $defaultSkin['set_emo_dir'],
                        
'set_css_inline'        => 1,
                        
'set_output_format'     => $info['set_output_format'],
                        
'set_css_groups'        => '',
                        
'set_hide_from_list'    => 1,    // Per Rikki :P
                        
'set_order'                => intval( $this->fetchHighestSetPosition() ) + 1,
                        
'set_master_key'        => ( isset( $info['set_master_key'] ) ) ? $info['set_master_key'] : 'root',
                        
'set_updated'           => time() );

        if ( 
$setID )
        {
            
//-----------------------------------------
            // Update...
            //-----------------------------------------
            
            
$this->DB->update( 'skin_collections', array( 'set_author_name' => $info['set_author_name'],
                                                          
'set_author_url'  => $info['set_author_url'],
                                                          
'set_updated'     => time(),
                                                        ), 
'set_id=' . $setID );
        }
        else
        {
            
//-----------------------------------------
            // Insert...
            //-----------------------------------------
            
            
$this->DB->insert( 'skin_collections', $newSet );
            
            
$setID = $this->DB->getInsertId();
        }
        
        
/* Rebuild trees */
        
$this->rebuildTreeInformation( $setID );
        
        
/* Now re-load to fetch the tree information */
        
$newSet = $this->DB->buildAndFetch( array( 'select' => '*',
                                                   
'from'   => 'skin_collections',
                                                   
'where'  => 'set_id=' . $setID ) );
                                                
        
/* Add to allSkins array for caching functions below */
        
$newSet['_parentTree']     = unserialize( $newSet['set_parent_array'] );
        
$newSet['_childTree']      = unserialize( $newSet['set_child_array'] );
        
$newSet['_userAgents']     = unserialize( $newSet['set_locked_uagent'] );
        
$newSet['_cssGroupsArray'] = unserialize( $newSet['set_css_groups'] );
        
        
$this->registry->output->allSkins[ $setID ] = $newSet;
        
        
//-----------------------------------------
        // Replacements...
        //-----------------------------------------
        
        
if ( is_array( $replacements ) )
        {
            foreach( 
$replacements as $replacement )
            {
                if ( 
$replacement['replacement_key'] )
                {
                    
$return['replacements']++;
                    
$existing_id = 0;
                    
                    
/* Check if we need to update or insert */
                    
if ( $doUpgrade )
                    {
                        
$exists = $this->DB->buildAndFetch( array( 'select' => 'replacement_id',
                                                                   
'from'   => 'skin_replacements',
                                                                   
'where'  => "replacement_key='{$replacement['replacement_key']}' AND replacement_set_id={$setID} AND replacement_added_to={$setID}" ) );
                        
                        
                        
$existing_id = $exists['replacement_id'];
                    }
                    
                    if ( 
$existing_id )
                    {
                        
$new_items['replacements'][] = $existing_id;
                        
$this->DB->update( 'skin_replacements', array( 'replacement_content'  => $replacement['replacement_content'] ), "replacement_id=".$existing_id );
                    }
                    else
                    {
                        
$this->DB->insert( 'skin_replacements', array( 'replacement_key'      => $replacement['replacement_key'],
                                                                       
'replacement_content'  => $replacement['replacement_content'],
                                                                       
'replacement_set_id'   => $setID,
                                                                       
'replacement_added_to' => $setID ) );
                    }
                }
            }
        }
        
        
//-----------------------------------------
        // CSS...
        //-----------------------------------------
        
        /* Fetch master CSS */
        
$_MASTER = $this->fetchCSS( 0 );
        
        if ( 
is_array( $csss ) )
        {
            foreach( 
ipsRegistry::$applications as $appDir => $data )
            {
                if ( isset( 
$csss[ $appDir ] ) && is_array( $csss[ $appDir ] ) )
                {
                    foreach( 
$csss[ $appDir ] as $css )
                    {
                        if ( 
$css['css_group'] )
                        {
                            
$return['css']++;
                            
$existing_id = 0;
                            
                            
/* Check if we need to update or insert */
                            
if ( $doUpgrade )
                            {
                                
$exists = $this->DB->buildAndFetch( array( 'select' => 'css_id',
                                                                           
'from'   => 'skin_css',
                                                                           
'where'  => "css_group='{$css['css_group']}' AND css_app='{$css['css_app']}' AND css_set_id={$setID}" ) );
                                
                                
$existing_id = $exists['css_id'];
                            }
                            
                            if ( 
$existing_id )
                            {
                                
$new_items['css'][] = $existing_id;
                                
$this->DB->update( 'skin_css', array( 'css_content'    => $css['css_content'],
                                                                      
'css_position'   => $css['css_position'],
                                                                      
'css_attributes' => $css['css_attributes'],
                                                                      
'css_app_hide'   => $css['css_app_hide'],
                                                                      
'css_modules'    => str_replace( ' ', '', $css['css_modules'] ),
                                                                      
'css_updated'    => time(),
                                                                      
'css_added_to'   => ( isset( $_MASTER[ $css['css_group'] ] ) ) ? 0 : $setID ), "css_id=".$existing_id );
                            }
                            else
                            {
                                
$this->DB->insert( 'skin_css', array( 'css_group'      => $css['css_group'],
                                                                      
'css_content'    => $css['css_content'],
                                                                      
'css_position'   => $css['css_position'],
                                                                      
'css_attributes' => $css['css_attributes'],
                                                                      
'css_app'           => $css['css_app'],
                                                                      
'css_app_hide'   => $css['css_app_hide'],
                                                                      
'css_modules'       => str_replace( ' ', '', $css['css_modules'] ),
                                                                      
'css_updated'    => time(),
                                                                      
'css_set_id'     => $setID,
                                                                      
'css_added_to'   => ( isset( $_MASTER[ $css['css_group'] ] ) ) ? 0 : $setID ) );
                            }
                        }
                    }
                }
            }
        }
        
        
//-----------------------------------------
        // Templates - only import apps we have...
        //-----------------------------------------
        
        /* Fetch all master items */
        
$_MASTER    = $this->fetchTemplates( 0, 'allNoContent' );
        
        if ( 
is_array( $templates ) )
        {
            foreach( 
ipsRegistry::$applications as $appDir => $data )
            {
                if ( 
array_key_exists( $appDir, $templates ) )
                {
                    foreach( 
$templates[ $appDir ] as $template )
                    {
                        if ( 
$template['template_group'] AND $template['template_name'] )
                        {
                            
/* Figure out if this is added by a user or not */
                            
$isAdded = ( is_array( $_MASTER[ $template['template_group'] ][ strtolower( $template['template_name'] ) ] ) AND ! $_MASTER[ $template['template_group'] ][ strtolower( $template['template_name'] ) ]['template_user_added'] ) ? 0 : 1;
                            
                            
$return['templates']++;
                            
$existing_id = 0;
                            
                            
/* Check if we need to update or insert */
                            
if ( $doUpgrade )
                            {
                                
$exists = $this->DB->buildAndFetch( array( 'select' => 'template_id',
                                                                           
'from'   => 'skin_templates',
                                                                           
'where'  => "template_set_id={$setID} AND template_group='{$template['template_group']}' AND template_name='{$template['template_name']}'" ) );
                                
                                
$existing_id = $exists['template_id'];
                            }
                                
                            if ( 
$existing_id )
                            {
                                
$new_items['templates'][] = $existing_id;
                                
$this->DB->update( 'skin_templates', array( 'template_content'     => $template['template_content'],
                                                                            
'template_data'        => $template['template_data'],
                                                                            
'template_updated'     => $template['template_updated'],
                                                                            
'template_removable'   => 1,
                                                                            
'template_user_edited' => 1,
                                                                            
'template_user_added'  => $isAdded,
                                                                            
'template_added_to'    => $setID ), "template_id=".$existing_id );
                            }
                            else
                            {
                                
$this->DB->insert( 'skin_templates', array( 'template_set_id'      => $setID,
                                                                            
'template_group'       => $template['template_group'],
                                                                            
'template_content'     => $template['template_content'],
                                                                            
'template_name'        => $template['template_name'],
                                                                            
'template_data'        => $template['template_data'],
                                                                            
'template_updated'     => $template['template_updated'],
                                                                            
'template_removable'   => 1,
                                                                            
'template_user_edited' => 1,
                                                                            
'template_user_added'  => $isAdded,
                                                                            
'template_added_to'    => $setID ) );
                            }
                        }
                    }
                }
            }
        }
        
        
//-----------------------------------------
        // If upgrading, and there are items from an old
        // skin not in the new one, delete the old elements
        // This probably won't ever come up, but I'm anal retentive :P
        //-----------------------------------------
        
        
if ( $doUpgrade )
        {
            if ( 
count( $new_items['replacements'] ) )
            {
                
$this->DB->delete( 'skin_replacements', "replacement_set_id={$setID} AND replacement_id NOT IN (" . implode( ',', $new_items['replacements']) . ")" );
            }
            if ( 
count( $new_items['css'] ) )
            {
                
$this->DB->delete( 'skin_css', "css_set_id={$setID} AND css_id NOT IN (" . implode( ',', $new_items['css']) . ")" );
            }
            if ( 
count( $new_items['templates'] ) )
            {
                
$this->DB->delete( 'skin_templates', "template_set_id={$setID} AND template_id NOT IN (" . implode( ',', $new_items['templates']) . ")" );
            }
        }
        
        
//-----------------------------------------
        // Re-cache
        //-----------------------------------------
        
        
$this->rebuildReplacementsCache( $setID );
        
$this->rebuildCSS( $setID );
        
$this->rebuildPHPTemplates( $setID );
        
$this->rebuildSkinSetsCache();
        
        
//-----------------------------------------
        // Done....
        //-----------------------------------------
        
        
return $return;
    }
    
    
/**
     * Parses an CSS XML file
     *
     * @access    public
     * @param    string    XML
     * @return    array
     */
    
public function parseTemplatesXML( $xmlContents )
    {
        
//-----------------------------------------
        // XML
        //-----------------------------------------

        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml    = new classXML( IPS_DOC_CHAR_SET );
        
$return = array();
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->loadXML( $xmlContents );
        
        foreach( 
$xml->fetchElements( 'template' ) as $xmlelement )
        {
            
$data = $xml->fetchElementsFromRecord( $xmlelement );
            
            if ( 
is_array( $data ) )
            {
                
$return[] = $data;
            }
        }
        
        return 
$return;
    }
    
    
/**
     * Parses an CSS XML file
     *
     * @access    public
     * @param    string    XML
     * @return    array
     */
    
public function parseCSSXML( $xmlContents )
    {
        if( ! 
$xmlContents )
        {
            return 
'';
        }
        
        
//-----------------------------------------
        // XML
        //-----------------------------------------

        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml    = new classXML( IPS_DOC_CHAR_SET );
        
$return = array();
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->loadXML( $xmlContents );
        
        foreach( 
$xml->fetchElements( 'cssfile' ) as $xmlelement )
        {
            
$data = $xml->fetchElementsFromRecord( $xmlelement );
            
            if ( 
is_array( $data ) )
            {
                
$return[] = $data;
            }
        }
        
        return 
$return;
    }
    
    
/**
     * Parses an replacements XML file
     *
     * @access    public
     * @param    string    XML
     * @return    array
     */
    
public function parseReplacementsXML( $xmlContents )
    {
        if( ! 
$xmlContents )
        {
            return 
'';
        }
        
        
//-----------------------------------------
        // XML
        //-----------------------------------------

        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml    = new classXML( IPS_DOC_CHAR_SET );
        
$return = array();
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->loadXML( $xmlContents );
        
        foreach( 
$xml->fetchElements( 'replacement' ) as $xmlelement )
        {
            
$data = $xml->fetchElementsFromRecord( $xmlelement );
            
            if ( 
is_array( $data ) )
            {
                
$return[] = $data;
            }
        }
        
        return 
$return;
    }
    
    
/**
     * Parses an info XML file
     *
     * @access    public
     * @param    string    XML
     * @return    array
     */
    
public function parseInfoXML( $xmlContents )
    {
        
//-----------------------------------------
        // XML
        //-----------------------------------------

        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->loadXML( $xmlContents );

        foreach( 
$xml->fetchElements( 'data' ) as $xmlelement )
        {
            
$data = $xml->fetchElementsFromRecord( $xmlelement );
        }
        
        return 
$data;
    }
    
    
/**
     * Generate an XML archive for an image set
     *
     * @access    public
     * @param    string        Image Directory
     * @return    mixed        bool, or xml contents
     */
    
public function generateImagesXMLArchive( $imgDir )
    {
        
//-----------------------------------------
        // Reset handlers
        //-----------------------------------------
        
        
$this->_resetErrorHandle();
        
$this->_resetMessageHandle();
        
        
//-----------------------------------------
        // Does this image directory exist?
        //-----------------------------------------
        
        
if ( $this->checkImageDirectoryExists( $imgDir ) !== TRUE )
        {
            
$this->_addErrorMessage( sprintf( $this->lang->words['imagedirnotexists'], $imgDir ) );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Create new XML archive...
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
        
$xmlArchive = new classXMLArchive();
        
$xmlArchive->setStripPath( $this->fetchImageDirectoryPath( $imgDir ) );
        
$xmlArchive->add( $this->fetchImageDirectoryPath( $imgDir ) );
        
        return 
$xmlArchive->getArchiveContents();
    }
    
    
/**
     * Generate XML Archive for skin set
     *
     * @access    public
     * @param    int            Skin set ID
     * @param    boolean        Modifications in this set only
     * @param    array        [Array of apps to export from. Default is all]
     * @return    string        XML
     */
    
public function generateSetXMLArchive( $setID=0, $setOnly=FALSE, $appslimit=null )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$templates    = array();
        
$csss          = array();
        
$replacements = "";
        
$css          = "";
        
$setData      = $this->fetchSkinData( $setID );
        
        
//-----------------------------------------
        // Reset handlers
        //-----------------------------------------
        
        
$this->_resetErrorHandle();
        
$this->_resetMessageHandle();
        
        
//-----------------------------------------
        // First up... fetch templates
        //-----------------------------------------
        
        
foreach( ipsRegistry::$applications as $appDir => $data )
        {
            if ( 
is_array( $appslimit ) AND ! in_array( $appDir, $appslimit ) )
            {
                continue;
            }
            
            if ( !empty( 
$data['app_enabled'] ) )
            {
                
$templates[ $appDir ]    = $this->generateTemplateXML( $appDir, $setID, $setOnly );
                
$csss[ $appDir ]        = $this->generateCSSXML( $appDir, $setID, $setOnly );
            }
        }

        
//-----------------------------------------
        // Replacements
        //-----------------------------------------
        
        
$replacements = $this->generateReplacementsXML( $setID, $setOnly );
        
        
//-----------------------------------------
        // Information
        //-----------------------------------------
        
        
$info = $this->generateInfoXML( $setID );
        
        
//-----------------------------------------
        // De-bug
        //-----------------------------------------
        
        
foreach( $templates as $app_dir => $templateXML )
        {
            
IPSDebug::addLogMessage( "Template Export: $app_dirn".$templateXML, 'admin-setExport', false, true, true );
        }
        
        foreach( 
$csss as $app_dir => $cssXML )
        {
            
IPSDebug::addLogMessage( "CSS Export: $app_dirn".$cssXML, 'admin-setExport', false, true );
        }
        
        
IPSDebug::addLogMessage( "Replacements Export:n".$replacements, 'admin-setExport', false, true );
        
IPSDebug::addLogMessage( "Info Export:n".$info, 'admin-setExport', false, true );
        
        
//-----------------------------------------
        // Create new XML archive...
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
        
$xmlArchive = new classXMLArchive();
        
        
/* Add in version numbers */
        
$version = IPSLib::fetchVersionNumber();
        
$xmlArchive->addRootTagValues( array( 'ipbLongVersion' => $version['long'], 'ipbHumanVersion' => $version['human'] ) );
        
        
# Templates
        
foreach( $templates as $app_dir => $templateXML )
        {
            
$xmlArchive->add( $templateXML, "templates/" . $app_dir . ".xml" );
        }
        
        
# CSS
        
foreach( $csss as $app_dir => $cssXML )
        {
            
$xmlArchive->add( $cssXML, "css/" . $app_dir . ".xml" );
        }
        
        
# Replacements
        
$xmlArchive->add( $replacements, "replacements.xml" );

        
# Information
        
$xmlArchive->add( $info, 'info.xml' );
        
        return 
$xmlArchive->getArchiveContents();
    }
    
    
/**
     * Export all Apps skin files
     *
     * @access    public
     * @param    int        [Set ID - 0/root if omitted]
     * @param    bool    Include root bits in any XML export. Default is true
     * @return    @e void
     */
    
public function exportAllAppTemplates( $setID=0, $setOnly=TRUE )
    {
        
//-----------------------------------------
        // Reset handlers
        //-----------------------------------------
        
        
$this->_resetErrorHandle();
        
$this->_resetMessageHandle();
        
        if ( 
$setID == 0 )
        {
            
/* This is which skins we want to export for default installations */
            
$skinIDs  = array_values( $this->remapData['export'] );
        }
        else
        {
            
$skinIDs = array( $setID );
        }
        
        foreach( 
$skinIDs as $setID )
        {
        foreach( 
ipsRegistry::$applications as $app_dir => $app_data )
        {
            if ( ! 
file_exists( IPSLib::getAppDir(  $app_dir ) . '/xml' ) )
            {
                    
$this->_addErrorMessage( IPSLib::getAppDir(  $app_dir ) . $this->lang->words['xmldirmissing'] );
                continue;
            }
            else if ( ! 
is_writable( IPSLib::getAppDir(  $app_dir ) . '/xml' ) )
            {
                if ( ! @
chmod( IPSLib::getAppDir(  $app_dir ) . '/xml', 0755 ) )
                {
                        
$this->_addErrorMessage( IPSLib::getAppDir(  $app_dir ) . $this->lang->words['xmldirnotwrite'] );
                    continue;
                }
            }
                
            
$this->exportTemplateAppXML( $app_dir, $setID, $setOnly );
        }
    }
    }
    
    
/**
     * Export all Apps CSS
     *
     * @access    public
     * @param    int        [Set ID - 0/root if omitted]
     * @return    @e void
     */
    
public function exportAllAppCSS( $setID=0 )
    {
        
//-----------------------------------------
        // Reset handlers
        //-----------------------------------------

        
$this->_resetErrorHandle();
        
$this->_resetMessageHandle();

        if ( 
$setID == 0 )
        {
            
/* This is which skins we want to export for default installations */
            
$skinIDs  = array_values( $this->remapData['export'] );
        }
        else
        {
            
$skinIDs = array( $setID );
        }
        
        foreach( 
$skinIDs as $setID )
        {
        foreach( 
ipsRegistry::$applications as $app_dir => $app_data )
        {
            
$file = IPSLib::getAppDir(  $app_dir ) . '/xml/' . $app_dir . '_css.xml';

            if ( ! 
file_exists( IPSLib::getAppDir(  $app_dir ) . '/xml' ) )
            {
                    
$this->_addErrorMessage( IPSLib::getAppDir(  $app_dir ) . $this->lang->words['xmldirmissing'] );
                continue;
            }
            else if ( ! 
is_writable( IPSLib::getAppDir(  $app_dir ) . '/xml' ) )
            {
                if ( ! @
chmod( IPSLib::getAppDir(  $app_dir ) . '/xml', 0755 ) )
                {
                        
$this->_addErrorMessage( IPSLib::getAppDir(  $app_dir ) . $this->lang->words['xmldirnotwrite'] );
                    continue;
                }
            }

            
$this->exportCSSAppXML( $app_dir, $setID );
        }
    }
    }
    
    
/**
     * Import all Apps skin files
     *
     * @todo  See Matt, this needs fixing! 
     * @access    public
     * @return    @e void
     */
    
public function importAllAppTemplates()
    {
        
//-----------------------------------------
        // Reset handlers
        //-----------------------------------------
        
        
$this->_resetErrorHandle();
        
$this->_resetMessageHandle();
        
        foreach( 
ipsRegistry::$applications as $app_dir => $app_data )
        {
            
$file = IPSLib::getAppDir(  $app_dir ) . '/xml/' . $app_dir . '_templates.xml';
            
            if ( ! 
is_file( $file ) )
            {
                
$this->_addMessage( $app_dir . $this->lang->words['importnothingtoimport'] );
                continue;
            }
            else
            {
                
$return = $this->importTemplateAppXML( $app_dir, 0 );
                
$this->_addMessage( sprintf( $this->lang->words['importaddupdate'], $app_dir, $return['updateCount'], $return['insertCount'] ) );
            }
        }
    }
    
    
/**
     * Generate the master skin set files
     *
     * @access    public
     * @param    array          Array of IDs
     * @return    string        XML contents
     */
    
public function generateMasterSkinSetXML( $skinIDs )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/useragents/userAgentFunctions.php', 'userAgentFunctions' );
        
$userAgentFunctions = new $classToLoad( $this->registry );
        
        
$skins    = array();
        
$setid    = 1;
        
$exports  = array_values( $this->remapData['export'] );
        
$remap    = array( 'mobile' => array( 'set_id'              => 2,
                                              
'set_name'           => 'IP.Board Mobile',
                                              
'set_key'            => 'mobile',
                                              
'set_master_key'      => 'mobile',
                                              
'set_output_format' => 'html',
                                              
'set_image_dir'     => 'mobile',
                                              
'set_locked_uagent' => serialize( $userAgentFunctions->getMobileSkinUserAgents() ) ),
                         
'xmlskin' => array(  'set_id'              => 3,
                                              
'set_name'           => 'IP.Board XML',
                                              
'set_key'            => 'xmlskin',
                                              
'set_master_key'      => 'xmlskin',
                                              
'set_output_format' => 'xml',
                                              
'set_image_dir'     => 'master' ) );
                                              
        
/* Figure out ID 0 */
        
if ( in_array( 0, $skinIDs ) OR in_array( 'root', $skinIDs ) )
        {
            
$cssSkinCollections = array();
            
$_css                 = $this->fetchCSS( 0 );
            
            foreach( 
$_css as $name => $css )
            {
                
/* Build skin set row*/
                
$cssSkinCollections[ $css['css_position'] . '.' . $css['css_id'] ] = array( 'css_group' => $css['css_group'], 'css_position' => $css['css_position'] );
            }
            
            
$setid++;
            
            
$skins[ 0 ] = array( 'set_id'              => 1,
                                   
'set_name'              => 'IP.Board',
                                   
'set_key'              => 'default',
                                   
'set_parent_id'      => 0,
                                   
'set_parent_array'   => serialize( array() ),
                                   
'set_child_array'    => serialize( array() ),
                                   
'set_permissions'    => '*',
                                   
'set_is_default'      => 1,
                                   
'set_author_name'      => 'Invision Power Services, Inc',
                                   
'set_author_url'      => 'http://www.invisionpower.com',
                                   
'set_image_dir'      => 'master',
                                   
'set_emo_dir'          => 'default',
                                   
'set_css_inline'      => 1,
                                   
'set_css_groups'      => serialize( $cssSkinCollections ),
                                   
'set_added'          => time(),
                                   
'set_updated'          => time(),
                                   
'set_output_format'  => 'html',
                                   
'set_locked_uagent'  => '',
                                   
'set_hide_from_list' => 0,
                                   
'set_master_key'     => 'root' );
        }
        
        foreach( 
$exports as $_id )
        {
            if ( 
$_id != 'root' AND in_array( $_id, $skinIDs ) )
            {
                
$cssSkinCollections = array();
                
$_css                 = $this->fetchCSS( $_id );
                
                foreach( 
$_css as $name => $css )
                {
                    
/* Build skin set row*/
                    
$cssSkinCollections[ $css['css_position'] . '.' . $css['css_id'] ] = array( 'css_group' => $css['css_group'], 'css_position' => $css['css_position'] );
                }
                
                
$setid++;
                
                
$skins[ $remap[ $_id ]['set_id'] ] = array(  'set_id'              => $remap[ $_id ]['set_id'],
                                                               
'set_name'              => $remap[ $_id ]['set_name'],
                                                               
'set_key'              => $remap[ $_id ]['set_key'],
                                                               
'set_parent_id'      => 0,
                                                               
'set_parent_array'   => serialize( array() ),
                                                               
'set_child_array'    => serialize( array() ),
                                                               
'set_permissions'    => '*',
                                                               
'set_is_default'      => ( $remap[ $_id ]['set_master_key'] == 'root' ) ? 1 : 0,
                                                               
'set_author_name'      => 'Invision Power Services, Inc',
                                                               
'set_author_url'      => 'http://www.invisionpower.com',
                                                               
'set_image_dir'      => $remap[ $_id ]['set_image_dir'],
                                                               
'set_emo_dir'          => 'default',
                                                               
'set_css_inline'      => 1,
                                                               
'set_css_groups'      => serialize( $cssSkinCollections ),
                                                               
'set_added'          => time(),
                                                               
'set_updated'          => time(),
                                                               
'set_output_format'  => $remap[ $_id ]['set_output_format'],
                                                               
'set_locked_uagent'  => ( isset( $remap[ $_id ]['set_locked_uagent'] ) ) ? $remap[ $_id ]['set_locked_uagent'] : '',
                                                               
'set_hide_from_list' => 0,
                                                               
'set_master_key'     => $remap[ $_id ]['set_master_key'] );
            }
        }
        

        if ( 
count( $skins ) != count( $skinIDs ) )
        {
            
/* Grab the rest */
            
$this->DB->build( array( 'select' => '*',
                                     
'from'   => 'skin_collections',
                                     
'where'  => 'set_id IN (' . implode( ",", $skinIDs ) . ')' ) );
                                    
            
$this->DB->execute();
            
            while( 
$row = $this->DB->fetch() )
            {
                
/* Ensure settings */
                
$row['set_id']               = $setid;
                
$row['set_permissions']    = '*';
                
$row['set_hide_from_list'] = 0;
                
$row['set_css_inline']     = 1;
                
                
$skins[ $row['set_id'] ] = $row;
                
                
$setid++;
            }
        }
        
        
//-----------------------------------------
        // Grab the XML parser
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
$xml->newXMLDocument();
        
$xml->addElement( 'skinsets' );
        
        foreach( 
$skins as $id => $setData )
        {
            
$xml->addElementAsRecord( 'skinsets', 'set', $setData );
        }

        return 
$xml->fetchDocument();
    }
    
    
/**
     * Generate XML Replacements data file
     *
     * @access    public
     * @param    int            Set ID
     * @param    boolean        Just get the changes for this set (if TRUE)
     * @return    mixed    bool, or XML
     */
    
public function generateReplacementsXML( $setID=0, $setOnly=FALSE )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$replacements = array();
        
        
//-----------------------------------------
        // Grab the CSS
        //-----------------------------------------
        
        
if ( $setOnly === TRUE )
        {
            
$where = ( is_numeric( $setID ) ) ? 'replacement_set_id=' . $setID : 'replacement_master_key='' . $setID . ''';
                
            
$this->DB->build( array( 'select' => '*',
                                     
'from'   => 'skin_replacements',
                                     
'where'  => $where ) );
                                    
            
$this->DB->execute();
            
            while( 
$row = $this->DB->fetch() )
            {
                
$replacements[ $row['replacement_key'] ] = $row;
            }
        }
        else
        {
            
$replacements = $this->fetchReplacements( $setID );
        }
                
        
//-----------------------------------------
        // Grab the XML parser
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
$xml->newXMLDocument();
        
$xml->addElement( 'replacements' );
        
        foreach( 
$replacements as $key => $replacementsData )
        {
            unset( 
$replacementsData['replacement_id'] );
            unset( 
$replacementsData['replacement_added_to'] );
            unset( 
$replacementsData['theorder'] );
            unset( 
$replacementsData['SAFE_replacement_content'] );
            
            
$xml->addElementAsRecord( 'replacements', 'replacement', $replacementsData );
        }
        
        return 
$xml->fetchDocument();
    }
    
    
/**
     * Generate XML CSS data file
     *
     * @access    public
     * @param    int            Set ID
     * @param    boolean        Just get the changes for this set (if TRUE)
     * @return    mixed        bool, or XML
     */
    
public function generateCSSXML( $app_dir='core', $setID=0, $setOnly=FALSE )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$css          = array();
        
$gotSomething = FALSE;
        
        
//-----------------------------------------
        // Grab the CSS
        //-----------------------------------------

        
if ( $setOnly === TRUE AND $setID > 0 )
        {
            
$this->DB->build( array( 'select' => '*',
                                     
'from'   => 'skin_css',
                                     
'where'  => 'css_set_id=' . $setID ) );
                                    
            
$this->DB->execute();
            
            while( 
$row = $this->DB->fetch() )
            {
                
$css[ $row['css_group'] ] = $row;
            }
        }
        else
        {
            
$_css = $this->fetchCSS( $setID );
            
            
/* Remove set 0 templates */
            
if ( $setID > 0 )
            {
                if ( 
is_array( $_css ) AND count( $_css ) )
                {
                    foreach( 
$_css as $name => $cssData )
                    {
                        if ( 
$cssData['css_set_id'] > 0 )
                        {
                            
$css[ $name ] = $cssData;
                        }
                    }
                }
            }
            else
            {
                
$css = $_css;
            }
        }

        if ( ! 
is_array( $css ) OR ! count( $css ) )
        {
            
$this->_addMessage( $this->lang->words['nocsstoexport'] . $app_dir );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Grab the XML parser
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH . 'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
$xml->newXMLDocument();
        
$xml->addElement( 'css' );

        foreach( 
$css as $name => $cssData )
        {
            
/* Checking this app dir? */
            
$cssData['css_app'] = ( $cssData['css_app'] ) ? $cssData['css_app']  : 'core';
            
            if ( 
$cssData['css_app'] != $app_dir )
            {
                continue;
            }
            
            
$gotSomething = TRUE;
            
            unset( 
$cssData['css_id'] );
            unset( 
$cssData['css_added_to'] );
            unset( 
$cssData['theorder'] );
            unset( 
$cssData['_cssSize'] );
            
            
$xml->addElementAsRecord( 'css', 'cssfile', $cssData );
        }

        if ( ! 
$gotSomething )
        {
            
$this->_addMessage( $this->lang->words['nocsstoexport'] . $app_dir );
            return 
FALSE;
        }
        
        return 
$xml->fetchDocument();
    }
    
    
/**
     * Generate XML template data file
     *
     * @access    public
     * @param    string        App
     * @param    int            Set ID
     * @param    boolean        Just get the changes for this set (if TRUE)
     * @return    mixed        bool, or XML
     */
    
public function generateTemplateXML( $app, $setID=0, $setOnly=FALSE )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$templateGroups = array();
        
        
//-----------------------------------------
        // XML
        //-----------------------------------------
        
        
$infoXML = IPSLib::getAppDir(  $app ) . '/xml/information.xml';
        
        if ( ! 
is_file( $infoXML ) )
        {
            
$this->_addErrorMessage( $this->lang->words['couldnotlocate'] . $infoXML );
            return 
FALSE;
        }
        
        require_once( 
IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->load( $infoXML );
        
        foreach( 
$xml->fetchElements( 'template' ) as $template )
        {
            
$name  = $xml->fetchItem( $template );
            
$match = $xml->fetchAttribute( $template, 'match' );
        
            if ( 
$name )
            {
                
$templateGroups[ $name ] = $match;
            }
        }
        
        if ( ! 
is_array( $templateGroups ) OR ! count( $templateGroups ) )
        {
            
$this->_addMessage( sprintf( $this->lang->words['nothingtoexportforapp'], $app ) );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Fetch templates
        //-----------------------------------------
        
$templates = array();
        
        if ( 
$setOnly === TRUE AND $setID > 0 )
        {
            
$this->DB->build( array( 'select' => '*',
                                     
'from'   => 'skin_templates',
                                     
'where'  => 'template_set_id=' . $setID ) );
                                    
            
$this->DB->execute();
            
            while( 
$row = $this->DB->fetch() )
            {
                
$templates[ $row['template_group'] ][ strtolower( $row['template_name'] ) ] = $row;
            }
        }
        else
        {
            
$_templates = $this->fetchTemplates( $setID );
            
            
/* Remove set 0 templates */
            
if ( $setID > 0 )
            {
                if ( 
is_array( $_templates ) AND count( $_templates ) )
                {
                    foreach( 
$_templates as $group => $data )
                    {
                        foreach( 
$data as $name => $templateData )
                        {
                            if ( 
$templateData['template_set_id'] > 0 )
                            {
                                
$templates[ $group ][ $name ] = $templateData;
                            }
                        }
                    }
                }
            }
            else
            {
                
$templates = $_templates;
            }
        }
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
$xml->newXMLDocument();
        
$xml->addElement( 'templates', '', array( 'application' => $app, 'templategroups' => serialize( $templateGroups ) ) );
        
        if ( ! 
is_array( $templates ) OR ! count( $templates ) )
        {
            
$this->_addMessage( sprintf( $this->lang->words['nogroupsforexportapp'], $app ) );
            return 
FALSE;
        }
        
        
$added   = 0;
        
        foreach( 
$templates as $group => $data )
        {
            
$_okToGo = FALSE;
            
            foreach( 
$templateGroups as $name => $match )
            {
                if ( 
$match == 'contains' )
                {
                    if ( 
stristr( $group, $name ) )
                    {
                        
$_okToGo = TRUE;
                        break;
                    }
                }
                else if ( 
$group == $name )
                {
                    
$_okToGo = TRUE;
                }
            }
            
            
/* If this is the core app, allow any custom bits also */
            
if ( $app == 'core' )
            {
                
$_data = $data;
                
$test  = array_shift( $_data );
                
                if ( 
$test['template_user_added'] )
                {
                    
$_okToGo = TRUE;
                }
            }
        
            if ( 
$_okToGo === TRUE )
            { 
                
$xml->addElement( 'templategroup', 'templates', array( 'group' => $group ) );
            
                foreach( 
$data as $name => $templateData )
                {
                    unset( 
$templateData['theorder'] );
                    unset( 
$templateData['template_id'] );
                    unset( 
$templateData['template_set_id'] );
                    unset( 
$templateData['template_added_to'] );
                
                    
$xml->addElementAsRecord( 'templategroup', 'template', $templateData );
                    
$added++;
                }
            }
        }
        
        if ( ! 
$added )
        {
            
$this->_addMessage( $this->lang->words['nothingtoexportfor'] . $app );
            return 
FALSE;
        }
        
        return 
$xml->fetchDocument();
    }
    
    
/**
     * Generate XML Information data file
     *
     * @access    public
     * @param    int            Set ID
     * @return    string        XML
     */
    
public function generateInfoXML( $setID=0 )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$data    = array();
        
$setData = $this->fetchSkinData( $setID );
        
$version = IPSLib::fetchVersionNumber();
        
        
//-----------------------------------------
        // Grab the XML parser
        //-----------------------------------------
        
        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
$xml->newXMLDocument();
        
$xml->addElement( 'info' );
        
        
$xml->addElementAsRecord( 'info', 'data', array( 'set_name'          => $setData['set_name'],
                                                         
'set_key'           => $setData['set_key'],
                                                         
'set_author_name'   => $setData['set_author_name'],
                                                         
'set_author_url'    => $setData['set_author_url'],
                                                         
'set_output_format' => $setData['set_output_format'],
                                                         
'set_master_key'    => $setData['set_master_key'],
                                                         
'ipb_human_version' => $version['human'],
                                                         
'ipb_long_version'  => $version['long'],
                                                         
'ipb_major_version' => '3' ) );

        return 
$xml->fetchDocument();
    }
    
    
/**
     * Import CSS for a single app
     *
     * @access    public
     * @param    string        App
     * @param    string        Skin key to import
     * @param    int            Set ID
     * @return    mixed        bool, or number of items added
     */
    
public function importCSSAppXML( $app, $skinKey, $setID=0 )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$fileXML        = IPSLib::getAppDir(  $app ) . '/xml/' . $app . '_' . $skinKey . '_css.xml';
        
$return            = array( 'updateCount' => 0, 'insertCount' => 0, 'updateBits' => array(), 'insertBits' => array() );
        
$masterKeys     = $this->fetchMasterKeys();
        
        
//-----------------------------------------
        // File exists
        //-----------------------------------------
        
        
if ( ! is_file( $fileXML ) )
        {
            return 
FALSE;
        }
        
        if ( ! 
$setID and ! in_array( $skinKey, $masterKeys ) )
        {
            
/* Figure out correct set ID based on key */
            
$skinSetData = $this->DB->buildAndFetch( array( 'select' => '*',
                                                            
'from'   => 'skin_collections',
                                                            
'where'  => "set_key='" . $skinKey . "'" ) );
                                                            
            
$setID         = $skinSetData['set_id'];
            
$skinMasterKey = $skinSetData['set_master_key'];
        }
                
        
/* If this is a 'master' skin, then reset master key */
        
if ( in_array( $skinKey, $masterKeys ) )
        {
            
$skinMasterKey = $skinKey;
            
$setID         = 0;
        }
        
        
//-----------------------------------------
        // Delete all CSS if this is set ID 0
        //-----------------------------------------
        
        
if ( in_array( $skinKey, $masterKeys ) )
        {
            
$this->DB->delete( 'skin_css', 'css_set_id=0 AND css_master_key='' . $skinMasterKey . '' AND css_app=''. addslashes( $app ) . ''' );
        }
        
        
//-----------------------------------------
        // Fetch CSS
        //-----------------------------------------
        
        
$css = $this->parseCSSXML( file_get_contents( $fileXML ) );
    
        if ( 
is_array( $css ) )
        {
            foreach( 
$css as $_css )
            {
                if ( 
$_css['css_group'] )
                {
                    
$return['insertCount']++;
                    
                    if ( 
$setID )
                    {
                        
$this->DB->delete( 'skin_css', 'css_set_id=' . $setID . ' AND css_group='' . addslashes( $_css['css_group'] ) . '' AND css_app='' . addslashes( $_css['css_app'] ) . ''' );
                    }
                    
                    
$this->DB->insert( 'skin_css', array( 'css_group'       => $_css['css_group'],
                                                          
'css_content'     => $_css['css_content'],
                                                          
'css_position'    => $_css['css_position'],
                                                          
'css_updated'     => time(),
                                                          
'css_app'            => $_css['css_app'],
                                                          
'css_app_hide'    => $_css['css_app_hide'],
                                                          
'css_attributes'  => $_css['css_attributes'],
                                                          
'css_modules'        => $_css['css_modules'],
                                                          
'css_master_key'  => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '',
                                                          
'css_set_id'      => $setID,
                                                          
'css_added_to'    => $setID ) );
                }
            }
        }

        return 
$return;
    }
     
    
/**
     * Export template CSS into app dirs
     *
     * @access    public
     * @param    string        App to export into
     * @param    int         Set ID (0 / root by default )
     * @return    @e void
     */
    
public function exportCSSAppXML( $app_dir, $setID=0 )
    {
        
//-----------------------------------------
        // Get it
        //-----------------------------------------
        
        
$setData = $this->fetchSkinData( $setID );
        
$xml     = $this->generateCSSXML( $app_dir, $setID );
        
        
//-----------------------------------------
        // Attempt to write...
        //-----------------------------------------
        
        /* Set file name */
        
$file = IPSLib::getAppDir(  $app_dir ) . '/xml/' . $app_dir . '_' . $setData['set_key'] . '_css.xml';
        
        
/* Attempt to unlink first */
        
@unlink( $file );
        
        if ( 
$xml )
        {
            if ( 
is_file( $file ) AND ! IPSLib::isWritable( $file ) )
            {
                
$this->_addErrorMessage( $file . ' ' . $this->lang->words['css_isnotwritable'] );
                return 
FALSE;
            }
            
            
file_put_contents( $file, $xml );
            
            
$this->_addMessage( sprintf( $this->lang->words['csscreatedmsg'], $app_dir, $setData['set_key'] ) );
        }
    }
    
    
/**
     * Export template XML into app dirs
     *
     * @access    public
     * @param    string        App to export into
     * @param    int            [Set ID (0/root if omitted)]
     * @param    bool        Include root bits in any XML export. Default is true
     * @return    @e void
     */
    
public function exportTemplateAppXML( $app_dir, $setID=0, $setOnly=TRUE )
    {
        
//-----------------------------------------
        // Get it
        //-----------------------------------------
        
        
$setData = $this->fetchSkinData( $setID );
        
$xml     = $this->generateTemplateXML( $app_dir, $setID, $setOnly );
        
        
//-----------------------------------------
        // Attempt to write...
        //-----------------------------------------
        
        /* Set file name */
        
$file = IPSLib::getAppDir(  $app_dir ) . '/xml/' . $app_dir . '_' . $setData['set_key'] . '_templates.xml';
            
        
/* Attempt to unlink first */
        
@unlink( $file );
            
        if ( 
$xml )
        {
            if ( 
is_file( $file ) AND ! IPSLib::isWritable( $file ) )
            {
                
$this->_addErrorMessage( $file . ' ' . $this->lang->words['css_isnotwritable'] );
                return 
FALSE;
            }
            
            
file_put_contents( $file, $xml );
            
            
$this->_addMessage( sprintf( $this->lang->words['templatescreatedmsg'], $app_dir, $setData['set_key'] ) );
        }
    }
    
    
/**
     * Import a single app
     *
     * @access    public
     * @param    string        App
     * @param    string        Skin key to import
     * @param    int            Set ID
     * @param    boolean        Set the edited / added flags to 0 (from install, upgrade)
     * @return    mixed        bool, or array of info
     */
    
public function importTemplateAppXML( $app, $skinKey, $setID=0, $ignoreAddedEditedFlag=false )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$templateGroups = array();
        
$templates      = array();
        
$fileXML        = IPSLib::getAppDir(  $app ) . '/xml/' . $app . '_' . $skinKey . '_templates.xml';
        
$infoXML        = IPSLib::getAppDir(  $app ) . '/xml/information.xml';
        
$return            = array( 'updateCount' => 0, 'insertCount' => 0, 'updateBits' => array(), 'insertBits' => array() );
        
$masterKeys     = $this->fetchMasterKeys();
        
        if( ! 
is_file($fileXML) )
        {
            return 
$return;
        }
        
        if ( ! 
$setID and ! in_array( $skinKey, $masterKeys ) )
        {
            
/* Figure out correct set ID based on key */
            
$skinSetData = $this->DB->buildAndFetch( array( 'select' => '*',
                                                            
'from'   => 'skin_collections',
                                                            
'where'  => "set_key='" . $skinKey . "'" ) );
                                                            
            
$setID         = $skinSetData['set_id'];
            
$skinMasterKey = $skinSetData['set_master_key'];
        }
        
        
/* Set ignore flag correctly */
        
if ( ! empty( $skinKey ) AND in_array( $skinKey, $masterKeys ) )
        {
            
$ignoreAddedEditedFlag = true;
        }
        
        
/* If this is a 'master' skin, then reset master key */
        
if ( in_array( $skinKey, $masterKeys ) )
        {
            
$skinMasterKey = $skinKey;
            
$setID         = 0;
        }
        
        
//-----------------------------------------
        // XML
        //-----------------------------------------

        
require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/
        
$xml = new classXML( IPS_DOC_CHAR_SET );
        
        
//-----------------------------------------
        // Get information file
        //-----------------------------------------
        
        
$xml->load( $infoXML );
        
        foreach( 
$xml->fetchElements( 'template' ) as $template )
        {
            
$name  = $xml->fetchItem( $template );
            
$match = $xml->fetchAttribute( $template, 'match' );
        
            if ( 
$name )
            {
                
$templateGroups[ $name ] = $match;
            }
        }
        
        if ( ! 
is_array( $templateGroups ) OR ! count( $templateGroups ) )
        {
            
$this->_addMessage( $this->lang->words['nothingtoexportfor'] . $app );
            return 
FALSE;
        }
        
        
//-----------------------------------------
        // Fetch templates
        //-----------------------------------------
    
        
$_templates = $this->fetchTemplates( $setID        , 'allNoContent' );
        
$_MASTER    = $this->fetchTemplates( $skinMasterKey, 'allNoContent' );
        
        
//-----------------------------------------
        // Loop through...
        //-----------------------------------------
        
        
foreach( $_templates as $group => $data )
        {
            
$_okToGo = FALSE;
            
            foreach( 
$templateGroups as $name => $match )
            {
                if ( 
$match == 'contains' )
                {
                    if ( 
stristr( $group, $name ) )
                    {
                        
$_okToGo = TRUE;
                        break;
                    }
                }
                else if ( 
$group == $name )
                {
                    
$_okToGo = TRUE;
                }
            }
            
            if ( 
$_okToGo === TRUE )
            {
                foreach( 
$data as $name => $templateData )
                {
                    
$templates[ $group ][ $name ] = $templateData;
                }
            }
        }
        
        
//-----------------------------------------
        // Wipe the master skins
        //-----------------------------------------
        
        
if ( in_array( $skinKey, $masterKeys ) )
        {
            
$this->DB->delete( 'skin_templates', "template_master_key='" . $skinKey . "' AND template_group IN ('" . implode( "','", array_keys( $templates ) ) . "') AND template_user_added=0 AND template_added_to=0" );
            
            
/* Now wipe the array so we enforce creation */
            
unset( $templates );
        }
                    
        
//-----------------------------------------
        // Now grab the actual XML files
        //-----------------------------------------

        
$xml->load( $fileXML );

        foreach( 
$xml->fetchElements( 'template' ) as $templatexml )
        {
            
$data = $xml->fetchElementsFromRecord( $templatexml );
            
            
/* Figure out if this is added by a user or not */
            
if ( $ignoreAddedEditedFlag === TRUE )
            {
                
$isAdded  = 0;
                
$isEdited = 0;
            }
            else
            {
                
$isAdded  = ( is_array( $_MASTER[ $data['template_group'] ][ strtolower( $data['template_name'] ) ] ) AND ! $_MASTER[ $data['template_group'] ][ strtolower( $data['template_name'] ) ]['template_user_added'] ) ? 0 : 1;
                
$isEdited = 1;
            }
            
            if ( 
is_array( $templates[ $data['template_group'] ][ strtolower( $data['template_name'] ) ] ) AND $templates[ $data['template_group'] ][ strtolower( $data['template_name'] ) ]['template_set_id'] == $setID )
            {
                
/* Update.. */
                
$return['updateCount']++;
                
$return['updateBits'][] = $data['template_name'];
                
$this->DB->update( 'skin_templates', array( 'template_content'     => $data['template_content'],
                                                            
'template_data'        => $data['template_data'],
                                                            
'template_user_edited' => $isEdited,
                                                            
'template_user_added'  => $isAdded,
                                                            
'template_master_key'  => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '',
                                                            
'template_updated'     => time() ), 'template_set_id=' . $setID . " AND template_group='" . $data['template_group'] . "' AND template_name='" . $data['template_name'] . "'" );
            }
            else
            {
                
/* Add... */
                
$return['insertCount']++;
                
$return['insertBits'][] = $data['template_name'];
                
$this->DB->insert( 'skin_templates', array( 'template_set_id'      => $setID,
                                                            
'template_group'       => $data['template_group'],
                                                            
'template_content'     => $data['template_content'],
                                                            
'template_name'        => $data['template_name'],
                                                            
'template_data'        => $data['template_data'],
                                                            
'template_removable'   => ( $setID ) ? $data['template_removable'] : 0,
                                                            
'template_added_to'    => $setID,
                                                            
'template_user_edited' => $isEdited,
                                                            
'template_user_added'  => $isAdded,
                                                            
'template_master_key'  => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '',
                                                            
'template_updated'     => time() ) );
            }
        }

        return 
$return;
    }
    
}
Онлайн: 2
Реклама