/** * Search and Replace templates. * * @param integer $dostyleid Style ID to be searched in. -1 means search in all styles. * @param string $searchstring Search for text. * @param string $replacestring Replace with text. * @param boolean $case_insensitive Case-Insensitive or not. * @param boolean $regex Whether to use regular expressions. * @param boolean $test Test only. * @param integer $startat_style Replacement startat style ID. * @param integer $startat_template Replacement startat template ID. * * @return mixed False if no templates found. Otherwise an array will be returned. */ public function searchAndReplace($dostyleid, $searchstring, $replacestring, $case_insensitive, $regex, $test, $startat_style, $startat_template) { $this->checkHasAdminPermission('canadmintemplates'); require_once DIR . '/includes/adminfunctions.php'; require_once DIR . '/includes/adminfunctions_template.php'; // TODO: Product API $full_product_info = fetch_product_list(true); $vb5_config =& vB::getConfig(); $userinfo = vB::getCurrentSession()->fetch_userinfo(); $perpage = 50; $searchstring = str_replace(chr(0), '', $searchstring); if (empty($searchstring)) { throw new vB_Exception_Api('please_complete_required_fields'); } $limit_style = $startat_style; $conditions = array(); if ($dostyleid == -1) { if ($vb5_config['Misc']['debug']) { $conditions[] = array('field' => 'styleid', 'value' => -2, 'operator' => vB_dB_Query::OPERATOR_NE); if ($startat_style == 0) { $editmaster = true; } else { $limit_style--; // since 0 means the master style, we have to renormalize } } else { $conditions[] = array('field' => 'styleid', 'value' => 0, 'operator' => vB_dB_Query::OPERATOR_GT); } } else { $conditions['styleid'] = $dostyleid; } if ($editmaster != true) { $result = vB::getDbAssertor()->assertQuery('getStyleByConds', array(vB_Db_Query::TYPE_KEY => vB_Db_Query::QUERY_METHOD, 'conds' => $conditions, 'limit_style' => $limit_style)); if (!$result->valid()) { // couldn't grab a style, so we're done return false; } $styleinfo = $result->current(); $templatelist = unserialize($styleinfo['templatelist']); } else { $styleinfo = array('styleid' => -1, 'title' => 'MASTER STYLE'); $templatelist = array(); $result = vB::getDbAssertor()->assertQuery('template_getmasters2'); foreach ($result as $tid) { $templatelist["{$tid['title']}"] = $tid['templateid']; } $styleinfo['templatelist'] = serialize($templatelist); // for sanity } $loopend = $startat_template + $perpage; $process_templates = array(0); $i = 0; foreach ($templatelist as $title => $tid) { if ($i >= $startat_template and $i < $loopend) { $process_templates[] = $tid; } if ($i >= $loopend) { break; } $i++; } if ($i != $loopend) { // didn't get the $perpage templates, so we're done with this style $styledone = true; } else { $styledone = false; } $templates = vB::getDbAssertor()->assertQuery('template', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'templateid' => $process_templates)); $stats['page'] = $startat_template / $perpage + 1; $stats['first'] = $startat_template + 1; $count = 0; $processed_templates = array(); foreach ($templates as $temp) { $count++; $insensitive_mod = $case_insensitive ? 'i' : ''; if ($test) { if ($regex) { $encodedsearchstr = str_replace('(?<', '(?<', htmlspecialchars_uni($searchstring)); } else { $encodedsearchstr = preg_quote(htmlspecialchars_uni($searchstring), '#'); } $newtemplate = preg_replace("#{$encodedsearchstr}#sU{$insensitive_mod}", '<span class="col-i" style="text-decoration:underline;">' . htmlspecialchars_uni($replacestring) . '</span>', htmlspecialchars_uni($temp['template_un'])); if ($newtemplate != htmlspecialchars_uni($temp['template_un'])) { $temp['newtemplate'] = $newtemplate; $processed_templates[] = $temp; } else { continue; } } else { if ($regex) { $newtemplate = preg_replace("#" . $searchstring . "#sU{$insensitive_mod}", $replacestring, $temp['template_un']); } else { $usedstr = preg_quote($searchstring, '#'); $newtemplate = preg_replace("#{$usedstr}#sU{$insensitive_mod}", $replacestring, $temp['template_un']); } if ($newtemplate != $temp['template_un']) { if (!empty($temp['textonly'])) { $newTemplateCompiled = $newtemplate; } else { $newTemplateCompiled = $this->library->compile($newtemplate, true); } if ($temp['styleid'] == $styleinfo['styleid']) { vB::getDbAssertor()->assertQuery('template', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'template' => $newTemplateCompiled, 'template_un' => $newtemplate, 'dateline' => TIMENOW, 'username' => $userinfo['username'], 'version' => $full_product_info["{$temp['product']}"]['version'], 'templateid' => $temp['templateid'], 'mergestatus' => 'none')); // now update the file system if we setup to do so and we are in the master style if (defined('DEV_AUTOEXPORT') and DEV_AUTOEXPORT and $temp['styleid'] == -1) { require_once DIR . '/includes/functions_filesystemxml.php'; autoexport_write_template($temp['title'], $newtemplate, $temp['product'], $full_product_info["{$temp['product']}"]['version'], $userinfo['username'], TIMENOW); } vB::getDbAssertor()->assertQuery('templatemerge', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_DELETE, 'templateid' => $temp['templateid'])); } else { /*insert query*/ $result = vB::getDbAssertor()->assertQuery('template', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'dostyleid' => $styleinfo['styleid'], 'title' => $temp['title'], 'template' => $newTemplateCompiled, 'template_un' => $newtemplate, 'dateline' => TIMENOW, 'username' => $userinfo['username'], 'version' => $full_product_info["{$temp['product']}"]['version'], 'product' => $temp['product'])); $requirerebuild = true; } $temp['newtemplate'] = $newtemplate; $processed_templates[] = $temp; vB_Library::instance('Style')->setCssDate(); } else { continue; } } } // End foreach $stats['last'] = $startat_template + $count; if ($styledone == true) { // Go to the next style. If we're only doing replacements in one style, // this will trigger the finished message. $startat_style++; $loopend = 0; } return array('processed_templates' => $processed_templates, 'startat_style' => $startat_style, 'startat_template' => $loopend, 'requirerebuild' => $requirerebuild, 'styleinfo' => $styleinfo, 'stats' => $stats); }
WHERE templateid = " . $vbulletin->GPC['templateid'] . " AND ( MD5(template_un) = '" . $db->escape_string($vbulletin->GPC['hash']) . "' OR template_un = '" . $db->escape_string($template_un) . "' ) "); // now update the file system if we setup to do so and we are in the master style if (defined('DEV_AUTOEXPORT') AND DEV_AUTOEXPORT AND $vbulletin->GPC['dostyleid'] == -1) { require_once(DIR . '/includes/functions_filesystemxml.php'); autoexport_write_template( $vbulletin->GPC['title'], $template_un, $vbulletin->GPC['product'], $full_product_info[$vbulletin->GPC['product']]['version'], $vbulletin->userinfo['username'], TIMENOW, $vbulletin->GPC['oldtitle'] ); } if ($db->affected_rows() == 0) { // we have an edit conflict $_REQUEST['do'] = 'edit'; $updatetemplate_edit_conflict = true; } else { // template saved successfully (no edit conflict)
/** * Save a template and handle all common operations between an insert and an update * caller is responsible for determining if a update or an insert is needed (via * providing the existing templateid for the record to be updated) * * @param $title string. The title of the template * @param $template string. Compiled template text * @param $content string. Uncompiled template text * @param $timenow int. Current time as a datestamp * @param $username string. Username of the user saving the template * @param $version string. The version of the product the template belongs to. * @param $product string. The product that the template belongs to. * @param $templateid int. The id of the template being saved, null if this is a new template * @param $hash string. The md5 hash of the original text of the template being updated. This is used to * avoid conflicting edits. Null if this is a new template. * @param $styleid int. The ID of the style the template is being saved to. * @param $savehistory bool. Whether to save this edit to the template history -- valid for new templates * @param $hiscomment string. A comment on the edit to save with the history * */ protected function saveTemplate($title, $template, $content, $timenow, $username, $version, $product, $templateid, $hash, $styleid, $savehistory, $histcomment, $additional = array()) { $fields = array('title' => $title, 'template' => $template, 'template_un' => $content, 'dateline' => $timenow, 'username' => $username, 'version' => $version, 'product' => $product); //if the current user does not have canadmintemplates, we force textonly to 1. Otherwise leave it alone. if (!vB::getUserContext()->hasAdminPermission('canadmintemplates')) { $fields['textonly'] = 1; } else { if (isset($additional['textonly'])) { $fields['textonly'] = $additional['textonly']; } } //update if ($templateid) { $fields['templateid'] = $templateid; $fields['hash'] = $hash; $queryid = 'template_update'; if (!isset($fields['textonly'])) { //We need to get the current value of textonly so we don't change it. $existing = vB::getDbAssertor()->getRow('template', array('templateid' => $templateid)); if ($existing and !empty($existing['textonly'])) { $fields['textonly'] = 1; } else { $fields['textonly'] = 0; } } } else { $fields['styleid'] = $styleid; $fields[vB_dB_Query::TYPE_KEY] = vB_dB_Query::QUERY_INSERT; $queryid = 'template'; } // Do update $result = vB::getDbAssertor()->assertQuery($queryid, $fields); //If we just did an insert, the templateid is in $result; if (empty($templateid) and is_numeric($result)) { $templateid = $result; } $this->setTextonlyDS($templateid, $fields['textonly']); //a non positive result indicates failure if ($result) { // now update the file system if we setup to do so and we are in the master style if (defined('DEV_AUTOEXPORT') and DEV_AUTOEXPORT and $styleid == -1) { require_once DIR . '/includes/functions_filesystemxml.php'; autoexport_write_template($title, $content, $product, $version, $username, $timenow); } if ($savehistory) { vB::getDbAssertor()->assertQuery('template_savehistory', array('dostyleid' => $styleid, 'title' => $title, 'template_un' => $content, 'dateline' => $timenow, 'username' => $username, 'version' => $version, 'comment' => $histcomment)); } //if this is a new template the return from the insert query is the templateid if (!$templateid) { $templateid = $result; } //if we are storing the templates on the file systems $options = vB::getDatastore()->getValue('options'); if ($options['cache_templates_as_files'] and $options['template_cache_path']) { $this->saveTemplateToFileSystem($templateid, $template, $options['template_cache_path'], $fields['textonly']); } vB_Library::instance('Style')->setCssDate(); // we need to reset the template fastDS cache. $options = vB::getDatastore()->getValue('miscoptions'); $options['tmtdate'] = vB::getRequest()->getTimeNow(); vB::getDatastore()->build('miscoptions', serialize($options), 1); } return $result; }