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

Incorrect access

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 __construct( ipsRegistry $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->buildRemapData( TRUE ); } //----------------------------------------- // 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_id, true ); /* Make all others non default */ $this->DB->update( 'skin_collections', array( 'set_is_default' => 0 ), '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 == 0 ) { /* 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 == 0 ) ? $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( '', file( IPS_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'] >= 1 ) { 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' => 0 ), 'set_parent_id=' . $setID ); /* Update any members */ $this->DB->update( 'members', array( 'skin' => 0 ), 'skin=' . $setID ); /* Update any forums */ $this->DB->update( 'forums', array( 'skin_id' => 0 ), '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::loadLibrary( IPS_KERNEL_PATH . '/classFileManagement.php', 'classFileManagement' ); $fileManagement = new $classToLoad(); $fileManagement->removeDirectory( DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_css/css_' . $setID ); /* Delete PHP Cache Files */ $fileManagement->removeDirectory( IPS_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' => 0 ) ) ); } /* Rebuild Tree Information */ $this->rebuildTreeInformation(); /* Rebuild Skin Set Caches */ if ( class_exists( 'skinCaching' ) ) { $this->rebuildSkinSetsCache(); $this->rebuildURLMapCache(); $this->cache->putWithCacheLib( 'Skin_Store_' . $setID, array(), 1 ); } 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( $_id, true ); /* If no parent, we must be a parent, then */ if ( ! $rootParent['set_id'] ) { $rootParent = $this->fetchSkinData( $setID, true ); } $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( $_id, true ); /* If no parent, we must be a parent, then */ if ( ! $rootParent['set_id'] ) { $rootParent = $this->fetchSkinData( $setID, true ); } } $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' => .... ] * * Usage: * $replacementData = $skinFunctions->fetchReplacements( 1 ); * * foreach( $replacementData as $key => $data ) * { * print $key . ' contains: ' . $data['replacement_content']; * } * */ 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'], 0 ); //----------------------------------------- // 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'], 0 ); //----------------------------------------- // 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 * * Exception Codes: * NO_SUCH_REPLACEMENT: Could not locate replacement * REPLACEMENT_EXISTS: Could not rename replacement * */ 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 * * Exception Codes: * REPLACEMENT_EXISTS: Could not rename replacement * */ 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 * * Exception Codes: * NO_SUCH_REPLACEMENT: Could not locate replacement id# * CANNOT_REMOVE: Cannot revert / remove the css * */ 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'] == 0 AND $replacement['replacement_added_to'] == 0 ) { 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' => .... ] * * Usage: * $cssData = $skinFunctions->fetchCSS( 1 ); * * foreach( $cssData as $group_name => $data ) * { * print $data['css_group'] . ' contains: ' . $data['css_content']; * } * */ 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'], 0 ); //----------------------------------------- // 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::sizeFormat( IPSLib::strlenToBytes( strlen( $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 * * Exception Codes: * NO_SUCH_CSS: Could not locate CSS id# * */ 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'] ) ? 1 : 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 * * Exception Codes: * CSS_EXISTS: CSS by that name already exists * NO_SUCH_SET: Set ID doesn't match anything in the DB * */ 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 * * Exception Codes: * NO_SUCH_CSS: Could not locate CSS * CSS_EXISTS: Could not rename CSS file * */ 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 == 1 ) { $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) * * Exception Codes: * NO_SUCH_CSS: Could not locate css id# * CANNOT_REMOVE: Cannot revert / remove the css * */ public function revertCSS( $cssID, $setID, $fromDelete=0 ) { //----------------------------------------- // 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'] == 0 ) { /* Did we want to delete? */ if ( $fromDelete ) { /* Inherited from master css */ if ( $css['css_set_id'] > 0 ) { /* 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' => 1 ) ); } else { /* We're reverting - just make sure it's not a master CSS file */ if ( $css['css_set_id'] > 0 ) { $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( $setID, TRUE ); //----------------------------------------- // 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 * * 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' ); * */ 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'], 0 ); //----------------------------------------- // 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'] = ''; if ( $type == 'groupNames' ) { $templates[ $r['template_group'] ] = $r; } else if ( $type == 'groupTemplates' OR $type == 'groupTemplatesNoContent' ) { $r['_templateSize'] = IPSLib::sizeFormat( IPSLib::strlenToBytes( strlen( $r['template_content'] ) ) ); if ( $type == 'groupTemplatesNoContent' ) { unset( $r['template_data'] ); unset( $r['template_content'] ); } $templates[ strtolower($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, 2 ) == '__' ) { 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' => 0 ); $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::sizeFormat( IPSLib::strlenToBytes( strlen( $r['template_content'] ) ) ); if ( $type == 'groupTemplatesNoContent' ) { unset( $r['template_data'] ); unset( $r['template_content'] ); } $templates[ strtolower($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 * * Exception Codes: * NO_SUCH_TEMPLATE: Could not locate template id# * */ 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'] ) ? 1 : 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) * * Exception Codes: * NO_SUCH_TEMPLATE: Could not locate template id# * CANNOT_REMOVE: Cannot revert / remove the template bit * */ 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'] == 0 AND $template['template_added_to'] == 0 ) { 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 ( $templates[ strtolower( $template['template_name'] ) ]['template_id'] ) { return $this->fetchTemplateBitForEdit( $templates[ strtolower( $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 * * Exception Codes: * TEMPLATE_EXISTS: Template bit name already exists * SYNTAX_INCORRECT: The php syntax is invalid * */ 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 * * 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 * */ 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, 0 ); $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, 0 ); $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 DirectoryIterator( DOC_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( $_name, 0, 1 ) == '.' ) { 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 DirectoryIterator( DOC_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( $_name, 0, 1 ) == '.' ) { 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_dir( DOC_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 ( @mkdir( DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_images/' . $dir ) ) { @chmod( DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_images/' . $dir, IPS_FOLDER_PERMISSION ); return TRUE; } } /** * Check Emoticon directory exists * * @access public * @param string Dir name * @return boolean */ public function checkEmoticonDirectoryExists( $dir ) { if ( ! is_dir( DOC_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( $_name, 0, 1 ) == '.' ) { 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_file( IPS_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 == 0 ) { /* 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 ] ) ? 1 : 0; } //----------------------------------------- // Got nothing? //----------------------------------------- if ( $forceLoadDB OR ( $setID > 0 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 ] ) ? 1 : 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' => 0 ); $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' => 1 ) ); } 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->fetchTemplates( 0, '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->fetchTemplates( 0, '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->load( IPS_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 ); } */ } }