Вход Регистрация
Файл: IPBMafia.ru_IPB_3.4.6_Final_Rus _Nulled/board/upload/admin/sources/classes/skins/skinFunctions.php
Строк: 2176
<?php

/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.4.6
 * Skin Functions
 * Last Updated: $Date: 2013-05-07 22:02:49 -0400 (Tue, 07 May 2013) $
 * </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: 12236 $
 *
 */

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 
skinFunctions
{
    
/**#@+
     * Registry objects
     *
     * @access    protected
     * @var        object
     */
    
protected $registry;
    protected 
$DB;
    protected 
$settings;
    protected 
$request;
    protected 
$lang;
    protected 
$member;
    protected 
$memberData;
    protected 
$cache;
    protected 
$caches;
    
/**#@-*/

    /**
     * Tier Class
     *
     * @access    public
     * @var        object
     */
    
public $recursiveTiers;

    
/**
     * Template count
     * Maintains an array: [skin_set_id][group_name][count]
     *
     * @access protected
     * @var    array
     */
    
protected $_templateCount;

    
/**
     * Error handle
     *
     * @access    protected
     * @var        array
     */
    
protected $_errorMsgs = array();

    
/**
     * Message handle
     *
     * @access    protected
     * @var        array
     */
    
protected $_generalMsgs = array();
    
    
/**
     * IN_DEV remap data
     *
     * @access    public
     * @var        array
     */
    
public $remapData = array();
    
    
/**
     * Set cache
     * @var protected
     */
    
protected $_seenSet = array();
    
    
/**
     * Constructor
     *
     * @access    public
     * @param    object        Registry object
     * @return    @e void
     */
    
public function __constructipsRegistry $registry )
    {
        
//-----------------------------------------
        // Make object
        //-----------------------------------------

        
$this->registry   =  $registry;
        
$this->DB          =  $this->registry->DB();
        
$this->settings   =& $this->registry->fetchSettings();
        
$this->request    =& $this->registry->fetchRequest();
        
$this->member     =  $this->registry->member();
        
$this->memberData =& $this->registry->member()->fetchMemberData();
        
$this->cache      =  $this->registry->cache();
        
$this->caches     =& $this->registry->cache()->fetchCaches();
        
$this->lang       $this->registry->class_localization;
        
        
$this->registry->class_localization->loadLanguageFile( array( 'admin_templates' ), 'core' );
        
        
//-----------------------------------------
        // IN_DEV on?
        //-----------------------------------------
        
        
if ( $this->registry->isClassLoaded'output' ) )
        {
            
$this->remapData $this->registry->output->buildRemapDataTRUE );
        }
        
        
//-----------------------------------------
        // Load tier class and init it
        //-----------------------------------------

        
require_once( IPS_ROOT_PATH 'sources/classes/tiers/recursiveTiers.php' );/*noLibHook*/

        
$this->recursiveTiers = new recursiveTiers$registry, array(   'sqlPrimaryID'    => 'set_id',
                                                                        
'sqlParentID'    => 'set_parent_id',
                                                                        
'sqlTitle'        => 'set_name',
                                                                        
'sqlOrder'        => 'set_parent_id, set_id',
                                                                        
'sqlTable'        => 'skin_collections',
                                                                        
'customMethod'    => '_buildSkinTiers' ) );
    }

    
/**
     * Return recursive tiers handle
     *
     * @access public
     * @return object
     */
    
public function getTiersFunction()
    {
        return 
$this->recursiveTiers;
    }
    
    
/**
     * Make this skin default
     * @param int $set_id
     */
    
public function makeDefault$set_id )
    {
        
$setData $this->fetchSkinData$set_idtrue );
        
        
/* Make all others non default */
        
$this->DB->update'skin_collections', array( 'set_is_default' => ), 'set_id != ' $set_id ' AND set_output_format='' . $setData['set_output_format'] . ''' );
        
        
/* Attempt to see if we have any other skin called 'default' */
        /* Not using this currently as it causes complications in other areas */
        /*
        $default = $this->DB->buildAndFetch( array( 'select' => 'set_id', 
                                                    'from'   => 'skin_collections',
                                                    'where'  => 'set_key='default' AND set_output_format='' . $setData['set_output_format'] . ''' ) );
        if ( $set_id != $default['set_id'] )
        {
            $this->DB->update( 'skin_collections', array( 'set_key' => IPS_UNIX_TIME_NOW ), 'set_id = ' . $default['set_id'] );
        }
        */
        /* Make this default */
        
$this->DB->update'skin_collections', array( 'set_is_default' => 1/*, 'set_key' => 'default'*/ ), 'set_id = ' $set_id ' AND set_output_format='' . $setData['set_output_format'] . ''' );
    }
    
    
/**
     * Fetch highest order
     *
     * @access    public
     * @return    int
     */
    
public function fetchHighestSetPosition()
    {
        
$bill $this->DB->buildAndFetch( array( 'select' => 'MAX(set_order) as and_ted',
                                                 
'from'   => 'skin_collections' ) );
                                                 
        
        
/* Excellent! (guitar solo) */
        
return intval$bill['and_ted'] );
    }
    
    
/**
     * Can we use the merge system?
     *
     * @access    public
     * @return    int
     */
    
public function canUseMergeSystem()
    {
        
$c    $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as ount',
                                                 
'from'   => 'skin_templates_previous' ) );
                                                 
        return ( 
$c['ount'] ) ? true false;
    }

    
    
/**
     * Fetch master template keys
     *
     * @access    public
     * @return    arraya
     */
    
public function fetchMasterKeys()
    {
        if ( 
is_array$this->remapData ) AND is_array$this->remapData['masterKeys'] ) )
        {
            return 
$this->remapData['masterKeys'];
        }
        else
        {
            
$REMAP = array();
            require( 
IPS_CACHE_PATH 'cache/skin_cache/masterMap.php' );/*noLibHook*/

            
if ( is_array($REMAP) && count($REMAP) )
            {
                
$this->remapData = array( 'masterKeys' => $REMAP['masterKeys'] );
            }
        }
        
        return 
$this->remapData['masterKeys'];
    }

    
/**
     * Returns a skin set ID based on a key
     * @param string     $key
     * @param boolean    $ignoreMasterKeys
     */
    
public function fetchSetIdByKey$key$ignoreMasterKeys=false )
    {
        
$masterKeys $this->fetchMasterKeys();
        
        if ( 
in_array$key$masterKeys ) && $ignoreMasterKeys === false )
        {
            
/* Default master keys are always 0 */
            
return 0;
        }
        
        if ( ! 
$this->_seenSet'k-' $key ] )
        {
            
$this->_seenSet'k-' $key ] = $this->DB->buildAndFetch( array( 'select' => 'set_id',
                                                                                 
'from'   => 'skin_collections',
                                                                                 
'where'  => 'set_key='' . addslashes( $key ) . ''' ) );
        }
        
        return ( 
$this->_seenSet'k-' $key ]['set_id'] ) ? $this->_seenSet'k-' $key ]['set_id'] : 0;
    }
    
    
/**
     * Returns a skin set key based on a id
     * @param string $key
     */
    
public function fetchSetKeyById$id )
    {
        
$masterKeys $this->fetchMasterKeys();
        
        if ( 
$id == )
        {
            
/* Default master keys are always 0 */
            
return '';
        }
        
        if ( ! 
$this->_seenSet'i-' $id ] )
        {
            
$this->_seenSet'i-' $id ] = $this->DB->buildAndFetch( array( 'select' => 'set_key',
                                                                                
'from'   => 'skin_collections',
                                                                                
'where'  => 'set_id=' intval$id ) ) );
        }
        
        return ( 
$this->_seenSet'i-' $id ]['set_key'] ) ? $this->_seenSet'i-' $id ]['set_key'] : 0;
    }
    
    
/**
     * Determine if the skin set is a "master" set
     *
     * @param    mixed    $id        Skin set key or skin set id
     * @return    bool    True if this is a master set, otherwise false
     */
    
public function isMasterSet$id )
    {
        
$key    is_numeric($id) ? $this->fetchSetKeyById$id ) : $id;
        
        return 
in_array$key$this->remapData['masterKeys'] );
    }
    
    
/**
     * Search template bits
     *
     * @access        public
     * @param        int            Template set id to search
     * @param        string        String to search
     * @param        boolean        Is regex
     * @param        boolean        Search all parents including master template set
     * @return        array         array( 'searchCount' => int, 'matchCount' => int, 'matches' => array )
     * Exception Codes
     * REGEX_INCORRECT            Regex is not valid
     */
    
public function searchTemplates$setID$searchString$isRegex=FALSE$searchParents=FALSE )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------
        
        
$searchString IPSText::stripslashes$searchString );
        
$regexString  str_replace'#''#'str_replace'"''"'$searchString ) );
        
$_templates   = array();
        
$_matches     = array();
        
$_matchCount  0;
        
$return          = array( 'searchCount' => 0'matchCount' => 0'matches' => array() );
        
        
/* Test Regex */
        
if ( $isRegex )
        {
            
ob_start();
            eval( 
"preg_match( "#{$regexString}#i", 'sometexthere' );");
            
$return ob_get_contents();
            
ob_end_clean();
            
            if ( 
$return )
            {
                throw new 
Exception("REGEX_INCORRECT");
            }
        }
        
        
/* Grab templates to search in */
        
if ( $searchParents )
        {
            
$_templates $this->fetchTemplates$setID );
        }
        else
        {
            
            
$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;
            }
        }
        
        
/* Got anything? */
        
if ( ! count$_templates ) )
        {
            return 
$return;
        }
        
        
$_templateCount 0;
        
        
/* You may continue... */
        
foreach( $_templates as $_group => $_gdata )
        {
            foreach( 
$_gdata as $_name => $_data )
            {
                if ( 
$isRegex )
                {
                    if ( 
preg_match"#{$regexString}#i"$_data['template_content'] ) )
                    {
                        
$_matches$_group ][ $_name ] = $_data;
                        
$_matchCount++;
                    }
                }
                else if ( 
stristr$_data['template_content'], $searchString ) )
                {
                    
$_matches$_group ][ $_name ] = $_data;
                    
$_matchCount++;
                }
                
                
$_templateCount++;
            }
        }
        
        
/* Return to sender */
        
return array( 'searchCount' => $_templateCount'matchCount' => $_matchCount'matches' => $_matches );
    }
    
    
/**
     * Returns no. of modified template bits for
     * the skin (and or group)
     *
     * @access    public
     * @param    int        Template Set ID
     * @param    int        [Optional: Template Group]
     * @return    array     Array of data
     */
    
public function fetchModifiedTemplateCount$setID$groupName='' )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$count 0;

        
//-----------------------------------------
        // Check...
        //-----------------------------------------

        
if ( ! $setID )
        {
            return 
0;
        }

        
