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();
     }
 }
Example #4
0
 /**
  * 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;
 }
Example #5
0
 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));
     }
 }
Example #6
0
 /**
  *
  *
  * @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;
 }
Example #7
0
 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();
 }
Example #9
0
 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;
 }
Example #10
0
<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;
 }
Example #12
0
 /**
  * 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;
 }
Example #14
0
 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;
 }
Example #16
0
 /**
  * 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();
     }
 }
Example #17
0
 /**
  * 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;
         }
     }
 }
Example #18
0
 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);
     }
 }
Example #21
0
 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();
 }
Example #24
0
 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) {
         }
     }
 }
Example #29
0
 /**
  * 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;
 }