/** * Imports language packs from an xml file and updates the database and recaches the languages * * @param integer $lang_id ID of the language pack to import * @param bool $in_dev Set to 1 for developer language import * @param bool $no_return If set to 1, this function will return a value, rather than outputting data * @param string $app_override Overrides the application for which languages are being imported * @param bool $skip_charset Skips charset conversion in the XML file (useful during upgrade routine as strings don't need to be converted) * @return mixed */ public function imprtFromXML($lang_id = 0, $in_dev = 0, $no_return = 0, $app_override = '', $skip_charset = false) { //----------------------------------------- // Set version.. //----------------------------------------- $LATESTVERSION = IPSLib::fetchVersionNumber(); //----------------------------------------- // INDEV? //----------------------------------------- if ($in_dev) { $_FILES['FILE_UPLOAD']['name'] = ''; } else { if ($this->request['file_location']) { $this->request['file_location'] = IPS_ROOT_PATH . $this->request['file_location']; } } //----------------------------------------- // Not an upload? //----------------------------------------- if ($_FILES['FILE_UPLOAD']['name'] == "" or !$_FILES['FILE_UPLOAD']['name'] or $_FILES['FILE_UPLOAD']['name'] == "none") { //----------------------------------------- // Check and load from server //----------------------------------------- if (!$this->request['file_location']) { $this->registry->output->global_message = $this->lang->words['l_nofile']; $this->languagesList(); return; } if (!is_file($this->request['file_location'])) { $this->registry->output->global_message = $this->lang->words['l_noopen'] . $this->request['file_location']; $this->languagesList(); return; } if (preg_match('#\\.gz$#', $this->request['file_location'])) { if ($FH = @gzopen($this->request['file_location'], 'rb')) { while (!@gzeof($FH)) { $content .= @gzread($FH, 1024); } @gzclose($FH); } } else { $content = file_get_contents($this->request['file_location']); } $originalContent = $content; //----------------------------------------- // Extract archive //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; /*noLibHook*/ $xmlarchive = new classXMLArchive(); //----------------------------------------- // Read the archive //----------------------------------------- $xmlarchive->readXML($content); //----------------------------------------- // Get the data //----------------------------------------- $content = ''; foreach ($xmlarchive->asArray() as $k => $f) { if ($k == 'language_entries.xml') { $content = $f['content']; break; } } //----------------------------------------- // No content from de-archiving, must not // be archive, but rather raw XML file //----------------------------------------- if ($content == '' and strpos($originalContent, "<languageexport") !== false) { $content = $originalContent; } } else { //----------------------------------------- // Get uploaded schtuff //----------------------------------------- $tmp_name = $_FILES['FILE_UPLOAD']['name']; $tmp_name = preg_replace('#\\.gz$#', "", $tmp_name); if ($_FILES['FILE_UPLOAD']['error']) { switch ($_FILES['FILE_UPLOAD']['error']) { case 1: $this->registry->output->global_message = sprintf($this->lang->words['lang_upload_too_large'], ini_get('upload_max_filesize')); $this->languagesList(); return; break; default: $this->registry->output->global_message = $this->lang->words['lang_upload_other_error']; $this->languagesList(); return; break; } } //----------------------------------------- // Get content //----------------------------------------- try { $uploadedContent = $this->registry->adminFunctions->importXml($tmp_name); } catch (Exception $e) { $this->registry->output->showError($e->getMessage()); } //----------------------------------------- // Extract archive //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; /*noLibHook*/ $xmlarchive = new classXMLArchive(); //----------------------------------------- // Read the archive //----------------------------------------- $xmlarchive->readXML($uploadedContent); //----------------------------------------- // Get the data //----------------------------------------- $content = ''; foreach ($xmlarchive->asArray() as $k => $f) { if ($k == 'language_entries.xml') { $content = $f['content']; break; } } //----------------------------------------- // No content from de-archiving, must not // be archive, but rather raw XML file //----------------------------------------- if ($content == '' and strpos($uploadedContent, "<languageexport") !== false) { $content = $uploadedContent; } } //----------------------------------------- // Make sure we have content //----------------------------------------- if (!$content) { if ($no_return) { return; } $this->registry->output->global_message = $this->lang->words['l_badfile']; $this->languagesList(); return; } //----------------------------------------- // Get xml class //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXML.php'; /*noLibHook*/ $xml = new classXML($skip_charset ? 'utf-8' : IPS_DOC_CHAR_SET); $xml->loadXML($content); //----------------------------------------- // Is this full language pack?... //----------------------------------------- foreach ($xml->fetchElements('langinfo') as $lang_data) { $lang_info = $xml->fetchElementsFromRecord($lang_data); $lang_data = array('lang_short' => $lang_info['lang_short'], 'lang_title' => $lang_info['lang_title']); } $lang_ids = array(); $insertId = 0; //----------------------------------------- // Do we have language pack info? //----------------------------------------- if ($lang_data['lang_short']) { //----------------------------------------- // Does this pack already exist //----------------------------------------- $update_lang = $this->DB->buildAndFetch(array('select' => 'lang_id', 'from' => 'core_sys_lang', 'where' => "lang_short='{$lang_data['lang_short']}'")); //----------------------------------------- // If doesn't exist, then create new pack //----------------------------------------- if (!$update_lang['lang_id']) { $this->DB->insert('core_sys_lang', $lang_data); $insertId = $this->DB->getInsertId(); if (@mkdir(IPS_CACHE_PATH . '/cache/lang_cache/' . $insertId)) { @file_put_contents(IPS_CACHE_PATH . 'cache/lang_cache/' . $insertId . '/index.html', ''); @chmod(IPS_CACHE_PATH . '/cache/lang_cache/' . $insertId, IPS_FOLDER_PERMISSION); } //----------------------------------------- // Copy over language bits from default lang //----------------------------------------- $default = $this->DB->buildAndFetch(array('select' => 'lang_id', 'from' => 'core_sys_lang', 'where' => "lang_default=1")); $this->DB->build(array('select' => 'word_app,word_pack,word_key,word_default,word_js', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$default['lang_id']}")); $q = $this->DB->execute(); while ($r = $this->DB->fetch($q)) { $r['lang_id'] = $insertId; $r['word_custom'] = ''; $this->DB->insert('core_sys_lang_words', $r); } //----------------------------------------- // Rebuild IPB and disk caches //----------------------------------------- $this->registry->class_localization->rebuildLanguagesCache(); } else { $insertId = $update_lang['lang_id']; } } //----------------------------------------- // We need to add language bits to every pack.. //----------------------------------------- $this->DB->build(array('select' => 'lang_id', 'from' => 'core_sys_lang')); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_ids[] = $r['lang_id']; } //----------------------------------------- // Init counts array //----------------------------------------- $counts = array('updates' => 0, 'inserts' => 0); //----------------------------------------- // Init a cache array to save entries //----------------------------------------- $lang_entries = array(); if ($app_override) { $this->DB->build(array('select' => "MD5( CONCAT( lang_id, '-', word_app, '-', word_pack, '-', word_key ) ) as word_lookup, word_id, md5(word_default) as word_default, word_default_version", 'from' => 'core_sys_lang_words', 'where' => "word_app='{$app_override}' AND lang_id IN(" . implode(",", $lang_ids) . ")")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_entries[$r['word_lookup']] = $r; } } //----------------------------------------- // Start looping //----------------------------------------- $_lastLookup = ''; foreach ($xml->fetchElements('lang') as $entry) { $lang = $xml->fetchElementsFromRecord($entry); foreach ($lang_ids as $_lang_id) { $lang_entry = array(); //----------------------------------------- // Build db array //----------------------------------------- $db_array = array('lang_id' => $_lang_id, 'word_app' => $app_override ? $app_override : $lang['word_app'], 'word_pack' => $lang['word_pack'], 'word_key' => $lang['word_key'], 'word_default' => $lang['word_default'], 'word_custom' => $in_dev ? '' : $lang['word_custom'], 'word_js' => intval($lang['word_js']), 'word_default_version' => $lang['word_default_version'] ? $lang['word_default_version'] : $LATESTVERSION['long'], 'word_custom_version' => $lang['word_custom_version']); $dbKey = md5($db_array['lang_id'] . '-' . $db_array['word_app'] . '-' . $db_array['word_pack'] . '-' . $db_array['word_key']); $langIdKey = md5($_lang_id . '-' . $db_array['word_app'] . '-' . $db_array['word_pack'] . '-' . $db_array['word_key']); // If the default value hasn't changed, we don't need to update the word_default_version (see bug report 19172) if (md5($lang['word_default']) == $lang_entries[$dbKey]['word_default']) { $db_array['word_default_version'] = $lang_entries[$dbKey]['word_default_version']; } //----------------------------------------- // If cached, get from cache //----------------------------------------- if ($lang_entries[$langIdKey]) { $lang_entry = $lang_entries[$langIdKey]; } else { if (!$app_override) { if ($_lastLookup != md5($db_array['word_app'] . '-' . $db_array['word_pack'])) { unset($lang_entries); } $_lastLookup = md5($db_array['word_app'] . '-' . $db_array['word_pack']); $this->DB->build(array('select' => '*', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$_lang_id} AND word_app='{$db_array['word_app']}' AND word_pack='{$db_array['word_pack']}'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_entries[md5($r['lang_id'] . '-' . $r['word_app'] . '-' . $r['word_pack'] . '-' . $r['word_key'])] = $r; } if ($lang_entries[$langIdKey]) { $lang_entry = $lang_entries[$langIdKey]; } } } //----------------------------------------- // Didn't find any match? Must be importing // a new language pack, huh? //----------------------------------------- if (!isset($lang_entry['word_id'])) { //continue 2; } //----------------------------------------- // If there is no new custom lang bit to insert // don't delete what is already there. //----------------------------------------- if (!$db_array['word_custom'] || $insertId > 0 && $insertId != $_lang_id) { unset($db_array['word_custom']); unset($db_array['word_custom_version']); } //----------------------------------------- // Lang bit already exists, update //----------------------------------------- if ($lang_entry['word_id'] and (!$insertId or $insertId == $_lang_id)) { //----------------------------------------- // Don't update default version //----------------------------------------- // This causes no languages to show "out of date" on upgrade // @link http://community.invisionpower.com/tracker/issue-31637-no-out-of-date-entries-for-language-string-updates // This WAS added to fix a previously reported bug, however, so need to watch out for this // unset( $db_array['word_default_version'] ); $counts['updates']++; $this->DB->update('core_sys_lang_words', $db_array, "word_id={$lang_entry['word_id']}"); } else { if (!$lang_entry['word_id']) { /* Ensure there is a value to avoid null */ if (!$db_array['word_custom']) { $db_array['word_custom'] = ''; } /* Ensure custom word but isn't added to other packs that simply had missing strings */ if ($insertId and $insertId != $_lang_id) { $db_array['word_custom'] = ''; } $counts['inserts']++; $this->DB->insert('core_sys_lang_words', $db_array); } } unset($lang_entry, $db_array); } } /* Save some memory */ unset($lang_entries); //----------------------------------------- // Recache all our lang packs //----------------------------------------- foreach ($lang_ids as $_lang_id) { $this->cacheToDisk($_lang_id, $app_override); } //----------------------------------------- // Set output message //----------------------------------------- $this->registry->output->global_message = sprintf($this->lang->words['l_updatedcount'], $counts['updates'], $counts['inserts']); if (is_array($this->cache_errors) and count($this->cache_errors)) { $this->registry->output->global_message .= "<br />" . implode("<br />", $this->cache_errors); } //----------------------------------------- // Free a little memory //----------------------------------------- unset($xml); //----------------------------------------- // Update IPB cache //----------------------------------------- $this->registry->class_localization->rebuildLanguagesCache(); //----------------------------------------- // Return! Now! //----------------------------------------- if (!$no_return) { $this->languagesList(); return; } }
/** * Import an emoticon pack * * @return @e void */ public function emoticonsPackImport() { /* Make sure all emoticon directories are writable */ $this->DB->build(array('select' => $this->DB->buildDistinct('emo_set') . ' as folder', 'from' => 'emoticons')); $this->DB->execute(); while ($r = $this->DB->fetch()) { $_folders[] = $r['folder']; } if (count($_folders)) { foreach ($_folders as $folder) { if (!IPSLib::isWritable(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $folder)) { $this->registry->output->global_error = sprintf($this->lang->words['emodir_not_write'], PUBLIC_DIRECTORY . '/style_emoticons/' . $folder); return $this->emoticonsPackSplash(); } } } /* Get the xml file */ try { $content = $this->registry->adminFunctions->importXml('ipb_emoticons.xml'); } catch (Exception $e) { $this->registry->output->showError($e->getMessage()); } /* Check for content */ if (!$content) { $this->registry->output->global_error = $this->lang->words['emo_fail']; return $this->emoticonsPackSplash(); } /* Setup XML */ require_once IPS_KERNEL_PATH . 'classXML.php'; /*noLibHook*/ $xml = new classXML(IPS_DOC_CHAR_SET); require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; /*noLibHook*/ $xmlarchive = new classXMLArchive(); /* Read the archive */ $xmlarchive->readXML($content); /* Get the data file */ $emoticons = array(); $emoticon_data = array(); foreach ($xmlarchive->asArray() as $k => $f) { if ($k == 'emoticon_data.xml') { $emoticon_data = $f; } else { $emoticons[$f['filename']] = $f['content']; } } /* Parse the XML Document */ $xml->loadXML($emoticon_data['content']); /* Make sure we have a destination for these emoicons */ if (!$this->request['emo_set'] and !$this->request['new_emo_set']) { $this->registry->output->global_error = $this->lang->words['emo_specify']; } /* Current emoticon set directory */ $emo_set_dir = trim($this->request['emo_set']); /* New emoticon set directory */ $this->request['new_emo_set'] = preg_replace('/[^a-zA-Z0-9\\-_]/', "", $this->request['new_emo_set']); /* Create the new set */ if ($this->request['new_emo_set']) { $emo_set_dir = trim($this->request['new_emo_set']); /* Check to see if the directory already exists */ if (file_exists(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir)) { $this->registry->output->global_error = sprintf($this->lang->words['emo_already'], $emo_set_dir); return $this->emoticonsPackSplash(); } /* Create the directory */ if (@mkdir(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir, IPS_FOLDER_PERMISSION)) { @chmod(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir, IPS_FOLDER_PERMISSION); @file_put_contents(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir . '/index.html', ''); } else { $this->registry->output->global_error = $this->lang->words['emo_ftp']; return $this->emoticonsPackSplash(); } } /* Get a list of current emoticons, if we are not overwriting */ $emo_image = array(); $emo_typed = array(); if ($this->request['overwrite'] != 1) { $this->DB->build(array('select' => '*', 'from' => 'emoticons', 'where' => "emo_set='" . $emo_set_dir . "'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $emo_image[$r['image']] = 1; $emo_typed[$r['typed']] = 1; } } /* Loop through the emoticons in the xml document */ foreach ($xml->fetchElements('emoticon') as $emoticon) { $entry = $xml->fetchElementsFromRecord($emoticon); /* Emoticon Data */ $image = $entry['image']; $typed = $entry['typed']; $click = $entry['clickable']; /* Skip if we're not overwriting */ if ($emo_image[$image] or $emo_typed[$typed]) { continue; } /* Get the extension */ $file_extension = preg_replace('#^.*\\.(.+?)$#si', "\\1", strtolower($image)); /* Make sure it's allowed */ if (!in_array($file_extension, $this->allowed_files)) { continue; } /* Remove any existing emoticon */ @unlink(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir . '/' . $image); $this->DB->delete('emoticons', "typed='{$typed}' and image='{$image}' and emo_set='{$emo_set_dir}'"); /* Create the image in the file system */ if ($FH = fopen(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $emo_set_dir . '/' . $image, 'wb')) { if (fwrite($FH, $emoticons[$image])) { fclose($FH); /* Insert the emoticon record */ $this->DB->insert('emoticons', array('typed' => $typed, 'image' => $image, 'clickable' => $click, 'emo_set' => $emo_set_dir)); } } /* Add the emoticon to all the other directories */ try { foreach (new DirectoryIterator(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/') as $file) { if (!$file->isDot() && $file->isDir()) { if (substr($file->getFilename(), 0, 1) == '.') { continue; } if (!is_file(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $file->getFilename() . '/' . $image)) { $this->DB->delete('emoticons', "typed='{$typed}' and image='{$image}' and emo_set='{$file->getFilename()}'"); if ($FH = @fopen(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_emoticons/' . $file->getFilename() . '/' . $image, 'wb')) { if (fwrite($FH, $emoticons[$image])) { fclose($FH); $this->DB->insert('emoticons', array('typed' => $typed, 'image' => $image, 'clickable' => $click, 'emo_set' => $file->getFilename())); } } } } } } catch (Exception $e) { } } /* Recache and bounce */ $this->emoticonsRebuildCache(); $this->registry->output->global_message = $this->lang->words['emo_xml_good']; $this->emoticonsOverview(); }
/** * 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 ] * @return mixed bool, or number of items added */ public function importSetXMLArchive($content, $parentID = 0, $imageDir = '', $setName = '') { //----------------------------------------- // INIT //----------------------------------------- $templates = array(); $csss = array(); $groups = array(); $defaultSkin = array(); $return = array('replacements' => 0, 'css' => 0, 'templates' => 0); //----------------------------------------- // Got anything? //----------------------------------------- if (!strstr($content, "<xmlarchive")) { $this->_addErrorMessage("The content was not a valid XMLArchive"); 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'; $xmlArchive = new classXMLArchive(); $xmlArchive->readXML($content); if (!$xmlArchive->countFileArray()) { $this->_addErrorMessage("The XMLArchive is empty"); return FALSE; } //----------------------------------------- // Gather data //----------------------------------------- /* Info */ $infoXml = $xmlArchive->getFile('info.xml'); if (!$infoXml) { $this->_addErrorMessage("The info.xml file is empty or was not included"); return FALSE; } $info = $this->parseInfoXML($infoXml); /* 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("The XMLArchive does not contain an info.xml file"); 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; } } //----------------------------------------- // Build Set Array //----------------------------------------- $newSet = array('set_name' => $setName ? $setName : $info['set_name'] . ' (Import)', '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' => 0, 'set_output_format' => $info['set_output_format'], 'set_css_groups' => '', 'set_hide_from_list' => 1, 'set_updated' => time()); //----------------------------------------- // 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']++; $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); $apps = new IPSApplicationsIterator(); if (is_array($csss)) { foreach ($apps as $app) { $appDir = $apps->fetchAppDir(); if (isset($csss[$appDir]) && is_array($csss[$appDir])) { foreach ($csss[$appDir] as $css) { if ($css['css_group']) { $return['css']++; $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'); $apps = new IPSApplicationsIterator(); if (is_array($templates)) { foreach ($apps as $app) { $appDir = $apps->fetchAppDir(); 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']++; $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)); } } } } } //----------------------------------------- // Re-cache //----------------------------------------- $this->rebuildReplacementsCache($setID); $this->rebuildCSS($setID); $this->rebuildPHPTemplates($setID); $this->rebuildSkinSetsCache(); //----------------------------------------- // Done.... //----------------------------------------- return $return; }
/** * Imports language packs from an xml file and updates the database and recaches the languages * * @access public * @param integer $lang_id ID of the language pack to import * @param bool $in_dev Set to 1 for developer language import * @param bool $no_return If set to 1, this function will return a value, rather than outputting data * @param string $app_override Overrides the application for which languages are being imported * @return mixed */ public function imprtFromXML($lang_id = 0, $in_dev = 0, $no_return = 0, $app_override = '') { //----------------------------------------- // Set version.. //----------------------------------------- $LATESTVERSION = IPSLib::fetchVersionNumber(); //----------------------------------------- // INDEV? //----------------------------------------- if ($in_dev) { $_FILES['FILE_UPLOAD']['name'] = ''; } else { if ($this->request['file_location']) { $this->request['file_location'] = IPS_ROOT_PATH . $this->request['file_location']; } } //----------------------------------------- // Not an upload? //----------------------------------------- if ($_FILES['FILE_UPLOAD']['name'] == "" or !$_FILES['FILE_UPLOAD']['name'] or $_FILES['FILE_UPLOAD']['name'] == "none") { //----------------------------------------- // Check and load from server //----------------------------------------- if (!$this->request['file_location']) { $this->registry->output->global_message = $this->lang->words['l_nofile']; $this->languagesList(); return; } if (!file_exists($this->request['file_location'])) { $this->registry->output->global_message = $this->lang->words['l_noopen'] . $this->request['file_location']; $this->languagesList(); return; } if (preg_match("#\\.gz\$#", $this->request['file_location'])) { if ($FH = @gzopen($this->request['file_location'], 'rb')) { while (!@gzeof($FH)) { $content .= @gzread($FH, 1024); } @gzclose($FH); } } else { $content = file_get_contents($this->request['file_location']); } $originalContent = $content; //----------------------------------------- // Extract archive //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; $xmlarchive = new classXMLArchive(); //----------------------------------------- // Read the archive //----------------------------------------- $xmlarchive->readXML($content); //----------------------------------------- // Get the data //----------------------------------------- $content = ''; foreach ($xmlarchive->asArray() as $k => $f) { if ($k == 'language_entries.xml') { $content = $f['content']; break; } } //----------------------------------------- // No content from de-archiving, must not // be archive, but rather raw XML file //----------------------------------------- if ($content == '' and strpos($originalContent, "<languageexport") !== false) { $content = $originalContent; } } else { //----------------------------------------- // Get uploaded schtuff //----------------------------------------- $tmp_name = $_FILES['FILE_UPLOAD']['name']; $tmp_name = preg_replace("#\\.gz\$#", "", $tmp_name); if ($_FILES['FILE_UPLOAD']['error']) { switch ($_FILES['FILE_UPLOAD']['error']) { case 1: $this->registry->output->global_message = sprintf($this->lang->words['lang_upload_too_large'], ini_get('upload_max_filesize')); $this->languagesList(); return; break; default: $this->registry->output->global_message = $this->lang->words['lang_upload_other_error']; $this->languagesList(); return; break; } } //----------------------------------------- // Get content //----------------------------------------- $uploadedContent = $this->registry->adminFunctions->importXml($tmp_name); //----------------------------------------- // Extract archive //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; $xmlarchive = new classXMLArchive(); //----------------------------------------- // Read the archive //----------------------------------------- $xmlarchive->readXML($uploadedContent); //----------------------------------------- // Get the data //----------------------------------------- $content = ''; foreach ($xmlarchive->asArray() as $k => $f) { if ($k == 'language_entries.xml') { $content = $f['content']; break; } } //----------------------------------------- // No content from de-archiving, must not // be archive, but rather raw XML file //----------------------------------------- if ($content == '' and strpos($uploadedContent, "<languageexport") !== false) { $content = $uploadedContent; } } //----------------------------------------- // Make sure we have content //----------------------------------------- if (!$content) { $this->registry->output->global_message = $this->lang->words['l_badfile']; $this->languagesList(); return; } //----------------------------------------- // Get xml class //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXML.php'; $xml = new classXML(IPS_DOC_CHAR_SET); $xml->loadXML($content); //----------------------------------------- // Is this full language pack?... //----------------------------------------- foreach ($xml->fetchElements('langinfo') as $lang_data) { $lang_info = $xml->fetchElementsFromRecord($lang_data); $lang_data = array('lang_short' => $lang_info['lang_short'], 'lang_title' => $lang_info['lang_title']); } $lang_ids = array(); $insertId = 0; //----------------------------------------- // Do we have language pack info? //----------------------------------------- if ($lang_data['lang_short']) { //----------------------------------------- // Does this pack already exist //----------------------------------------- $update_lang = $this->DB->buildAndFetch(array('select' => 'lang_id', 'from' => 'core_sys_lang', 'where' => "lang_short='{$lang_data['lang_short']}'")); //----------------------------------------- // If doesn't exist, then create new pack //----------------------------------------- if (!$update_lang['lang_id']) { $this->DB->insert('core_sys_lang', $lang_data); $insertId = $this->DB->getInsertId(); if (@mkdir(IPS_CACHE_PATH . '/cache/lang_cache/' . $insertId)) { @file_put_contents(IPS_CACHE_PATH . 'cache/lang_cache/' . $insertId . '/index.html', ''); @chmod(IPS_CACHE_PATH . '/cache/lang_cache/' . $insertId, 0777); } //----------------------------------------- // Copy over language bits from default lang //----------------------------------------- $default = $this->DB->buildAndFetch(array('select' => 'lang_id', 'from' => 'core_sys_lang', 'where' => "lang_default=1")); $this->DB->build(array('select' => 'word_app,word_pack,word_key,word_default', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$default['lang_id']}")); $q = $this->DB->execute(); while ($r = $this->DB->fetch($q)) { $r['lang_id'] = $insertId; $this->DB->insert('core_sys_lang_words', $r); } //----------------------------------------- // Rebuild IPB and disk caches //----------------------------------------- $this->registry->class_localization->rebuildLanguagesCache(); } } //----------------------------------------- // We need to add language bits to every pack.. //----------------------------------------- if (count($this->caches['lang_data'])) { foreach ($this->caches['lang_data'] as $langData) { $lang_ids[] = $langData['lang_id']; } } else { $this->DB->build(array('select' => 'lang_id', 'from' => 'core_sys_lang')); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_ids[] = $r['lang_id']; } } //----------------------------------------- // Init counts array //----------------------------------------- $counts = array('updates' => 0, 'inserts' => 0); //----------------------------------------- // Init a cache array to save entries //----------------------------------------- $lang_entries = array(); if ($app_override) { $this->DB->build(array('select' => '*', 'from' => 'core_sys_lang_words', 'where' => "word_app='{$app_override}'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_entries[$r['lang_id']][$r['word_app']][$r['word_pack']][$r['word_key']] = $r; } } //----------------------------------------- // Start looping //----------------------------------------- foreach ($xml->fetchElements('lang') as $entry) { $lang = $xml->fetchElementsFromRecord($entry); foreach ($lang_ids as $_lang_id) { //----------------------------------------- // Build db array //----------------------------------------- $db_array = array('lang_id' => $_lang_id, 'word_app' => $app_override ? $app_override : $lang['word_app'], 'word_pack' => $lang['word_pack'], 'word_key' => $lang['word_key'], 'word_default' => stripslashes($lang['word_default']), 'word_custom' => $in_dev ? '' : stripslashes($lang['word_custom']), 'word_js' => $lang['word_js'], 'word_default_version' => $lang['word_default_version'] >= 30000 ? $lang['word_default_version'] : $LATESTVERSION['long'], 'word_custom_version' => $lang['word_custom_version']); //----------------------------------------- // If cached, get from cache //----------------------------------------- if ($lang_entries[$_lang_id][$db_array['word_app']][$db_array['word_pack']]) { $lang_entry = $lang_entries[$_lang_id][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]; } else { if (!$app_override) { $this->DB->build(array('select' => '*', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$_lang_id} AND word_app='{$db_array['word_app']}' AND word_pack='{$db_array['word_pack']}'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_entries[$r['lang_id']][$r['word_app']][$r['word_pack']][$r['word_key']] = $r; } if ($lang_entries[$_lang_id][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]) { $lang_entry = $lang_entries[$_lang_id][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]; } } } //----------------------------------------- // If there is no new custom lang bit to insert // don't delete what is already there. //----------------------------------------- if (!$db_array['word_custom']) { unset($db_array['word_custom']); unset($db_array['word_custom_version']); } //----------------------------------------- // Lang bit already exists, update //----------------------------------------- if ($lang_entry['word_id'] and (!$insertId or $insertId == $_lang_id)) { //----------------------------------------- // Don't update default version //----------------------------------------- unset($db_array['word_default_version']); $counts['updates']++; $this->DB->update('core_sys_lang_words', $db_array, "word_id={$lang_entry['word_id']}"); } else { if (!$lang_entry['word_id']) { $counts['inserts']++; $this->DB->insert('core_sys_lang_words', $db_array); } } } } //----------------------------------------- // Recache all our lang packs //----------------------------------------- foreach ($lang_ids as $_lang_id) { $this->cacheToDisk($_lang_id); } //----------------------------------------- // Set output message //----------------------------------------- $this->registry->output->global_message = sprintf($this->lang->words['l_updatedcount'], $counts['updates'], $counts['inserts']); if (is_array($this->cache_errors) and count($this->cache_errors)) { $this->registry->output->global_message .= "<br />" . implode("<br />", $this->cache_errors); } //----------------------------------------- // Free a little memory //----------------------------------------- unset($xml); //----------------------------------------- // Update IPB cache //----------------------------------------- $this->registry->class_localization->rebuildLanguagesCache(); //----------------------------------------- // Return! Now! //----------------------------------------- if (!$no_return) { $this->languagesList(); return; } }
/** * Create new session * * @access public * @param string Diff session title * @param string Compare HTML * @param boolean Ignore new bits * @return int New session ID */ public function createSession($title, $content, $ignoreBits = FALSE) { //----------------------------------------- // INIT //----------------------------------------- $templateBits = array(); //----------------------------------------- // Get number for missing template bits //----------------------------------------- $_bits = $this->DB->buildAndFetch(array('select' => 'COUNT(*) as count', 'from' => 'skin_templates', 'where' => 'template_set_id=0')); //----------------------------------------- // Create session //----------------------------------------- $this->DB->allow_sub_select = 1; $this->DB->insert('template_diff_session', array('diff_session_togo' => intval($_bits['count']), 'diff_session_done' => 0, 'diff_session_title' => $title, 'diff_session_updated' => time(), 'diff_session_ignore_missing' => $ignoreBits === TRUE ? 1 : 0)); $diffSesssionID = $this->DB->getInsertId(); //----------------------------------------- // XML //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXML.php'; $xml = new classXML(IPS_DOC_CHAR_SET); //----------------------------------------- // Check to see if its an archive... //----------------------------------------- if (strstr($content, "<xmlarchive")) { /* It's an archive... */ require IPS_KERNEL_PATH . 'classXMLArchive.php'; $xmlArchive = new classXMLArchive(IPS_KERNEL_PATH); $xmlArchive->readXML($content); /* We just want the templates.. */ foreach ($xmlArchive->asArray() as $path => $fileData) { if ($fileData['path'] == 'templates') { $xml->loadXML($fileData['content']); foreach ($xml->fetchElements('template') as $xmlelement) { $data = $xml->fetchElementsFromRecord($xmlelement); if (is_array($data)) { $templateBits[] = $data; } } } } } else { $xml->loadXML($content); foreach ($xml->fetchElements('template') as $xmlelement) { $data = $xml->fetchElementsFromRecord($xmlelement); if (is_array($data)) { $templateBits[] = $data; } } } //----------------------------------------- // Got anything? //----------------------------------------- if (!count($templateBits)) { return FALSE; } //----------------------------------------- // Build session data //----------------------------------------- foreach ($templateBits as $bit) { $diffKey = $diffSesssionID . ':' . $bit['template_group'] . ':' . $bit['template_name']; if (!$seen[$diffKey]) { $this->DB->allow_sub_select = 1; $this->DB->insert('templates_diff_import', array('diff_key' => $diffKey, 'diff_func_group' => $bit['template_group'], 'diff_func_data' => $bit['template_data'], 'diff_func_name' => $bit['template_name'], 'diff_func_content' => $bit['template_content'], 'diff_session_id' => $diffSesssionID)); $seen[$diffKey] = 1; } } return $diffSesssionID; }
/** * Imports a set XMLArchive * * @access public * @param string XMLArchive content to import * @param int [ Skin set parent. If omitted, it will be made a root skin ] * @param string [ Images directory to use. If omitted, default skin's image dir is used ] * @param string [ Name of skin to create. If omitted, name from skin set is used ] * @param bool [ Whether or not we are attempting to upgrade an existing skin ] * @return mixed bool, or number of items added */ public function importSetXMLArchive($content, $parentID = 0, $imageDir = '', $setName = '', $upgrading = FALSE) { //----------------------------------------- // INIT //----------------------------------------- $templates = array(); $csss = array(); $groups = array(); $defaultSkin = array(); $return = array('replacements' => 0, 'css' => 0, 'templates' => 0, 'upgrade' => FALSE); //----------------------------------------- // Got anything? //----------------------------------------- if (!strstr($content, "<xmlarchive")) { $this->_addErrorMessage($this->lang->words['invalidxmlarchivei']); return FALSE; } //----------------------------------------- // Make admin group list //----------------------------------------- foreach ($this->caches['group_cache'] as $id => $data) { if ($data['g_access_cp']) { $groups[] = $id; } } //----------------------------------------- // Grab the XMLArchive class //----------------------------------------- require_once IPS_KERNEL_PATH . 'classXMLArchive.php'; /*noLibHook*/ $xmlArchive = new classXMLArchive(); $xmlArchive->readXML($content); if (!$xmlArchive->countFileArray()) { $this->_addErrorMessage($this->lang->words['emptyxmlarchivei']); return FALSE; } //----------------------------------------- // Gather data //----------------------------------------- /* Info */ $infoXml = $xmlArchive->getFile('info.xml'); if (!$infoXml) { $this->_addErrorMessage($this->lang->words['noinfoxml']); return FALSE; } $info = $this->parseInfoXML($infoXml); /* Are we attempting to upgrade? */ $setID = 0; $doUpgrade = FALSE; $new_items = array('replacements' => array(), 'css' => array(), 'templates' => array()); if ($info['set_key'] && $upgrading) { foreach ($this->caches['skinsets'] as $set_id => $set_data) { if ($set_data['set_key'] == $info['set_key']) { $setID = $set_id; $doUpgrade = TRUE; $return['upgrade'] = TRUE; break; } } } /* Replacements */ $replacements = $this->parseReplacementsXML($xmlArchive->getFile('replacements.xml')); /* Templates */ foreach ($xmlArchive->asArray() as $path => $fileData) { if ($fileData['path'] == 'templates' && $fileData['content']) { $templates[str_replace('.xml', '', $fileData['filename'])] = $this->parseTemplatesXML($fileData['content']); } } /* Templates */ foreach ($xmlArchive->asArray() as $path => $fileData) { if ($fileData['path'] == 'css') { $csss[str_replace('.xml', '', $fileData['filename'])] = $this->parseCSSXML($fileData['content']); } } if (!is_array($info)) { $this->_addErrorMessage($this->lang->words['noinfoxml']); return FALSE; } $info['set_output_format'] = $info['set_output_format'] ? $info['set_output_format'] : 'html'; //----------------------------------------- // Find default skin //----------------------------------------- foreach ($this->registry->output->allSkins as $id => $data) { if ($data['set_is_default'] and $data['set_output_format'] == $info['set_output_format']) { $defaultSkin = $data; break; } } /* Make sure key in unique */ $test = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'skin_collections', 'where' => 'set_key=\'' . $this->DB->addSlashes($info['set_key']) . '\' AND set_id != ' . intval($setID))); if ($test['set_id']) { $info['set_key'] .= '_' . time(); } //----------------------------------------- // Build Set Array //----------------------------------------- $newSet = array('set_name' => $setName ? $setName : $info['set_name'] . ' (Import)', 'set_key' => $info['set_key'], 'set_parent_id' => $parentID, 'set_permissions' => implode(",", $groups), 'set_is_default' => 0, 'set_author_name' => $info['set_author_name'], 'set_author_url' => $info['set_author_url'], 'set_image_dir' => $imageDir ? $imageDir : $defaultSkin['set_image_dir'], 'set_emo_dir' => $defaultSkin['set_emo_dir'], 'set_css_inline' => 1, 'set_output_format' => $info['set_output_format'], 'set_css_groups' => '', 'set_hide_from_list' => 1, '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['template_updated'] : IPS_UNIX_TIME_NOW, '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['template_updated'] : IPS_UNIX_TIME_NOW, '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; }