//-----------------------------------------
        // Get 'em
        //-----------------------------------------

        
if ( $groupName )
        {
            if ( 
count$this->_templateCount ) )
            {
                return 
intval$this->_templateCount$setID ][ $groupName ]['count'] );
            }
            else
            {
                
$count $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
                                                                 
'from'   => 'skin_templates',
                                                                 
'where'  => 'template_set_id=' $setID ' AND template_group=''. $groupName . ''' ) );

                return 
intval$count['count'] );
            }
        }
        else
        {
            if ( 
count$this->_templateCount ) )
            {
                foreach( 
$this->_templateCount$setID ] as $group => $data )
                {
                    
$count += intval$data['count'] );
                }

                return 
intval$count );
            }
            else
            {
                
$count $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
                                                                 
'from'   => 'skin_templates',
                                                                 
'where'  => 'template_set_id=' $setID ) );

                return 
intval$count['count'] );
            }
        }
    }

    
/**
     * Reset error handle
     *
     * @access    protected
     * @return    @e void
     */
    
final protected function _resetErrorHandle()
    {
        
$this->_errorMsgs = array();
    }

    
/**
     * Add an error message
     *
     * @access    protected
     * @param    string        Error message to add
     * @return    @e void
     */
    
final protected function _addErrorMessage$error )
    {
        
$this->_errorMsgs[] = $error;
    }

    
/**
     * Fetch error messages
     *
     * @access     public
     * @param    boolean        Always return an array
     * @return     mixed         Array of messages or (FALSE/empty array)
     */
    
public function fetchErrorMessages$alwaysAnArray=FALSE )
    {
        return ( 
count$this->_errorMsgs ) ) ? $this->_errorMsgs : ( ($alwaysAnArray === TRUE) ? array() :  FALSE );
    }

    
/**
     * Reset error handle
     *
     * @access    protected
     * @return    @e void
     */
    
final protected function _resetMessageHandle()
    {
        
$this->_generalMsgs = array();
    }

    
/**
     * Add an error message
     *
     * @access    protected
     * @param    string        Error message to add
     * @return    @e void
     */
    
final protected function _addMessage$error )
    {
        
$this->_generalMsgs[] = $error;
    }

    
/**
     * Fetch error messages
     *
     * @access     public
     * @param    boolean        Always return an array
     * @return     mixed         Array of messages or (FALSE/empty array)
     */
    
public function fetchMessages$alwaysAnArray=FALSE )
    {
        return ( 
count$this->_generalMsgs ) ) ? $this->_generalMsgs : ( ($alwaysAnArray === TRUE) ? array() :  FALSE );
    }

    
/**
     * Load a 'master_skin' template file. Used when developing
     *
     * @access    public
     * @param    string        Name of skin file
     * @return    @e void        Evals the skin to add the class in memory
     */
    
public function loadMasterSkinTemplate$name$id )
    {
        if ( ! 
count$this->remapData ) )
        {
            
$this->remapData $this->registry->output->buildRemapData();
        }
        
        
$_id = ( $id == ) ? $this->remapData['inDevDefault'] : $id;
        
        
$_dir $this->remapData['templates'][ $_id ];
    
        if( ! 
is_file(IPS_CACHE_PATH."cache/skin_cache/" $_dir "/".$name.".php") )
        {
            return;
        }
        
        
//-----------------------------------------
        // Get data...
        //-----------------------------------------

        
$data implode''fileIPS_CACHE_PATH."cache/skin_cache/" $_dir "/".$name.".php" ) );

        
//-----------------------------------------
        // Get template class
        //-----------------------------------------

        
$toeval $this->registry->templateEngine->convertCacheToEval$data$name '_' $id );
        
$showme = ( strstr$data'{{{SHOWME}}}' ) ) ? $name '';

        if ( ! 
class_exists$name '_' $id ) )
        {
            
ob_start();
            eval(
$toeval);
            
$result ob_get_contents();
             
ob_end_clean();

            if ( 
strstr$result"Parse error" ) OR strstr$result'Catchable fatal error:' ) OR $showme == $name )
            {    
                
IPSDebug::showTemplateError$result$toeval );
            }
        }
    }

    
/**
     * Returns whether or not a skin set is suitable for removal
     *
     * @access    public
     * @param    int        Skin set ID
     * @return    boolean    (True OK to remove, false NOT OK to remove)
     */
    
public function canRemoveSet$setID )
    {
        
$skinSetData  $this->fetchSkinData$setID );

        if ( 
$skinSetData['set_is_default'] )
        {
            return 
FALSE;
        }

        
$allSkinCount $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
                                                         
'from'   => 'skin_collections',
                                                         
'where'  => 'set_parent_id=' $setID ) );

        if ( 
$allSkinCount['count'] >= )
        {
            return 
FALSE;
        }
        
        
/* Root skin? */
        
if ( in_array$setID$this->remapData['masterKeys'] ) )
        {
            return 
FALSE;
        }

        return 
TRUE;
    }

    
/**
     * Removes a skin set
     *
     * @access    public
     * @param    int        Skin set ID
     * @param    bool    Force, even if it is not removable
     * @return    boolean    (True OK to remove, false NOT OK to remove)
     */
    
public function removeSet$setID$force=false )
    {
        
$skinSetData  $this->fetchSkinData$setID );

        if ( 
$force !== TRUE AND $this->canRemoveSet$setID ) !== TRUE )
        {
            return 
FALSE;
        }

        
/* Update any children */
        
$this->DB->update'skin_collections', array( 'set_parent_id' => ), 'set_parent_id=' $setID );

        
/* Update any members */
        
$this->DB->update'members', array( 'skin' => ), 'skin=' $setID );

        
/* Update any forums */
        
$this->DB->update'forums', array( 'skin_id' => ), 'skin_id=' $setID );

        
/* Delete skin set */
        
$this->DB->delete'skin_collections''set_id=' $setID );

        
/* Delete Templates */
        
$this->DB->delete'skin_templates''template_set_id=' $setID );

        
/* Delete Replacements */
        
$this->DB->delete'skin_replacements''replacement_set_id=' $setID );

        
/* Delete CSS */
        
$this->DB->delete'skin_css''css_set_id=' $setID );

        
/* Delete Caches */
        
$this->DB->delete'skin_templates_cache''template_set_id=' $setID );

        
/* Delete URL Mapping */
        
$this->DB->delete'skin_url_mapping''map_skin_set_id=' $setID );

        
/* Delete CSS Files */
        
$classToLoad    IPSLib::loadLibraryIPS_KERNEL_PATH '/classFileManagement.php''classFileManagement' );
        
$fileManagement    = new $classToLoad();

        
$fileManagement->removeDirectoryDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_css/css_' $setID );

        
/* Delete PHP Cache Files */
        
$fileManagement->removeDirectoryIPS_CACHE_PATH 'cache/skin_cache/cacheid_' $setID );
        
        
/* Delete any diff/merge sessions */
        
$this->DB->build( array( 'select' => '*',
                                 
'from'   => 'skin_merge_session',
                                 
'where'  => 'merge_set_id=' $setID ) );
                                 
        
$o $this->DB->execute();
        
        while( 
$row $this->DB->fetch$o ) )
        {
            
/* Delete 'em */
            
$this->DB->delete('skin_merge_session''merge_id=' $row['merge_id'] );
            
$this->DB->delete('skin_merge_changes''change_session_id=' $row['merge_id'] );
        }

        
/* Generator stuff */
        
$this->DB->build( array( 'select' => '*',
                                 
'from'   => 'skin_generator_sessions',
                                 
'where'  => 'sg_skin_set_id=' $setID ) );
                                 
        
$o $this->DB->execute();
        
        while( 
$row $this->DB->fetch$o ) )
        {
            
/* Delete 'em */
            
$this->DB->delete('skin_generator_sessions'"sg_session_id='" $row['sg_session_id'] . "'" );
            
            
IPSMember::save$row['sg_member_id'], array( 'core' => array( 'bw_using_skin_gen' => ) ) );
        }
        
        
        
/* Rebuild Tree Information */
        
$this->rebuildTreeInformation();

        
/* Rebuild Skin Set Caches */
        
if ( class_exists'skinCaching' ) )
        {
            
$this->rebuildSkinSetsCache();
            
$this->rebuildURLMapCache();
            
$this->cache->putWithCacheLib'Skin_Store_' $setID, array(), );
        }    
        
        return 
TRUE;
    }

    
/**
     * Rebuild parent and child tree information
     *
     * @access    public
     * @param    int        [Optional Skin set id to rebuild. If no value given, all skin sets are rebuilt]
     * @return    boolean
     */
    
public function rebuildTreeInformation$setID=NULL )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$_where = ( $setID !== NULL ) ? 'set_id=' $setID '';
        
        
/* Rebuild tiers to ensure cache isn't stale after a new set has been added */
        
$this->caches['skinsets'] = array();
        
$this->recursiveTiers->rebuildTiers();
        
        
//-----------------------------------------
        // Grab skins and loop through 'em
        //-----------------------------------------

        
$this->DB->build( array( 'select' => '*',
                                 
'from'   => 'skin_collections',
                                 
'where'  => $_where,
                                 
'order'  => 'set_id ASC' ) );

        
$outer $this->DB->execute();

        while( 
$row $this->DB->fetch$outer ) )
        {
            
$_parents  $this->recursiveTiers->fetchItemParents$row['set_id'] );
            
$_children $this->recursiveTiers->fetchItemChildren$row['set_id'] );
            
            
$this->DB->update'skin_collections', array( 'set_parent_array' => serialize( ( is_array$_parents ) ) ? $_parents : array() ),
                                                          
'set_child_array'  => serialize( ( is_array$_children ) ) ? $_children : array() ) ), 'set_id=' $row['set_id'] );

            
            
/* Reset master key - parents */
            
if( count($_parents) AND $row['set_id'] )
            {
                
$_p            $_parents;
                
$_id         array_pop$_p );
                
$rootParent $this->fetchSkinData$_idtrue );
                
                
/* If no parent, we must be a parent, then */
                
if ( ! $rootParent['set_id'] )
                {
                    
$rootParent $this->fetchSkinData$setIDtrue );
                }
                
                
$this->DB->update'skin_collections', array( 'set_master_key' => ( $rootParent['set_master_key'] ) ? $rootParent['set_master_key'] : 'root' ), 'set_id IN (' implode','$_parents ) . ')' );
            }
            
            
/* Reset master key - children */
            
if( count($_children) AND $row['set_id'] )
            {
                if ( ! 
is_array$rootParent ) )
                {
                    
$_p            $_parents;
                    
$_id         array_pop$_p );
                    
$rootParent $this->fetchSkinData$_idtrue );
                    
                    
/* If no parent, we must be a parent, then */
                    
