Attached Files |
Caching_process.vsd [^] (64,512 bytes) 2010-02-13 07:50
memcache_modules.patch [^] (15,971 bytes) 2010-02-24 07:49
[Show Content]
Index: in-auction/units/helpers/ebay_helper.php
===================================================================
--- in-auction/units/helpers/ebay_helper.php (revision 13152)
+++ in-auction/units/helpers/ebay_helper.php (working copy)
@@ -13,11 +13,11 @@
defined('FULL_PATH') or die('restricted access!');
- if (class_exists('SoapClient')) {
+ if (class_exists('SoapClient')) {
k4_include_once(dirname(__FILE__).'/ebay_soap.php');
} else {
k4_include_once(dirname(__FILE__).'/ebay_no_soap.php');
- }
+ }
class eBayHelper extends kHelper {
@@ -71,7 +71,7 @@
if (!class_exists('SoapClient')) {
return;
}
-
+
$this->soap_enabled = 1;
// Create and configure session
@@ -121,7 +121,7 @@
public function __call($function, $args)
{
static $client = null;
-
+
$request_time = adodb_mktime();
if (!$this->soap_enabled) {
$fields_hash = Array (
@@ -132,9 +132,9 @@
'AnswerStatus' => 'Error',
'Errors' => 'PHP doesn\'t have SOAP module enabled'
);
-
+
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'eBayErrorLog');
- return;
+ return;
}
if (!isset($client)) {
@@ -256,11 +256,8 @@
function CheckItemsLimits($request_time, $quantity)
{
// get limits
+ $a_counters = unserialize( $this->Application->getDBCache('call_counters') );
- $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = '.$this->Conn->qstr('call_counters');
- $a_counters = unserialize($this->Conn->GetOne($sql));
-
if (!is_array($a_counters))
{
return 'overall';
@@ -298,11 +295,8 @@
function CheckCallLimits($request_time)
{
// get limits
+ $a_counters = unserialize( $this->Application->getDBCache('call_counters') );
- $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = '.$this->Conn->qstr('call_counters');
- $a_counters = unserialize($this->Conn->GetOne($sql));
-
if (!is_array($a_counters))
{
return 'overall';
@@ -341,13 +335,7 @@
// save counters
$a_counters['LastCallTime'] = $request_time;
- $sql = 'REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached)
- VALUES (
- '.$this->Conn->qstr('call_counters').',
- '.$this->Conn->qstr(serialize($a_counters)).',
- '.adodb_mktime().'
- )';
- $this->Conn->Query($sql);
+ $this->Application->setDBCache('call_counters', serialize($a_counters));
}
function RemoveToken()
@@ -389,8 +377,12 @@
function ClearConfigCache()
{
- $sql = 'DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = \'configs_parsed\'';
- $this->Conn->Query($sql);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:configs_parsed');
+ }
+ else {
+ $this->Application->deleteDBCache('configs_parsed');
+ }
}
function RuName()
Index: in-auction/units/sections/ebay_eh.php
===================================================================
--- in-auction/units/sections/ebay_eh.php (revision 13152)
+++ in-auction/units/sections/ebay_eh.php (working copy)
@@ -2591,7 +2591,7 @@
{
// Get last usage time
- $last_usage_time = $this->GetCacheValue($cache_name);
+ $last_usage_time = $this->Application->getDBCache($cache_name);
if ($last_usage_time == 0)
{
@@ -2674,7 +2674,7 @@
{
$a_items = Array($a_items);
}
- $this->SetCacheValue('get_list_time', $curr_gmt_time);
+ $this->Application->setDBCache('get_list_time', $curr_gmt_time);
foreach ($a_items AS $Item) {
$this->UpdateListing($Item);
@@ -2910,7 +2910,7 @@
}
- $this->SetCacheValue('get_transactions_time', $curr_gmt_time);
+ $this->Application->setDBCache('get_transactions_time', $curr_gmt_time);
foreach ($a_transactions AS $Transaction) {
// Locate for order item. If not present - create it
@@ -2961,27 +2961,13 @@
}
}
- function GetCacheValue($var_name)
+ function resetAgents()
{
- $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = '.$this->Conn->qstr($var_name);
- return $this->Conn->GetOne($sql);
- }
-
- function SetCacheValue($var_name, $data)
- {
- $sql = 'REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached)
- VALUES (
- '.$this->Conn->qstr($var_name).',
- '.$this->Conn->qstr($data).',
- '.adodb_mktime().'
- )';
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Agents
+ SET NextRunOn = NULL';
$this->Conn->Query($sql);
}
-
-
-
/**
* Create Item Unpaid disputes on e-Bay
*
@@ -3336,7 +3322,7 @@
return;
}
- $this->SetCacheValue('call_counters', $call_counters);
+ $this->Application->setDBCache('call_counters', $call_counters);
}
@@ -3366,14 +3352,17 @@
$this->ClearConfigCache();
// clear cache to process all eBay interaction with new token
- $this->SetCacheValue('RegularEventRuns', '');
-
+ $this->resetAgents();
}
function ClearConfigCache()
{
- $sql = 'DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = \'configs_parsed\'';
- $this->Conn->Query($sql);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:configs_parsed');
+ }
+ else {
+ $this->Application->deleteDBCache('configs_parsed');
+ }
}
/**
@@ -3423,7 +3412,7 @@
/* @var $eBayHelper eBayHelper*/
$a_params = Array(
- 'SessionID' => $this->GetCacheValue('ebay_token_sid'),
+ 'SessionID' => $this->Application->getDBCache('ebay_token_sid'),
);
$Answer = $eBayHelper->FetchToken($a_params);
@@ -3447,8 +3436,7 @@
$this->ClearConfigCache();
// clear cache to process all eBay interaction with new token
- $this->SetCacheValue('RegularEventRuns', '');
-
+ $this->resetAgents();
}
/**
@@ -3504,7 +3492,7 @@
}
}
- $this->SetCacheValue('ebay_token_sid', $sid);
+ $this->Application->setDBCache('ebay_token_sid', $sid);
$ebay_url = 'https://signin.'.(($this->Application->ConfigValue('eBay_ConnectionMode') == EBAY_PRODUCTION_CONNECTION) ? '' : 'sandbox.').'ebay.com/ws/eBayISAPI.dll?SignIn&runame='.$eBayHelper->RuName().(($this->Application->ConfigValue('eBay_UseFetchToken') == 1) ? '&sid='.$sid : '');
header("location: ".$ebay_url);
exit;
Index: in-auction/units/sections/ebay_tp.php
===================================================================
--- in-auction/units/sections/ebay_tp.php (revision 13152)
+++ in-auction/units/sections/ebay_tp.php (working copy)
@@ -75,9 +75,7 @@
function PrintCallsArray($params)
{
- $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = '.$this->Conn->qstr('call_counters');
- return var_export(unserialize($this->Conn->GetOne($sql)), true);
+ return var_export(unserialize( $this->Application->getDBCache('call_counters') ), true);
}
}
\ No newline at end of file
Index: in-commerce/units/currencies/currency_rates.php
===================================================================
--- in-commerce/units/currencies/currency_rates.php (revision 13152)
+++ in-commerce/units/currencies/currency_rates.php (working copy)
@@ -17,31 +17,41 @@
var $RateSource;
var $ExchangeRates = Array();
- var $PrimaryCurrency;
function kCurrencyRates()
{
- $this->Application =& kApplication::Instance();
+ parent::kBase();
+
$this->GetRatesData();
}
function GetRatesData()
{
- // written :) just check that it's correct
- $conn =& $this->Application->GetADODBConnection();
- $table = $this->Application->getUnitOption('curr', 'TableName');
- $primary = $this->GetPrimaryCurrency();
- $sql = 'SELECT "'.$primary.'" AS TARGET, ISO AS ID, RateToPrimary As RATE, 1 AS UNITS FROM '.$table.' WHERE 1';
- $rates = $conn->Query($sql);
- foreach ($rates as $a_rate) {
- $this->SetRate($primary, $a_rate['ID'], $a_rate['RATE']);
+ $cache_key = 'currency_rates[%CurrSerial%]';
+ $rates = $this->Application->getCache($cache_key);
+ $primary = $this->Application->GetPrimaryCurrency();
+
+ if ($rates === false) {
+ $conn =& $this->Application->GetADODBConnection();
+
+ $conn->nextQueryCachable = true;
+ $sql = 'SELECT ISO, RateToPrimary
+ FROM ' . $this->Application->getUnitOption('curr', 'TableName') . '
+ WHERE Status = ' . STATUS_ACTIVE;
+ $rates = $conn->Query($sql);
+
+ $this->Application->setCache($cache_key, $rates);
}
+
+ foreach ($rates as $rate) {
+ $this->SetRate($primary, $rate['ISO'], $rate['RateToPrimary']);
+ }
}
function GetRate($source_cur, $target_cur, $units = 1)
{
- $source_cur = ($source_cur == 'PRIMARY') ? $this->GetPrimaryCurrency() : $source_cur;
- $target_cur = ($target_cur == 'PRIMARY') ? $this->GetPrimaryCurrency() : $target_cur;
+ $source_cur = ($source_cur == 'PRIMARY') ? $this->Application->GetPrimaryCurrency() : $source_cur;
+ $target_cur = ($target_cur == 'PRIMARY') ? $this->Application->GetPrimaryCurrency() : $target_cur;
if($source_cur == $target_cur)
{
return 1;
@@ -76,18 +86,6 @@
$this->ExchangeRates[$target_cur]['UNITS'] = $units;
}
- function GetPrimaryCurrency()
- {
- if(!$this->PrimaryCurrency)
- {
- $conn =& $this->Application->GetADODBConnection();
- $table = $this->Application->getUnitOption('curr', 'TableName');
- $sql = 'SELECT ISO FROM '.$table.' WHERE IsPrimary = 1';
- $this->PrimaryCurrency = $conn->GetOne($sql);
- }
- return $this->PrimaryCurrency;
- }
-
function StoreRates($currencies=null)
{
$curr_object =& $this->Application->recallObject('curr', null, Array ('skip_autoload' => true));
@@ -127,7 +125,6 @@
function GetRatesData()
{
- $this->GetPrimaryCurrency();
$xml_parser = xml_parser_create();
$curl_helper =& $this->Application->recallObject('CurlHelper');
@@ -179,7 +176,6 @@
function GetRatesData()
{
- $this->GetPrimaryCurrency();
$xml_parser = xml_parser_create();
$curl_helper =& $this->Application->recallObject('CurlHelper');
@@ -225,7 +221,6 @@
$curl_helper =& $this->Application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
- $this->GetPrimaryCurrency();
for($i = 0; $i < 10; $i++)
{
$time = adodb_mktime() - $i * 3600 * 24;
Index: in-commerce/units/products/products_item.php
===================================================================
--- in-commerce/units/products/products_item.php (revision 13152)
+++ in-commerce/units/products/products_item.php (working copy)
@@ -34,34 +34,51 @@
*/
function getPrimaryPricing()
{
- if (!$this->Application->isAdminUser) {
- $user_id = $this->Application->RecallVar('user_id');
- $primary_group = $user_id != -2 ? $this->Conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'UserGroup WHERE PrimaryGroup = 1 AND PortalUserId = '.$user_id) : false;
+ // product + pricing based
+ $cache_key = 'product_primary_pricing[%PIDSerial:' . $this->GetID() . '%][%PrIDSerial:ProductId:' . $this->GetID() . '%]';
- if ($primary_group) {
+ if (!$this->Application->isAdmin && $this->Application->LoggedIn()) {
+ // also group based
+ $primary_group = (int)$this->Application->Session->GetField('GroupId');
+ $cache_key .= ':group=' . $primary_group;
+ }
+
+ $price_info = $this->Application->getCache($cache_key);
+
+ if ($price_info === false) {
+ if (!$this->Application->isAdmin && $this->Application->LoggedIn()) {
+ // logged in user on front-end
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT Price, Cost
- FROM '.TABLE_PREFIX.'ProductsPricing
- WHERE (ProductId = '.$this->GetID().') AND (GroupId = '.$primary_group.')
- ORDER BY MinQty';
- $a_values = $this->Conn->GetRow($sql);
+ FROM ' . TABLE_PREFIX . 'ProductsPricing
+ WHERE (ProductId = ' . $this->GetID() . ') AND (GroupId = ' . $primary_group . ')
+ ORDER BY MinQty';
+ $price_info = $this->Conn->GetRow($sql);
- if ($a_values !== false) {
- return $a_values;
+ if ($price_info !== false) {
+ $this->Application->setCache($cache_key, $price_info);
+
+ return $price_info;
}
}
- }
- $pr_table = $this->Application->getUnitOption('pr', 'TableName');
+ // not logged-in user on front-end or in administrative console
+ $pr_table = $this->Application->getUnitOption('pr', 'TableName');
- if ($this->mode == 't') {
- $pr_table = $this->Application->GetTempName($pr_table, 'prefix:'.$this->Prefix);
+ if ($this->IsTempTable()) {
+ $pr_table = $this->Application->GetTempName($pr_table, 'prefix:' . $this->Prefix);
+ }
+
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT Price, Cost
+ FROM ' . $pr_table . '
+ WHERE (' . $this->IDField . ' = ' . $this->GetID() . ') AND (IsPrimary = 1)';
+ $price_info = $this->Conn->GetRow($sql);
+
+ $this->Application->setCache($cache_key, $price_info);
}
- $sql = 'SELECT Price, Cost
- FROM '.$pr_table.'
- WHERE ('.$this->IDField.' = '.$this->GetID().') AND (IsPrimary = 1)';
-
- return $this->Conn->GetRow($sql);
+ return $price_info;
}
}
\ No newline at end of file
Index: in-commerce/units/shipping_quote_engines/shipping_quote_collector.php
===================================================================
--- in-commerce/units/shipping_quote_engines/shipping_quote_collector.php (revision 13152)
+++ in-commerce/units/shipping_quote_engines/shipping_quote_collector.php (working copy)
@@ -27,11 +27,10 @@
$db =& $this->Application->GetADODBConnection();
$cached_var_name = 'ShippingQuotes'.crc32(serialize($params));
- $day_ago = adodb_mktime() - 3600*24;
- $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "'.$cached_var_name.'"
- AND Cached > '.$day_ago;
- if($shipping_types = $db->GetOne($sql))
- {
+
+ $shipping_types = $this->Application->getDBCache($cached_var_name);
+
+ if ($shipping_types) {
return unserialize($shipping_types);
}
@@ -76,11 +75,8 @@
}
$shipping_types = $available_types;
- $sql = 'DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName LIKE "ShippingQuotes%" AND Cached < '.$day_ago;
- $db->Query($sql);
- $sql = 'INSERT INTO '.TABLE_PREFIX.'Cache(VarName, Data, Cached)
- VALUES("'.$cached_var_name.'", '.$db->qstr(serialize($shipping_types)).', '.adodb_mktime().')';
- $db->Query($sql);
+ $this->Application->setDBCache($cached_var_name, serialize($shipping_types), 24 * 3600);
+
return $shipping_types;
}
Index: in-link/units/link_validation/link_validation_tp.php
===================================================================
--- in-link/units/link_validation/link_validation_tp.php (revision 13152)
+++ in-link/units/link_validation/link_validation_tp.php (working copy)
@@ -40,19 +40,27 @@
$object =& $this->getObject($params);
$category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
- $category_path = $this->Application->getCache('category_paths', $category_id);
+ $cache_key = 'category_paths[%CIDSerial:' . $category_id . '%]';
+
+ if ($category_id == 0) {
+ // home category name is phrase AND phrase name is defined in configuration
+ $cache_key .= '[%PhrasesSerial%][%ConfSerial%]';
+ }
+
+ $category_path = $this->Application->getCache($cache_key);
+
if ($category_path === false) {
- // not chached
if ($category_id > 0) {
-
$cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $object->GetDBField('CachedNavbar'));
$category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > ');
}
else {
$category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
}
- $this->Application->setCache('category_paths', $category_id, $category_path);
+
+ $this->Application->setCache($cache_key, $category_path);
}
+
return $category_path;
}
}
\ No newline at end of file
memcache_core.patch [^] (172,247 bytes) 2010-02-24 10:46
[Show Content]
Index: admin/system_presets/simple/categories_c.php
===================================================================
--- admin/system_presets/simple/categories_c.php (revision 13152)
+++ admin/system_presets/simple/categories_c.php (working copy)
@@ -46,7 +46,7 @@
'MetaDescription', 'HotItem',*/ 'NewItem', /*'PopItem', 'Modified', 'ModifiedById', 'CachedTemplate',*/
'Template', /*'UseExternalUrl', 'ExternalUrl',*/ 'UseMenuIconUrl', 'MenuIconUrl', 'Title', 'MenuTitle',
/*'MetaTitle', 'IndexTools', 'IsMenu', 'IsSystem',*/ 'FormId', 'FormSubmittedTemplate',
- /*'FriendlyURL', 'ThemeId'*/
+ /*'FriendlyURL', 'ThemeId', 'EnablePageCache', 'OverridePageCacheKey', 'PageCacheKey', 'PageExpiration'*/
);
// virtual fields to hide
Index: core/admin_templates/categories/categories_edit.tpl
===================================================================
--- core/admin_templates/categories/categories_edit.tpl (revision 13152)
+++ core/admin_templates/categories/categories_edit.tpl (working copy)
@@ -109,6 +109,13 @@
<inp2:m_RenderElement name="inp_edit_textarea" prefix="c" field="MetaKeywords" title="!la_fld_MetaKeywords!" allow_html="0" control_options="{min_height: 50}" rows="3" cols="70"/>
<inp2:m_RenderElement name="inp_edit_textarea" prefix="c" field="MetaDescription" title="!la_fld_MetaDescription!" allow_html="0" control_options="{min_height: 50}" rows="4" cols="70"/>
<inp2:m_RenderElement name="inp_edit_textarea" prefix="c" field="IndexTools" title="!la_fld_TrackingCode!" control_options="{min_height: 50}" allow_html="0"/>
+
+ <inp2:m_RenderElement name="subsection" prefix="c" fields="EnablePageCache,OverridePageCacheKey,PageCacheKey,PageExpiration" title="la_section_PageCaching"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="c" field="EnablePageCache" title="la_fld_EnablePageCache" onclick="reflectCachingSettings();"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="c" field="OverridePageCacheKey" title="la_fld_OverridePageCacheKey" onclick="reflectCacheKeyOverride();"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="c" field="PageCacheKey" title="la_fld_PageCacheKey"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="c" field="PageExpiration" title="la_fld_PageExpiration" hint_label="la_hint_PageExpiration"/>
+
<!-- custom fields: begin -->
<inp2:m_include t="incs/custom_blocks"/>
<inp2:cf.general_PrintList render_as="cv_row_block" SourcePrefix="c" value_field="Value" per_page="-1" grid="Default" />
@@ -168,17 +175,42 @@
function reflectFilename() {
var $filename = getControl('Filename');
if ($filename) {
- var $checked = getControl('AutomaticFilename', null, '_cb').checked;
- $filename.readOnly = $checked;
+ var $checked = getControl('AutomaticFilename', null, '_cb').checked;
+ $filename.readOnly = $checked;
}
}
+ function reflectCachingSettings() {
+ var $checked = getControl('EnablePageCache', null, '_cb').checked;
+
+ getControl('OverridePageCacheKey', null, '_cb').disabled = !$checked;
+ getControl('PageCacheKey').disabled = !$checked || !getControl('OverridePageCacheKey', null, '_cb').checked;
+// getControl('PageExpiration').disabled = !$checked;
+ }
+
+ function reflectCacheKeyOverride() {
+ var $checked = getControl('OverridePageCacheKey', null, '_cb').checked;
+ getControl('PageCacheKey').disabled = !$checked;
+ }
+
+ Application.setHook(
+ 'c:*',
+ function () {
+ getControl('OverridePageCacheKey', null, '_cb').disabled = false;
+ getControl('PageCacheKey').disabled = false;
+// getControl('PageExpiration').disabled = false;
+ }
+ );
+
$(document).ready(
function() {
reflectMenuIcon();
reflectExternalUrl();
reflectFilename();
-// OnSystemClick();
+ // OnSystemClick();
+
+ reflectCacheKeyOverride();
+ reflectCachingSettings();
}
);
</script>
Index: core/admin_templates/tools/system_tools.tpl
===================================================================
--- core/admin_templates/tools/system_tools.tpl (revision 13152)
+++ core/admin_templates/tools/system_tools.tpl (working copy)
@@ -17,10 +17,10 @@
</script>
<inp2:m_DefineElement name="service_elem" event_prefix="adm">
- <tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
<inp2:m_inc param="tab_index" by="1"/>
<td class="text" style="width: 300px;">
- <inp2:m_param name="title"/>:
+ <inp2:m_param name="title"/>
</td>
<td valign="top" colspan="2">
<input class="button" type="button" onclick="submit_event('<inp2:m_param name="event_prefix"/>', '<inp2:m_param name="event_name"/>');" value="Run">
@@ -28,18 +28,20 @@
</tr>
</inp2:m_DefineElement>
-<table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
- <inp2:m_RenderElement name="subsection" title="la_section_General"/>
+<table width="100%" cellspacing="0" cellpadding="4" class="bordered">
+ <!--##<inp2:m_RenderElement name="subsection" title="la_section_General"/>##-->
<inp2:m_RenderElement name="service_elem" title="Reset mod_rewrite Cache" event_name="OnResetModRwCache"/>
<inp2:m_RenderElement name="service_elem" title="Reset SMS Menu Cache" event_prefix="c" event_name="OnResetCMSMenuCache"/>
<inp2:m_RenderElement name="service_elem" title="Reset Sections Cache" event_name="OnResetSections"/>
<inp2:m_RenderElement name="service_elem" title="Reset Configs Cache" event_name="OnResetConfigsCache"/>
+ <inp2:m_RenderElement name="service_elem" title="Re-build Multilanguage Fields" event_prefix="lang" event_name="OnReflectMultiLingualFields"/>
+
+ <inp2:m_RenderElement name="subsection" title="la_section_Templates"/>
<inp2:m_RenderElement name="service_elem" title="Re-build Themes Files" event_name="OnRebuildThemes"/>
- <inp2:m_RenderElement name="service_elem" title="Re-build Multilanguage Fields" event_prefix="lang" event_name="OnReflectMultiLingualFields"/>
- <tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
<inp2:m_inc param="tab_index" by="1"/>
<td class="text" style="width: 300px;">
- Compile Templates (with NParser):
+ Re-compile Templates
</td>
<td valign="top" colspan="2">
<input class="button" type="button" onclick="compile_templates();" value="Run">
@@ -47,7 +49,7 @@
</tr>
<inp2:m_RenderElement name="service_elem" title="Delete Compiled Templates" event_name="OnDeleteCompiledTemplates"/>
<inp2:m_RenderElement name="subsection" title="la_section_Configs"/>
- <tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
<inp2:m_inc param="tab_index" by="1"/>
<td class="text" style="width: 300px;">
Table Structure:
@@ -55,27 +57,154 @@
<td valign="top" colspan="2">
<input type="text" name="table_name" value="" size="30"/>
<input class="button" type="button" onclick="show_structure('adm', 'OnGenerateTableStructure');" value="Run">
- <span class="small">Table Name (table prefix is optional) OR "Unit-config" Prefix</span>
+ <span class="small">table name (table prefix is optional) OR "unit config" prefix</span>
</td>
</tr>
- <tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
<inp2:m_inc param="tab_index" by="1"/>
<td class="text" style="width: 300px;">
- Prefix:
+ Locate Unit Config File:
</td>
<td valign="top" colspan="2">
<input type="text" name="config_prefix" value="" size="30"/>
<input class="button" type="button" onclick="check_prefix_config();" value="Run">
- <span class="small">Unit-config Prefix</span>
+ <span class="small">unit config prefix</span>
</td>
</tr>
+ <inp2:m_if check="adm_MemoryCacheEnabled">
+ <inp2:m_RenderElement name="subsection" title="la_section_MemoryCache"/>
+ <inp2:m_RenderElement name="service_elem" title="Reset All Keys" event_name="OnResetMemcache"/>
+
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
+ <inp2:m_inc param="tab_index" by="1"/>
+ <td class="text" style="width: 300px;">
+ Key Name:
+ </td>
+ <td valign="top" colspan="2">
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ <td colspan="2">
+ <a href="#" class="quick-memory-cache-key">master:configs_parsed</a>,
+ <a href="#" class="quick-memory-cache-key">master:config_files</a>,
+ <a href="#" class="quick-memory-cache-key">master:sections_parsed</a>,
+ <a href="#" class="quick-memory-cache-key">master:cms_menu</a>,
+ <a href="#" class="quick-memory-cache-key">master:template_mapping</a>,
+ <a href="#" class="quick-memory-cache-key">master:StructureTree</a>
+ <br/>
+ <br/>
+ </td>
+ </tr>
+ <tr>
+ <td style="width: 440px;">
+ <input type="text" id="memory_cache_key_name" value="" style="width: 440px;"/>
+ </td>
+ <td style="padding-bottom: 2px; padding-left: 4px;">
+ <input type="button" class="button" id="memory_cache_get" value="Get Value"/>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>">
+ <inp2:m_inc param="tab_index" by="1"/>
+ <td class="text" style="width: 300px;">
+ Key Value:
+ </td>
+ <td valign="top" colspan="2">
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ <td valign="bottom">
+ <textarea id="memory_cache_key_value" style="width: 440px; height: 120px;"></textarea>
+ </td>
+ <td valign="bottom" style="padding-bottom: 2px; padding-left: 4px;">
+ <input type="button" class="button" id="memory_cache_set" value="Set Value"/>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </inp2:m_if>
</table>
<script type="text/javascript">
<inp2:m_if check="m_Get" name="refresh_tree">
getFrame('menu').location.reload();
</inp2:m_if>
+
+ <inp2:m_if check="adm_MemoryCacheEnabled">
+ $(document).ready(
+ function () {
+ $('#memory_cache_get').click(
+ function ($e) {
+ var $me = $(this);
+
+ $me.attr('disabled', 'disabled').removeClass('button').addClass('button-disabled');
+
+ $.post(
+ '<inp2:m_Link template="dummy" pass="m,adm" adm_event="OnMemoryCacheGet" js_escape="1" no_amp="1"/>',
+ {
+ key: $('#memory_cache_key_name').val()
+ },
+ function ($data) {
+ $data = eval('(' + $data + ')');
+
+ if ($data.code === 0) {
+ if (confirm('Data Size: ' + $data.size + '. Type: ' + $data.type + '. Display data?')) {
+ $('#memory_cache_key_value').val($data.value);
+ }
+ }
+ else {
+ alert($data.message);
+ }
+
+ $me.attr('disabled', '').addClass('button').removeClass('button-disabled');
+ }
+ );
+
+ }
+ );
+
+ $('a.quick-memory-cache-key').click(
+ function ($e) {
+ $('#memory_cache_key_name').val( $(this).text() );
+ $('#memory_cache_get').click();
+
+ return false;
+ }
+ );
+
+ $('#memory_cache_set').click(
+ function ($e) {
+ var $me = $(this);
+
+ $me.attr('disabled', 'disabled').removeClass('button').addClass('button-disabled');
+
+ $.post(
+ '<inp2:m_Link template="dummy" pass="m,adm" adm_event="OnMemoryCacheSet" js_escape="1" no_amp="1"/>',
+ {
+ key: $('#memory_cache_key_name').val(),
+ value: $('#memory_cache_key_value').val()
+ },
+ function ($data) {
+ $data = eval('(' + $data + ')');
+
+ if ($data.code === 0) {
+ alert($data.result);
+ }
+ else {
+ alert($data.message);
+ }
+
+ $me.attr('disabled', '').addClass('button').removeClass('button-disabled');
+ }
+ );
+
+ }
+ );
+ }
+ );
+ </inp2:m_if>
</script>
<inp2:m_include t="incs/footer"/>
\ No newline at end of file
Index: core/install/install_data.sql
===================================================================
--- core/install/install_data.sql (revision 13152)
+++ core/install/install_data.sql (working copy)
@@ -175,6 +175,8 @@
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CSVExportSeparator', '0', 'In-Portal', 'in-portal:configure_advanced');
INSERT INTO ConfigurationAdmin VALUES ('CSVExportEncoding', 'la_section_SettingsCSVExport', 'la_config_CSVExportEncoding', 'radio', NULL, '0=la_Unicode,1=la_Regular', 70.04, 0, 1);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CSVExportEncoding', '0', 'In-Portal', 'in-portal:configure_advanced');
+INSERT INTO ConfigurationAdmin VALUES ('MemcacheServers', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', '', '', 80.01, 0, 0);
+INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MemcacheServers', 'localhost:11211', 'In-Portal', 'in-portal:configure_advanced');
# Section "in-portal:configure_users":
INSERT INTO ConfigurationAdmin VALUES ('User_Allow_New', 'la_title_General', 'la_users_allow_new', 'radio', '', '1=la_opt_UserInstantRegistration,2=la_opt_UserNotAllowedRegistration,3=la_opt_UserUponApprovalRegistration,4=la_opt_UserEmailActivation', 10.01, 0, 1);
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql (revision 13152)
+++ core/install/install_schema.sql (working copy)
@@ -448,6 +448,10 @@
FormSubmittedTemplate varchar(255) DEFAULT NULL,
FriendlyURL varchar(255) NOT NULL DEFAULT '',
ThemeId int(10) unsigned NOT NULL DEFAULT '0',
+ EnablePageCache tinyint(4) NOT NULL DEFAULT '0',
+ OverridePageCacheKey tinyint(4) NOT NULL DEFAULT '0',
+ PageCacheKey varchar(255) NOT NULL DEFAULT '',
+ PageExpiration int(11) DEFAULT NULL,
PRIMARY KEY (CategoryId),
UNIQUE KEY ResourceId (ResourceId),
KEY ParentId (ParentId),
@@ -471,7 +475,10 @@
KEY `Status` (`Status`),
KEY CreatedOn (CreatedOn),
KEY EditorsPick (EditorsPick),
- KEY ThemeId (ThemeId)
+ KEY ThemeId (ThemeId),
+ KEY EnablePageCache (EnablePageCache),
+ KEY OverridePageCacheKey (OverridePageCacheKey),
+ KEY PageExpiration (PageExpiration)
);
CREATE TABLE CategoryCustomData (
@@ -1095,4 +1102,20 @@
KEY SessionKey (SessionKey),
KEY `Timestamp` (`Timestamp`),
KEY MainPrefix (MainPrefix)
+);
+
+CREATE TABLE CachedUrls (
+ UrlId int(11) NOT NULL AUTO_INCREMENT,
+ Url varchar(255) NOT NULL DEFAULT '',
+ `Hash` int(11) NOT NULL DEFAULT '0',
+ Prefixes varchar(255) NOT NULL DEFAULT '',
+ ParsedVars text NOT NULL,
+ Cached int(10) unsigned DEFAULT NULL,
+ LifeTime int(11) NOT NULL DEFAULT '-1',
+ PRIMARY KEY (UrlId),
+ KEY Url (Url),
+ KEY `Hash` (`Hash`),
+ KEY Prefixes (Prefixes),
+ KEY Cached (Cached),
+ KEY LifeTime (LifeTime)
);
\ No newline at end of file
Index: core/install/install_toolkit.php
===================================================================
--- core/install/install_toolkit.php (revision 13152)
+++ core/install/install_toolkit.php (working copy)
@@ -789,10 +789,7 @@
*/
function deleteCache($refresh_permissions = false)
{
- $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName IN ("config_files", "configs_parsed", "sections_parsed")';
- $this->Conn->Query($sql);
-
+ $this->Application->HandleEvent($event, 'adm:OnResetConfigsCache');
$this->Application->HandleEvent($event, 'c:OnResetCMSMenuCache');
if ($refresh_permissions) {
@@ -805,12 +802,7 @@
}
else {
// refresh permissions with ajax progress bar (when available)
- $fields_hash = Array (
- 'VarName' => 'ForcePermCacheUpdate',
- 'Data' => 1,
- );
-
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache');
+ $this->Application->setDBCache('ForcePermCacheUpdate', 1);
}
}
}
Index: core/install/remove_schema.sql
===================================================================
--- core/install/remove_schema.sql (revision 13152)
+++ core/install/remove_schema.sql (working copy)
@@ -68,3 +68,4 @@
DROP TABLE FormSubmissions;
DROP TABLE Forms;
DROP TABLE Semaphores;
+DROP TABLE CachedUrls;
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql (revision 13161)
+++ core/install/upgrades.sql (working copy)
@@ -1652,3 +1652,33 @@
DELETE FROM PersistantSessionData WHERE VariableName = 'phrases_columns_.';
UPDATE Category SET FormId = NULL WHERE FormId = 0;
+
+INSERT INTO ConfigurationAdmin VALUES ('MemcacheServers', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', '', '', 80.01, 0, 0);
+INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MemcacheServers', 'localhost:11211', 'In-Portal', 'in-portal:configure_advanced');
+
+ALTER TABLE Category
+ ADD EnablePageCache TINYINT NOT NULL DEFAULT '0',
+ ADD OverridePageCacheKey TINYINT NOT NULL DEFAULT '0',
+ ADD PageCacheKey VARCHAR(255) NOT NULL DEFAULT '',
+ ADD PageExpiration INT NULL DEFAULT NULL ,
+ ADD INDEX (EnablePageCache),
+ ADD INDEX (OverridePageCacheKey),
+ ADD INDEX (PageExpiration);
+
+DELETE FROM Cache WHERE VarName LIKE 'mod_rw_%';
+
+CREATE TABLE CachedUrls (
+ UrlId int(11) NOT NULL AUTO_INCREMENT,
+ Url varchar(255) NOT NULL DEFAULT '',
+ `Hash` int(11) NOT NULL DEFAULT '0',
+ Prefixes varchar(255) NOT NULL DEFAULT '',
+ ParsedVars text NOT NULL,
+ Cached int(10) unsigned DEFAULT NULL,
+ LifeTime int(11) NOT NULL DEFAULT '-1',
+ PRIMARY KEY (UrlId),
+ KEY Url (Url),
+ KEY `Hash` (`Hash`),
+ KEY Prefixes (Prefixes),
+ KEY Cached (Cached),
+ KEY LifeTime (LifeTime)
+);
\ No newline at end of file
Index: core/kernel/application.php
===================================================================
--- core/kernel/application.php (revision 13152)
+++ core/kernel/application.php (working copy)
@@ -198,11 +198,11 @@
var $CurrentNTag = null;
/**
- * Memcache object pointer
+ * Object of memory caching class
*
- * @var Memcache
+ * @var kCache
*/
- var $Memcached = null;
+ var $memoryCache = null;
/**
* Tells, that administrator has authentificated in administrative console
@@ -254,40 +254,6 @@
return $instance;
}
- function InitMemcached()
- {
- return ;
-
- $memcached_servers = 'localhost:11211'; // $this->Application->ConfigValue('MemcachedServers');
-
- if ($memcached_servers && class_exists('Memcache')) {
- $this->Memcached = new Memcache();
- $servers = explode(';', $memcached_servers);
- foreach ($servers as $server) {
- list ($server, $port) = strpos($server, ':') !== false ? explode(':', $server, 2) : Array ($server, 11211);
- $this->Memcached->addServer($server, $port);
- }
- }
-
- //try to set something to cache, if not working - set $this->Memcached to null
- }
-
- function CacheSet($name, $value, $expiration)
- {
- if (isset($this->Memcached)) {
- return $this->Memcached->set($name, $value, 0, $expiration);
- }
- return false;
- }
-
- function CacheGet($name)
- {
- if (isset($this->Memcached)) {
- return $this->Memcached->get($name);
- }
- return false;
- }
-
/**
* Initializes the Application
*
@@ -305,8 +271,6 @@
$this->isAdmin = constOn('ADMIN');
- $this->InitMemcached();
-
if (!constOn('SKIP_OUT_COMPRESSION')) {
ob_start(); // collect any output from method (other then tags) into buffer
}
@@ -333,6 +297,7 @@
$this->Factory = new kFactory();
$this->registerDefaultClasses();
$this->Phrases = new PhrasesCache();
+ $this->memoryCache =& $this->Factory->makeClass('Cache');
$this->EventManager =& $this->Factory->makeClass('EventManager');
$this->Factory->Storage['EventManager'] =& $this->EventManager;
$this->RegisterDefaultBuildEvents();
@@ -386,13 +351,11 @@
$this->LoadCache();
$this->InitConfig();
- $this->Phrases->Init('phrases');
-
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Loaded cache and phrases');
}
- $this->ValidateLogin();
+ $this->ValidateLogin(); // must be called before AfterConfigRead, because current user should be available there
$this->UnitConfigReader->AfterConfigRead();
@@ -400,20 +363,20 @@
$this->Debugger->appendTimestamp('Processed AfterConfigRead');
}
- /*// Module items are recalled during url parsing & PhrasesCache is needed already there,
- // because it's used in their build events. That's why phrases cache initialization is
- // called from kHTTPQuery in case when mod_rewrite is used
- if (!$this->RewriteURLs()) {
- $this->Phrases = new PhrasesCache();
- }*/
+ if ($this->GetVar('m_cat_id') === false) {
+ $this->SetVar('m_cat_id', 0);
+ }
- if ($this->GetVar('m_cat_id') === false) $this->SetVar('m_cat_id', 0);
if (!$this->RecallVar('curr_iso')) {
$this->StoreVar('curr_iso', $this->GetPrimaryCurrency(), true); // true for optional
}
- $this->SetVar('visits_id', $this->RecallVar('visit_id') );
+ $visit_id = $this->RecallVar('visit_id');
+ if ($visit_id !== false) {
+ $this->SetVar('visits_id', $visit_id);
+ }
+
$language =& $this->recallObject( 'lang.current', null, Array('live_table' => true) );
if (preg_match('/utf-8/', $language->GetDBField('Charset'))) {
setlocale(LC_ALL, 'en_US.UTF-8');
@@ -494,8 +457,8 @@
$language_id = 'default';
}
- $this->SetVar('lang.current_id', $language_id );
- $this->SetVar('m_lang', $language_id );
+ $this->SetVar('lang.current_id', $language_id);
+ $this->SetVar('m_lang', $language_id);
$lang_mode = $this->GetVar('lang_mode');
$this->SetVar('lang_mode', '');
@@ -567,17 +530,23 @@
function GetDefaultLanguageId($init = false)
{
- static $language_info = null;
+ $cache_key = 'primary_language_info[%LangSerial%]';
+ $language_info = $this->getCache($cache_key);
- if (!isset($language_info)) {
+ if ($language_info === false) {
// cache primary language info first
$table = $this->getUnitOption('lang', 'TableName');
$id_field = $this->getUnitOption('lang', 'IDField');
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT ' . $id_field . ', IF(AdminInterfaceLang, "Admin", "Front") AS LanguageKey
FROM ' . $table . '
WHERE (AdminInterfaceLang = 1 OR PrimaryLang = 1) AND (Enabled = 1)';
$language_info = $this->Conn->GetCol($sql, 'LanguageKey');
+
+ if ($language_info !== false) {
+ $this->setCache($cache_key, $language_info);
+ }
}
$language_key = ($this->isAdmin && $init) || count($language_info) == 1 ? 'Admin' : 'Front';
@@ -611,12 +580,20 @@
$theme_id = 999;
}
else {
- $table = $this->getUnitOption('theme','TableName');
- $id_field = $this->getUnitOption('theme','IDField');
- $sql = 'SELECT '.$id_field.'
- FROM '.$table.'
- WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
- $theme_id = $this->Conn->GetOne($sql);
+ $cache_key = 'primary_theme[%ThemeSerial%]';
+ $theme_id = $this->getCache($cache_key);
+
+ if ($theme_id === false) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT ' . $this->getUnitOption('theme', 'IDField') . '
+ FROM ' . $this->getUnitOption('theme', 'TableName') . '
+ WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
+ $theme_id = $this->Conn->GetOne($sql);
+
+ if ($theme_id !== false) {
+ $this->setCache($cache_key, $theme_id);
+ }
+ }
}
return $theme_id;
@@ -624,13 +601,25 @@
function GetPrimaryCurrency()
{
- if ($this->isModuleEnabled('In-Commerce')) {
- $table = $this->getUnitOption('curr', 'TableName');
- return $this->Conn->GetOne('SELECT ISO FROM '.$table.' WHERE IsPrimary = 1');
+ $cache_key = 'primary_currency[%CurrSerial%]';
+ $primary_currency = $this->getCache($cache_key);
+
+ if ($primary_currency === false) {
+ if ($this->isModuleEnabled('In-Commerce')) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT ISO
+ FROM ' . $this->getUnitOption('curr', 'TableName') . '
+ WHERE IsPrimary = 1';
+ $primary_currency = $this->Conn->GetOne($sql);
+ }
+ else {
+ $primary_currency = 'USD';
+ }
+
+ $this->setCache($cache_key, $primary_currency);
}
- else {
- return 'USD';
- }
+
+ return $primary_currency;
}
/**
@@ -693,99 +682,231 @@
}
/**
- * Returns item's filename that corresponds id passed. If possible, then get it from cache
+ * Returns cached category informaton by given cache name. All given category
+ * information is recached, when at least one of 4 caches is missing.
*
- * @param string $prefix
- * @param int $id
+ * @param int $category_id
+ * @param string $name cache name = {filenames, category_designs, category_tree}
* @return string
*/
- function getFilename($prefix, $id, $category_id=null)
+ function getCategoryCache($category_id, $name)
{
- $filename = $this->getCache('filenames', $prefix.'_'.$id);
- if ($filename === false) {
- $table = $this->getUnitOption($prefix, 'TableName');
- $id_field = $this->getUnitOption($prefix, 'IDField');
+ $serial_name = '[%CIDSerial:' . $category_id . '%]';
+ $cache_key = $name . $serial_name;
+ $ret = $this->getCache($cache_key);
- if ($prefix == 'c') {
- if(!$id) {
- $this->setCache('filenames', $prefix.'_'.$id, '');
- return '';
- }
+ if ($ret === false) {
+ if (!$category_id) {
+ // don't query database for "Home" category (ID = 0), because it doesn't exist in database
+ return false;
+ }
- // this allows to save 2 sql queries for each category
- $sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight
- FROM '.$table.'
- WHERE '.$id_field.' = '.$this->Conn->qstr($id);
- $category_data = $this->Conn->GetRow($sql);
+ // this allows to save 2 sql queries for each category
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . (int)$category_id;
+ $category_data = $this->Conn->GetRow($sql);
+ if ($category_data !== false) {
// only direct links to category pages work (symlinks, container pages and so on won't work)
- $filename = $category_data['NamedParentPath'];
- $this->setCache('category_templates', $id, $filename);
- $this->setCache('category_designs', $id, ltrim($category_data['CachedTemplate'], '/'));
- $this->setCache('category_tree', $id, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']);
+ $this->setCache('filenames' . $serial_name, $category_data['NamedParentPath']);
+ $this->setCache('category_designs' . $serial_name, ltrim($category_data['CachedTemplate'], '/'));
+ $this->setCache('category_tree' . $serial_name, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']);
}
- else {
- $sql = 'SELECT ResourceId
- FROM ' . $table . '
- WHERE ' . $id_field . ' = ' . $this->Conn->qstr($id);
- $resource_id = $this->Conn->GetOne($sql);
+ }
- if (is_null($category_id)) {
- $category_id = $this->GetVar('m_cat_id');
- }
+ return $this->getCache($cache_key);
+ }
- $sql = 'SELECT Filename
- FROM ' . TABLE_PREFIX . 'CategoryItems
- WHERE (ItemResourceId = ' . $resource_id . ') AND (CategoryId = ' . (int)$category_id . ')';
- $filename = $this->Conn->GetOne($sql);
+ /**
+ * Returns item's filename that corresponds id passed. If possible, then get it from cache
+ *
+ * @param string $prefix
+ * @param int $id
+ * @param int $category_id
+ * @return string
+ */
+ function getFilename($prefix, $id, $category_id = null)
+ {
+ if ($prefix == 'c') {
+ trigger_error('Method "<strong>' . __FUNCTION__ . '</strong>" no longer work with "<strong>c</strong>" prefix. Please use "<strong>getCategoryCache</strong>" method instead.', E_USER_ERROR);
+ return false;
+ }
- /*if (!$filename) {
- $sql = 'SELECT Filename
- FROM ' . TABLE_PREFIX . 'CategoryItems
- WHERE ItemResourceId = ' . $resource_id . ' AND PrimaryCat = 1';
- $filename = $this->Conn->GetOne($sql);
- }
+ $category_id = isset($category_id) ? $category_id : $this->GetVar('m_cat_id');
- $sql = 'SELECT Filename
- FROM ' . $table . '
- WHERE ' . $id_field . ' = ' . $this->Conn->qstr($id);
- $filename = $this->Conn->GetOne($sql);*/
+ $cache_key = 'filenames[%' . $this->incrementCacheSerial($prefix, $id, false) . '%]:' . (int)$category_id;
+ $filename = $this->getCache($cache_key);
+
+ if ($filename === false) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT ResourceId
+ FROM ' . $this->getUnitOption($prefix, 'TableName') . '
+ WHERE ' . $this->getUnitOption($prefix, 'IDField') . ' = ' . $this->Conn->qstr($id);
+ $resource_id = $this->Conn->GetOne($sql);
+
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT Filename
+ FROM ' . TABLE_PREFIX . 'CategoryItems
+ WHERE (ItemResourceId = ' . $resource_id . ') AND (CategoryId = ' . (int)$category_id . ')';
+ $filename = $this->Conn->GetOne($sql);
+
+ if ($filename !== false) {
+ $this->setCache($cache_key, $filename);
}
- $this->setCache('filenames', $prefix.'_'.$id, $filename);
}
+
return $filename;
}
+ /**
+ * Returns caching type (none, memory, temporary)
+ *
+ * @return int
+ */
+ function isCachingType($caching_type)
+ {
+ return $this->memoryCache->getCachingType() == $caching_type;
+ }
/**
+ * Increments serial based on prefix and it's ID (optional)
+ *
+ * @param string $prefix
+ * @param int $id ID (value of IDField) or ForeignKeyField:ID
+ * @param bool $increment
+ */
+ function incrementCacheSerial($prefix, $id = null, $increment = true)
+ {
+ $pascal_case_prefix = implode('', array_map('ucfirst', explode('-', $prefix)));
+ $serial_name = $pascal_case_prefix . (isset($id) ? 'IDSerial:' . $id : 'Serial');
+
+ if ($increment) {
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Incrementing serial: <strong>' . $serial_name . '</strong>.');
+ }
+
+ if ($this->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->setCache($serial_name, (int)$this->getCache($serial_name) + 1);
+ }
+
+ // delete cached mod-rewrite urls related to given prefix and id
+ $delete_clause = isset($id) ? $prefix . ':' . $id : $prefix;
+
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls
+ WHERE Prefixes LIKE ' . $this->Conn->qstr('%|' . $delete_clause . '|%');
+ $this->Conn->Query($sql);
+ }
+
+ return $serial_name;
+ }
+
+ /**
* Adds new value to cache $cache_name and identified by key $key
*
- * @param string $cache_name cache name
* @param int $key key name to add to cache
* @param mixed $value value of chached record
+ * @param int $expiration when value expires (0 - doesn't expire)
*/
- function setCache($cache_name, $key, $value, $expiration=3600)
+ function setCache($key, $value, $expiration = 0)
{
- $cache =& $this->recallObject('Cache');
- /* @var $cache kCache */
+ return $this->memoryCache->setCache($key, $value, $expiration);
+ }
- return $cache->setCache($cache_name, $key, $value, $expiration);
+ /**
+ * Sets value to database cache
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param int $expiration
+ */
+ function setDBCache($name, &$value, $expiration = false)
+ {
+ if ((int)$expiration <= 0) {
+ $expiration = -1;
+ }
+
+ $fields_hash = Array (
+ 'VarName' => $name,
+ 'Data' => &$value,
+ 'Cached' => adodb_mktime(),
+ 'LifeTime' => (int)$expiration,
+ );
+
+ $this->Conn->nextQueryCachable = true;
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
}
/**
* Returns cached $key value from cache named $cache_name
*
- * @param string $cache_name cache name
* @param int $key key name from cache
+ * @param bool $store_locally store data locally after retrieved
* @return mixed
*/
- function getCache($cache_name, $key)
+ function getCache($key, $store_locally = true)
{
- $cache =& $this->recallObject('Cache');
- return $cache->getCache($cache_name, $key);
+ return $this->memoryCache->getCache($key, $store_locally);
}
/**
+ * Returns value from database cache
+ *
+ * @param string $name key name
+ * @return mixed
+ */
+ function getDBCache($name)
+ {
+ $this->Conn->nextQueryCachable = true;
+
+ $sql = 'SELECT Data, Cached, LifeTime
+ FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = ' . $this->Conn->qstr($name);
+ $data = $this->Conn->GetRow($sql);
+
+ if ($data) {
+ $lifetime = (int)$data['LifeTime']; // in seconds
+ if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) {
+ // delete expired
+ $this->Conn->nextQueryCachable = true;
+
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = ' . $this->Conn->qstr($name);
+ $this->Conn->Query($sql);
+
+ return false;
+ }
+
+ return $data['Data'];
+ }
+
+ return false;
+ }
+
+ /**
+ * Deletes key from cache
+ *
+ * @param string $key
+ */
+ function deleteCache($key)
+ {
+ $this->memoryCache->delete($key);
+ }
+
+ /**
+ * Deletes key from database cache
+ *
+ * @param string $name
+ */
+ function deleteDBCache($name)
+ {
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = ' . $this->Conn->qstr($name);
+ $this->Conn->Query($sql);
+ }
+
+ /**
* Defines default constants if it's not defined before - in config.php
*
* @access private
@@ -805,13 +926,18 @@
k4_include_once(KERNEL_PATH.'/constants.php');
}
- if (!$this->ModuleInfo) return false;
- foreach($this->ModuleInfo as $module_name => $module_info)
- {
- $module_path = '/'.$module_info['Path'];
- $contants_file = FULL_PATH.$module_path.'constants.php';
- if( file_exists($contants_file) ) k4_include_once($contants_file);
+ if (!$this->ModuleInfo) {
+ return false;
}
+
+ foreach ($this->ModuleInfo as $module_name => $module_info) {
+ $contants_file = FULL_PATH . '/' . $module_info['Path'] . 'constants.php';
+
+ if (file_exists($contants_file)) {
+ k4_include_once($contants_file);
+ }
+ }
+
return true;
}
@@ -937,8 +1063,7 @@
$this->Session->SaveData();
if (constOn('DBG_CACHE')) {
- $cache =& $this->recallObject('Cache');
- $cache->printStatistics();
+ $this->memoryCache->printStatistics();
}
$this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true);
@@ -1411,7 +1536,8 @@
$target_url = 'http://'.DOMAIN.$this->ConfigValue('Site_Path');
}
- if (!preg_match('#'.preg_quote($cookie_url).'#', $target_url)) {
+ // set session to GET_ONLY, to pass sid only if sid is REAL AND session is set
+ if (!preg_match('#'.preg_quote($cookie_url).'#', $target_url) && $session->SessionSet) {
$session->SetMode(smGET_ONLY);
}
}
@@ -1847,17 +1973,15 @@
}
if (strtolower($t) == '__default__') {
- // to put category & item templates into cache
- $filename = $this->getFilename('c', $category_id);
if (is_numeric($item_id)) {
$mod_rw_helper =& $this->Application->recallObject('ModRewriteHelper');
/* @var $mod_rw_helper kModRewriteHelper */
$t = $mod_rw_helper->GetItemTemplate($category_id, $pass_element); // $pass_element should be the last processed element
-// $t = $this->getCache('item_templates', $category_id);
+ // $t = $this->getCategoryCache($category_id, 'item_templates');
}
elseif ($category_id) {
- $t = strtolower( preg_replace('/^Content\//i', '', $this->getCache('category_templates', $category_id)) );
+ $t = strtolower(preg_replace('/^Content\//i', '', $this->getCategoryCache($category_id, 'filenames') ));
}
else {
$t = 'index';
@@ -2057,39 +2181,44 @@
$this->Session->LoadPersistentVars();
}
- function LoadCache() {
- $cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->isAdmin;
- $query = sprintf("SELECT PhraseList, ConfigVariables FROM %s WHERE Template = %s",
- TABLE_PREFIX.'PhraseCache',
- $this->Conn->qstr(md5($cache_key)));
- $res = $this->Conn->GetRow($query);
+ function LoadCache()
+ {
+ // TODO: maybe language part isn't required, since same phrase from different languages have one ID now
+ $cache_key = $this->GetVar('t') . $this->GetVar('m_theme') . $this->GetVar('m_lang') . $this->isAdmin;
+ $sql = 'SELECT PhraseList, ConfigVariables
+ FROM ' . TABLE_PREFIX . 'PhraseCache
+ WHERE Template = ' . $this->Conn->qstr( md5($cache_key) );
+ $res = $this->Conn->GetRow($sql);
+
if ($res) {
- $this->Caches['PhraseList'] = $res['PhraseList'] ? explode(',', $res['PhraseList']) : array();
+ $this->Caches['PhraseList'] = $res['PhraseList'] ? explode(',', $res['PhraseList']) : Array ();
+ $config_ids = $res['ConfigVariables'] ? explode(',', $res['ConfigVariables']) : Array ();
- $config_ids = $res['ConfigVariables'] ? explode(',', $res['ConfigVariables']) : array();
if (isset($this->Caches['ConfigVariables'])) {
$config_ids = array_diff($config_ids, $this->Caches['ConfigVariables']);
}
}
else {
- $config_ids = array();
+ $config_ids = Array ();
}
+
+ $this->Phrases->Init('phrases');
$this->Caches['ConfigVariables'] = $config_ids;
$this->ConfigCacheIds = $config_ids;
}
+ /**
+ * Loads template mapping for Front-End
+ *
+ */
function LoadStructureTemplateMapping()
{
- // get template mapping
- $sql = 'SELECT Data
- FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "template_mapping"';
- $template_mapping = $this->Conn->GetOne($sql);
+ if (!$this->isAdmin) {
+ $category_helper =& $this->Application->recallObject('CategoryHelper');
+ /* @var $category_helper CategoryHelper */
- if (!$this->isAdmin && $template_mapping) {
- // template mappings only for Front-End
- $this->structureTemplateMapping = unserialize($template_mapping);
+ $this->structureTemplateMapping = $category_helper->getTemplateMapping();
}
}
@@ -2099,14 +2228,15 @@
//something changed
$update = $update || $this->Phrases->NeedsCacheUpdate();
$update = $update || (count($this->ConfigCacheIds) && $this->ConfigCacheIds != $this->Caches['ConfigVariables']);
+
if ($update) {
$cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->isAdmin;
$query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables)
VALUES (%s, %s, %s, %s)",
TABLE_PREFIX.'PhraseCache',
- $this->Conn->Qstr(join(',', $this->Phrases->Ids)),
+ $this->Conn->qstr(join(',', $this->Phrases->Ids)),
adodb_mktime(),
- $this->Conn->Qstr(md5($cache_key)),
+ $this->Conn->qstr(md5($cache_key)),
$this->Conn->qstr(implode(',', array_unique($this->ConfigCacheIds))));
$this->Conn->Query($query);
}
@@ -2115,9 +2245,10 @@
function InitConfig()
{
if (isset($this->Caches['ConfigVariables']) && count($this->Caches['ConfigVariables']) > 0) {
- $this->ConfigHash = array_merge($this->ConfigHash, $this->Conn->GetCol(
- 'SELECT VariableValue, VariableName FROM '.TABLE_PREFIX.'ConfigurationValues
- WHERE VariableId IN ('.implode(',', $this->Caches['ConfigVariables']).')', 'VariableName'));
+ $sql = 'SELECT VariableValue, VariableName
+ FROM ' . TABLE_PREFIX . 'ConfigurationValues
+ WHERE VariableId IN (' . implode(',', $this->Caches['ConfigVariables']) . ')';
+ $this->ConfigHash = array_merge($this->ConfigHash, $this->Conn->GetCol($sql, 'VariableName'));
}
}
@@ -2988,10 +3119,8 @@
*/
function getTreeIndex($category_id)
{
- $category_template = $this->getFilename('c', $category_id); // to rebuild "category_tree" cache
+ $tree_index = $this->getCategoryCache($category_id, 'category_tree');
- $tree_index = $this->getCache('category_tree', $category_id);
-
if ($tree_index) {
$ret = Array ();
list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index);
Index: core/kernel/db/cat_event_handler.php
===================================================================
--- core/kernel/db/cat_event_handler.php (revision 13159)
+++ core/kernel/db/cat_event_handler.php (working copy)
@@ -814,13 +814,18 @@
)');
// hot items (cache updated every hour)
- $sql = 'SELECT Data
- FROM '.TABLE_PREFIX.'Cache
- WHERE (VarName = "'.$property_map['HotLimit'].'") AND (Cached >'.(adodb_mktime() - 3600).')';
- $hot_limit = $this->Conn->GetOne($sql);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $serial_name = $this->Application->incrementCacheSerial($event->Prefix, null, false);
+ $hot_limit = $this->Application->getCache($property_map['HotLimit'] . '[%' . $serial_name . '%]');
+ }
+ else {
+ $hot_limit = $this->Application->getDBCache($property_map['HotLimit']);
+ }
+
if ($hot_limit === false) {
$hot_limit = $this->CalculateHotLimit($event);
}
+
$object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2,
IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0),
%1$s.HotItem
@@ -840,9 +845,11 @@
function CalculateHotLimit(&$event)
{
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
+
if (!$property_map) {
return;
}
+
$click_field = $property_map['ClickField'];
$last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1;
@@ -851,10 +858,16 @@
LIMIT '.$last_hot.', 1';
$res = $this->Conn->GetCol($sql);
$hot_limit = (double)array_shift($res);
- $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("'.$property_map['HotLimit'].'", "'.$hot_limit.'", '.adodb_mktime().')');
+
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $serial_name = $this->Application->incrementCacheSerial($event->Prefix, null, false);
+ $this->Application->setCache($property_map['HotLimit'] . '[%' . $serial_name . '%]', $hot_limit);
+ }
+ else {
+ $this->Application->setDBCache($property_map['HotLimit'], $hot_limit, 3600);
+ }
+
return $hot_limit;
-
- return 0;
}
/**
@@ -1604,10 +1617,7 @@
case 'HotItem':
$hot_limit_var = getArrayValue($property_mappings, 'HotLimit');
if ($hot_limit_var) {
- $sql = 'SELECT Data
- FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = "'.$hot_limit_var.'"';
- $hot_limit = (int)$this->Conn->GetOne($sql);
+ $hot_limit = (int)$this->Application->getDBCache($hot_limit_var);
$condition = 'IF('.$items_table.'.HotItem = 2,
IF('.$items_table.'.Hits >= '.
Index: core/kernel/db/cat_tag_processor.php
===================================================================
--- core/kernel/db/cat_tag_processor.php (revision 13159)
+++ core/kernel/db/cat_tag_processor.php (working copy)
@@ -241,7 +241,15 @@
$object =& $this->getObject($params);
$category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
- $category_path = $this->Application->getCache('category_paths', $category_id);
+ $cache_key = 'category_paths[%CIDSerial:' . $category_id . '%]';
+
+ if ($category_id == 0) {
+ // home category name is phrase AND phrase name is defined in configuration
+ $cache_key .= '[%PhrasesSerial%][%ConfSerial%]';
+ }
+
+ $category_path = $this->Application->getCache($cache_key);
+
if ($category_path === false) {
// not chached
if ($category_id > 0) {
@@ -251,8 +259,10 @@
else {
$category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
}
- $this->Application->setCache('category_paths', $category_id, $category_path);
+
+ $this->Application->setCache($cache_key, $category_path);
}
+
return $category_path;
}
@@ -336,10 +346,22 @@
function HasAdditionalImages($params)
{
$object =& $this->getObject($params);
- $sql = 'SELECT ImageId
- FROM '.$this->Application->getUnitOption('img', 'TableName').'
- WHERE ResourceId = '.$object->GetDBField('ResourceId').' AND DefaultImg != 1 AND Enabled = 1';
- return $this->Conn->GetOne($sql) ? 1 : 0;
+ /* @var $object kDBItem */
+
+ $cache_key = 'product_additional_images[%PIDSerial:' . $object->GetID() . '%]';
+ $ret = $this->Application->getCache($cache_key);
+
+ if ($ret === false) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT ImageId
+ FROM ' . $this->Application->getUnitOption('img', 'TableName') . '
+ WHERE ResourceId = ' . $object->GetDBField('ResourceId') . ' AND DefaultImg != 1 AND Enabled = 1';
+ $ret = $this->Conn->GetOne($sql) ? 1 : 0;
+
+ $this->Application->setCache($cache_key, $ret);
+ }
+
+ return $ret;
}
/**
@@ -589,29 +611,37 @@
*/
function LastUpdated($params)
{
- $category_id = $this->Application->GetVar('m_cat_id');
- $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
+ $category_id = (int)$this->Application->GetVar('m_cat_id');
+ $local = array_key_exists('local', $params) && ($category_id > 0) ? $params['local'] : false;
- if (isset($params['local']) && $params['local'] && $category_id > 0) {
- // scan only current category & it's children
- $sql = 'SELECT TreeLeft, TreeRight
- FROM ' . TABLE_PREFIX . 'Category
- WHERE CategoryId = ' . (int)$category_id;
- $tree_info = $this->Conn->GetRow($sql);
+ $serial_name1 = $this->Application->incrementCacheSerial('c', $local ? $category_id : null, false);
+ $serial_name2 = $this->Application->incrementCacheSerial($this->Prefix, null, false);
+ $cache_key = 'categoryitems_last_updated[%' . $serial_name1 . '%][%' . $serial_name2 . '%]';
- $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate
- FROM '.$table_name.' item_table
- LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId)
- LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
- WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight'];
- }
- else {
- // scan all categories in system
- $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
- FROM '.$table_name;
- }
+ $row_data = $this->Application->getCache($cache_key);
- $row_data = $this->Conn->GetRow($sql);
+ if ($row_data === false) {
+ if ($local && ($category_id > 0)) {
+ // scan only current category & it's children
+ list ($tree_left, $tree_right) = $this->Application->getTreeIndex($category_id);
+
+ $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate
+ FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . ' item_table
+ LEFT JOIN ' . TABLE_PREFIX . 'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId)
+ LEFT JOIN ' . TABLE_PREFIX . 'Category c ON c.CategoryId = ci.CategoryId
+ WHERE c.TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right;
+ }
+ else {
+ // scan all categories in system
+ $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
+ FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName');
+ }
+
+ $this->Conn->nextQueryCachable = true;
+ $row_data = $this->Conn->GetRow($sql);
+ $this->Application->setCache($cache_key, $row_data);
+ }
+
if (!$row_data) {
return '';
}
Index: core/kernel/db/db_connection.php
===================================================================
--- core/kernel/db/db_connection.php (revision 13152)
+++ core/kernel/db/db_connection.php (working copy)
@@ -122,6 +122,13 @@
var $_queryTime = 0;
/**
+ * Indicates, that next database query could be cached, when memory caching is enabled
+ *
+ * @var bool
+ */
+ var $nextQueryCachable = false;
+
+ /**
* Initializes connection class with
* db type to used in future
*
@@ -489,10 +496,11 @@
}
// set 2nd checkpoint: begin
- $first_cell = count($ret) == 1 && count(current($ret)) == 1 ? current(current($ret)) : null;
if ($profileSQLs) {
- $debugger->profileFinish('sql_'.$queryID, null, null, $this->getAffectedRows(), $first_cell, $this->_queryCount);
+ $first_cell = count($ret) == 1 && count(current($ret)) == 1 ? current(current($ret)) : null;
+ $debugger->profileFinish('sql_'.$queryID, null, null, $this->getAffectedRows(), $first_cell, $this->_queryCount, $this->nextQueryCachable);
$debugger->profilerAddTotal('sql', 'sql_'.$queryID);
+ $this->nextQueryCachable = false;
}
// set 2nd checkpoint: end
@@ -502,8 +510,9 @@
else {
// set 2nd checkpoint: begin
if ($profileSQLs) {
- $debugger->profileFinish('sql_'.$queryID, null, null, $this->getAffectedRows(), null, $this->_queryCount);
+ $debugger->profileFinish('sql_'.$queryID, null, null, $this->getAffectedRows(), null, $this->_queryCount, $this->nextQueryCachable);
$debugger->profilerAddTotal('sql', 'sql_'.$queryID);
+ $this->nextQueryCachable = false;
}
// set 2nd checkpoint: end
}
Index: core/kernel/db/db_event_handler.php
===================================================================
--- core/kernel/db/db_event_handler.php (revision 13161)
+++ core/kernel/db/db_event_handler.php (working copy)
@@ -279,7 +279,7 @@
$resulting_ids = $direct_ids ? array_values($direct_ids) : ($ids ? array_values($ids) : false);
if ($resulting_ids) {
$this->Application->SetVar($event->getPrefixSpecial() . '_selected_ids', implode(',', $resulting_ids));
- $this->Application->LinkVar($event->getPrefixSpecial() . '_selected_ids', $session_name);
+ $this->Application->LinkVar($event->getPrefixSpecial() . '_selected_ids', $session_name, '', true);
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $resulting_ids[0]);
return $resulting_ids;
@@ -1600,6 +1600,44 @@
return ;
}
+ // TODO: 2. optimize change log records (replace multiple changes to same record with one change record)
+
+ $to_increment = Array ();
+
+ // 3. collect serials to reset based on foreign keys
+ foreach ($changes as $index => $rec) {
+ if (array_key_exists('DependentFields', $rec)) {
+
+ foreach ($rec['DependentFields'] as $field_name => $field_value) {
+ // will be "ci|ItemResourceId:345"
+ $to_increment[] = $rec['Prefix'] . '|' . $field_name . ':' . $field_value;
+ }
+
+ unset($changes[$index]['DependentFields']);
+ }
+
+ unset($changes[$index]['ParentId'], $changes[$index]['ParentPrefix']);
+ }
+
+ // 4. collect serials to reset based on changed ids
+ foreach ($changes as $change) {
+ $to_increment[] = $change['MasterPrefix'] . '|' . $change['MasterId'];
+
+ if ($change['MasterPrefix'] != $change['Prefix']) {
+ $to_increment[] = $change['Prefix'] . '|' . $change['ItemId'];
+ }
+ }
+
+ // 5. reset serials collected before
+ $to_increment = array_unique($to_increment);
+ $this->Application->incrementCacheSerial($this->Prefix);
+
+ foreach ($to_increment as $to_increment_mixed) {
+ list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2);
+
+ $this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id);
+ }
+
// save changes to database
$sesion_log_id = $this->Application->RecallVar('_SessionLogId_');
@@ -1619,10 +1657,14 @@
$this->Conn->doInsert(array_merge($rec, $add_fields), $change_log_table);
}
+ $this->Application->incrementCacheSerial('change-log');
+
$sql = 'UPDATE ' . $this->Application->getUnitOption('session-log', 'TableName') . '
SET AffectedItems = AffectedItems + ' . count($changes) . '
WHERE SessionLogId = ' . $sesion_log_id;
$this->Conn->Query($sql);
+
+ $this->Application->incrementCacheSerial('session-log');
}
/**
Index: core/kernel/db/db_tag_processor.php
===================================================================
--- core/kernel/db/db_tag_processor.php (revision 13159)
+++ core/kernel/db/db_tag_processor.php (working copy)
@@ -526,11 +526,12 @@
$displayed = array();
$column_number = 1;
- $cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') && $this->Application->RewriteURLs();
+ $cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') &&
+ $this->Application->RewriteURLs() && !$this->Application->isCachingType(CACHING_TYPE_MEMORY);
+
$limit = isset($params['limit']) ? $params['limit'] : false;
- while (!$list->EOL() && (!$limit || $i<$limit))
- {
+ while (!$list->EOL() && (!$limit || $i<$limit)) {
$this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
$this->Application->SetVar( $this->Prefix.'_id', $list->GetDBField($id_field) );
$block_params['is_last'] = ($i == $list->SelectedCount - 1);
@@ -538,14 +539,18 @@
$block_params['not_last'] = !$block_params['is_last']; // for front-end
if ($cache_mod_rw) {
+ $serial_name = $this->Application->incrementCacheSerial($this->Prefix, $list->GetDBField($id_field), false);
+
if ($this->Prefix == 'c') {
// for listing subcategories in category
- $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('NamedParentPath'));
- $this->Application->setCache('category_tree', $list->GetDBField($id_field), $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight'));
+ $this->Application->setCache('filenames[%' . $serial_name . '%]' , $list->GetDBField('NamedParentPath'));
+ $this->Application->setCache('category_tree[%CIDSerial:' . $list->GetDBField($id_field) . '%]', $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight'));
} else {
// for listing items in category
- $this->Application->setCache('filenames', 'c_'.$list->GetDBField('CategoryId'), $list->GetDBField('CategoryFilename'));
- $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('Filename'));
+ $this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('Filename'));
+
+ $serial_name = $this->Application->incrementCacheSerial('c', $list->GetDBField('CategoryId'), false);
+ $this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('CategoryFilename'));
}
}
@@ -782,18 +787,23 @@
function AddCurrencySymbol($value, $iso)
{
- $currency =& $this->Application->recallObject('curr.-'.$iso, null, Array('skip_autoload' => true));
- if( !$currency->isLoaded() ) $currency->Load($iso, 'ISO');
+ $cache_key = 'iso_masks[%CurrSerial%]';
+ $iso_masks = $this->Application->getCache($cache_key);
- $symbol = $currency->GetDBField('Symbol');
- if (!$symbol) $symbol = $currency->GetDBField('ISO').' ';
- if ($currency->GetDBField('SymbolPosition') == 0) {
- $value = $symbol.$value;
+ if ($iso_masks === false) {
+ $this->Conn->nextQueryCachable = true;
+ $symbol_sql = 'IF(COALESCE(Symbol, "") = "", CONCAT(ISO, " "), Symbol)';
+
+ $sql = 'SELECT IF(SymbolPosition = 0, CONCAT(' . $symbol_sql . ', "%s"), CONCAT("%s", ' . $symbol_sql . ')), LOWER(ISO) AS ISO
+ FROM ' . $this->Application->getUnitOption('curr', 'TableName') . '
+ WHERE Status = ' . STATUS_ACTIVE;
+ $iso_masks = $this->Conn->GetCol($sql, 'ISO');
+ $this->Application->setCache($cache_key, $iso_masks);
}
- if ($currency->GetDBField('SymbolPosition') == 1) {
- $value = $value.$symbol;
- }
- return $value;
+
+ $iso = strtolower($iso);
+
+ return array_key_exists($iso, $iso_masks) ? sprintf($iso_masks[$iso], $value) : $value;
}
/**
@@ -2562,7 +2572,7 @@
if (!array_key_exists($check_field, $fields)) {
// field not found in real fields array -> it's 100% virtual then
- $fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields');
+ $fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields', Array ());
}
if (!array_key_exists($check_field, $fields)) {
Index: core/kernel/db/dbitem.php
===================================================================
--- core/kernel/db/dbitem.php (revision 13161)
+++ core/kernel/db/dbitem.php (working copy)
@@ -354,9 +354,10 @@
* @access public
* @param mixed $id item id of keys->values hash to load item by
* @param string $id_field_name Optional parameter to load item by given Id field
+ * @param bool $cachable cache this query result based on it's prefix serial
* @return bool True if item has been loaded, false otherwise
*/
- function Load($id, $id_field_name = null)
+ function Load($id, $id_field_name = null, $cachable = false)
{
if ( isset($id_field_name) ) {
$this->SetIDField($id_field_name); // set new IDField
@@ -385,8 +386,25 @@
}
$q = $this->GetSelectSQL() . ' WHERE ' . $keys_sql;
- $field_values = $this->Conn->GetRow($q);
+ if ($cachable && $this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $serial_name = $this->Application->incrementCacheSerial($this->Prefix == 'st' ? 'c' : $this->Prefix, isset($id_field_name) ? null : $id, false);
+ $cache_key = 'kDBItem::Load_' . crc32(serialize($id) . '-' . $this->IDField) . '[%' . $serial_name . '%]';
+ $field_values = $this->Application->getCache($cache_key, false);
+
+ if ($field_values === false) {
+ $field_values = $this->Conn->GetRow($q);
+
+ if ($field_values !== false) {
+ // only cache, when data was retrieved
+ $this->Application->setCache($cache_key, $field_values);
+ }
+ }
+ }
+ else {
+ $field_values = $this->Conn->GetRow($q);
+ }
+
if ($field_values) {
$this->FieldValues = array_merge_recursive2($this->FieldValues, $field_values);
$this->OriginalFieldValues = $this->FieldValues;
@@ -1082,8 +1100,22 @@
}
if (in_array($this->Prefix, $rec['ParentPrefix']) && $rec['ParentId'][$this->Prefix] == $this->GetID()) {
- // change log record of given item's sub item
+ // change log record of given item's sub item -> update changed id's in dependent fields
$changes[$key]['ParentId'][$this->Prefix] = $new_id;
+
+ if (array_key_exists('DependentFields', $rec)) {
+ // these are fields from table of $rec['Prefix'] table!
+ // when one of dependent fields goes into idfield of it's parent item, that was changed
+ $parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey');
+ $parent_table_key = is_array($parent_table_key) ? $parent_table_key[$this->Prefix] : $parent_table_key;
+
+ if ($parent_table_key == $this->IDField) {
+ $foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey');
+ $foreign_key = is_array($foreign_key) ? $foreign_key[$this->Prefix] : $foreign_key;
+
+ $changes[$key]['DependentFields'][$foreign_key] = $new_id;
+ }
+ }
}
}
}
@@ -1162,19 +1194,24 @@
// sub item
// collect foreign key values (for serial reset)
$foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey');
- $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array ();
+ $dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array ();
if (is_array($foreign_keys)) {
foreach ($foreign_keys as $prefix => $field_name) {
+ $dependent_fields[$field_name] = $this->GetDBField($field_name);
$fields_hash['ParentPrefix'][] = $prefix;
$fields_hash['ParentId'][$prefix] = $this->getParentId($prefix);
}
}
else {
+ $dependent_fields[$foreign_keys] = $this->GetDBField($foreign_keys);
$fields_hash['ParentPrefix'] = Array ( $this->Application->getUnitOption($this->Prefix, 'ParentPrefix') );
$fields_hash['ParentId'][ $fields_hash['ParentPrefix'][0] ] = $this->getParentId('auto');
}
+ $fields_hash['DependentFields'] = $dependent_fields;
+
+
// works only, when main item is present in url, when subitem is changed
$master_id = $this->Application->GetVar($main_prefix . '_id');
Index: core/kernel/db/dblist.php
===================================================================
--- core/kernel/db/dblist.php (revision 13159)
+++ core/kernel/db/dblist.php (working copy)
@@ -375,7 +375,7 @@
if (!$this->Records && ($this->Page > 1)) {
// no records & page > 1, try to reset to 1st page (works only when list in not counted before)
- $this->Application->StoreVar($this->getPrefixSpecial().'_Page', 1);
+ $this->Application->StoreVar($this->getPrefixSpecial() . '_Page', 1, true);
$this->SetPage(1);
$this->Query($force);
}
Index: core/kernel/kbase.php
===================================================================
--- core/kernel/kbase.php (revision 13152)
+++ core/kernel/kbase.php (working copy)
@@ -650,8 +650,23 @@
$select_clause = $this->escapeField($field_options['option_title_field']) . ',' . $this->escapeField($field_options['option_key_field']);
$sql = sprintf($field_options['options_sql'], $select_clause);
- $dynamic_options = $this->Conn->GetCol($sql, preg_replace('/^.*?\./', '', $field_options['option_key_field']));
+ if (array_key_exists('serial_name', $field_options)) {
+ // try to cache option sql on serial basis
+ $cache_key = 'sql_' . crc32($sql) . '[%' . $field_options['serial_name'] . '%]';
+ $dynamic_options = $this->Application->getCache($cache_key);
+
+ if ($dynamic_options === false) {
+ $this->Conn->nextQueryCachable = true;
+ $dynamic_options = $this->Conn->GetCol($sql, preg_replace('/^.*?\./', '', $field_options['option_key_field']));
+ $this->Application->setCache($cache_key, $dynamic_options);
+ }
+ }
+ else {
+ // don't cache options sql
+ $dynamic_options = $this->Conn->GetCol($sql, preg_replace('/^.*?\./', '', $field_options['option_key_field']));
+ }
+
$options_hash = array_key_exists('options', $field_options) ? $field_options['options'] : Array ();
$field_options['options'] = array_merge_recursive2($options_hash, $dynamic_options);
}
Index: core/kernel/nparser/nparser.php
===================================================================
--- core/kernel/nparser/nparser.php (revision 13152)
+++ core/kernel/nparser/nparser.php (working copy)
@@ -21,7 +21,7 @@
class NParser extends kBase {
- var $Stack = array();
+ var $Stack = Array ();
var $Level = 0;
var $Buffers = array();
@@ -40,7 +40,12 @@
var $Definitions = '';
- var $Elements = array(); // holds dynamic elements to function names mapping during execution
+ /**
+ * Holds dynamic elements to function names mapping during execution
+ *
+ * @var Array
+ */
+ var $Elements = Array ();
/**
* Holds location of element definitions inside templates.
@@ -55,10 +60,31 @@
var $TemplateName = null;
var $TempalteFullPath = null;
- var $CachePointers = array();
- var $Cachable = array();
+ var $CachePointers = Array ();
+ var $Cachable = Array ();
/**
+ * Caching in templates enabled
+ *
+ * @var bool
+ */
+ var $CachingEnabled = false;
+
+ /**
+ * Completely cache given page
+ *
+ * @var bool
+ */
+ var $FullCachePage = false;
+
+ /**
+ * Prefixes, that are used on current page
+ *
+ * @var Array
+ */
+ var $PrefixesInUse = Array ();
+
+ /**
* Parser parameter names, that are created via m_Capture tag are listed here
*
* @var Array
@@ -72,6 +98,20 @@
*/
var $_btnPhrases = Array ();
+ /**
+ * Mod-rewrite system enabled
+ *
+ * @var bool
+ */
+ var $RewriteUrls = false;
+
+ /**
+ * Current user is logged-in
+ *
+ * @var bool
+ */
+ var $UserLoggedIn = false;
+
function NParser()
{
parent::kBase();
@@ -80,6 +120,12 @@
$this->_btnPhrases['design'] = $this->Application->Phrase('la_btn_EditDesign', false, true);
$this->_btnPhrases['block'] = $this->Application->Phrase('la_btn_EditBlock', false, true);
}
+
+ $this->RewriteUrls = $this->Application->RewriteURLs();
+ $this->UserLoggedIn = $this->Application->LoggedIn();
+
+ // cache only Front-End templated, when memory caching is available and template caching is enabled in configuration
+ $this->CachingEnabled = !$this->Application->isAdmin && $this->Application->ConfigValue('SystemTagCache') && $this->Application->isCachingType(CACHING_TYPE_MEMORY);
}
function Compile($pre_parsed, $template_name = 'unknown')
@@ -383,7 +429,13 @@
$this->TemplateName = $t;
$this->TempalteFullPath = $pre_parsed['tname'];
- $output =& $this->Application->TemplatesCache->runTemplate($this, $pre_parsed);
+ if (!isset($backup_template) && $this->CachingEnabled && !$this->UserLoggedIn && !EDITING_MODE) {
+ // this is main page template -> check for page-based aggressive caching settings
+ $output =& $this->RunMainPage($pre_parsed);
+ }
+ else {
+ $output =& $this->Application->TemplatesCache->runTemplate($this, $pre_parsed);
+ }
$this->TemplateName = $backup_template;
$this->TempalteFullPath = $backup_fullpath;
@@ -391,6 +443,112 @@
return $output;
}
+ function &RunMainPage($pre_parsed)
+ {
+ $page =& $this->Application->recallObject('st.-virtual');
+ /* @var $page kDBItem */
+
+ if ($page->isLoaded()) {
+ // page found in database
+ $debug_mode = $this->Application->isDebugMode(); // don't cache debug output
+ $template_path = preg_replace('/^' . preg_quote(FULL_PATH, '/') . '/', '', $this->TempalteFullPath, 1);
+ $element = ($debug_mode ? 'DEBUG_MODE:' : '') . 'file=' . $template_path;
+ $this->FullCachePage = $page->GetDBField('EnablePageCache');
+
+ if ($this->FullCachePage && $page->GetDBField('PageCacheKey')) {
+ // page caching enabled -> try to get from cache
+ $cache_key = $this->FormCacheKey($element, $page->GetDBField('PageCacheKey'));
+ $output = $this->getCache($cache_key);
+
+ if ($output !== false) {
+ return $output;
+ }
+ }
+
+ // page not cached OR cache expired
+ $output =& $this->Application->TemplatesCache->runTemplate($this, $pre_parsed);
+ $this->generatePageCacheKey($page);
+
+ if ($this->FullCachePage && $page->GetDBField('PageCacheKey')) {
+ $cache_key = $this->FormCacheKey($element, $page->GetDBField('PageCacheKey'));
+ $this->setCache($cache_key, $output, (int)$page->GetDBField('PageExpiration'));
+ }
+ }
+ else {
+ // page not found in database
+ $output =& $this->Application->TemplatesCache->runTemplate($this, $pre_parsed);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Generate page caching key based on prefixes used on it + prefix IDs passed in url
+ *
+ * @param kDBItem $page
+ */
+ function generatePageCacheKey(&$page)
+ {
+ if (!$page->isLoaded() || $page->GetDBField('OverridePageCacheKey')) {
+ return ;
+ }
+
+ $page_cache_key = Array ();
+ // nobody resets "m" prefix serial, don't count no user too
+ unset($this->PrefixesInUse['m'], $this->PrefixesInUse['u']);
+
+ if (array_key_exists('st', $this->PrefixesInUse)) {
+ // prefix "st" serial will never be changed
+ unset($this->PrefixesInUse['st']);
+ $this->PrefixesInUse['c'] = 1;
+ }
+
+ $prefix_ids = Array ();
+ $prefixes = array_keys($this->PrefixesInUse);
+ asort($prefixes);
+
+ foreach ($prefixes as $index => $prefix) {
+ $id = $this->Application->GetVar($prefix . '_id');
+
+ if (is_numeric($id)) {
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Found: "' . $prefix . '_id" = ' . $id . ' during PageCacheKey forming.');
+ }
+
+ $prefix_ids[] = $prefix;
+ unset($prefixes[$index]);
+ }
+ }
+
+ if ($prefix_ids) {
+ $page_cache_key[] = 'prefix_id:' . implode(',', $prefix_ids);
+ }
+
+ if ($prefixes) {
+ $page_cache_key[] = 'prefix:' . implode(',', $prefixes);
+ }
+
+ $page_cache_key = implode(';', $page_cache_key);
+
+ if ($page_cache_key != $page->GetOriginalField('PageCacheKey')) {
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Canging PageCacheKey from "<strong>' . $page->GetOriginalField('PageCacheKey') . '</strong>" to "<strong>' . $page_cache_key . '</strong>".');
+ }
+
+ $page->SetDBField('PageCacheKey', $page_cache_key);
+
+ // don't use kDBItem::Update(), because it will change ModifiedById to current front-end user
+ $sql = 'UPDATE ' . $page->TableName . '
+ SET PageCacheKey = ' . $page->Conn->qstr($page_cache_key) . '
+ WHERE ' . $page->IDField . ' = ' . $page->GetID();
+ $page->Conn->Query($sql);
+
+ // increment serial, because we issue direct sql above!
+ $this->Application->incrementCacheSerial('c');
+ $this->Application->incrementCacheSerial('c', $page->GetID());
+ }
+ }
+
function &GetProcessor($prefix)
{
static $Processors = array();
@@ -443,8 +601,12 @@
function ParseBlock($params, $pass_params=false)
{
- if (isset($params['cache_timeout']) && ($ret = $this->CacheGet($this->FormCacheKey('element_'.$params['name'])))) {
- return $ret;
+ if (array_key_exists('cache_timeout', $params) && $params['cache_timeout']) {
+ $ret = $this->getCache( $this->FormCacheKey('element_' . $params['name']) );
+
+ if ($ret) {
+ return $ret;
+ }
}
if (substr($params['name'], 0, 5) == 'html:') {
@@ -517,8 +679,9 @@
$this->DataExists = $data_exists_bak || $this->DataExists;
- if (isset($original_params['cache_timeout'])) {
- $this->CacheSet($this->FormCacheKey('element_'.$original_params['name']), $ret, $original_params['cache_timeout']);
+ if (array_key_exists('cache_timeout', $original_params) && $original_params['cache_timeout']) {
+ $cache_key = $this->FormCacheKey('element_' . $original_params['name']);
+ $this->setCache($cache_key, $ret, (int)$original_params['cache_timeout']);
}
if (array_key_exists('no_editing', $block_params) && $block_params['no_editing']) {
@@ -563,9 +726,9 @@
if (!$decorate) {
return $block_content;
}
- else {
- $block_content = /*$prepend .*/ $block_content;
- }
+ /*else {
+ $block_content = $prepend . $block_content;
+ }*/
$block_name = $block_params['name'];
$function_name = $is_template ? $block_name : $this->Elements[$block_name];
@@ -629,9 +792,15 @@
function IncludeTemplate($params, $silent=null)
{
$t = is_array($params) ? $this->SelectParam($params, 't,template,block,name') : $params;
+ $cache_timeout = array_key_exists('cache_timeout', $params) ? $params['cache_timeout'] : false;
- if (isset($params['cache_timeout']) && ($ret = $this->CacheGet('template:'.$t))) {
- return $ret;
+ if ($cache_timeout) {
+ $cache_key = $this->FormCacheKey('template:' . $t);
+ $ret = $this->getCache($cache_key);
+
+ if ($ret !== false) {
+ return $ret;
+ }
}
$t = preg_replace('/\.tpl$/', '', $t);
@@ -654,8 +823,8 @@
$this->CheckNoData($ret, $params);
$this->DataExists = $data_exists_bak || $this->DataExists;
- if (isset($params['cache_timeout'])) {
- $this->CacheSet('template:'.$t, $ret, $params['cache_timeout']);
+ if ($cache_timeout) {
+ $this->setCache($cache_key, $ret, (int)$cache_timeout);
}
return $ret;
@@ -674,53 +843,216 @@
}
}
- function CacheGet($name)
+ function getCache($name)
{
- if (!$this->Application->ConfigValue('SystemTagCache')) return false;
- return $this->Application->CacheGet($name);
+ if (!$this->CachingEnabled) {
+ return false;
+ }
+
+ $ret = $this->Application->getCache($name, false);
+
+ if (preg_match('/^\[DE_MARK:(.*?)\]$/', substr($ret, -11), $regs)) {
+ $this->DataExists = $regs[1] ? true : false;
+ $ret = substr($ret, 0, -11);
+ }
+
+ return $ret;
}
- function CacheSet($name, $value, $expiration=0)
+ function setCache($name, $value, $expiration = 0)
{
- if (!$this->Application->ConfigValue('SystemTagCache')) return false;
- return $this->Application->CacheSet($name, $value, $expiration);
+ if (!$this->CachingEnabled) {
+ return false;
+ }
+
+ // remeber DataExists in cache, because after cache will be restored
+ // it will not be available naturally (no tags, that set it will be called)
+ $value .= '[DE_MARK:' . (int)$this->DataExists . ']';
+
+ return $this->Application->setCache($name, $value, $expiration);
}
- function FormCacheKey($element, $file=null, $add_prefixes=null)
+ function FormCacheKey($element, $key_string = '')
{
- if (!isset($file)) {
- $file = str_replace(FULL_PATH, '', $this->TempalteFullPath).':'.$this->Application->GetVar('t');
+ if (strpos($key_string, 'guest_only') !== false && $this->UserLoggedIn) {
+ // don't cache, when user is logged-in "guest_only" is specified in key
+ return '';
}
- $parts = array(
- 'file_'.$file.'('.filemtime($this->TempalteFullPath).')' => 'serials:file_ts', // theme + template timestamp
- 'm_lang_'.$this->Application->GetVar('m_lang') => 'serials:lang_ts',
- 'm_cat_id_'.$this->Application->GetVar('m_cat_id') => 'serials:cat_'.$this->Application->GetVar('m_cat_id').'_ts',
- 'm_cat_page'.$this->Application->GetVar('m_cat_page') => false,
- );
- if (isset($add_prefixes)) {
- foreach ($add_prefixes as $prefix) {
- $parts[$prefix.'_id_'.$this->Application->GetVar("{$prefix}_id")] = "serials:$prefix_".$this->Application->GetVar("{$prefix}_id").'_ts';
- $parts[$prefix.'_page_'.$this->Application->GetVar("{$prefix}_Page")] = false;
+
+ $parts = Array ();
+
+ // 1. replace INLINE variable (from request) into key parts
+ if (preg_match_all('/\(%(.*?)\)/', $key_string, $regs)) {
+ // parts in form "(%variable_name)" were found
+ foreach ($regs[1] as $variable_name) {
+ $variable_value = $this->Application->GetVar($variable_name);
+ $key_string = str_replace('(%' . $variable_name . ')', $variable_value, $key_string);
}
}
- $key = '';
- foreach ($parts as $part => $ts_name) {
- if ($ts_name) {
- $ts = $this->Application->CacheGet($ts_name);
- $key .= "$part($ts):";
+
+ // 2. replace INLINE serial numbers (they may not be related to any prefix at all)
+ // Serial number also could be composed of inline variables!
+ if (preg_match_all('/\[%(.*?)%\]/', $key_string, $regs)) {
+ // format "[%LangSerial%]" - prefix-wide serial in case of any change in "lang" prefix
+ // format "[%LangIDSerial:5%]" - one id-wide serial in case of data, associated with given id was changed
+ // format "[%CiIDSerial:ItemResourceId:5%]" - foreign key-based serial in case of data, associated with given foreign key was changed
+ foreach ($regs[1] as $serial_name) {
+ $serial_value = $this->Application->getCache('[%' . $serial_name . '%]');
+ $key_string = str_replace('[%' . $serial_name . '%]', '[%' . $serial_name . '=' . $serial_value . '%]', $key_string);
}
+ }
+
+ /*
+ Always add:
+ ===========
+ * "var:m_lang" - show content on current language
+ * "var:t" - template from url, used to differ multiple pages using same physical template (like as design)
+ * "var:admin,editing_mode" - differ cached content when different editing modes are used
+ * "var:m_cat_id,m_cat_page" - pass current category
+ * "var:page,per_page,sort_by" - list pagination/sorting parameters
+ * "prefix:theme-file" - to be able to reset all cached templated using "Rebuild Theme Files" function
+ * "prefix:phrases" - use latest phrase translations
+ * "prefix:conf" - output could slighly differ based on configuration settings
+ */
+ $key_string = rtrim('var:m_lang,t,admin,editing_mode,m_cat_id,m_cat_page,page,per_page,sort_by;prefix:theme-file,phrases,conf;' . $key_string, ';');
+
+ $keys = explode(';', $key_string);
+
+ /*
+ Possible parts of a $key_string (all can have multiple occurencies):
+ ====================================================================
+ * prefix:<prefixA>[,<prefixB>,<prefixC>] - include global serial for given prefix(-es)
+ * skip_prefix:<prefix1>[,<prefix2>,<prefix3>] - exclude global serial for given prefix(-es)
+ * prefix_id:<prefixA>[,<prefixB>,<prefixC>] - include id-based serial for given prefix(-es)
+ * skip_prefix_id:<prefix1>[,<prefix2>,<prefix3>] - exclude id-based serial for given prefix(-es)
+ * var:<aaa>[,<bbb>,<ccc>] - include request variable value(-s)
+ * skip_var:<varA>[,<varB>,<varC>] - exclude request variable value(-s)
+ * (%variable_name) - include request variable value (only value without variable name ifself, like in "var:variable_name")
+ * [%SerialName%] - use to retrieve serial value in free form
+ */
+
+ // 3. get variable names, prefixes and prefix ids, that should be skipped
+ $skip_prefixes = $skip_prefix_ids = $skip_variables = Array ();
+
+ foreach ($keys as $index => $key) {
+ if (preg_match('/^(skip_var|skip_prefix|skip_prefix_id):(.*?)$/i', $key, $regs)) {
+ unset($keys[$index]);
+ $tmp_parts = explode(',', $regs[2]);
+
+ switch ($regs[1]) {
+ case 'skip_var':
+ $skip_variables = array_merge($skip_variables, $tmp_parts);
+ break;
+
+ case 'skip_prefix':
+ $skip_prefixes = array_merge($skip_prefixes, $tmp_parts);
+ break;
+
+ case 'skip_prefix_id':
+ $skip_prefix_ids = array_merge($skip_prefix_ids, $tmp_parts);
+ break;
+ }
+ }
+ }
+
+ $skip_prefixes = array_unique($skip_prefixes);
+ $skip_variables = array_unique($skip_variables);
+ $skip_prefix_ids = array_unique($skip_prefix_ids);
+
+ // 4. process keys
+ foreach ($keys as $key) {
+ if (preg_match('/^(var|prefix|prefix_id):(.*?)$/i', $key, $regs)) {
+ $tmp_parts = explode(',', $regs[2]);
+
+ switch ($regs[1]) {
+ case 'var':
+ // format: "var:country_id" will become "country_id=<country_id>"
+ $tmp_parts = array_diff($tmp_parts, $skip_variables);
+
+ foreach ($tmp_parts as $variable_name) {
+ $variable_value = $this->Application->GetVar($variable_name);
+
+ if ($variable_value !== false) {
+ $parts[] = $variable_name . '=' . $variable_value;
+ }
+ }
+ break;
+
+ case 'prefix':
+ // format: "prefix:country" will become "[%CountrySerial%]"
+ $tmp_parts = array_diff($tmp_parts, $skip_prefixes);
+
+ foreach ($tmp_parts as $prefix) {
+ $serial_name = $this->Application->incrementCacheSerial($prefix, null, false);
+ $parts[] = '[%' . $serial_name . '=' . $this->Application->getCache($serial_name) . '%]';
+
+ if (!$this->RewriteUrls) {
+ // add env-style page and per-page variable, when mod-rewrite is off
+ $prefix_variables = Array ($prefix . '_Page', $prefix . '_PerPage');
+ foreach ($prefix_variables as $variable_name) {
+ $variable_value = $this->Application->GetVar($variable_name);
+
+ if ($variable_value !== false) {
+ $parts[] = $variable_name . '=' . $variable_value;
+ }
+ }
+ }
+ }
+ break;
+
+ case 'prefix_id':
+ // format: "id:country" will become "[%CountryIDSerial:5%]"
+ $tmp_parts = array_diff($tmp_parts, $skip_prefix_ids);
+
+ foreach ($tmp_parts as $prefix_id) {
+ $id = $this->Application->GetVar($prefix_id . '_id');
+
+ if ($id !== false) {
+ $serial_name = $this->Application->incrementCacheSerial($prefix_id, $id, false);
+ $parts[] = '[%' . $serial_name . '=' . $this->Application->getCache($serial_name) . '%]';
+ }
+ }
+ break;
+ }
+ }
+ elseif ($key == 'currency') {
+ // based on current currency
+ $parts[] = 'curr_iso=' . $this->Application->RecallVar('curr_iso');
+ }
+ elseif ($key == 'groups') {
+ // based on logged-in user groups
+ $parts[] = 'groups=' . $this->Application->RecallVar('UserGroups');
+ }
+ elseif ($key == 'guest_only') {
+ // we know this key, but process it at method beginning
+ }
else {
- $key .= "$part:";
+ if ($this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendTrace();
+ }
+
+ trigger_error('Unknown key part "<strong>' . $key . '</strong>" used in "<strong>key</strong>" parameter of <inp2:m_Cache key="..."/> tag.', E_USER_ERROR);
}
}
- $key .= $element;
- return crc32($key);
+ // 5. add unique given cache key identifier on this page
+ $parts[] = $element;
+
+ $key = implode(':', $parts);
+
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Parser Key: ' . $key);
+ }
+
+ return 'parser_' . crc32($key);
}
- function PushPointer($pointer)
+ function PushPointer($pointer, $key)
{
- $this->CachePointers[++$this->CacheLevel] = $this->FormCacheKey('pointer:'.$pointer);
+ $cache_key = $this->FullCachePage || !$this->CachingEnabled ? '' : $this->FormCacheKey('pointer:' . $pointer, $key);
+
+ $this->CachePointers[++$this->CacheLevel] = $cache_key;
+
return $this->CachePointers[$this->CacheLevel];
}
@@ -729,21 +1061,45 @@
return $this->CachePointers[$this->CacheLevel--];
}
- function CacheStart($pointer=null)
+ function CacheStart($pointer, $key)
{
- if ($ret = $this->CacheGet($this->PushPointer($pointer)) ) {
- echo $ret;
- $this->PopPointer();
- return true;
+ $pointer = $this->PushPointer($pointer, $key);
+
+ if ($pointer) {
+ $ret = $this->getCache($pointer);
+
+ $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode();
+
+ if ($ret !== false) {
+ echo $debug_mode ? '<!-- CACHED OUTPUT START -->' . $ret . '<!-- /CACHED OUTPUT END -->' : $ret;
+ $this->PopPointer();
+
+ return true;
+ }
+
+ if ($debug_mode) {
+ echo '<!-- NO CACHE FOR POINTER: ' . $pointer . ' -->';
+ }
}
+
ob_start();
+
return false;
}
- function CacheEnd($elem=null)
+ function CacheEnd($expiration = 0)
{
$ret = ob_get_clean();
- $this->CacheSet($this->PopPointer(), $ret); // . ($this->CurrentKeyPart ? ':'.$this->CurrentKeyPart : '')
+ $pointer = $this->PopPointer();
+
+ if ($pointer) {
+ $res = $this->setCache($pointer, $ret, $expiration);
+
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
+ echo '<!-- STORING CACHE FOR POINTER: ' . $pointer . ' [' . $res . '] -->';
+ }
+ }
+
echo $ret;
}
}
\ No newline at end of file
Index: core/kernel/nparser/ntags.php
===================================================================
--- core/kernel/nparser/ntags.php (revision 13152)
+++ core/kernel/nparser/ntags.php (working copy)
@@ -404,14 +404,14 @@
$code[] = '$_tag_params = ' . $to_pass . ';';
$code[] = "\${$tag['NP']['name']} = \$_p_->PostProcess(\${$tag['NP']['name']}, \$_p_->PreparePostProcess(\$_tag_params));";
$code[] = "}";
-
+
if (array_key_exists('result_to_var', $tag['NP']) && $tag['NP']['result_to_var']) {
$code[] = "\$params['{$tag['NP']['result_to_var']}'] = \$_parser->GetParam('{$tag['NP']['result_to_var']}');";
-
+
if (array_key_exists('plus', $tag['NP'])) {
$code[] = "\$params['{$tag['NP']['result_to_var']}'] += {$tag['NP']['plus']};";
}
-
+
$code[] = "\${$tag['NP']['result_to_var']} = \$params['{$tag['NP']['result_to_var']}'];";
}
elseif (array_key_exists('plus', $tag['NP'])) {
@@ -573,16 +573,20 @@
function Open($tag)
{
+ $o = '';
$pointer = abs(crc32($tag['file'])).'_'.$tag['line'];
- $o = '';
- $this->AppendCode($o, "if (!\$_parser->CacheStart('{$pointer}')) {\n");
+ $key = array_key_exists('key', $tag['NP']) ? $tag['NP']['key'] : '';
+ $this->AppendCode($o, "if (!\$_parser->CacheStart('{$pointer}', \"{$key}\")) {\n");
+
return $o;
}
function Close($tag)
{
$o = $this->Parser->Buffers[$this->Parser->Level];
- $this->AppendCode($o, "\$_parser->CacheEnd();\n}\n");
+ $cache_timeout = array_key_exists('cache_timeout', $this->Tag['NP']) ? $this->Tag['NP']['cache_timeout'] : 0;
+ $this->AppendCode($o, "\$_parser->CacheEnd(" . (int)$cache_timeout . ");\n}\n");
+
return $o;
}
Index: core/kernel/processors/tag_processor.php
===================================================================
--- core/kernel/processors/tag_processor.php (revision 13152)
+++ core/kernel/processors/tag_processor.php (working copy)
@@ -49,18 +49,12 @@
function FormCacheKey($tag, $params, $prefix)
{
- $k = $this->Application->Parser->TemplateName;
- $k .= $prefix.'_'.$tag;
- foreach (array('m_cat_id','m_cat_page','m_lang','m_theme') as $m_var) {
- $params[$m_var] = $this->Application->GetVar($m_var);
- }
+ // link tag to it's template
+ $reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
+ $template_path = preg_replace($reg_exp, '', $this->Application->Parser->TempalteFullPath, 1);
+ $element = 'file=' . $template_path . ':' . $prefix . '_' . $tag . '_' . crc32( serialize($params) );
- ksort($params);
- foreach ($params as $p => $v) {
- $k .= "$p=$v&";
- }
-
- return md5($k);
+ return $this->Application->Parser->FormCacheKey($element);
}
function ProcessParsedTag($tag, $params, $prefix, $file='unknown', $line=0)
@@ -71,11 +65,18 @@
$this->Application->Debugger->appendHTML('Processing PreParsed Tag '.$Method.' in '.$this->Prefix);
}
+ list ($prefix_only, ) = explode('.', $prefix);
+ $this->Application->Parser->PrefixesInUse[$prefix_only] = 1;
+
$backup_prefix = $this->Prefix;
$backup_special = $this->Special;
- if ($this->Application->ConfigValue('SystemTagCache') && isset($params['cache_timeout'])) {
- if ($res = $this->Application->CacheGet($this->FormCacheKey($tag, $params, $prefix))) {
+ if ($this->Application->Parser->CachingEnabled && array_key_exists('cache_timeout', $params)) {
+ // individual tag caching
+ $cache_key = $this->FormCacheKey($tag, $params, $prefix);
+ $res = $this->Application->Parser->getCache($cache_key);
+
+ if ($res !== false) {
return $res;
}
}
@@ -94,9 +95,11 @@
$this->Special = $backup_special;
$ret = $this->PostProcess($ret, $flag_values);
- if ($this->Application->ConfigValue('SystemTagCache') && $flag_values['cache_timeout'] && isset($this->Application->Memcached)) {
- $this->Application->CacheSet($this->FormCacheKey($tag, $original_params, $prefix), $ret, $flag_values['cache_timeout']);
+
+ if ($this->Application->Parser->CachingEnabled && $flag_values['cache_timeout']) {
+ $this->Application->Parser->setCache($cache_key, $ret, (int)$flag_values['cache_timeout']);
}
+
return $ret;
}
else {
Index: core/kernel/startup.php
===================================================================
--- core/kernel/startup.php (revision 13152)
+++ core/kernel/startup.php (working copy)
@@ -103,6 +103,11 @@
safeDefine('EDITOR_PATH', isset($vars['EditorPath']) ? $vars['EditorPath'] : '/core/editor/');
+ // caching types
+ define('CACHING_TYPE_NONE', 0);
+ define('CACHING_TYPE_MEMORY', 1);
+ define('CACHING_TYPE_TEMPORARY', 2);
+
if (ini_get('safe_mode')) {
// safe mode will be removed at all in PHP6
define('SAFE_MODE', 1);
Index: core/kernel/utility/cache.php
===================================================================
--- core/kernel/utility/cache.php (revision 13152)
+++ core/kernel/utility/cache.php (working copy)
@@ -23,22 +23,29 @@
*/
var $_storage = null;
+ /**
+ * Cache usage statistics (per script run)
+ *
+ * @var Array
+ */
var $statistics = Array ();
+
+ /**
+ * Debug cache usage
+ *
+ * @var bool
+ */
var $debugCache = false;
- function kCache() {
+ function kCache()
+ {
parent::kBase();
- $this->debugCache = $this->Application->isDebugMode() && constOn('DBG_CACHE');
+ $this->debugCache = defined('DBG_CACHE') && DBG_CACHE && $this->Application->isDebugMode();
- $memcached_servers = false; // 'localhost:11211'; // $this->Application->ConfigValue('MemcachedServers');
-
- if ($memcached_servers && class_exists('Memcache')) {
- $this->_storage = new MemcacheCacheStorage($memcached_servers);
+ if (class_exists('Memcache')) {
+ $this->_storage = new MemcacheCacheStorage();
}
- /*else if (false || $this->Application->ConfigValue('UseFileCache')) {
- $this->_storage = new FileCacheStorage('file_cache.tmp');
- }*/
else {
$this->_storage = new CacheStorage();
}
@@ -50,58 +57,90 @@
}
/**
- * Adds new value to cache $cache_name and identified by key $key
+ * Adds new value to cache $cache_name and identified by key $name
*
- * @param string $cache_name cache name
- * @param int $key key name to add to cache
+ * @param int $name key name to add to cache
* @param mixed $value value of chached record
+ * @param int $expires expiration
*/
- function setCache($cache_name, $key, $value, $expires = 3600)
+ function setCache($name, $value, $expires = 0)
{
- return $this->_storage->set($cache_name, $key, $value, $expires);
+ return $this->_storage->set($name, $value, $expires);
}
+ function reset()
+ {
+ return $this->_storage->reset();
+ }
+
/**
- * Returns cached $key value from cache named $cache_name
+ * Returns cached $name value from cache named $cache_name
*
- * @param string $cache_name cache name
- * @param int $key key name from cache
+ * @param int $name key name from cache
+ * @param bool $store_locally store data locally after retrieved
* @return mixed
*/
- function getCache($cache_name, $key)
+ function getCache($name, $store_locally = true)
{
- $ret = $this->_storage->get($cache_name, $key);
+ $ret = $this->_storage->get($name, $store_locally);
- $this->setStatistics($cache_name, $key, $ret);
+ if ($this->debugCache && $store_locally) {
+ $this->setStatistics($name, $ret);
+ }
return $ret;
}
- function setStatistics($cache_name, $key, $found)
+ /**
+ * Deletes cached $name value from cache named $cache_name
+ *
+ * @param int $name key name from cache
+ * @return mixed
+ */
+ function delete($name)
{
- if (!$this->debugCache) {
- return true;
+ $this->_storage->delete($name);
+ }
+
+ /**
+ * Returns caching type of current storage engine
+ *
+ * @return int
+ */
+ function getCachingType()
+ {
+ return $this->_storage->cachingType;
+ }
+
+ function setStatistics($name, $found)
+ {
+ if (strpos($name, ']:') !== false) {
+ list ($cache_name, $name) = explode(']:', $name, 2);
}
+ else {
+ $cache_name = '-';
+ }
if (!array_key_exists($cache_name, $this->statistics)) {
$this->statistics[$cache_name] = Array ();
}
- if (!array_key_exists($key, $this->statistics[$cache_name])) {
- $this->statistics[$cache_name][$key] = Array ();
+ if (!array_key_exists($name, $this->statistics[$cache_name])) {
+ $this->statistics[$cache_name][$name] = Array ();
}
$status_key = $found ? 'found' : 'not_found';
- if (!isset($this->statistics[$cache_name][$key][$status_key])) {
- $this->statistics[$cache_name][$key][$status_key] = 0;
+
+ if (!isset($this->statistics[$cache_name][$name][$status_key])) {
+ $this->statistics[$cache_name][$name][$status_key] = 0;
}
- $this->statistics[$cache_name][$key][$status_key]++;
+ $this->statistics[$cache_name][$name][$status_key]++;
}
function printStatistics()
{
- $cache_size = strlen(serialize($this->_storage));
+ $cache_size = $this->_storage->getStorageSize();
$this->Application->Debugger->appendHTML('<strong>Cache Size:</strong> ' . formatSize($cache_size) . ' (' . $cache_size . ')');
@@ -120,7 +159,19 @@
class CacheStorage extends Params {
+ var $cachingType = CACHING_TYPE_TEMPORARY;
+
/**
+ * Returns storage size in bytes
+ *
+ * @return int
+ */
+ function getStorageSize()
+ {
+ return strlen( serialize($this->_Params) );
+ }
+
+ /**
* Determines, that cache storage is working fine
*
* @return bool
@@ -130,18 +181,31 @@
return true;
}
+ function _getKeyInfo($name)
+ {
+ if (strpos($name, ':') !== false) {
+ list ($cache_name, $name) = explode(':', $name, 2);
+ }
+ else {
+ $cache_name = '-';
+ }
+
+ return Array ($cache_name, $name);
+ }
+
/**
* Stores value to cache
*
- * @param string $cache_name
- * @param string $key
+ * @param string $name
* @param mixed $value
* @param int $expires cache record expiration time in seconds
*/
- function set($cache_name, $key, $value, $expires)
+ function set($name, $value, $expires)
{
+ list ($cache_name, $name) = $this->_getKeyInfo($name);
+
$cache = parent::Get($cache_name, Array());
- $cache[$key] = $value;
+ $cache[$name] = $value;
parent::Set($cache_name, $cache);
}
@@ -149,141 +213,260 @@
/**
* Returns value from cache
*
- * @param string $cache_name
- * @param string $key
+ * @param string $name
+ * @param bool $store_locally store data locally after retrieved
* @return mixed
*/
- function get($cache_name, $key)
+ function get($name, $store_locally = false)
{
+ list ($cache_name, $name) = $this->_getKeyInfo($name);
+
$cache = parent::Get($cache_name, Array());
- $ret = array_key_exists($key, $cache) ? $cache[$key] : false;
+ $ret = array_key_exists($name, $cache) ? $cache[$name] : false;
return $ret;
}
+
+ /**
+ * Deletes value from cache
+ *
+ * @param string $name
+ * @return mixed
+ */
+ function delete($name)
+ {
+ list ($cache_name, $name) = $this->_getKeyInfo($name);
+
+ $this->set($cache_name, $name, false, -3600);
+ }
+
+ function reset()
+ {
+
+ }
}
- class MemcacheCacheStorage {
+ class MemcacheCacheStorage extends kBase {
+ var $cachingType = CACHING_TYPE_MEMORY;
+
/**
+ * Part of what we retrieve will be stored locally (per script run) not to bother memcache a lot
+ *
+ * @var Array
+ */
+ var $_localStorage = Array ();
+
+ /**
* Memcache connection
*
* @var Memcache
*/
var $_handler = null;
- function MemcacheCacheStorage($servers)
+ var $_enabled = false;
+
+ var $_debugMode = false;
+
+ function MemcacheCacheStorage()
{
- $this->_handler = new Memcache;
+ parent::kBase();
- $servers = explode(';', $servers);
- foreach ($servers as $server) {
- list ($server, $port) = strpos($server, ':') !== false ? explode(':', $server, 2) : Array ($server, 11211);
- $this->_handler->addServer($server, $port);
- }
+ if (array_key_exists('MemcacheServers', $GLOBALS['vars'])) {
+ // for advanced users, who want to save one SQL on each page load
+ $memcached_servers = $GLOBALS['vars']['MemcacheServers'];
+ }
+ else {
+ $memcached_servers = $this->Application->ConfigValue('MemcacheServers');
+ }
+
+ if ($memcached_servers && class_exists('Memcache')) {
+ $this->_enabled = true;
+ $this->_handler = new Memcache();
+ $servers = explode(';', $memcached_servers);
+
+ foreach ($servers as $server) {
+ list ($server, $port) = strpos($server, ':') !== false ? explode(':', $server, 2) : Array ($server, 11211);
+ $this->_handler->addServer($server, $port);
+ }
+
+ // try to set something to cache, if not working - set $this->Memcached to null
+ if (!$this->_handler->set('test', 1)) {
+ $this->_handler = null;
+ $this->_enabled = false;
+ }
+ }
+
+ $this->_debugMode = $this->Application->isDebugMode();
+
+ if ($this->_debugMode) {
+ $this->Application->Debugger->appendHTML('MemCache Enabled: ' . ($this->_enabled ? 'YES' : 'NO'));
+ }
}
/**
+ * Returns storage size in bytes
+ *
+ * @return int
+ */
+ function getStorageSize()
+ {
+ return strlen( serialize($this->_localStorage) );
+ }
+
+ /**
+ * Returns site-wide caching prefix
+ *
+ * @param bool $only_site_key_name
+ * @return string
+ */
+ function _cachePrefix($only_site_key_name = false)
+ {
+ if (!$this->_enabled) {
+ return false;
+ }
+
+ // don't use SERVER_NAME here, because it may be cron, or command line request also
+ $site_key = 'site_serial:' . crc32(FULL_PATH);
+
+ if ($only_site_key_name) {
+ return $site_key;
+ }
+
+ $site_serial = $this->_handler->get($site_key);
+
+ if (!$site_serial) {
+ $site_serial = 1;
+ $this->_handler->set($site_key, $site_serial);
+ }
+
+ return "$site_key:$site_serial:";
+ }
+
+ /**
* Determines, that cache storage is working fine
*
* @return bool
*/
function isWorking()
{
- return $this->_handler->getVersion() !== false;
+ return $this->_enabled;
}
/**
* Stores value to cache
*
- * @param string $cache_name
- * @param string $key
+ * @param string $name
* @param mixed $value
* @param int $expires cache record expiration time in seconds
*/
- function set($cache_name, $key, $value, $expires)
+ function set($name, $value, $expiration)
{
- return $this->_handler->set($cache_name . '-' . $key, $value, false, $expires); // false could be MEMCACHE_COMPRESSED to compress values in memory
+ if (!$this->_enabled) {
+ return false;
+ }
+
+ $name = $this->prepareKeyName($name);
+ unset($this->_localStorage[$name]);
+
+ // 0 - don't use compression
+ return $this->_handler->set($name, $value, 0, $expiration);
}
/**
* Returns value from cache
*
- * @param string $cache_name
- * @param string $key
+ * @param string $name
+ * @param bool $store_locally store data locally after retrieved
+ * @param bool $replace_serials
* @return mixed
*/
- function get($cache_name, $key)
+ function get($name, $store_locally = true, $replace_serials = true)
{
- return $this->_handler->get($cache_name . '-' . $key);
- }
- }
+ if (!$this->_enabled) {
+ return false;
+ }
- class FileCacheStorage extends Params {
+ $name = $this->prepareKeyName($name, $replace_serials);
- /**
- * Expiration time for each variable in cache
- *
- * @var resource
- */
- var $_expiration = Array ();
+ if ($store_locally) {
+ if (array_key_exists($name, $this->_localStorage)) {
+ return $this->_localStorage[$name];
+ }
+ }
- /**
- * Filename for storing cache
- *
- * @var string
- */
- var $_filename = '';
+ $res = $this->_handler->get($name);
- function FileCacheStorage($filename = '')
- {
- $this->_filename = WRITEABLE . '/cache' . '/' . $filename;
+ if ($replace_serials && $this->_debugMode) {
+ // don't display subsequent serial cache retrievals (ones, that are part of keys)
+ if (is_array($res)) {
+ $this->Application->Debugger->appendHTML('Restoring key "' . $name . '". Type: ' . gettype($res) . '.');
+ }
+ else {
+ $res_display = strip_tags($res);
- if (file_exists($this->_filename)) {
- $cache_data = unserialize(file_get_contents($this->_filename));
+ if (strlen($res_display) > 200) {
+ $res_display = substr($res_display, 0, 50) . ' ...';
+ }
+
+ $this->Application->Debugger->appendHTML('Restoring key "' . $name . '" resulted [' . $res_display . ']');
+ }
}
- else {
- $cache_data = Array ();
- }
+
+ $this->_localStorage[$name] = $res;
+
+ return $res;
}
/**
- * Determines, that cache storage is working fine
+ * Replaces serials in cache variable name
*
- * @return bool
+ * @param string $name
+ * @param bool $replace_serials
+ * @return string
*/
- function isWorking()
+ function prepareKeyName($name, $replace_serials = true)
{
- return false;
+ // replace serials in key name
+ if ($replace_serials && preg_match_all('/\[%(.*?)%\]/', $name, $regs)) {
+ // [%LangSerial%] - prefix-wide serial in case of any change in "lang" prefix
+ // [%LangIDSerial:5%] - one id-wide serial in case of data, associated with given id was changed
+ // [%CiIDSerial:ItemResourceId:5%] - foreign key-based serial in case of data, associated with given foreign key was changed
+ foreach ($regs[1] as $serial_name) {
+ $name = str_replace('[%' . $serial_name . '%]', '[' . $serial_name . '=' . $this->get($serial_name, true, false) . ']', $name);
+ }
+ }
+
+ // add site-wide prefix to key
+ return $this->_cachePrefix() . $name;
}
/**
- * Stores value to cache
+ * Deletes value from cache
*
- * @param string $cache_name
- * @param string $key
- * @param mixed $value
- * @param int $expires cache record expiration time in seconds
+ * @param string $name
+ * @return mixed
*/
- function set($cache_name, $key, $value, $expires)
+ function delete($name)
{
- $cache = parent::Get($cache_name, Array());
- $cache[$key] = $value;
+ if (!$this->_enabled) {
+ return false;
+ }
- parent::Set($cache_name, $cache);
+ $name = $this->prepareKeyName($name);
+ unset($this->_localStorage[$name]);
+
+ return $this->_handler->delete($name);
}
/**
- * Returns value from cache
- *
- * @param string $cache_name
- * @param string $key
- * @return mixed
+ * Reset's all memory cache at once
*/
- function get($cache_name, $key)
+ function reset()
{
- $cache = parent::Get($cache_name, Array());
- $ret = array_key_exists($key, $cache) ? $cache[$key] : false;
+ // don't check for enabled, because we maybe need to reset cache anyway
+ $site_key = $this->_cachePrefix(true);
- return $ret;
+ $this->_handler->set($site_key, $this->_handler->get($site_key) + 1);
}
- }
\ No newline at end of file
+ }
Index: core/kernel/utility/debugger.php
===================================================================
--- core/kernel/utility/debugger.php (revision 13152)
+++ core/kernel/utility/debugger.php (working copy)
@@ -187,7 +187,7 @@
}
$this->safeDefine('DBG_ZEND_PRESENT', 0); // set this constant value to 0 (zero) to debug debugger using Zend Studio
-
+
// set default values for debugger constants
$dbg_constMap = Array (
'DBG_USE_HIGHLIGHT' => 1, // highlight output same as php code using "highlight_string" function
@@ -417,7 +417,8 @@
$div_width['current'] = round(($runtime / $total) * $total_width);
$div_width['left'] = round((($total - $total_before - $runtime) / $total) * $total_width);
- $ret = '<b>Name</b>: '.$Data['description'].'<br />';
+ $subtitle = array_key_exists('subtitle', $Data) ? ' (' . $Data['subtitle'] . ')' : '';
+ $ret = '<b>Name' . $subtitle . '</b>: '.$Data['description'].'<br />';
$additional = isset($Data['additional']) ? $Data['additional'] : Array ();
if (isset($Data['file'])) {
@@ -885,8 +886,16 @@
}
$i++;
}
+
$this->ProfilerData[$key]['file'] = $trace_results[$i]['file'];
$this->ProfilerData[$key]['line'] = $trace_results[$i]['line'];
+
+ if (array_key_exists('object', $trace_results[$i + 1]) && isset($trace_results[$i + 1]['object']->Prefix)) {
+ $object =& $trace_results[$i + 1]['object'];
+ $prefix_special = rtrim($object->Prefix . '.' . $object->Special, '.');
+ $this->ProfilerData[$key]['prefix_special'] = $prefix_special;
+ }
+
unset($trace_results);
}
@@ -923,6 +932,16 @@
}
$additional[] = Array ('name' => 'Query Number', 'value' => $func_arguments[5]);
+
+ if ($func_arguments[6]) {
+ $this->profilerAddTotal('cachable_queries', $key);
+ $this->ProfilerData[$key]['subtitle'] = 'cachable';
+ }
+
+ if (array_key_exists('prefix_special', $this->ProfilerData[$key])) {
+ $additional[] = Array ('name' => 'PrefixSpecial', 'value' => $this->ProfilerData[$key]['prefix_special']);
+ }
+
$this->ProfilerData[$key]['additional'] =& $additional;
}
}
@@ -1097,7 +1116,14 @@
if ($this->constOn('DBG_SQL_PROFILE') && isset($this->ProfilerTotals['sql'])) {
// sql query profiling was enabled -> show totals
- $this->appendHTML('<b>SQL Total time:</b> '.$this->ProfilerTotals['sql'].' <b>Number of queries</b>: '.$this->ProfilerTotalCount['sql']);
+ if (array_key_exists('cachable_queries', $this->ProfilerTotalCount)) {
+ $append = ' <strong>Cachable queries</strong>: ' . $this->ProfilerTotalCount['cachable_queries'];
+ }
+ else {
+ $append = '';
+ }
+
+ $this->appendHTML('<b>SQL Total time:</b> '.$this->ProfilerTotals['sql'].' <b>Number of queries</b>: '.$this->ProfilerTotalCount['sql'] . $append);
}
if ($this->constOn('DBG_PROFILE_INCLUDES') && isset($this->ProfilerTotals['includes'])) {
Index: core/kernel/utility/formatters/multilang_formatter.php
===================================================================
--- core/kernel/utility/formatters/multilang_formatter.php (revision 13152)
+++ core/kernel/utility/formatters/multilang_formatter.php (working copy)
@@ -24,13 +24,23 @@
*/
function LangFieldName($field_name, $from_primary = false)
{
- if (preg_match('/^l[0-9]+_/', $field_name)) return $field_name;
- $lang = $from_primary ? $this->Application->GetDefaultLanguageId() : $this->Application->GetVar('m_lang');
+ static $primary_language = null;
+
+ if (preg_match('/^l[0-9]+_/', $field_name)) {
+ return $field_name;
+ }
+
+ if (!isset($primary_language)) {
+ $primary_language = $this->Application->GetDefaultLanguageId();
+ }
+
+ $lang = $from_primary ? $primary_language : $this->Application->GetVar('m_lang');
+
if (!$lang || ($lang == 'default')) {
- $lang = $this->Application->GetDefaultLanguageId();
+ $lang = $primary_language;
}
- return 'l'.$lang.'_'.$field_name;
+ return 'l' . $lang . '_' . $field_name;
}
function PrepareOptions($field_name, &$field_options, &$object)
Index: core/kernel/utility/temp_handler.php
===================================================================
--- core/kernel/utility/temp_handler.php (revision 13162)
+++ core/kernel/utility/temp_handler.php (working copy)
@@ -702,6 +702,20 @@
if (in_array($prefix, $rec['ParentPrefix']) && $rec['ParentId'][$prefix] == $temp_id) {
// parent item change log record
$changes[$key]['ParentId'][$prefix] = $live_id;
+
+ if (array_key_exists('DependentFields', $rec)) {
+ // these are fields from table of $rec['Prefix'] table!
+ // when one of dependent fields goes into idfield of it's parent item, that was changed
+ $parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey');
+ $parent_table_key = is_array($parent_table_key) ? $parent_table_key[$prefix] : $parent_table_key;
+
+ if ($parent_table_key == $master['IdField']) {
+ $foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey');
+ $foreign_key = is_array($foreign_key) ? $foreign_key[$prefix] : $foreign_key;
+
+ $changes[$key]['DependentFields'][$foreign_key] = $live_id;
+ }
+ }
}
}
Index: core/kernel/utility/unit_config_reader.php
===================================================================
--- core/kernel/utility/unit_config_reader.php (revision 13152)
+++ core/kernel/utility/unit_config_reader.php (working copy)
@@ -79,23 +79,29 @@
$aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray');
$config_vars = Array (
+ // session related
'SessionTimeout',
'SessionCookieName',
'SessionBrowserSignatureCheck',
'SessionIPAddressCheck',
'CookieSessions',
- 'UseCronForRegularEvent',
+ 'SessionTimeout',
+ 'KeepSessionOnBrowserClose',
'User_GuestGroup',
'User_LoggedInGroup',
- 'SessionTimeout',
+
+ // output related
'UseModRewrite',
'UseOutputCompression',
'OutputCompressionLevel',
- 'KeepSessionOnBrowserClose',
'Config_Server_Time',
'Config_Site_Time',
+ 'SystemTagCache',
+
+ // tracking related
'UseChangeLog',
'UseVisitorTracking',
+ 'UseCronForRegularEvent',
);
foreach ($config_vars as $var) {
@@ -123,18 +129,17 @@
'Application.ModuleInfo' => $this->Application->ModuleInfo,
);
- $conn =& $this->Application->GetADODBConnection();
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->set('master:configs_parsed', serialize($cache));
- $this->Application->Memcached->set('master:config_files', serialize($this->configFiles));
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->setCache('master:configs_parsed', serialize($cache));
+ $this->Application->setCache('master:config_files', serialize($this->configFiles));
}
else {
- $conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("configs_parsed", '.$conn->qstr(serialize($cache)).', '.adodb_mktime().')');
- $conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("config_files", '.$conn->qstr(serialize($this->configFiles)).', '.adodb_mktime().')');
+ $this->Application->setDBCache('configs_parsed', serialize($cache));
+ $this->Application->setDBCache('config_files', serialize($this->configFiles));
}
$cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s');
- $conn->Query('REPLACE ' . TABLE_PREFIX . 'Cache (VarName, Data, Cached) VALUES ("last_cache_rebuild", ' . $conn->qstr($cache_rebuild_by) . ', ' . adodb_mktime() . ')');
+ $this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by);
unset($this->configFiles);
}
@@ -142,9 +147,14 @@
function RestoreParsedData()
{
$conn =& $this->Application->GetADODBConnection();
- if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:configs_parsed'))) {
- $data = $conn->GetOne('SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"');
+
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->getCache('master:configs_parsed', false);
}
+ else {
+ $data = $this->Application->getDBCache('configs_parsed');
+ }
+
if ($data) {
$cache = unserialize($data);
$this->Application->Factory->Files = $cache['Factory.Files'];
@@ -181,16 +191,21 @@
function ResetParsedData($include_sections = false)
{
$conn =& $this->Application->GetADODBConnection();
- $conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"');
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->delete('master:configs_parsed');
+
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:configs_parsed');
}
+ else {
+ $this->Application->deleteDBCache('configs_parsed');
+ }
if ($include_sections) {
- $conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->delete('master:sections_parsed');
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:sections_parsed');
}
+ else {
+ $this->Application->deleteDBCache('sections_parsed');
+ }
}
}
@@ -273,10 +288,12 @@
{
$this->Application->refreshModuleInfo();
- $conn =& $this->Application->GetADODBConnection();
- if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:config_files'))) {
- $data = $conn->GetOne('SELECT Data FROM ' . TABLE_PREFIX . 'Cache WHERE VarName = "config_files"');
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->getCache('master:config_files', false);
}
+ else {
+ $data = $this->Application->getDBCache('config_files');
+ }
if ($cache && $data) {
$this->configFiles = unserialize($data);
Index: core/units/admin/admin_events_handler.php
===================================================================
--- core/units/admin/admin_events_handler.php (revision 13152)
+++ core/units/admin/admin_events_handler.php (working copy)
@@ -43,14 +43,14 @@
$perm_value = null;
$system_events = Array (
- 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache',
+ 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache', 'OnResetMemcache',
'OnDeleteCompiledTemplates', 'OnCompileTemplates', 'OnGenerateTableStructure',
- 'OnRebuildThemes', 'OnCheckPrefixConfig',
+ 'OnRebuildThemes', 'OnCheckPrefixConfig', 'OnMemoryCacheGet', 'OnMemoryCacheSet'
);
if (in_array($event->Name, $system_events)) {
// events from "Tools -> System Tools" section are controlled via that section "edit" permission
- $perm_value = $this->Application->CheckPermission($event->getSection() . '.edit');
+ $perm_value = /*$this->Application->isDebugMode() ||*/ $this->Application->CheckPermission($event->getSection() . '.edit');
}
$tools_events = Array (
@@ -95,7 +95,7 @@
$event->status = erSTOP;
}
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName LIKE "mod_rw%"');
+ $this->Conn->Query('DELETE FROM ' . TABLE_PREFIX . 'CachedUrls');
}
function OnResetSections(&$event)
@@ -104,13 +104,12 @@
$event->status = erSTOP;
}
- $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "sections_parsed"';
- $this->Conn->Query($sql);
-
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->delete('master:sections_parsed');
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:sections_parsed');
}
+ else {
+ $this->Application->deleteDBCache('sections_parsed');
+ }
$event->SetRedirectParam('refresh_tree', 1);
}
@@ -121,22 +120,34 @@
$event->status = erSTOP;
}
- $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName IN("config_files", "configs_parsed", "sections_parsed")';
- $this->Conn->Query($sql);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:config_files');
+ $this->Application->deleteCache('master:configs_parsed');
+ $this->Application->deleteCache('master:sections_parsed');
+ }
+ else {
+ $this->Application->deleteDBCache('config_files');
+ $this->Application->deleteDBCache('configs_parsed');
+ $this->Application->deleteDBCache('sections_parsed');
+ }
$skin_helper =& $this->Application->recallObject('SkinHelper');
/* @var $skin_helper SkinHelper */
$skin_helper->deleteCompiled();
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->delete('master:config_files');
- $this->Application->Memcached->delete('master:configs_parsed');
- $this->Application->Memcached->delete('master:sections_parsed');
+ $event->SetRedirectParam('refresh_tree', 1);
+ }
+
+ function OnResetMemcache(&$event)
+ {
+ if ($this->Application->GetVar('ajax') == 'yes') {
+ $event->status = erSTOP;
}
- $event->SetRedirectParam('refresh_tree', 1);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->memoryCache->reset();
+ }
}
function OnCompileTemplates(&$event)
@@ -1247,4 +1258,75 @@
}
}
+ /**
+ * Retrieves data from memory cache
+ *
+ * @param kEvent $event
+ */
+ function OnMemoryCacheGet(&$event)
+ {
+ $event->status = erSTOP;
+
+ $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error
+ $key = $this->Application->GetVar('key');
+
+ if (!$key) {
+ $ret['code'] = 1;
+ $ret['message'] = 'Key name missing';
+ }
+ else {
+ $value = $this->Application->getCache($key);
+
+ $ret['value'] =& $value;
+ $ret['size'] = is_string($value) ? formatSize( strlen($value) ) : '?';
+ $ret['type'] = gettype($value);
+
+ if (IsSerialized($value)) {
+ $value = unserialize($value);
+ }
+
+ if (is_array($value)) {
+ $ret['value'] = print_r($value, true);
+ }
+
+ if ($ret['value'] === false) {
+ $ret['code'] = 2;
+ $ret['message'] = 'Key "' . $key . '" doesn\'t exist';
+ }
+ }
+
+ $json_helper =& $this->Application->recallObject('JSONHelper');
+ /* @var $json_helper JSONHelper */
+
+ echo $json_helper->encode($ret);
+ }
+
+ /**
+ * Retrieves data from memory cache
+ *
+ * @param kEvent $event
+ */
+ function OnMemoryCacheSet(&$event)
+ {
+ $event->status = erSTOP;
+
+ $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error
+ $key = $this->Application->GetVar('key');
+
+ if (!$key) {
+ $ret['code'] = 1;
+ $ret['message'] = 'Key name missing';
+ }
+ else {
+ $value = $this->Application->GetVar('value');
+ $res = $this->Application->setCache($key, $value);
+
+ $ret['result'] = $res ? 'OK' : 'FAILED';
+ }
+
+ $json_helper =& $this->Application->recallObject('JSONHelper');
+ /* @var $json_helper JSONHelper */
+
+ echo $json_helper->encode($ret);
+ }
}
\ No newline at end of file
Index: core/units/admin/admin_tag_processor.php
===================================================================
--- core/units/admin/admin_tag_processor.php (revision 13152)
+++ core/units/admin/admin_tag_processor.php (working copy)
@@ -587,11 +587,7 @@
function CheckPermCache($params)
{
// we have separate session between install wizard and admin console, so store in cache
- $sql = 'SELECT Data
- FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = "ForcePermCacheUpdate"';
- $global_mark = $this->Conn->GetOne($sql);
-
+ $global_mark = $this->Application->getDBCache('ForcePermCacheUpdate');
$local_mark = $this->Application->RecallVar('PermCache_UpdateRequired');
if ($global_mark || $local_mark) {
@@ -1139,4 +1135,15 @@
return false;
}
+
+ /**
+ * Checks, that we are using memory cache
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function MemoryCacheEnabled($params)
+ {
+ return $this->Application->isCachingType(CACHING_TYPE_MEMORY);
+ }
}
\ No newline at end of file
Index: core/units/categories/cache_updater.php
===================================================================
--- core/units/categories/cache_updater.php (revision 13152)
+++ core/units/categories/cache_updater.php (working copy)
@@ -322,10 +322,13 @@
function clearData()
{
+ // some templates use this
+ $this->Conn->Query('UPDATE '.TABLE_PREFIX.'ConfigurationValues SET VariableValue = VariableValue+1 WHERE VariableName = \'CategoriesRebuildSerial\'');
+
+ // always drop temporary tables
$this->Conn->Query('DROP TABLE IF EXISTS '.$this->progressTable);
$this->Conn->Query('DROP TABLE IF EXISTS '.$this->permCacheTable);
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = \'ForcePermCacheUpdate\'');
- $this->Conn->Query('UPDATE '.TABLE_PREFIX.'ConfigurationValues SET VariableValue = VariableValue+1 WHERE VariableName = \'CategoriesRebuildSerial\'');
+ $this->Application->deleteDBCache('ForcePermCacheUpdate');
}
function SaveData()
@@ -338,6 +341,8 @@
FROM '.$this->permCacheTable;
$this->Conn->Query($sql);
$this->clearData();
+
+ $this->Application->incrementCacheSerial('c');
}
function DoTheJob()
@@ -449,6 +454,10 @@
}
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'Category', 'CategoryId = '.$data['current_id']);
+
+ if ($this->Conn->getAffectedRows() > 0) {
+ $this->Application->incrementCacheSerial('c', $data['current_id']);
+ }
}
function QueryTitle(&$data)
Index: core/units/categories/categories_config.php
===================================================================
--- core/units/categories/categories_config.php (revision 13167)
+++ core/units/categories/categories_config.php (working copy)
@@ -259,7 +259,8 @@
FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'Images img ON img.ResourceId = %1$s.ResourceId AND img.DefaultImg = 1
LEFT JOIN '.TABLE_PREFIX.'PermCache ON '.TABLE_PREFIX.'PermCache.CategoryId = %1$s.CategoryId
- LEFT JOIN '.TABLE_PREFIX.'%3$sCategoryCustomData cust ON %1$s.ResourceId = cust.ResourceId'
+ LEFT JOIN '.TABLE_PREFIX.'%3$sCategoryCustomData cust ON %1$s.ResourceId = cust.ResourceId',
+ '-virtual' => 'SELECT %1$s.* %2$s FROM %1$s',
),
'SubItems' => Array ('c-rel', 'c-search','c-img', 'c-cdata', 'c-perm', 'content'),
@@ -282,7 +283,8 @@
'LocalPath' => 'img.LocalPath',
'FullUrl' => 'img.Url',
'CreatedBySystem' => 'IF(ThemeId != 0, 1, 0)',
- )
+ ),
+ '-virtual' => Array (),
),
'CacheModRewrite' => true,
@@ -363,6 +365,19 @@
'FormSubmittedTemplate' => Array ('type' => 'string', 'default' => null),
'FriendlyURL' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
'ThemeId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
+
+ 'EnablePageCache' => Array (
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 0
+ ),
+ 'OverridePageCacheKey' => Array (
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 0
+ ),
+ 'PageCacheKey' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''),
+ 'PageExpiration' => Array ('type' => 'int', 'default' => NULL),
),
'VirtualFields' => Array (
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php (revision 13152)
+++ core/units/categories/categories_event_handler.php (working copy)
@@ -648,16 +648,18 @@
*/
function prepareObject(&$object, &$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ if ($event->Special != '-virtual') {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
- $object->addCalculatedField(
- 'IsNew',
- ' IF(%1$s.NewItem = 2,
- IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
- $this->Application->ConfigValue('Category_DaysNew').
- '*3600*24), 1, 0),
- %1$s.NewItem
- )');
+ $object->addCalculatedField(
+ 'IsNew',
+ ' IF(%1$s.NewItem = 2,
+ IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
+ $this->Application->ConfigValue('Category_DaysNew').
+ '*3600*24), 1, 0),
+ %1$s.NewItem
+ )');
+ }
}
/**
@@ -1553,6 +1555,8 @@
$object->SetDBField('Modified_date', $now);
$object->SetDBField('Modified_time', $now);
+
+ $object->setRequired('PageCacheKey', $object->GetDBField('OverridePageCacheKey'));
$object->SetDBField('Template', $this->_stripTemplateExtension( $object->GetDBField('Template') ));
if ($object->GetDBField('IsSystem') == 1) {
@@ -1810,55 +1814,17 @@
function _resetMenuCache()
{
- // reset cms menu cache
- $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName IN ("cms_menu", "StructureTree")';
- $this->Conn->Query($sql);
-
- // build structure template mapping
- $sql = 'SELECT
- IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS SrcTemplate,
- LOWER(
- IF(
- c.SymLinkCategoryId IS NOT NULL,
- (SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc WHERE cc.CategoryId = c.SymLinkCategoryId),
- c.NamedParentPath
- )
- ) AS DstTemplate,
- c.UseExternalUrl, c.ExternalUrl
- FROM ' . TABLE_PREFIX . 'Category AS c
- WHERE c.Status = ' . STATUS_ACTIVE;
- $pages = $this->Conn->Query($sql, 'SrcTemplate');
-
- $mapping = Array ();
- $base_url = $this->Application->BaseURL();
-
- foreach ($pages as $src_template => $page) {
- // process external url, before placing in cache
- if ($page['UseExternalUrl']) {
- $external_url = $page['ExternalUrl'];
-
- if (!preg_match('/^(.*?):\/\/(.*)$/', $external_url)) {
- // url without protocol will be relative url to our site
- $external_url = $base_url . $external_url;
- }
-
- $dst_template = 'external:' . $external_url;
- }
- else {
- $dst_template = preg_replace('/^Content\//i', '', $page['DstTemplate']);
- }
-
- $mapping[$src_template] = $dst_template;
+ // reset cms menu cache (all variables are automatically rebuild, when missing)
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->deleteCache('master:cms_menu');
+ $this->Application->deleteCache('master:StructureTree');
+ $this->Application->deleteCache('master:template_mapping');
}
-
- $fields_hash = Array (
- 'VarName' => 'template_mapping',
- 'Data' => serialize($mapping),
- 'Cached' => adodb_mktime(),
- );
-
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
+ else {
+ $this->Application->deleteDBCache('cms_menu');
+ $this->Application->deleteDBCache('StructureTree');
+ $this->Application->deleteDBCache('template_mapping');
+ }
}
/**
@@ -2418,4 +2384,35 @@
$this->Application->SetVar('search_logged', 1);
}
}
+
+ /**
+ * Load item if id is available
+ *
+ * @param kEvent $event
+ */
+ function LoadItem(&$event)
+ {
+ if ($event->Special != '-virtual') {
+ parent::LoadItem($event);
+ return ;
+ }
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $id = $this->getPassedID($event);
+
+ if ($object->isLoaded() && !is_array($id) && ($object->GetID() == $id)) {
+ // object is already loaded by same id
+ return ;
+ }
+
+ if ($object->Load($id, null, true)) {
+ $actions =& $this->Application->recallObject('kActions');
+ $actions->Set($event->Prefix_Special.'_id', $object->GetID() );
+ }
+ else {
+ $object->setID($id);
+ }
+ }
}
\ No newline at end of file
Index: core/units/categories/categories_tag_processor.php
===================================================================
--- core/units/categories/categories_tag_processor.php (revision 13159)
+++ core/units/categories/categories_tag_processor.php (working copy)
@@ -220,22 +220,26 @@
*/
function getCategorySymLink($category_id)
{
- static $cache = null;
-
if (!$category_id) {
// don't bother to get symlink for "Home" category
return $category_id;
}
- if (!isset($cache)) {
+ $cache_key = 'category_symlinks[%CSerial%]';
+ $cache = $this->Application->getCache($cache_key);
+
+ if ($cache === false) {
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
// get symlinked categories, that are not yet deleted
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . '
FROM ' . $table_name . ' c1
JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field;
$cache = $this->Conn->GetCol($sql, $id_field);
+
+ $this->Application->setCache($cache_key, $cache);
}
return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id;
@@ -748,27 +752,34 @@
*/
function LastUpdated($params)
{
- $category_id = $this->Application->GetVar('m_cat_id');
- $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
+ $category_id = (int)$this->Application->GetVar('m_cat_id');
+ $local = array_key_exists('local', $params) && ($category_id > 0) ? $params['local'] : false;
- if (isset($params['local']) && $params['local'] && $category_id > 0) {
- // scan only current category & it's children
- $sql = 'SELECT TreeLeft, TreeRight
- FROM '.TABLE_PREFIX.'Category
- WHERE CategoryId = '.$category_id;
- $tree_info = $this->Conn->GetRow($sql);
+ $serial_name = $this->Application->incrementCacheSerial('c', $local ? $category_id : null, false);
+ $cache_key = 'category_last_updated[%' . $serial_name . '%]';
- $sql = 'SELECT MAX(c.Modified) AS ModDate, MAX(c.CreatedOn) AS NewDate
- FROM '.TABLE_PREFIX.'Category c
- WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight'];
+ $row_data = $this->Application->getCache($cache_key);
+
+ if ($row_data === false) {
+ if ($local && ($category_id > 0)) {
+ // scan only current category & it's children
+ list ($tree_left, $tree_right) = $this->Application->getTreeIndex($category_id);
+
+ $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right;
+ }
+ else {
+ // scan all categories in system
+ $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
+ FROM ' . TABLE_PREFIX . 'Category';
+ }
+
+ $this->Conn->nextQueryCachable = true;
+ $row_data = $this->Conn->GetRow($sql);
+ $this->Application->setCache($cache_key, $row_data);
}
- else {
- // scan all categories in system
- $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
- FROM '.$table_name;
- }
- $row_data = $this->Conn->GetRow($sql);
if (!$row_data) {
return '';
}
@@ -781,7 +792,7 @@
$lang =& $this->Application->recallObject('lang.current');
if ($regs[1] == 'DateTimeFormat') {
// combined format
- $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat');
+ $format = $lang->GetDBField('DateFormat') . ' ' . $lang->GetDBField('TimeFormat');
}
else {
// simple format
@@ -891,7 +902,9 @@
}
// 1. try to get already cached suggestion
- $suggestion = $this->Application->getCache('search.suggestion', $keywords);
+ $cache_key = 'search.suggestion[%SpellingDictionary%]:' . $keywords;
+ $suggestion = $this->Application->getCache($cache_key);
+
if ($suggestion !== false) {
return $suggestion;
}
@@ -899,12 +912,14 @@
$table_name = $this->Application->getUnitOption('spelling-dictionary', 'TableName');
// 2. search suggestion in database
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT SuggestedCorrection
FROM ' . $table_name . '
WHERE MisspelledWord = ' . $this->Conn->qstr($keywords);
$suggestion = $this->Conn->GetOne($sql);
+
if ($suggestion !== false) {
- $this->Application->setCache('search.suggestion', $keywords, $suggestion);
+ $this->Application->setCache($cache_key, $suggestion);
return $suggestion;
}
@@ -933,7 +948,7 @@
);
$this->Conn->doInsert($fields_hash, $table_name);
- $this->Application->setCache('search.suggestion', $keywords, $result->Data);
+ $this->Application->setCache($cache_key, $result->Data);
return $result->Data;
}
@@ -1003,7 +1018,15 @@
$object =& $this->getObject($params);
$category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
- $category_path = $this->Application->getCache('category_paths', $category_id);
+ $cache_key = 'category_paths[%CIDSerial:' . $category_id . '%]';
+
+ if ($category_id == 0) {
+ // home category name is phrase AND phrase name is defined in configuration
+ $cache_key .= '[%PhrasesSerial%][%ConfSerial%]';
+ }
+
+ $category_path = $this->Application->getCache($cache_key);
+
if ($category_path === false) {
// not chached
if ($category_id > 0) {
@@ -1035,8 +1058,10 @@
else {
$category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
}
- $this->Application->setCache('category_paths', $category_id, $category_path);
+
+ $this->Application->setCache($cache_key, $category_path);
}
+
return $category_path;
}
Index: core/units/custom_data/custom_data_event_handler.php
===================================================================
--- core/units/custom_data/custom_data_event_handler.php (revision 13152)
+++ core/units/custom_data/custom_data_event_handler.php (working copy)
@@ -57,11 +57,20 @@
if (!$custom_fields || (defined('IS_INSTALL') && IS_INSTALL) || (defined('CUSTOM_FIELD_ADDED') && CUSTOM_FIELD_ADDED)) {
// query all custom fields at once -> saves 4 sqls queries
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'CustomField';
- $all_custom_fields = $this->Conn->Query($sql, 'CustomFieldId');
- ksort($all_custom_fields);
+ $cache_key = 'all_custom_fields[%CfSerial%][%ModSerial%]';
+ $all_custom_fields = $this->Application->getCache($cache_key, false);
+
+ if ($all_custom_fields === false) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'CustomField';
+ $all_custom_fields = $this->Conn->Query($sql, 'CustomFieldId');
+ ksort($all_custom_fields);
+
+ $this->Application->setCache($cache_key, $all_custom_fields);
+ }
+
foreach ($all_custom_fields as $custom_field_id => $custom_field_data) {
$cf_type = $custom_field_data['Type'];
if (!array_key_exists($cf_type, $custom_fields)) {
@@ -168,6 +177,10 @@
$config_calculated_fields = $this->Application->getUnitOption($prefix, 'CalculatedFields', Array());
foreach ($config_calculated_fields as $special => $special_fields) {
+ if ($special == '-virtual') {
+ continue;
+ }
+
$config_calculated_fields[$special] = array_merge_recursive2($config_calculated_fields[$special], $calculated_fields);
}
$this->Application->setUnitOption($prefix, 'CalculatedFields', $config_calculated_fields);
Index: core/units/forms/forms_eh.php
===================================================================
--- core/units/forms/forms_eh.php (revision 13152)
+++ core/units/forms/forms_eh.php (working copy)
@@ -70,12 +70,11 @@
function OnSave(&$event)
{
parent::OnSave($event);
+
if ($event->status == erSUCCESS) {
-
$this->OnCreateFormFields($event);
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
- $this->Application->StoreVar('RefreshStructureTree', 1);
+ $this->_deleteSectionCache();
}
}
@@ -84,11 +83,18 @@
parent::OnMassDelete($event);
if ($event->status == erSUCCESS) {
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
- $this->Application->StoreVar('RefreshStructureTree', 1);
+ $this->_deleteSectionCache();
}
}
+ function _deleteSectionCache()
+ {
+ $reset_event = new kEvent('adm:OnResetSections');
+ $this->Application->HandleEvent($reset_event);
+
+ $this->Application->StoreVar('RefreshStructureTree', 1);
+ }
+
/**
* Dynamically fills customdata config
*
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php (revision 13152)
+++ core/units/helpers/category_helper.php (working copy)
@@ -283,27 +283,30 @@
*/
function getCategoryParentPath($main_category_id)
{
- static $cached_path = null;
-
if ($main_category_id == 0) {
// don't query path for "Home" category
return Array ();
}
- if (!isset($cached_path[$main_category_id])) {
+ $cache_key = 'parent_paths[%CIDSerial:' . $main_category_id . '%]';
+ $cached_path = $this->Application->getCache($cache_key);
+
+ if ($cached_path === false) {
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
$navbar_field = $ml_formatter->LangFieldName('CachedNavBar');
$id_field = $this->Application->getUnitOption('c', 'IDField');
$table_name = $this->Application->getUnitOption('c', 'TableName');
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT '.$navbar_field.', ParentPath
FROM '.$table_name.'
WHERE '.$id_field.' = '.$main_category_id;
$category_data = $this->Conn->GetRow($sql);
+ $cached_path = Array ();
$skip_category = $this->Application->findModule('Name', 'Core', 'RootCat');
- $cached_path[$main_category_id] = Array ();
+
if ($category_data) {
$category_names = explode('&|&', $category_data[$navbar_field]);
$category_ids = explode('|', substr($category_data['ParentPath'], 1, -1));
@@ -312,11 +315,15 @@
if ($category_id == $skip_category) {
continue;
}
- $cached_path[$main_category_id][$category_id] = $category_names[$category_index];
+
+ $cached_path[$category_id] = $category_names[$category_index];
}
}
+
+ $this->Application->setCache($cache_key, $cached_path);
}
- return $cached_path[$main_category_id];
+
+ return $cached_path;
}
/**
@@ -419,10 +426,12 @@
function &_getStructureTree()
{
// get cached version of structure tree
- $sql = 'SELECT Data
- FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "StructureTree"';
- $data = $this->Conn->GetOne($sql);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->getCache('master:StructureTree', false);
+ }
+ else {
+ $data = $this->Application->getDBCache('StructureTree');
+ }
if ($data) {
$data = unserialize($data);
@@ -439,17 +448,75 @@
$root_category = $this->Application->findModule('Name', 'Core', 'RootCat');
$data = $this->_getChildren($root_category, $language_count);
- $fields_hash = Array (
- 'VarName' => 'StructureTree',
- 'Data' => serialize($data),
- 'Cached' => adodb_mktime(),
- );
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->setCache('master:StructureTree', serialize($data));
+ }
+ else {
+ $this->Application->setDBCache('StructureTree', serialize($data));
+ }
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'Cache', 'REPLACE');
-
return $data;
}
+ function getTemplateMapping()
+ {
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->getCache('master:template_mapping', false);
+ }
+ else {
+ $data = $this->Application->getDBCache('template_mapping');
+ }
+
+ if ($data) {
+ return unserialize($data);
+ }
+
+ $sql = 'SELECT
+ IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS SrcTemplate,
+ LOWER(
+ IF(
+ c.SymLinkCategoryId IS NOT NULL,
+ (SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc WHERE cc.CategoryId = c.SymLinkCategoryId),
+ c.NamedParentPath
+ )
+ ) AS DstTemplate,
+ c.UseExternalUrl, c.ExternalUrl
+ FROM ' . TABLE_PREFIX . 'Category AS c
+ WHERE c.Status = ' . STATUS_ACTIVE;
+ $pages = $this->Conn->Query($sql, 'SrcTemplate');
+
+ $mapping = Array ();
+ $base_url = $this->Application->BaseURL();
+
+ foreach ($pages as $src_template => $page) {
+ // process external url, before placing in cache
+ if ($page['UseExternalUrl']) {
+ $external_url = $page['ExternalUrl'];
+
+ if (!preg_match('/^(.*?):\/\/(.*)$/', $external_url)) {
+ // url without protocol will be relative url to our site
+ $external_url = $base_url . $external_url;
+ }
+
+ $dst_template = 'external:' . $external_url;
+ }
+ else {
+ $dst_template = preg_replace('/^Content\//i', '', $page['DstTemplate']);
+ }
+
+ $mapping[$src_template] = $dst_template;
+ }
+
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->setCache('master:template_mapping', serialize($mapping));
+ }
+ else {
+ $this->Application->setDBCache('template_mapping', serialize($mapping));
+ }
+
+ return $mapping;
+ }
+
/**
* Returns category structure as field option list
*
@@ -457,8 +524,9 @@
*/
function getStructureTreeAsOptions()
{
- if (defined('IS_INSTALL') && IS_INSTALL) {
- // no need to create category structure during install, because it's not used there
+ if ((defined('IS_INSTALL') && IS_INSTALL) || !$this->Application->isAdmin) {
+ // no need to create category structure during install
+ // OR on Front-End, because it's not used there
return Array ();
}
Index: core/units/helpers/count_helper.php
===================================================================
--- core/units/helpers/count_helper.php (revision 13152)
+++ core/units/helpers/count_helper.php (working copy)
@@ -16,17 +16,6 @@
class kCountHelper extends kHelper {
- function kCountHelper()
- {
- parent::kHelper();
-
- // reset expired counts
- $sql = 'UPDATE '.TABLE_PREFIX.'Counters
- SET CountValue = NULL
- WHERE (LifeTime > 0) AND (LastCounted < '.adodb_mktime().' - LifeTime)';
- $this->Conn->Query($sql);
- }
-
/**
* Returns counter value
*
@@ -38,6 +27,8 @@
*/
function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false)
{
+ $this->resetExpiredCounters();
+
$clone_counter = false;
$query_name = isset($query_name) ? $query_name : rtrim($name.'-'.implode('-', array_values($params)), '-');
$sql = 'SELECT *
@@ -107,6 +98,20 @@
$this->Conn->Query($sql);
}
+ function resetExpiredCounters()
+ {
+ static $reset = false;
+
+ if (!$reset) {
+ // reset expired counts
+ $sql = 'UPDATE '.TABLE_PREFIX.'Counters
+ SET CountValue = NULL
+ WHERE (LifeTime > 0) AND (LastCounted < '.adodb_mktime().' - LifeTime)';
+ $this->Conn->Query($sql);
+ $reset = true;
+ }
+ }
+
/**
* Counts items (of specific type) in category & subcategories
*
@@ -206,25 +211,42 @@
*/
function CategoryCount($today = false)
{
- $table_name = $this->Application->getUnitOption('c', 'TableName');
+ $cache_key = 'category_count[%CSerial%]';
- $sql = 'SELECT COUNT(*)
- FROM '.$table_name.' c
- INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId';
+ if ($today) {
+ $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y'));
+ $cache_key .= ':date=' . $today_date;
+ }
- list ($view_perm, $view_filter) = $this->GetPermissionClause('c', 'perm_cache');
- $where_clauses = Array (
- $view_filter, 'perm_cache.PermId = '.$view_perm, 'c.Status = '.STATUS_ACTIVE,
- );
+ $count = $this->Application->getCache($cache_key);
- if ($today) {
- $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y'));
- $where_clauses[] = 'c.CreatedOn >= '.$today_date;
+ if ($count === false) {
+ $sql = 'SELECT COUNT(*)
+ FROM ' . $this->Application->getUnitOption('c', 'TableName') . ' c
+ INNER JOIN ' . TABLE_PREFIX . 'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId';
+
+ list ($view_perm, $view_filter) = $this->GetPermissionClause('c', 'perm_cache');
+
+ $where_clauses = Array (
+ $view_filter,
+ 'perm_cache.PermId = ' . $view_perm,
+ 'c.Status = ' . STATUS_ACTIVE,
+ );
+
+ if ($today) {
+ $where_clauses[] = 'c.CreatedOn >= ' . $today_date;
+ }
+
+ $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')';
+
+ $count = $this->Conn->GetOne($sql);
+
+ if ($count !== false) {
+ $this->Application->setCache($cache_key, $count);
+ }
}
- $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')';
-
- return $this->Conn->GetOne($sql);
+ return $count;
}
/**
@@ -236,17 +258,24 @@
*/
function GetPermissionClause($prefix, $table_alias)
{
- $view_perm = $this->Application->getCache(__CLASS__ . __FUNCTION__, $prefix);
- if ($view_perm === false) {
- $sql = 'SELECT PermissionConfigId
+ $permissions_ids = $this->Application->getCache(__CLASS__ . '::' . __FUNCTION__);
+
+ if ($permissions_ids === false) {
+ $this->Conn->nextQueryCachable = true;
+
+ $sql = 'SELECT PermissionConfigId, PermissionName
FROM '.TABLE_PREFIX.'PermissionConfig
- WHERE PermissionName = "'.$this->Application->getUnitOption($prefix, 'PermItemPrefix').'.VIEW"';
- $view_perm = $this->Conn->GetOne($sql);
+ WHERE PermissionName LIKE "%.VIEW"';
+ $permissions_ids = $this->Conn->GetCol($sql, 'PermissionName');
- $this->Application->setCache(__CLASS__ . __FUNCTION__, $prefix, $view_perm);
+ $this->Application->setCache(__CLASS__ . '::' . __FUNCTION__, $permissions_ids);
}
+ $permission_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix');
+ $view_perm = $permissions_ids[$permission_prefix . '.VIEW'];
+
$groups = explode(',', $this->Application->RecallVar('UserGroups'));
+
foreach ($groups as $group) {
$view_filters[] = 'FIND_IN_SET('.$group.', '.$table_alias.'.acl)';
}
Index: core/units/helpers/language_import_helper.php
===================================================================
--- core/units/helpers/language_import_helper.php (revision 13152)
+++ core/units/helpers/language_import_helper.php (working copy)
@@ -103,6 +103,13 @@
*/
var $_latestVersion = 2;
+ /**
+ * Prefix-based serial numbers, that should be changed after import is finished
+ *
+ * @var Array
+ */
+ var $changedPrefixes = Array ();
+
function LanguageImportHelper()
{
parent::kHelper();
@@ -166,7 +173,12 @@
}
$this->_initImportTables(true);
+ $this->changedPrefixes = array_unique($this->changedPrefixes);
+ foreach ($this->changedPrefixes as $prefix) {
+ $this->Application->incrementCacheSerial($prefix);
+ }
+
if ($this->_debugMode) {
$this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (getmicrotime() - $start_time));
}
@@ -331,6 +343,9 @@
FROM ' . $this->_tables[$prefix] . '
WHERE ' . $unique_field . ' IN (' . implode(',', $to_insert) . ')';
$this->Conn->Query($sql);
+
+ // new records were added
+ $this->changedPrefixes[] = $prefix;
}
// perform update for records, that are present in live table
@@ -370,6 +385,11 @@
}
$this->Conn->Query($sql);
+
+ if ($this->Conn->getAffectedRows() > 0) {
+ // existing records were updated
+ $this->changedPrefixes[] = $prefix;
+ }
}
}
Index: core/units/helpers/menu_helper.php
===================================================================
--- core/units/helpers/menu_helper.php (revision 13152)
+++ core/units/helpers/menu_helper.php (working copy)
@@ -115,24 +115,41 @@
if (!$root_cat) {
$root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
+ $cache_key = 'parent_paths[%CIDSerial:' . $root_cat . '%]';
+ $root_path = $this->Application->getCache($cache_key);
- $sql = 'SELECT ParentPath
- FROM ' . TABLE_PREFIX . 'Category
- WHERE CategoryId = ' . $root_cat;
- $root_path = $this->Conn->GetOne($sql);
+ if ($root_path === false) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT ParentPath
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $root_cat;
+ $root_path = $this->Conn->GetOne($sql);
+ $this->Application->setCache($cache_key, $root_path);
+ }
}
if (!$this->Menu) {
- $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
- if ($menu && $menu['Cached'] > 0) {
- $menu = unserialize($menu['Data']);
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $menu = $this->Application->getCache('master:cms_menu', false);
+ }
+ else {
+ $menu = $this->Application->getDBCache('cms_menu');
+ }
+
+ if ($menu) {
+ $menu = unserialize($menu);
$this->parentPaths = $menu['parentPaths'];
}
else {
$menu = $this->_altBuildMenuStructure(Array ('CategoryId' => $root_cat, 'ParentPath' => $root_path));
$menu['parentPaths'] = $this->parentPaths;
- $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->setCache('master:cms_menu', serialize($menu));
+ }
+ else {
+ $this->Application->setDBCache('cms_menu', serialize($menu));
+ }
}
unset($menu['parentPaths']);
Index: core/units/helpers/mod_rewrite_helper.php
===================================================================
--- core/units/helpers/mod_rewrite_helper.php (revision 13159)
+++ core/units/helpers/mod_rewrite_helper.php (working copy)
@@ -65,16 +65,12 @@
}
$restored = false;
- $sql = 'SELECT Data, Cached
- FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "mod_rw_' . md5($url) . '"';
- $cache = $this->Conn->GetRow($sql);
- if (false && $cache && $cache['Cached'] > 0) {
- // not used for now
- $cache = unserialize($cache['Data']);
- $vars = $cache['vars'];
- $passed = $cache['passed'];
+ $cached = $this->_getCachedUrl($url);
+
+ if ($cached !== false) {
+ $vars = $cached['vars'];
+ $passed = $cached['passed'];
$restored = true;
}
else {
@@ -82,15 +78,8 @@
$passed = $vars['pass']; // also used in bottom of this method
unset($vars['pass']);
- $cache = Array ('vars' => $vars, 'passed' => $passed);
+ $this->_setCachedUrl($url, Array ('vars' => $vars, 'passed' => $passed));
- $fields_hash = Array (
- 'VarName' => 'mod_rw_' . md5($url),
- 'Data' => serialize($cache),
- 'Cached' => adodb_mktime(),
- );
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
-
if (array_key_exists('t', $this->HTTPQuery->Post) && $this->HTTPQuery->Post['t']) {
// template from POST overrides template from URL.
$vars['t'] = $this->HTTPQuery->Post['t'];
@@ -111,19 +100,90 @@
$this->HTTPQuery->finalizeParsing($passed);
}
- function parseRewriteURL($url)
+ function _getCachedUrl($url)
{
- $sql = 'SELECT Data, Cached
- FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "mod_rw_' . md5($url) . '"';
- $vars = $this->Conn->GetRow($sql);
+ if (!$url) {
+ return false;
+ }
- if (false && $vars && $vars['Cached'] > 0) {
- // not used for now
- $vars = unserialize($menu['Data']);
- return $vars;
+ $sql = 'SELECT *
+ FROM ' . TABLE_PREFIX . 'CachedUrls
+ WHERE Hash = ' . crc32($url);
+ $data = $this->Conn->GetRow($sql);
+
+ if ($data) {
+ $lifetime = (int)$data['LifeTime']; // in seconds
+ if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) {
+ // delete expired
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls
+ WHERE UrlId = ' . $data['UrlId'];
+ $this->Conn->Query($sql);
+
+ return false;
+ }
+
+ return unserialize($data['ParsedVars']);
}
+ return false;
+ }
+
+ function _setCachedUrl($url, $data)
+ {
+ if (!$url) {
+ return ;
+ }
+
+ $vars = $data['vars'];
+ $passed = $data['passed'];
+ sort($passed);
+
+ // get expiration
+ if ($vars['m_cat_id'] > 0) {
+ $sql = 'SELECT PageExpiration
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $vars['m_cat_id'];
+ $expiration = $this->Conn->GetOne($sql);
+ }
+
+ // get prefixes
+ $prefixes = Array ();
+ $m_index = array_search('m', $passed);
+
+ if ($m_index !== false) {
+ unset($passed[$m_index]);
+
+ if ($vars['m_cat_id'] > 0) {
+ $prefixes[] = 'c:' . $vars['m_cat_id'];
+ }
+
+ $prefixes[] = 'lang:' . $vars['m_lang'];
+ $prefixes[] = 'theme:' . $vars['m_theme'];
+ }
+
+ foreach ($passed as $prefix) {
+ if (array_key_exists($prefix . '_id', $vars) && is_numeric($vars[$prefix . '_id'])) {
+ $prefixes[] = $prefix . ':' . $vars[$prefix . '_id'];
+ }
+ else {
+ $prefixes[] = $prefix;
+ }
+ }
+
+ $fields_hash = Array (
+ 'Url' => $url,
+ 'Hash' => crc32($url),
+ 'Prefixes' => $prefixes ? '|' . implode('|', $prefixes) . '|' : '',
+ 'ParsedVars' => serialize($data),
+ 'Cached' => adodb_mktime(),
+ 'LifeTime' => isset($expiration) && is_numeric($expiration) ? $expiration : -1
+ );
+
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'CachedUrls');
+ }
+
+ function parseRewriteURL($url)
+ {
$vars = Array ('pass' => Array ('m'));
$url_parts = $url ? explode('/', trim(mb_strtolower($url, 'UTF-8'), '/')) : Array ();
@@ -329,14 +389,14 @@
// add language
$default_language_id = $this->Application->GetDefaultLanguageId();
if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $default_language_id)) {
- $language_name = $this->Application->getCache('language_names', $processed_params['m_lang']);
+ $language_name = $this->Application->getCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]');
if ($language_name === false) {
$sql = 'SELECT PackName
FROM ' . TABLE_PREFIX . 'Language
WHERE LanguageId = ' . $processed_params['m_lang'];
$language_name = $this->Conn->GetOne($sql);
- $this->Application->setCache('language_names', $processed_params['m_lang'], $language_name);
+ $this->Application->setCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]', $language_name);
}
$ret .= $language_name . '/';
@@ -345,14 +405,14 @@
// add theme
$default_theme_id = $this->Application->GetDefaultThemeId(true);
if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $default_theme_id)) {
- $theme_name = $this->Application->getCache('theme_names', $processed_params['m_theme']);
+ $theme_name = $this->Application->getCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]');
if ($theme_name === false) {
$sql = 'SELECT Name
FROM ' . TABLE_PREFIX . 'Theme
WHERE ThemeId = ' . $processed_params['m_theme'];
$theme_name = $this->Conn->GetOne($sql);
- $this->Application->setCache('theme_names', $processed_params['m_theme'], $theme_name);
+ $this->Application->setCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]', $theme_name);
}
@@ -366,7 +426,7 @@
// add category
if ($processed_params['m_cat_id'] > 0 && $params['pass_category']) {
- $category_filename = $this->Application->getFilename('c', $processed_params['m_cat_id']);
+ $category_filename = $this->Application->getCategoryCache($processed_params['m_cat_id'], 'filenames');
preg_match('/^Content\/(.*)/i', $category_filename, $regs);
@@ -401,7 +461,7 @@
}
$template = array_key_exists('t', $params) ? $params['t'] : false;
- $category_template = ($processed_params['m_cat_id'] > 0) && $params['pass_category'] ? $this->Application->getCache('category_designs', $processed_params['m_cat_id']) : '';
+ $category_template = ($processed_params['m_cat_id'] > 0) && $params['pass_category'] ? $this->Application->getCategoryCache($processed_params['m_cat_id'], 'category_designs') : '';
if ((strtolower($template) == '__default__') && ($processed_params['m_cat_id'] == 0)) {
// for "Home" category set template to index when not set
@@ -696,13 +756,10 @@
}
if ($processed_params[$prefix_special . '_id']) {
- // this allows to fill 3 cache records with one query (see this method for details)
$category_id = array_key_exists('m_cat_id', $params) ? $params['m_cat_id'] : $this->Application->GetVar('m_cat_id');
- $category_filename = $this->Application->getFilename('c', $category_id);
// if template is also item template of category, then remove template
$template = array_key_exists('t', $params) ? $params['t'] : false;
-
$item_template = $this->GetItemTemplate($category_id, $prefix);
if ($template == $item_template || strtolower($template) == '__default__') {
@@ -887,9 +944,10 @@
*/
function GetItemTemplate($category, $module_prefix)
{
- $cache_key = serialize($category) . '_' . $module_prefix;
+ $category_id = is_array($category) ? $category['CategoryId'] : $category;
+ $cache_key = __CLASS__ . '::' . __FUNCTION__ . '[%CIDSerial:' . $category_id . '%]:' . $module_prefix;
- $cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $cache_key);
+ $cached_value = $this->Application->getCache($cache_key);
if ($cached_value !== false) {
return $cached_value;
}
@@ -938,7 +996,7 @@
$item_template = $this->_templateAliases[$item_template];
}
- $this->Application->setCache(__CLASS__ . __FUNCTION__, $cache_key, $item_template);
+ $this->Application->setCache($cache_key, $item_template);
return $item_template;
}
@@ -973,7 +1031,9 @@
*/
function getItemTemplateCustomField($module_prefix)
{
- $cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $module_prefix);
+ $cache_key = __CLASS__ . '::' . __FUNCTION__ . '[%CfSerial%]:' . $module_prefix;
+ $cached_value = $this->Application->getCache($cache_key);
+
if ($cached_value !== false) {
return $cached_value;
}
@@ -983,7 +1043,7 @@
WHERE FieldName = ' . $this->Conn->qstr($module_prefix . '_ItemTemplate');
$item_template_field_id = $this->Conn->GetOne($sql);
- $this->Application->setCache(__CLASS__ . __FUNCTION__, $module_prefix, $item_template_field_id);
+ $this->Application->setCache($cache_key, $item_template_field_id);
return $item_template_field_id;
}
Index: core/units/helpers/permissions_helper.php
===================================================================
--- core/units/helpers/permissions_helper.php (revision 13152)
+++ core/units/helpers/permissions_helper.php (working copy)
@@ -536,12 +536,6 @@
$cat_id = $this->Application->GetVar('m_cat_id');
}
- $cache_key = $name.'|'.$type.'|'.$cat_id;
- $perm_value = $this->Application->getCache('permissions', $cache_key);
- if ($perm_value !== false) {
- return $perm_value;
- }
-
// perm cache is build only based on records in db, that's why if permission is not explicitly denied, then
// that (perm cache creator) code thinks that it is allowed & adds corresponding record and code below will
// return incorrect results
@@ -557,6 +551,13 @@
array_push($groups, $this->Application->ConfigValue('User_LoggedInGroup') );
}
+ $cache_key = $name . '|' . $type . '|' . $cat_id . '|' . implode(',', $groups);
+ $perm_value = $this->Application->getCache('permissions[%' . ($type == 1 ? 'G' : 'C') . 'PermSerial%]:' . $cache_key);
+
+ if ($perm_value !== false) {
+ return $perm_value;
+ }
+
if (preg_match('/(.*)\.VIEW$/', $name) && ($type == 0)) {
// cached view permission of category: begin
if (strpos($cat_id, '|') !== false) {
@@ -580,7 +581,7 @@
$sql .= ' AND ('.implode(' OR ', $view_filters).')';
$perm_value = $this->Conn->GetOne($sql) ? 1 : 0;
- $this->Application->setCache('permissions', $cache_key, $perm_value);
+ $this->Application->setCache('permissions[%CPermSerial%]:' . $cache_key, $perm_value);
return $perm_value;
// cached view permission of category: end
}
@@ -621,7 +622,8 @@
}
}
- $this->Application->setCache('permissions', $cache_key, $perm_value);
+ $this->Application->setCache('permissions[%' . ($type == 1 ? 'G' : 'C') . 'PermSerial%]:' . $cache_key, $perm_value);
+
return $perm_value;
}
Index: core/units/helpers/sections_helper.php
===================================================================
--- core/units/helpers/sections_helper.php (revision 13152)
+++ core/units/helpers/sections_helper.php (working copy)
@@ -47,9 +47,13 @@
*/
function BuildTree()
{
- if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:sections_parsed'))) {
- $data = $this->Conn->GetOne('SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $data = $this->Application->getCache('master:sections_parsed', false);
}
+ else {
+ $data = $this->Application->getDBCache('sections_parsed');
+ }
+
if ($data) {
$this->Tree = unserialize($data);
return ;
@@ -174,12 +178,12 @@
$this->Application->HandleEvent( new kEvent('adm:OnAfterBuildTree') );
- if (isset($this->Application->Memcached)) {
- $this->Application->Memcached->set('master:sections_parsed',serialize($this->Tree), 0, 0);
- return;
+ if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ $this->Application->setCache('master:sections_parsed', serialize($this->Tree));
}
-
- $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("sections_parsed", '.$this->Conn->qstr(serialize($this->Tree)).', '.adodb_mktime().')');
+ else {
+ $this->Application->setDBCache('sections_parsed', serialize($this->Tree));
+ }
}
function _processPrefixSections($prefix)
Index: core/units/helpers/skin_helper.php
===================================================================
--- core/units/helpers/skin_helper.php (revision 13152)
+++ core/units/helpers/skin_helper.php (working copy)
@@ -98,6 +98,9 @@
WHERE ' . $object->IDField . ' = ' . $object->GetID();
$this->Conn->Query($sql);
+ $this->Application->incrementCacheSerial('skin');
+ $this->Application->incrementCacheSerial('skin', $object->GetID());
+
return $compile_ts;
}
@@ -108,16 +111,20 @@
*/
function _getStyleInfo()
{
- static $style = null;
+ $cache_key = 'primary_skin_info[%SkinSerial%]';
+ $ret = $this->Application->getCache($cache_key);
- if (!isset($style)) {
+ if ($ret === false) {
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Skins
WHERE IsPrimary = 1';
- $style = $this->Conn->GetRow($sql);
+ $ret = $this->Conn->GetRow($sql);
+
+ $this->Application->setCache($cache_key, $ret);
}
- return $style;
+ return $ret;
}
/**
Index: core/units/helpers/themes_helper.php
===================================================================
--- core/units/helpers/themes_helper.php (revision 13152)
+++ core/units/helpers/themes_helper.php (working copy)
@@ -381,6 +381,8 @@
$theme_ids = $this->Conn->GetCol($sql);
$this->deleteThemes($theme_ids);
+ $this->Application->incrementCacheSerial('theme');
+ $this->Application->incrementCacheSerial('theme-file');
}
/**
Index: core/units/languages/languages_event_handler.php
===================================================================
--- core/units/languages/languages_event_handler.php (revision 13152)
+++ core/units/languages/languages_event_handler.php (working copy)
@@ -31,14 +31,28 @@
'OnExportProgress' => Array('self' => 'advanced:export'),
'OnReflectMultiLingualFields' => Array ('self' => 'view'),
'OnSynchronizeLanguages' => Array ('self' => 'edit'),
-
- 'OnItemBuild' => Array('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
+ * Permission check override
+ *
+ * @param kEvent $event
+ */
+ function CheckPermission(&$event)
+ {
+ if ($event->Name == 'OnItemBuild') {
+ // check permission without using $event->getSection(),
+ // so first cache rebuild won't lead to "ldefault_Name" field being used
+ return true;
+ }
+
+ return parent::CheckPermission($event);
+ }
+
+ /**
* [HOOK] Updates table structure on new language adding/removing language
*
* @param kEvent $event
Index: core/units/languages/languages_item.php
===================================================================
--- core/units/languages/languages_item.php (revision 13152)
+++ core/units/languages/languages_item.php (working copy)
@@ -65,7 +65,7 @@
$default = true;
}
- $res = parent::Load($id, $id_field_name);
+ $res = parent::Load($id, $id_field_name, true);
if ($default) {
if (!$res) {
Index: core/units/permissions/permissions_tag_processor.php
===================================================================
--- core/units/permissions/permissions_tag_processor.php (revision 13152)
+++ core/units/permissions/permissions_tag_processor.php (working copy)
@@ -181,7 +181,15 @@
function CategoryPath($params)
{
$category_id = $params['cat_id'];
- $category_path = $this->Application->getCache('category_paths', $category_id);
+ $cache_key = 'category_paths[%CIDSerial:' . $category_id . '%]';
+
+ if ("$category_id" == '0') {
+ // home category name is phrase AND phrase name is defined in configuration
+ $cache_key .= '[%PhrasesSerial%][%ConfSerial%]';
+ }
+
+ $category_path = $this->Application->getCache($cache_key);
+
if ($category_path === false) {
// not chached
if ($category_id > 0) {
@@ -198,8 +206,10 @@
else {
$category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
}
- $this->Application->setCache('category_paths', $category_id, $category_path);
+
+ $this->Application->setCache($cache_key, $category_path);
}
+
return $category_path;
}
Index: core/units/statistics/statistics_tag_processor.php
===================================================================
--- core/units/statistics/statistics_tag_processor.php (revision 13152)
+++ core/units/statistics/statistics_tag_processor.php (working copy)
@@ -208,7 +208,9 @@
function CountPending($params)
{
$prefix = $params['prefix'];
- $value = $this->Application->getCache('statistics.pending', $prefix);
+ $cache_key = 'statistics.pending[%' . $this->Application->incrementCacheSerial($prefix, null, false) . '%]';
+ $value = $this->Application->getCache($cache_key);
+
if ($value === false) {
$statistics_info = $this->Application->getUnitOption($prefix.'.pending', 'StatisticsInfo');
if (!$statistics_info) {
@@ -217,12 +219,14 @@
$table = $this->Application->getUnitOption($prefix, 'TableName');
$status_field = array_shift( $this->Application->getUnitOption($prefix, 'StatusField') );
+ $this->Conn->nextQueryCachable = true;
$sql = 'SELECT COUNT(*)
FROM '.$table.'
WHERE '.$status_field.' = '.$statistics_info['status'];
$value = $this->Conn->GetOne($sql);
- $this->Application->setCache('statistics.pending', $prefix, $value);
+ $this->Application->setCache($cache_key, $value);
}
+
return $value;
}
Index: core/units/structure/structure_config.php
===================================================================
--- core/units/structure/structure_config.php (revision 13166)
+++ core/units/structure/structure_config.php (working copy)
@@ -77,14 +77,13 @@
'PermItemPrefix' => 'CATEGORY',
'PermSection' => Array('main' => 'CATEGORY:in-portal:structure', 'email' => 'in-portal:configemail'),
- 'ListSQLs' => Array( ''=> ' SELECT %1$s.* %2$s
- FROM %1$s
- LEFT JOIN '.TABLE_PREFIX.'PermCache ON '.TABLE_PREFIX.'PermCache.CategoryId = %1$s.CategoryId'),
+ 'ListSQLs' => Array (
+ '' => ' SELECT %1$s.* %2$s
+ FROM %1$s
+ LEFT JOIN '.TABLE_PREFIX.'PermCache ON '.TABLE_PREFIX.'PermCache.CategoryId = %1$s.CategoryId',
+ '-virtual' => 'SELECT %1$s.* %2$s FROM %1$s',
+ ),
- 'ItemSQLs' => Array( ''=> ' SELECT %1$s.* %2$s
- FROM %1$s
- LEFT JOIN '.TABLE_PREFIX.'PermCache ON '.TABLE_PREFIX.'PermCache.CategoryId = %1$s.CategoryId'),
-
'SubItems' => Array('content'),
'ListSortings' => Array(
@@ -97,7 +96,8 @@
'CalculatedFields' => Array(
'' => Array(
'CurrentSort' => "REPLACE(ParentPath, CONCAT('|', ".'%1$s'.".CategoryId, '|'), '')",
- )
+ ),
+ '-virtual' => Array (),
),
'Fields' => Array (
@@ -168,6 +168,19 @@
'FormSubmittedTemplate' => Array('type' => 'string', 'default' => null),
'FriendlyURL' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
'ThemeId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
+
+ 'EnablePageCache' => Array (
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 0
+ ),
+ 'OverridePageCacheKey' => Array (
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 0
+ ),
+ 'PageCacheKey' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''),
+ 'PageExpiration' => Array ('type' => 'int', 'default' => NULL),
),
'VirtualFields' => Array(
Index: core/units/themes/theme_item.php
===================================================================
--- core/units/themes/theme_item.php (revision 13152)
+++ core/units/themes/theme_item.php (working copy)
@@ -25,7 +25,7 @@
$default = true;
}
- $res = parent::Load($id, $id_field_name);
+ $res = parent::Load($id, $id_field_name, true);
if ($default) {
if (!$res) {
@@ -36,6 +36,7 @@
$this->Application->SetVar('theme.current_id', $this->GetID() );
$this->Application->SetVar('m_theme', $this->GetID() );
}
+
return $res;
}
}
\ No newline at end of file
Index: core/units/themes/themes_eh.php
===================================================================
--- core/units/themes/themes_eh.php (revision 13152)
+++ core/units/themes/themes_eh.php (working copy)
@@ -24,7 +24,6 @@
{
parent::mapPermissions();
$permissions = Array(
- 'OnItemBuild' => Array('self' => true),
'OnChangeTheme' => Array('self' => true),
);
@@ -32,6 +31,22 @@
}
/**
+ * Permission check override
+ *
+ * @param kEvent $event
+ */
+ function CheckPermission(&$event)
+ {
+ if ($event->Name == 'OnItemBuild') {
+ // check permission without using $event->getSection(),
+ // so first cache rebuild won't lead to "ldefault_Name" field being used
+ return true;
+ }
+
+ return parent::CheckPermission($event);
+ }
+
+ /**
* Allows to set selected theme as primary
*
* @param kEvent $event
Index: core/units/users/users_event_handler.php
===================================================================
--- core/units/users/users_event_handler.php (revision 13152)
+++ core/units/users/users_event_handler.php (working copy)
@@ -1925,4 +1925,26 @@
$object->setRequired($required_field);
}
}
+
+ /**
+ * Load item if id is available
+ *
+ * @param kEvent $event
+ */
+ function LoadItem(&$event)
+ {
+ $id = $this->getPassedID($event);
+
+ if ($id < 0) {
+ // when root, guest and so on
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $object->Clear($id);
+ return ;
+ }
+
+ parent::LoadItem($event);
+ }
}
Index: tools/show_cache.php
===================================================================
--- tools/show_cache.php (revision 13152)
+++ tools/show_cache.php (working copy)
@@ -33,10 +33,7 @@
$show_var = $application->GetVar('show_var');
if ($show_var) {
- $sql = 'SELECT Data
- FROM ' . TABLE_PREFIX . 'Cache
- WHERE VarName = "' . $show_var . '"';
- $var_data = $application->Conn->GetOne($sql);
+ $var_data = $application->getDBCache($show_var);
if ($var_data === false) {
echo 'Not Found';
@@ -47,7 +44,7 @@
}
else {
$sql = 'SELECT VarName
- FROM ' . TABLE_PREFIX . 'Cache';
+ FROM ' . TABLE_PREFIX . 'Cache';
$var_names = $application->Conn->GetCol($sql);
memcache_themes.patch [^] (24,485 bytes) 2010-02-24 12:04
[Show Content]
Index: in-commerce/designs/section.tpl
===================================================================
--- in-commerce/designs/section.tpl (revision 13160)
+++ in-commerce/designs/section.tpl (working copy)
@@ -24,12 +24,18 @@
<div class="movable-element">
<inp2:m_RenderElement name="platform/elements/side_boxes/search.elm" design="blue_box"/>
</div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-commerce/elements/side_boxes/credit_cards.elm" design="blue_box"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-commerce/elements/side_boxes/pick_products.elm" design="blue_box" data_exists="1"/>
- </div>
+
+ <inp2:m_Cache>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-commerce/elements/side_boxes/credit_cards.elm" design="blue_box"/>
+ </div>
+ </inp2:m_Cache>
+
+ <inp2:m_Cache key="prefix:p;currency;guest_only">
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-commerce/elements/side_boxes/pick_products.elm" design="blue_box" data_exists="1"/>
+ </div>
+ </inp2:m_Cache>
</div>
</inp2:m_DefineElement>
<!--## /SIDE-BAR ELEMENT ##-->
@@ -42,15 +48,17 @@
</div>
<!--## IF IN-COMMERCE HOME PAGE ##-->
<inp2:m_if check="p_IsModuleHome">
- <div class="movable-element">
- <inp2:m_include template="in-commerce/elements/content_boxes/featured_products.elm"/>
- </div>
- <div class="movable-element">
- <inp2:m_include template="in-commerce/elements/content_boxes/new_products.elm"/>
- </div>
- <div class="movable-element">
- <inp2:m_include template="in-commerce/elements/content_boxes/pick_products.elm"/>
- </div>
+ <inp2:m_Cache key="prefix:p;currency;guest_only">
+ <div class="movable-element">
+ <inp2:m_include template="in-commerce/elements/content_boxes/featured_products.elm"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_include template="in-commerce/elements/content_boxes/new_products.elm"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_include template="in-commerce/elements/content_boxes/pick_products.elm"/>
+ </div>
+ </inp2:m_Cache>
<inp2:m_else/>
<!--## /IF IN-COMMERCE HOME PAGE ##-->
@@ -58,39 +66,43 @@
<inp2:m_include template="platform/elements/content_boxes/sub_categories.elm"/>
</div>
- <div class="movable-element">
- <!-- Category Products List -->
- <inp2:m_RenderElement design="content_box" block_no_data="no_products">
- <inp2:p_InitList list_name="products_in_category" main_list="1"/>
+ <inp2:m_Cache key="prefix:p;currency;guest_only">
+ <div class="movable-element">
+ <!-- Category Products List -->
+ <inp2:m_RenderElement design="content_box" block_no_data="no_products">
+ <inp2:p_InitList list_name="products_in_category" main_list="1"/>
- <inp2:m_Capture to_var="header">
- <inp2:m_phrase name="lu_title_Products"/> (<inp2:p_TotalRecords list_name="products_in_category"/>)
- </inp2:m_Capture>
+ <inp2:m_Capture to_var="header">
+ <inp2:m_phrase name="lu_title_Products"/> (<inp2:p_TotalRecords list_name="products_in_category"/>)
+ </inp2:m_Capture>
- <inp2:m_include template="in-commerce/elements/sorting.elm" list_name="products_in_category"/>
+ <inp2:m_include template="in-commerce/elements/sorting.elm" list_name="products_in_category"/>
- <inp2:m_include template="in-commerce/elements/products.elm"/>
+ <inp2:m_include template="in-commerce/elements/products.elm"/>
- <table class="fullwidth table-border">
- <inp2:p_ListProducts list_name="products_in_category" render_as="product_element"/>
- </table>
+ <table class="fullwidth table-border">
+ <inp2:p_ListProducts list_name="products_in_category" render_as="product_element"/>
+ </table>
- <inp2:m_include template="platform/elements/pagination.elm" prefix="p" list_name="products_in_category"/>
- </inp2:m_RenderElement>
- <!-- // Category Products List -->
- </div>
+ <inp2:m_include template="platform/elements/pagination.elm" prefix="p" list_name="products_in_category"/>
+ </inp2:m_RenderElement>
+ <!-- // Category Products List -->
+ </div>
+ </inp2:m_Cache>
<!--## RELATED CATEGORIES ##-->
<!--##
- <div class="movable-element">
- <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
- <inp2:m_Capture to_var="header">
- <inp2:m_Phrase label="lu_title_RelatedCategories"/>
- </inp2:m_Capture>
+ <inp2:m_Cache key="prefix:c">
+ <div class="movable-element">
+ <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
+ <inp2:m_Capture to_var="header">
+ <inp2:m_Phrase label="lu_title_RelatedCategories"/>
+ </inp2:m_Capture>
- <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
- </inp2:m_RenderElement>
- </div>
+ <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
+ </inp2:m_RenderElement>
+ </div>
+ </inp2:m_Cache>
##-->
<!--## // RELATED CATEGORIES ##-->
Index: in-commerce/elements/currency_picker.elm.tpl
===================================================================
--- in-commerce/elements/currency_picker.elm.tpl (revision 13152)
+++ in-commerce/elements/currency_picker.elm.tpl (working copy)
@@ -6,10 +6,14 @@
<inp2:m_Phrase label="lu_YourCurrency"/>:
<input type="hidden" name="events[curr][OnChangeCurrency]" value="" />
<select name="curr_iso" class="input-select" onchange="document.getElementById('cur_form').submit()">
- <inp2:m_DefineElement name="currency">
- <option value="<inp2:Field name="ISO"/>" <inp2:m_if check="SelectedCurrency">selected="selected"</inp2:m_if> ><inp2:Field name="ISO"/></option>
- </inp2:m_DefineElement>
- <inp2:curr_ListCurrencies render_as="currency" no_table="1"/>
+
+ <inp2:m_Cache key="prefix:curr;currency;skip_var:t,page,per_page,sort_by">
+ <inp2:m_DefineElement name="currency">
+ <option value="<inp2:Field name='ISO'/>"<inp2:m_if check="SelectedCurrency"> selected="selected"</inp2:m_if>><inp2:Field name="ISO"/></option>
+ </inp2:m_DefineElement>
+
+ <inp2:curr_ListCurrencies render_as="currency" no_table="1"/>
+ </inp2:m_Cache>
</select>
</form>
</td>
\ No newline at end of file
Index: in-commerce/elements/side_boxes/categories.elm.tpl
===================================================================
--- in-commerce/elements/side_boxes/categories.elm.tpl (revision 13152)
+++ in-commerce/elements/side_boxes/categories.elm.tpl (working copy)
@@ -29,22 +29,25 @@
<inp2:m_Phrase label="lu_title_Categories"/>
</inp2:m_Capture>
-<table width="100%">
- <inp2:m_DefineElement name="category_elem">
- <td class="top-category-padding">
- <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/menu-li-1-level.gif" alt="" width="6" height="5" border="0" /><br />
- </td>
- <td valign="top">
- <inp2:m_if check="IsCurrent">
- <strong><inp2:Field name="Name"/></strong><br />
- <inp2:m_else/>
- <a href="<inp2:CategoryLink template="__default__" m_cat_page="1"/>" class="top-category"><inp2:Field name="Name"/></a><br />
- </inp2:m_if>
- <table>
- <inp2:ListCategories requery="1" render_as="subcategory_elem" more_link_render_as="more_link_elem" max_items="4" no_table="1"/>
- </table>
- <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="5" border="0" /><br />
- </td>
- </inp2:m_DefineElement>
- <inp2:c_ListCategories render_as="category_elem" per_page="-1" columns="1" direction="H" parent_cat_id="Root" module="In-Commerce"/>
-</table>
+<inp2:m_Cache key="prefix:c;skip_var:t,page,per_page,sort_by">
+ <table width="100%">
+ <inp2:m_DefineElement name="category_elem">
+ <td class="top-category-padding">
+ <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/menu-li-1-level.gif" alt="" width="6" height="5" border="0" /><br />
+ </td>
+ <td valign="top">
+ <inp2:m_if check="IsCurrent">
+ <strong><inp2:Field name="Name"/></strong><br />
+ <inp2:m_else/>
+ <a href="<inp2:CategoryLink template="__default__" m_cat_page="1"/>" class="top-category"><inp2:Field name="Name"/></a><br />
+ </inp2:m_if>
+ <table>
+ <inp2:ListCategories requery="1" render_as="subcategory_elem" more_link_render_as="more_link_elem" max_items="4" no_table="1"/>
+ </table>
+ <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="5" border="0" /><br />
+ </td>
+ </inp2:m_DefineElement>
+
+ <inp2:c_ListCategories render_as="category_elem" per_page="-1" columns="1" direction="H" parent_cat_id="Root" module="In-Commerce"/>
+ </table>
+</inp2:m_Cache>
\ No newline at end of file
Index: in-link/designs/section.tpl
===================================================================
--- in-link/designs/section.tpl (revision 13160)
+++ in-link/designs/section.tpl (working copy)
@@ -24,18 +24,21 @@
<div class="movable-element">
<inp2:m_RenderElement name="platform/elements/side_boxes/related_searches.elm" design="blue_box" data_exists="1"/>
</div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-link/elements/side_boxes/new.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-link/elements/side_boxes/hot.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-link/elements/side_boxes/pop.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-link/elements/side_boxes/pick.elm" design="blue_box" data_exists="1"/>
- </div>
+
+ <inp2:m_Cache key="prefix:l">
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-link/elements/side_boxes/new.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-link/elements/side_boxes/hot.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-link/elements/side_boxes/pop.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-link/elements/side_boxes/pick.elm" design="blue_box" data_exists="1"/>
+ </div>
+ </inp2:m_Cache>
</div>
</inp2:m_DefineElement>
<!--## //SIDE-BAR ELEMENT ##-->
@@ -51,43 +54,47 @@
<inp2:m_include template="platform/elements/content_boxes/sub_categories.elm"/>
<!--## /SUB-CATEGORIES ##-->
</div>
- <div class="movable-element">
- <!--## links in category ##-->
- <inp2:m_RenderElement design="content_box" data_exists="1" block_no_data="no_links">
- <inp2:l_InitList list_name="items_in_current_cat" main_list="1"/>
- <inp2:m_Capture to_var="header">
- <inp2:m_phrase name="lu_title_Links"/> (<inp2:l_TotalRecords list_name="items_in_current_cat"/>)
- </inp2:m_Capture>
+ <inp2:m_Cache key="prefix:l;guest_only">
+ <div class="movable-element">
+ <!--## links in category ##-->
+ <inp2:m_RenderElement design="content_box" data_exists="1" block_no_data="no_links">
+ <inp2:l_InitList list_name="items_in_current_cat" main_list="1"/>
- <inp2:m_include template="in-link/elements/links.elm"/>
+ <inp2:m_Capture to_var="header">
+ <inp2:m_phrase name="lu_title_Links"/> (<inp2:l_TotalRecords list_name="items_in_current_cat"/>)
+ </inp2:m_Capture>
- <inp2:m_include template="in-link/elements/sorting.elm" list_name="items_in_current_cat"/>
+ <inp2:m_include template="in-link/elements/links.elm"/>
- <table class="fullwidth item-listing table-border">
- <inp2:l_ListLinks list_name="items_in_current_cat" render_as="link_element" direction="H"/>
- </table>
+ <inp2:m_include template="in-link/elements/sorting.elm" list_name="items_in_current_cat"/>
- <inp2:m_include template="platform/elements/pagination.elm" prefix="l" list_name="items_in_current_cat"/>
- </inp2:m_RenderElement>
- <!--## // links in category ##-->
- </div>
+ <table class="fullwidth item-listing table-border">
+ <inp2:l_ListLinks list_name="items_in_current_cat" render_as="link_element" direction="H"/>
+ </table>
+
+ <inp2:m_include template="platform/elements/pagination.elm" prefix="l" list_name="items_in_current_cat"/>
+ </inp2:m_RenderElement>
+ <!--## // links in category ##-->
+ </div>
+ </inp2:m_Cache>
</div>
<!--## RELATED CATEGORIES ##-->
<!--##
-<div class="movable-element">
- <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
- <inp2:m_Capture to_var="header">
- <inp2:m_Phrase label="lu_title_RelatedCategories"/>
- </inp2:m_Capture>
+ <inp2:m_Cache key="prefix:c">
+ <div class="movable-element">
+ <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
+ <inp2:m_Capture to_var="header">
+ <inp2:m_Phrase label="lu_title_RelatedCategories"/>
+ </inp2:m_Capture>
- <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
- </inp2:m_RenderElement>
-</div>
+ <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
+ </inp2:m_RenderElement>
+ </div>
+ </inp2:m_Cache>
##-->
<!--## // RELATED CATEGORIES ##-->
-
</inp2:m_DefineElement>
<!--## /MAIN CONTENT ##-->
Index: in-news/designs/section.tpl
===================================================================
--- in-news/designs/section.tpl (revision 13160)
+++ in-news/designs/section.tpl (working copy)
@@ -21,18 +21,21 @@
<div class="movable-element">
<inp2:m_RenderElement name="in-news/elements/side_boxes/action_box.elm" design="blue_box"/>
</div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-news/elements/side_boxes/pick.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-news/elements/side_boxes/new.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-news/elements/side_boxes/pop.elm" design="blue_box" data_exists="1"/>
- </div>
- <div class="movable-element">
- <inp2:m_RenderElement name="in-news/elements/side_boxes/hot.elm" design="blue_box" data_exists="1"/>
- </div>
+
+ <inp2:m_Cache key="prefix:n">
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-news/elements/side_boxes/pick.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-news/elements/side_boxes/new.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-news/elements/side_boxes/pop.elm" design="blue_box" data_exists="1"/>
+ </div>
+ <div class="movable-element">
+ <inp2:m_RenderElement name="in-news/elements/side_boxes/hot.elm" design="blue_box" data_exists="1"/>
+ </div>
+ </inp2:m_Cache>
</div>
</inp2:m_DefineElement>
<!--## //SIDE-BAR ELEMENT ##-->
@@ -55,58 +58,62 @@
<inp2:m_include template="platform/elements/content_boxes/sub_categories.elm"/>
</div>
- <div class="movable-element">
- <!-- category lead articles -->
- <inp2:m_RenderElement design="content_box" data_exists="1">
- <inp2:n_InitList list_name="category_lead" types="cat_lead" per_page="-1"/>
+ <inp2:m_Cache key="prefix:n;guest_only">
+ <div class="movable-element">
+ <!-- category lead articles -->
+ <inp2:m_RenderElement design="content_box" data_exists="1">
+ <inp2:n_InitList list_name="category_lead" types="cat_lead" per_page="-1"/>
- <inp2:m_Capture to_var="header">
- <inp2:m_phrase name="lu_title_CategoryLeadStory"/>
- </inp2:m_Capture>
+ <inp2:m_Capture to_var="header">
+ <inp2:m_phrase name="lu_title_CategoryLeadStory"/>
+ </inp2:m_Capture>
- <table class="table-gradient-grey" width="100%">
- <inp2:n_ListArticles list_name="category_lead" render_as="category_lead_article_element" no_table="1"/>
- </table>
- </inp2:m_RenderElement>
- <!-- // category lead articles -->
- </div>
+ <table class="table-gradient-grey" width="100%">
+ <inp2:n_ListArticles list_name="category_lead" render_as="category_lead_article_element" no_table="1"/>
+ </table>
+ </inp2:m_RenderElement>
+ <!-- // category lead articles -->
+ </div>
- <div class="movable-element">
- <!-- articles in category -->
- <inp2:m_RenderElement design="content_box" data_exists="1" block_no_data="no_articles">
- <inp2:m_include template="in-news/elements/articles.elm"/>
- <inp2:n_InitList list_name="items_in_current_cat" main_list="1"/>
+ <div class="movable-element">
+ <!-- articles in category -->
+ <inp2:m_RenderElement design="content_box" data_exists="1" block_no_data="no_articles">
+ <inp2:m_include template="in-news/elements/articles.elm"/>
+ <inp2:n_InitList list_name="items_in_current_cat" main_list="1"/>
- <inp2:m_Capture to_var="header">
- <inp2:m_phrase name="lu_title_Articles"/> (<inp2:n_TotalRecords list_name="items_in_current_cat"/>)
- </inp2:m_Capture>
+ <inp2:m_Capture to_var="header">
+ <inp2:m_phrase name="lu_title_Articles"/> (<inp2:n_TotalRecords list_name="items_in_current_cat"/>)
+ </inp2:m_Capture>
- <inp2:m_include template="in-news/elements/sorting.elm" list_name="items_in_current_cat"/>
+ <inp2:m_include template="in-news/elements/sorting.elm" list_name="items_in_current_cat"/>
- <table class="fullwidth item-listing table-border">
- <inp2:n_ListArticles list_name="items_in_current_cat" render_as="article_element" direction="H"/>
- </table>
+ <table class="fullwidth item-listing table-border">
+ <inp2:n_ListArticles list_name="items_in_current_cat" render_as="article_element" direction="H"/>
+ </table>
- <inp2:m_include template="platform/elements/pagination.elm" prefix="n" list_name="items_in_current_cat"/>
+ <inp2:m_include template="platform/elements/pagination.elm" prefix="n" list_name="items_in_current_cat"/>
- <div align="left">
- <a href="<inp2:c_CategoryLink template="in-news/elements/rss.xml" cat_id="current"/>"><inp2:m_Phrase name="lu_rss_feed"/></a>
- </div>
- </inp2:m_RenderElement>
- <!-- // articles in category -->
- </div>
+ <div align="left">
+ <a href="<inp2:c_CategoryLink template="in-news/elements/rss.xml" cat_id="current"/>"><inp2:m_Phrase name="lu_rss_feed"/></a>
+ </div>
+ </inp2:m_RenderElement>
+ <!-- // articles in category -->
+ </div>
+ </inp2:m_Cache>
<!--## LIST RELATED CATEGORIES ##-->
<!--##
- <div class="movable-element">
- <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
- <inp2:m_Capture to_var="header">
- <inp2:m_Phrase label="lu_title_RelatedCategories"/>
- </inp2:m_Capture>
+ <inp2:m_Cache key="prefix:c">
+ <div class="movable-element">
+ <inp2:m_RenderElement design="content_box" related_to="Category" data_exists="1">
+ <inp2:m_Capture to_var="header">
+ <inp2:m_Phrase label="lu_title_RelatedCategories"/>
+ </inp2:m_Capture>
- <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
- </inp2:m_RenderElement>
- </div>
+ <inp2:m_include template="platform/elements/content_boxes/related_items.elm" related_to="$related_to" />
+ </inp2:m_RenderElement>
+ </div>
+ </inp2:m_Cache>
##-->
<!--## //LIST RELATED CATEGORIES ##-->
</inp2:m_DefineElement>
Index: platform/elements/header.elm.tpl
===================================================================
--- platform/elements/header.elm.tpl (revision 13152)
+++ platform/elements/header.elm.tpl (working copy)
@@ -18,29 +18,35 @@
<input type="hidden" name="events[lang][OnChangeLanguage]" value="" />
<inp2:m_Phrase label="lu_YourLanguage"/>:
<select name="language" class="input-select" onchange="document.getElementById('lang_form').submit()">
- <inp2:m_DefineElement name="lang_elem" no_editing="1">
- <option value="<inp2:Field name="LanguageId"/>" <inp2:m_if check="SelectedLanguage">selected="selected"</inp2:m_if> ><inp2:Field name="PackName"/></option>
- </inp2:m_DefineElement>
- <inp2:lang_ListLanguages render_as="lang_elem" no_table="1"/>
+
+ <inp2:m_Cache key="prefix:lang;skip_var:t,page,per_page,sort_by">
+ <inp2:m_DefineElement name="lang_elem" no_editing="1">
+ <option value="<inp2:Field name="LanguageId"/>" <inp2:m_if check="SelectedLanguage">selected="selected"</inp2:m_if> ><inp2:Field name="PackName"/></option>
+ </inp2:m_DefineElement>
+
+ <inp2:lang_ListLanguages render_as="lang_elem" no_table="1"/>
+ </inp2:m_Cache>
</select>
</form>
</td>
<!--## THEME DROP-DOWN ##-->
- <!--##
<td class="top-select-padding">
<form method="post" name="theme_form" id="theme_form" action="<inp2:m_FormAction />">
<input type="hidden" name="events[theme][OnChangeTheme]" value="" />
<inp2:m_Phrase label="lu_CurrentTheme"/>:
<select name="theme" class="input-select" onchange="document.getElementById('theme_form').submit()">
- <inp2:m_DefineElement name="theme_elem">
- <option value="<inp2:Field name="ThemeId"/>" <inp2:m_if check="SelectedTheme">selected="selected"</inp2:m_if> ><inp2:Field name="Name"/></option>
- </inp2:m_DefineElement>
- <inp2:theme_PrintList render_as="theme_elem" no_table="1"/>
+
+ <inp2:m_Cache key="prefix:theme;skip_var:t,page,per_page,sort_by">
+ <inp2:m_DefineElement name="theme_elem">
+ <option value="<inp2:Field name="ThemeId"/>" <inp2:m_if check="SelectedTheme">selected="selected"</inp2:m_if> ><inp2:Field name="Name"/></option>
+ </inp2:m_DefineElement>
+
+ <inp2:theme_PrintList render_as="theme_elem"/>
+ </inp2:m_Cache>
</select>
</form>
</td>
- ##-->
<!--## /THEME DROP-DOWN ##-->
<inp2:m_if check="m_ModuleEnabled" module="In-Commerce">
Index: platform/elements/html_head.elm.tpl
===================================================================
--- platform/elements/html_head.elm.tpl (revision 13152)
+++ platform/elements/html_head.elm.tpl (working copy)
@@ -28,10 +28,12 @@
<script type="text/javascript">
var aRatingManager = new RatingManager('<inp2:m_Link template="index" events[#PREFIX#]="OnMakeVote" rating="#VOTE#" id="#ID#" no_amp="1" size="#SIZE#"/>');
- <inp2:m_DefineElement name="ml_selector_language_element">
- <inp2:Field name="LanguageId"/>: {'on': '<inp2:Field name="IconURL" js_ecape="1"/>', 'off': '<inp2:Field name="IconDisabledURL" js_ecape="1"/>'}
- <inp2:m_ifnot check="m_Param" name="is_last">,</inp2:m_ifnot>
- </inp2:m_DefineElement>
+ <inp2:m_Cache key="prefix:lang;skip_var:t,page,per_page,sort_by">
+ <inp2:m_DefineElement name="ml_selector_language_element">
+ <inp2:Field name="LanguageId"/>: {'on': '<inp2:Field name="IconURL" js_ecape="1"/>', 'off': '<inp2:Field name="IconDisabledURL" js_ecape="1"/>'}
+ <inp2:m_ifnot check="m_Param" name="is_last">,</inp2:m_ifnot>
+ </inp2:m_DefineElement>
- var aMultiLanguageSelector = new MultiLanguageSelector({<inp2:lang.enabled_PrintList render_as="ml_selector_language_element" per_page="-1" no_editing="1" strip_nl="2"/>}, <inp2:m_Get name="m_lang"/>);
+ var aMultiLanguageSelector = new MultiLanguageSelector({<inp2:lang.enabled_PrintList render_as="ml_selector_language_element" per_page="-1" no_editing="1" strip_nl="2"/>}, <inp2:m_Get name="m_lang"/>);
+ </inp2:m_Cache>
</script>
Index: platform/elements/menu_subsections.xml.tpl
===================================================================
--- platform/elements/menu_subsections.xml.tpl (revision 13152)
+++ platform/elements/menu_subsections.xml.tpl (working copy)
@@ -26,7 +26,7 @@
><![CDATA[<inp2:m_Param name="title"/>]]></item>
</inp2:m_DefineElement>
- <inp2:st_CachedMenu except="index" menu_id="$page_id" category_id="$cat_id" render_as="top_sub_menu_elem"/>
+ <inp2:st_CachedMenu except="index" menu_id="$page_id" max_level="$max_level" render_as="top_sub_menu_elem"/>
</items>
</menu>
</menus>
\ No newline at end of file
memcache_notification_addon.patch [^] (867 bytes) 2010-03-02 14:18
[Show Content]
Index: application.php
===================================================================
--- application.php (revision 13168)
+++ application.php (working copy)
@@ -783,11 +783,11 @@
$serial_name = $pascal_case_prefix . (isset($id) ? 'IDSerial:' . $id : 'Serial');
if ($increment) {
- if (defined('DEBUG_MODE') && DEBUG_MODE && $this->isDebugMode()) {
- $this->Application->Debugger->appendHTML('Incrementing serial: <strong>' . $serial_name . '</strong>.');
- }
+ if ($this->isCachingType(CACHING_TYPE_MEMORY)) {
+ if (defined('DEBUG_MODE') && DEBUG_MODE && $this->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Incrementing serial: <strong>' . $serial_name . '</strong>.');
+ }
- if ($this->isCachingType(CACHING_TYPE_MEMORY)) {
$this->setCache($serial_name, (int)$this->getCache($serial_name) + 1);
}
memcache_theme_rebuild_fix.patch [^] (863 bytes) 2010-03-07 13:29
[Show Content]
Index: units/helpers/themes_helper.php
===================================================================
--- units/helpers/themes_helper.php (revision 13168)
+++ units/helpers/themes_helper.php (working copy)
@@ -357,6 +357,8 @@
$theme_id = $this->refreshTheme($filename);
if ($theme_id) {
$themes_found[] = $theme_id;
+ // increment serial of updated themes
+ $this->Application->incrementCacheSerial('theme', $theme_id);
}
}
}
@@ -381,6 +383,11 @@
$theme_ids = $this->Conn->GetCol($sql);
$this->deleteThemes($theme_ids);
+ foreach ($theme_ids as $theme_id) {
+ // increment serial of deleted themes
+ $this->Application->incrementCacheSerial('theme', $theme_id);
+ }
+
$this->Application->incrementCacheSerial('theme');
$this->Application->incrementCacheSerial('theme-file');
}
memcache_install_fix.patch [^] (478 bytes) 2010-03-21 16:29
[Show Content]
Index: install_toolkit.php
===================================================================
--- install_toolkit.php (revision 13268)
+++ install_toolkit.php (working copy)
@@ -797,6 +797,7 @@
*/
function deleteCache($refresh_permissions = false)
{
+ $this->Application->HandleEvent($event, 'adm:OnResetMemcache');
$this->Application->HandleEvent($event, 'adm:OnResetConfigsCache');
$this->Application->HandleEvent($event, 'c:OnResetCMSMenuCache');
memcache_install_fix_v2.patch [^] (1,035 bytes) 2010-03-24 08:33
[Show Content]
Index: install.php
===================================================================
--- install.php (revision 13268)
+++ install.php (working copy)
@@ -593,6 +593,9 @@
break;
case 'select_license':
+ // reset memory cache, when application is first available (on fresh install and clean reinstall steps)
+ $this->Application->HandleEvent($event, 'adm:OnResetMemcache');
+
$license_source = $this->GetVar('license_source');
switch ($license_source) {
case 1: // Download from Intechnic
Index: install/install_toolkit.php
===================================================================
--- install/install_toolkit.php (revision 13275)
+++ install/install_toolkit.php (working copy)
@@ -797,7 +797,6 @@
*/
function deleteCache($refresh_permissions = false)
{
- $this->Application->HandleEvent($event, 'adm:OnResetMemcache');
$this->Application->HandleEvent($event, 'adm:OnResetConfigsCache');
$this->Application->HandleEvent($event, 'c:OnResetCMSMenuCache');
memcache_custom_field_caching_on_install.patch [^] (2,078 bytes) 2010-03-24 08:39
[Show Content]
Index: units/custom_data/custom_data_event_handler.php
===================================================================
--- units/custom_data/custom_data_event_handler.php (revision 13268)
+++ units/custom_data/custom_data_event_handler.php (working copy)
@@ -55,20 +55,23 @@
return false;
}
- if (!$custom_fields || (defined('IS_INSTALL') && IS_INSTALL) || (defined('CUSTOM_FIELD_ADDED') && CUSTOM_FIELD_ADDED)) {
+ $no_caching = (defined('IS_INSTALL') && IS_INSTALL) || (defined('CUSTOM_FIELD_ADDED') && CUSTOM_FIELD_ADDED);
+
+ if (!$custom_fields || $no_caching) {
// query all custom fields at once -> saves 4 sqls queries
- $cache_key = 'all_custom_fields[%CfSerial%][%ModSerial%]';
- $all_custom_fields = $this->Application->getCache($cache_key, false);
+ if ($no_caching) {
+ $all_custom_fields = $this->getCustomFields();
+ }
+ else {
+ $cache_key = 'all_custom_fields[%CfSerial%][%ModSerial%]';
+ $all_custom_fields = $this->Application->getCache($cache_key, false);
- if ($all_custom_fields === false) {
- $this->Conn->nextQueryCachable = true;
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'CustomField';
- $all_custom_fields = $this->Conn->Query($sql, 'CustomFieldId');
- ksort($all_custom_fields);
-
- $this->Application->setCache($cache_key, $all_custom_fields);
+ if ($all_custom_fields === false) {
+ $this->Conn->nextQueryCachable = true;
+ $all_custom_fields = $this->getCustomFields();
+ $this->Application->setCache($cache_key, $all_custom_fields);
+ }
}
foreach ($all_custom_fields as $custom_field_id => $custom_field_data) {
@@ -85,6 +88,22 @@
}
/**
+ * Returns sorted list of all custom fields
+ *
+ * @return Array
+ */
+ function getCustomFields()
+ {
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'CustomField';
+ $ret = $this->Conn->Query($sql, 'CustomFieldId');
+
+ ksort($ret);
+
+ return $ret;
+ }
+
+ /**
* Fills cloned cdata config with data from it's parent
*
* @param kEvent $event
cached_permissions_not_updated_after_group_edit.patch [^] (1,651 bytes) 2010-04-13 12:40
[Show Content]
Index: kernel/db/db_event_handler.php
===================================================================
--- kernel/db/db_event_handler.php (revision 13377)
+++ kernel/db/db_event_handler.php (working copy)
@@ -1611,6 +1611,9 @@
foreach ($rec['DependentFields'] as $field_name => $field_value) {
// will be "ci|ItemResourceId:345"
$to_increment[] = $rec['Prefix'] . '|' . $field_name . ':' . $field_value;
+
+ // also reset sub-item prefix general serial
+ $to_increment[] = $rec['Prefix'];
}
unset($changes[$index]['DependentFields']);
@@ -1624,6 +1627,10 @@
$to_increment[] = $change['MasterPrefix'] . '|' . $change['MasterId'];
if ($change['MasterPrefix'] != $change['Prefix']) {
+ // also reset sub-item prefix general serial
+ $to_increment[] = $change['Prefix'];
+
+ // will be "ci|ItemResourceId"
$to_increment[] = $change['Prefix'] . '|' . $change['ItemId'];
}
}
@@ -1633,9 +1640,13 @@
$this->Application->incrementCacheSerial($this->Prefix);
foreach ($to_increment as $to_increment_mixed) {
- list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2);
-
- $this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id);
+ if (strpos($to_increment_mixed, '|') !== false) {
+ list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2);
+ $this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id);
+ }
+ else {
+ $this->Application->incrementCacheSerial($to_increment_mixed);
+ }
}
// save changes to database
QuestionAboutCachingNumberOfProductsInCategory.jpg [^] (580,125 bytes) 2010-04-25 18:24
overlaped_cache_names_fix.patch [^] (477 bytes) 2010-05-12 07:28
[Show Content]
Index: category_helper.php
===================================================================
--- category_helper.php (revision 13557)
+++ category_helper.php (working copy)
@@ -288,7 +288,7 @@
return Array ();
}
- $cache_key = 'parent_paths[%CIDSerial:' . $main_category_id . '%]';
+ $cache_key = 'parent_paths_named[%CIDSerial:' . $main_category_id . '%]';
$cached_path = $this->Application->getCache($cache_key);
if ($cached_path === false) {
memcache_addon.patch [^] (6,083 bytes) 2010-05-24 14:50
[Show Content]
Index: english.lang
===================================================================
--- english.lang (revision 13613)
+++ english.lang (working copy)
@@ -658,6 +658,7 @@
<PHRASE Label="la_hint_ExportPhrases" Module="Core" Type="1">U2luZ2xlIFBocmFzZSBMYWJlbCBwZXIgbGluZSAoZm9ybWF0czogbGFfU2FtcGxlTGFiZWwsIGx1X0Zyb250RW5kTGFiZWwp</PHRASE>
<PHRASE Label="la_hint_ForceModRewriteUrlEnding" Module="Core" Type="1">VXNlciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVkaXJlY3RlZCB0byB0aGUgc2VsZWN0ZWQgVXJsIEVuZGluZyBpbiBjYXNlIHdoZW4gY3VycmVudCBwYWdlIHVybCBoYXMgYSBkaWZmZXJlbnQgZW5kaW5n</PHRASE>
<PHRASE Label="la_hint_ImageFiles" Module="Core" Type="1">SW1hZ2UgRmlsZXM=</PHRASE>
+ <PHRASE Label="la_hint_MemcacheServers" Module="Core" Type="1">TXVsdGlwbGUgTWVtY2FjaGVkIHNlcnZlcnMgY2FuIGJlIGxpc3RlZCBzZXBhcmF0ZWQgYnkgc2VtaS1jb2xvbiAoOykuIEZvciBleGFtcGxlLCAxOTIuMTY4LjEuMToxMTIxOzE5Mi4xNjguMS4yOjExMjE7MTkyLjE2OC4xLjM6MTEyMQ==</PHRASE>
<PHRASE Label="la_hint_PageExpiration" Module="Core" Type="1">SG93IHNvb24gKGluIHNlY29uZHMpIHRoZSBzZWN0aW9uIGNhY2hlIHNob3VsZCBhdXRvLWV4cGlyZSBhZnRlciBpdCdzIGNyZWF0aW9uLiBCeSBkZWZhdWx0IHN5c3RlbSB0ZW5kcyB0byByZWJ1aWxkIHRoZSBjYWNoZSBvbmx5IHdoZW4gaXQncyBwcm9wZXJ0aWVzIG9yIGVsZW1lbnRzIGhhdmUgY2hhbmdlZC4=</PHRASE>
<PHRASE Label="la_hint_PopPort" Module="Core" Type="1">UE9QMyBTZXJ2ZXIgUG9ydC4gRm9yIGV4LiAiMTEwIiBmb3IgcmVndWxhciBjb25uZWN0aW9uLCAiOTk1IiBmb3Igc2VjdXJlIGNvbm5lY3Rpb24u</PHRASE>
<PHRASE Label="la_hint_PopServer" Module="Core" Type="1">UE9QMyBTZXJ2ZXIgQWRkcmVzcy4gRm9yIGV4LiB1c2UgInNzbDovL3BvcC5nbWFpbC5jb20iIGZvciBHbWFpbCwgInBvcC5tYWlsLnlhaG9vLmNvbSIgZm9yIFlhaG9vLg==</PHRASE>
Index: install_data.sql
===================================================================
--- install_data.sql (revision 13613)
+++ install_data.sql (working copy)
@@ -93,8 +93,8 @@
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'CSVExportEnclosure', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCSVExport', 'la_config_CSVExportEnclosure', 'radio', NULL, '0=la_Doublequotes||1=la_Quotes', 70.02, 0, 1, NULL);
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'CSVExportSeparator', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCSVExport', 'la_config_CSVExportSeparator', 'radio', NULL, '0=la_Linux||1=la_Windows', 70.03, 0, 1, NULL);
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'CSVExportEncoding', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCSVExport', 'la_config_CSVExportEncoding', 'radio', NULL, '0=la_Unicode||1=la_Regular', 70.04, 0, 1, NULL);
-INSERT INTO ConfigurationValues VALUES(DEFAULT, 'MemcacheServers', 'localhost:11211', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', NULL, '', 80.01, 0, 0, NULL);
-INSERT INTO ConfigurationValues VALUES(DEFAULT, 'CacheHandler', 'Fake', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCaching', 'la_config_CacheHandler', 'select', NULL, 'Fake=la_None||Memcache=+Memcached||Apc=+Alternative PHP Cache||XCache=+XCache', 80.02, 0, 0, NULL);
+INSERT INTO ConfigurationValues VALUES(DEFAULT, 'CacheHandler', 'Fake', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCaching', 'la_config_CacheHandler', 'select', NULL, 'Fake=la_None||Memcache=+Memcached||Apc=+Alternative PHP Cache||XCache=+XCache', 80.01, 0, 0, NULL);
+INSERT INTO ConfigurationValues VALUES(DEFAULT, 'MemcacheServers', 'localhost:11211', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', NULL, '', 80.02, 0, 0, 'la_hint_MemcacheServers');
# Section "in-portal:configure_users":
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'User_Allow_New', '3', 'In-Portal:Users', 'in-portal:configure_users', 'la_title_General', 'la_users_allow_new', 'radio', '', '1=la_opt_UserInstantRegistration||2=la_opt_UserNotAllowedRegistration||3=la_opt_UserUponApprovalRegistration||4=la_opt_UserEmailActivation', 10.01, 0, 1, NULL);
Index: upgrades.sql
===================================================================
--- upgrades.sql (revision 13613)
+++ upgrades.sql (working copy)
@@ -1670,7 +1670,7 @@
UPDATE Category SET FormId = NULL WHERE FormId = 0;
-INSERT INTO ConfigurationAdmin VALUES ('MemcacheServers', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', '', '', 80.01, 0, 0);
+INSERT INTO ConfigurationAdmin VALUES ('MemcacheServers', 'la_section_SettingsCaching', 'la_config_MemcacheServers', 'text', '', '', 80.02, 0, 0);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MemcacheServers', 'localhost:11211', 'In-Portal', 'in-portal:configure_advanced');
ALTER TABLE Category
@@ -1702,7 +1702,7 @@
KEY DomainId (DomainId)
);
-INSERT INTO ConfigurationAdmin VALUES ('CacheHandler', 'la_section_SettingsCaching', 'la_config_CacheHandler', 'select', NULL, 'Fake=la_None,Memcache=+Memcached,Apc=+Alternative PHP Cache,XCache=+XCache', 80.02, 0, 0);
+INSERT INTO ConfigurationAdmin VALUES ('CacheHandler', 'la_section_SettingsCaching', 'la_config_CacheHandler', 'select', NULL, 'Fake=la_None,Memcache=+Memcached,Apc=+Alternative PHP Cache,XCache=+XCache', 80.01, 0, 0);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CacheHandler', 'Fake', 'In-Portal', 'in-portal:configure_advanced');
ALTER TABLE ConfigurationValues
@@ -1823,6 +1823,7 @@
ADD HintLabel VARCHAR(255) NULL DEFAULT NULL,
ADD INDEX (HintLabel);
+UPDATE ConfigurationValues SET HintLabel = 'la_hint_MemcacheServers' WHERE VariableName = 'MemcacheServers';
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'ModRewriteUrlEnding', '.html', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsWebsite', 'la_config_ModRewriteUrlEnding', 'select', '', '=+||/=+/||.html=+.html', 10.021, 0, 0, NULL);
INSERT INTO ConfigurationValues VALUES(DEFAULT, 'ForceModRewriteUrlEnding', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsWebsite', 'la_config_ForceModRewriteUrlEnding', 'checkbox', '', NULL, 10.022, 0, 0, 'la_hint_ForceModRewriteUrlEnding');
|