protected function getBirthdays() { $birthdays = json_decode(Gdn::get('BirthdayModule.Birthdays')); $token = date('y-m-d/H'); if ($birthdays && $birthdays[0] == $token) { return $birthdays[1]; } $date = new DateTime(); if ($guestTimeZone = C('Garden.GuestTimeZone')) { try { $timeZone = new DateTimeZone($guestTimeZone); $offset = $timeZone->getOffset(new DateTime('now', new DateTimeZone('UTC'))); $offset = -floor($offset / 3600); $date->modify("{$offset} hours"); } catch (Exception $e) { } } $birthdays = Gdn::sql()->select('UserID')->from('User')->where("DATE_FORMAT(DateOfBirth, '%m-%d')", $date->format("'m-d'"), false, false)->get()->resultArray(); $birthdays = array_column($birthdays, 'UserID'); Gdn::set('BirthdayModule.Birthdays', json_encode([$token, $birthdays])); return $birthdays; }
/** * Statistics setup & configuration. * * @since 2.0.17 * @access public */ public function index() { $this->permission('Garden.Settings.Manage'); $this->addSideMenu('dashboard/statistics'); //$this->addJsFile('statistics.js'); $this->title(t('Vanilla Statistics')); $this->enableSlicing($this); if ($this->Form->authenticatedPostBack()) { $Flow = true; if ($Flow && $this->Form->getFormValue('Reregister')) { $id = Gdn::installationID(); $secret = Gdn::installationSecret(); Gdn::installationID(false); Gdn::installationSecret(false); Gdn::Statistics()->register(); if (!Gdn::installationID()) { Gdn::installationID($id); Gdn::installationSecret($secret); } $this->Form->setFormValue('InstallationID', Gdn::installationID()); $this->Form->setFormValue('InstallationSecret', Gdn::installationSecret()); } if ($Flow && $this->Form->getFormValue('Save')) { Gdn::installationID($this->Form->getFormValue('InstallationID')); Gdn::installationSecret($this->Form->getFormValue('InstallationSecret')); $this->informMessage(t("Your settings have been saved.")); } if ($Flow && $this->Form->getFormValue('AllowLocal')) { saveToConfig('Garden.Analytics.AllowLocal', true); } if ($Flow && $this->Form->getFormValue('Allow')) { saveToConfig('Garden.Analytics.Enabled', true); } if ($Flow && $this->Form->getFormValue('ClearCredentials')) { Gdn::installationID(false); Gdn::installationSecret(false); Gdn::statistics()->Tick(); $Flow = false; } } else { $this->Form->setValue('InstallationID', Gdn::installationID()); $this->Form->setValue('InstallationSecret', Gdn::installationSecret()); } $AnalyticsEnabled = Gdn_Statistics::checkIsEnabled(); if ($AnalyticsEnabled) { $ConfFile = Gdn::config()->defaultPath(); $this->setData('ConfWritable', $ConfWritable = is_writable($ConfFile)); if (!$ConfWritable) { $AnalyticsEnabled = false; } } $this->setData('AnalyticsEnabled', $AnalyticsEnabled); $NotifyMessage = Gdn::get('Garden.Analytics.Notify', false); $this->setData('NotifyMessage', $NotifyMessage); if ($NotifyMessage !== false) { Gdn::set('Garden.Analytics.Notify', null); } $this->render(); }
/** * * * @param $Table * @param $Key * @param int $Limit * @param bool $Max * @return array|mixed */ public function getBatch($Table, $Key, $Limit = 10000, $Max = false) { $Key = "DBA.Range.{$Key}"; // See if there is already a range. $Current = @unserialize(Gdn::get($Key, '')); if (!is_array($Current) || !isset($Current['Min']) || !isset($Current['Max'])) { list($Current['Min'], $Current['Max']) = $this->primaryKeyRange($Table); if ($Max && $Current['Max'] > $Max) { $Current['Max'] = $Max; } } if (!isset($Current['To'])) { $Current['To'] = $Current['Max']; } else { $Current['To'] -= $Limit - 1; } $Current['From'] = $Current['To'] - $Limit; Gdn::set($Key, serialize($Current)); $Current['Complete'] = $Current['To'] < $Current['Min']; $Total = $Current['Max'] - $Current['Min']; if ($Total > 0) { $Complete = $Current['Max'] - $Current['From']; $Percent = 100 * $Complete / $Total; if ($Percent > 100) { $Percent = 100; } $Current['Percent'] = round($Percent) . '%'; } return $Current; }
/** * This is the asynchronous callback. * * This method is triggerd on every page request via a callback AJAX request * so that it may execute asychronously and reduce lag for users. It tracks * views, handles registration for new installations, and sends stats every day as needed. * * @return void */ public function tick() { // Fire an event for plugins to track their own stats. // TODO: Make this analyze the path and throw a specific event (this event will change in future versions). $this->EventArguments['Path'] = Gdn::Request()->Post('Path'); $this->fireEvent('Tick'); // Store the view, using denormalization if enabled $ViewType = 'normal'; if (preg_match('`discussion/embed`', Gdn::request()->post('ResolvedPath', ''))) { $ViewType = 'embed'; } $this->addView($ViewType); if (Gdn::session()->isValid()) { Gdn::userModel()->updateVisit(Gdn::session()->UserID); } if (!self::checkIsEnabled()) { return; } if (Gdn::session()->checkPermission('Garden.Settings.Manage')) { if (Gdn::get('Garden.Analytics.Notify', false) !== false) { $CallMessage = Sprite('Bandaid', 'InformSprite'); $CallMessage .= sprintf(T("There's a problem with Vanilla Analytics that needs your attention.<br/> Handle it <a href=\"%s\">here »</a>"), Url('dashboard/statistics')); Gdn::controller()->informMessage($CallMessage, array('CssClass' => 'HasSprite')); } } $InstallationID = Gdn::installationID(); // Check if we're registered with the central server already. If not, this request is // hijacked and used to perform that task instead of sending stats or recording a tick. if (is_null($InstallationID)) { // If the config file is not writable, gtfo $ConfFile = PATH_CONF . '/config.php'; if (!is_writable($ConfFile)) { // Admins see a helpful notice if (Gdn::session()->checkPermission('Garden.Settings.Manage')) { $Warning = sprite('Sliders', 'InformSprite'); $Warning .= T('Your config.php file is not writable.<br/> Find out <a href="http://vanillaforums.org/docs/vanillastatistics">how to fix this »</a>'); Gdn::controller()->informMessage($Warning, array('CssClass' => 'HasSprite')); } return; } $AttemptedRegistration = Gdn::get('Garden.Analytics.Registering', false); // If we last attempted to register less than 60 seconds ago, do nothing. Could still be working. if ($AttemptedRegistration !== false && time() - $AttemptedRegistration < 60) { return; } return $this->register(); } // If we get here, the installation is registered and we can decide on whether or not to send stats now. $LastSentDate = self::lastSentDate(); if (empty($LastSentDate) || $LastSentDate < date('Ymd', strtotime('-1 day'))) { return $this->stats(); } }
/** * Run a structure update on the database. * * It should always be possible to call this method, even if no database tables exist yet. * A working forum database should be built from scratch where none exists. Therefore, * it can have no reliance on existing data calls, or they must be able to fail gracefully. * * @since 2.0.? * @access public */ public function update() { // Check for permission or flood control. // These settings are loaded/saved to the database because we don't want the config file storing non/config information. $Now = time(); $LastTime = 0; $Count = 0; try { $LastTime = Gdn::get('Garden.Update.LastTimestamp', 0); } catch (Exception $Ex) { // We don't have a GDN_UserMeta table yet. Sit quietly and one will appear. } if ($LastTime + 60 * 60 * 24 > $Now) { // Check for flood control. try { $Count = Gdn::get('Garden.Update.Count', 0) + 1; } catch (Exception $Ex) { // Once more we sit, watching the breath. } if ($Count > 5) { if (!Gdn::session()->checkPermission('Garden.Settings.Manage')) { // We are only allowing an update of 5 times every 24 hours. throw permissionException(); } } } else { $Count = 1; } try { Gdn::set('Garden.Update.LastTimestamp', $Now); Gdn::set('Garden.Update.Count', $Count); } catch (Exception $Ex) { // What is a GDN_UserMeta table, really? Suffering. } try { // Run the structure. $UpdateModel = new UpdateModel(); $UpdateModel->runStructure(); $this->setData('Success', true); } catch (Exception $Ex) { $this->setData('Success', false); $this->setData('Error', $Ex->getMessage()); if (Debug()) { throw $Ex; } } if (Gdn::session()->checkPermission('Garden.Settings.Manage')) { saveToConfig('Garden.Version', APPLICATION_VERSION); } if ($Target = $this->Request->get('Target')) { safeRedirect($Target); } $this->fireEvent('AfterUpdate'); $this->MasterView = 'empty'; $this->CssClass = 'Home'; $this->render(); }
/** * Run a structure update on the database. * * @since 2.0.? * @access public */ public function update() { try { // Check for permission or flood control. // These settings are loaded/saved to the database because we don't want the config file storing non/config information. $Now = time(); $LastTime = Gdn::get('Garden.Update.LastTimestamp', 0); if ($LastTime + 60 * 60 * 24 > $Now) { // Check for flood control. $Count = Gdn::get('Garden.Update.Count', 0) + 1; if ($Count > 5) { if (!Gdn::session()->checkPermission('Garden.Settings.Manage')) { // We are only allowing an update of 5 times every 24 hours. throw permissionException(); } } } else { $Count = 1; } Gdn::set('Garden.Update.LastTimestamp', $Now); Gdn::set('Garden.Update.Count', $Count); } catch (PermissionException $Ex) { return; } catch (Exception $Ex) { } try { // Run the structure. $UpdateModel = new UpdateModel(); $UpdateModel->runStructure(); $this->setData('Success', true); } catch (Exception $Ex) { $this->setData('Success', false); if (Debug()) { throw $Ex; } } if (Gdn::session()->checkPermission('Garden.Settings.Manage')) { saveToConfig('Garden.Version', APPLICATION_VERSION); } if ($Target = $this->Request->get('Target')) { redirect($Target); } $this->fireEvent('AfterUpdate'); $this->MasterView = 'empty'; $this->CssClass = 'Home'; $this->render(); }