if ( ! $rootParent['set_id'] )
                    {
                        
$rootParent $this->fetchSkinData$setIDtrue );
                    }

                }
                
                
$this->DB->update'skin_collections', array( 'set_master_key' => ( $rootParent['set_master_key'] ) ? $rootParent['set_master_key'] : 'root' ), 'set_id IN (' implode','$_children ) . ')' );
            }
            
            if( 
count($_parents) AND $setID )
            {
                foreach( 
$_parents as $parent )
                {
                    
$this->rebuildTreeInformation$parent );
                }
            }
        }
        
        return 
TRUE;
    }

    
/**
     * Fetch replacements from the tree
     * Very simple little function to return the replacements for a particular skin set
     * Figures out all the inheritence and stuff for you. It's good like that
     *
     * @access    public
     * @param    int            Skin set ID
     * @return    array         Array of css data: array[ 'replacement_key' => [ 'replacement_id' => ..., 'replacement_key' => ... , 'replacement_content' => ... 'replacement_set_id' => ..., 'replacement_added_to' => .... ]
     * <code>
     * Usage:
     * $replacementData = $skinFunctions->fetchReplacements( 1 );
     *
     * foreach( $replacementData as $key => $data )
     * {
     *    print $key . ' contains: ' . $data['replacement_content'];
     * }
     * </code>
     */
    
public function fetchReplacements$setID )
    {
        
$replacements = array();
        
        
//-----------------------------------------
        // Try and get the skin from the cache
        //-----------------------------------------
        
        /* Did we pass a master key? - all root skins are 0  */
        
if ( ! is_numeric$setID ) )
        {
            
$skinSetData = array( 'set_id'          => 0,
                                  
'set_master_key'  => $setID,
                                  
'set_key'            => $setID,
                                  
'_isMaster'        => 1,
                                  
'_parentTree'     => array(),
                                  
'_childTree'      => array(),
                                  
'_userAgents'     => array(),
                                  
'_cssGroupsArray' => array() );
        }
        else
        {        
            
$skinSetData $this->fetchSkinData$setID );
        }
        
        
/* Did we get a skin set? */
        
if ( ! isset( $skinSetData['_parentTree'] ) OR ! is_array$skinSetData['_parentTree'] ) )
        {
            return array();
        }
        
        
//-----------------------------------------
        // Push root ID onto the END of the parent array
        //-----------------------------------------

        
array_push$skinSetData['_parentTree'], );

        
//-----------------------------------------
        // Push the current skin set ID onto the beginnging
        //-----------------------------------------

        
if ( is_numeric$setID ) )
        {
            
array_unshift$skinSetData['_parentTree'], $setID );
        }
    
        
/* We want to capture only this set's master bits */
        
$where ' AND ( ( replacement_set_id > 0 AND ( replacement_master_key='' OR replacement_master_key IS NULL ) ) OR ( replacement_set_id=0 AND replacement_master_key='' . $skinSetData['set_master_key'] . '' ) )';
        
        
//-----------------------------------------
        // Push root ID onto the END of the parent array
        //-----------------------------------------

        
array_push$skinSetData['_parentTree'], );

        
//-----------------------------------------
        // Push the current skin set ID onto the beginnging
        //-----------------------------------------

        
if ( is_numeric$setID ) )
        {
            
array_unshift$skinSetData['_parentTree'], $setID );
        }
        
        
//-----------------------------------------
        // Geddit
        //-----------------------------------------

        
$this->DB->build( array( 'select'    => '*,' .
                                                   
$this->DB->buildInstring"," implode","$skinSetData['_parentTree'] ) . ",",
                                                   
$this->DB->buildConcat( array( array( ',''string' ), array( 'replacement_set_id' ), array( ',''string' ) ) ) ) . ' as theorder',
                                        
'from'    => 'skin_replacements',
                                        
'where'    => "replacement_set_id IN (" implode","$skinSetData['_parentTree'] ) .")" $where,
                                        
'order'    => 'replacement_key ASC, theorder DESC' ) );

        
$i $this->DB->execute();

        while( 
$row $this->DB->fetch$i ) )
        {
            
$row['SAFE_replacement_content'] = IPSText::textToForm$row['replacement_content'] );
            
$replacements$row['replacement_key'] ] = $row;
            
// Matt, the above is not consistent with the .inc file, so I'm changing it for now'
            // RIkki: There is loads more data needed, like set_id, original set ID, etc, so changing it back :p
            //$replacements[ $row['replacement_key'] ] = $row['replacement_content'];
        
}

        return 
$replacements;
    }

    
/**
     * Save replacement after edit
     *
     * @access    public
     * @param    int            Replacement ID
     * @param    int            Replacement Set ID
     * @param    string        Replacement content
     * @param    string        Replacement key
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * NO_SUCH_REPLACEMENT:        Could not locate replacement
     * REPLACEMENT_EXISTS:         Could not rename replacement
     * </code>
     */
    
public function saveReplacementFromEdit$replacementID$setID$replacement_content$replacement_key )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$replacementID       intval$replacementID );
        
$replacement_key     IPSText::alphanumericalClean$replacement_key );
        
$replacement_content IPSText::formToText$replacement_content );

        
//-----------------------------------------
        // Fetch replacement data
        //-----------------------------------------

        
$replacement $this->DB->buildAndFetch( array( 'select' => '*',
                                                        
'from'   => 'skin_replacements',
                                                           
'where'  => 'replacement_id=' $replacementID ) );

        if ( ! 
$replacement['replacement_id'] )
        {
            throw new 
Exception'NO_SUCH_REPLACEMENT' );
        }

        
//-----------------------------------------
        // Group?
        //-----------------------------------------

        
if ( $replacement['replacement_added_to'] == $setID )
        {
            if ( 
$replacement['replacement_key'] != $replacement_key )
            {
                
$replacementTest $this->DB->buildAndFetch( array( 'select' => '*',
                                                                       
'from'   => 'skin_replacements',
                                                                    
'where'  => 'replacement_set_id=' $setID ' AND replacement_key='' . $replacement_key . ''' ) );

                if ( 
$replacementTest['replacement_id'] )
                {
                    throw new 
Exception"REPLACEMENT_EXISTS" );
                }
            }
        }
        else
        {
            
$replacement_group $replacement['replacement_group'];
        }

        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Same set?
        //-----------------------------------------

        
if ( $setID == $replacement['replacement_set_id'] )
        {
            
$this->DB->update'skin_replacements', array( 'replacement_content'  => $replacement_content,
                                                               
'replacement_key'      => $replacement_key,
                                                             ), 
'replacement_id=' $replacementID );

            
$replacement_id_new $replacementID;
        }
        else
        {
            
$this->DB->insert'skin_replacements', array( 'replacement_set_id'   => $setID,
                                                               
'replacement_content'  => $replacement_content,
                                                               
'replacement_key'      => $replacement_key,
                                                               
'replacement_added_to' => $replacement['replacement_added_to'] ) );

            
$replacement_id_new $this->DB->getInsertId();
        }

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildReplacementsCache$setID );

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $replacement_id_new;
    }

    
/**
     * Save replacement after add
     *
     * @access    public
     * @param    int            Replacement Set ID
     * @param    string        Replacement content
     * @param    string        Replacement key
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * REPLACEMENT_EXISTS:         Could not rename replacement
     * </code>
     */
    
public function saveReplacementFromAdd$setID$replacement_content$replacement_key )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$replacementID       intval$replacementID );
        
$replacement_key     IPSText::alphanumericalClean$replacement_key );
        
$replacement_content IPSText::formToText$replacement_content );

        
//-----------------------------------------
        // Goddit?
        //-----------------------------------------

        
$replacementTest $this->DB->buildAndFetch( array( 'select' => '*',
                                                                      
'from'   => 'skin_replacements',
                                                                   
'where'  => 'replacement_set_id=' $setID ' AND replacement_key='' . $replacement_key . ''' ) );

        if ( 
$replacementTest['replacement_id'] )
        {
            throw new 
Exception"REPLACEMENT_EXISTS" );
        }

        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Save set?
        //-----------------------------------------

        
$this->DB->insert'skin_replacements', array( 'replacement_set_id'   => $setID,
                                                           
'replacement_content'  => $replacement_content,
                                                           
'replacement_key'      => $replacement_key,
                                                           
'replacement_added_to' => $setID ) );

        
$replacement_id_new $this->DB->getInsertId();


        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildReplacementsCache$setID );

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $replacement_id_new;
    }

    
/**
     * Reverts / Removes Replacement
     *
     * @access    public
     * @param    int            Replacement ID
     * @param    int            Template Set ID
     * @return    array         All replacements for this skin set
     * <code>
     * Exception Codes:
     * NO_SUCH_REPLACEMENT:            Could not locate replacement id#
     * CANNOT_REMOVE:                 Cannot revert / remove the css
     * </code>
     */
    
public function revertReplacement$replacementID$setID )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$replacementID intval$replacementID );
        
        
//-----------------------------------------
        // Fetch replacement data
        //-----------------------------------------

        
$replacement $this->DB->buildAndFetch( array( 'select' => '*',
                                                        
'from'   => 'skin_replacements',
                                                           
'where'  => 'replacement_id=' $replacementID ) );

        if ( ! 
$replacement['replacement_id'] )
        {
            throw new 
Exception'NO_SUCH_REPLACEMENT' );
        }

        
//-----------------------------------------
        // Is this a master skin bit?
        //-----------------------------------------

        
if ( $replacement['replacement_set_id'] == AND $replacement['replacement_added_to'] == )
        {
            throw new 
Exception"CANNOT_REMOVE");
        }

        
//-----------------------------------------
        // Remove it...
        //-----------------------------------------

        
if ( $replacement['replacement_added_to'] == $setID  )
        {
            
# remove it from ALL template sets
            
$this->DB->delete'skin_replacements'"replacement_key='" $replacement['replacement_key'] . "'" );
        }
        else
        {
            
$this->DB->delete'skin_replacements''replacement_id=' $replacementID );
        }

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildReplacementsCache$setID );

        
//-----------------------------------------
        // Grab the next template bit inline...
        //-----------------------------------------

        
$replacements $this->fetchReplacements$setID );

        
//-----------------------------------------
        // Reeee-turn
        //-----------------------------------------

        
return $replacements;
    }

    
/**
     * Fetch CSS from the tree
     * Very simple little function to return the CSS for a particular skin set
     * Figures out all the inheritence and stuff for you. It's good like that
     *
     * @access    public
     * @param    int            Skin set ID
     * @param    boolean     Parse data (TRUE is default). Adds elements into the array, such as '_cssSize', etc
     * @param    boolean        Skip any 'removed' CSS files.
     * @return    array         Array of css data: array[ 'css_group' => [ 'css_id' => ..., 'css_group' => ... , 'css_content' => ... 'css_position' => ..., 'css_set_id' => .... ]
     * <code>
     * Usage:
     * $cssData = $skinFunctions->fetchCSS( 1 );
     *
     * foreach( $cssData as $group_name => $data )
     * {
     *    print $data['css_group'] . ' contains: ' . $data['css_content'];
     * }
     * </code>
     */
    
