Get a reference to the user model.
public static userModel ( ) : UserModel | ||
return | UserModel |
public function pluginController_quoteMention_create($sender, $discussionID, $commentID, $username) { $sender->deliveryMethod(DELIVERY_METHOD_JSON); $user = Gdn::userModel()->getByUsername($username); $discussionModel = new DiscussionModel(); $discussion = $discussionModel->getID($discussionID); if (!$user || !$discussion) { throw notFoundException(); } // Make sure this endpoint can't be used to snoop around. $sender->permission('Vanilla.Discussions.View', true, 'Category', $discussion->PermissionCategoryID); // Find the previous comment of the mentioned user in this discussion. $item = Gdn::sql()->getWhere('Comment', ['DiscussionID' => $discussion->DiscussionID, 'InsertUserID' => $user->UserID, 'CommentID <' => $commentID], 'CommentID', 'desc', 1)->firstRow(); // The items ID in the DOM used for highlighting. if ($item) { $target = '#Comment_' . $item->CommentID; // The mentioned user might be the discussion creator. } elseif ($discussion->InsertUserID == $user->UserID) { $item = $discussion; $target = '#Discussion_' . $item->DiscussionID; } if (!$item) { // A success response code always means that a comment was found. $sender->statusCode(404); } $sender->renderData($item ? ['html' => nl2br(sliceString(Gdn_Format::plainText($item->Body, $item->Format), c('QuoteMention.MaxLength', 400))), 'target' => $target] : []); }
/** * Custom finalization. * * @throws Exception */ public function afterImport() { // Set up the routes to redirect from their older counterparts. $Router = Gdn::router(); // Categories $Router->SetRoute('forumdisplay\\.php\\?f=(\\d+)', 'categories/$1', 'Permanent'); $Router->SetRoute('archive\\.php/f-(\\d+)\\.html', 'categories/$1', 'Permanent'); // Discussions & Comments $Router->SetRoute('showthread\\.php\\?t=(\\d+)', 'discussion/$1', 'Permanent'); //$Router->SetRoute('showthread\.php\?p=(\d+)', 'discussion/comment/$1#Comment_$1', 'Permanent'); //$Router->SetRoute('showpost\.php\?p=(\d+)', 'discussion/comment/$1#Comment_$1', 'Permanent'); $Router->SetRoute('archive\\.php/t-(\\d+)\\.html', 'discussion/$1', 'Permanent'); // Profiles $Router->SetRoute('member\\.php\\?u=(\\d+)', 'profile/$1/x', 'Permanent'); $Router->SetRoute('usercp\\.php', 'profile', 'Permanent'); $Router->SetRoute('profile\\.php', 'profile', 'Permanent'); // Other $Router->SetRoute('attachment\\.php\\?attachmentid=(\\d+)', 'discussion/download/$1', 'Permanent'); $Router->SetRoute('search\\.php', 'discussions', 'Permanent'); $Router->SetRoute('private\\.php', 'messages/all', 'Permanent'); $Router->SetRoute('subscription\\.php', 'discussions/bookmarked', 'Permanent'); // Make different sizes of avatars $this->ProcessAvatars(); // Prep config for ProfileExtender plugin based on imported fields $this->ProfileExtenderPrep(); // Set guests to System user to prevent security issues $SystemUserID = Gdn::userModel()->GetSystemUserID(); $this->SQL->update('Discussion')->set('InsertUserID', $SystemUserID)->where('InsertUserID', 0)->put(); $this->SQL->update('Comment')->set('InsertUserID', $SystemUserID)->where('InsertUserID', 0)->put(); }
/** * Create the default admin user. * * @return void */ protected function adminUser() { $UserModel = Gdn::userModel(); $UserModel->defineSchema(); $user = ['Name' => getenv('VANILLA_ADMIN_NAME'), 'Email' => getenv('VANILLA_ADMIN_EMAIL'), 'Password' => getenv('VANILLA_ADMIN_PASSWORD')]; $AdminUserID = $UserModel->SaveAdminUser($user); }
public function loadData() { $UserID = Gdn::controller()->data('Profile.UserID', Gdn::session()->UserID); $this->User = Gdn::userModel()->getID($UserID); $this->Roles = Gdn::userModel()->GetRoles($UserID)->resultArray(); // Hide personal info roles if (!checkPermission('Garden.PersonalInfo.View')) { $this->Roles = array_filter($this->Roles, 'RoleModel::FilterPersonalInfo'); } }
/** * Check whether or not the record is spam. * @param string $RecordType By default, this should be one of the following: * - Comment: A comment. * - Discussion: A discussion. * - User: A user registration. * @param array $Data The record data. * @param array $Options Options for fine-tuning this method call. * - Log: Log the record if it is found to be spam. */ public static function isSpam($RecordType, $Data, $Options = array()) { if (self::$Disabled) { return false; } // Set some information about the user in the data. if ($RecordType == 'Registration') { touchValue('Username', $Data, $Data['Name']); } else { touchValue('InsertUserID', $Data, Gdn::session()->UserID); $User = Gdn::userModel()->getID(val('InsertUserID', $Data), DATASET_TYPE_ARRAY); if ($User) { if (val('Verified', $User)) { // The user has been verified and isn't a spammer. return false; } touchValue('Username', $Data, $User['Name']); touchValue('Email', $Data, $User['Email']); touchValue('IPAddress', $Data, $User['LastIPAddress']); } } if (!isset($Data['Body']) && isset($Data['Story'])) { $Data['Body'] = $Data['Story']; } touchValue('IPAddress', $Data, Gdn::request()->ipAddress()); $Sp = self::_Instance(); $Sp->EventArguments['RecordType'] = $RecordType; $Sp->EventArguments['Data'] =& $Data; $Sp->EventArguments['Options'] =& $Options; $Sp->EventArguments['IsSpam'] = false; $Sp->fireEvent('CheckSpam'); $Spam = $Sp->EventArguments['IsSpam']; // Log the spam entry. if ($Spam && val('Log', $Options, true)) { $LogOptions = array(); switch ($RecordType) { case 'Registration': $LogOptions['GroupBy'] = array('RecordIPAddress'); break; case 'Comment': case 'Discussion': case 'Activity': case 'ActivityComment': $LogOptions['GroupBy'] = array('RecordID'); break; } LogModel::insert('Spam', $RecordType, $Data, $LogOptions); } return $Spam; }
/** * Post every new discussion to HipChat. * * @param PostController $sender * @param array $args */ public function discussionModel_afterSaveDiscussion_handler($sender, $args) { // Make sure we have a valid discussion. if (!$args['Discussion'] || !val('DiscussionID', $args['Discussion'])) { return; } // Only trigger for new discussions. if (!$args['Insert']) { return; } // Prep HipChat message. $author = Gdn::userModel()->getID(val('InsertUserID', $args['Discussion'])); $message = sprintf('%1$s: %2$s', userAnchor($author), anchor(val('Name', $args['Discussion']), discussionUrl($args['Discussion']))); // Say it. self::sayInHipChat($message); }
/** * Delete all of the Vanilla related information for a specific user. * * @since 2.1 * * @param int $userID The ID of the user to delete. * @param array $options An array of options: * - DeleteMethod: One of delete, wipe, or NULL */ public function deleteUserData($userID, $options = array(), &$data = null) { $sql = Gdn::sql(); // Remove discussion watch records and drafts. $sql->delete('UserDiscussion', array('UserID' => $userID)); Gdn::userModel()->getDelete('Draft', array('InsertUserID' => $userID), $data); // Comment deletion depends on method selected $deleteMethod = val('DeleteMethod', $options, 'delete'); if ($deleteMethod == 'delete') { // Get a list of category IDs that has this user as the most recent poster. $discussionCats = $sql->select('cat.CategoryID')->from('Category cat')->join('Discussion d', 'd.DiscussionID = cat.LastDiscussionID')->where('d.InsertUserID', $userID)->get()->resultArray(); $commentCats = $sql->select('cat.CategoryID')->from('Category cat')->join('Comment c', 'c.CommentID = cat.LastCommentID')->where('c.InsertUserID', $userID)->get()->resultArray(); $categoryIDs = array_unique(array_merge(array_column($discussionCats, 'CategoryID'), array_column($commentCats, 'CategoryID'))); // Grab all of the discussions that the user has engaged in. $discussionIDs = $sql->select('DiscussionID')->from('Comment')->where('InsertUserID', $userID)->groupBy('DiscussionID')->get()->resultArray(); $discussionIDs = array_column($discussionIDs, 'DiscussionID'); Gdn::userModel()->getDelete('Comment', array('InsertUserID' => $userID), $data); // Update the comment counts. $commentCounts = $sql->select('DiscussionID')->select('CommentID', 'count', 'CountComments')->select('CommentID', 'max', 'LastCommentID')->whereIn('DiscussionID', $discussionIDs)->groupBy('DiscussionID')->get('Comment')->resultArray(); foreach ($commentCounts as $row) { $sql->put('Discussion', array('CountComments' => $row['CountComments'] + 1, 'LastCommentID' => $row['LastCommentID']), array('DiscussionID' => $row['DiscussionID'])); } // Update the last user IDs. $sql->update('Discussion d')->join('Comment c', 'd.LastCommentID = c.CommentID', 'left')->set('d.LastCommentUserID', 'c.InsertUserID', false, false)->set('d.DateLastComment', 'coalesce(c.DateInserted, d.DateInserted)', false, false)->whereIn('d.DiscussionID', $discussionIDs)->put(); // Update the last posts. $discussions = $sql->whereIn('DiscussionID', $discussionIDs)->where('LastCommentUserID', $userID)->get('Discussion'); // Delete the user's discussions. Gdn::userModel()->getDelete('Discussion', array('InsertUserID' => $userID), $data); // Update the appropriate recent posts in the categories. $categoryModel = new CategoryModel(); foreach ($categoryIDs as $categoryID) { $categoryModel->setRecentPost($categoryID); } } elseif ($deleteMethod == 'wipe') { // Erase the user's discussions. $sql->update('Discussion')->set('Body', t('The user and all related content has been deleted.'))->set('Format', 'Deleted')->where('InsertUserID', $userID)->put(); $sql->update('Comment')->set('Body', t('The user and all related content has been deleted.'))->set('Format', 'Deleted')->where('InsertUserID', $userID)->put(); } else { // Leave comments } // Remove the user's profile information related to this application $sql->update('User')->set(array('CountDiscussions' => 0, 'CountUnreadDiscussions' => 0, 'CountComments' => 0, 'CountDrafts' => 0, 'CountBookmarks' => 0))->where('UserID', $userID)->put(); }
/** * Delete all of the Vanilla related information for a specific user. * * @since 2.1 * * @param int $UserID The ID of the user to delete. * @param array $Options An array of options: * - DeleteMethod: One of delete, wipe, or NULL */ public function deleteUserData($UserID, $Options = array(), &$Data = null) { $SQL = Gdn::sql(); // Remove discussion watch records and drafts. $SQL->delete('UserDiscussion', array('UserID' => $UserID)); Gdn::userModel()->GetDelete('Draft', array('InsertUserID' => $UserID), $Data); // Comment deletion depends on method selected $DeleteMethod = val('DeleteMethod', $Options, 'delete'); if ($DeleteMethod == 'delete') { // Clear out the last posts to the categories. $SQL->update('Category c')->join('Discussion d', 'd.DiscussionID = c.LastDiscussionID')->where('d.InsertUserID', $UserID)->set('c.LastDiscussionID', null)->set('c.LastCommentID', null)->put(); $SQL->update('Category c')->join('Comment d', 'd.CommentID = c.LastCommentID')->where('d.InsertUserID', $UserID)->set('c.LastDiscussionID', null)->set('c.LastCommentID', null)->put(); // Grab all of the discussions that the user has engaged in. $DiscussionIDs = $SQL->select('DiscussionID')->from('Comment')->where('InsertUserID', $UserID)->groupBy('DiscussionID')->get()->resultArray(); $DiscussionIDs = consolidateArrayValuesByKey($DiscussionIDs, 'DiscussionID'); Gdn::userModel()->GetDelete('Comment', array('InsertUserID' => $UserID), $Data); // Update the comment counts. $CommentCounts = $SQL->select('DiscussionID')->select('CommentID', 'count', 'CountComments')->select('CommentID', 'max', 'LastCommentID')->whereIn('DiscussionID', $DiscussionIDs)->groupBy('DiscussionID')->get('Comment')->resultArray(); foreach ($CommentCounts as $Row) { $SQL->put('Discussion', array('CountComments' => $Row['CountComments'] + 1, 'LastCommentID' => $Row['LastCommentID']), array('DiscussionID' => $Row['DiscussionID'])); } // Update the last user IDs. $SQL->update('Discussion d')->join('Comment c', 'd.LastCommentID = c.CommentID', 'left')->set('d.LastCommentUserID', 'c.InsertUserID', false, false)->set('d.DateLastComment', 'c.DateInserted', false, false)->whereIn('d.DiscussionID', $DiscussionIDs)->put(); // Update the last posts. $Discussions = $SQL->whereIn('DiscussionID', $DiscussionIDs)->where('LastCommentUserID', $UserID)->get('Discussion'); // Delete the user's dicussions Gdn::userModel()->GetDelete('Discussion', array('InsertUserID' => $UserID), $Data); // Update the appropriat recent posts in the categories. $CategoryModel = new CategoryModel(); $Categories = $CategoryModel->getWhere(array('LastDiscussionID' => null))->resultArray(); foreach ($Categories as $Category) { $CategoryModel->SetRecentPost($Category['CategoryID']); } } elseif ($DeleteMethod == 'wipe') { // Erase the user's dicussions $SQL->update('Discussion')->set('Body', t('The user and all related content has been deleted.'))->set('Format', 'Deleted')->where('InsertUserID', $UserID)->put(); $SQL->update('Comment')->set('Body', t('The user and all related content has been deleted.'))->set('Format', 'Deleted')->where('InsertUserID', $UserID)->put(); } else { // Leave comments } // Remove the user's profile information related to this application $SQL->update('User')->set(array('CountDiscussions' => 0, 'CountUnreadDiscussions' => 0, 'CountComments' => 0, 'CountDrafts' => 0, 'CountBookmarks' => 0))->where('UserID', $UserID)->put(); }
/** * Output 'edited' notice. * * @param $Sender */ protected function drawEdited($Sender) { $Record = $Sender->data('Discussion'); if (!$Record) { $Record = $Sender->data('Record'); } if (!$Record) { return; } $PermissionCategoryID = val('PermissionCategoryID', $Record); $Data = $Record; $RecordType = 'discussion'; $RecordID = val('DiscussionID', $Data); // But override if comment if (isset($Sender->EventArguments['Comment']) || val('RecordType', $Record) == 'comment') { $Data = $Sender->EventArguments['Comment']; $RecordType = 'comment'; $RecordID = val('CommentID', $Data); } $UserCanEdit = Gdn::session()->checkPermission('Vanilla.' . ucfirst($RecordType) . 's.Edit', true, 'Category', $PermissionCategoryID); if (is_null($Data->DateUpdated)) { return; } // Do not show log link if no log would have been generated. $elapsed = Gdn_Format::toTimestamp(val('DateUpdated', $Data)) - Gdn_Format::toTimestamp(val('DateInserted', $Data)); $grace = c('Garden.Log.FloodControl', 20) * 60; if ($elapsed < $grace) { return; } $UpdatedUserID = $Data->UpdateUserID; $UserData = Gdn::userModel()->getID($UpdatedUserID); $Edited = array('EditUser' => val('Name', $UserData, t('Unknown User')), 'EditDate' => Gdn_Format::date($Data->DateUpdated, 'html'), 'EditLogUrl' => url("/log/record/{$RecordType}/{$RecordID}"), 'EditWord' => 'at'); $DateUpdateTime = Gdn_Format::toTimestamp($Data->DateUpdated); if (date('ymd', $DateUpdateTime) != date('ymd')) { $Edited['EditWord'] = 'on'; } $Format = t('PostEdited.Plain', 'Post edited by {EditUser} {EditWord} {EditDate}'); if ($UserCanEdit) { $Format = t('PostEdited.Log', 'Post edited by {EditUser} {EditWord} {EditDate} (<a href="{EditLogUrl}">log</a>)'); } echo '<div class="PostEdited">' . formatString($Format, $Edited) . '</div>'; }
/** * * * @throws Exception */ protected function getData() { $userID = $this->UserID ?: Gdn::session()->UserID; $user = Gdn::userModel()->getID($userID); $banned = val('Banned', $user); $bits = BanModel::explodeBans($banned); $reasons = array(); foreach ($bits as $bit) { if (($bit & $this->ExcludeBans) === 0) { $reasons[$bit] = t("BanReason.{$bit}"); } } $this->setData('Reasons', $reasons); if (!$this->Summary) { if ($this->ExcludeBans) { $summary = "Also banned for the following:"; } else { $summary = "Banned for the following:"; } } $this->setData('Summary', $this->Summary ?: $summary); $this->EventArguments['User'] = $user; $this->fireEvent('GetData'); }
/** * Allows the configuration of basic setup information in Garden. This * should not be functional after the application has been set up. * * @since 2.0.0 * @access public * @param string $RedirectUrl Where to send user afterward. */ private function configure($RedirectUrl = '') { // Create a model to save configuration settings $Validation = new Gdn_Validation(); $ConfigurationModel = new Gdn_ConfigurationModel($Validation); $ConfigurationModel->setField(array('Garden.Locale', 'Garden.Title', 'Garden.WebRoot', 'Garden.Cookie.Salt', 'Garden.Cookie.Domain', 'Database.Name', 'Database.Host', 'Database.User', 'Database.Password', 'Garden.Registration.ConfirmEmail', 'Garden.Email.SupportName')); // Set the models on the forms. $this->Form->setModel($ConfigurationModel); // If seeing the form for the first time... if (!$this->Form->isPostback()) { // Force the webroot using our best guesstimates $ConfigurationModel->Data['Database.Host'] = 'localhost'; $this->Form->setData($ConfigurationModel->Data); } else { // Define some validation rules for the fields being saved $ConfigurationModel->Validation->applyRule('Database.Name', 'Required', 'You must specify the name of the database in which you want to set up Vanilla.'); // Let's make some user-friendly custom errors for database problems $DatabaseHost = $this->Form->getFormValue('Database.Host', '~~Invalid~~'); $DatabaseName = $this->Form->getFormValue('Database.Name', '~~Invalid~~'); $DatabaseUser = $this->Form->getFormValue('Database.User', '~~Invalid~~'); $DatabasePassword = $this->Form->getFormValue('Database.Password', '~~Invalid~~'); $ConnectionString = GetConnectionString($DatabaseName, $DatabaseHost); try { $Connection = new PDO($ConnectionString, $DatabaseUser, $DatabasePassword); } catch (PDOException $Exception) { switch ($Exception->getCode()) { case 1044: $this->Form->addError(t('The database user you specified does not have permission to access the database. Have you created the database yet? The database reported: <code>%s</code>'), strip_tags($Exception->getMessage())); break; case 1045: $this->Form->addError(t('Failed to connect to the database with the username and password you entered. Did you mistype them? The database reported: <code>%s</code>'), strip_tags($Exception->getMessage())); break; case 1049: $this->Form->addError(t('It appears as though the database you specified does not exist yet. Have you created it yet? Did you mistype the name? The database reported: <code>%s</code>'), strip_tags($Exception->getMessage())); break; case 2005: $this->Form->addError(t("Are you sure you've entered the correct database host name? Maybe you mistyped it? The database reported: <code>%s</code>"), strip_tags($Exception->getMessage())); break; default: $this->Form->addError(sprintf(t('ValidateConnection'), strip_tags($Exception->getMessage()))); break; } } $ConfigurationModel->Validation->applyRule('Garden.Title', 'Required'); $ConfigurationFormValues = $this->Form->formValues(); if ($ConfigurationModel->validate($ConfigurationFormValues) !== true || $this->Form->errorCount() > 0) { // Apply the validation results to the form(s) $this->Form->setValidationResults($ConfigurationModel->validationResults()); } else { $Host = array_shift(explode(':', Gdn::request()->requestHost())); $Domain = Gdn::request()->domain(); // Set up cookies now so that the user can be signed in. $ExistingSalt = c('Garden.Cookie.Salt', false); $ConfigurationFormValues['Garden.Cookie.Salt'] = $ExistingSalt ? $ExistingSalt : betterRandomString(16, 'Aa0'); $ConfigurationFormValues['Garden.Cookie.Domain'] = ''; // Don't set this to anything by default. # Tim - 2010-06-23 // Additional default setup values. $ConfigurationFormValues['Garden.Registration.ConfirmEmail'] = true; $ConfigurationFormValues['Garden.Email.SupportName'] = $ConfigurationFormValues['Garden.Title']; $ConfigurationModel->save($ConfigurationFormValues, true); // If changing locale, redefine locale sources: $NewLocale = 'en-CA'; // $this->Form->getFormValue('Garden.Locale', false); if ($NewLocale !== false && Gdn::config('Garden.Locale') != $NewLocale) { $Locale = Gdn::locale(); $Locale->set($NewLocale); } // Install db structure & basic data. $Database = Gdn::database(); $Database->init(); $Drop = false; $Explicit = false; try { include PATH_APPLICATIONS . DS . 'dashboard' . DS . 'settings' . DS . 'structure.php'; } catch (Exception $ex) { $this->Form->addError($ex); } if ($this->Form->errorCount() > 0) { return false; } // Create the administrative user $UserModel = Gdn::userModel(); $UserModel->defineSchema(); $UsernameError = t('UsernameError', 'Username can only contain letters, numbers, underscores, and must be between 3 and 20 characters long.'); $UserModel->Validation->applyRule('Name', 'Username', $UsernameError); $UserModel->Validation->applyRule('Name', 'Required', t('You must specify an admin username.')); $UserModel->Validation->applyRule('Password', 'Required', t('You must specify an admin password.')); $UserModel->Validation->applyRule('Password', 'Match'); $UserModel->Validation->applyRule('Email', 'Email'); if (!($AdminUserID = $UserModel->SaveAdminUser($ConfigurationFormValues))) { $this->Form->setValidationResults($UserModel->validationResults()); } else { // The user has been created successfully, so sign in now. saveToConfig('Garden.Installed', true, array('Save' => false)); Gdn::session()->start($AdminUserID, true); saveToConfig('Garden.Installed', false, array('Save' => false)); } if ($this->Form->errorCount() > 0) { return false; } // Assign some extra settings to the configuration file if everything succeeded. $ApplicationInfo = array(); include CombinePaths(array(PATH_APPLICATIONS . DS . 'dashboard' . DS . 'settings' . DS . 'about.php')); // Detect Internet connection for CDNs $Disconnected = !(bool) @fsockopen('ajax.googleapis.com', 80); saveToConfig(array('Garden.Version' => val('Version', val('Dashboard', $ApplicationInfo, array()), 'Undefined'), 'Garden.Cdns.Disable' => $Disconnected, 'Garden.CanProcessImages' => function_exists('gd_info'), 'EnabledPlugins.GettingStarted' => 'GettingStarted', 'EnabledPlugins.HtmLawed' => 'HtmLawed')); } } return $this->Form->errorCount() == 0 ? true : false; }
/** * The callback helper for {@link formatString()}. * * @param array $Match Either the array of arguments or the regular expression match. * @param bool $SetArgs Whether this is a call to initialize the arguments or a matching callback. * @return mixed Returns the matching string or nothing when setting the arguments. * @access private */ function _formatStringCallback($Match, $SetArgs = false) { static $Args = array(), $ContextUserID = null; if ($SetArgs) { $Args = $Match; if (isset($Args['_ContextUserID'])) { $ContextUserID = $Args['_ContextUserID']; } else { $ContextUserID = Gdn::session() && Gdn::session()->isValid() ? Gdn::session()->UserID : null; } return ''; } $Match = $Match[1]; if ($Match == '{') { return $Match; } // Parse out the field and format. $Parts = explode(',', $Match); $Field = trim($Parts[0]); $Format = trim(val(1, $Parts, '')); $SubFormat = strtolower(trim(val(2, $Parts, ''))); $FormatArgs = val(3, $Parts, ''); if (in_array($Format, array('currency', 'integer', 'percent'))) { $FormatArgs = $SubFormat; $SubFormat = $Format; $Format = 'number'; } elseif (is_numeric($SubFormat)) { $FormatArgs = $SubFormat; $SubFormat = ''; } $Value = valr($Field, $Args, null); if ($Value === null && !in_array($Format, array('url', 'exurl', 'number', 'plural'))) { $Result = ''; } else { switch (strtolower($Format)) { case 'date': switch ($SubFormat) { case 'short': $Result = Gdn_Format::date($Value, '%d/%m/%Y'); break; case 'medium': $Result = Gdn_Format::date($Value, '%e %b %Y'); break; case 'long': $Result = Gdn_Format::date($Value, '%e %B %Y'); break; default: $Result = Gdn_Format::date($Value); break; } break; case 'html': case 'htmlspecialchars': $Result = htmlspecialchars($Value); break; case 'number': if (!is_numeric($Value)) { $Result = $Value; } else { switch ($SubFormat) { case 'currency': $Result = '$' . number_format($Value, is_numeric($FormatArgs) ? $FormatArgs : 2); break; case 'integer': $Result = (string) round($Value); if (is_numeric($FormatArgs) && strlen($Result) < $FormatArgs) { $Result = str_repeat('0', $FormatArgs - strlen($Result)) . $Result; } break; case 'percent': $Result = round($Value * 100, is_numeric($FormatArgs) ? $FormatArgs : 0); break; default: $Result = number_format($Value, is_numeric($FormatArgs) ? $FormatArgs : 0); break; } } break; case 'plural': if (is_array($Value)) { $Value = count($Value); } elseif (StringEndsWith($Field, 'UserID', true)) { $Value = 1; } if (!is_numeric($Value)) { $Result = $Value; } else { if (!$SubFormat) { $SubFormat = rtrim("%s {$Field}", 's'); } if (!$FormatArgs) { $FormatArgs = $SubFormat . 's'; } $Result = Plural($Value, $SubFormat, $FormatArgs); } break; case 'rawurlencode': $Result = rawurlencode($Value); break; case 'text': $Result = Gdn_Format::text($Value, false); break; case 'time': $Result = Gdn_Format::date($Value, '%l:%M%p'); break; case 'url': if (strpos($Field, '/') !== false) { $Value = $Field; } $Result = Url($Value, $SubFormat == 'domain'); break; case 'exurl': if (strpos($Field, '/') !== false) { $Value = $Field; } $Result = externalUrl($Value); break; case 'urlencode': $Result = urlencode($Value); break; case 'gender': // Format in the form of FieldName,gender,male,female,unknown[,plural] if (is_array($Value) && count($Value) == 1) { $Value = array_shift($Value); } $Gender = 'u'; if (!is_array($Value)) { $User = Gdn::userModel()->getID($Value); if ($User) { $Gender = $User->Gender; } } else { $Gender = 'p'; } switch ($Gender) { case 'm': $Result = $SubFormat; break; case 'f': $Result = $FormatArgs; break; case 'p': $Result = val(5, $Parts, val(4, $Parts)); break; case 'u': default: $Result = val(4, $Parts); } break; case 'user': case 'you': case 'his': case 'her': case 'your': // $Result = print_r($Value, true); $ArgsBak = $Args; if (is_array($Value) && count($Value) == 1) { $Value = array_shift($Value); } if (is_array($Value)) { if (isset($Value['UserID'])) { $User = $Value; $User['Name'] = formatUsername($User, $Format, $ContextUserID); $Result = userAnchor($User); } else { $Max = c('Garden.FormatUsername.Max', 5); // See if there is another count. $ExtraCount = valr($Field . '_Count', $Args, 0); $Count = count($Value); $Result = ''; for ($i = 0; $i < $Count; $i++) { if ($i >= $Max && $Count > $Max + 1) { $Others = $Count - $i + $ExtraCount; $Result .= ' ' . t('sep and', 'and') . ' ' . plural($Others, '%s other', '%s others'); break; } $ID = $Value[$i]; if (is_array($ID)) { continue; } if ($i == $Count - 1) { $Result .= ' ' . T('sep and', 'and') . ' '; } elseif ($i > 0) { $Result .= ', '; } $Special = array(-1 => T('everyone'), -2 => T('moderators'), -3 => T('administrators')); if (isset($Special[$ID])) { $Result .= $Special[$ID]; } else { $User = Gdn::userModel()->getID($ID); if ($User) { $User->Name = formatUsername($User, $Format, $ContextUserID); $Result .= userAnchor($User); } } } } } else { $User = Gdn::userModel()->getID($Value); if ($User) { // Store this name separately because of special 'You' case. $Name = formatUsername($User, $Format, $ContextUserID); // Manually build instead of using userAnchor() because of special 'You' case. $Result = anchor(htmlspecialchars($Name), userUrl($User)); } else { $Result = ''; } } $Args = $ArgsBak; break; default: $Result = $Value; break; } } return $Result; }
/** * Invitation-only registration. Requires code. * * @param int $InvitationCode * @since 2.0.0 */ public function registerInvitation($InvitationCode = 0) { $this->Form->setModel($this->UserModel); // Define gender dropdown options $this->GenderOptions = array('u' => t('Unspecified'), 'm' => t('Male'), 'f' => t('Female')); if (!$this->Form->isPostBack()) { $this->Form->setValue('InvitationCode', $InvitationCode); } $InvitationModel = new InvitationModel(); // Look for the invitation. $Invitation = $InvitationModel->getWhere(array('Code' => $this->Form->getValue('InvitationCode')))->firstRow(DATASET_TYPE_ARRAY); if (!$Invitation) { $this->Form->addError('Invitation not found.', 'Code'); } else { if ($Expires = val('DateExpires', $Invitation)) { $Expires = Gdn_Format::toTimestamp($Expires); if ($Expires <= time()) { } } } $this->Form->addHidden('ClientHour', date('Y-m-d H:00')); // Use the server's current hour as a default $this->Form->addHidden('Target', $this->target()); Gdn::userModel()->addPasswordStrength($this); if ($this->Form->isPostBack() === true) { $this->InvitationCode = $this->Form->getValue('InvitationCode'); // Add validation rules that are not enforced by the model $this->UserModel->defineSchema(); $this->UserModel->Validation->applyRule('Name', 'Username', $this->UsernameError); $this->UserModel->Validation->applyRule('TermsOfService', 'Required', t('You must agree to the terms of service.')); $this->UserModel->Validation->applyRule('Password', 'Required'); $this->UserModel->Validation->applyRule('Password', 'Strength'); $this->UserModel->Validation->applyRule('Password', 'Match'); // $this->UserModel->Validation->applyRule('DateOfBirth', 'MinimumAge'); $this->fireEvent('RegisterValidation'); try { $Values = $this->Form->formValues(); $Values = $this->UserModel->filterForm($Values, true); unset($Values['Roles']); $AuthUserID = $this->UserModel->register($Values, array('Method' => 'Invitation')); $this->setData('UserID', $AuthUserID); if (!$AuthUserID) { $this->Form->setValidationResults($this->UserModel->validationResults()); } else { // The user has been created successfully, so sign in now. Gdn::session()->start($AuthUserID); if ($this->Form->getFormValue('RememberMe')) { Gdn::authenticator()->setIdentity($AuthUserID, true); } $this->fireEvent('RegistrationSuccessful'); // ... and redirect them appropriately $Route = $this->redirectTo(); if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { $this->RedirectUrl = url($Route); } else { if ($Route !== false) { redirect($Route); } } } } catch (Exception $Ex) { $this->Form->addError($Ex); } } else { // Set some form defaults. if ($Name = val('Name', $Invitation)) { $this->Form->setValue('Name', $Name); } $this->InvitationCode = $InvitationCode; } // Make sure that the hour offset for new users gets defined when their account is created $this->addJsFile('entry.js'); $this->render(); }
/** * Update user's total comment count. * * @since 2.0.0 * @access public * * @param int $UserID Unique ID of the user to be updated. */ public function updateUser($UserID, $Inc = false) { if ($Inc) { // Just increment the comment count. $this->SQL->update('User')->set('CountComments', 'CountComments + 1', false)->where('UserID', $UserID)->put(); } else { // Retrieve a comment count $CountComments = $this->SQL->select('c.CommentID', 'count', 'CountComments')->from('Comment c')->where('c.InsertUserID', $UserID)->get()->firstRow()->CountComments; // Save to the attributes column of the user table for this user. Gdn::userModel()->setField($UserID, 'CountComments', $CountComments); } }
/** * * * @param $Sender */ public function profileController_quotes_create($Sender) { $Sender->permission('Garden.SignIn.Allow'); $Sender->title(t("Quotes Settings")); $Args = $Sender->RequestArgs; if (sizeof($Args) < 2) { $Args = array_merge($Args, array(0, 0)); } elseif (sizeof($Args) > 2) { $Args = array_slice($Args, 0, 2); } list($UserReference, $Username) = $Args; $Sender->getUserInfo($UserReference, $Username); $UserPrefs = Gdn_Format::unserialize($Sender->User->Preferences); if (!is_array($UserPrefs)) { $UserPrefs = array(); } $UserID = Gdn::session()->UserID; $ViewingUserID = $UserID; if ($Sender->User->UserID != $ViewingUserID) { $Sender->permission('Garden.Users.Edit'); $UserID = $Sender->User->UserID; $Sender->setData('ForceEditing', $Sender->User->Name); } else { $Sender->setData('ForceEditing', false); } $QuoteFolding = val('Quotes.Folding', $UserPrefs, '1'); $Sender->Form->setValue('QuoteFolding', $QuoteFolding); $Sender->setData('QuoteFoldingOptions', array('None' => t("Don't fold quotes"), '1' => plural(1, '%s level deep', '%s levels deep'), '2' => plural(2, '%s level deep', '%s levels deep'), '3' => plural(3, '%s level deep', '%s levels deep'), '4' => plural(4, '%s level deep', '%s levels deep'), '5' => plural(5, '%s level deep', '%s levels deep'))); // Form submission handling. if ($Sender->Form->authenticatedPostBack()) { $NewFoldingLevel = $Sender->Form->getValue('QuoteFolding', '1'); if ($NewFoldingLevel != $QuoteFolding) { Gdn::userModel()->savePreference($UserID, 'Quotes.Folding', $NewFoldingLevel); $Sender->informMessage(t("Your changes have been saved.")); } } $Sender->render('quotes', '', 'plugins/Quotes'); }
/** * * * @param $UserID * @param $Verified * @throws Exception */ public function verify($UserID, $Verified) { $this->permission('Garden.Moderation.Manage'); if (!$this->Request->isAuthenticatedPostBack()) { throw permissionException('Javascript'); } // First, set the field value. Gdn::userModel()->setField($UserID, 'Verified', $Verified); $User = Gdn::userModel()->getID($UserID); if (!$User) { throw notFoundException('User'); } // Send back the verified button. require_once $this->fetchViewLocation('helper_functions', 'Profile', 'Dashboard'); $this->jsonTarget('.User-Verified', userVerified($User), 'ReplaceWith'); $this->render('Blank', 'Utility', 'Dashboard'); }
/** * Tests whether a user has permission for a discussion by checking category-specific permissions. * Fires an event that can override the calculated permission. * * @param object|array|integer $discussion The discussion ID or the discussion to test. * @param string $permission The category permission to test against the user. * @param integer $userID The ID of the user to test permission for. If empty, it defaults to Session user. * @return bool Whether the user has the specified permission privileges to the discussion. * @throws Exception */ public function checkPermission($discussion, $permission, $userID = 0) { // Either the permission string is a full permission, or we prepend 'Vanilla.Discussions.' to the permission. if (strpos($permission, '.') === false) { $permission = ucfirst(strtolower($permission)); if (in_array($permission, $this->permissionTypes)) { $permission = 'Vanilla.Discussions.' . $permission; } else { throw new Exception(t('Unexpected discussion permission.')); } } // Default to session user. if (!$userID) { $userID = Gdn::session()->UserID; } // Fetch discussion. if (is_numeric($discussion)) { $discussion = $this->getID($discussion); } $userModel = Gdn::userModel(); // Get category permission. $hasPermission = $userID && $userModel->getCategoryViewPermission($userID, val('CategoryID', $discussion), $permission); // Check if we've timed out. if (strpos(strtolower($permission), 'edit' !== false)) { $hasPermission &= self::editContentTimeout($discussion); } // Fire event to override permission ruling. $this->EventArguments['Discussion'] = $discussion; $this->EventArguments['UserID'] = $userID; $this->EventArguments['Permission'] = $permission; $this->EventArguments['HasPermission'] =& $hasPermission; $this->fireEvent('checkPermission'); return $hasPermission; }
/** * Adds to the "To" recipient collection. * * @param mixed $RecipientEmail An email (or array of emails) to add to the "To" recipient collection. * @param string $RecipientName The recipient name associated with $RecipientEmail. If $RecipientEmail is * an array of email addresses, this value will be ignored. */ public function to($RecipientEmail, $RecipientName = '') { if ($RecipientName != '' && c('Garden.Email.OmitToName', false)) { $RecipientName = ''; } if (is_string($RecipientEmail)) { if (strpos($RecipientEmail, ',') > 0) { $RecipientEmail = explode(',', $RecipientEmail); // trim no need, PhpMailer::AddAnAddress() will do it return $this->to($RecipientEmail, $RecipientName); } if ($this->PhpMailer->SingleTo) { return $this->addTo($RecipientEmail, $RecipientName); } if (!$this->_IsToSet) { $this->_IsToSet = true; $this->addTo($RecipientEmail, $RecipientName); } else { $this->cc($RecipientEmail, $RecipientName); } return $this; } elseif (is_object($RecipientEmail) && property_exists($RecipientEmail, 'Email') || is_array($RecipientEmail) && isset($RecipientEmail['Email'])) { $User = $RecipientEmail; $RecipientName = val('Name', $User); $RecipientEmail = val('Email', $User); $UserID = val('UserID', $User, false); if ($UserID !== false) { // Check to make sure the user can receive email. if (!Gdn::userModel()->checkPermission($UserID, 'Garden.Email.View')) { $this->Skipped[] = $User; return $this; } } return $this->to($RecipientEmail, $RecipientName); } elseif ($RecipientEmail instanceof Gdn_DataSet) { foreach ($RecipientEmail->resultObject() as $Object) { $this->to($Object); } return $this; } elseif (is_array($RecipientEmail)) { $Count = count($RecipientEmail); if (!is_array($RecipientName)) { $RecipientName = array_fill(0, $Count, ''); } if ($Count == count($RecipientName)) { $RecipientEmail = array_combine($RecipientEmail, $RecipientName); foreach ($RecipientEmail as $Email => $Name) { $this->to($Email, $Name); } } else { trigger_error(errorMessage('Size of arrays do not match', 'Email', 'To'), E_USER_ERROR); } return $this; } trigger_error(errorMessage('Incorrect first parameter (' . getType($RecipientEmail) . ') passed to function.', 'Email', 'To'), E_USER_ERROR); }
/** * Check and apply login rate limiting * * @param array $User * @param bool $PasswordOK */ public static function rateLimit($User, $PasswordOK) { if (Gdn::cache()->activeEnabled()) { // Rate limit using Gdn_Cache. $UserRateKey = formatString(self::LOGIN_RATE_KEY, ['Source' => $User->UserID]); $UserRate = (int) Gdn::cache()->get($UserRateKey); $UserRate += 1; Gdn::cache()->store($UserRateKey, 1, [Gdn_Cache::FEATURE_EXPIRY => self::LOGIN_RATE]); $SourceRateKey = formatString(self::LOGIN_RATE_KEY, ['Source' => Gdn::request()->ipAddress()]); $SourceRate = (int) Gdn::cache()->get($SourceRateKey); $SourceRate += 1; Gdn::cache()->store($SourceRateKey, 1, [Gdn_Cache::FEATURE_EXPIRY => self::LOGIN_RATE]); } elseif (c('Garden.Apc', false) && function_exists('apc_store')) { // Rate limit using the APC data store. $UserRateKey = formatString(self::LOGIN_RATE_KEY, ['Source' => $User->UserID]); $UserRate = (int) apc_fetch($UserRateKey); $UserRate += 1; apc_store($UserRateKey, 1, self::LOGIN_RATE); $SourceRateKey = formatString(self::LOGIN_RATE_KEY, ['Source' => Gdn::request()->ipAddress()]); $SourceRate = (int) apc_fetch($SourceRateKey); $SourceRate += 1; apc_store($SourceRateKey, 1, self::LOGIN_RATE); } else { // Rate limit using user attributes. $Now = time(); $UserModel = Gdn::userModel(); $LastLoginAttempt = $UserModel->getAttribute($User->UserID, 'LastLoginAttempt', 0); $UserRate = $UserModel->getAttribute($User->UserID, 'LoginRate', 0); $UserRate += 1; if ($LastLoginAttempt + self::LOGIN_RATE < $Now) { $UserRate = 0; } $UserModel->saveToSerializedColumn('Attributes', $User->UserID, ['LastLoginAttempt' => $Now, 'LoginRate' => 1]); // IP rate limiting is not available without an active cache. $SourceRate = 0; } // Put user into cooldown mode. if ($UserRate > 1) { throw new Gdn_UserException(t('LoginUserCooldown', 'You are trying to log in too often. Slow down!.')); } if ($SourceRate > 1) { throw new Gdn_UserException(t('LoginSourceCooldown', 'Your IP is trying to log in too often. Slow down!')); } return true; }
public function notSpam($LogIDs) { $this->permission(array('Garden.Moderation.Manage', 'Moderation.Spam.Manage'), false); if (!$this->Request->isPostBack()) { throw permissionException('Javascript'); } $Logs = array(); // Verify the appropriate users. $UserIDs = $this->Form->getFormValue('UserID', array()); if (!is_array($UserIDs)) { $UserIDs = array(); } foreach ($UserIDs as $UserID) { Gdn::userModel()->setField($UserID, 'Verified', true); $Logs = array_merge($Logs, $this->LogModel->getWhere(array('Operation' => 'Spam', 'RecordUserID' => $UserID))); } // Grab the logs. $Logs = array_merge($Logs, $this->LogModel->getIDs($LogIDs)); // try { foreach ($Logs as $Log) { $this->LogModel->restore($Log); } // } catch (Exception $Ex) { // $this->Form->addError($Ex->getMessage()); // } $this->LogModel->recalculate(); $this->setData('Complete'); $this->setData('Count', count($Logs)); $this->render('Blank', 'Utility'); }
/** * * * @param bool $Notify * @param bool $UserID */ public function post($Notify = false, $UserID = false) { if (is_numeric($Notify)) { $UserID = $Notify; $Notify = false; } if (!$UserID) { $UserID = Gdn::session()->UserID; } switch ($Notify) { case 'mods': $this->permission('Garden.Moderation.Manage'); $NotifyUserID = ActivityModel::NOTIFY_MODS; break; case 'admins': $this->permission('Garden.Settings.Manage'); $NotifyUserID = ActivityModel::NOTIFY_ADMINS; break; default: $this->permission('Garden.Profiles.Edit'); $NotifyUserID = ActivityModel::NOTIFY_PUBLIC; break; } $Activities = array(); if ($this->Form->authenticatedPostBack()) { $Data = $this->Form->formValues(); $Data = $this->ActivityModel->filterForm($Data); if (!isset($Data['Format']) || strcasecmp($Data['Format'], 'Raw') == 0) { $Data['Format'] = c('Garden.InputFormatter'); } if ($UserID != Gdn::session()->UserID) { // This is a wall post. $Activity = array('ActivityType' => 'WallPost', 'ActivityUserID' => $UserID, 'RegardingUserID' => Gdn::session()->UserID, 'HeadlineFormat' => t('HeadlineFormat.WallPost', '{RegardingUserID,you} → {ActivityUserID,you}'), 'Story' => $Data['Comment'], 'Format' => $Data['Format'], 'Data' => array('Bump' => true)); } else { // This is a status update. $Activity = array('ActivityType' => 'Status', 'HeadlineFormat' => t('HeadlineFormat.Status', '{ActivityUserID,user}'), 'Story' => $Data['Comment'], 'Format' => $Data['Format'], 'NotifyUserID' => $NotifyUserID, 'Data' => array('Bump' => true)); $this->setJson('StatusMessage', Gdn_Format::plainText($Activity['Story'], $Activity['Format'])); } $Activity = $this->ActivityModel->save($Activity, false, array('CheckSpam' => true)); if ($Activity == SPAM || $Activity == UNAPPROVED) { $this->StatusMessage = t('ActivityRequiresApproval', 'Your post will appear after it is approved.'); $this->render('Blank', 'Utility'); return; } if ($Activity) { if ($UserID == Gdn::session()->UserID && $NotifyUserID == ActivityModel::NOTIFY_PUBLIC) { Gdn::userModel()->setField(Gdn::session()->UserID, 'About', Gdn_Format::plainText($Activity['Story'], $Activity['Format'])); } $Activities = array($Activity); ActivityModel::joinUsers($Activities); $this->ActivityModel->calculateData($Activities); } else { $this->Form->setValidationResults($this->ActivityModel->validationResults()); $this->StatusMessage = $this->ActivityModel->Validation->resultsText(); // $this->render('Blank', 'Utility'); } } if ($this->deliveryType() == DELIVERY_TYPE_ALL) { $Target = $this->Request->get('Target', '/activity'); if (isSafeUrl($Target)) { redirect($Target); } else { redirect(url('/activity')); } } $this->setData('Activities', $Activities); $this->render('Activities'); }
/** * * * @return bool */ public function insertUserTable() { $CurrentUser = $this->SQL->getWhere('User', array('UserID' => Gdn::session()->UserID))->firstRow(DATASET_TYPE_ARRAY); $CurrentPassword = $CurrentUser['Password']; $CurrentHashMethod = $CurrentUser['HashMethod']; // Delete the current user table. $this->SQL->Truncate('User'); // Load the new user table. $UserTableInfo =& $this->Data['Tables']['User']; if (!$this->importExists('User', 'HashMethod')) { $this->_InsertTable('User', array('HashMethod' => $this->GetPasswordHashMethod())); } else { $this->_InsertTable('User'); } $UserTableInfo['Inserted'] = true; $AdminEmail = val('OverwriteEmail', $this->Data); $SqlArgs = array(':Email' => $AdminEmail); $SqlSet = ''; $SqlArgs[':Password'] = $CurrentPassword; $SqlArgs[':HashMethod'] = $CurrentHashMethod; $SqlSet = ', Password = :Password, HashMethod = :HashMethod'; // If doing a password reset, save out the new admin password: if (strcasecmp($this->GetPasswordHashMethod(), 'reset') == 0) { if (!isset($SqlArgs[':Password'])) { $PasswordHash = new Gdn_PasswordHash(); $Hash = $PasswordHash->HashPassword(val('OverwritePassword', $this->Data)); $SqlSet .= ', Password = :Password, HashMethod = :HashMethod'; $SqlArgs[':Password'] = $Hash; $SqlArgs[':HashMthod'] = 'Vanilla'; } // Write it out. $this->query("update :_User set Admin = 1{$SqlSet} where Email = :Email", $SqlArgs); } else { // Set the admin user flag. $this->query("update :_User set Admin = 1{$SqlSet} where Email = :Email", $SqlArgs); } // Start the new session. $User = Gdn::userModel()->GetByEmail(val('OverwriteEmail', $this->Data)); if (!$User) { $User = Gdn::userModel()->GetByUsername(val('OverwriteEmail', $this->Data)); } Gdn::session()->start(val('UserID', $User), true); return true; }
<?php $Session = Gdn::session(); $Alt = FALSE; foreach ($this->InvitationData->Format('Text')->result() as $Invitation) { $Alt = $Alt == TRUE ? FALSE : TRUE; ?> <tr class="js-invitation" data-id="<?php echo $Invitation->InvitationID; ?> "> <td class="Alt"><?php if ($Invitation->AcceptedName == '') { echo $Invitation->Email; echo wrap(anchor(t('Uninvite'), "/profile/uninvite/{$Invitation->InvitationID}", 'Uninvite Hijack') . ' | ' . anchor(t('Send Again'), "/profile/sendinvite/{$Invitation->InvitationID}", 'SendAgain Hijack'), 'div'); } else { $User = Gdn::userModel()->getID($Invitation->AcceptedUserID); echo userAnchor($User); echo wrap(anchor(t('Remove'), "/profile/deleteinvitation/{$Invitation->InvitationID}", 'Delete Hijack'), 'div'); } if ($Invitation->AcceptedName == '') { } ?> </td> <td><?php echo Gdn_Format::date($Invitation->DateInserted, 'html'); ?> </td> <td class="Alt"><?php if ($Invitation->AcceptedName == '') { echo t('Pending'); } else {
/** * Create or update a comment. * * @since 2.0.0 * @access public * * @param int $DiscussionID Unique ID to add the comment to. If blank, this method will throw an error. */ public function comment($DiscussionID = '') { // Get $DiscussionID from RequestArgs if valid if ($DiscussionID == '' && count($this->RequestArgs)) { if (is_numeric($this->RequestArgs[0])) { $DiscussionID = $this->RequestArgs[0]; } } // If invalid $DiscussionID, get from form. $this->Form->setModel($this->CommentModel); $DiscussionID = is_numeric($DiscussionID) ? $DiscussionID : $this->Form->getFormValue('DiscussionID', 0); // Set discussion data $this->DiscussionID = $DiscussionID; $this->Discussion = $Discussion = $this->DiscussionModel->getID($DiscussionID); // Is this an embedded comment being posted to a discussion that doesn't exist yet? $vanilla_type = $this->Form->getFormValue('vanilla_type', ''); $vanilla_url = $this->Form->getFormValue('vanilla_url', ''); $vanilla_category_id = $this->Form->getFormValue('vanilla_category_id', ''); $Attributes = array('ForeignUrl' => $vanilla_url); $vanilla_identifier = $this->Form->getFormValue('vanilla_identifier', ''); $isEmbeddedComments = $vanilla_url != '' && $vanilla_identifier != ''; // Only allow vanilla identifiers of 32 chars or less - md5 if larger if (strlen($vanilla_identifier) > 32) { $Attributes['vanilla_identifier'] = $vanilla_identifier; $vanilla_identifier = md5($vanilla_identifier); } if (!$Discussion && $isEmbeddedComments) { $Discussion = $Discussion = $this->DiscussionModel->getForeignID($vanilla_identifier, $vanilla_type); if ($Discussion) { $this->DiscussionID = $DiscussionID = $Discussion->DiscussionID; $this->Form->setValue('DiscussionID', $DiscussionID); } } // If so, create it! if (!$Discussion && $isEmbeddedComments) { // Add these values back to the form if they exist! $this->Form->addHidden('vanilla_identifier', $vanilla_identifier); $this->Form->addHidden('vanilla_type', $vanilla_type); $this->Form->addHidden('vanilla_url', $vanilla_url); $this->Form->addHidden('vanilla_category_id', $vanilla_category_id); $PageInfo = fetchPageInfo($vanilla_url); if (!($Title = $this->Form->getFormValue('Name'))) { $Title = val('Title', $PageInfo, ''); if ($Title == '') { $Title = t('Undefined discussion subject.'); if (!empty($PageInfo['Exception']) && $PageInfo['Exception'] === "Couldn't connect to host.") { $Title .= ' ' . t('Page timed out.'); } } } $Description = val('Description', $PageInfo, ''); $Images = val('Images', $PageInfo, array()); $LinkText = t('EmbededDiscussionLinkText', 'Read the full story here'); if (!$Description && count($Images) == 0) { $Body = formatString('<p><a href="{Url}">{LinkText}</a></p>', array('Url' => $vanilla_url, 'LinkText' => $LinkText)); } else { $Body = formatString(' <div class="EmbeddedContent">{Image}<strong>{Title}</strong> <p>{Excerpt}</p> <p><a href="{Url}">{LinkText}</a></p> <div class="ClearFix"></div> </div>', array('Title' => $Title, 'Excerpt' => $Description, 'Image' => count($Images) > 0 ? img(val(0, $Images), array('class' => 'LeftAlign')) : '', 'Url' => $vanilla_url, 'LinkText' => $LinkText)); } if ($Body == '') { $Body = $vanilla_url; } if ($Body == '') { $Body = t('Undefined discussion body.'); } // Validate the CategoryID for inserting. $Category = CategoryModel::categories($vanilla_category_id); if (!$Category) { $vanilla_category_id = c('Vanilla.Embed.DefaultCategoryID', 0); if ($vanilla_category_id <= 0) { // No default category defined, so grab the first non-root category and use that. $vanilla_category_id = $this->DiscussionModel->SQL->select('CategoryID')->from('Category')->where('CategoryID >', 0)->get()->firstRow()->CategoryID; // No categories in the db? default to 0 if (!$vanilla_category_id) { $vanilla_category_id = 0; } } } else { $vanilla_category_id = $Category['CategoryID']; } $EmbedUserID = c('Garden.Embed.UserID'); if ($EmbedUserID) { $EmbedUser = Gdn::userModel()->getID($EmbedUserID); } if (!$EmbedUserID || !$EmbedUser) { $EmbedUserID = Gdn::userModel()->getSystemUserID(); } $EmbeddedDiscussionData = array('InsertUserID' => $EmbedUserID, 'DateInserted' => Gdn_Format::toDateTime(), 'DateUpdated' => Gdn_Format::toDateTime(), 'CategoryID' => $vanilla_category_id, 'ForeignID' => $vanilla_identifier, 'Type' => $vanilla_type, 'Name' => $Title, 'Body' => $Body, 'Format' => 'Html', 'Attributes' => dbencode($Attributes)); $this->EventArguments['Discussion'] =& $EmbeddedDiscussionData; $this->fireEvent('BeforeEmbedDiscussion'); $DiscussionID = $this->DiscussionModel->SQL->insert('Discussion', $EmbeddedDiscussionData); $ValidationResults = $this->DiscussionModel->validationResults(); if (count($ValidationResults) == 0 && $DiscussionID > 0) { $this->Form->addHidden('DiscussionID', $DiscussionID); // Put this in the form so reposts won't cause new discussions. $this->Form->setFormValue('DiscussionID', $DiscussionID); // Put this in the form values so it is used when saving comments. $this->setJson('DiscussionID', $DiscussionID); $this->Discussion = $Discussion = $this->DiscussionModel->getID($DiscussionID, DATASET_TYPE_OBJECT, array('Slave' => false)); // Update the category discussion count if ($vanilla_category_id > 0) { $this->DiscussionModel->updateDiscussionCount($vanilla_category_id, $DiscussionID); } } } // If no discussion was found, error out if (!$Discussion) { $this->Form->addError(t('Failed to find discussion for commenting.')); } /** * Special care is taken for embedded comments. Since we don't currently use an advanced editor for these * comments, we may need to apply certain filters and fixes to the data to maintain its intended display * with the input format (e.g. maintaining newlines). */ if ($isEmbeddedComments) { $inputFormatter = $this->Form->getFormValue('Format', c('Garden.InputFormatter')); switch ($inputFormatter) { case 'Wysiwyg': $this->Form->setFormValue('Body', nl2br($this->Form->getFormValue('Body'))); break; } } $PermissionCategoryID = val('PermissionCategoryID', $Discussion); // Setup head $this->addJsFile('jquery.autosize.min.js'); $this->addJsFile('autosave.js'); $this->addJsFile('post.js'); // Setup comment model, $CommentID, $DraftID $Session = Gdn::session(); $CommentID = isset($this->Comment) && property_exists($this->Comment, 'CommentID') ? $this->Comment->CommentID : ''; $DraftID = isset($this->Comment) && property_exists($this->Comment, 'DraftID') ? $this->Comment->DraftID : ''; $this->EventArguments['CommentID'] = $CommentID; $this->EventArguments['DraftID'] = $DraftID; // Determine whether we are editing $Editing = $CommentID > 0 || $DraftID > 0; $this->EventArguments['Editing'] = $Editing; // If closed, cancel & go to discussion if ($Discussion && $Discussion->Closed == 1 && !$Editing && !$Session->checkPermission('Vanilla.Discussions.Close', true, 'Category', $PermissionCategoryID)) { redirect(DiscussionUrl($Discussion)); } // Add hidden IDs to form $this->Form->addHidden('DiscussionID', $DiscussionID); $this->Form->addHidden('CommentID', $CommentID); $this->Form->addHidden('DraftID', $DraftID, true); // Check permissions if ($Discussion && $Editing) { // Permission to edit if ($this->Comment->InsertUserID != $Session->UserID) { $this->permission('Vanilla.Comments.Edit', true, 'Category', $Discussion->PermissionCategoryID); } // Make sure that content can (still) be edited. $EditContentTimeout = c('Garden.EditContentTimeout', -1); $CanEdit = $EditContentTimeout == -1 || strtotime($this->Comment->DateInserted) + $EditContentTimeout > time(); if (!$CanEdit) { $this->permission('Vanilla.Comments.Edit', true, 'Category', $Discussion->PermissionCategoryID); } // Make sure only moderators can edit closed things if ($Discussion->Closed) { $this->permission('Vanilla.Comments.Edit', true, 'Category', $Discussion->PermissionCategoryID); } $this->Form->setFormValue('CommentID', $CommentID); } elseif ($Discussion) { // Permission to add $this->permission('Vanilla.Comments.Add', true, 'Category', $Discussion->PermissionCategoryID); } if ($this->Form->authenticatedPostBack()) { // Save as a draft? $FormValues = $this->Form->formValues(); $FormValues = $this->CommentModel->filterForm($FormValues); if (!$Editing) { unset($FormValues['CommentID']); } if ($DraftID == 0) { $DraftID = $this->Form->getFormValue('DraftID', 0); } $Type = GetIncomingValue('Type'); $Draft = $Type == 'Draft'; $this->EventArguments['Draft'] = $Draft; $Preview = $Type == 'Preview'; if ($Draft) { $DraftID = $this->DraftModel->save($FormValues); $this->Form->addHidden('DraftID', $DraftID, true); $this->Form->setValidationResults($this->DraftModel->validationResults()); } elseif (!$Preview) { // Fix an undefined title if we can. if ($this->Form->getFormValue('Name') && val('Name', $Discussion) == t('Undefined discussion subject.')) { $Set = array('Name' => $this->Form->getFormValue('Name')); if (isset($vanilla_url) && $vanilla_url && strpos(val('Body', $Discussion), t('Undefined discussion subject.')) !== false) { $LinkText = t('EmbededDiscussionLinkText', 'Read the full story here'); $Set['Body'] = formatString('<p><a href="{Url}">{LinkText}</a></p>', array('Url' => $vanilla_url, 'LinkText' => $LinkText)); } $this->DiscussionModel->setField(val('DiscussionID', $Discussion), $Set); } $Inserted = !$CommentID; $CommentID = $this->CommentModel->save($FormValues); // The comment is now half-saved. if (is_numeric($CommentID) && $CommentID > 0) { if (in_array($this->deliveryType(), array(DELIVERY_TYPE_ALL, DELIVERY_TYPE_DATA))) { $this->CommentModel->save2($CommentID, $Inserted, true, true); } else { $this->jsonTarget('', url("/post/comment2.json?commentid={$CommentID}&inserted={$Inserted}"), 'Ajax'); } // $Discussion = $this->DiscussionModel->getID($DiscussionID); $Comment = $this->CommentModel->getID($CommentID, DATASET_TYPE_OBJECT, array('Slave' => false)); $this->EventArguments['Discussion'] = $Discussion; $this->EventArguments['Comment'] = $Comment; $this->fireEvent('AfterCommentSave'); } elseif ($CommentID === SPAM || $CommentID === UNAPPROVED) { $this->StatusMessage = t('CommentRequiresApprovalStatus', 'Your comment will appear after it is approved.'); } $this->Form->setValidationResults($this->CommentModel->validationResults()); if ($CommentID > 0 && $DraftID > 0) { $this->DraftModel->delete($DraftID); } } // Handle non-ajax requests first: if ($this->_DeliveryType == DELIVERY_TYPE_ALL) { if ($this->Form->errorCount() == 0) { // Make sure that this form knows what comment we are editing. if ($CommentID > 0) { $this->Form->addHidden('CommentID', $CommentID); } // If the comment was not a draft if (!$Draft) { // Redirect to the new comment. if ($CommentID > 0) { redirect("discussion/comment/{$CommentID}/#Comment_{$CommentID}"); } elseif ($CommentID == SPAM) { $this->setData('DiscussionUrl', DiscussionUrl($Discussion)); $this->View = 'Spam'; } } elseif ($Preview) { // If this was a preview click, create a comment shell with the values for this comment $this->Comment = new stdClass(); $this->Comment->InsertUserID = $Session->User->UserID; $this->Comment->InsertName = $Session->User->Name; $this->Comment->InsertPhoto = $Session->User->Photo; $this->Comment->DateInserted = Gdn_Format::date(); $this->Comment->Body = val('Body', $FormValues, ''); $this->Comment->Format = val('Format', $FormValues, c('Garden.InputFormatter')); $this->addAsset('Content', $this->fetchView('preview')); } else { // If this was a draft save, notify the user about the save $this->informMessage(sprintf(t('Draft saved at %s'), Gdn_Format::date())); } } } else { // Handle ajax-based requests if ($this->Form->errorCount() > 0) { // Return the form errors $this->errorMessage($this->Form->errors()); } else { // Make sure that the ajax request form knows about the newly created comment or draft id $this->setJson('CommentID', $CommentID); $this->setJson('DraftID', $DraftID); if ($Preview) { // If this was a preview click, create a comment shell with the values for this comment $this->Comment = new stdClass(); $this->Comment->InsertUserID = $Session->User->UserID; $this->Comment->InsertName = $Session->User->Name; $this->Comment->InsertPhoto = $Session->User->Photo; $this->Comment->DateInserted = Gdn_Format::date(); $this->Comment->Body = val('Body', $FormValues, ''); $this->Comment->Format = val('Format', $FormValues, c('Garden.InputFormatter')); $this->View = 'preview'; } elseif (!$Draft) { // If the comment was not a draft // If Editing a comment if ($Editing) { // Just reload the comment in question $this->Offset = 1; $Comments = $this->CommentModel->getIDData($CommentID, array('Slave' => false)); $this->setData('Comments', $Comments); $this->setData('Discussion', $Discussion); // Load the discussion $this->ControllerName = 'discussion'; $this->View = 'comments'; // Also define the discussion url in case this request came from the post screen and needs to be redirected to the discussion $this->setJson('DiscussionUrl', DiscussionUrl($this->Discussion) . '#Comment_' . $CommentID); } else { // If the comment model isn't sorted by DateInserted or CommentID then we can't do any fancy loading of comments. $OrderBy = valr('0.0', $this->CommentModel->orderBy()); // $Redirect = !in_array($OrderBy, array('c.DateInserted', 'c.CommentID')); // $DisplayNewCommentOnly = $this->Form->getFormValue('DisplayNewCommentOnly'); // if (!$Redirect) { // // Otherwise load all new comments that the user hasn't seen yet // $LastCommentID = $this->Form->getFormValue('LastCommentID'); // if (!is_numeric($LastCommentID)) // $LastCommentID = $CommentID - 1; // Failsafe back to this new comment if the lastcommentid was not defined properly // // // Don't reload the first comment if this new comment is the first one. // $this->Offset = $LastCommentID == 0 ? 1 : $this->CommentModel->GetOffset($LastCommentID); // // Do not load more than a single page of data... // $Limit = c('Vanilla.Comments.PerPage', 30); // // // Redirect if the new new comment isn't on the same page. // $Redirect |= !$DisplayNewCommentOnly && PageNumber($this->Offset, $Limit) != PageNumber($Discussion->CountComments - 1, $Limit); // } // if ($Redirect) { // // The user posted a comment on a page other than the last one, so just redirect to the last page. // $this->RedirectUrl = Gdn::request()->Url("discussion/comment/$CommentID/#Comment_$CommentID", true); // } else { // // Make sure to load all new comments since the page was last loaded by this user // if ($DisplayNewCommentOnly) $this->Offset = $this->CommentModel->GetOffset($CommentID); $Comments = $this->CommentModel->GetIDData($CommentID, array('Slave' => false)); $this->setData('Comments', $Comments); $this->setData('NewComments', true); $this->ClassName = 'DiscussionController'; $this->ControllerName = 'discussion'; $this->View = 'comments'; // } // Make sure to set the user's discussion watch records $CountComments = $this->CommentModel->getCount($DiscussionID); $Limit = is_object($this->data('Comments')) ? $this->data('Comments')->numRows() : $Discussion->CountComments; $Offset = $CountComments - $Limit; $this->CommentModel->SetWatch($this->Discussion, $Limit, $Offset, $CountComments); } } else { // If this was a draft save, notify the user about the save $this->informMessage(sprintf(t('Draft saved at %s'), Gdn_Format::date())); } // And update the draft count $UserModel = Gdn::userModel(); $CountDrafts = $UserModel->getAttribute($Session->UserID, 'CountDrafts', 0); $this->setJson('MyDrafts', t('My Drafts')); $this->setJson('CountDrafts', $CountDrafts); } } } elseif ($this->Request->isPostBack()) { throw new Gdn_UserException(t('Invalid CSRF token.', 'Invalid CSRF token. Please try again.'), 401); } else { // Load form if (isset($this->Comment)) { $this->Form->setData((array) $this->Comment); } } // Include data for FireEvent if (property_exists($this, 'Discussion')) { $this->EventArguments['Discussion'] = $this->Discussion; } if (property_exists($this, 'Comment')) { $this->EventArguments['Comment'] = $this->Comment; } $this->fireEvent('BeforeCommentRender'); if ($this->deliveryType() == DELIVERY_TYPE_DATA) { if ($this->data('Comments') instanceof Gdn_DataSet) { $Comment = $this->data('Comments')->firstRow(DATASET_TYPE_ARRAY); if ($Comment) { $Photo = $Comment['InsertPhoto']; if (strpos($Photo, '//') === false) { $Photo = Gdn_Upload::url(changeBasename($Photo, 'n%s')); } $Comment['InsertPhoto'] = $Photo; } $this->Data = array('Comment' => $Comment); } $this->RenderData($this->Data); } else { require_once $this->fetchViewLocation('helper_functions', 'Discussion'); // Render default view. $this->render(); } }
/** * * * @param ProfileController $Sender * @param type $UserReference * @param type $Username * @param type $Code */ public function profileController_FacebookConnect_create($Sender, $UserReference, $Username, $Code = false) { $Sender->permission('Garden.SignIn.Allow'); $Sender->getUserInfo($UserReference, $Username, '', true); $Sender->_setBreadcrumbs(t('Connections'), '/profile/connections'); // Get the access token. $AccessToken = $this->getAccessToken($Code, self::profileConnecUrl()); // Get the profile. $Profile = $this->getProfile($AccessToken); // Save the authentication. Gdn::userModel()->saveAuthentication(array('UserID' => $Sender->User->UserID, 'Provider' => self::ProviderKey, 'UniqueID' => $Profile['id'])); // Save the information as attributes. $Attributes = array('AccessToken' => $AccessToken, 'Profile' => $Profile); Gdn::userModel()->saveAttribute($Sender->User->UserID, self::ProviderKey, $Attributes); $this->EventArguments['Provider'] = self::ProviderKey; $this->EventArguments['User'] = $Sender->User; $this->fireEvent('AfterConnection'); redirect(userUrl($Sender->User, '', 'connections')); }
* @copyright 2009-2016 Vanilla Forums Inc. * @license http://www.opensource.org/licenses/gpl-2.0.php GNU GPL v2 * @since 2.0 * @package Vanilla */ $SQL = Gdn::database()->sql(); // Only do this once, ever. $Row = $SQL->get('Discussion', '', 'asc', 1)->firstRow(DATASET_TYPE_ARRAY); if ($Row) { return; } $DiscussionModel = new DiscussionModel(); // Prep default content $DiscussionTitle = "BAM! You’ve got a sweet forum"; $DiscussionBody = "There’s nothing sweeter than a fresh new forum, ready to welcome your community. A Vanilla Forum has all the bits and pieces you need to build an awesome discussion platform customized to your needs. Here’s a few tips:\n<ul>\n <li>Use the <a href=\"/dashboard/settings/gettingstarted\">Getting Started</a> list in the Dashboard to configure your site.</li>\n <li>Don’t use too many categories. We recommend 3-8. Keep it simple!</li>\n <li>“Announce” a discussion (click the gear) to stick to the top of the list, and “Close” it to stop further comments.</li>\n <li>Use “Sink” to take attention away from a discussion. New comments will no longer bring it back to the top of the list.</li>\n <li>Bookmark a discussion (click the star) to get notifications for new comments. You can edit notification settings from your profile.</li>\n</ul>\nGo ahead and edit or delete this discussion, then spread the word to get this place cooking. Cheers!"; $CommentBody = "This is the first comment on your site and it’s an important one.\n\nDon’t see your must-have feature? We keep Vanilla nice and simple by default. Use <b>addons</b> to get the special sauce your community needs.\n\nNot sure which addons to enable? Our favorites are Button Bar and Tagging. They’re almost always a great start."; $WallBody = "Ping! An activity post is a public way to talk at someone. When you update your status here, it posts it on your activity feed."; // Prep content meta data $SystemUserID = Gdn::userModel()->GetSystemUserID(); $TargetUserID = Gdn::session()->UserID; $Now = Gdn_Format::toDateTime(); $CategoryID = val('CategoryID', CategoryModel::DefaultCategory()); // Get wall post type ID $WallCommentTypeID = $SQL->getWhere('ActivityType', array('Name' => 'WallPost'))->value('ActivityTypeID'); // Insert first discussion & comment $DiscussionID = $SQL->Options('Ignore', true)->insert('Discussion', array('Name' => t('StubDiscussionTitle', $DiscussionTitle), 'Body' => t('StubDiscussionBody', $DiscussionBody), 'Format' => 'Html', 'CategoryID' => $CategoryID, 'ForeignID' => 'stub', 'InsertUserID' => $SystemUserID, 'DateInserted' => $Now, 'DateLastComment' => $Now, 'LastCommentUserID' => $SystemUserID, 'CountComments' => 1)); $CommentID = $SQL->insert('Comment', array('DiscussionID' => $DiscussionID, 'Body' => t('StubCommentBody', $CommentBody), 'Format' => 'Html', 'InsertUserID' => $SystemUserID, 'DateInserted' => $Now)); $SQL->update('Discussion')->set('LastCommentID', $CommentID)->where('DiscussionID', $DiscussionID)->put(); $DiscussionModel->UpdateDiscussionCount($CategoryID); // Insert first wall post $SQL->insert('Activity', array('Story' => t('StubWallBody', $WallBody), 'Format' => 'Html', 'HeadlineFormat' => '{RegardingUserID,you} → {ActivityUserID,you}', 'NotifyUserID' => -1, 'ActivityUserID' => $TargetUserID, 'RegardingUserID' => $SystemUserID, 'ActivityTypeID' => $WallCommentTypeID, 'InsertUserID' => $SystemUserID, 'DateInserted' => $Now, 'DateUpdated' => $Now));
/** * Take a user object an return the URL to their photo. * * @param object|array $User */ function userPhotoUrl($User) { $FullUser = Gdn::userModel()->getID(val('UserID', $User), DATASET_TYPE_ARRAY); $Photo = val('Photo', $User); if ($FullUser && $FullUser['Banned']) { $Photo = 'https://c3409409.ssl.cf0.rackcdn.com/images/banned_100.png'; } if ($Photo) { if (!isUrl($Photo)) { $PhotoUrl = Gdn_Upload::url(changeBasename($Photo, 'n%s')); } else { $PhotoUrl = $Photo; } return $PhotoUrl; } return UserModel::getDefaultAvatarUrl($User); }
/** * * * @param string|unknown_type $InvitationID * @return bool * @throws Exception */ public function delete($InvitationID) { $Session = Gdn::session(); $UserID = $Session->UserID; // Validate that this user can delete this invitation: $Invitation = $this->getID($InvitationID, DATASET_TYPE_ARRAY); // Does the invitation exist? if (!$Invitation) { throw notFoundException('Invitation'); } // Does this user own the invitation? if ($UserID != $Invitation['InsertUserID'] && !$Session->checkPermission('Garden.Moderation.Manage')) { throw permissionException('@' . t('InviteErrorPermission', t('ErrorPermission'))); } // Delete it. $this->SQL->delete($this->Name, array('InvitationID' => $InvitationID)); // Add the invitation back onto the user's account if the invitation has not been accepted. if (!$Invitation->AcceptedUserID) { Gdn::userModel()->IncreaseInviteCount($UserID); } return true; }
$SystemUserID = c('Garden.SystemUserID'); if ($SystemUserID) { $SysUser = Gdn::userModel()->getID($SystemUserID); if (!$SysUser || val('Deleted', $SysUser) || val('Admin', $SysUser) != 2) { $SystemUserID = false; removeFromConfig('Garden.SystemUserID'); } } if (!$SystemUserID) { // Try and find a system user. $SystemUserID = Gdn::sql()->getWhere('User', array('Name' => 'System', 'Admin' => 2))->value('UserID'); if ($SystemUserID) { saveToConfig('Garden.SystemUserID', $SystemUserID); } else { // Create a new one if we couldn't find one. Gdn::userModel()->getSystemUserID(); } } // UserRole Table $Construct->table('UserRole'); $UserRoleExists = $Construct->tableExists(); $Construct->column('UserID', 'int', false, 'primary')->column('RoleID', 'int', false, array('primary', 'index'))->set($Explicit, $Drop); // Fix old default roles that were stored in the config and user-role table. if ($RoleTableExists && $UserRoleExists && $RoleTypeExists) { $types = $RoleModel->getAllDefaultRoles(); if ($v = c('Garden.Registration.ApplicantRoleID')) { $SQL->update('Role')->set('Type', RoleModel::TYPE_APPLICANT)->where('RoleID', $types[RoleModel::TYPE_APPLICANT])->put(); // RemoveFromConfig('Garden.Registration.ApplicantRoleID'); } if ($v = c('Garden.Registration.DefaultRoles')) { $SQL->update('Role')->set('Type', RoleModel::TYPE_MEMBER)->where('RoleID', $types[RoleModel::TYPE_MEMBER])->put();
/** * Main dashboard. * * You can override this method with a method in your plugin named * SettingsController_Index_Create. You can hook into it with methods named * SettingsController_Index_Before and SettingsController_Index_After. * * @since 2.0.0 * @access public */ public function xIndex() { $this->addJsFile('settings.js'); $this->title(t('Dashboard')); $this->RequiredAdminPermissions[] = 'Garden.Settings.View'; $this->RequiredAdminPermissions[] = 'Garden.Settings.Manage'; $this->RequiredAdminPermissions[] = 'Garden.Community.Manage'; $this->RequiredAdminPermissions[] = 'Garden.Users.Add'; $this->RequiredAdminPermissions[] = 'Garden.Users.Edit'; $this->RequiredAdminPermissions[] = 'Garden.Users.Delete'; $this->RequiredAdminPermissions[] = 'Garden.Users.Approve'; $this->fireEvent('DefineAdminPermissions'); $this->permission($this->RequiredAdminPermissions, false); $this->addSideMenu('dashboard/settings'); $UserModel = Gdn::userModel(); // Get recently active users $this->ActiveUserData = $UserModel->getActiveUsers(5); // Check for updates $this->addUpdateCheck(); // Fire an event so other applications can add some data to be displayed $this->fireEvent('DashboardData'); $this->render(); }