* Invision Power Services * IP.Board v3.3.4 * Skin Functions * Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $ * * * 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: 10914 $ * */ 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 skinImportExport extends skinCaching { /**#@+ * Registry objects * * @access protected * @var object */ protected $registry; protected $DB; protected $settings; protected $request; protected $lang; protected $member; protected $memberData; protected $cache; protected $caches; /**#@-*/ /** * Constructor * * @access public * @param object Registry object * @return @e void */ public function __construct( ipsRegistry $registry ) { /* Make object */ parent::__construct( $registry ); } /** * Imports a replacements XMLArchive * * @access public * @param string XMLArchive content to import * @param int Set ID to apply to (if desired) * @return int Number of items added */ public function importReplacementsXMLArchive( $content, $setID=0 ) { //----------------------------------------- // INIT //----------------------------------------- $addedCount = 0; $masterKeys = $this->fetchMasterKeys(); $skinMasterKey = ''; //----------------------------------------- // Got anything? //----------------------------------------- $replacements = $this->parseReplacementsXML( $content ); $where = ( is_numeric( $setID ) ) ? 'replacement_set_id=' . $setID : 'replacement_master_key=\'' . $setID . '\''; /* If this is a 'master' skin, then reset master key */ if ( in_array( $setID, $masterKeys ) ) { $skinMasterKey = $setID; $setID = 0; } //----------------------------------------- // Replacements... //----------------------------------------- if ( is_array( $replacements ) ) { /* Get all the keys for this set id */ $this->DB->build( array( 'select' => 'replacement_key', 'from' => 'skin_replacements', 'where' => $where ) ); $this->DB->execute(); $repKeyCache = array(); while( $r = $this->DB->fetch() ) { $repKeyCache[] = $r['replacement_key']; } foreach( $replacements as $replacement ) { if ( $replacement['replacement_key'] ) { /* Until this function is reworked, both update and insert count as 'added' */ $addedCount++; if( in_array( $replacement['replacement_key'], $repKeyCache ) ) { $this->DB->update( 'skin_replacements', array( 'replacement_content' => $replacement['replacement_content'] ), "replacement_key='{$replacement['replacement_key']}' AND " . $where ); } else { $this->DB->insert( 'skin_replacements', array( 'replacement_key' => $replacement['replacement_key'], 'replacement_content' => $replacement['replacement_content'], 'replacement_set_id' => $setID, 'replacement_added_to' => $setID, 'replacement_master_key' => $skinMasterKey ) ); } } } } $this->rebuildReplacementsCache( $setID ); $this->rebuildSkinSetsCache( $setID ); return $addedCount; } /** * Imports a set XMLArchive * * @access public * @param string XMLArchive content to import * @param string Images directory name to use. * @param int [ Set ID to apply to (if desired) ] * @return mixed Number of items added, or bool */ public function importImagesXMLArchive( $content, $imageSetName, $setID=0 ) { //----------------------------------------- // INIT //----------------------------------------- $addedCount = 0; //----------------------------------------- // Got anything? //----------------------------------------- if ( ! strstr( $content, "_addErrorMessage( $this->lang->words['invalidxmlarchivei'] ); return FALSE; } //----------------------------------------- // Grab the XMLArchive class //----------------------------------------- require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/ $xmlArchive = new classXMLArchive(); $xmlArchive->readXML( $content ); if ( ! $xmlArchive->countFileArray() ) { $this->_addErrorMessage( $this->lang->words['emptyxmlarchivei'] ); return FALSE; } $added = $xmlArchive->countFileArray(); //----------------------------------------- // Checks... //----------------------------------------- if ( $this->checkImageDirectoryExists( $imageSetName ) === TRUE ) { /* Already exists... */ $this->_addErrorMessage( sprintf( $this->lang->words['imagediralreadyexists'], $imageSetName ) ); return FALSE; } if ( $this->createNewImageDirectory( $imageSetName ) !== TRUE ) { $this->_addErrorMessage( sprintf( $this->lang->words['imagedircannotcreate'], $imageSetName ) ); return FALSE; } //----------------------------------------- // OK, write it... //----------------------------------------- /* Find the name of the folder */ //preg_match( "#([^/]+?)#", $content, $match ); //$_strip = $match[1]; /* Strip the path */ //$xmlArchive->setStripPath( $_strip ); /* Write it */ if ( $xmlArchive->write( $content, $this->fetchImageDirectoryPath( $imageSetName ) ) === FALSE ) { $this->_addErrorMessage( $this->lang->words['cannotwriteimageset'] ); return FALSE; } //----------------------------------------- // Update set? //----------------------------------------- if ( $setID ) { $this->DB->update( 'skin_collections', array( 'set_image_dir' => $imageSetName ), 'set_id=' . $setID ); /* Rebuild trees */ $this->rebuildTreeInformation( $setID ); /* Now re-load to fetch the tree information */ $newSet = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'skin_collections', 'where' => 'set_id=' . $setID ) ); /* Add to allSkins array for caching functions below */ $newSet['_parentTree'] = unserialize( $newSet['set_parent_array'] ); $newSet['_childTree'] = unserialize( $newSet['set_child_array'] ); $newSet['_userAgents'] = unserialize( $newSet['set_locked_uagent'] ); $newSet['_cssGroupsArray'] = unserialize( $newSet['set_css_groups'] ); $this->registry->output->allSkins[ $setID ] = $newSet; $this->rebuildSkinSetsCache( $setID ); $this->rebuildCSS( $setID ); $this->rebuildReplacementsCache( $setID ); } return $added; } /** * Imports a set XMLArchive * * @access public * @param string XMLArchive content to import * @param int [ Skin set parent. If omitted, it will be made a root skin ] * @param string [ Images directory to use. If omitted, default skin's image dir is used ] * @param string [ Name of skin to create. If omitted, name from skin set is used ] * @param bool [ Whether or not we are attempting to upgrade an existing skin ] * @return mixed bool, or number of items added */ public function importSetXMLArchive( $content, $parentID=0, $imageDir='', $setName='', $upgrading=FALSE ) { //----------------------------------------- // INIT //----------------------------------------- $templates = array(); $csss = array(); $groups = array(); $defaultSkin = array(); $return = array( 'replacements' => 0, 'css' => 0, 'templates' => 0, 'upgrade' => FALSE ); //----------------------------------------- // Got anything? //----------------------------------------- if ( ! strstr( $content, "_addErrorMessage( $this->lang->words['invalidxmlarchivei'] ); return FALSE; } //----------------------------------------- // Make admin group list //----------------------------------------- foreach( $this->caches['group_cache'] as $id => $data ) { if ( $data['g_access_cp'] ) { $groups[] = $id; } } //----------------------------------------- // Grab the XMLArchive class //----------------------------------------- require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/ $xmlArchive = new classXMLArchive(); $xmlArchive->readXML( $content ); if ( ! $xmlArchive->countFileArray() ) { $this->_addErrorMessage( $this->lang->words['emptyxmlarchivei'] ); return FALSE; } //----------------------------------------- // Gather data //----------------------------------------- /* Info */ $infoXml = $xmlArchive->getFile('info.xml'); if( !$infoXml ) { $this->_addErrorMessage( $this->lang->words['noinfoxml'] ); return FALSE; } $info = $this->parseInfoXML( $infoXml ); /* Are we attempting to upgrade? */ $setID = 0; $doUpgrade = FALSE; $new_items = array( 'replacements' => array(), 'css' => array(), 'templates' => array(), ); if ( $info['set_key'] && $upgrading ) { foreach ( $this->caches['skinsets'] as $set_id => $set_data ) { if ( $set_data['set_key'] == $info['set_key'] ) { $setID = $set_id; $doUpgrade = TRUE; $return['upgrade'] = TRUE; break; } } } /* Replacements */ $replacements = $this->parseReplacementsXML( $xmlArchive->getFile( 'replacements.xml' ) ); /* Templates */ foreach( $xmlArchive->asArray() as $path => $fileData ) { if ( $fileData['path'] == 'templates' && $fileData['content'] ) { $templates[ str_replace( '.xml', '', $fileData['filename'] ) ] = $this->parseTemplatesXML( $fileData['content'] ); } } /* Templates */ foreach( $xmlArchive->asArray() as $path => $fileData ) { if ( $fileData['path'] == 'css' ) { $csss[ str_replace( '.xml', '', $fileData['filename'] ) ] = $this->parseCSSXML( $fileData['content'] ); } } if ( ! is_array( $info ) ) { $this->_addErrorMessage( $this->lang->words['noinfoxml'] ); return FALSE; } $info['set_output_format'] = ( $info['set_output_format'] ) ? $info['set_output_format'] : 'html'; //----------------------------------------- // Find default skin //----------------------------------------- foreach( $this->registry->output->allSkins as $id => $data ) { if ( $data['set_is_default'] AND $data['set_output_format'] == $info['set_output_format'] ) { $defaultSkin = $data; break; } } /* Make sure key in unique */ $test = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'skin_collections', 'where' => 'set_key=\'' . $this->DB->addSlashes( $info['set_key'] ) . '\' AND set_id != ' . intval( $setID ) ) ); if ( $test['set_id'] ) { $info['set_key'] .= '_' . time(); } //----------------------------------------- // Build Set Array //----------------------------------------- $newSet = array('set_name' => ( $setName ) ? $setName : $info['set_name'] . ' (Import)', 'set_key' => $info['set_key'], 'set_parent_id' => $parentID, 'set_permissions' => implode( ",", $groups ), 'set_is_default' => 0, 'set_author_name' => $info['set_author_name'], 'set_author_url' => $info['set_author_url'], 'set_image_dir' => ( $imageDir ) ? $imageDir : $defaultSkin['set_image_dir'], 'set_emo_dir' => $defaultSkin['set_emo_dir'], 'set_css_inline' => 1, 'set_output_format' => $info['set_output_format'], 'set_css_groups' => '', 'set_hide_from_list' => 1, // Per Rikki :P 'set_order' => intval( $this->fetchHighestSetPosition() ) + 1, 'set_master_key' => ( isset( $info['set_master_key'] ) ) ? $info['set_master_key'] : 'root', 'set_updated' => time() ); if ( $setID ) { //----------------------------------------- // Update... //----------------------------------------- $this->DB->update( 'skin_collections', array( 'set_author_name' => $info['set_author_name'], 'set_author_url' => $info['set_author_url'], 'set_updated' => time(), ), 'set_id=' . $setID ); } else { //----------------------------------------- // Insert... //----------------------------------------- $this->DB->insert( 'skin_collections', $newSet ); $setID = $this->DB->getInsertId(); } /* Rebuild trees */ $this->rebuildTreeInformation( $setID ); /* Now re-load to fetch the tree information */ $newSet = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'skin_collections', 'where' => 'set_id=' . $setID ) ); /* Add to allSkins array for caching functions below */ $newSet['_parentTree'] = unserialize( $newSet['set_parent_array'] ); $newSet['_childTree'] = unserialize( $newSet['set_child_array'] ); $newSet['_userAgents'] = unserialize( $newSet['set_locked_uagent'] ); $newSet['_cssGroupsArray'] = unserialize( $newSet['set_css_groups'] ); $this->registry->output->allSkins[ $setID ] = $newSet; //----------------------------------------- // Replacements... //----------------------------------------- if ( is_array( $replacements ) ) { foreach( $replacements as $replacement ) { if ( $replacement['replacement_key'] ) { $return['replacements']++; $existing_id = 0; /* Check if we need to update or insert */ if ( $doUpgrade ) { $exists = $this->DB->buildAndFetch( array( 'select' => 'replacement_id', 'from' => 'skin_replacements', 'where' => "replacement_key='{$replacement['replacement_key']}' AND replacement_set_id={$setID} AND replacement_added_to={$setID}" ) ); $existing_id = $exists['replacement_id']; } if ( $existing_id ) { $new_items['replacements'][] = $existing_id; $this->DB->update( 'skin_replacements', array( 'replacement_content' => $replacement['replacement_content'] ), "replacement_id=".$existing_id ); } else { $this->DB->insert( 'skin_replacements', array( 'replacement_key' => $replacement['replacement_key'], 'replacement_content' => $replacement['replacement_content'], 'replacement_set_id' => $setID, 'replacement_added_to' => $setID ) ); } } } } //----------------------------------------- // CSS... //----------------------------------------- /* Fetch master CSS */ $_MASTER = $this->fetchCSS( 0 ); if ( is_array( $csss ) ) { foreach( ipsRegistry::$applications as $appDir => $data ) { if ( isset( $csss[ $appDir ] ) && is_array( $csss[ $appDir ] ) ) { foreach( $csss[ $appDir ] as $css ) { if ( $css['css_group'] ) { $return['css']++; $existing_id = 0; /* Check if we need to update or insert */ if ( $doUpgrade ) { $exists = $this->DB->buildAndFetch( array( 'select' => 'css_id', 'from' => 'skin_css', 'where' => "css_group='{$css['css_group']}' AND css_app='{$css['css_app']}' AND css_set_id={$setID}" ) ); $existing_id = $exists['css_id']; } if ( $existing_id ) { $new_items['css'][] = $existing_id; $this->DB->update( 'skin_css', array( 'css_content' => $css['css_content'], 'css_position' => $css['css_position'], 'css_attributes' => $css['css_attributes'], 'css_app_hide' => $css['css_app_hide'], 'css_modules' => str_replace( ' ', '', $css['css_modules'] ), 'css_updated' => time(), 'css_added_to' => ( isset( $_MASTER[ $css['css_group'] ] ) ) ? 0 : $setID ), "css_id=".$existing_id ); } else { $this->DB->insert( 'skin_css', array( 'css_group' => $css['css_group'], 'css_content' => $css['css_content'], 'css_position' => $css['css_position'], 'css_attributes' => $css['css_attributes'], 'css_app' => $css['css_app'], 'css_app_hide' => $css['css_app_hide'], 'css_modules' => str_replace( ' ', '', $css['css_modules'] ), 'css_updated' => time(), 'css_set_id' => $setID, 'css_added_to' => ( isset( $_MASTER[ $css['css_group'] ] ) ) ? 0 : $setID ) ); } } } } } } //----------------------------------------- // Templates - only import apps we have... //----------------------------------------- /* Fetch all master items */ $_MASTER = $this->fetchTemplates( 0, 'allNoContent' ); if ( is_array( $templates ) ) { foreach( ipsRegistry::$applications as $appDir => $data ) { if ( array_key_exists( $appDir, $templates ) ) { foreach( $templates[ $appDir ] as $template ) { if ( $template['template_group'] AND $template['template_name'] ) { /* Figure out if this is added by a user or not */ $isAdded = ( is_array( $_MASTER[ $template['template_group'] ][ strtolower( $template['template_name'] ) ] ) AND ! $_MASTER[ $template['template_group'] ][ strtolower( $template['template_name'] ) ]['template_user_added'] ) ? 0 : 1; $return['templates']++; $existing_id = 0; /* Check if we need to update or insert */ if ( $doUpgrade ) { $exists = $this->DB->buildAndFetch( array( 'select' => 'template_id', 'from' => 'skin_templates', 'where' => "template_set_id={$setID} AND template_group='{$template['template_group']}' AND template_name='{$template['template_name']}'" ) ); $existing_id = $exists['template_id']; } if ( $existing_id ) { $new_items['templates'][] = $existing_id; $this->DB->update( 'skin_templates', array( 'template_content' => $template['template_content'], 'template_data' => $template['template_data'], 'template_updated' => $template['template_updated'], 'template_removable' => 1, 'template_user_edited' => 1, 'template_user_added' => $isAdded, 'template_added_to' => $setID ), "template_id=".$existing_id ); } else { $this->DB->insert( 'skin_templates', array( 'template_set_id' => $setID, 'template_group' => $template['template_group'], 'template_content' => $template['template_content'], 'template_name' => $template['template_name'], 'template_data' => $template['template_data'], 'template_updated' => $template['template_updated'], 'template_removable' => 1, 'template_user_edited' => 1, 'template_user_added' => $isAdded, 'template_added_to' => $setID ) ); } } } } } } //----------------------------------------- // If upgrading, and there are items from an old // skin not in the new one, delete the old elements // This probably won't ever come up, but I'm anal retentive :P //----------------------------------------- if ( $doUpgrade ) { if ( count( $new_items['replacements'] ) ) { $this->DB->delete( 'skin_replacements', "replacement_set_id={$setID} AND replacement_id NOT IN (" . implode( ',', $new_items['replacements']) . ")" ); } if ( count( $new_items['css'] ) ) { $this->DB->delete( 'skin_css', "css_set_id={$setID} AND css_id NOT IN (" . implode( ',', $new_items['css']) . ")" ); } if ( count( $new_items['templates'] ) ) { $this->DB->delete( 'skin_templates', "template_set_id={$setID} AND template_id NOT IN (" . implode( ',', $new_items['templates']) . ")" ); } } //----------------------------------------- // Re-cache //----------------------------------------- $this->rebuildReplacementsCache( $setID ); $this->rebuildCSS( $setID ); $this->rebuildPHPTemplates( $setID ); $this->rebuildSkinSetsCache(); //----------------------------------------- // Done.... //----------------------------------------- return $return; } /** * Parses an CSS XML file * * @access public * @param string XML * @return array */ public function parseTemplatesXML( $xmlContents ) { //----------------------------------------- // XML //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); $return = array(); //----------------------------------------- // Get information file //----------------------------------------- $xml->loadXML( $xmlContents ); foreach( $xml->fetchElements( 'template' ) as $xmlelement ) { $data = $xml->fetchElementsFromRecord( $xmlelement ); if ( is_array( $data ) ) { $return[] = $data; } } return $return; } /** * Parses an CSS XML file * * @access public * @param string XML * @return array */ public function parseCSSXML( $xmlContents ) { if( ! $xmlContents ) { return ''; } //----------------------------------------- // XML //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); $return = array(); //----------------------------------------- // Get information file //----------------------------------------- $xml->loadXML( $xmlContents ); foreach( $xml->fetchElements( 'cssfile' ) as $xmlelement ) { $data = $xml->fetchElementsFromRecord( $xmlelement ); if ( is_array( $data ) ) { $return[] = $data; } } return $return; } /** * Parses an replacements XML file * * @access public * @param string XML * @return array */ public function parseReplacementsXML( $xmlContents ) { if( ! $xmlContents ) { return ''; } //----------------------------------------- // XML //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); $return = array(); //----------------------------------------- // Get information file //----------------------------------------- $xml->loadXML( $xmlContents ); foreach( $xml->fetchElements( 'replacement' ) as $xmlelement ) { $data = $xml->fetchElementsFromRecord( $xmlelement ); if ( is_array( $data ) ) { $return[] = $data; } } return $return; } /** * Parses an info XML file * * @access public * @param string XML * @return array */ public function parseInfoXML( $xmlContents ) { //----------------------------------------- // XML //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Get information file //----------------------------------------- $xml->loadXML( $xmlContents ); foreach( $xml->fetchElements( 'data' ) as $xmlelement ) { $data = $xml->fetchElementsFromRecord( $xmlelement ); } return $data; } /** * Generate an XML archive for an image set * * @access public * @param string Image Directory * @return mixed bool, or xml contents */ public function generateImagesXMLArchive( $imgDir ) { //----------------------------------------- // Reset handlers //----------------------------------------- $this->_resetErrorHandle(); $this->_resetMessageHandle(); //----------------------------------------- // Does this image directory exist? //----------------------------------------- if ( $this->checkImageDirectoryExists( $imgDir ) !== TRUE ) { $this->_addErrorMessage( sprintf( $this->lang->words['imagedirnotexists'], $imgDir ) ); return FALSE; } //----------------------------------------- // Create new XML archive... //----------------------------------------- require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/ $xmlArchive = new classXMLArchive(); $xmlArchive->setStripPath( $this->fetchImageDirectoryPath( $imgDir ) ); $xmlArchive->add( $this->fetchImageDirectoryPath( $imgDir ) ); return $xmlArchive->getArchiveContents(); } /** * Generate XML Archive for skin set * * @access public * @param int Skin set ID * @param boolean Modifications in this set only * @param array [Array of apps to export from. Default is all] * @return string XML */ public function generateSetXMLArchive( $setID=0, $setOnly=FALSE, $appslimit=null ) { //----------------------------------------- // INIT //----------------------------------------- $templates = array(); $csss = array(); $replacements = ""; $css = ""; $setData = $this->fetchSkinData( $setID ); //----------------------------------------- // Reset handlers //----------------------------------------- $this->_resetErrorHandle(); $this->_resetMessageHandle(); //----------------------------------------- // First up... fetch templates //----------------------------------------- foreach( ipsRegistry::$applications as $appDir => $data ) { if ( is_array( $appslimit ) AND ! in_array( $appDir, $appslimit ) ) { continue; } if ( !empty( $data['app_enabled'] ) ) { $templates[ $appDir ] = $this->generateTemplateXML( $appDir, $setID, $setOnly ); $csss[ $appDir ] = $this->generateCSSXML( $appDir, $setID, $setOnly ); } } //----------------------------------------- // Replacements //----------------------------------------- $replacements = $this->generateReplacementsXML( $setID, $setOnly ); //----------------------------------------- // Information //----------------------------------------- $info = $this->generateInfoXML( $setID ); //----------------------------------------- // De-bug //----------------------------------------- foreach( $templates as $app_dir => $templateXML ) { IPSDebug::addLogMessage( "Template Export: $app_dir\n".$templateXML, 'admin-setExport', false, true, true ); } foreach( $csss as $app_dir => $cssXML ) { IPSDebug::addLogMessage( "CSS Export: $app_dir\n".$cssXML, 'admin-setExport', false, true ); } IPSDebug::addLogMessage( "Replacements Export:\n".$replacements, 'admin-setExport', false, true ); IPSDebug::addLogMessage( "Info Export:\n".$info, 'admin-setExport', false, true ); //----------------------------------------- // Create new XML archive... //----------------------------------------- require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/ $xmlArchive = new classXMLArchive(); /* Add in version numbers */ $version = IPSLib::fetchVersionNumber(); $xmlArchive->addRootTagValues( array( 'ipbLongVersion' => $version['long'], 'ipbHumanVersion' => $version['human'] ) ); # Templates foreach( $templates as $app_dir => $templateXML ) { $xmlArchive->add( $templateXML, "templates/" . $app_dir . ".xml" ); } # CSS foreach( $csss as $app_dir => $cssXML ) { $xmlArchive->add( $cssXML, "css/" . $app_dir . ".xml" ); } # Replacements $xmlArchive->add( $replacements, "replacements.xml" ); # Information $xmlArchive->add( $info, 'info.xml' ); return $xmlArchive->getArchiveContents(); } /** * Export all Apps skin files * * @access public * @param int [Set ID - 0/root if omitted] * @param bool Include root bits in any XML export. Default is true * @return @e void */ public function exportAllAppTemplates( $setID=0, $setOnly=TRUE ) { //----------------------------------------- // Reset handlers //----------------------------------------- $this->_resetErrorHandle(); $this->_resetMessageHandle(); if ( $setID == 0 ) { /* This is which skins we want to export for default installations */ $skinIDs = array_values( $this->remapData['export'] ); } else { $skinIDs = array( $setID ); } foreach( $skinIDs as $setID ) { foreach( ipsRegistry::$applications as $app_dir => $app_data ) { if ( ! file_exists( IPSLib::getAppDir( $app_dir ) . '/xml' ) ) { $this->_addErrorMessage( IPSLib::getAppDir( $app_dir ) . $this->lang->words['xmldirmissing'] ); continue; } else if ( ! is_writable( IPSLib::getAppDir( $app_dir ) . '/xml' ) ) { if ( ! @chmod( IPSLib::getAppDir( $app_dir ) . '/xml', 0755 ) ) { $this->_addErrorMessage( IPSLib::getAppDir( $app_dir ) . $this->lang->words['xmldirnotwrite'] ); continue; } } $this->exportTemplateAppXML( $app_dir, $setID, $setOnly ); } } } /** * Export all Apps CSS * * @access public * @param int [Set ID - 0/root if omitted] * @return @e void */ public function exportAllAppCSS( $setID=0 ) { //----------------------------------------- // Reset handlers //----------------------------------------- $this->_resetErrorHandle(); $this->_resetMessageHandle(); if ( $setID == 0 ) { /* This is which skins we want to export for default installations */ $skinIDs = array_values( $this->remapData['export'] ); } else { $skinIDs = array( $setID ); } foreach( $skinIDs as $setID ) { foreach( ipsRegistry::$applications as $app_dir => $app_data ) { $file = IPSLib::getAppDir( $app_dir ) . '/xml/' . $app_dir . '_css.xml'; if ( ! file_exists( IPSLib::getAppDir( $app_dir ) . '/xml' ) ) { $this->_addErrorMessage( IPSLib::getAppDir( $app_dir ) . $this->lang->words['xmldirmissing'] ); continue; } else if ( ! is_writable( IPSLib::getAppDir( $app_dir ) . '/xml' ) ) { if ( ! @chmod( IPSLib::getAppDir( $app_dir ) . '/xml', 0755 ) ) { $this->_addErrorMessage( IPSLib::getAppDir( $app_dir ) . $this->lang->words['xmldirnotwrite'] ); continue; } } $this->exportCSSAppXML( $app_dir, $setID ); } } } /** * Import all Apps skin files * * @todo See Matt, this needs fixing! * @access public * @return @e void */ public function importAllAppTemplates() { //----------------------------------------- // Reset handlers //----------------------------------------- $this->_resetErrorHandle(); $this->_resetMessageHandle(); foreach( ipsRegistry::$applications as $app_dir => $app_data ) { $file = IPSLib::getAppDir( $app_dir ) . '/xml/' . $app_dir . '_templates.xml'; if ( ! is_file( $file ) ) { $this->_addMessage( $app_dir . $this->lang->words['importnothingtoimport'] ); continue; } else { $return = $this->importTemplateAppXML( $app_dir, 0 ); $this->_addMessage( sprintf( $this->lang->words['importaddupdate'], $app_dir, $return['updateCount'], $return['insertCount'] ) ); } } } /** * Generate the master skin set files * * @access public * @param array Array of IDs * @return string XML contents */ public function generateMasterSkinSetXML( $skinIDs ) { //----------------------------------------- // INIT //----------------------------------------- $classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/useragents/userAgentFunctions.php', 'userAgentFunctions' ); $userAgentFunctions = new $classToLoad( $this->registry ); $skins = array(); $setid = 1; $exports = array_values( $this->remapData['export'] ); $remap = array( 'mobile' => array( 'set_id' => 2, 'set_name' => 'IP.Board Mobile', 'set_key' => 'mobile', 'set_master_key' => 'mobile', 'set_output_format' => 'html', 'set_image_dir' => 'mobile', 'set_locked_uagent' => serialize( $userAgentFunctions->getMobileSkinUserAgents() ) ), 'xmlskin' => array( 'set_id' => 3, 'set_name' => 'IP.Board XML', 'set_key' => 'xmlskin', 'set_master_key' => 'xmlskin', 'set_output_format' => 'xml', 'set_image_dir' => 'master' ) ); /* Figure out ID 0 */ if ( in_array( 0, $skinIDs ) OR in_array( 'root', $skinIDs ) ) { $cssSkinCollections = array(); $_css = $this->fetchCSS( 0 ); foreach( $_css as $name => $css ) { /* Build skin set row*/ $cssSkinCollections[ $css['css_position'] . '.' . $css['css_id'] ] = array( 'css_group' => $css['css_group'], 'css_position' => $css['css_position'] ); } $setid++; $skins[ 0 ] = array( 'set_id' => 1, 'set_name' => 'IP.Board', 'set_key' => 'default', 'set_parent_id' => 0, 'set_parent_array' => serialize( array() ), 'set_child_array' => serialize( array() ), 'set_permissions' => '*', 'set_is_default' => 1, 'set_author_name' => 'Invision Power Services, Inc', 'set_author_url' => 'http://www.invisionpower.com', 'set_image_dir' => 'master', 'set_emo_dir' => 'default', 'set_css_inline' => 1, 'set_css_groups' => serialize( $cssSkinCollections ), 'set_added' => time(), 'set_updated' => time(), 'set_output_format' => 'html', 'set_locked_uagent' => '', 'set_hide_from_list' => 0, 'set_master_key' => 'root' ); } foreach( $exports as $_id ) { if ( $_id != 'root' AND in_array( $_id, $skinIDs ) ) { $cssSkinCollections = array(); $_css = $this->fetchCSS( $_id ); foreach( $_css as $name => $css ) { /* Build skin set row*/ $cssSkinCollections[ $css['css_position'] . '.' . $css['css_id'] ] = array( 'css_group' => $css['css_group'], 'css_position' => $css['css_position'] ); } $setid++; $skins[ $remap[ $_id ]['set_id'] ] = array( 'set_id' => $remap[ $_id ]['set_id'], 'set_name' => $remap[ $_id ]['set_name'], 'set_key' => $remap[ $_id ]['set_key'], 'set_parent_id' => 0, 'set_parent_array' => serialize( array() ), 'set_child_array' => serialize( array() ), 'set_permissions' => '*', 'set_is_default' => ( $remap[ $_id ]['set_master_key'] == 'root' ) ? 1 : 0, 'set_author_name' => 'Invision Power Services, Inc', 'set_author_url' => 'http://www.invisionpower.com', 'set_image_dir' => $remap[ $_id ]['set_image_dir'], 'set_emo_dir' => 'default', 'set_css_inline' => 1, 'set_css_groups' => serialize( $cssSkinCollections ), 'set_added' => time(), 'set_updated' => time(), 'set_output_format' => $remap[ $_id ]['set_output_format'], 'set_locked_uagent' => ( isset( $remap[ $_id ]['set_locked_uagent'] ) ) ? $remap[ $_id ]['set_locked_uagent'] : '', 'set_hide_from_list' => 0, 'set_master_key' => $remap[ $_id ]['set_master_key'] ); } } if ( count( $skins ) != count( $skinIDs ) ) { /* Grab the rest */ $this->DB->build( array( 'select' => '*', 'from' => 'skin_collections', 'where' => 'set_id IN (' . implode( ",", $skinIDs ) . ')' ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { /* Ensure settings */ $row['set_id'] = $setid; $row['set_permissions'] = '*'; $row['set_hide_from_list'] = 0; $row['set_css_inline'] = 1; $skins[ $row['set_id'] ] = $row; $setid++; } } //----------------------------------------- // Grab the XML parser //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Loop through... //----------------------------------------- $xml->newXMLDocument(); $xml->addElement( 'skinsets' ); foreach( $skins as $id => $setData ) { $xml->addElementAsRecord( 'skinsets', 'set', $setData ); } return $xml->fetchDocument(); } /** * Generate XML Replacements data file * * @access public * @param int Set ID * @param boolean Just get the changes for this set (if TRUE) * @return mixed bool, or XML */ public function generateReplacementsXML( $setID=0, $setOnly=FALSE ) { //----------------------------------------- // INIT //----------------------------------------- $replacements = array(); //----------------------------------------- // Grab the CSS //----------------------------------------- if ( $setOnly === TRUE ) { $where = ( is_numeric( $setID ) ) ? 'replacement_set_id=' . $setID : 'replacement_master_key=\'' . $setID . '\''; $this->DB->build( array( 'select' => '*', 'from' => 'skin_replacements', 'where' => $where ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $replacements[ $row['replacement_key'] ] = $row; } } else { $replacements = $this->fetchReplacements( $setID ); } //----------------------------------------- // Grab the XML parser //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Loop through... //----------------------------------------- $xml->newXMLDocument(); $xml->addElement( 'replacements' ); foreach( $replacements as $key => $replacementsData ) { unset( $replacementsData['replacement_id'] ); unset( $replacementsData['replacement_added_to'] ); unset( $replacementsData['theorder'] ); unset( $replacementsData['SAFE_replacement_content'] ); $xml->addElementAsRecord( 'replacements', 'replacement', $replacementsData ); } return $xml->fetchDocument(); } /** * Generate XML CSS data file * * @access public * @param int Set ID * @param boolean Just get the changes for this set (if TRUE) * @return mixed bool, or XML */ public function generateCSSXML( $app_dir='core', $setID=0, $setOnly=FALSE ) { //----------------------------------------- // INIT //----------------------------------------- $css = array(); $gotSomething = FALSE; //----------------------------------------- // Grab the CSS //----------------------------------------- if ( $setOnly === TRUE AND $setID > 0 ) { $this->DB->build( array( 'select' => '*', 'from' => 'skin_css', 'where' => 'css_set_id=' . $setID ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $css[ $row['css_group'] ] = $row; } } else { $_css = $this->fetchCSS( $setID ); /* Remove set 0 templates */ if ( $setID > 0 ) { if ( is_array( $_css ) AND count( $_css ) ) { foreach( $_css as $name => $cssData ) { if ( $cssData['css_set_id'] > 0 ) { $css[ $name ] = $cssData; } } } } else { $css = $_css; } } if ( ! is_array( $css ) OR ! count( $css ) ) { $this->_addMessage( $this->lang->words['nocsstoexport'] . $app_dir ); return FALSE; } //----------------------------------------- // Grab the XML parser //----------------------------------------- require_once( IPS_KERNEL_PATH . 'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Loop through... //----------------------------------------- $xml->newXMLDocument(); $xml->addElement( 'css' ); foreach( $css as $name => $cssData ) { /* Checking this app dir? */ $cssData['css_app'] = ( $cssData['css_app'] ) ? $cssData['css_app'] : 'core'; if ( $cssData['css_app'] != $app_dir ) { continue; } $gotSomething = TRUE; unset( $cssData['css_id'] ); unset( $cssData['css_added_to'] ); unset( $cssData['theorder'] ); unset( $cssData['_cssSize'] ); $xml->addElementAsRecord( 'css', 'cssfile', $cssData ); } if ( ! $gotSomething ) { $this->_addMessage( $this->lang->words['nocsstoexport'] . $app_dir ); return FALSE; } return $xml->fetchDocument(); } /** * Generate XML template data file * * @access public * @param string App * @param int Set ID * @param boolean Just get the changes for this set (if TRUE) * @return mixed bool, or XML */ public function generateTemplateXML( $app, $setID=0, $setOnly=FALSE ) { //----------------------------------------- // INIT //----------------------------------------- $templateGroups = array(); //----------------------------------------- // XML //----------------------------------------- $infoXML = IPSLib::getAppDir( $app ) . '/xml/information.xml'; if ( ! is_file( $infoXML ) ) { $this->_addErrorMessage( $this->lang->words['couldnotlocate'] . $infoXML ); return FALSE; } require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Get information file //----------------------------------------- $xml->load( $infoXML ); foreach( $xml->fetchElements( 'template' ) as $template ) { $name = $xml->fetchItem( $template ); $match = $xml->fetchAttribute( $template, 'match' ); if ( $name ) { $templateGroups[ $name ] = $match; } } if ( ! is_array( $templateGroups ) OR ! count( $templateGroups ) ) { $this->_addMessage( sprintf( $this->lang->words['nothingtoexportforapp'], $app ) ); return FALSE; } //----------------------------------------- // Fetch templates //----------------------------------------- $templates = array(); if ( $setOnly === TRUE AND $setID > 0 ) { $this->DB->build( array( 'select' => '*', 'from' => 'skin_templates', 'where' => 'template_set_id=' . $setID ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $templates[ $row['template_group'] ][ strtolower( $row['template_name'] ) ] = $row; } } else { $_templates = $this->fetchTemplates( $setID ); /* Remove set 0 templates */ if ( $setID > 0 ) { if ( is_array( $_templates ) AND count( $_templates ) ) { foreach( $_templates as $group => $data ) { foreach( $data as $name => $templateData ) { if ( $templateData['template_set_id'] > 0 ) { $templates[ $group ][ $name ] = $templateData; } } } } } else { $templates = $_templates; } } //----------------------------------------- // Loop through... //----------------------------------------- $xml->newXMLDocument(); $xml->addElement( 'templates', '', array( 'application' => $app, 'templategroups' => serialize( $templateGroups ) ) ); if ( ! is_array( $templates ) OR ! count( $templates ) ) { $this->_addMessage( sprintf( $this->lang->words['nogroupsforexportapp'], $app ) ); return FALSE; } $added = 0; foreach( $templates as $group => $data ) { $_okToGo = FALSE; foreach( $templateGroups as $name => $match ) { if ( $match == 'contains' ) { if ( stristr( $group, $name ) ) { $_okToGo = TRUE; break; } } else if ( $group == $name ) { $_okToGo = TRUE; } } /* If this is the core app, allow any custom bits also */ if ( $app == 'core' ) { $_data = $data; $test = array_shift( $_data ); if ( $test['template_user_added'] ) { $_okToGo = TRUE; } } if ( $_okToGo === TRUE ) { $xml->addElement( 'templategroup', 'templates', array( 'group' => $group ) ); foreach( $data as $name => $templateData ) { unset( $templateData['theorder'] ); unset( $templateData['template_id'] ); unset( $templateData['template_set_id'] ); unset( $templateData['template_added_to'] ); $xml->addElementAsRecord( 'templategroup', 'template', $templateData ); $added++; } } } if ( ! $added ) { $this->_addMessage( $this->lang->words['nothingtoexportfor'] . $app ); return FALSE; } return $xml->fetchDocument(); } /** * Generate XML Information data file * * @access public * @param int Set ID * @return string XML */ public function generateInfoXML( $setID=0 ) { //----------------------------------------- // INIT //----------------------------------------- $data = array(); $setData = $this->fetchSkinData( $setID ); $version = IPSLib::fetchVersionNumber(); //----------------------------------------- // Grab the XML parser //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Loop through... //----------------------------------------- $xml->newXMLDocument(); $xml->addElement( 'info' ); $xml->addElementAsRecord( 'info', 'data', array( 'set_name' => $setData['set_name'], 'set_key' => $setData['set_key'], 'set_author_name' => $setData['set_author_name'], 'set_author_url' => $setData['set_author_url'], 'set_output_format' => $setData['set_output_format'], 'set_master_key' => $setData['set_master_key'], 'ipb_human_version' => $version['human'], 'ipb_long_version' => $version['long'], 'ipb_major_version' => '3' ) ); return $xml->fetchDocument(); } /** * Import CSS for a single app * * @access public * @param string App * @param string Skin key to import * @param int Set ID * @return mixed bool, or number of items added */ public function importCSSAppXML( $app, $skinKey, $setID=0 ) { //----------------------------------------- // INIT //----------------------------------------- $fileXML = IPSLib::getAppDir( $app ) . '/xml/' . $app . '_' . $skinKey . '_css.xml'; $return = array( 'updateCount' => 0, 'insertCount' => 0, 'updateBits' => array(), 'insertBits' => array() ); $masterKeys = $this->fetchMasterKeys(); //----------------------------------------- // File exists //----------------------------------------- if ( ! is_file( $fileXML ) ) { return FALSE; } if ( ! $setID and ! in_array( $skinKey, $masterKeys ) ) { /* Figure out correct set ID based on key */ $skinSetData = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'skin_collections', 'where' => "set_key='" . $skinKey . "'" ) ); $setID = $skinSetData['set_id']; $skinMasterKey = $skinSetData['set_master_key']; } /* If this is a 'master' skin, then reset master key */ if ( in_array( $skinKey, $masterKeys ) ) { $skinMasterKey = $skinKey; $setID = 0; } //----------------------------------------- // Delete all CSS if this is set ID 0 //----------------------------------------- if ( in_array( $skinKey, $masterKeys ) ) { $this->DB->delete( 'skin_css', 'css_set_id=0 AND css_master_key=\'' . $skinMasterKey . '\' AND css_app=\''. addslashes( $app ) . '\'' ); } //----------------------------------------- // Fetch CSS //----------------------------------------- $css = $this->parseCSSXML( file_get_contents( $fileXML ) ); if ( is_array( $css ) ) { foreach( $css as $_css ) { if ( $_css['css_group'] ) { $return['insertCount']++; if ( $setID ) { $this->DB->delete( 'skin_css', 'css_set_id=' . $setID . ' AND css_group=\'' . addslashes( $_css['css_group'] ) . '\' AND css_app=\'' . addslashes( $_css['css_app'] ) . '\'' ); } $this->DB->insert( 'skin_css', array( 'css_group' => $_css['css_group'], 'css_content' => $_css['css_content'], 'css_position' => $_css['css_position'], 'css_updated' => time(), 'css_app' => $_css['css_app'], 'css_app_hide' => $_css['css_app_hide'], 'css_attributes' => $_css['css_attributes'], 'css_modules' => $_css['css_modules'], 'css_master_key' => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '', 'css_set_id' => $setID, 'css_added_to' => $setID ) ); } } } return $return; } /** * Export template CSS into app dirs * * @access public * @param string App to export into * @param int Set ID (0 / root by default ) * @return @e void */ public function exportCSSAppXML( $app_dir, $setID=0 ) { //----------------------------------------- // Get it //----------------------------------------- $setData = $this->fetchSkinData( $setID ); $xml = $this->generateCSSXML( $app_dir, $setID ); //----------------------------------------- // Attempt to write... //----------------------------------------- /* Set file name */ $file = IPSLib::getAppDir( $app_dir ) . '/xml/' . $app_dir . '_' . $setData['set_key'] . '_css.xml'; /* Attempt to unlink first */ @unlink( $file ); if ( $xml ) { if ( is_file( $file ) AND ! IPSLib::isWritable( $file ) ) { $this->_addErrorMessage( $file . ' ' . $this->lang->words['css_isnotwritable'] ); return FALSE; } file_put_contents( $file, $xml ); $this->_addMessage( sprintf( $this->lang->words['csscreatedmsg'], $app_dir, $setData['set_key'] ) ); } } /** * Export template XML into app dirs * * @access public * @param string App to export into * @param int [Set ID (0/root if omitted)] * @param bool Include root bits in any XML export. Default is true * @return @e void */ public function exportTemplateAppXML( $app_dir, $setID=0, $setOnly=TRUE ) { //----------------------------------------- // Get it //----------------------------------------- $setData = $this->fetchSkinData( $setID ); $xml = $this->generateTemplateXML( $app_dir, $setID, $setOnly ); //----------------------------------------- // Attempt to write... //----------------------------------------- /* Set file name */ $file = IPSLib::getAppDir( $app_dir ) . '/xml/' . $app_dir . '_' . $setData['set_key'] . '_templates.xml'; /* Attempt to unlink first */ @unlink( $file ); if ( $xml ) { if ( is_file( $file ) AND ! IPSLib::isWritable( $file ) ) { $this->_addErrorMessage( $file . ' ' . $this->lang->words['css_isnotwritable'] ); return FALSE; } file_put_contents( $file, $xml ); $this->_addMessage( sprintf( $this->lang->words['templatescreatedmsg'], $app_dir, $setData['set_key'] ) ); } } /** * Import a single app * * @access public * @param string App * @param string Skin key to import * @param int Set ID * @param boolean Set the edited / added flags to 0 (from install, upgrade) * @return mixed bool, or array of info */ public function importTemplateAppXML( $app, $skinKey, $setID=0, $ignoreAddedEditedFlag=false ) { //----------------------------------------- // INIT //----------------------------------------- $templateGroups = array(); $templates = array(); $fileXML = IPSLib::getAppDir( $app ) . '/xml/' . $app . '_' . $skinKey . '_templates.xml'; $infoXML = IPSLib::getAppDir( $app ) . '/xml/information.xml'; $return = array( 'updateCount' => 0, 'insertCount' => 0, 'updateBits' => array(), 'insertBits' => array() ); $masterKeys = $this->fetchMasterKeys(); if( ! is_file($fileXML) ) { return $return; } if ( ! $setID and ! in_array( $skinKey, $masterKeys ) ) { /* Figure out correct set ID based on key */ $skinSetData = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'skin_collections', 'where' => "set_key='" . $skinKey . "'" ) ); $setID = $skinSetData['set_id']; $skinMasterKey = $skinSetData['set_master_key']; } /* Set ignore flag correctly */ if ( ! empty( $skinKey ) AND in_array( $skinKey, $masterKeys ) ) { $ignoreAddedEditedFlag = true; } /* If this is a 'master' skin, then reset master key */ if ( in_array( $skinKey, $masterKeys ) ) { $skinMasterKey = $skinKey; $setID = 0; } //----------------------------------------- // XML //----------------------------------------- require_once( IPS_KERNEL_PATH.'classXML.php' );/*noLibHook*/ $xml = new classXML( IPS_DOC_CHAR_SET ); //----------------------------------------- // Get information file //----------------------------------------- $xml->load( $infoXML ); foreach( $xml->fetchElements( 'template' ) as $template ) { $name = $xml->fetchItem( $template ); $match = $xml->fetchAttribute( $template, 'match' ); if ( $name ) { $templateGroups[ $name ] = $match; } } if ( ! is_array( $templateGroups ) OR ! count( $templateGroups ) ) { $this->_addMessage( $this->lang->words['nothingtoexportfor'] . $app ); return FALSE; } //----------------------------------------- // Fetch templates //----------------------------------------- $_templates = $this->fetchTemplates( $setID , 'allNoContent' ); $_MASTER = $this->fetchTemplates( $skinMasterKey, 'allNoContent' ); //----------------------------------------- // Loop through... //----------------------------------------- foreach( $_templates as $group => $data ) { $_okToGo = FALSE; foreach( $templateGroups as $name => $match ) { if ( $match == 'contains' ) { if ( stristr( $group, $name ) ) { $_okToGo = TRUE; break; } } else if ( $group == $name ) { $_okToGo = TRUE; } } if ( $_okToGo === TRUE ) { foreach( $data as $name => $templateData ) { $templates[ $group ][ $name ] = $templateData; } } } //----------------------------------------- // Wipe the master skins //----------------------------------------- if ( in_array( $skinKey, $masterKeys ) ) { $this->DB->delete( 'skin_templates', "template_master_key='" . $skinKey . "' AND template_group IN ('" . implode( "','", array_keys( $templates ) ) . "') AND template_user_added=0 AND template_added_to=0" ); /* Now wipe the array so we enforce creation */ unset( $templates ); } //----------------------------------------- // Now grab the actual XML files //----------------------------------------- $xml->load( $fileXML ); foreach( $xml->fetchElements( 'template' ) as $templatexml ) { $data = $xml->fetchElementsFromRecord( $templatexml ); /* Figure out if this is added by a user or not */ if ( $ignoreAddedEditedFlag === TRUE ) { $isAdded = 0; $isEdited = 0; } else { $isAdded = ( is_array( $_MASTER[ $data['template_group'] ][ strtolower( $data['template_name'] ) ] ) AND ! $_MASTER[ $data['template_group'] ][ strtolower( $data['template_name'] ) ]['template_user_added'] ) ? 0 : 1; $isEdited = 1; } if ( is_array( $templates[ $data['template_group'] ][ strtolower( $data['template_name'] ) ] ) AND $templates[ $data['template_group'] ][ strtolower( $data['template_name'] ) ]['template_set_id'] == $setID ) { /* Update.. */ $return['updateCount']++; $return['updateBits'][] = $data['template_name']; $this->DB->update( 'skin_templates', array( 'template_content' => $data['template_content'], 'template_data' => $data['template_data'], 'template_user_edited' => $isEdited, 'template_user_added' => $isAdded, 'template_master_key' => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '', 'template_updated' => time() ), 'template_set_id=' . $setID . " AND template_group='" . $data['template_group'] . "' AND template_name='" . $data['template_name'] . "'" ); } else { /* Add... */ $return['insertCount']++; $return['insertBits'][] = $data['template_name']; $this->DB->insert( 'skin_templates', array( 'template_set_id' => $setID, 'template_group' => $data['template_group'], 'template_content' => $data['template_content'], 'template_name' => $data['template_name'], 'template_data' => $data['template_data'], 'template_removable' => ( $setID ) ? $data['template_removable'] : 0, 'template_added_to' => $setID, 'template_user_edited' => $isEdited, 'template_user_added' => $isAdded, 'template_master_key' => ( in_array( $skinKey, $masterKeys ) ) ? $skinKey : '', 'template_updated' => time() ) ); } } return $return; } }