public function fetchCSS$setID$parse=TRUE$skipRemoved=TRUE )
    {
        
$css                        = array();
        
$skip                        = array();
        
$where                        '';
        
        
/* Did we pass a master key? - all root skins are 0  */
        
if ( ! is_numeric$setID ) )
        {
            
$skinSetData = array( 'set_id'          => 0,
                                  
'set_master_key'  => $setID,
                                  
'set_key'            => $setID,
                                  
'_isMaster'        => 1,
                                  
'_parentTree'     => array(),
                                  
'_childTree'      => array(),
                                  
'_userAgents'     => array(),
                                  
'_cssGroupsArray' => array() );
        }
        else
        {        
            
$skinSetData                $this->fetchSkinData$setID );
            
$skinSetData['_isMaster']    = $skinSetData['_isMaster'] ? $skinSetData['_isMaster'] : 0;
        }
        
        
/* Did we get a skin set? */
        
if ( ! isset( $skinSetData['_parentTree'] ) OR ! is_array$skinSetData['_parentTree'] ) )
        {
            return array();
        }
        
        
//-----------------------------------------
        // Push root ID onto the END of the parent array
        //-----------------------------------------

        
array_push$skinSetData['_parentTree'], );

        
//-----------------------------------------
        // Push the current skin set ID onto the beginnging
        //-----------------------------------------

        
if ( is_numeric$setID ) )
        {
            
array_unshift$skinSetData['_parentTree'], $setID );
        }
    
        
/* We want to capture only this set's master bits */
        
$where ' AND ( ( css_set_id > 0 AND ( css_master_key='' OR css_master_key IS NULL ) ) OR ( css_set_id=0 AND css_master_key='' . $skinSetData['set_master_key'] . '' ) )';

        
//-----------------------------------------
        // Geddit
        //-----------------------------------------

        
$this->DB->build( array( 'select'    => '*,' .
                                                   
$this->DB->buildInstring"," implode","$skinSetData['_parentTree'] ) . ",",
                                                   
$this->DB->buildConcat( array( array( ',''string' ), array( 'css_set_id' ), array( ',''string' ) ) ) ) . ' as theorder',
                                 
'from'        => 'skin_css',
                                 
'where'    => "css_set_id IN (" implode","$skinSetData['_parentTree'] ) .")" $where,
                                  
'order'    => 'css_group, theorder DESC' ) );

        
$i $this->DB->execute();

        while( 
$row $this->DB->fetch$i ) )
        {
            
/* skipping this group? */
            
if ( in_array$row['css_group'], $skip ) )
            {
                continue;
            }
            
            if ( 
$parse === TRUE )
            {
                
$row['_cssSize'] = IPSLib::sizeFormatIPSLib::strlenToBytesstrlen$row['css_content'] ) ) );
            }
            
            
/* CSS has been removed up the tree? */
            
if ( $row['css_removed'] AND $skipRemoved === TRUE )
            {
                unset( 
$css$row['css_group'] ] );
                
$skip[] = $row['css_group'];
                continue;
            }
            
            
$css$row['css_group'] ] = $row;
        }
        
        return 
$css;
    }

    
/**
     * Fetch CSS for editing
     *
     * @access    public
     * @param    int            CSS ID
     * @param    int            Template Set ID
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * NO_SUCH_CSS:        Could not locate CSS id#
     * </code>
     */
    
public function fetchCSSForEdit$cssID$setID )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$cssID intval$cssID );

        
//-----------------------------------------
        // Fetch template data
        //-----------------------------------------
        
        
$css $this->DB->buildAndFetch( array( 'select' => '*',
                                                
'from'   => 'skin_css',
                                                
'where'  => 'css_id=' $cssID ) );

        if ( ! 
$css['css_id'] )
        {
            throw new 
Exception'NO_SUCH_CSS' );
        }
        
        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Update data
        //-----------------------------------------

        
$css['_actualSetID']      = $css['css_set_id'];
        
$css['_belongsSetID']     = $setID;
        
$css['_isMaster']          = ( $css['css_master_key'] ) ? 0;
        
//$css['_css_content']      = $css['css_content'];

        //-----------------------------------------
        // Update content for editing
        //-----------------------------------------
        
        /* Commented out for bug #18432 */
//        $css['css_content'] = IPSText::textToForm( $css['css_content'] );

        //-----------------------------------------
        // Return it
        //-----------------------------------------

        
return $css;
    }

    
/**
     * Save template bit after edit
     *
     * @access    public
     * @param    int            CSS ID
     * @param    int            CSS content
     * @param    string        CSS group
     * @param    string        CSS position
     * @param    string        CSS attributes (media="Screen")
     * @param    string        APP key to tie CSS to
     * @param    int            If APP key, hide when APP key doesn't match viewing app
     * @param    string        Modules to tie CSS to
     * @return    int            New CSS id
     * <code>
     * Exception Codes:
     * CSS_EXISTS:        CSS by that name already exists
     * NO_SUCH_SET:        Set ID doesn't match anything in the DB
     * </code>
     */
    
public function saveCSSFromAdd$setID$css_content$css_group$css_position=0$css_attributes=''$css_app=''$css_app_hide=0$css_modules='' )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$setID        intval$setID );
        
$css_group    str_replace'.css'''IPSText::alphanumericalClean$css_group ) );
        
$css_position intval$css_position );
        
        
/* Make sure skingen is always on top */
        
if ( $css_group != 'ipb_skingen' )
        {
            
$css_position = ( $css_position >= 999 ) ? 998 $css_position;
        }
        
        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Got it?
        //-----------------------------------------

        
if ( ! $skinSetData['set_id'] )
        {
            throw new 
Exception'NO_SUCH_SET' );
        }

        
//-----------------------------------------
        // Make sure we don't have one already
        //-----------------------------------------

        
$css $this->DB->buildAndFetch( array( 'select' => '*',
                                                
'from'   => 'skin_css',
                                                
'where'  => 'css_set_id=' $setID ' AND css_group='' . $css_group . ''' ) );

        if ( 
$css['css_id'] )
        {
            throw new 
Exception'CSS_EXISTS' );
        }

        
//-----------------------------------------
        // Fix up content
        //-----------------------------------------

        
$css_content IPSText::formToText$css_content );

        
//-----------------------------------------
        // Save CSS?
        //-----------------------------------------

        
$this->DB->insert'skin_css', array(    'css_set_id'     => $setID,
                                                 
'css_content'    => $css_content,
                                                 
'css_group'      => $css_group,
                                                 
'css_position'   => $css_position,
                                                 
'css_attributes' => $css_attributes,
                                                 
'css_app'          => $css_app,
                                                 
'css_app_hide'      => $css_app_hide,
                                                 
'css_modules'      => str_replace' '''$css_modules ),
                                                 
'css_added_to'   => $setID,
                                                 
'css_updated'    => time() ) );

        
$css_id_new $this->DB->getInsertId();

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildCSS$setID );

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $css_id_new;
    }

    
/**
     * Save template bit after edit
     *
     * @access    public
     * @param    int            CSS ID
     * @param    int            CSS Set ID
     * @param    string        CSS content
     * @param    string        CSS name (css_group)
     * @param    int            CSS position
     * @param    string        CSS attributes (media="Screen")
     * @param    string        APP key to tie CSS to
     * @param    int            If APP key, hide when APP key doesn't match viewing app
     * @param    string        Modules to tie CSS to
     * @return    int         New CSS id
     * <code>
     * Exception Codes:
     * NO_SUCH_CSS:        Could not locate CSS
     * CSS_EXISTS:         Could not rename CSS file
     * </code>
     */
    
public function saveCSSFromEdit$cssID$setID$css_content$css_group$css_position=0$css_attributes=''$css_app=''$css_app_hide=0$css_modules='' )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$cssID        intval$cssID );
        
$css_group    str_replace'.css'''IPSText::alphanumericalClean$css_group ) );
        
$css_position intval$css_position );
        
$_goClean     0;
        
        
/* Make sure skingen is always on top */
        
if ( $css_group != 'ipb_skingen' )
        {
            
$css_position = ( $css_position >= 999 ) ? 998 $css_position;
        }
        
        
//-----------------------------------------
        // Fetch template data
        //-----------------------------------------

        
$css $this->DB->buildAndFetch( array( 'select' => '*',
                                                
'from'   => 'skin_css',
                                                
'where'  => 'css_id=' $cssID ) );

        if ( ! 
$css['css_id'] )
        {
            throw new 
Exception'NO_SUCH_CSS' );
        }

        
//-----------------------------------------
        // Group?
        //-----------------------------------------

        
if ( $css['css_added_to'] == $setID )
        {
            if ( 
$css['css_group'] != $css_group )
            {
                
$cssTest $this->DB->buildAndFetch( array( 'select' => '*',
                                                            
'from'   => 'skin_css',
                                                            
'where'  => 'css_set_id=' $setID ' AND css_group='' . $css_group . ''' ) );

                if ( 
$cssTest['css_id'] )
                {
                    throw new 
Exception"CSS_EXISTS" );
                }

                
$_goClean 1;
            }
        }
        else
        {
            
$css_group $css['css_group'];
        }

        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Fix up content
        //-----------------------------------------

        
$css_content IPSText::formToText$css_content );
        
$css_attributes IPSText::formToText$css_attributes );

        
//-----------------------------------------
        // Same CSS?
        //-----------------------------------------

        
if ( $setID == $css['css_set_id'] )
        {
            
$this->DB->update'skin_css', array( 'css_content'      => $css_content,
                                                  
'css_group'        => $css_group,
                                                  
'css_position'     => $css_position,
                                                  
'css_attributes'     => $css_attributes,
                                                  
'css_app'            => $css_app,
                                                  
'css_app_hide'    => $css_app_hide,
                                                  
'css_modules'        => str_replace' '''$css_modules ),
                                                  
'css_updated'      => time() ), 'css_id=' $cssID );

            
$css_id_new $cssID;
        }
        else
        {
            
$this->DB->insert'skin_css', array(     'css_set_id'       => $setID,
                                                    
'css_content'      => $css_content,
                                                    
'css_group'        => $css_group,
                                                    
'css_position'     => $css_position   $css_position   $css['css_position'],
                                                    
'css_attributes'=> $css_attributes $css_attributes $css['css_attributes'],
                                                    
'css_app'        => $css_app        $css_app        $css['css_app'],
                                                    
'css_app_hide'    => $css_app_hide   $css_app_hide   $css['css_app_hide'],
                                                    
'css_modules'   => str_replace' '''$css_modules ),
                                                    
'css_added_to'     => $css['css_added_to'],
                                                    
'css_updated'      => time() ) );

            
$css_id_new $this->DB->getInsertId();
        }

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildCSS$setID );
        
        
/* Flush CDN */
        
