/** * * @param Gdn_Form $Sender */ public function Gdn_Form_BeforeBodyBox_Handler($Sender, $Args) { $this->_AddCLEditor(Gdn::Controller()); $Format = $Sender->GetValue('Format'); if ($Format) { $Formatter = Gdn::Factory($Format . 'Formatter'); if ($Formatter && method_exists($Formatter, 'FormatForWysiwyg')) { $Body = $Formatter->FormatForWysiwyg($Sender->GetValue('Body')); $Sender->SetValue('Body', $Body); } elseif (!in_array($Format, array('Html', 'Wysiwyg'))) { $Sender->SetValue('Body', Gdn_Format::To($Sender->GetValue('Body'), $Format)); } } $Sender->SetValue('Format', 'Wysiwyg'); }
/** * Signin process that multiple authentication methods. * * @access public * @since 2.0.0 * @author Tim Gunter * * @param string $Method * @param array $Arg1 * @return string Rendered XHTML template. */ public function SignIn($Method = FALSE, $Arg1 = FALSE) { $this->AddJsFile('entry.js'); $this->SetData('Title', T('Sign In')); $this->Form->AddHidden('Target', $this->Target()); $this->Form->AddHidden('ClientHour', date('Y-m-d H:00')); // Use the server's current hour as a default. // Additional signin methods are set up with plugins. $Methods = array(); $this->SetData('MainFormArgs', array($Arg1)); $this->SetData('Methods', $Methods); $this->SetData('FormUrl', Url('entry/signin')); $this->FireEvent('SignIn'); if ($this->Form->IsPostBack()) { $this->Form->ValidateRule('Email', 'ValidateRequired', sprintf(T('%s is required.'), T('Email/Username'))); $this->Form->ValidateRule('Password', 'ValidateRequired'); // Check the user. if ($this->Form->ErrorCount() == 0) { $Email = $this->Form->GetFormValue('Email'); $User = Gdn::UserModel()->GetByEmail($Email); if (!$User) { $User = Gdn::UserModel()->GetByUsername($Email); } if (!$User) { $this->Form->AddError('ErrorCredentials'); } else { $ClientHour = $this->Form->GetFormValue('ClientHour'); $HourOffset = Gdn_Format::ToTimestamp($ClientHour) - time(); $HourOffset = round($HourOffset / 3600); // Check the password. $PasswordHash = new Gdn_PasswordHash(); if ($PasswordHash->CheckPassword($this->Form->GetFormValue('Password'), GetValue('Password', $User), GetValue('HashMethod', $User))) { Gdn::Session()->Start(GetValue('UserID', $User), TRUE, (bool) $this->Form->GetFormValue('RememberMe')); if (!Gdn::Session()->CheckPermission('Garden.SignIn.Allow')) { $this->Form->AddError('ErrorPermission'); Gdn::Session()->End(); } else { if ($HourOffset != Gdn::Session()->User->HourOffset) { Gdn::UserModel()->SetProperty(Gdn::Session()->UserID, 'HourOffset', $HourOffset); } $this->_SetRedirect(); } } else { $this->Form->AddError('ErrorCredentials'); } } } } else { if ($Target = $this->Request->Get('Target')) { $this->Form->AddHidden('Target', $Target); } $this->Form->SetValue('RememberMe', TRUE); } return $this->Render(); }
/** * Signin process that multiple authentication methods. * * @access public * @since 2.0.0 * @author Tim Gunter * * @param string $Method * @param array $Arg1 * @return string Rendered XHTML template. */ public function SignIn($Method = FALSE, $Arg1 = FALSE) { Gdn::Session()->EnsureTransientKey(); $this->AddJsFile('entry.js'); $this->SetData('Title', T('Sign In')); $this->Form->AddHidden('Target', $this->Target()); $this->Form->AddHidden('ClientHour', date('Y-m-d H:00')); // Use the server's current hour as a default. // Additional signin methods are set up with plugins. $Methods = array(); $this->SetData('Methods', $Methods); $this->SetData('FormUrl', Url('entry/signin')); $this->FireEvent('SignIn'); if ($this->Form->IsPostBack()) { $this->Form->ValidateRule('Email', 'ValidateRequired', sprintf(T('%s is required.'), T(UserModel::SigninLabelCode()))); $this->Form->ValidateRule('Password', 'ValidateRequired'); if (!$this->Request->IsAuthenticatedPostBack()) { $this->Form->AddError('Please try again.'); } // Check the user. if ($this->Form->ErrorCount() == 0) { $Email = $this->Form->GetFormValue('Email'); $User = Gdn::UserModel()->GetByEmail($Email); if (!$User) { $User = Gdn::UserModel()->GetByUsername($Email); } if (!$User) { $this->Form->AddError('@' . sprintf(T('User not found.'), strtolower(T(UserModel::SigninLabelCode())))); } else { // Check the password. $PasswordHash = new Gdn_PasswordHash(); $Password = $this->Form->GetFormValue('Password'); try { $PasswordChecked = $PasswordHash->CheckPassword($Password, GetValue('Password', $User), GetValue('HashMethod', $User)); // Rate limiting Gdn::UserModel()->RateLimit($User, $PasswordChecked); if ($PasswordChecked) { // Update weak passwords $HashMethod = GetValue('HashMethod', $User); if ($PasswordHash->Weak || $HashMethod && strcasecmp($HashMethod, 'Vanilla') != 0) { $Pw = $PasswordHash->HashPassword($Password); Gdn::UserModel()->SetField(GetValue('UserID', $User), array('Password' => $Pw, 'HashMethod' => 'Vanilla')); } Gdn::Session()->Start(GetValue('UserID', $User), TRUE, (bool) $this->Form->GetFormValue('RememberMe')); if (!Gdn::Session()->CheckPermission('Garden.SignIn.Allow')) { $this->Form->AddError('ErrorPermission'); Gdn::Session()->End(); } else { $ClientHour = $this->Form->GetFormValue('ClientHour'); $HourOffset = Gdn::Session()->User->HourOffset; if (is_numeric($ClientHour) && $ClientHour >= 0 && $ClientHour < 24) { $HourOffset = $ClientHour - date('G', time()); } if ($HourOffset != Gdn::Session()->User->HourOffset) { Gdn::UserModel()->SetProperty(Gdn::Session()->UserID, 'HourOffset', $HourOffset); } Gdn::UserModel()->FireEvent('AfterSignIn'); $this->_SetRedirect(); } } else { $this->Form->AddError('Invalid password.'); } } catch (Gdn_UserException $Ex) { $this->Form->AddError($Ex); } } } } else { if ($Target = $this->Request->Get('Target')) { $this->Form->AddHidden('Target', $Target); } $this->Form->SetValue('RememberMe', TRUE); } return $this->Render(); }
/** * Pre-populate the form with values from the query string. * * @param Gdn_Form $Form * @param bool $LimitCategories Whether to turn off the category dropdown if there is only one category to show. */ protected function PopulateForm($Form) { $Get = $this->Request->Get(); $Get = array_change_key_case($Get); $Values = ArrayTranslate($Get, array('name' => 'Name', 'tags' => 'Tags', 'body' => 'Body')); foreach ($Values as $Key => $Value) { $Form->SetValue($Key, $Value); } if (isset($Get['category'])) { $Category = CategoryModel::Categories($Get['category']); if ($Category && $Category['PermsDiscussionsAdd']) { $Form->SetValue('CategoryID', $Category['CategoryID']); } } }
/** * Editing a category. * * @since 2.0.0 * @access public * * @param int $CategoryID Unique ID of the category to be updated. */ public function EditCategory($CategoryID = '') { // Check permission $this->Permission('Garden.Settings.Manage'); // Set up models $RoleModel = new RoleModel(); $PermissionModel = Gdn::PermissionModel(); $this->Form->SetModel($this->CategoryModel); if (!$CategoryID && $this->Form->IsPostBack()) { if ($ID = $this->Form->GetFormValue('CategoryID')) { $CategoryID = $ID; } } // Get category data $this->Category = $this->CategoryModel->GetID($CategoryID); $this->Category->CustomPermissions = $this->Category->CategoryID == $this->Category->PermissionCategoryID; // Set up head $this->AddJsFile('jquery.alphanumeric.js'); $this->AddJsFile('categories.js'); $this->AddJsFile('jquery.gardencheckboxgrid.js'); $this->Title(T('Edit Category')); $this->AddSideMenu('vanilla/settings/managecategories'); // Make sure the form knows which item we are editing. $this->Form->AddHidden('CategoryID', $CategoryID); $this->SetData('CategoryID', $CategoryID); // Load all roles with editable permissions $this->RoleArray = $RoleModel->GetArray(); $this->FireEvent('AddEditCategory'); if ($this->Form->IsPostBack() == FALSE) { $this->Form->SetData($this->Category); $this->SetupDiscussionTypes($this->Category); $this->Form->SetValue('CustomPoints', $this->Category->PointsCategoryID == $this->Category->CategoryID); } else { $this->SetupDiscussionTypes($this->Category); $Upload = new Gdn_Upload(); $TmpImage = $Upload->ValidateUpload('PhotoUpload', FALSE); if ($TmpImage) { // Generate the target image name $TargetImage = $Upload->GenerateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Save the uploaded image $Parts = $Upload->SaveAs($TmpImage, $ImageBaseName); $this->Form->SetFormValue('Photo', $Parts['SaveName']); } $this->Form->SetFormValue('CustomPoints', (bool) $this->Form->GetFormValue('CustomPoints')); if ($this->Form->Save()) { $Category = CategoryModel::Categories($CategoryID); $this->SetData('Category', $Category); if ($this->DeliveryType() == DELIVERY_TYPE_ALL) { Redirect('vanilla/settings/managecategories'); } } } // Get all of the currently selected role/permission combinations for this junction. $Permissions = $PermissionModel->GetJunctionPermissions(array('JunctionID' => $CategoryID), 'Category', '', array('AddDefaults' => !$this->Category->CustomPermissions)); $Permissions = $PermissionModel->UnpivotPermissions($Permissions, TRUE); if ($this->DeliveryType() == DELIVERY_TYPE_ALL) { $this->SetData('PermissionData', $Permissions, TRUE); } // Render default view $this->Render(); }
/** * Manage list of locales. * * @since 2.0.0 * @access public * @param string $Op 'enable' or 'disable' * @param string $LocaleKey Unique ID of locale to be modified. * @param string $TransientKey Security token. */ public function Locales($Op = NULL, $LocaleKey = NULL, $TransientKey = NULL) { $this->Permission('Garden.Settings.Manage'); $this->Title(T('Locales')); $this->AddSideMenu('dashboard/settings/locales'); $this->AddJsFile('addons.js'); $LocaleModel = new LocaleModel(); // Get the available locale packs. $AvailableLocales = $LocaleModel->AvailableLocalePacks(); // Get the enabled locale packs. $EnabledLocales = $LocaleModel->EnabledLocalePacks(); // Check to enable/disable a locale. if ($TransientKey && Gdn::Session()->ValidateTransientKey($TransientKey) || $this->Form->AuthenticatedPostBack()) { if ($Op) { $Refresh = FALSE; switch (strtolower($Op)) { case 'enable': $Locale = GetValue($LocaleKey, $AvailableLocales); if (!is_array($Locale)) { $this->Form->AddError('@' . sprintf(T('The %s locale pack does not exist.'), htmlspecialchars($LocaleKey)), 'LocaleKey'); } elseif (!isset($Locale['Locale'])) { $this->Form->AddError('ValidateRequired', 'Locale'); } else { SaveToConfig("EnabledLocales.{$LocaleKey}", $Locale['Locale']); $EnabledLocales[$LocaleKey] = $Locale['Locale']; $Refresh = TRUE; } break; case 'disable': RemoveFromConfig("EnabledLocales.{$LocaleKey}"); unset($EnabledLocales[$LocaleKey]); $Refresh = TRUE; break; } // Set default locale field if just doing enable/disable $this->Form->SetValue('Locale', C('Garden.Locale', 'en-CA')); } elseif ($this->Form->IsPostBack()) { // Save the default locale. SaveToConfig('Garden.Locale', $this->Form->GetFormValue('Locale')); $Refresh = TRUE; $this->InformMessage(T("Your changes have been saved.")); } if ($Refresh) { Gdn::Locale()->Refresh(); } } elseif (!$this->Form->IsPostBack()) { $this->Form->SetValue('Locale', C('Garden.Locale', 'en-CA')); } // Check for the default locale warning. $DefaultLocale = C('Garden.Locale'); if ($DefaultLocale != 'en-CA') { $LocaleFound = FALSE; $MatchingLocales = array(); foreach ($AvailableLocales as $Key => $LocaleInfo) { $Locale = GetValue('Locale', $LocaleInfo); if ($Locale == $DefaultLocale) { $MatchingLocales[] = GetValue('Name', $LocaleInfo, $Key); } if (GetValue($Key, $EnabledLocales) == $DefaultLocale) { $LocaleFound = TRUE; } } $this->SetData('DefaultLocale', $DefaultLocale); $this->SetData('DefaultLocaleWarning', !$LocaleFound); $this->SetData('MatchingLocalePacks', htmlspecialchars(implode(', ', $MatchingLocales))); } $this->SetData('AvailableLocales', $AvailableLocales); $this->SetData('EnabledLocales', $EnabledLocales); $this->SetData('Locales', $LocaleModel->AvailableLocales()); $this->Render(); }
/** * 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 = GetValue('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(); unset($Values['Roles']); $AuthUserID = $this->UserModel->Register($Values, array('Method' => 'Invitation')); 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 = GetValue('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(); }
/** * 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', ''); // 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 && $vanilla_url != '' && $vanilla_identifier != '') { $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 && $vanilla_url != '' && $vanilla_identifier != '') { // 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); $Title = GetValue('Title', $PageInfo, ''); if ($Title == '') { $Title = T('Undefined discussion subject.'); } $Description = GetValue('Description', $PageInfo, ''); $Images = GetValue('Images', $PageInfo, array()); $LinkText = T('EmbededDiscussionLinkText', 'Read the full story here'); $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(GetValue(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']; } $SystemUserID = Gdn::UserModel()->GetSystemUserID(); $EmbeddedDiscussionData = array('InsertUserID' => $SystemUserID, 'DateInserted' => Gdn_Format::ToDateTime(), 'UpdateUserID' => $SystemUserID, 'DateUpdated' => Gdn_Format::ToDateTime(), 'CategoryID' => $vanilla_category_id, 'ForeignID' => $vanilla_identifier, 'Type' => $vanilla_type, 'Name' => $Title, 'Body' => $Body, 'Format' => 'Html', 'Attributes' => serialize($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); // 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.')); } $PermissionCategoryID = GetValue('PermissionCategoryID', $Discussion); // Setup head $this->AddJsFile('jquery.autogrow.js'); $this->AddJsFile('post.js'); $this->AddJsFile('autosave.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) { // Permisssion 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); } } else { if ($Discussion) { // Permission to add $this->Permission('Vanilla.Comments.Add', TRUE, 'Category', $Discussion->PermissionCategoryID); } } if (!$this->Form->IsPostBack()) { // Form was validly submitted if (isset($this->Comment)) { $this->Form->SetData((array) $this->Comment); } } else { // Save as a draft? $FormValues = $this->Form->FormValues(); $FormValues = $this->CommentModel->FilterForm($FormValues); 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()); } else { if (!$Preview) { $Inserted = !$CommentID; $CommentID = $this->CommentModel->Save($FormValues); // The comment is now half-saved. if (is_numeric($CommentID) && $CommentID > 0) { if ($this->_DeliveryType == DELIVERY_TYPE_ALL) { $this->CommentModel->Save2($CommentID, $Inserted, TRUE, TRUE); } else { $this->JsonTarget('', Url("/vanilla/post/comment2.json?commentid={$CommentID}&inserted={$Inserted}"), 'Ajax'); } // $Discussion = $this->DiscussionModel->GetID($DiscussionID); $Comment = $this->CommentModel->GetID($CommentID); $this->EventArguments['Discussion'] = $Discussion; $this->EventArguments['Comment'] = $Comment; $this->FireEvent('AfterCommentSave'); } elseif ($CommentID === SPAM) { $this->StatusMessage = T('Your post has been flagged for moderation.'); } $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 = ArrayValue('Body', $FormValues, ''); $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 = ArrayValue('Body', $FormValues, ''); $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); $this->SetData('Comments', $Comments); // 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 = GetValueR('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); $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); } } } // 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) { $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 { // Render default view. $this->Render(); } }
/** * Edit user account. * * @since 2.0.0 * @access public * @param mixed $UserReference Username or User ID. */ public function Edit($UserReference = '', $Username = '', $UserID = '') { $this->Permission('Garden.SignIn.Allow'); $this->GetUserInfo($UserReference, $Username, $UserID, TRUE); $UserID = GetValueR('User.UserID', $this); $Settings = array(); // Set up form $User = Gdn::UserModel()->GetID($UserID, DATASET_TYPE_ARRAY); $this->Form->SetModel(Gdn::UserModel()); $this->Form->SetData($User); $this->SetData('User', $User); // Decide if they have ability to edit the username $CanEditUsername = (bool) C("Garden.Profile.EditUsernames") || Gdn::Session()->CheckPermission('Garden.Users.Edit'); $this->SetData('_CanEditUsername', $CanEditUsername); // Decide if they have ability to edit the email $EmailEnabled = (bool) C('Garden.Profile.EditEmails', TRUE) && !UserModel::NoEmail(); $CanEditEmail = $EmailEnabled && $UserID == Gdn::Session()->UserID || CheckPermission('Garden.Users.Edit'); $this->SetData('_CanEditEmail', $CanEditEmail); // Decide if they have ability to confirm users $Confirmed = (bool) GetValueR('User.Confirmed', $this); $CanConfirmEmail = UserModel::RequireConfirmEmail() && CheckPermission('Garden.Users.Edit'); $this->SetData('_CanConfirmEmail', $CanConfirmEmail); $this->SetData('_EmailConfirmed', $Confirmed); $this->Form->SetValue('ConfirmEmail', (int) $Confirmed); // Decide if we can *see* email $this->SetData('_CanViewPersonalInfo', Gdn::Session()->UserID == GetValue('UserID', $User) || CheckPermission('Garden.PersonalInfo.View') || CheckPermission('Garden.Users.Edit')); // Define gender dropdown options $this->GenderOptions = array('u' => T('Unspecified'), 'm' => T('Male'), 'f' => T('Female')); $this->FireEvent('BeforeEdit'); // If seeing the form for the first time... if ($this->Form->IsPostBack()) { $this->Form->SetFormValue('UserID', $UserID); if (!$CanEditUsername) { $this->Form->SetFormValue("Name", $User['Name']); } else { $UsernameError = T('UsernameError', 'Username can only contain letters, numbers, underscores, and must be between 3 and 20 characters long.'); Gdn::UserModel()->Validation->ApplyRule('Name', 'Username', $UsernameError); } // API // These options become available when POSTing as a user with Garden.Settings.Manage permissions if (Gdn::Session()->CheckPermission('Garden.Settings.Manage')) { // Role change $RequestedRoles = $this->Form->GetFormValue('RoleID', NULL); if (!is_null($RequestedRoles)) { $RoleModel = new RoleModel(); $AllRoles = $RoleModel->GetArray(); if (!is_array($RequestedRoles)) { $RequestedRoles = is_numeric($RequestedRoles) ? array($RequestedRoles) : array(); } $RequestedRoles = array_flip($RequestedRoles); $UserNewRoles = array_intersect_key($AllRoles, $RequestedRoles); // Put the data back into the forum object as if the user had submitted // this themselves $this->Form->SetFormValue('RoleID', array_keys($UserNewRoles)); // Allow saving roles $Settings['SaveRoles'] = TRUE; } // Password change $NewPassword = $this->Form->GetFormValue('Password', NULL); if (!is_null($NewPassword)) { } } // Allow mods to confirm emails $this->Form->RemoveFormValue('Confirmed'); $Confirmation = $this->Form->GetFormValue('ConfirmEmail', null); $Confirmation = !is_null($Confirmation) ? (bool) $Confirmation : null; if ($CanConfirmEmail && is_bool($Confirmation)) { $this->Form->SetFormValue('Confirmed', (int) $Confirmation); } if ($this->Form->Save($Settings) !== FALSE) { $User = Gdn::UserModel()->GetID($UserID, DATASET_TYPE_ARRAY); $this->SetData('Profile', $User); $this->InformMessage(Sprite('Check', 'InformSprite') . T('Your changes have been saved.'), 'Dismissable AutoDismiss HasSprite'); } if (!$CanEditEmail) { $this->Form->SetFormValue("Email", $User['Email']); } } $this->Title(T('Edit Profile')); $this->_SetBreadcrumbs(T('Edit Profile'), '/profile/edit'); $this->Render(); }