public function PluginController_ThankFor_Create($Sender) { $Session = $this->Session; if (!$Session->IsValid()) { return; } //$Sender->Permission('Plugins.ThankfulPeople.Thank'); // TODO: PERMISSION THANK FOR CATEGORY $ThanksLogModel = new ThanksLogModel(); $Type = GetValue(0, $Sender->RequestArgs); $ObjectID = GetValue(1, $Sender->RequestArgs); $Field = $ThanksLogModel->GetPrimaryKeyField($Type); $UserID = $ThanksLogModel->GetObjectInserUserID($Type, $ObjectID); if ($UserID == False) { throw new Exception('Object has no owner.'); } if ($UserID == $Session->UserID) { throw new Exception('You cannot thank yourself.'); } if (!self::IsThankable($Type)) { throw new Exception("Not thankable ({$Type})."); } // Make sure that user is not trying to say thanks twice. $Count = $ThanksLogModel->GetCount(array($Field => $ObjectID, 'InsertUserID' => $Session->User->UserID)); if ($Count < 1) { $ThanksLogModel->PutThank($Type, $ObjectID, $UserID); } if ($Sender->DeliveryType() == DELIVERY_TYPE_ALL) { $Target = GetIncomingValue('Target', 'discussions'); Redirect($Target); } $ThankfulPeopleDataSet = $ThanksLogModel->GetThankfulPeople($Type, $ObjectID); $Sender->SetData('NewThankedByBox', self::ThankedByBox($ThankfulPeopleDataSet->Result(), False)); $Sender->Render(); }
private function BuildPager($Sender, $Total) { $Sanitized = $this->ValidateInputs(); //get offset $GETString = '?' . Gdn_Url::QueryString() . '&tar=srch'; //use this to providea link back to search - be sure to append the '&tar=srch' to tell to load the main search page $GETString = str_replace('p=search&', 'search?', $GETString); //echo $GETString; die; $Limit = $this->Settings['Admin']->LimitResultsPage; $Offset = ($Sanitized['Offset'] - 1) * $Limit; //limit per page $Pos = strpos($GETString, '&pg=' . $_GET['pg']); if (!$Pos == FALSE) { //$Url = substr($GETString, 0, $Pos); //strip the page number if it exists $Url = str_replace('&pg=' . GetIncomingValue('pg'), '', $GETString); //strip the page number if it exists $Url = str_replace('&tar=srch', '', $Url); //don't want to load adv search page when clicking page numbers } else { $Url = str_replace('&tar=srch', '', $GETString); } //don't want to load adv search page when clicking page numbers $PagerFactory = new Gdn_PagerFactory(); $Sender->Pager = $PagerFactory->GetPager('Pager', $Sender); $Sender->Pager->MoreCode = '>'; $Sender->Pager->LessCode = '<'; $Sender->Pager->ClientID = 'Pager'; $Sender->Pager->Configure($Offset, $Limit, $Total, $Url . '&pg=%1$s'); //echo $Url; die; $Sender->SetData('GETString', $GETString); }
public function PluginController_TimerTick_Create($Sender) { // Assume that $Sender->RequestArgs is empty. $Token = GetIncomingValue('TimerTickToken', RandomString(5)); if ($Token == C('Plugins.UsefulFunctions.TimerTick.SecretKey', RandomString(8))) { require dirname(__FILE__) . '/bin/tick.php'; } }
public function Slug() { $Session = Gdn::Session(); if ($Session->IsValid()) { $Text = GetIncomingValue('Text'); echo CandyModel::Slug($Text); } }
/** * Stash a value in the user's session, or unstash it if no value was provided to stash. */ public function Stash() { $this->DeliveryType(DELIVERY_TYPE_BOOL); $this->DeliveryMethod(DELIVERY_METHOD_JSON); $Name = GetIncomingValue('Name', ''); $Value = GetIncomingValue('Value', ''); $Response = Gdn::Session()->Stash($Name, $Value); if ($Name != '' && $Value == '') $this->SetJson('Unstash', $Response); $this->Render(); }
public function AutoComplete() { $this->DeliveryType(DELIVERY_TYPE_NONE); $Q = GetIncomingValue('q'); $UserModel = new Gdn_UserModel(); $Data = $UserModel->GetLike(array('u.Name' => $Q), 'u.Name', 'asc', 10, 0); foreach ($Data->Result('Text') as $User) { echo $User->Name . '|' . $User->UserID . "\n"; } $this->Render(); }
/** * Dismiss a message (per user). * * @since 2.0.0 * @access public */ public function Dismiss($MessageID = '', $TransientKey = FALSE) { $Session = Gdn::Session(); if ($TransientKey !== FALSE && $Session->ValidateTransientKey($TransientKey)) { $Prefs = $Session->GetPreference('DismissedMessages', array()); $Prefs[] = $MessageID; $Session->SetPreference('DismissedMessages', $Prefs); } if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { Redirect(GetIncomingValue('Target', '/discussions')); } $this->Render(); }
/** * Set the preference in the user's session. */ public function setToggle() { $Session = Gdn::session(); if (!$Session->isValid()) { return; } $ShowAllCategories = GetIncomingValue('ShowAllCategories', ''); if ($ShowAllCategories != '') { $ShowAllCategories = $ShowAllCategories == 'true' ? true : false; $ShowAllCategoriesPref = $Session->GetPreference('ShowAllCategories'); if ($ShowAllCategories != $ShowAllCategoriesPref) { $Session->setPreference('ShowAllCategories', $ShowAllCategories); } redirect('/' . ltrim(Gdn::request()->Path(), '/')); } }
/** * Set the preference in the user's session. */ public function SetToggle() { $Session = Gdn::Session(); if (!$Session->IsValid()) { return; } $ShowAllCategories = GetIncomingValue('ShowAllCategories', ''); if ($ShowAllCategories != '') { $ShowAllCategories = $ShowAllCategories == 'true' ? TRUE : FALSE; $ShowAllCategoriesPref = $Session->GetPreference('ShowAllCategories'); if ($ShowAllCategories != $ShowAllCategoriesPref) { $Session->SetPreference('ShowAllCategories', $ShowAllCategories); } Redirect('/' . ltrim(Gdn::Request()->Path(), '/')); } }
public function Index() { $Limit = GetIncomingValue('limit', 5); $Offset = GetIncomingValue('offset', 0); $DiscussionID = GetIncomingValue('id', 0); $Session = Gdn::Session(); $Discussion = $this->DiscussionModel->GetID($DiscussionID); if ($Discussion != False && $Session->CheckPermission('Vanilla.Discussions.View', $Discussion->CategoryID)) { $this->SetJSON("discussion", $Discussion); if ($Discussion->CountComments > 0) { $Comments = $this->CommentModel->Get($DiscussionID, $Limit, $Offset)->Result(); $this->SetJSON("comments", $Comments); } } $this->Render(); }
/** * Settings screen placeholder * * @param mixed $Sender */ public function Controller_Index($Sender) { $Sender->Permission('Garden.Settings.Manage'); $Sender->Title('Community Reporting'); $Sender->AddSideMenu('settings/plugins'); $Sender->AddCssFile('reporting.css', 'plugins/Reporting'); // Check to see if the admin is toggling a feature $Feature = GetValue('1', $Sender->RequestArgs); $Command = GetValue('2', $Sender->RequestArgs); $TransientKey = GetIncomingValue('TransientKey'); if (Gdn::Session()->ValidateTransientKey($TransientKey)) { if (in_array($Feature, array('awesome', 'report'))) { SaveToConfig('Plugins.Reporting.' . ucfirst($Feature) . 'Enabled', $Command == 'disable' ? FALSE : TRUE); Redirect('plugin/reporting'); } } $CategoryModel = new CategoryModel(); $Sender->SetData('Plugins.Reporting.Data', array('ReportEnabled' => $this->ReportEnabled, 'AwesomeEnabled' => $this->AwesomeEnabled)); $Sender->Render($this->GetView('settings.php')); }
public function Delete($ActivityID = '', $TransientKey = '') { $Session = Gdn::Session(); if ($Session->ValidateTransientKey($TransientKey) && is_numeric($ActivityID)) { $HasPermission = $Session->CheckPermission('Garden.Activity.Delete'); if (!$HasPermission) { $Activity = $this->ActivityModel->GetID($ActivityID); $HasPermission = $Activity->InsertUserID == $Session->UserID; } if ($HasPermission) { $this->ActivityModel->Delete($ActivityID); } } if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { Redirect(GetIncomingValue('Return', Gdn_Url::WebRoot())); } $this->ControllerName = 'Home'; $this->View = 'FileNotFound'; $this->Render(); }
public function Base_Render_Before($Sender) { $InDashboard = !($Sender->MasterView == 'default' || $Sender->MasterView == ''); $Sender->AddJsFile('plugins/embedvanilla/local.js'); // Record the remote source using the embed feature. $RemoteUrl = C('Plugins.EmbedVanilla.RemoteUrl'); if (!$RemoteUrl) { $RemoteUrl = GetIncomingValue('remote'); if ($RemoteUrl) { SaveToConfig('Plugins.EmbedVanilla.RemoteUrl', $RemoteUrl); } } // Report the remote url to redirect to if not currently embedded. $Sender->AddDefinition('RemoteUrl', $RemoteUrl); if (!IsSearchEngine() && !$InDashboard && C('Plugins.EmbedVanilla.ForceRemoteUrl')) { $Sender->AddDefinition('ForceRemoteUrl', TRUE); } if ($InDashboard) { $Sender->AddDefinition('InDashboard', C('Plugins.EmbedVanilla.EmbedDashboard')); } }
public function Delete($DraftID = '', $TransientKey = '') { $Form = Gdn::Factory('Form'); $Session = Gdn::Session(); if (is_numeric($DraftID) && $DraftID > 0 && $Session->UserID > 0 && $Session->ValidateTransientKey($TransientKey)) { $Draft = $this->DraftModel->GetID($DraftID); if ($Draft && !$this->DraftModel->Delete($DraftID)) { $Form->AddError('Failed to delete discussion'); } } else { $Form->AddError('ErrPermission'); } // Redirect if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { $Target = GetIncomingValue('Target', '/vanilla/drafts'); Redirect($Target); } if ($Form->ErrorCount() > 0) { $this->SetJson('ErrorMessage', $Form->Errors()); } $this->Render(); }
public function Base_Render_Before($Sender) { // Set P3P header because IE won't allow cookies thru the iFrame without it $Sender->SetHeader('P3P', 'CP="CAO PSA OUR"'); $InDashboard = !($Sender->MasterView == 'default' || $Sender->MasterView == ''); $Sender->AddJsFile('plugins/embedvanilla/local.js'); // Record the remote source using the embed feature. $RemoteUrl = C('Plugins.EmbedVanilla.RemoteUrl'); if (!$RemoteUrl) { $RemoteUrl = GetIncomingValue('remote'); if ($RemoteUrl) { SaveToConfig('Plugins.EmbedVanilla.RemoteUrl', $RemoteUrl); } } // Report the remote url to redirect to if not currently embedded. $Sender->AddDefinition('RemoteUrl', $RemoteUrl); if (!IsSearchEngine() && !$InDashboard && C('Plugins.EmbedVanilla.ForceRemoteUrl')) { $Sender->AddDefinition('ForceRemoteUrl', TRUE); } $Sender->AddDefinition('Path', Gdn::Request()->Path()); if ($InDashboard) { $Sender->AddDefinition('InDashboard', C('Plugins.EmbedVanilla.EmbedDashboard')); } }
public function UpdateResponse() { // Get the message, response, and transientkey $Messages = GetIncomingValue('Messages', ''); $Response = GetIncomingValue('Response', ''); $TransientKey = GetIncomingValue('TransientKey', ''); // If the key validates $Session = Gdn::Session(); if ($Session->ValidateTransientKey($TransientKey)) { // If messages wasn't empty if ($Messages != '') { // Unserialize them & save them if necessary $Messages = Format::Unserialize($Messages); if (is_array($Messages)) { $MessageModel = new Gdn_MessageModel(); foreach ($Messages as $Message) { // Check to see if it already exists, and if not, add it. if (is_object($Message)) { $Message = Format::ObjectAsArray($Message); } $Content = ArrayValue('Content', $Message, ''); if ($Content != '') { $Data = $MessageModel->GetWhere(array('Content' => $Content)); if ($Data->NumRows() == 0) { $MessageModel->Save(array('Content' => $Content, 'AllowDismiss' => ArrayValue('AllowDismiss', $Message, '1'), 'Enabled' => ArrayValue('Enabled', $Message, '1'), 'Application' => ArrayValue('Application', $Message, 'Garden'), 'Controller' => ArrayValue('Controller', $Message, 'Settings'), 'Method' => ArrayValue('Method', $Message, ''), 'AssetTarget' => ArrayValue('AssetTarget', $Message, 'Content'), 'CssClass' => ArrayValue('CssClass', $Message, ''))); } } } } } // Load the config file so we can save some info in it $Config = Gdn::Factory(Gdn::AliasConfig); $Config->Load(PATH_CONF . DS . 'config.php', 'Save'); // If the response wasn't empty, save it in the config if ($Response != '') { $Config->Set('Garden.RequiredUpdates', $Response); } // Record the current update check time in the config. $Config->Set('Garden.UpdateCheckDate', time()); $Config->Save(); } }
/** * Calls the appropriate registration method based on the configuration setting. */ public function Register($InvitationCode = '') { $this->Form->SetModel($this->UserModel); // Define gender dropdown options $this->GenderOptions = array('m' => T('Male'), 'f' => T('Female')); // Make sure that the hour offset for new users gets defined when their account is created $this->AddJsFile('entry.js'); $this->Form->AddHidden('ClientHour', date('G', time())); // Use the server's current hour as a default $this->Form->AddHidden('Target', GetIncomingValue('Target', '')); $RegistrationMethod = $this->_RegistrationView(); $this->View = $RegistrationMethod; $this->{$RegistrationMethod}($InvitationCode); }
/** * Undocumented method. * * @todo Method __construct() needs a description. */ public function __construct() { $this->Application = ''; $this->ApplicationFolder = ''; $this->Assets = array(); $this->ControllerFolder = ''; $this->CssClass = ''; $this->Head = Gdn::Factory('Dummy'); $this->MasterView = ''; $this->ModuleSortContainer = ''; $this->OriginalRequestMethod = ''; $this->RedirectUrl = ''; $this->RequestMethod = ''; $this->RequestArgs = FALSE; $this->Routes = array(); $this->SelfUrl = ''; $this->StatusMessage = ''; $this->SyndicationMethod = SYNDICATION_NONE; $this->Theme = Gdn::Config('Garden.Theme'); $this->View = ''; $this->_CssFiles = array(); $this->_Definitions = array(); $this->_DeliveryMethod = GetIncomingValue('DeliveryMethod', DELIVERY_METHOD_XHTML); $this->_DeliveryType = GetIncomingValue('DeliveryType', DELIVERY_TYPE_ALL); $this->_Json = array(); $this->_ReDispatchRoute = FALSE; $this->_Headers = array('Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', 'X-Powered-By' => 'Lussumo ' . APPLICATION . ' ' . APPLICATION_VERSION, 'Content-Type' => Gdn::Config('Garden.ContentType', '') . '; charset=' . Gdn::Config('Garden.Charset', ''), 'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT'); parent::__construct(); $this->ControllerName = strtolower($this->ClassName); }
/** * Search results for tagging autocomplete. */ public function PluginController_TagSearch_Create($Sender, $q = '', $id = false, $parent = false, $type = 'default') { // Allow per-category tags $CategorySearch = C('Plugins.Tagging.CategorySearch', FALSE); if ($CategorySearch) { $CategoryID = GetIncomingValue('CategoryID'); } if ($parent && !is_numeric($parent)) { $parent = Gdn::SQL()->GetWhere('Tag', array('Name' => $parent))->Value('TagID', -1); } $Query = $q; $Data = array(); $Database = Gdn::Database(); if ($Query || $parent || $type !== 'default') { $TagQuery = Gdn::SQL()->Select('*')->From('Tag')->Limit(20); if ($Query) { $TagQuery->Like('FullName', str_replace(array('%', '_'), array('\\%', '_'), $Query), strlen($Query) > 2 ? 'both' : 'right'); } if ($type === 'default') { $defaultTypes = array_keys(TagModel::instance()->defaultTypes()); $TagQuery->Where('Type', $defaultTypes); // Other UIs can set a different type } elseif ($type) { $TagQuery->Where('Type', $type); } // Allow per-category tags if ($CategorySearch) { $TagQuery->Where('CategoryID', $CategoryID); } if ($parent) { $TagQuery->Where('ParentTagID', $parent); } // Run tag search query $TagData = $TagQuery->Get(); foreach ($TagData as $Tag) { $Data[] = array('id' => $id ? $Tag->TagID : $Tag->Name, 'name' => $Tag->FullName); } } // Close the db before exiting. $Database->CloseConnection(); // Return the data header("Content-type: application/json"); echo json_encode($Data); exit; }
/** * Add or subtract a value from a comment's score. * @param DiscussionController $Sender The controller that is implementing this method. * @param array $Args The arguments for the operation. */ public function DiscussionController_Score_Create($Sender, $Args) { $CommentID = $Args[0]; $ScoreKey = substr($Args[1], 0, 3) == 'Neg' ? -1 : 1; //$TransientKey = $Args[2]; $SQL = Gdn::SQL(); $Session = Gdn::Session(); // Get the current score for this user. $Data = $SQL->Select('uc.Score')->From('UserComment uc')->Where('uc.CommentID', $CommentID)->Where('uc.UserID', $Session->UserID)->Get()->FirstRow(); $UserScore = $Data ? $Data->Score : 0; // Get the score increments. $Inc = $this->GetScoreIncrements($CommentID, $UserScore); $Score = $Inc[$ScoreKey]; $UserScore += $Score; if ($Score != 0) { if ($Data) { // Update the score on an existing comment. $SQL->Update('UserComment')->Set('Score', $UserScore)->Set('DateUpdated', Format::ToDateTime())->Set('UpdateUserID', $Session->UserID)->Where('UserID', $Session->UserID)->Where('CommentID', $CommentID)->Put(); } else { // Insert a new score. $SQL->Insert('UserComment', array('CommentID' => $CommentID, 'UserID' => $Session->UserID, 'Score' => $UserScore, 'DateInserted' => Format::ToDateTime(), 'InsertUserID' => $Session->UserID, 'DateUpdated' => Format::ToDateTime(), 'UpdateUserID' => $Session->UserID)); } // Update the comment table with the sum of the scores. $Data = $SQL->Select('uc.Score', 'sum', 'SumScore')->From('UserComment uc')->Where('uc.CommentID', $CommentID)->Get()->FirstRow(); $SumScore = $Data ? $Data->SumScore : 0; $SQL->Update('Comment')->Set('SumScore', $SumScore)->Where('CommentID', $CommentID)->Put(); $Inc = $this->GetScoreIncrements($CommentID, $UserScore); } // Redirect back where the user came from if necessary if ($Sender->DeliveryType() != DELIVERY_TYPE_BOOL) { $Target = GetIncomingValue('Target', '/vanilla/discussions/scored'); Redirect($Target); } // Send the current information back to be dealt with on the client side. $Sender->SetJson('SumScore', isset($SumScore) ? sprintf(Plural($SumScore, '%s point', '%s points'), $SumScore) : NULL); $Sender->SetJson('Inc', $Inc); $Sender->Render(); break; }
public function UpdateResponse() { // Get the message, response, and transientkey $Messages = TrueStripSlashes(GetValue('Messages', $_POST)); $Response = TrueStripSlashes(GetValue('Response', $_POST)); $TransientKey = GetIncomingValue('TransientKey', ''); // If the key validates $Session = Gdn::Session(); if ($Session->ValidateTransientKey($TransientKey)) { // If messages wasn't empty if ($Messages != '') { // Unserialize them & save them if necessary $Messages = Gdn_Format::Unserialize($Messages); if (is_array($Messages)) { $MessageModel = new MessageModel(); foreach ($Messages as $Message) { // Check to see if it already exists, and if not, add it. if (is_object($Message)) $Message = Gdn_Format::ObjectAsArray($Message); $Content = ArrayValue('Content', $Message, ''); if ($Content != '') { $Data = $MessageModel->GetWhere(array('Content' => $Content)); if ($Data->NumRows() == 0) { $MessageModel->Save(array( 'Content' => $Content, 'AllowDismiss' => ArrayValue('AllowDismiss', $Message, '1'), 'Enabled' => ArrayValue('Enabled', $Message, '1'), 'Application' => ArrayValue('Application', $Message, 'Dashboard'), 'Controller' => ArrayValue('Controller', $Message, 'Settings'), 'Method' => ArrayValue('Method', $Message, ''), 'AssetTarget' => ArrayValue('AssetTarget', $Message, 'Content'), 'CssClass' => ArrayValue('CssClass', $Message, '') )); } } } } } // Save some info to the configuration file $Save = array(); // If the response wasn't empty, save it in the config if ($Response != '') $Save['Garden.RequiredUpdates'] = Gdn_Format::Unserialize($Response); // Record the current update check time in the config. $Save['Garden.UpdateCheckDate'] = time(); SaveToConfig($Save); } }
/** * Delete an activity item. * * @since 2.0.0 * @access public * * @param int $ActivityID Unique ID of item to delete. * @param string $TransientKey Verify intent. */ public function Delete($ActivityID = '', $TransientKey = '') { $Session = Gdn::Session(); if (!$Session->ValidateTransientKey($TransientKey)) { throw PermissionException(); } if (!is_numeric($ActivityID)) { throw Gdn_UserException('Invalid activity ID'); } $HasPermission = $Session->CheckPermission('Garden.Activity.Delete'); if (!$HasPermission) { $Activity = $this->ActivityModel->GetID($ActivityID); if (!$Activity) { throw NotFoundException('Activity'); } $HasPermission = $Activity['InsertUserID'] == $Session->UserID; } if (!$HasPermission) { throw PermissionException(); } $this->ActivityModel->Delete($ActivityID); if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { Redirect(GetIncomingValue('Target', $this->SelfUrl)); } // Still here? Getting a 404. $this->ControllerName = 'Home'; $this->View = 'FileNotFound'; $this->Render(); }
<li> <?php echo $this->Form->Label('Password', 'Password'); echo $this->Form->Input('Password', 'password', array('class' => 'InputBox Password')); echo Anchor(T('Forgot?'), '/entry/passwordrequest', 'ForgotPassword'); ?> </li> <li class="Buttons"> <?php echo $this->Form->Button('Sign In'); echo $this->Form->CheckBox('RememberMe', T('Keep me signed in'), array('value' => '1', 'id' => 'SignInRememberMe')); ?> </li> <li class="CreateAccount"> <?php $Target = GetIncomingValue('Target', ''); if ($Target != '') { $Target = '?Target=' . $Target; } printf(T("Don't have an account? %s"), Anchor(T('Create One.'), '/entry/register' . $Target)); ?> </li> </ul> <?php echo $this->Form->Close(); echo $this->Form->Open(array('Action' => Url('/entry/passwordrequest'), 'id' => 'Form_User_Password', 'style' => 'display: none;')); ?> <ul> <li> <?php echo $this->Form->Label('Enter your Email address', 'Email');
/** * Alternate version of Index that uses the embed master view. * * @param int $DiscussionID Unique identifier, if discussion has been created. * @param string $DiscussionStub Deprecated. * @param int $Offset * @param int $Limit */ public function Embed($DiscussionID = '', $DiscussionStub = '', $Offset = '', $Limit = '') { $this->Title(T('Comments')); // Add theme data $this->Theme = C('Garden.CommentsTheme', $this->Theme); Gdn_Theme::Section('Comments'); // Force view options $this->MasterView = 'empty'; $this->CanEditComments = FALSE; // Don't show the comment checkboxes on the embed comments page // Add some css to help with the transparent bg on embedded comments if ($this->Head) { $this->Head->AddString('<style type="text/css"> body { background: transparent !important; } </style>'); } // Javascript files & options $this->AddJsFile('jquery.gardenmorepager.js'); $this->AddJsFile('jquery.autogrow.js'); $this->RemoveJsFile('autosave.js'); $this->AddJsFile('discussion.js'); $this->AddDefinition('DoInform', '0'); // Suppress inform messages on embedded page. $this->AddDefinition('SelfUrl', Gdn::Request()->PathAndQuery()); $this->AddDefinition('Embedded', TRUE); // Define incoming variables (prefer querystring parameters over method parameters) $DiscussionID = is_numeric($DiscussionID) && $DiscussionID > 0 ? $DiscussionID : 0; $DiscussionID = GetIncomingValue('vanilla_discussion_id', $DiscussionID); $Offset = GetIncomingValue('Offset', $Offset); $Limit = GetIncomingValue('Limit', $Limit); $vanilla_identifier = GetIncomingValue('vanilla_identifier', ''); // Only allow vanilla identifiers of 32 chars or less - md5 if larger if (strlen($vanilla_identifier) > 32) { $vanilla_identifier = md5($vanilla_identifier); } $vanilla_type = GetIncomingValue('vanilla_type', 'page'); $vanilla_url = GetIncomingValue('vanilla_url', ''); $vanilla_category_id = GetIncomingValue('vanilla_category_id', ''); $ForeignSource = array('vanilla_identifier' => $vanilla_identifier, 'vanilla_type' => $vanilla_type, 'vanilla_url' => $vanilla_url, 'vanilla_category_id' => $vanilla_category_id); $this->SetData('ForeignSource', $ForeignSource); // Set comment sorting $SortComments = C('Garden.Embed.SortComments') == 'desc' ? 'desc' : 'asc'; $this->SetData('SortComments', $SortComments); // Retrieve the discussion record $Discussion = FALSE; if ($DiscussionID > 0) { $Discussion = $this->DiscussionModel->GetID($DiscussionID); } else { if ($vanilla_identifier != '' && $vanilla_type != '') { $Discussion = $this->DiscussionModel->GetForeignID($vanilla_identifier, $vanilla_type); } } // Set discussion data if we have one for this page if ($Discussion) { $this->Permission('Vanilla.Discussions.View', TRUE, 'Category', $Discussion->PermissionCategoryID); $this->SetData('Discussion', $Discussion, TRUE); $this->SetData('DiscussionID', $Discussion->DiscussionID, TRUE); $this->Title($Discussion->Name); // Actual number of comments, excluding the discussion itself $ActualResponses = $Discussion->CountComments; // Define the query offset & limit if (!is_numeric($Limit) || $Limit < 0) { $Limit = C('Garden.Embed.CommentsPerPage', 30); } $OffsetProvided = $Offset != ''; list($Offset, $Limit) = OffsetLimit($Offset, $Limit); $this->Offset = $Offset; if (C('Vanilla.Comments.AutoOffset')) { if ($ActualResponses <= $Limit) { $this->Offset = 0; } if ($this->Offset == $ActualResponses) { $this->Offset -= $Limit; } } else { if ($this->Offset == '') { $this->Offset = 0; } } if ($this->Offset < 0) { $this->Offset = 0; } // Set the canonical url to have the proper page title. $this->CanonicalUrl(DiscussionUrl($Discussion, PageNumber($this->Offset, $Limit))); // Load the comments. $CurrentOrderBy = $this->CommentModel->OrderBy(); if (StringBeginsWith(GetValueR('0.0', $CurrentOrderBy), 'c.DateInserted')) { $this->CommentModel->OrderBy('c.DateInserted ' . $SortComments); } // allow custom sort $this->SetData('Comments', $this->CommentModel->Get($Discussion->DiscussionID, $Limit, $this->Offset), TRUE); if (count($this->CommentModel->Where()) > 0) { $ActualResponses = FALSE; } $this->SetData('_Count', $ActualResponses); // Build a pager $PagerFactory = new Gdn_PagerFactory(); $this->EventArguments['PagerType'] = 'MorePager'; $this->FireEvent('BeforeBuildPager'); $this->Pager = $PagerFactory->GetPager($this->EventArguments['PagerType'], $this); $this->Pager->ClientID = 'Pager'; $this->Pager->MoreCode = 'More Comments'; $this->Pager->Configure($this->Offset, $Limit, $ActualResponses, 'discussion/embed/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . '/%1$s'); $this->Pager->CurrentRecords = $this->Comments->NumRows(); $this->FireEvent('AfterBuildPager'); } // Define the form for the comment input $this->Form = Gdn::Factory('Form', 'Comment'); $this->Form->Action = Url('/vanilla/post/comment/'); $this->Form->AddHidden('CommentID', ''); $this->Form->AddHidden('Embedded', 'true'); // Tell the post controller that this is an embedded page (in case there are custom views it needs to pick up from a theme). $this->Form->AddHidden('DisplayNewCommentOnly', 'true'); // Only load/display the new comment after posting (don't load all new comments since the page last loaded). // Grab the page title if ($this->Request->Get('title')) { $this->Form->SetValue('Name', $this->Request->Get('title')); } // Set existing DiscussionID for comment form if ($Discussion) { $this->Form->AddHidden('DiscussionID', $Discussion->DiscussionID); } foreach ($ForeignSource as $Key => $Val) { // Drop the foreign source information into the form so it can be used if creating a discussion $this->Form->AddHidden($Key, $Val); // Also drop it into the definitions so it can be picked up for stashing comments $this->AddDefinition($Key, $Val); } // Retrieve & apply the draft if there is one: $Draft = FALSE; if (Gdn::Session()->UserID && $Discussion) { $DraftModel = new DraftModel(); $Draft = $DraftModel->Get(Gdn::Session()->UserID, 0, 1, $Discussion->DiscussionID)->FirstRow(); $this->Form->AddHidden('DraftID', $Draft ? $Draft->DraftID : ''); } if ($Draft) { $this->Form->SetFormValue('Body', $Draft->Body); } else { // Look in the session stash for a comment $StashComment = Gdn::Session()->Stash('CommentForForeignID_' . $ForeignSource['vanilla_identifier'], '', FALSE); if ($StashComment) { $this->Form->SetValue('Body', $StashComment); $this->Form->SetFormValue('Body', $StashComment); } } // Deliver JSON data if necessary if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { if ($this->Discussion) { $this->SetJson('LessRow', $this->Pager->ToString('less')); $this->SetJson('MoreRow', $this->Pager->ToString('more')); } $this->View = 'comments'; } // Ordering note for JS if ($SortComments == 'desc') { $this->AddDefinition('PrependNewComments', '1'); } // Report the discussion id so js can use it. if ($Discussion) { $this->AddDefinition('DiscussionID', $Discussion->DiscussionID); } $this->FireEvent('BeforeDiscussionRender'); $this->Render(); }
/** * Allows you to delete a comment. If the comment is the only one in the * discussion, the discussion will be deleted as well. Users without * administrative delete abilities should not be able to delete a comment * unless it is a draft. */ public function DeleteComment($CommentID = '', $TransientKey = '') { $Session = Gdn::Session(); if (is_numeric($CommentID) && $CommentID > 0 && $Session->UserID > 0 && $Session->ValidateTransientKey($TransientKey)) { $Comment = $this->CommentModel->GetID($CommentID); if ($Comment) { $Discussion = $this->DiscussionModel->GetID($Comment->DiscussionID); $HasPermission = $Comment->InsertUserID == $Session->UserID; if (!$HasPermission && $Discussion) { $HasPermission = $Session->CheckPermission('Vanilla.Comments.Delete', TRUE, 'Category', $Discussion->CategoryID); } if ($Discussion && $HasPermission) { if (!$this->CommentModel->Delete($CommentID)) { $this->Form->AddError('Failed to delete comment'); } } else { $this->Form->AddError('ErrPermission'); } } } else { $this->Form->AddError('ErrPermission'); } // Redirect if ($this->_DeliveryType != DELIVERY_TYPE_BOOL) { $Target = GetIncomingValue('Target', 'discussions'); Redirect($Target); } if ($this->Form->ErrorCount() > 0) { $this->SetJson('ErrorMessage', $this->Form->Errors()); } $this->Render(); }
/** * Delete an activity item. * * @since 2.0.0 * @access public * * @param int $ActivityID Unique ID of item to delete. * @param string $TransientKey Verify intent. */ public function delete($ActivityID = '', $TransientKey = '') { $session = Gdn::session(); if (!$session->validateTransientKey($TransientKey)) { throw permissionException(); } if (!is_numeric($ActivityID)) { throw Gdn_UserException('Invalid ID'); } if (!$this->ActivityModel->canDelete($this->ActivityModel->getID($ActivityID))) { throw permissionException(); } $this->ActivityModel->delete($ActivityID); if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { redirect(GetIncomingValue('Target', $this->SelfUrl)); } // Still here? Getting a 404. $this->ControllerName = 'Home'; $this->View = 'FileNotFound'; $this->render(); }
public function Leave($AuthenticationSchemeAlias = 'default', $TransientKey = '') { $this->EventArguments['AuthenticationSchemeAlias'] = $AuthenticationSchemeAlias; $this->FireEvent('BeforeLeave'); // Allow hijacking deauth type $AuthenticationSchemeAlias = $this->EventArguments['AuthenticationSchemeAlias']; try { $Authenticator = Gdn::Authenticator()->AuthenticateWith($AuthenticationSchemeAlias); } catch (Exception $e) { $Authenticator = Gdn::Authenticator()->AuthenticateWith('default'); } // Only sign the user out if this is an authenticated postback! Start off pessimistic $this->Leaving = FALSE; $Result = Gdn_Authenticator::REACT_RENDER; // Build these before doing anything desctructive as they are supposed to have user context $LogoutResponse = $Authenticator->LogoutResponse(); $LoginResponse = $Authenticator->LoginResponse(); $AuthenticatedPostbackRequired = $Authenticator->RequireLogoutTransientKey(); if (!$AuthenticatedPostbackRequired || Gdn::Session()->ValidateTransientKey($TransientKey)) { $Result = $Authenticator->DeAuthenticate(); $this->Leaving = TRUE; } if ($Result == Gdn_Authenticator::AUTH_SUCCESS) { $this->View = 'leave'; $Reaction = $LogoutResponse; } else { $this->View = 'auth/' . $Authenticator->GetAuthenticationSchemeAlias(); $Reaction = $LoginResponse; } switch ($Reaction) { case Gdn_Authenticator::REACT_RENDER: break; case Gdn_Authenticator::REACT_EXIT: exit; break; case Gdn_Authenticator::REACT_REMOTE: // Render the view, but set the delivery type to VIEW $this->_DeliveryType = DELIVERY_TYPE_VIEW; break; case Gdn_Authenticator::REACT_REDIRECT: default: // If we're just told to redirect, but not where... try to figure out somewhere that makes sense. if ($Reaction == Gdn_Authenticator::REACT_REDIRECT) { $Route = '/'; $Target = GetIncomingValue('Target', NULL); if (!is_null($Target)) { $Route = $Target; } } else { $Route = $Reaction; } if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { $this->RedirectUrl = Url($Route); } else { if ($Route !== FALSE) { Redirect($Route); } else { Redirect(Gdn::Router()->GetDestination('DefaultController')); } } break; } $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', ''); $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 PostController $Sender * @param array $Args * @return mixed */ public function PostController_Comment_Create($Sender, $Args = array()) { if ($Sender->Form->AuthenticatedPostBack()) { $Sender->Form->SetModel($Sender->CommentModel); // Grab the discussion for use later. $DiscussionID = $Sender->Form->GetFormValue('DiscussionID'); $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->GetID($DiscussionID); // Check to see if the discussion is supposed to be in private... $WhisperConversationID = GetValueR('Attributes.WhisperConversationID', $Discussion); if ($WhisperConversationID === TRUE) { // There isn't a conversation so we want to create one. $Sender->Form->SetFormValue('Whisper', TRUE); $WhisperUserIDs = GetValueR('Attributes.WhisperUserIDs', $Discussion); $Sender->Form->SetFormValue('RecipientUserID', $WhisperUserIDs); } elseif ($WhisperConversationID) { // There is already a conversation. $Sender->Form->SetFormValue('Whisper', TRUE); $Sender->Form->SetFormValue('ConversationID', $WhisperConversationID); } $Whisper = $Sender->Form->GetFormValue('Whisper') && GetIncomingValue('Type') != 'Draft'; $WhisperTo = trim($Sender->Form->GetFormValue('To')); $ConversationID = $Sender->Form->GetFormValue('ConversationID'); // If this isn't a whisper then post as normal. if (!$Whisper) { return call_user_func_array(array($Sender, 'Comment'), $Args); } $ConversationModel = new ConversationModel(); $ConversationMessageModel = new ConversationMessageModel(); if ($ConversationID > 0) { $Sender->Form->SetModel($ConversationMessageModel); } else { // We have to remove the blank conversation ID or else the model won't validate. $FormValues = $Sender->Form->FormValues(); unset($FormValues['ConversationID']); $FormValues['Subject'] = GetValue('Name', $Discussion); $Sender->Form->FormValues($FormValues); $Sender->Form->SetModel($ConversationModel); $ConversationModel->Validation->ApplyRule('DiscussionID', 'Required'); } $ID = $Sender->Form->Save($ConversationMessageModel); if ($Sender->Form->ErrorCount() > 0) { $Sender->ErrorMessage($Sender->Form->Errors()); } else { if ($WhisperConversationID === TRUE) { $Discussion->Attributes['WhisperConversationID'] = $ID; $DiscussionModel->SetProperty($DiscussionID, 'Attributes', serialize($Discussion->Attributes)); } $LastCommentID = GetValue('LastCommentID', $Discussion); $MessageID = GetValue('LastMessageID', $ConversationMessageModel, FALSE); // Randomize the querystring to force the browser to refresh. $Rand = mt_rand(10000, 99999); if ($LastCommentID) { // Link to the last comment. $HashID = $MessageID ? 'w' . $MessageID : $LastCommentID; $Sender->RedirectUrl = Url("discussion/comment/{$LastCommentID}?rand={$Rand}#Comment_{$HashID}", TRUE); } else { // Link to the discussion. $Hash = $MessageID ? "Comment_w{$MessageID}" : 'Item_1'; $Name = rawurlencode(GetValue('Name', $Discussion, 'x')); $Sender->RedirectUrl = Url("discussion/{$DiscussionID}/{$Name}?rand={$Rand}#{$Hash}", TRUE); } } $Sender->Render(); } else { return call_user_func_array(array($Sender, 'Comment'), $Args); } }
/** * Allows user to delete a comment. * * If the comment is the only one in the discussion, the discussion will * be deleted as well. Users without administrative delete abilities * should not be able to delete a comment unless it is a draft. This is * a "hard" delete - it is removed from the database. * * @since 2.0.0 * @access public * * @param int $CommentID Unique comment ID. * @param string $TransientKey Single-use hash to prove intent. */ public function deleteComment($CommentID = '', $TransientKey = '') { $Session = Gdn::session(); $DefaultTarget = '/discussions/'; $ValidCommentID = is_numeric($CommentID) && $CommentID > 0; $ValidUser = $Session->UserID > 0 && $Session->validateTransientKey($TransientKey); if ($ValidCommentID && $ValidUser) { // Get comment and discussion data $Comment = $this->CommentModel->getID($CommentID); $DiscussionID = val('DiscussionID', $Comment); $Discussion = $this->DiscussionModel->getID($DiscussionID); if ($Comment && $Discussion) { $DefaultTarget = discussionUrl($Discussion); // Make sure comment is this user's or they have Delete permission if ($Comment->InsertUserID != $Session->UserID || !c('Vanilla.Comments.AllowSelfDelete')) { $this->permission('Vanilla.Comments.Delete', true, 'Category', $Discussion->PermissionCategoryID); } // Make sure that content can (still) be edited $EditContentTimeout = c('Garden.EditContentTimeout', -1); $CanEdit = $EditContentTimeout == -1 || strtotime($Comment->DateInserted) + $EditContentTimeout > time(); if (!$CanEdit) { $this->permission('Vanilla.Comments.Delete', true, 'Category', $Discussion->PermissionCategoryID); } // Delete the comment if (!$this->CommentModel->delete($CommentID)) { $this->Form->addError('Failed to delete comment'); } } else { $this->Form->addError('Invalid comment'); } } else { $this->Form->addError('ErrPermission'); } // Redirect if ($this->_DeliveryType == DELIVERY_TYPE_ALL) { $Target = GetIncomingValue('Target', $DefaultTarget); SafeRedirect($Target); } if ($this->Form->errorCount() > 0) { $this->setJson('ErrorMessage', $this->Form->errors()); } else { $this->jsonTarget("#Comment_{$CommentID}", '', 'SlideUp'); } $this->render(); }