$this->flushipscdn();

        
//-----------------------------------------
        // Remove dead-uns?
        //-----------------------------------------

        
if ( $_goClean == )
        {
            
$this->removeDeadCSSCaches$setID );
        }

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $css_id_new;
    }

    
/**
     * Reverts / Removes CSS
     *
     * @access    public
     * @param    int            CSS ID
     * @param    int            Template Set ID
     * @param    int            From a delete request
     * @return    array         Data from "next in line" CSS (parent, or root)
     * <code>
     * Exception Codes:
     * NO_SUCH_CSS:            Could not locate css id#
     * CANNOT_REMOVE:         Cannot revert / remove the css
     * </code>
     */
    
public function revertCSS$cssID$setID$fromDelete=)
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$cssID   intval$cssID );
        
$setData $this->fetchSkinData$setID );

        
//-----------------------------------------
        // Fetch CSS data
        //-----------------------------------------

        
$css $this->DB->buildAndFetch( array( 'select' => '*',
                                                
'from'   => 'skin_css',
                                                
'where'  => 'css_id=' $cssID ) );

        if ( ! 
$css['css_id'] )
        {
            throw new 
Exception'NO_SUCH_CSS' );
        }

        
/* Inherited from master */
        
if ( $css['css_added_to'] == )
        {
            
/* Did we want to delete? */
            
if ( $fromDelete )
            {
                
/* Inherited from master css */
                
if ( $css['css_set_id'] > )
                {
                    
/* Clear any existing CSS if it's been modified from set 0 */
                    
$this->DB->delete'skin_css''css_id=' $cssID );
                }
            
                
/* Add one as 'removed' */
                
$this->DB->insert'skin_css', array( 'css_set_id'   => $setID,
                                                      
'css_updated'  => time(),
                                                      
'css_group'    => $css['css_group'],
                                                      
'css_added_to' => $setID,
                                                      
'css_removed'  => ) );
            }
            else
            {
                
/* We're reverting - just make sure it's not a master CSS file */
                
if ( $css['css_set_id'] > )
                {
                    
$this->DB->delete'skin_css''css_id=' $cssID );
                }
            }
        }
        
/* Modified or added to this skin set or a parent
           Remove and revert do the same thing here... */
        
else
        {
            
/* Fix up child array */
            
array_unshift$setData['_childTree'], $setID );
            
            
/* This is CSS unique to this skin set, so remove it from this set and all children */
            
$this->DB->delete'skin_css'"css_group='" $css['css_group'] . "' AND css_set_id IN(" implode','$setData['_childTree'] ) . ")" );

            
# Remove dead caches
            
$this->removeDeadCSSCaches$setID );
        }

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildCSS$setID );
        
        
/* Flush CDN */
        
$this->flushipscdn();
        
        
//-----------------------------------------
        // Grab the next template bit inline...
        //-----------------------------------------

        
$cssData $this->fetchCSS$setIDTRUE );
            
        
//-----------------------------------------
        // Reeee-turn
        //-----------------------------------------

        
return $cssData;
    }
    
    
/**
     * Fetch Templates from the tree
     *
     * @access    public
     * @param    mixed        Skin key or    Skin set ID
     * @param    string        Type of data to return: 'allTemplates' will return the data [template_group][template_name], 'allNoContent' the same as 'allTemplates' minus the actual template content, 'groupNames'; [template_group] or groupTemplates, just that groups templates [template_name], groupTemplatesNoContent is the same as groupTemplates but template_content is removed
     * @param    string        Which group to use
     * @return    array         Array of data depending on the params
     * <code>
     * Usage:
     * # To return all skin 'groups' (eg, skin_global, skin_topics, etc)
     * $groups = $skinFunctions->fetchTemplates( 1, 'groupNames' );
     * # To return all templates within group 'skin_global'
     * $templates = $skinFunctions->fetchTemplates( 1, 'groupTemplates', 'skin_global' );
     * # To return all templates in all groups
     * $templates = $skinFunctions->fetchTemplates( 1, 'allTemplates');
     * # To return all master templates for the mobile skin
     * $templates = $skinFunctions->fetchTemplates( 'mobile', 'allTemplates' );
     * </code>
     */
    
public function fetchTemplates$setID$type='allTemplates'$group='')
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$templates     = array();
        
$where           '';
    
        
/* Did we pass a master key? - all root skins are 0  */
        
if ( ! is_numeric$setID ) )
        {
            
$skinSetData = array( 'set_id'          => 0,
                                  
'set_master_key'  => $setID,
                                  
'set_key'            => $setID,
                                  
'_isMaster'        => 1,
                                  
'_parentTree'     => array(),
                                  
'_childTree'      => array(),
                                  
'_userAgents'     => array(),
                                  
'_cssGroupsArray' => array() );
        }
        else
        {        
            
$skinSetData                $this->fetchSkinData$setID );
            
$skinSetData['_isMaster']    = $skinSetData['_isMaster'] ? $skinSetData['_isMaster'] : 0;
        }
        
        
/* Did we get a skin set? */
        
if ( ! isset( $skinSetData['_parentTree'] ) OR ! is_array$skinSetData['_parentTree'] ) )
        {
            return array();
        }
        
        
//-----------------------------------------
        // Push root ID onto the END of the parent array
        //-----------------------------------------

        
array_push$skinSetData['_parentTree'], );

        
//-----------------------------------------
        // Push the current skin set ID onto the beginnging
        //-----------------------------------------
        
        
if ( is_numeric$setID ) )
        {
            
array_unshift$skinSetData['_parentTree'], $setID );
        }
        
        
/* We want to capture only this set's master bits */
        
$where ' AND ( ( template_set_id > 0 AND ( template_master_key='' OR template_master_key IS NULL ) ) OR ( template_set_id=0 AND template_master_key='' . $skinSetData['set_master_key'] . '' ) )';
        
        
/* First off, load 'root' skin as we tend to develop this the most and there is always a small chance other master skins won't
           contain all the template bits. We'll just load the group / name and leave the content blank to prevent parse errors, etc */
        
if ( $setID != 'root' )
        {
            if ( ( 
$type == 'groupTemplates' OR $type == 'groupTemplatesNoContent' ) and $group != '' )
            {
                 
$_w " AND template_group='{$group}'";
            }
            
            
$this->DB->build( array( 'select'    => '*',
                                     
'from'        => 'skin_templates',
                                     
'where'    => "template_master_key='root'" $_w,
                                     
'order'    => 'template_group' ) );
                                     
            
$this->DB->execute();
        
            while( 
$r $this->DB->fetch() )
            {
                
$r['template_content'] = '<!--no data in this master skin-->';
                
                if ( 
$type == 'groupNames' )
                {
                    
$templates$r['template_group'] ] = $r;
                }
                else if ( 
$type == 'groupTemplates' OR $type == 'groupTemplatesNoContent' )
                {
                    
$r['_templateSize'] = IPSLib::sizeFormatIPSLib::strlenToBytesstrlen$r['template_content'] ) ) );
    
                    if ( 
$type == 'groupTemplatesNoContent' )
                    {
                        unset( 
$r['template_data'] );
                        unset( 
$r['template_content'] );
                    }
                    
                    
$templatesstrtolower($r['template_name']) ] = $r;
                }
                else
                {
                    if ( 
$type == 'allNoContent' )
                    {
                        unset( 
$r['template_content'] );
                    }
                    
                    
$templates$r['template_group'] ][ strtolower($r['template_name']) ] = $r;
                }
            }
        }
        
        
//-----------------------------------------
        // Ok, what to return?
        //-----------------------------------------

        
if ( $type == 'groupNames' )
        {
            
# Just return group titles
            
$this->DB->build( array( 'select'    => 'template_group, template_set_id, template_id, template_name, template_data,' .
                                                        
$this->DB->buildInstring"," implode","$skinSetData['_parentTree'] ) . ",",
                                                        
$this->DB->buildConcat( array( array( ',''string' ), array( 'template_set_id' ), array( ',''string' ) ) ) ) . ' as theorder',
                                           
'from'    => 'skin_templates',
                                           
'where'    => "template_set_id IN (" implode","$skinSetData['_parentTree'] ) ." )" $where,
                                           
'order'    => 'template_group, theorder DESC'
                                
)        );
            
$newq $this->DB->execute();
        }
        else if ( ( 
$type == 'groupTemplates' OR $type == 'groupTemplatesNoContent' ) and $group != '' )
        {
            
# Return group template bits
            
$this->DB->build( array( 'select'    => '*,' .
                                                       
$this->DB->buildInstring"," implode","$skinSetData['_parentTree'] ) . ",",
                                                       
$this->DB->buildConcat( array( array( ',''string' ), array( 'template_set_id' ), array( ',''string' ) ) ) ) . ' as theorder',
                                            
'from'    => 'skin_templates',
                                            
'where'    => "template_set_id IN (" implode","$skinSetData['_parentTree'] ) . ") AND template_group='{$group}'" $where,
                                            
'order'    => 'template_name, theorder DESC'
                                
)        );
            
$newq $this->DB->execute();
        }
        else
        {
            
# Return all...
            
$this->DB->build( array( 'select'    => '*,' .
                                                       
$this->DB->buildInstring"," implode","$skinSetData['_parentTree'] ) . ",",
                                                       
$this->DB->buildConcat( array( array( ',''string' ), array( 'template_set_id' ), array( ',''string' ) ) ) ) . ' as theorder',
                                            
'from'    => 'skin_templates',
                                            
'where'    => "template_set_id IN (" implode","$skinSetData['_parentTree'] ) .")" $where,
                                            
'order'    => 'template_group, template_name, theorder DESC'
                                
)        );
            
$newq $this->DB->execute();
        }

        
//-----------------------------------------
        // Get all results
        //-----------------------------------------

        
while ( $r $this->DB->fetch($newq) )
        {
            if ( isset( 
$r['template_name'] ) )
            {
                if ( 
substr$r['template_name'], 0) == '__' )
                {
                    continue;
                }
            }

            
//-----------------------------------------
            // Build counts
            //-----------------------------------------

            
$this->_templateCount$r['template_set_id'] ] = isset($this->_templateCount$r['template_set_id'] ]) ? $this->_templateCount$r['template_set_id'] ] : array();
            
$this->_templateCount$r['template_set_id'] ][ $r['template_group'] ] = isset($this->_templateCount$r['template_set_id'] ][ $r['template_group'] ]) ? $this->_templateCount$r['template_set_id'] ][ $r['template_group'] ] : array( 'count' => );
            
