/**
  * Select content based on author RoleID
  * 
  * @param array $Parameters
  * @return boolean
  */
 protected function SelectByRole($Parameters)
 {
     if (!is_array($Parameters)) {
         $RoleID = $Parameters;
     } else {
         $RoleID = GetValue('RoleID', $Parameters, NULL);
     }
     // Lookup role name -> roleID
     if (is_string($RoleID)) {
         $RoleModel = new RoleModel();
         $Roles = explode(',', $RoleID);
         $RoleID = array();
         foreach ($Roles as $TestRoleID) {
             $TestRoleID = trim($TestRoleID);
             $Role = $RoleModel->GetByName($TestRoleID);
             if (!$Role) {
                 continue;
             } else {
                 $Role = array_shift($Role);
                 $RoleID[] = GetValue('RoleID', $Role);
             }
         }
     }
     if (empty($RoleID) || !sizeof($RoleID)) {
         return FALSE;
     }
     // Check cache
     $SelectorRoleCacheKey = "modules.promotedcontent.role.{$RoleID}";
     $Content = Gdn::Cache()->Get($SelectorRoleCacheKey);
     if ($Content == Gdn_Cache::CACHEOP_FAILURE) {
         // Get everyone with this Role
         $UserIDs = Gdn::SQL()->Select('ur.UserID')->From('UserRole ur')->Where('ur.RoleID', $RoleID)->GroupBy('UserID')->Get()->Result(DATASET_TYPE_ARRAY);
         $UserIDs = ConsolidateArrayValuesByKey($UserIDs, 'UserID');
         // Get matching Discussions
         $Discussions = Gdn::SQL()->Select('d.*')->From('Discussion d')->WhereIn('d.InsertUserID', $UserIDs)->OrderBy('DateInserted', 'DESC')->Limit($this->Limit)->Get()->Result(DATASET_TYPE_ARRAY);
         // Get matching Comments
         $Comments = Gdn::SQL()->Select('c.*')->From('Comment c')->WhereIn('InsertUserID', $UserIDs)->OrderBy('DateInserted', 'DESC')->Limit($this->Limit)->Get()->Result(DATASET_TYPE_ARRAY);
         $this->JoinCategory($Comments);
         // Interleave
         $Content = $this->Union('DateInserted', array('Discussion' => $Discussions, 'Comment' => $Comments));
         $this->Prepare($Content);
         // Add result to cache
         Gdn::Cache()->Store($SelectorRoleCacheKey, $Content, array(Gdn_Cache::FEATURE_EXPIRY => $this->Expiry));
     }
     $this->Security($Content);
     $this->Condense($Content, $this->Limit);
     return $Content;
 }
 /**
  * Connect the user with an external source.
  *
  * This controller method is meant to be used with plugins that set its data array to work.
  * Events: ConnectData
  * 
  * @since 2.0.0
  * @access public
  *
  * @param string $Method Used to register multiple providers on ConnectData event.
  */
 public function Connect($Method)
 {
     $this->AddJsFile('entry.js');
     $this->View = 'connect';
     $IsPostBack = $this->Form->IsPostBack() && $this->Form->GetFormValue('Connect', NULL) !== NULL;
     if (!$IsPostBack) {
         // Here are the initial data array values. that can be set by a plugin.
         $Data = array('Provider' => '', 'ProviderName' => '', 'UniqueID' => '', 'FullName' => '', 'Name' => '', 'Email' => '', 'Photo' => '', 'Target' => $this->Target());
         $this->Form->SetData($Data);
         $this->Form->AddHidden('Target', $this->Request->Get('Target', '/'));
     }
     // The different providers can check to see if they are being used and modify the data array accordingly.
     $this->EventArguments = array($Method);
     // Fire ConnectData event & error handling.
     $CurrentData = $this->Form->FormValues();
     try {
         $this->FireEvent('ConnectData');
     } catch (Gdn_UserException $Ex) {
         $this->Form->AddError($Ex);
         return $this->Render('ConnectError');
     } catch (Exception $Ex) {
         if (Debug()) {
             $this->Form->AddError($Ex);
         } else {
             $this->Form->AddError('There was an error fetching the connection data.');
         }
         return $this->Render('ConnectError');
     }
     if (!UserModel::NoEmail()) {
         if (!$this->Form->GetFormValue('Email') || $this->Form->GetFormValue('EmailVisible')) {
             $this->Form->SetFormValue('EmailVisible', TRUE);
             $this->Form->AddHidden('EmailVisible', TRUE);
             if ($IsPostBack) {
                 $this->Form->SetFormValue('Email', GetValue('Email', $CurrentData));
             }
         }
     }
     $FormData = $this->Form->FormValues();
     // debug
     // Make sure the minimum required data has been provided to the connect.
     if (!$this->Form->GetFormValue('Provider')) {
         $this->Form->AddError('ValidateRequired', T('Provider'));
     }
     if (!$this->Form->GetFormValue('UniqueID')) {
         $this->Form->AddError('ValidateRequired', T('UniqueID'));
     }
     if (!$this->Data('Verified')) {
         // Whatever event handler catches this must Set the data 'Verified' to true to prevent a random site from connecting without credentials.
         // This must be done EVERY postback and is VERY important.
         $this->Form->AddError('The connection data has not been verified.');
     }
     if ($this->Form->ErrorCount() > 0) {
         return $this->Render();
     }
     $UserModel = Gdn::UserModel();
     // Check to see if there is an existing user associated with the information above.
     $Auth = $UserModel->GetAuthentication($this->Form->GetFormValue('UniqueID'), $this->Form->GetFormValue('Provider'));
     $UserID = GetValue('UserID', $Auth);
     // Check to synchronise roles upon connecting.
     if (($this->Data('Trusted') || C('Garden.SSO.SynchRoles')) && $this->Form->GetFormValue('Roles', NULL) !== NULL) {
         $SaveRoles = TRUE;
         // Translate the role names to IDs.
         $Roles = $this->Form->GetFormValue('Roles', NULL);
         $Roles = RoleModel::GetByName($Roles);
         $RoleIDs = array_keys($Roles);
         if (empty($RoleIDs)) {
             // The user must have at least one role. This protects that.
             $RoleIDs = $this->UserModel->NewUserRoleIDs();
         }
         $this->Form->SetFormValue('RoleID', $RoleIDs);
     } else {
         $SaveRoles = FALSE;
     }
     if ($UserID) {
         // The user is already connected.
         $this->Form->SetFormValue('UserID', $UserID);
         if (C('Garden.Registration.ConnectSynchronize', TRUE)) {
             $User = Gdn::UserModel()->GetID($UserID, DATASET_TYPE_ARRAY);
             $Data = $this->Form->FormValues();
             // Don't overwrite the user photo if the user uploaded a new one.
             $Photo = GetValue('Photo', $User);
             if (!GetValue('Photo', $Data) || $Photo && !StringBeginsWith($Photo, 'http')) {
                 unset($Data['Photo']);
             }
             // Synchronize the user's data.
             $UserModel->Save($Data, array('NoConfirmEmail' => TRUE, 'FixUnique' => TRUE, 'SaveRoles' => $SaveRoles));
         }
         // Always save the attributes because they may contain authorization information.
         if ($Attributes = $this->Form->GetFormValue('Attributes')) {
             $UserModel->SaveAttribute($UserID, $Attributes);
         }
         // Sign the user in.
         Gdn::Session()->Start($UserID, TRUE, TRUE);
         Gdn::UserModel()->FireEvent('AfterSignIn');
         //         $this->_SetRedirect(TRUE);
         $this->_SetRedirect($this->Request->Get('display') == 'popup');
     } elseif ($this->Form->GetFormValue('Name') || $this->Form->GetFormValue('Email')) {
         $NameUnique = C('Garden.Registration.NameUnique', TRUE);
         $EmailUnique = C('Garden.Registration.EmailUnique', TRUE);
         $AutoConnect = C('Garden.Registration.AutoConnect');
         // Get the existing users that match the name or email of the connection.
         $Search = FALSE;
         if ($this->Form->GetFormValue('Name') && $NameUnique) {
             $UserModel->SQL->OrWhere('Name', $this->Form->GetFormValue('Name'));
             $Search = TRUE;
         }
         if ($this->Form->GetFormValue('Email') && ($EmailUnique || $AutoConnect)) {
             $UserModel->SQL->OrWhere('Email', $this->Form->GetFormValue('Email'));
             $Search = TRUE;
         }
         if ($Search) {
             $ExistingUsers = $UserModel->GetWhere()->ResultArray();
         } else {
             $ExistingUsers = array();
         }
         // Check to automatically link the user.
         if ($AutoConnect && count($ExistingUsers) > 0) {
             foreach ($ExistingUsers as $Row) {
                 if ($this->Form->GetFormValue('Email') == $Row['Email']) {
                     $UserID = $Row['UserID'];
                     $this->Form->SetFormValue('UserID', $UserID);
                     $Data = $this->Form->FormValues();
                     if (C('Garden.Registration.ConnectSynchronize', TRUE)) {
                         // Don't overwrite a photo if the user has already uploaded one.
                         $Photo = GetValue('Photo', $Row);
                         if (!GetValue('Photo', $Data) || $Photo && !StringBeginsWith($Photo, 'http')) {
                             unset($Data['Photo']);
                         }
                         $UserModel->Save($Data, array('NoConfirmEmail' => TRUE, 'FixUnique' => TRUE, 'SaveRoles' => $SaveRoles));
                     }
                     if ($Attributes = $this->Form->GetFormValue('Attributes')) {
                         $UserModel->SaveAttribute($UserID, $Attributes);
                     }
                     // Save the userauthentication link.
                     $UserModel->SaveAuthentication(array('UserID' => $UserID, 'Provider' => $this->Form->GetFormValue('Provider'), 'UniqueID' => $this->Form->GetFormValue('UniqueID')));
                     // Sign the user in.
                     Gdn::Session()->Start($UserID, TRUE, TRUE);
                     Gdn::UserModel()->FireEvent('AfterSignIn');
                     //         $this->_SetRedirect(TRUE);
                     $this->_SetRedirect($this->Request->Get('display') == 'popup');
                     $this->Render();
                     return;
                 }
             }
         }
         $CurrentUserID = Gdn::Session()->UserID;
         // Massage the existing users.
         foreach ($ExistingUsers as $Index => $UserRow) {
             if ($EmailUnique && $UserRow['Email'] == $this->Form->GetFormValue('Email')) {
                 $EmailFound = $UserRow;
                 break;
             }
             if ($UserRow['Name'] == $this->Form->GetFormValue('Name')) {
                 $NameFound = $UserRow;
             }
             if ($CurrentUserID > 0 && $UserRow['UserID'] == $CurrentUserID) {
                 unset($ExistingUsers[$Index]);
                 $CurrentUserFound = TRUE;
             }
         }
         if (isset($EmailFound)) {
             // The email address was found and can be the only user option.
             $ExistingUsers = array($UserRow);
             $this->SetData('NoConnectName', TRUE);
         } elseif (isset($CurrentUserFound)) {
             $ExistingUsers = array_merge(array('UserID' => 'current', 'Name' => sprintf(T('%s (Current)'), Gdn::Session()->User->Name)), $ExistingUsers);
         }
         if (!isset($NameFound) && !$IsPostBack) {
             $this->Form->SetFormValue('ConnectName', $this->Form->GetFormValue('Name'));
         }
         $this->SetData('ExistingUsers', $ExistingUsers);
         if (UserModel::NoEmail()) {
             $EmailValid = TRUE;
         } else {
             $EmailValid = ValidateRequired($this->Form->GetFormValue('Email'));
         }
         if ($this->Form->GetFormValue('Name') && $EmailValid && (!is_array($ExistingUsers) || count($ExistingUsers) == 0)) {
             // There is no existing user with the suggested name so we can just create the user.
             $User = $this->Form->FormValues();
             $User['Password'] = RandomString(50);
             // some password is required
             $User['HashMethod'] = 'Random';
             $User['Source'] = $this->Form->GetFormValue('Provider');
             $User['SourceID'] = $this->Form->GetFormValue('UniqueID');
             $User['Attributes'] = $this->Form->GetFormValue('Attributes', NULL);
             $User['Email'] = $this->Form->GetFormValue('ConnectEmail', $this->Form->GetFormValue('Email', NULL));
             //            $UserID = $UserModel->InsertForBasic($User, FALSE, array('ValidateEmail' => FALSE, 'NoConfirmEmail' => TRUE, 'SaveRoles' => $SaveRoles));
             $UserID = $UserModel->Register($User, array('CheckCaptcha' => FALSE, 'ValidateEmail' => FALSE, 'NoConfirmEmail' => TRUE, 'SaveRoles' => $SaveRoles));
             $User['UserID'] = $UserID;
             $this->Form->SetValidationResults($UserModel->ValidationResults());
             if ($UserID) {
                 $UserModel->SaveAuthentication(array('UserID' => $UserID, 'Provider' => $this->Form->GetFormValue('Provider'), 'UniqueID' => $this->Form->GetFormValue('UniqueID')));
                 $this->Form->SetFormValue('UserID', $UserID);
                 Gdn::Session()->Start($UserID, TRUE, TRUE);
                 Gdn::UserModel()->FireEvent('AfterSignIn');
                 // Send the welcome email.
                 if (C('Garden.Registration.SendConnectEmail', FALSE)) {
                     try {
                         $UserModel->SendWelcomeEmail($UserID, '', 'Connect', array('ProviderName' => $this->Form->GetFormValue('ProviderName', $this->Form->GetFormValue('Provider', 'Unknown'))));
                     } catch (Exception $Ex) {
                         // Do nothing if emailing doesn't work.
                     }
                 }
                 $this->_SetRedirect(TRUE);
             }
         }
     }
     // Save the user's choice.
     if ($IsPostBack) {
         // The user has made their decision.
         $PasswordHash = new Gdn_PasswordHash();
         $UserSelect = $this->Form->GetFormValue('UserSelect');
         if (!$UserSelect || $UserSelect == 'other') {
             // The user entered a username.
             $ConnectNameEntered = TRUE;
             if ($this->Form->ValidateRule('ConnectName', 'ValidateRequired')) {
                 $ConnectName = $this->Form->GetFormValue('ConnectName');
                 $User = FALSE;
                 if (C('Garden.Registration.NameUnique')) {
                     // Check to see if there is already a user with the given name.
                     $User = $UserModel->GetWhere(array('Name' => $ConnectName))->FirstRow(DATASET_TYPE_ARRAY);
                 }
                 if (!$User) {
                     $this->Form->ValidateRule('ConnectName', 'ValidateUsername');
                 }
             }
         } else {
             // The user selected an existing user.
             $ConnectNameEntered = FALSE;
             if ($UserSelect == 'current') {
                 if (Gdn::Session()->UserID == 0) {
                     // This shouldn't happen, but a use could sign out in another browser and click submit on this form.
                     $this->Form->AddError('@You were uexpectidly signed out.');
                 } else {
                     $UserSelect = Gdn::Session()->UserID;
                 }
             }
             $User = $UserModel->GetID($UserSelect, DATASET_TYPE_ARRAY);
         }
         if (isset($User) && $User) {
             // Make sure the user authenticates.
             if (!$User['UserID'] == Gdn::Session()->UserID) {
                 if ($this->Form->ValidateRule('ConnectPassword', 'ValidateRequired', sprintf(T('ValidateRequired'), T('Password')))) {
                     try {
                         if (!$PasswordHash->CheckPassword($this->Form->GetFormValue('ConnectPassword'), $User['Password'], $User['HashMethod'], $this->Form->GetFormValue('ConnectName'))) {
                             if ($ConnectNameEntered) {
                                 $this->Form->AddError('The username you entered has already been taken.');
                             } else {
                                 $this->Form->AddError('The password you entered is incorrect.');
                             }
                         }
                     } catch (Gdn_UserException $Ex) {
                         $this->Form->AddError($Ex);
                     }
                 }
             }
         } elseif ($this->Form->ErrorCount() == 0) {
             // The user doesn't exist so we need to add another user.
             $User = $this->Form->FormValues();
             $User['Name'] = $User['ConnectName'];
             $User['Password'] = RandomString(50);
             // some password is required
             $User['HashMethod'] = 'Random';
             $UserID = $UserModel->Register($User, array('CheckCaptcha' => FALSE, 'NoConfirmEmail' => TRUE, 'SaveRoles' => $SaveRoles));
             $User['UserID'] = $UserID;
             $this->Form->SetValidationResults($UserModel->ValidationResults());
             if ($UserID) {
                 //               // Add the user to the default roles.
                 //               $UserModel->SaveRoles($UserID, C('Garden.Registration.DefaultRoles'));
                 // Send the welcome email.
                 $UserModel->SendWelcomeEmail($UserID, '', 'Connect', array('ProviderName' => $this->Form->GetFormValue('ProviderName', $this->Form->GetFormValue('Provider', 'Unknown'))));
             }
         }
         if ($this->Form->ErrorCount() == 0) {
             // Save the authentication.
             if (isset($User) && GetValue('UserID', $User)) {
                 $UserModel->SaveAuthentication(array('UserID' => $User['UserID'], 'Provider' => $this->Form->GetFormValue('Provider'), 'UniqueID' => $this->Form->GetFormValue('UniqueID')));
                 $this->Form->SetFormValue('UserID', $User['UserID']);
             }
             // Sign the appropriate user in.
             Gdn::Session()->Start($this->Form->GetFormValue('UserID', TRUE, TRUE));
             Gdn::UserModel()->FireEvent('AfterSignIn');
             $this->_SetRedirect(TRUE);
         }
     }
     $this->Render();
 }
 /**
  * Select content based on author RoleID.
  *
  * @param array|int $Parameters
  * @return array|false
  */
 protected function selectByRole($Parameters)
 {
     if (!is_array($Parameters)) {
         $RoleID = $Parameters;
     } else {
         $RoleID = val('RoleID', $Parameters, null);
     }
     // Lookup role name -> roleID
     if ($RoleID && is_string($RoleID)) {
         $RoleModel = new RoleModel();
         $Roles = explode(',', $RoleID);
         $RoleID = array();
         foreach ($Roles as $TestRoleID) {
             $TestRoleID = trim($TestRoleID);
             $Role = $RoleModel->GetByName($TestRoleID);
             if (!$Role) {
                 continue;
             } else {
                 $Role = array_shift($Role);
                 $RoleID[] = val('RoleID', $Role);
             }
         }
     }
     if (empty($RoleID) || !sizeof($RoleID)) {
         return false;
     }
     // Check cache
     sort($RoleID);
     $RoleIDKey = implode('-', $RoleID);
     $SelectorRoleCacheKey = "modules.promotedcontent.role.{$RoleIDKey}";
     $Content = Gdn::cache()->get($SelectorRoleCacheKey);
     if ($Content == Gdn_Cache::CACHEOP_FAILURE) {
         // Get everyone with this Role
         $UserIDs = Gdn::sql()->select('ur.UserID')->from('UserRole ur')->where('ur.RoleID', $RoleID)->groupBy('UserID')->get()->result(DATASET_TYPE_ARRAY);
         $UserIDs = array_column($UserIDs, 'UserID');
         // Get matching Discussions
         $Discussions = array();
         if ($this->ShowDiscussions()) {
             $Discussions = Gdn::sql()->select('d.*')->from('Discussion d')->whereIn('d.InsertUserID', $UserIDs)->orderBy('DateInserted', 'DESC')->limit($this->Limit)->get()->result(DATASET_TYPE_ARRAY);
         }
         // Get matching Comments
         $Comments = array();
         if ($this->ShowComments()) {
             $Comments = Gdn::sql()->select('c.*')->from('Comment c')->whereIn('InsertUserID', $UserIDs)->orderBy('DateInserted', 'DESC')->limit($this->Limit)->get()->result(DATASET_TYPE_ARRAY);
             $this->JoinCategory($Comments);
         }
         // Interleave
         $Content = $this->Union('DateInserted', array('Discussion' => $Discussions, 'Comment' => $Comments));
         $this->processContent($Content);
         // Add result to cache
         Gdn::cache()->store($SelectorRoleCacheKey, $Content, array(Gdn_Cache::FEATURE_EXPIRY => $this->Expiry));
     }
     $this->Security($Content);
     $this->Condense($Content, $this->Limit);
     return $Content;
 }