protected function GetCount($Table) { // Try and get the count from the cache. $Key = "{$Table}.CountRows"; $Count = Gdn::Cache()->Get($Key); if ($Count !== Gdn_Cache::CACHEOP_FAILURE) { return $Count; } // The count wasn't in the cache so grab it from the table. $Count = Gdn::SQL()->Select($Table . 'ID', 'count', 'CountRows')->From($Table)->Get()->Value('CountRows'); // Save the value to the cache. Gdn::Cache()->Store($Key, $Count, array(Gdn_Cache::FEATURE_EXPIRY => 5 * 60 + mt_rand(0, 30))); return $Count; }
/** * This checks the cache for current rule set that can be triggered for a user * by another user. It loads all rules and selects only those that return true * on its `Interacts()` method. * * @return array Rules that are currently available to use that are interactive. */ public static function GetInteractionRules() { $Rules = Gdn::Cache()->Get('Yaga.Badges.InteractionRules'); if ($Rules === Gdn_Cache::CACHEOP_FAILURE) { $AllRules = RulesController::GetRules(); $TempRules = array(); foreach ($AllRules as $ClassName => $Name) { $Rule = new $ClassName(); if ($Rule->Interacts()) { $TempRules[$ClassName] = $Name; } } if (empty($TempRules)) { $Rules = serialize(FALSE); } else { $Rules = serialize($TempRules); } Gdn::Cache()->Store('Yaga.Badges.InteractionRules', $Rules, array(Gdn_Cache::FEATURE_EXPIRY => C('Yaga.Rules.CacheExpire', 86400))); } return unserialize($Rules); }
/** * Increments view count for the specified discussion. * * @since 2.0.0 * @access public * * @param int $DiscussionID Unique ID of discussion to get +1 view. */ public function AddView($DiscussionID) { $IncrementBy = 0; if (C('Vanilla.Views.Denormalize', FALSE) && Gdn::Cache()->ActiveEnabled()) { $WritebackLimit = C('Vanilla.Views.DenormalizeWriteback', 10); $CacheKey = sprintf(DiscussionModel::CACHE_DISCUSSIONVIEWS, $DiscussionID); // Increment. If not success, create key. $Views = Gdn::Cache()->Increment($CacheKey); if ($Views === Gdn_Cache::CACHEOP_FAILURE) { Gdn::Cache()->Store($CacheKey, 1); } // Every X views, writeback to Discussions if ($Views % $WritebackLimit == 0) { $IncrementBy = floor($Views / $WritebackLimit) * $WritebackLimit; Gdn::Cache()->Decrement($CacheKey, $IncrementBy); } } else { $IncrementBy = 1; } if ($IncrementBy) { $this->SQL->Update('Discussion')->Set('CountViews', "CountViews + {$IncrementBy}", FALSE)->Where('DiscussionID', $DiscussionID)->Put(); } }
/** * Saves all settings in $Group to $File. * * @param string $File The full path to the file where the Settings should be saved. * @param string $Group The name of the settings group to be saved to the $File. * @param boolean $RequireSourceFile Should $File be required to exist in order to save? If true, then values * from this file will be merged into the settings array before it is saved. * If false, the values in the settings array will overwrite any values * existing in the file (if it exists). * @return boolean */ public function Save($File = '', $Group = '', $RequireSourceFile = TRUE) { if ($File == '') { $File = $this->_File; } if ($File == '') { trigger_error(ErrorMessage('You must specify a file path to be saved.', 'Configuration', 'Save'), E_USER_ERROR); } if (!is_writable($File)) { throw new Exception(sprintf(T("Unable to write to config file '%s' when saving."), $File)); } if ($Group == '') { $Group = $this->CurrentGroup; } if ($Group == '') { $Group = 'Configuration'; } $Data =& $this->_SaveData; $this->_Sort($Data); // Check for the case when the configuration is the group. if (is_array($Data) && count($Data) == 1 && array_key_exists($Group, $Data)) { $Data = $Data[$Group]; } // Do a sanity check on the config save. if ($File == PATH_LOCAL_CONF . '/config.php') { if (!isset($Data['Database'])) { if ($Pm = Gdn::PluginManager()) { $Pm->EventArguments['Data'] = $Data; $Pm->EventArguments['Backtrace'] = debug_backtrace(); $Pm->FireEvent('ConfigError'); } $this->_SaveData = array(); $this->_File = ''; return FALSE; } } $NewLines = array(); $NewLines[] = "<?php if (!defined('APPLICATION')) exit();"; $LastName = ''; foreach ($Data as $Name => $Value) { // Write a newline to seperate sections. if ($LastName != $Name && is_array($Value)) { $NewLines[] = ''; $NewLines[] = '// ' . $Name; } $Line = "\$" . $Group . "['" . $Name . "']"; FormatArrayAssignment($NewLines, $Line, $Value); } // Record who made the change and when if (is_array($NewLines)) { $Session = Gdn::Session(); $User = $Session->UserID > 0 && is_object($Session->User) ? $Session->User->Name : 'Unknown'; $NewLines[] = ''; $NewLines[] = '// Last edited by ' . $User . ' (' . RemoteIp() . ')' . Gdn_Format::ToDateTime(); } $FileContents = FALSE; if ($NewLines !== FALSE) { $FileContents = implode("\n", $NewLines); } if ($FileContents === FALSE) { trigger_error(ErrorMessage('Failed to define configuration file contents.', 'Configuration', 'Save'), E_USER_ERROR); } $FileKey = sprintf(self::CONFIG_FILE_CACHE_KEY, $File); if ($this->Caching() && Gdn::Cache()->Type() == Gdn_Cache::CACHE_TYPE_MEMORY && Gdn::Cache()->ActiveEnabled()) { $CachedConfigData = Gdn::Cache()->Store($FileKey, $Data, array(Gdn_Cache::FEATURE_NOPREFIX => TRUE)); } // Infrastructure deployment. Use old method. if (PATH_LOCAL_CONF != PATH_CONF) { $Result = Gdn_FileSystem::SaveFile($File, $FileContents, LOCK_EX); } else { $TmpFile = tempnam(PATH_CONF, 'config'); $Result = FALSE; if (file_put_contents($TmpFile, $FileContents) !== FALSE) { chmod($TmpFile, 0775); $Result = rename($TmpFile, $File); } } if ($Result && function_exists('apc_delete_file')) { // This fixes a bug with some configurations of apc. @apc_delete_file($File); } // Clear out the save data array $this->_SaveData = array(); $this->_File = ''; return $Result; }
public function ClearThemeCache($SearchPaths = NULL) { if (!is_null($SearchPaths)) { if (!is_array($SearchPaths)) { $SearchPaths = array($SearchPaths); } } else { $SearchPaths = $this->SearchPaths(); } foreach ($SearchPaths as $SearchPath => $SearchPathName) { $SearchPathCacheKey = "Garden.Themes.PathCache.{$SearchPath}"; $SearchPathCache = Gdn::Cache()->Remove($SearchPathCacheKey, array(Gdn_Cache::FEATURE_NOPREFIX => TRUE)); } }
/** * * * @param type $Key Cache key * @param type $Options * @return mixed */ protected function Fallback($Key, $Options) { $Fallback = GetValue(Gdn_Cache::FEATURE_FALLBACK, $Options, NULL); if (is_null($Fallback)) { return Gdn_Cache::CACHEOP_FAILURE; } $FallbackType = array_shift($Fallback); switch ($FallbackType) { case 'query': $QueryFallbackField = array_shift($Fallback); $QueryFallbackCode = array_shift($Fallback); $FallbackResult = Gdn::Database()->Query($QueryFallbackCode); if ($FallbackResult->NumRows()) { if (!is_null($QueryFallbackField)) { $FallbackResult = GetValue($QueryFallbackField, $FallbackResult->FirstRow(DATASET_TYPE_ARRAY)); } else { $FallbackResult = $FallbackResult->ResultArray(); } } break; case 'callback': $CallbackFallbackMethod = array_shift($Fallback); $CallbackFallbackArgs = $Fallback; $FallbackResult = call_user_func_array($CallbackFallbackMethod, $CallbackFallbackArgs); break; } Gdn::Cache()->Store($Key, $FallbackResult); return $FallbackResult; }
public function Save($FormPostValues, $Settings = FALSE) { // The "location" is packed into a single input with a / delimiter. Need to explode it into three different fields for saving $Location = ArrayValue('Location', $FormPostValues, ''); if ($Location != '') { $Location = explode('/', $Location); $Application = GetValue(0, $Location, ''); if (in_array($Application, $this->_SpecialLocations)) { $FormPostValues['Application'] = NULL; $FormPostValues['Controller'] = $Application; $FormPostValues['Method'] = NULL; } else { $FormPostValues['Application'] = $Application; $FormPostValues['Controller'] = GetValue(1, $Location, ''); $FormPostValues['Method'] = GetValue(2, $Location, ''); } } Gdn::Cache()->Remove('Messages'); return parent::Save($FormPostValues, $Settings); }
public function Ping() { $start = microtime(true); $this->SetData('pong', TRUE); $this->MasterView = 'empty'; $this->CssClass = 'Home'; $valid = true; // Test the cache. if (Gdn::Cache()->ActiveEnabled()) { $k = BetterRandomString(20); Gdn::Cache()->Store($k, 1); Gdn::Cache()->Increment($k, 1); $v = Gdn::Cache()->Get($k); if ($v !== 2) { $valid = false; $this->SetData('cache', false); } else { $this->SetData('cache', true); } } else { $this->SetData('cache', 'disabled'); } // Test the db. try { $users = Gdn::SQL()->Get('User', 'UserID', 'asc', 1); $this->SetData('database', true); } catch (Exception $ex) { $this->SetData('database', false); $valid = false; } $this->EventArguments['Valid'] =& $valid; $this->FireEvent('Ping'); if (!$valid) { $this->StatusCode(500); } $time = microtime(true) - $start; $this->SetData('time', Gdn_Format::Timespan($time)); $this->SetData('time_s', $time); $this->SetData('valid', $valid); $this->Title('Ping'); $this->Render(); }
public function GetUnansweredCount() { $Count = Gdn::Cache()->Get('QnA-UnansweredCount'); if ($Count === Gdn_Cache::CACHEOP_FAILURE) { Gdn::SQL()->WhereIn('QnA', array('Unanswered', 'Rejected')); $Count = Gdn::SQL()->GetCount('Discussion', array('Type' => 'Question')); Gdn::Cache()->Store('QnA-UnansweredCount', $Count, array(Gdn_Cache::FEATURE_EXPIRY => 15 * 60)); } return $Count; }
<div id="Sql" class="DebugInfo"> <h2>Debug Information</h2> <?php // Add the canonical Url. if (method_exists($Sender, 'CanonicalUrl')) { $CanonicalUrl = htmlspecialchars($Sender->CanonicalUrl(), ENT_COMPAT, 'UTF-8'); echo '<div class="CanonicalUrl"><b>' . T('Canonical Url') . "</b>: <a href=\"{$CanonicalUrl}\" accesskey=\"r\">{$CanonicalUrl}</a></div>"; } ?> <?php // Add some cache info. if (Gdn::Cache()->ActiveEnabled()) { echo '<h3>Cache Information</h3>'; echo '<pre>'; echo '<b>Cache Revision</b>: ' . Gdn::Cache()->GetRevision() . "\n"; echo '<b>Permissions Revision</b>: ' . Gdn::UserModel()->GetPermissionsIncrement() . "\n"; if (property_exists('Gdn_Cache', 'GetCount')) { echo '<b>Cache Gets</b>: ' . sprintf('%s in %ss', Gdn_Cache::$GetCount, Gdn_Cache::$GetTime); } echo '</pre>'; if (property_exists('Gdn_Cache', 'trackGet') && sizeof(Gdn_Cache::$trackGet)) { uasort(Gdn_Cache::$trackGet, function ($a, $b) { return $b['hits'] - $a['hits']; }); $numKeys = sizeof(Gdn_Cache::$trackGet); $duplicateGets = 0; $wastedBytes = 0; $totalBytes = 0; foreach (Gdn_Cache::$trackGet as $key => $keyData) { if ($keyData['hits'] > 1) {
/** * Returns a list of all recent scored posts ordered by highest score * * @param string $Timespan strtotime compatible time * @param int $Limit * @param int $Offset * @return array */ public function GetRecent($Timespan = 'week', $Limit = NULL, $Offset = 0) { $CacheKey = "yaga.best.last.{$Timespan}"; $Content = Gdn::Cache()->Get($CacheKey); if ($Content == Gdn_Cache::CACHEOP_FAILURE) { $TargetDate = date('Y-m-d H:i:s', strtotime("1 {$Timespan} ago")); $SQL = $this->_BaseSQL('Discussion'); $Discussions = $SQL->Where('d.DateUpdated >', $TargetDate)->Get()->Result(DATASET_TYPE_ARRAY); $SQL = $this->_BaseSQL('Comment'); $Comments = $SQL->Where('c.DateUpdated >', $TargetDate)->Get()->Result(DATASET_TYPE_ARRAY); $this->JoinCategory($Comments); // Interleave $Content = $this->Union('Score', array('Discussion' => $Discussions, 'Comment' => $Comments)); $this->Prepare($Content); Gdn::Cache()->Store($CacheKey, $Content, array(Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry)); } $this->Security($Content); $this->Condense($Content, $Limit, $Offset); return $Content; }
/** * Increments view count for the specified discussion. * * @since 2.0.0 * @access public * * @param int $DiscussionID Unique ID of discussion to get +1 view. */ public function AddView($DiscussionID) { if (C('Vanilla.Views.Denormalize', FALSE) && Gdn::Cache()->ActiveEnabled()) { $CacheKey = "QueryCache.Discussion.{$DiscussionID}.CountViews"; // Increment. If not success, create key. $Views = Gdn::Cache()->Increment($CacheKey); if ($Views === Gdn_Cache::CACHEOP_FAILURE) { $Views = $this->GetWhere(array('DiscussionID' => $DiscussionID))->Value('CountViews', 0); Gdn::Cache()->Store($CacheKey, $Views); } // Every X views, writeback to Discussions if ($Views % C('Vanilla.Views.DenormalizeWriteback', 100) == 0) { $this->SetField($DiscussionID, 'CountViews', $Views); } } else { $this->SQL->Update('Discussion')->Set('CountViews', 'CountViews + 1', FALSE)->Where('DiscussionID', $DiscussionID)->Put(); } }
/** * Wrapper for GetCountWhere that takes care of caching specific operation counts. * @param string $Operation Comma-delimited list of operation types to get (sum of) counts for. */ public function GetOperationCount($Operation) { if ($Operation == 'edits') { $Operation = array('edit', 'delete'); } else { $Operation = explode(',', $Operation); } sort($Operation); array_map('ucfirst', $Operation); $CacheKey = 'Moderation.LogCount.' . implode('.', $Operation); $Count = Gdn::Cache()->Get($CacheKey); if ($Count === Gdn_Cache::CACHEOP_FAILURE) { $Count = $this->GetCountWhere(array('Operation' => $Operation)); Gdn::Cache()->Store($CacheKey, $Count, array(Gdn_Cache::FEATURE_EXPIRY => 300)); } return $Count; }
public static function Module($Name, $Properties = array()) { if (isset($Properties['cache'])) { $Key = isset($Properties['cachekey']) ? $Properties['cachekey'] : 'module.' . $Name; $Result = Gdn::Cache()->Get($Key); if ($Result !== Gdn_Cache::CACHEOP_FAILURE) { // Trace('Module: '.$Result, $Key); return $Result; } } try { if (!class_exists($Name)) { if (Debug()) { $Result = "Error: {$Name} doesn't exist"; } else { $Result = "<!-- Error: {$Name} doesn't exist -->"; } } else { $Module = new $Name(Gdn::Controller(), ''); $Module->Visible = TRUE; // Add properties passed in from the controller. $ControllerProperties = Gdn::Controller()->Data('_properties.' . strtolower($Name), array()); $Properties = array_merge($ControllerProperties, $Properties); foreach ($Properties as $Name => $Value) { $Module->{$Name} = $Value; } $Result = $Module->ToString(); } } catch (Exception $Ex) { if (Debug()) { $Result = '<pre class="Exception">' . htmlspecialchars($Ex->getMessage() . "\n" . $Ex->getTraceAsString()) . '</pre>'; } else { $Result = $Ex->getMessage(); } } if (isset($Key)) { // Trace($Result, "Store $Key"); Gdn::Cache()->Store($Key, $Result, array(Gdn_Cache::FEATURE_EXPIRY => $Properties['cache'])); } return $Result; }
public function Query($Sql, $InputParameters = NULL, $Options = array()) { $Trace = debug_backtrace(); $Method = ''; foreach ($Trace as $Info) { $Class = GetValue('class', $Info, ''); if ($Class === '' || StringEndsWith($Class, 'Model', TRUE) || StringEndsWith($Class, 'Plugin', TRUE)) { $Type = ArrayValue('type', $Info, ''); $Method = $Class . $Type . $Info['function'] . '(' . self::FormatArgs($Info['args']) . ')'; break; } } // Save the query for debugging // echo '<br />adding to queries: '.$Sql; $Query = array('Sql' => $Sql, 'Parameters' => $InputParameters, 'Method' => $Method); $SaveQuery = TRUE; if (isset($Options['Cache'])) { $CacheKeys = (array) $Options['Cache']; $Cache = array(); $AllSet = TRUE; foreach ($CacheKeys as $CacheKey) { $Value = Gdn::Cache()->Get($CacheKey); $CacheValue = $Value !== Gdn_Cache::CACHEOP_FAILURE; $AllSet &= $CacheValue; $Cache[$CacheKey] = $CacheValue; } $SaveQuery = !$AllSet; $Query['Cache'] = $Cache; } // Start the Query Timer $TimeStart = Now(); $Result = parent::Query($Sql, $InputParameters, $Options); // Aggregate the query times $TimeEnd = Now(); $this->_ExecutionTime += $TimeEnd - $TimeStart; if ($SaveQuery && !StringBeginsWith($Sql, 'set names')) { $Query['Time'] = $TimeEnd - $TimeStart; $this->_Queries[] = $Query; } return $Result; }
/** * Increments view count for the specified discussion. * * @since 2.0.0 * @access public * * @param int $DiscussionID Unique ID of discussion to get +1 view. */ public function AddView($DiscussionID, $Views = 0) { $Views++; if (C('Vanilla.Views.Denormalize', FALSE) && Gdn::Cache()->ActiveEnabled()) { $CacheKey = "QueryCache.Discussion.{$DiscussionID}.CountViews"; // Increment. If not success, create key. $Incremented = Gdn::Cache()->Increment($CacheKey); if ($Incremented === Gdn_Cache::CACHEOP_FAILURE) { Gdn::Cache()->Store($CacheKey, $Views); } // Every X views, writeback to Discussions if ($Views % C('Vanilla.Views.DenormalizeWriteback', 100) == 0) { Gdn::Database()->Query("UPDATE {$this->Database->DatabasePrefix}Discussion \n SET CountViews={$Views}\n WHERE DiscussionID={$DiscussionID}"); } } else { $this->SQL->Update('Discussion')->Set('CountViews', 'CountViews + 1', FALSE)->Where('DiscussionID', $DiscussionID)->Put(); } }
/** * Increments overall pageview view count * * @since 2.1a * @access public */ public function AddView($ViewType = 'normal') { // Add a pageview entry. $TimeSlot = date('Ymd'); $Px = Gdn::Database()->DatabasePrefix; $Views = 1; $EmbedViews = 0; try { if (C('Garden.Analytics.Views.Denormalize', FALSE) && Gdn::Cache()->ActiveEnabled()) { $CacheKey = "QueryCache.Analytics.CountViews"; // Increment. If not success, create key. $Incremented = Gdn::Cache()->Increment($CacheKey); if ($Incremented === Gdn_Cache::CACHEOP_FAILURE) { Gdn::Cache()->Store($CacheKey, 1); } // Get current cache value $Views = Gdn::Cache()->Get($CacheKey); if ($ViewType == 'embed') { $EmbedCacheKey = "QueryCache.Analytics.CountEmbedViews"; // Increment. If not success, create key. $EmbedIncremented = Gdn::Cache()->Increment($EmbedCacheKey); if ($EmbedIncremented === Gdn_Cache::CACHEOP_FAILURE) { Gdn::Cache()->Store($EmbedCacheKey, 1); } // Get current cache value $EmbedViews = Gdn::Cache()->Get($EmbedCacheKey); } // Every X views, writeback to AnalyticsLocal $DenormalizeWriteback = C('Garden.Analytics.Views.DenormalizeWriteback', 10); if ($Views % $DenormalizeWriteback == 0) { Gdn::Controller()->SetData('WritebackViews', $Views); Gdn::Controller()->SetData('WritebackEmbed', $EmbedViews); Gdn::Database()->Query("insert into {$Px}AnalyticsLocal (TimeSlot, Views, EmbedViews) values (:TimeSlot, {$Views}, {$EmbedViews})\n on duplicate key update \n Views = COALESCE(Views, 0)+{$Views}, \n EmbedViews = COALESCE(EmbedViews, 0)+{$EmbedViews}", array(':TimeSlot' => $TimeSlot)); // ... and get rid of those views from the keys if ($Views) { Gdn::Cache()->Decrement($CacheKey, $Views); } if ($EmbedViews) { Gdn::Cache()->Decrement($EmbedCacheKey, $EmbedViews); } } } else { $ExtraViews = 1; $ExtraEmbedViews = $ViewType == 'embed' ? 1 : 0; Gdn::Database()->Query("insert into {$Px}AnalyticsLocal (TimeSlot, Views, EmbedViews) values (:TimeSlot, {$ExtraViews}, {$ExtraEmbedViews})\n on duplicate key update \n Views = COALESCE(Views, 0)+{$ExtraViews}, \n EmbedViews = COALESCE(EmbedViews, 0)+{$ExtraEmbedViews}", array(':TimeSlot' => $TimeSlot)); } } catch (Exception $Ex) { if (Gdn::Session()->CheckPermission('Garden.Settings.Manage')) { throw $Ex; } } }
public function Save() { if (!$this->Dirty) { return NULL; } $this->EventArguments['ConfigDirty'] =& $this->Dirty; $this->EventArguments['ConfigNoSave'] = FALSE; $this->EventArguments['ConfigType'] = $this->Type; $this->EventArguments['ConfigSource'] = $this->Source; $this->EventArguments['ConfigData'] = $this->Settings; $this->FireEvent('BeforeSave'); if ($this->EventArguments['ConfigNoSave']) { $this->Dirty = FALSE; return TRUE; } // Check for and fire callback if one exists if ($this->Callback && is_callable($this->Callback)) { $CallbackOptions = array(); if (!is_array($this->CallbackOptions)) { $this->CallbackOptions = array(); } $CallbackOptions = array_merge($CallbackOptions, $this->CallbackOptions, array('ConfigDirty' => $this->Dirty, 'ConfigType' => $this->Type, 'ConfigSource' => $this->Source, 'ConfigData' => $this->Settings, 'SourceObject' => $this)); $ConfigSaved = call_user_func($this->Callback, $CallbackOptions); if ($ConfigSaved) { $this->Dirty = FALSE; return TRUE; } } switch ($this->Type) { case 'file': if (empty($this->Source)) { trigger_error(ErrorMessage('You must specify a file path to be saved.', 'Configuration', 'Save'), E_USER_ERROR); } $CheckWrite = $this->Source; if (!file_exists($CheckWrite)) { $CheckWrite = dirname($CheckWrite); } if (!is_writable($CheckWrite)) { throw new Exception(sprintf(T("Unable to write to config file '%s' when saving."), $this->Source)); } $Group = $this->Group; $Data =& $this->Settings; ksort($Data); // Check for the case when the configuration is the group. if (is_array($Data) && count($Data) == 1 && array_key_exists($Group, $Data)) { $Data = $Data[$Group]; } // Do a sanity check on the config save. if ($this->Source == Gdn::Config()->DefaultPath()) { // Log root config changes try { $LogData = $this->Initial; $LogData['_New'] = $this->Settings; LogModel::Insert('Edit', 'Configuration', $LogData); } catch (Exception $Ex) { } if (!isset($Data['Database'])) { if ($Pm = Gdn::PluginManager()) { $Pm->EventArguments['Data'] = $Data; $Pm->EventArguments['Backtrace'] = debug_backtrace(); $Pm->FireEvent('ConfigError'); } return FALSE; } } // Write config data to string format, ready for saving $FileContents = Gdn_Configuration::Format($Data, array('VariableName' => $Group, 'WrapPHP' => TRUE, 'ByLine' => TRUE)); if ($FileContents === FALSE) { trigger_error(ErrorMessage('Failed to define configuration file contents.', 'Configuration', 'Save'), E_USER_ERROR); } // Save to cache if we're into that sort of thing $FileKey = sprintf(Gdn_Configuration::CONFIG_FILE_CACHE_KEY, $this->Source); if ($this->Configuration && $this->Configuration->Caching() && Gdn::Cache()->Type() == Gdn_Cache::CACHE_TYPE_MEMORY && Gdn::Cache()->ActiveEnabled()) { $CachedConfigData = Gdn::Cache()->Store($FileKey, $Data, array(Gdn_Cache::FEATURE_NOPREFIX => TRUE, Gdn_Cache::FEATURE_EXPIRY => 3600)); } $TmpFile = tempnam(PATH_CONF, 'config'); $Result = FALSE; if (file_put_contents($TmpFile, $FileContents) !== FALSE) { chmod($TmpFile, 0775); $Result = rename($TmpFile, $this->Source); } if ($Result && function_exists('apc_delete_file')) { // This fixes a bug with some configurations of apc. @apc_delete_file($this->Source); } $this->Dirty = FALSE; return $Result; break; case 'json': case 'array': case 'string': /** * How would these even save? String config data must be handled by * an event hook or callback, if at all. */ $this->Dirty = FALSE; return FALSE; break; } }
/** * Executes a string of SQL. Returns a @@DataSet object. * * @param string $Sql A string of SQL to be executed. * @param array $InputParameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. */ public function Query($Sql, $InputParameters = NULL, $Options = array()) { if ($Sql == '') { trigger_error(ErrorMessage('Database was queried with an empty string.', $this->ClassName, 'Query'), E_USER_ERROR); } // Get the return type. if (isset($Options['ReturnType'])) { $ReturnType = $Options['ReturnType']; } elseif (preg_match('/^\\s*"?(insert)\\s+/i', $Sql)) { $ReturnType = 'ID'; } elseif (!preg_match('/^\\s*"?(update|delete|replace|create|drop|load data|copy|alter|grant|revoke|lock|unlock)\\s+/i', $Sql)) { $ReturnType = 'DataSet'; } else { $ReturnType = NULL; } if (isset($Options['Cache'])) { // Check to see if the query is cached. $CacheKeys = (array) GetValue('Cache', $Options, NULL); $CacheOperation = GetValue('CacheOperation', $Options, NULL); if (is_null($CacheOperation)) { switch ($ReturnType) { case 'DataSet': $CacheOperation = 'get'; break; case 'ID': case NULL: $CacheOperation = 'remove'; break; } } switch ($CacheOperation) { case 'get': foreach ($CacheKeys as $CacheKey) { $Data = Gdn::Cache()->Get($CacheKey); } // Cache hit. Return. if ($Data !== Gdn_Cache::CACHEOP_FAILURE) { return new Gdn_DataSet($Data); } // Cache miss. Save later. $StoreCacheKey = $CacheKey; break; case 'increment': case 'decrement': $CacheMethod = ucfirst($CacheOperation); foreach ($CacheKeys as $CacheKey) { $CacheResult = Gdn::Cache()->{$CacheMethod}($CacheKey); } break; case 'remove': foreach ($CacheKeys as $CacheKey) { $Res = Gdn::Cache()->Remove($CacheKey); } break; } } // Make sure other unbufferred queries are not open if (is_object($this->_CurrentResultSet)) { $this->_CurrentResultSet->Result(); $this->_CurrentResultSet->FreePDOStatement(FALSE); } // Run the Query if (!is_null($InputParameters) && count($InputParameters) > 0) { $PDOStatement = $this->Connection()->prepare($Sql); if (!is_object($PDOStatement)) { trigger_error(ErrorMessage('PDO Statement failed to prepare', $this->ClassName, 'Query', $this->GetPDOErrorMessage($this->Connection()->errorInfo())), E_USER_ERROR); } else { if ($PDOStatement->execute($InputParameters) === FALSE) { trigger_error(ErrorMessage($this->GetPDOErrorMessage($PDOStatement->errorInfo()), $this->ClassName, 'Query', $Sql), E_USER_ERROR); } } } else { $PDOStatement = $this->Connection()->query($Sql); } if ($PDOStatement === FALSE) { trigger_error(ErrorMessage($this->GetPDOErrorMessage($this->Connection()->errorInfo()), $this->ClassName, 'Query', $Sql), E_USER_ERROR); } // Did this query modify data in any way? if ($ReturnType == 'ID') { $this->_CurrentResultSet = $this->Connection()->lastInsertId(); if (is_a($PDOStatement, 'PDOStatement')) { $PDOStatement->closeCursor(); } } else { if ($ReturnType == 'DataSet') { // Create a DataSet to manage the resultset $this->_CurrentResultSet = new Gdn_DataSet(); $this->_CurrentResultSet->Connection = $this->Connection(); $this->_CurrentResultSet->PDOStatement($PDOStatement); } elseif (is_a($PDOStatement, 'PDOStatement')) { $PDOStatement->closeCursor(); } } if (isset($StoreCacheKey)) { if ($CacheOperation == 'get') { Gdn::Cache()->Store($StoreCacheKey, $this->_CurrentResultSet instanceof Gdn_DataSet ? $this->_CurrentResultSet->ResultArray() : $this->_CurrentResultSet, GetValue('CacheOptions', $Options, array())); } } return $this->_CurrentResultSet; }
public static function SetUserRoles(&$Users, $UserIDColumn = 'UserID', $RolesColumn = 'Roles') { $UserIDs = array_unique(ConsolidateArrayValuesByKey($Users, $UserIDColumn)); // Try and get all of the mappings from the cache. $Keys = array(); foreach ($UserIDs as $UserID) { $Keys[$UserID] = FormatString(UserModel::USERROLES_KEY, array('UserID' => $UserID)); } $UserRoles = Gdn::Cache()->Get($Keys); if (!is_array($UserRoles)) { $UserRoles = array(); } // Grab all of the data that doesn't exist from the DB. $MissingIDs = array(); foreach ($Keys as $UserID => $Key) { if (!array_key_exists($Key, $UserRoles)) { $MissingIDs[$UserID] = $Key; } } if (count($MissingIDs) > 0) { $DbUserRoles = Gdn::SQL()->Select('ur.*')->From('UserRole ur')->WhereIn('ur.UserID', array_keys($MissingIDs))->Get()->ResultArray(); $DbUserRoles = Gdn_DataSet::Index($DbUserRoles, 'UserID', array('Unique' => FALSE)); // Store the user role mappings. foreach ($DbUserRoles as $UserID => $Rows) { $RoleIDs = ConsolidateArrayValuesByKey($Rows, 'RoleID'); $Key = $Keys[$UserID]; Gdn::Cache()->Store($Key, $RoleIDs); $UserRoles[$Key] = $RoleIDs; } } $AllRoles = self::Roles(); // roles indexed by role id. // Skip personal info roles if (!CheckPermission('Garden.PersonalInfo.View')) { $AllRoles = array_filter($AllRoles, 'self::FilterPersonalInfo'); } // Join the users. foreach ($Users as &$User) { $UserID = GetValue($UserIDColumn, $User); $Key = $Keys[$UserID]; $RoleIDs = GetValue($Key, $UserRoles, array()); $Roles = array(); foreach ($RoleIDs as $RoleID) { if (!array_key_exists($RoleID, $AllRoles)) { continue; } $Roles[$RoleID] = $AllRoles[$RoleID]['Name']; } SetValue($RolesColumn, $User, $Roles); } }
public function RemovePageCache($DiscussionID, $From = 1) { if (!Gdn::Cache()->ActiveEnabled()) { return; } $CountComments = $this->SQL->GetWhere('Discussion', array('DiscussionID' => $DiscussionID))->Value('CountComments'); $PageCount = PageNumber($CountComments - 1, C('Vanilla.Comments.PerPage', 30)); for ($Page = $From; $Page <= $PageCount; $Page++) { $CacheKey = "Comment.Page.{$DiscussionID}.{$Page}"; Gdn::Cache()->Remove($CacheKey); } }
/** * Select content based on its Score * * @param array $Parameters * @todo complete * @return boolean */ protected function SelectByScore($Parameters) { if (!is_array($Parameters)) { $MinScore = $Parameters; } else { $MinScore = GetValue('Score', $Parameters, NULL); } if (!is_integer($MinScore)) { $MinScore = FALSE; } // Check cache $SelectorScoreCacheKey = "modules.promotedcontent.score.{$Score}"; $Content = Gdn::Cache()->Get($SelectorScoreCacheKey); if ($Content == Gdn_Cache::CACHEOP_FAILURE) { // Get matching Discussions $Discussions = Gdn::SQL()->Select('d.*')->From('Discussion d')->Where('Score >', $MinScore)->OrderBy('Score', 'DESC')->Limit($this->Limit); if ($MinScore !== FALSE) { $Discussions->Where('Score >', $MinScore); } $Discussions = $Discussions->Get()->Result(DATASET_TYPE_ARRAY); // Get matching Comments $Comments = Gdn::SQL()->Select('c.*')->From('Comment c')->OrderBy('Score', 'DESC')->Limit($this->Limit); if ($MinScore !== FALSE) { $Comments->Where('Score >', $MinScore); } $Comments = $Comments->Get()->Result(DATASET_TYPE_ARRAY); $this->JoinCategory($Comments); // Interleave $Content = $this->Union('DateInserted', array('Discussion' => $Discussions, 'Comment' => $Comments)); $this->Prepare($Content); // Add result to cache Gdn::Cache()->Store($SelectorScoreCacheKey, $Content, array(Gdn_Cache::FEATURE_EXPIRY => $this->Expiry)); } $this->Security($Content); $this->Condense($Content, $this->Limit); return $Content; }
/** * Takes a set of discussion identifiers and returns their comment counts in the same order. */ public function GetCommentCounts() { $this->AllowJSONP(TRUE); $vanilla_identifier = GetValue('vanilla_identifier', $_GET); if (!is_array($vanilla_identifier)) { $vanilla_identifier = array($vanilla_identifier); } $vanilla_identifier = array_unique($vanilla_identifier); $FinalData = array_fill_keys($vanilla_identifier, 0); $Misses = array(); $CacheKey = 'embed.comments.count.%s'; $OriginalIDs = array(); foreach ($vanilla_identifier as $ForeignID) { $HashedForeignID = ForeignIDHash($ForeignID); // Keep record of non-hashed identifiers for the reply $OriginalIDs[$HashedForeignID] = $ForeignID; $RealCacheKey = sprintf($CacheKey, $HashedForeignID); $Comments = Gdn::Cache()->Get($RealCacheKey); if ($Comments !== Gdn_Cache::CACHEOP_FAILURE) { $FinalData[$ForeignID] = $Comments; } else { $Misses[] = $HashedForeignID; } } if (sizeof($Misses)) { $CountData = Gdn::SQL()->Select('ForeignID, CountComments')->From('Discussion')->Where('Type', 'page')->WhereIn('ForeignID', $Misses)->Get()->ResultArray(); foreach ($CountData as $Row) { // Get original identifier to send back $ForeignID = $OriginalIDs[$Row['ForeignID']]; $FinalData[$ForeignID] = $Row['CountComments']; // Cache using the hashed identifier $RealCacheKey = sprintf($CacheKey, $Row['ForeignID']); Gdn::Cache()->Store($RealCacheKey, $Row['CountComments'], array(Gdn_Cache::FEATURE_EXPIRY => 60)); } } $this->SetData('CountData', $FinalData); $this->DeliveryMethod = DELIVERY_METHOD_JSON; $this->DeliveryType = DELIVERY_TYPE_DATA; $this->Render(); }
public function Gdn_Statistics_Tick_Handler($Sender, $Args) { $Path = Gdn::Request()->Post('Path'); $Args = Gdn::Request()->Post('Args'); parse_str($Args, $Args); $ResolvedPath = trim(Gdn::Request()->Post('ResolvedPath'), '/'); $ResolvedArgs = @json_decode(Gdn::Request()->Post('ResolvedArgs')); $DiscussionID = NULL; $DiscussionModel = new DiscussionModel(); // Gdn::Controller()->SetData('Path', $Path); // Gdn::Controller()->SetData('Args', $Args); // Gdn::Controller()->SetData('ResolvedPath', $ResolvedPath); // Gdn::Controller()->SetData('ResolvedArgs', $ResolvedArgs); // Comment permalink if ($ResolvedPath == 'vanilla/discussion/comment') { $CommentID = GetValue('CommentID', $ResolvedArgs); $CommentModel = new CommentModel(); $Comment = $CommentModel->GetID($CommentID); $DiscussionID = GetValue('DiscussionID', $Comment); } elseif ($ResolvedPath == 'vanilla/discussion/index') { $DiscussionID = GetValue('DiscussionID', $ResolvedArgs, NULL); } elseif ($ResolvedPath == 'vanilla/discussion/embed') { $ForeignID = GetValue('vanilla_identifier', $Args); if ($ForeignID) { // This will be hit a lot so let's try caching it... $Key = "DiscussionID.ForeignID.page.{$ForeignID}"; $DiscussionID = Gdn::Cache()->Get($Key); if (!$DiscussionID) { $Discussion = $DiscussionModel->GetForeignID($ForeignID, 'page'); $DiscussionID = GetValue('DiscussionID', $Discussion); Gdn::Cache()->Store($Key, $DiscussionID, array(Gdn_Cache::FEATURE_EXPIRY, 1800)); } } } if ($DiscussionID) { $DiscussionModel->AddView($DiscussionID); } }
/** * @param DiscussionsController $Sender * @param array $Args */ public function DiscussionsController_UnansweredCount_Create($Sender, $Args = array()) { Gdn::SQL()->WhereIn('QnA', array('Unanswered', 'Rejected')); $Count = Gdn::SQL()->GetCount('Discussion', array('Type' => 'Question')); Gdn::Cache()->Store('QnA-UnansweredCount', $Count, array(Gdn_Cache::FEATURE_EXPIRY => 15 * 60)); $Sender->SetData('UnansweredCount', $Count); $Sender->SetData('_Value', $Count); $Sender->Render('Value', 'Utility', 'Dashboard'); }
/** * Sets UserMeta data to the UserMeta table * * This method takes a UserID, Key, and Value, and attempts to set $Key = $Value for $UserID. * $Key can be an SQL wildcard, thereby allowing multiple variations of a $Key to be set. $UserID * can be an array, thereby allowing multiple users' $Keys to be set to the same $Value. * * ++ Before any queries are run, $Key is converted to its fully qualified format (Plugin.<PluginName> prepended) * ++ to prevent collisions in the meta table when multiple plugins have similar key names. * * If $Value == NULL, the matching row(s) are deleted instead of updated. * * @param $UserID int UserID or array of UserIDs * @param $Key string relative user key * @param $Value mixed optional value to set, null to delete * @return void */ public function SetUserMeta($UserID, $Key, $Value = NULL) { if (Gdn::Cache()->ActiveEnabled()) { if (is_array($UserID)) { foreach ($UserID as $ID) { $this->SetUserMeta($ID, $Key, $Value); } return; } $UserMeta = $this->GetUserMeta($UserID); if (!stristr($Key, '%')) { if ($Value === NULL) { unset($UserMeta[$Key]); } else { $UserMeta[$Key] = $Value; } } else { $MatchKey = str_replace('%', '*', $Key); foreach ($UserMeta as $UserMetaKey => $UserMetaValue) { if (fnmatch($MatchKey, $UserMetaKey)) { if ($Value === NULL) { unset($UserMeta[$UserMetaKey]); } else { $UserMeta[$UserMetaKey] = $Value; } } } } $CacheKey = 'UserMeta_' . $UserID; Gdn::Cache()->Store($CacheKey, $UserMeta); // Update the DB. $this->SQL->Reset(); if ($Value === NULL) { $Q = $this->SQL->Where('UserID', $UserID); if (stristr($Key, '%')) { $Q->Like('Name', $Key); } else { $Q->Where('Name', $Key); } $Q->Delete('UserMeta'); } else { $Px = $this->SQL->Database->DatabasePrefix; $Sql = "insert {$Px}UserMeta (UserID, Name, Value) values(:UserID, :Name, :Value) on duplicate key update Value = :Value1"; $Params = array(':UserID' => $UserID, ':Name' => $Key, ':Value' => $Value, ':Value1' => $Value); $this->Database->Query($Sql, $Params); } return; } if (is_null($Value)) { // Delete $UserMetaQuery = Gdn::SQL(); if (is_array($UserID)) { $UserMetaQuery->WhereIn('UserID', $UserID); } else { $UserMetaQuery->Where('UserID', $UserID); } if (stristr($Key, '%')) { $UserMetaQuery->Like('Name', $Key); } else { $UserMetaQuery->Where('Name', $Key); } $UserMetaQuery->Delete('UserMeta'); } else { // Set if (!is_array($UserID)) { $UserID = array($UserID); } foreach ($UserID as $UID) { try { Gdn::SQL()->Insert('UserMeta', array('UserID' => $UID, 'Name' => $Key, 'Value' => $Value)); } catch (Exception $e) { Gdn::SQL()->Update('UserMeta', array('Value' => $Value), array('UserID' => $UID, 'Name' => $Key))->Put(); } } } return; }
public function ClearPluginCache($SearchPaths = NULL) { if (!is_null($SearchPaths)) { if (!is_array($SearchPaths)) { $SearchPaths = array($SearchPaths); } } else { $SearchPaths = $this->SearchPaths(); } foreach ($SearchPaths as $SearchPath => $SearchPathName) { $SearchPathCacheKey = "Garden.Plugins.PathCache.{$SearchPath}"; if ($this->Apc) { apc_delete($SearchPathCacheKey); } else { Gdn::Cache()->Remove($SearchPathCacheKey, array(Gdn_Cache::FEATURE_NOPREFIX => TRUE)); } } }
/** * Save the provided library's data to the on disk location. * * @param string $CacheName name of cache library * @return void */ public static function SaveCache($CacheName) { if ($CacheName != 'locale') { return; } if (!array_key_exists($CacheName, self::$Caches)) { return FALSE; } $UseCache = Gdn::Cache()->Type() == Gdn_Cache::CACHE_TYPE_MEMORY && Gdn::Cache()->ActiveEnabled(); if ($UseCache) { $CacheKey = sprintf(Gdn_LibraryMap::CACHE_CACHE_NAME_FORMAT, $CacheName); $Stored = Gdn::Cache()->Store($CacheKey, self::$Caches[$CacheName]['cache']); } else { $FileName = self::$Caches[$CacheName]['ondisk']; $CacheContents = ""; foreach (self::$Caches[$CacheName]['cache'] as $SectionTitle => $SectionData) { $CacheContents .= "[{$SectionTitle}]\n"; foreach ($SectionData as $StoreKey => $StoreValue) { $CacheContents .= "{$StoreKey} = \"{$StoreValue}\"\n"; } } try { Gdn_FileSystem::SaveFile(PATH_CACHE . DS . $FileName, $CacheContents, LOCK_EX); } catch (Exception $e) { } } }
/** * Grab and update the category cache * * @since 2.0.18 * @access public * @param int $ID * @param array $Data */ public static function SetCache($ID = FALSE, $Data = FALSE) { $Categories = Gdn::Cache()->Get(self::CACHE_KEY); self::$Categories = NULL; if (!$Categories) { return; } if (!$ID || !is_array($Categories)) { Gdn::Cache()->Remove(self::CACHE_KEY); return; } if (!array_key_exists($ID, $Categories)) { Gdn::Cache()->Remove(self::CACHE_KEY); return; } $Category = $Categories[$ID]; $Category = array_merge($Category, $Data); $Categories[$ID] = $Category; self::$Categories = $Categories; unset($Categories); self::BuildCache(); self::JoinUserData(self::$Categories, TRUE); }
public function GetPermissionsIncrement() { $PermissionsIncrementKey = self::INC_PERMISSIONS_KEY; $PermissionsKeyValue = Gdn::Cache()->Get($PermissionsIncrementKey); if (!$PermissionsKeyValue) { $Stored = Gdn::Cache()->Store($PermissionsIncrementKey, 1); return $Stored ? 1 : FALSE; } return $PermissionsKeyValue; }