$this->_templateCount$r['template_set_id'] ][ $r['template_group'] ]['count']++;

            if ( 
$type == 'groupNames' )
            {
                
$templates$r['template_group'] ] = $r;
            }
            else if ( 
$type == 'groupTemplates' OR $type == 'groupTemplatesNoContent' )
            {
                
$r['_templateSize'] = IPSLib::sizeFormatIPSLib::strlenToBytesstrlen$r['template_content'] ) ) );

                if ( 
$type == 'groupTemplatesNoContent' )
                {
                    unset( 
$r['template_data'] );
                    unset( 
$r['template_content'] );
                }
                
                
$templatesstrtolower($r['template_name']) ] = $r;
            }
            else
            {
                if ( 
$type == 'allNoContent' )
                {
                    unset( 
$r['template_content'] );
                }
                
                
$templates$r['template_group'] ][ strtolower($r['template_name']) ] = $r;
            }
        }

        
ksort($templates);
        
        foreach( 
$templates as $k => $v )
        {
            if( 
is_array($v) )
            {
                
ksort($templates$k ]);
            }
        }

        return 
$templates;
    }

    
/**
     * Fetch template bit for editing
     *
     * @access    public
     * @param    int            Template ID
     * @param    int            Template Set ID
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * NO_SUCH_TEMPLATE:        Could not locate template id#
     * </code>
     */
    
public function fetchTemplateBitForEdit$templateID$setID )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$templateID intval$templateID );

        
//-----------------------------------------
        // Fetch template data
        //-----------------------------------------

        
$template $this->DB->buildAndFetch( array( 'select' => '*',
                                                     
'from'   => 'skin_templates',
                                                     
'where'  => 'template_id=' $templateID ) );

        if ( ! 
$template['template_id'] )
        {
            throw new 
Exception'NO_SUCH_TEMPLATE' );
        }

        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Update data
        //-----------------------------------------

        
$template['_actualSetID']      = $template['template_set'];
        
$template['_belongsSetID']     = $setID;
        
$template['_template_content'] = $template['template_content'];
        
$template['_template_data']    = $template['template_data'];
        
$template['_isMaster']           = ( $template['template_master_key'] ) ? 0;

        
//-----------------------------------------
        // Update content for editing
        //-----------------------------------------

        
$template['template_content'] = IPSText::textToForm$template['template_content'] );

        
//-----------------------------------------
        // Update function data for editing
        //-----------------------------------------

        
$template['template_data'] = IPSText::textToForm$template['template_data'] );

        
//-----------------------------------------
        // Return it
        //-----------------------------------------

        
return $template;
    }

    
/**
     * Reverts a template bit
     *
     * @access    public
     * @param    int            Template ID
     * @param    int            Template Set ID
     * @return    array         Data from "next in line" template bit (parent, or root)
     * <code>
     * Exception Codes:
     * NO_SUCH_TEMPLATE:    Could not locate template id#
     * CANNOT_REMOVE:         Cannot revert / remove the template bit
     * </code>
     */
    
public function revertTemplateBit$templateID$setID )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$templateID intval$templateID );
        
$_goClean   0;

        
//-----------------------------------------
        // Fetch template data
        //-----------------------------------------

        
$template $this->DB->buildAndFetch( array( 'select' => '*',
                                                     
'from'   => 'skin_templates',
                                                     
'where'  => 'template_id=' $templateID ) );

        if ( ! 
$template['template_id'] )
        {
            throw new 
Exception'NO_SUCH_TEMPLATE' );
        }

        
//-----------------------------------------
        // Is this a master skin bit?
        //-----------------------------------------

        
if ( $template['template_set_id'] == AND $template['template_added_to'] == )
        {
            throw new 
Exception"CANNOT_REMOVE");
        }

        
//-----------------------------------------
        // Remove it...
        //-----------------------------------------

        
if ( $template['template_added_to'] == $setID  )
        {
            
/* Does it exist in set ID 0? */
            
$test $this->DB->buildAndFetch( array( 'select' => 'template_id',
                                                      
'from'   => 'skin_templates',
                                                      
'where'  => "template_set_id=0 AND template_user_added=0 AND template_name='" $template['template_name'] . "' AND template_group='" $template['template_group'] . "'" ) );
            
            
/* Is from master skin? */
            
if ( $test['template_id'] )
            {
                
$this->DB->delete'skin_templates''template_id=' $templateID );
            }
            else
            {
                
# Remove it from ALL template sets
                
$this->DB->delete'skin_templates'"template_name='" $template['template_name'] . "' AND template_group='" $template['template_group'] . "'" );
            }
            
            
$_goClean 1;
        }
        else
        {
            
$this->DB->delete'skin_templates''template_id=' $templateID );
        }

        
//-----------------------------------------
        // Grab the next template bit inline...
        //-----------------------------------------

        
$templates $this->fetchTemplates$setID'groupTemplates'$template['template_group'] );

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildPHPTemplates$setID$template['template_group'] );

        
//-----------------------------------------
        // Clean up?
        //-----------------------------------------

        
if ( $_goClean )
        {
            
$this->removeDeadPHPCaches$setID );
        }

        
//-----------------------------------------
        // Reeee-turn
        //-----------------------------------------
        
        
if ( $templatesstrtolower$template['template_name'] ) ]['template_id'] )
        {
            return 
$this->fetchTemplateBitForEdit$templatesstrtolower$template['template_name'] ) ]['template_id'], $setID );
        }
        else
        {
            return array();
        }
    }

    
/**
     * Save template bit from 'add' form
     *
     * @access    public
     * @param    int            Template Set ID
     * @param    string        Template content
     * @param    string        Template function data
     * @param    string        Template group
     * @param    string        Template name
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * TEMPLATE_EXISTS:        Template bit name already exists
     * SYNTAX_INCORRECT:    The php syntax is invalid
     * </code>
     */
    
public function saveTemplateBitFromAdd$setID$template_content$template_data$template_group$template_name )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$template_group   IPSText::alphanumericalClean$template_group );
        
$template_name    IPSText::alphanumericalClean$template_name );
        
$template_content str_replace'\"''\"'$template_content );
        
        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Does this template bit already exist?
        //-----------------------------------------

        
$template $this->DB->buildAndFetch( array( 
                                                    
'select' => '*',
                                                    
'from'   => 'skin_templates',
                                                    
'where'  => "template_name='" $template_name "' AND template_group='" $template_group "' AND template_added_to={$setID}) );

        if ( 
$template['template_id'] )
        {
            throw new 
Exception'TEMPLATE_EXISTS' );
        }

        
//-----------------------------------------
        // Fix up content
        //-----------------------------------------

        
$template_content IPSText::formToText$template_content );

        
//-----------------------------------------
        // Fix up data
        //-----------------------------------------

        
$template_data IPSText::formToText$template_data );

        
//-----------------------------------------
        // Test it..
        //-----------------------------------------

        
if ( $this->testTemplateBitSyntax$template_name$template_data$template_content ) !== TRUE )
        {
            throw new 
Exception"SYNTAX_INCORRECT" );
        }

        
//-----------------------------------------
        // Same template set?
        //-----------------------------------------
        
        /* @todo - 'root' is almost certainly what we want but we *should* write a method that traverses up the tree
         * from this set ID and looks for the master key of the root set. Especially important if we add any future
         * output engines.
         */
        
$this->DB->insert'skin_templates', array( 'template_set_id'      => 0,
                                                    
'template_group'       => $template_group,
                                                    
'template_content'     => $template_content,
                                                    
'template_name'        => $template_name,
                                                    
'template_data'        => $template_data,
                                                    
'template_added_to'    => $setID,
                                                    
'template_user_edited' => 1,
                                                    
'template_user_added'  => 1,
                                                    
'template_removable'   => 1,
                                                    
'template_updated'     => time(),
                                                    
'template_master_key'  => 'root' ) );

        
$template_id_new $this->DB->getInsertId();

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildPHPTemplates$setID$template_group );

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $template_id_new;
    }

    
/**
     * Save template bit after edit
     *
     * @access    public
     * @param    int            Template ID
     * @param    int            Template Set ID
     * @param    string        Template content
     * @param    string        Template function data
     * @return    array         ..of data
     * <code>
     * Exception Codes:
     * NO_SUCH_TEMPLATE:        Could not locate template id#
     * SYNTAX_INCORRECT:        The template bit syntax is incorrect and would cause a parse error if saved
     * </code>
     */
    
public function saveTemplateBitFromEdit$templateID$setID$template_content$template_data )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$templateID       intval$templateID );
        
$template_content str_replace'\"''\"'$template_content );
        
        
//-----------------------------------------
        // Fetch template data
        //-----------------------------------------

        
$template $this->DB->buildAndFetch( array( 'select' => '*',
                                                     
'from'   => 'skin_templates',
                                                     
'where'  => 'template_id=' $templateID ) );

        if ( ! 
$template['template_id'] )
        {
            throw new 
Exception'NO_SUCH_TEMPLATE' );
        }

        
//-----------------------------------------
        // Get skin data
        //-----------------------------------------

        
$skinSetData $this->registry->output->allSkins$setID ];

        
//-----------------------------------------
        // Fix up content
        //-----------------------------------------

        
$template_content IPSText::formToText$template_content );

        
//-----------------------------------------
        // Fix up data
        //-----------------------------------------

        
$template_data IPSText::formToText$template_data );

        
//-----------------------------------------
        // Test it..
        //-----------------------------------------

        
if ( $this->testTemplateBitSyntax$template['template_name'], $template_data$template_content ) !== TRUE )
        {
            throw new 
Exception"SYNTAX_INCORRECT" );
        }

        
//-----------------------------------------
        // Same template set?
        //-----------------------------------------

        
if ( $setID == $template['template_set_id'] )
        {
            
$this->DB->update'skin_templates', array( 'template_data'        => $template_data,
                                                        
'template_content'     => $template_content,
                                                        
'template_user_edited' => 1,
                                                        
'template_updated'     => time() ), 'template_id=' $templateID );

            
$template_id_new $templateID;
        }
        else
        {
            
$this->DB->insert'skin_templates', array( 'template_set_id'      => $setID,
                                                        
'template_group'       => $template['template_group'],
                                                        
'template_content'     => $template_content,
                                                        
'template_name'        => $template['template_name'],
                                                        
'template_data'        => $template_data,
                                                        
'template_added_to'    => $template['template_added_to'],
                                                        
'template_user_added'  => $template['template_user_added'],
                                                        
'template_user_edited' => 1,
                                                        
'template_removable'   => 1,
                                                        
'template_updated'     => time() ) );

            
$template_id_new $this->DB->getInsertId();

            
# Update count
            
$this->_templateCount$setID ][ $template['template_group'] ]['count']++;
        }
        
        
/* If this is a user-added template bit and we're editing it in the same skin, update master */
        
if ( $template['template_id'] && $template['template_user_added'] && $template['template_added_to'] == $setID )
        {
            
$this->DB->update'skin_templates', array( 'template_content' => $template_content ), "template_set_id=0 AND template_group='" $template['template_group'] . "' AND template_name='" $template['template_name'] . "'" );
        }

        
//-----------------------------------------
        // Recache
        //-----------------------------------------

        
$this->rebuildPHPTemplates$setID$template['template_group'] );
        
        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return $template_id_new;
    }
    
    
/**
     * renames a template title
     * @param int $templateId
     * @param string $newName
     */
    
public function renameTemplateName$templateId$newName )
    {
        
$template  $this->fetchTemplateBitForEdit$templateId);
        
$skinSet   $this->fetchSkinData$template['template_set_id'] );
        
$okToSave  true;
        
$masterKey 'root';
        
        
$update   = array( 'template_name' => $newName );
        
        if ( ( 
$template['template_set_id'] == $template['template_added_to'] ) )
        {
            
$masterTemplates $this->fetchTemplates$masterKey'allNoContent'$template['template_group'] );
            
            if ( isset( 
$masterTemplates$template['template_group'] ][ $newName ] ) )
            {
                
/* Added by webdav, now attempting to rename */
                
$update['template_added_to']   = 0;
                
$update['template_master_key'] = $masterKey;
            }
        }
        
        if ( ! 
$template['template_id'] OR $template['_isMaster'] )
        {
            
$okToSave false;
        }
        
        if ( 
$okToSave )
        {
            
$this->DB->update'skin_templates'$update'template_name='' . $this->DB->addSlashes( $template['template_name'] ) . '' AND template_group='' . $this->DB->addSlashes( $template['template_group'] ) . ''' );
        }
        
        
/* rebuild */
        
$this->rebuildPHPTemplates$template['template_set_id'], $template['template_group'] );
    }
    
    
/**
     * renames a css title
     * @param int $cssId
     * @param string $newName
     */
    
public function renameCssName$cssId$newName )
    {
        
$template $this->fetchCssForEdit$cssId);
        
$okToSave true;
        
$update   = array( 'css_group' => $newName );
        
        if ( ( 
$template['css_set_id'] == $template['css_added_to'] ) )
        {
            
$masterCss $this->fetchCSS'root'false );
            
            if ( isset( 
$masterCss$newName ] ) )
            {
                
/* Added by webdav, now attempting to rename */
                
$update['css_added_to'] = 0;
            }
        }
        
        if ( ! 
$template['css_id'] OR $template['_isMaster'] )
        {
            
$okToSave false;
        }
        
        if ( 
$okToSave )
        {
            
$this->DB->update'skin_css'$update'css_group='' . $this->DB->addSlashes( $template['css_group'] ) . ''' );
        }
        
        
/* rebuild */
        
$this->rebuildCSS$template['css_set_id'] );
    }    

    
/**
     * Fetch image directories from the file system
     *
     * @access    public
     * @return    array     simple array of filenames
     */
    
public function fetchImageDirectories()
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$dirs = array();
        
        try
        {
            foreach( new 
DirectoryIteratorDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_images' ) as $file )
            {
                if ( ! 
$file->isDot() AND $file->isDir() )
                {
                    
$_name $file->getFileName();
            
                    
/* Annoyingly, isDot doesn't match .svn, etc */
                    
if ( substr$_name0) == '.' )
                    {
                        continue;
                    }
            
                    
$dirs[] = $_name;
                }
            }
        } catch ( 
Exception $e ) {}

        return 
$dirs;
    }

    
/**
     * Fetch emoticon directories from the file system
     *
     * @access    public
     * @return    array     simple array of filenames
     */
    
public function fetchEmoticonDirectories()
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$dirs = array();
        
        try
        {
            foreach( new 
DirectoryIteratorDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_emoticons' ) as $file )
            {
                if ( ! 
$file->isDot() AND $file->isDir() )
                {
                    
$_name $file->getFileName();
            
                    
/* Annoyingly, isDot doesn't match .svn, etc */
                    
if ( substr$_name0) == '.' )
                    {
                        continue;
                    }
            
                    
$dirs[] = $_name;
                }
            }
        } catch ( 
Exception $e ) {}

        return 
$dirs;
    }

    
/**
     * Returns the Image directory
     *
     * @access    public
     * @param    string    Dir name
     * @return    mixed    False, or directory path
     */
    
public function fetchImageDirectoryPath$dir )
    {
        if ( 
$this->checkImageDirectoryExists$dir ) === TRUE )
        {
            return 
DOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_images/' $dir;
        }
        else
        {
            return 
FALSE;
        }
    }

    
/**
     * Check Image directory exists
     *
     * @access    public
     * @param    string    Dir name
     * @return    boolean
     */
    
public function checkImageDirectoryExists$dir )
    {
        if ( ! 
is_dirDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_images/' $dir ) )
        {
            return 
FALSE;
        }
        else
        {
            return 
TRUE;
        }
    }

    
/**
     * Creates a new image directory
     *
     * @access    public
     * @param    string    Dir name
     * @return    boolean
     */
    
public function createNewImageDirectory$dir )
    {
        if ( @
mkdirDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_images/' $dir ) )
        {
            @
chmodDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_images/' $dirIPS_FOLDER_PERMISSION );
            return 
TRUE;
        }
    }

    
/**
     * Check Emoticon directory exists
     *
     * @access    public
     * @param    string    Dir name
     * @return    boolean
     */
    
public function checkEmoticonDirectoryExists$dir )
    {
        if ( ! 
is_dirDOC_IPS_ROOT_PATH PUBLIC_DIRECTORY '/style_emoticons/' $dir ) )
        {
            return 
FALSE;
        }
        else
        {
            return 
TRUE;
        }
    }

    
/**
     * Fetch output formats
     *
     * @access    public
     * @return    array         array( 'key' => array( $confdata.... ) )
     */
    
public function fetchOutputFormats()
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$formats = array();
        
$path    IPS_ROOT_PATH 'sources/classes/output/formats';
        
        try
        {
            foreach( new 
DirectoryIterator$path ) as $file )
            {
                if ( ! 
$file->isDot() AND $file->isDir() )
                {
                    
$_name $file->getFileName();
            
                    
/* Annoyingly, isDot doesn't match .svn, etc */
                    
if ( substr$_name0) == '.' )
                    {
                        continue;
                    }
                    
                    if( ! 
is_file$path '/' $_name '/conf.php' ) )
                    {
                        continue;
                    }
                    
                    
$config = array();
                    require( 
$path '/' $_name '/conf.php' );/*noLibHook*/
                    
                    
$formats$_name ] = $config;
                }
            }
        } catch ( 
Exception $e ) {}

        return 
$formats;
    }

    
/**
     * Fetch all template hooks
     *
     * @access    public
     * @param    array         [Array of skin groups to search in. Leave blank to search in all]
     * @return    array         Array of skin groups and their hooks
     */
    
public function fetchSkinHooks$groups=array() )
    {
        
/* INIT */
        
$myHooks = array();
        
        
/* Fetch groups? */
        
if ( ! count$groups ) )
        {
            
$groups array_keys$this->fetchTemplates'root''groupNames' ) );
        }
        
        
/* Got a hooks cache? */
        
if ( ! $this->cache->exists('hooks') )
        {
            
$this->cache->rebuildCache('hooks''global' );
        }
        
        
/* Loop through the cache */
        
$hooksCache $this->cache->getCache'hooks' );
        
        if( 
is_array$hooksCache['templateHooks'] ) AND count$hooksCache['templateHooks'] ) )
        {
            foreach( 
$hooksCache['templateHooks'] as $skinGroup => $hooks )
            {
                
/* Check to see if the group is loaded */
                
if( ! in_array$skinGroup$groups ) )
                {
                    continue;
                }

                foreach( 
$hooks as $tplHook )
                {
                    
/* Check for hook file */
                    
if( is_fileIPS_HOOKS_PATH $tplHook['filename'] ) )
                    {
                        
$tplHook['_commentTag'] = $tplHook['type'] . '.' $skinGroup '.' $tplHook['skinFunction'] . '.' $tplHook['id'] . '.' $tplHook['position'];
                        
$myHooks$skinGroup ][] = $tplHook;
                    }
                }
            }
        }
        
        return 
$myHooks;
    }
    
    
/**
     * Flushes and reloads skin set data
     *
     * @access    public
     * @return  void
     */
    
public function flushSkinData()
    {
        try
        {
            
$skinSetData $this->registry->output->reloadSkinData();
        }
        catch( 
Exception $error )
        {
            
# We're here 'cos this was called during setup and
            # registry->getClass('output') isn't set up yet, so we
            # just carry on and let the DB get it
            
        
}
    }
    
    
/**
     * Fetch skin set data
     *
     * @access    public
     * @param    int        Skin set ID
     * @param    bool    Force load from DB
     * @return    array
     */
    
public function fetchSkinData$setID$forceLoadDB=false )
    {
        
//-----------------------------------------
        // Skin ID #0?
        //-----------------------------------------

        
if ( $setID == )
        {
            
/* This is a master skin, so lets fake it */
            
$skinSetData['set_id']            = 0;
            
$skinSetData['set_key']            = is_numeric$setID ) ? 'root' $setID;
            
$skinSetData['set_master_key']  = is_numeric$setID ) ? 'root' $setID;
            
$skinSetData['_isMaster']        = 1;
            
$skinSetData['_parentTree']     = array();
            
$skinSetData['_childTree']      = array();
            
$skinSetData['_userAgents']     = array();
            
$skinSetData['_cssGroupsArray'] = array();

            return 
$skinSetData;
        }

        
//-----------------------------------------
        // Try and get the skin from the cache
        //-----------------------------------------

        
try
        {
            
$skinSetData $this->registry->output->allSkins$setID ];
        }
        catch( 
Exception $error )
        {
            
# We're here 'cos this was called during setup and
            # registry->getClass('output') isn't set up yet, so we
            # just carry on and let the DB get it
        
}

        
$skinSetData['_parentTree']     = $skinSetData['_parentTree'] ? $skinSetData['_parentTree'] : array();
        
$skinSetData['_childTree']      = $skinSetData['_childTree'] ? $skinSetData['_childTree'] : array();
        
$skinSetData['_userAgents']     = $skinSetData['_userAgents'] ? $skinSetData['_userAgents'] : array();
        
$skinSetData['_cssGroupsArray'] = $skinSetData['_cssGroupsArray'] ? $skinSetData['_cssGroupsArray'] : array();
        
        if ( 
is_array$this->remapData ) AND count$this->remapData ) )
        {
            
$skinSetData['_isMaster'] = ( $this->remapData['templates'][ $setID ] ) ? 0;
        }
        
        
//-----------------------------------------
        // Got nothing?
        //-----------------------------------------

        
if ( $forceLoadDB OR ( $setID AND ! $skinSetData['set_id'] ) )
        {
            
$skinSetData $this->DB->buildAndFetch( array( 'select' => '*',
                                                            
'from'   => 'skin_collections',
                                                            
'where'  => 'set_id=' $setID ) );

            
$skinSetData['_parentTree']     = unserialize$skinSetData['set_parent_array'] );
            
$skinSetData['_childTree']      = unserialize$skinSetData['set_child_array'] );
            
$skinSetData['_userAgents']     = unserialize$skinSetData['set_locked_uagent'] );
            
$skinSetData['_cssGroupsArray'] = unserialize$skinSetData['set_css_groups'] );
            
            if ( 
is_array$this->remapData ) AND count$this->remapData ) )
            {
                
$skinSetData['_isMaster'] = ( $this->remapData['templates'][ $setID ] ) ? 0;
            }
            
            if ( 
is_array$skinSetData['_cssGroupsArray'] ) )
            {
                
ksort$skinSetData['_cssGroupsArray'], SORT_NUMERIC );
            }
            else
            {
                
$skinSetData['_cssGroupsArray'] = array();
            }
        }
        
        
/* Fail safe */
        
$skinSetData['set_master_key'] = ( $skinSetData['set_master_key'] ) ? $skinSetData['set_master_key'] : 'root';

        return 
$skinSetData;
    }
    
    
/**
     * Removes customizations in a skin set
     *
     * @access    public
     * @param    int            Skin set ID
     * @param    array         Items to revert ( 'templates' => TRUE/FALSE, 'css' => TRUE/FALSE, 'replacements' => TRUE/FALSE )
     * @return    boolean
     */
    
public function removeCustomizations$setId$which=array() )
    {
        
/* INIT */
        
$setId  intval$setId );
        
        
/* Templates */
        
if ( !empty( $which['templates'] ) )
        {
            
$this->DB->delete'skin_templates''template_set_id=' $setId );
        }
        
        
/* CSS */
        
if ( !empty( $which['css'] ) )
        {
            
$this->DB->delete'skin_css''css_set_id=' $setId );
        }
        
        
/* Replacements */
        
if ( !empty( $which['replacements'] ) )
        {
            
$this->DB->delete'skin_replacements''replacement_set_id=' $setId );
        }
        
        
/* Recache */
        
if ( method_exists$this'rebuildReplacementsCache' ) )
        {
            
$this->rebuildReplacementsCache$setId );
            
$this->rebuildCSS$setId );
            
$this->rebuildPHPTemplates$setId );
        }
        
        
/* Flush CDN */
        
$this->flushipscdn();
        
        return 
TRUE;
    }
    
    
    
/**
     * Fetch number of customizations in a skin set
     *
     * @access    public
     * @param    int            Skin set ID
     * @return    array         ( 'templates' => x, 'css' => x, 'replacements' => x )
     */
    
public function fetchCustomizationCount$setId )
    {
        
/* INIT */
        
$return = array( 'templates' => 0'css' => 0'replacements' => );
        
$setId  intval$setId );
        
        
/* Templates.. */
        
$c $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as count',
                                              
'from'   => 'skin_templates',
                                              
'where'  => 'template_set_id=' $setId ) );
                                            
        
$return['templates'] = intval$c['count'] );
        
        
/* CSS */
        
$c $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as count',
                                              
'from'   => 'skin_css',
                                              
'where'  => 'css_set_id=' $setId ) );
                                            
        
$return['css'] = intval$c['count'] );
        
        
/* Replacements */
        
$c $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as count',
                                              
'from'   => 'skin_replacements',
                                              
'where'  => 'replacement_set_id=' $setId ) );
                                            
        
$return['replacements'] = intval$c['count'] );
        
        return 
$return;
    }
    
    
/**
     * Test template bit syntax
     *
     * @access    public
     * @param    string        Template name
     * @param    string        Template function data
     * @param    string        Template content
     * @return    boolean        [ TRUE == OK ]
     */
    
public function testTemplateBitSyntax$name$data$content )
    {
        
//-----------------------------------------
        // INIT
        //-----------------------------------------

        
$return '';

        
$this->_resetMessageHandle();

        
//-----------------------------------------
        // Test...
        //-----------------------------------------

        
$eval $this->registry->templateEngine->convertHtmlToPhp'test__' $name$data$content );
        
        
ob_start();
        eval( 
$eval );
        
$return ob_get_contents();
        
ob_end_clean();

        
//-----------------------------------------
        // More data...
        //-----------------------------------------

        
$this->_addMessage$return );

        
//-----------------------------------------
        // Return
        //-----------------------------------------

        
return ($return) ? FALSE TRUE;
    }
    
    
/**
     * Minify text
     *
     * @access    public
     * @param    string        Text to minify
     * @param    string        Type to minify (css/html). Default is css
     * @return    string        Minified text
     */
    
    
public function minify$text$type='css' )
    {
        
$type strtolower$type );
        
        
/* What to do? */
        
if ( $type == 'css' )
        {
            require_once( 
IPS_PUBLIC_PATH 'min/lib/Minify/CSS/Compressor.php' );/*noLibHook*/
            
            
$text Minify_CSS_Compressor::process$text );
        }
        else if ( 
$type == 'html' )
        {
            require_once( 
IPS_PUBLIC_PATH 'min/lib/Minify/HTML.php' );/*noLibHook*/
            
            
$text Minify_HTML::minify$text, array( 'xhtml' => ) );
        }
        
        return 
$text;
    }
    
    
/**
     * Clean out templates DB
     * Goes through and removes any 'dead' templates
     *
     * @access    public
     * @return    array        ( 'cached' => x, 'templates' => x ) Number of template bits removed
     */
    
public function cleanDbCss()
    {
        
/* INIT */
        
$sets     array_keys$this->registry->output->allSkins );
        
$affected 0;
        
$cached   0;
        
        
/* Remove from cache: sets */
        
$this->DB->delete'skin_cache''cache_type='css' AND cache_set_id NOT IN ( 0,' implode','$sets ) . ')' );
        
        
$cached += intval$this->DB->getAffectedRows() );
        
        
/* Clean out any template bits no longer assigned to a valid skin set */
        
$this->DB->delete'skin_css''css_set_id NOT IN ( 0,' implode','$sets ) . ')' );
        
        
$affected += intval$this->DB->getAffectedRows() );
        
        return array( 
'cached' => intval$cached ), 'templates' => intval$affected ) );
    }    
    
    
    
/**
     * Clean out templates DB
     * Goes through and removes any 'dead' templates
     *
     * @access    public
     * @return    array        ( 'cached' => x, 'templates' => x ) Number of template bits removed
     */
    
public function cleanDbTemplates()
    {
        
/* INIT */
        
$sets     array_keys$this->registry->output->allSkins );
        
$groups   $this->fetchTemplates0'groupNames' );
        
$affected 0;
        
$cached   0;
        
        
/* Remove from cache: sets */
        
$this->DB->delete'skin_cache''cache_type='phptemplate' AND cache_set_id NOT IN ( 0,' implode','$sets ) . ')' );
        
        
$cached += intval$this->DB->getAffectedRows() );
        
        
/* Remove from cache: non-existant groups */
        
$this->DB->delete'skin_cache'"cache_type='phptemplate' AND cache_value_1 NOT IN ('" implode"','"array_keys$groups ) ) . "')" );
        
        
$cached += intval$this->DB->getAffectedRows() );
        
        
/* Clean out any template bits no longer assigned to a valid skin set */
        
$this->DB->delete'skin_templates''template_set_id NOT IN ( 0,' implode','$sets ) . ')' );
        
        
$affected += intval$this->DB->getAffectedRows() );
        
        
/* Loop through groups */
        
foreach( $groups as $_group => $_data )
        {
            
$templates $this->fetchTemplates0'groupTemplatesNoContent'$_group );
            
            
/* Clean out any template bits no longer part of this group */
            
$this->DB->delete'skin_templates'"template_group='" $_group "' AND template_user_added=0 AND " $this->DB->buildLower('template_name') . " NOT IN ('" implode"','"array_keys$templates ) ) . "')" );

            
$affected += intval$this->DB->getAffectedRows() );
        }
        
        return array( 
'cached' => intval$cached ), 'templates' => intval$affected ) );
    }
    
    
/**
     * Rebuilds the mobile user agents from the skin set data
     */
    
public function rebuildMobileSkinUserAgentsFromSetDataXml()
    {
        
/* Init */
        
$mobileSkinSet $this->fetchSkinData$this->fetchSetIdByKey'mobile'true ), true );
        
$xmlData       = array();
        
        
/* Grab xml */
        
require_once( IPS_KERNEL_PATH 'classXML.php' );/*noLibHook*/
        
$xml    = new classXML'UTF-8' );
        
        
/* Skin Set Data */
        
$xml->loadIPS_ROOT_PATH 'setup/xml/skins/setsData.xml' );

        foreach( 
$xml->fetchElements'set' ) as $xmlelement )
        {
            
$data $xml->fetchElementsFromRecord$xmlelement );

            if ( 
$data['set_key'] == 'mobile' )
            {
                
$xmlData $data;
                break;
            }
        }
        
        
/* Update */
        
if ( $xmlData['set_key'] && IPSLib::isSerialized$xmlData['set_locked_uagent'] ) && IPSLib::isSerialized$mobileSkinSet['set_locked_uagent'] ) )
        {
            
$new unserialize$xmlData['set_locked_uagent'] );
            
$old unserialize$mobileSkinSet['set_locked_uagent'] );
            
            
/* Merge them */
            
foreach( $new['groups'] as $group )
            {
                if ( ! 
in_array$group$old['groups'] ) )
                {
                    
$old['groups'][] = $group;
                }
            }
            
            foreach( 
$new['uagents'] as $agent => $version )
            {
                if ( ! 
in_array$agent$new['uagents'] ) )
                {
                    
$old['uagents'][ $agent ] = $version;
                }
            }
        }    
        
        if ( 
is_array$old ) && count$old ) )
        {
            
$this->DB->update'skin_collections', array( 'set_locked_uagent' => serialize$old ) ), "set_key='mobile'" );
        }
    }
    
    
/**
     * Flush IPS CDN Cache
     */
    
public function flushipscdn()
    {    
        if ( 
ipsRegistry::$settings['ips_cdn'] )
        {                
            require_once 
IPS_KERNEL_PATH 'classFileManagement.php';
            
$cfm = new classFileManagement();
            
$cfm->timeout 1;
            
$cfm->getFileContents"http://license.invisionpower.com/?a=cdnflush&key=" ipsRegistry::$settings['ipb_reg_number'] . "&version=" IPB_LONG_VERSION );
        }
    }
}
Онлайн: 0
Реклама