/**
    * Check whether or not the record is spam.
    * @param string $RecordType By default, this should be one of the following:
    *  - Comment: A comment.
    *  - Discussion: A discussion.
    *  - User: A user registration.
    * @param array $Data The record data.
    * @param array $Options Options for fine-tuning this method call.
    *  - Log: Log the record if it is found to be spam.
    */
   public static function IsSpam($RecordType, $Data, $Options = array()) {
      // Set some information about the user in the data.
      TouchValue('IPAddress', $Data, Gdn::Request()->IpAddress());
      
      if ($RecordType == 'User') {
         TouchValue('Username', $Data, $Data['Name']);
      } else {
         TouchValue('Username', $Data, Gdn::Session()->User->Name);
         TouchValue('Email', $Data, Gdn::Session()->User->Email);
      }

      $Sp = self::_Instance();
      
      $Sp->EventArguments['RecordType'] = $RecordType;
      $Sp->EventArguments['Data'] = $Data;
      $Sp->EventArguments['Options'] = $Options;
      $Sp->EventArguments['IsSpam'] = FALSE;

      $Sp->FireEvent('CheckSpam');
      $Spam = $Sp->EventArguments['IsSpam'];

      // Log the spam entry.
      if ($Spam && GetValue('Log', $Options, TRUE)) {
         LogModel::Insert('Spam', $RecordType, $Data);
      }

      return $Spam;
   }
 /**
  * Check whether or not the record is spam.
  * @param string $RecordType By default, this should be one of the following:
  *  - Comment: A comment.
  *  - Discussion: A discussion.
  *  - User: A user registration.
  * @param array $Data The record data.
  * @param array $Options Options for fine-tuning this method call.
  *  - Log: Log the record if it is found to be spam.
  */
 public static function IsSpam($RecordType, $Data, $Options = array())
 {
     // Set some information about the user in the data.
     TouchValue('IPAddress', $Data, Gdn::Request()->IpAddress());
     if ($RecordType == 'Registration') {
         TouchValue('Username', $Data, $Data['Name']);
     } else {
         TouchValue('Username', $Data, Gdn::Session()->User->Name);
         TouchValue('Email', $Data, Gdn::Session()->User->Email);
     }
     $Sp = self::_Instance();
     $Sp->EventArguments['RecordType'] = $RecordType;
     $Sp->EventArguments['Data'] =& $Data;
     $Sp->EventArguments['Options'] =& $Options;
     $Sp->EventArguments['IsSpam'] = FALSE;
     $Sp->FireEvent('CheckSpam');
     $Spam = $Sp->EventArguments['IsSpam'];
     // Log the spam entry.
     if ($Spam && GetValue('Log', $Options, TRUE)) {
         $LogOptions = array();
         switch ($RecordType) {
             case 'Registration':
                 $LogOptions['GroupBy'] = array('RecordIPAddress');
                 break;
             case 'Comment':
             case 'Discussion':
                 $LogOptions['GroupBy'] = array('RecordID');
                 break;
         }
         LogModel::Insert('Spam', $RecordType, $Data, $LogOptions);
     }
     return $Spam;
 }
 /**
  * Check whether or not the record is spam.
  * @param string $RecordType By default, this should be one of the following:
  *  - Comment: A comment.
  *  - Discussion: A discussion.
  *  - User: A user registration.
  * @param array $Data The record data.
  * @param array $Options Options for fine-tuning this method call.
  *  - Log: Log the record if it is found to be spam.
  */
 public static function IsSpam($RecordType, $Data, $Options = array())
 {
     if (self::$Disabled) {
         return FALSE;
     }
     // Set some information about the user in the data.
     if ($RecordType == 'Registration') {
         TouchValue('Username', $Data, $Data['Name']);
     } else {
         TouchValue('InsertUserID', $Data, Gdn::Session()->UserID);
         $User = Gdn::UserModel()->GetID(GetValue('InsertUserID', $Data), DATASET_TYPE_ARRAY);
         if ($User) {
             if (GetValue('Verified', $User)) {
                 // The user has been verified and isn't a spammer.
                 return FALSE;
             }
             TouchValue('Username', $Data, $User['Name']);
             TouchValue('Email', $Data, $User['Email']);
             TouchValue('IPAddress', $Data, $User['LastIPAddress']);
         }
     }
     if (!isset($Data['Body']) && isset($Data['Story'])) {
         $Data['Body'] = $Data['Story'];
     }
     TouchValue('IPAddress', $Data, Gdn::Request()->IpAddress());
     $Sp = self::_Instance();
     $Sp->EventArguments['RecordType'] = $RecordType;
     $Sp->EventArguments['Data'] =& $Data;
     $Sp->EventArguments['Options'] =& $Options;
     $Sp->EventArguments['IsSpam'] = FALSE;
     $Sp->FireEvent('CheckSpam');
     $Spam = $Sp->EventArguments['IsSpam'];
     // Log the spam entry.
     if ($Spam && GetValue('Log', $Options, TRUE)) {
         $LogOptions = array();
         switch ($RecordType) {
             case 'Registration':
                 $LogOptions['GroupBy'] = array('RecordIPAddress');
                 break;
             case 'Comment':
             case 'Discussion':
             case 'Activity':
             case 'ActivityComment':
                 $LogOptions['GroupBy'] = array('RecordID');
                 break;
         }
         LogModel::Insert('Spam', $RecordType, $Data, $LogOptions);
     }
     return $Spam;
 }
 function SmallImage($Source, $Attributes = array())
 {
     if (function_exists('Debug') && Debug()) {
         trigger_error('SmallImage() is deprecated. Use Thumbnail().', E_USER_DEPRECATED);
     }
     $Width = ArrayValue('width', $Attributes, '');
     $Height = ArrayValue('height', $Attributes, '');
     $ImageQuality = GetValue('ImageQuality', $Attributes, 100, True);
     $Crop = GetValue('Crop', $Attributes, False, True);
     $Hash = Crc32Value($Source, array($Width, $Height, $ImageQuality, $Crop));
     $TargetFolder = 'uploads/cached';
     // cache directory
     if (!is_dir($TargetFolder)) {
         mkdir($TargetFolder, 0777, True);
     }
     $Filename = pathinfo($Source, 8);
     $Extension = pathinfo($Source, 4);
     $SmallImage = GenerateCleanTargetName($TargetFolder, $Filename . '-' . $Hash, $Extension, False, True);
     if (!file_exists($SmallImage)) {
         Gdn_UploadImage::SaveImageAs($Source, $SmallImage, $Height, $Width, $Crop);
     }
     if (GetValue('MakeOnly', $Attributes, False, True)) {
         if (GetValue('OutOriginalImageSize', $Attributes, False, True)) {
             // TEMP, TODO: FIX ME
             $Return = array();
             $Return['ImageSize'] = getimagesize($Source);
             $Return['Result'] = Url($SmallImage);
             return $Return;
         }
         return Url($SmallImage);
     }
     TouchValue('alt', $Attributes, $Filename);
     // Fail. ImageSY expects parameter 1 to be resource
     //if (!array_key_exists('height', $Attributes)) TouchValue('height', $Attributes, ImageSY($SmallImage));
     //if (!array_key_exists('width', $Attributes)) TouchValue('width', $Attributes, ImageSX($SmallImage));
     return Img($SmallImage, $Attributes);
 }
 /**
  * Perform client request to server.
  * Options: see here http://www.php.net/manual/en/function.curl-setopt.php
  * Bool options: 
  * 	ReturnTransfer, Post, FollowLocation, Header
  * Integer options: 
  * 	ConnectTimeout, Timeout, Timeout_Ms
  * Other options: 
  * 	Url, Cookie, CookieFile, CustomRequest, PostFields, Referer, UserAgent, UserPwd
  * 
  * @param mixed $Url or array $Options.
  * @return mixed $Result.
  */
 function ClientRequest($Url, $Options = False)
 {
     static $Connections = array();
     static $ManualFollowLocation;
     $NumArgs = func_num_args();
     if ($NumArgs == 1) {
         $Options = $Url;
         if (is_string($Options)) {
             $Options = array('Url' => $Options);
         }
     } else {
         $Options['Url'] = $Url;
     }
     $NewOptions = $Options;
     $Cache = GetValue('Cache', $Options, False, True);
     if ($Cache !== False) {
         $Crc = sprintf('%u', crc32(serialize($Options)));
         $CacheDirectory = PATH_CACHE . '/client-request';
         $CacheFile = $CacheDirectory . DS . $Crc . '.php';
         if (file_exists($CacheFile)) {
             $IncludeCache = True;
             if (is_int($Cache)) {
                 $LifeTime = time() - filemtime($CacheFile);
                 $Expired = $LifeTime > $Cache;
                 if ($Expired) {
                     $IncludeCache = False;
                 }
             }
             if ($IncludeCache) {
                 $Result = (include $CacheFile);
                 return $Result;
             }
         }
     }
     $Url = GetValue('Url', $Options, False, True);
     $ConvertEncoding = GetValue('ConvertEncoding', $Options, False, True);
     $Header = GetValue('Header', $Options);
     $FollowLocation = GetValue('FollowLocation', $Options);
     if ($FollowLocation) {
         if ($ManualFollowLocation === Null) {
             $ManualFollowLocation = array_filter(array_map('ini_get', array('safe_mode', 'open_basedir'))) > 0;
         }
         if ($ManualFollowLocation) {
             unset($Options['FollowLocation']);
         }
     }
     $GetInfo = GetValue('GetInfo', $Options, False, True);
     TouchValue('ReturnTransfer', $Options, True);
     //TouchValue('ConnectTimeout', $Options, 30);
     //TouchValue('Timeout', $Options, 5);
     if (!array_key_exists($Url, $Connections)) {
         $Connections[$Url] = curl_init($Url);
     }
     $Connection =& $Connections[$Url];
     foreach ($Options as $Option => $Value) {
         $Constant = 'CURLOPT_' . strtoupper($Option);
         if (!defined($Constant)) {
             $InfoConstant = 'CURLINFO_' . strtoupper($Option);
             if (!defined($InfoConstant)) {
                 trigger_error("cURL. Unknown option: {$Constant} ({$InfoConstant})");
             } else {
                 $Constant = $InfoConstant;
             }
         }
         curl_setopt($Connection, constant($Constant), $Value);
     }
     $Result = curl_exec($Connection);
     if ($Result === False) {
         $ErrorMessage = curl_error($Connection);
         //$ErrorNo = curl_errno($Connection);
         trigger_error($ErrorMessage);
         return False;
     }
     if ($Header != False) {
         $ResponseLines = explode("\n", trim($Result));
         $Status = array_shift($ResponseLines);
         $Response = array();
         $Response['HTTP'] = trim($Status);
         $Response['StatusCode'] = array_pop(array_slice(explode(' ', trim($Status)), 1, 1));
         for ($Count = count($ResponseLines), $i = 0; $i < $Count; $i++) {
             $Line = trim($ResponseLines[$i]);
             unset($ResponseLines[$i]);
             if ($Line === '') {
                 break;
             }
             $Line = explode(':', $Line);
             $Key = trim(array_shift($Line));
             $Value = trim(implode(':', $Line));
             if (!isset($Response[$Key])) {
                 $Response[$Key] = $Value;
             } else {
                 if (!is_array($Response[$Key])) {
                     $Response[$Key] = array($Response[$Key]);
                 }
                 $Response[$Key][] = $Value;
             }
         }
         $Result = implode("\n", $ResponseLines);
         unset($ResponseLines);
     }
     if ($GetInfo || $ConvertEncoding || $Header) {
         $Result = array('Result' => $Result);
         $Result['Info'] = curl_getinfo($Connection);
         if ($Header) {
             $Result['Headers'] = $Response;
         }
     }
     if ($FollowLocation != False && $ManualFollowLocation) {
         $Code = GetValueR('Info.http_code', $Result);
         if (in_array($Code, array(301, 302))) {
             $Location = GetValueR('Info.redirect_url', $Result);
             if ($Location === False) {
                 $Location = GetValueR('Headers.Location', $Result);
             }
             $NewOptions['Url'] = $Location;
             return ClientRequest($NewOptions);
         }
     }
     if ($ConvertEncoding) {
         list($MimeType, $DirtyCharsetInfo) = array_pad(explode(';', $Result['Info']['content_type']), 2, Null);
         $Result['MimeType'] = $MimeType;
         preg_match('/charset=(.+)/', $DirtyCharsetInfo, $Match);
         $Charset = strtolower(GetValue(1, $Match));
         if ($Charset && $Charset != 'utf-8') {
             $Result['Result'] = mb_convert_encoding($Result['Result'], 'utf-8', $Charset);
         }
         if (!$GetInfo) {
             $Result = $Result['Result'];
         }
     }
     if (isset($Result['Info']['content_type'])) {
         $Tmp = explode(';', $Result['Info']['content_type']);
         $Type = trim(array_shift($Tmp));
         if (substr($Type, -4) == 'json') {
             $Result['Json'] = json_decode($Result['Result']);
         }
     }
     if ($Cache !== False) {
         if (!is_dir($CacheDirectory)) {
             mkdir($CacheDirectory, 0777, True);
         }
         $Contents = "<?php if (!defined('APPLICATION')) exit(); \nreturn " . var_export($Result, True) . ';';
         file_put_contents($CacheFile, $Contents);
     }
     return $Result;
 }
 function socialSignInButton($Name, $Url, $Type = 'button', $Attributes = array())
 {
     TouchValue('title', $Attributes, sprintf(T('Sign In with %s'), $Name));
     $Title = $Attributes['title'];
     $Class = val('class', $Attributes, '');
     unset($Attributes['class']);
     switch ($Type) {
         case 'icon':
             $Result = Anchor('<span class="Icon"></span>', $Url, 'SocialIcon SocialIcon-' . $Name . ' ' . $Class, $Attributes);
             break;
         case 'button':
         default:
             $Result = Anchor('<span class="Icon"></span><span class="Text">' . $Title . '</span>', $Url, 'SocialIcon SocialIcon-' . $Name . ' HasText ' . $Class, $Attributes);
             break;
     }
     return $Result;
 }
 /**
  * Save message from form submission.
  * 
  * @since 2.0.0
  * @access public
  *
  * @param array $FormPostValues Values submitted via form.
  * @return int Unique ID of message created or updated.
  */
 public function Save($FormPostValues, $Conversation = NULL)
 {
     $Session = Gdn::Session();
     // Define the primary key in this model's table.
     $this->DefineSchema();
     // Add & apply any extra validation rules:
     $this->Validation->ApplyRule('Body', 'Required');
     $this->AddInsertFields($FormPostValues);
     // Validate the form posted values
     $MessageID = FALSE;
     if ($this->Validate($FormPostValues)) {
         $Fields = $this->Validation->SchemaValidationFields();
         // All fields on the form that relate to the schema
         TouchValue('Format', $Fields, C('Garden.InputFormatter', 'Html'));
         $MessageID = $this->SQL->Insert($this->Name, $Fields);
         $this->LastMessageID = $MessageID;
         $ConversationID = ArrayValue('ConversationID', $Fields, 0);
         if (!$Conversation) {
             $Conversation = $this->SQL->GetWhere('Conversation', array('ConversationID' => $ConversationID))->FirstRow(DATASET_TYPE_ARRAY);
         }
         // Get the new message count for the conversation.
         $SQLR = $this->SQL->Select('MessageID', 'count', 'CountMessages')->Select('MessageID', 'max', 'LastMessageID')->From('ConversationMessage')->Where('ConversationID', $ConversationID)->Get()->FirstRow(DATASET_TYPE_ARRAY);
         if (sizeof($SQLR)) {
             list($CountMessages, $LastMessageID) = array_values($SQLR);
         } else {
             return;
         }
         // Update the conversation's DateUpdated field.
         $DateUpdated = Gdn_Format::ToDateTime();
         $this->SQL->Update('Conversation c')->Set('CountMessages', $CountMessages)->Set('LastMessageID', $LastMessageID)->Set('UpdateUserID', Gdn::Session()->UserID)->Set('DateUpdated', $DateUpdated)->Where('ConversationID', $ConversationID)->Put();
         // Update the last message of the users that were previously up-to-date on their read messages.
         $this->SQL->Update('UserConversation uc')->Set('uc.LastMessageID', $MessageID)->Set('uc.DateConversationUpdated', $DateUpdated)->Where('uc.ConversationID', $ConversationID)->Where('uc.Deleted', '0')->Where('uc.CountReadMessages', $CountMessages - 1)->Where('uc.UserID <>', $Session->UserID)->Put();
         // Update the date updated of the users that were not up-to-date.
         $this->SQL->Update('UserConversation uc')->Set('uc.DateConversationUpdated', $DateUpdated)->Where('uc.ConversationID', $ConversationID)->Where('uc.Deleted', '0')->Where('uc.CountReadMessages <>', $CountMessages - 1)->Where('uc.UserID <>', $Session->UserID)->Put();
         // Update the sending user.
         $this->SQL->Update('UserConversation uc')->Set('uc.CountReadMessages', $CountMessages)->Set('Deleted', 0)->Set('uc.DateConversationUpdated', $DateUpdated)->Where('ConversationID', $ConversationID)->Where('UserID', $Session->UserID)->Put();
         // Find users involved in this conversation
         $UserData = $this->SQL->Select('UserID')->Select('LastMessageID')->Select('Deleted')->From('UserConversation')->Where('ConversationID', $ConversationID)->Get()->Result(DATASET_TYPE_ARRAY);
         $UpdateCountUserIDs = array();
         $NotifyUserIDs = array();
         // Collapse for call to UpdateUserCache and ActivityModel.
         $InsertUserFound = FALSE;
         foreach ($UserData as $UpdateUser) {
             $LastMessageID = GetValue('LastMessageID', $UpdateUser);
             $UserID = GetValue('UserID', $UpdateUser);
             $Deleted = GetValue('Deleted', $UpdateUser);
             if ($UserID == GetValue('InsertUserID', $Fields)) {
                 $InsertUserFound = TRUE;
                 if ($Deleted) {
                     $this->SQL->Put('UserConversation', array('Deleted' => 0, 'DateConversationUpdated' => $DateUpdated), array('ConversationID' => $ConversationID, 'UserID' => $UserID));
                 }
             }
             // Update unread for users that were up to date
             if ($LastMessageID == $MessageID) {
                 $UpdateCountUserIDs[] = $UserID;
             }
             // Send activities to users that have not deleted the conversation
             if (!$Deleted) {
                 $NotifyUserIDs[] = $UserID;
             }
         }
         if (!$InsertUserFound) {
             $UserConversation = array('UserID' => GetValue('InsertUserID', $Fields), 'ConversationID' => $ConversationID, 'LastMessageID' => $LastMessageID, 'CountReadMessages' => $CountMessages, 'DateConversationUpdated' => $DateUpdated);
             $this->SQL->Insert('UserConversation', $UserConversation);
         }
         if (sizeof($UpdateCountUserIDs)) {
             $ConversationModel = new ConversationModel();
             $ConversationModel->UpdateUserUnreadCount($UpdateCountUserIDs, TRUE);
         }
         $ActivityModel = new ActivityModel();
         foreach ($NotifyUserIDs as $NotifyUserID) {
             if ($Session->UserID == $NotifyUserID) {
                 continue;
             }
             // don't notify self.
             // Notify the users of the new message.
             $ActivityID = $ActivityModel->Add($Session->UserID, 'ConversationMessage', '', $NotifyUserID, '', "/messages/{$ConversationID}#{$MessageID}", FALSE);
             $Story = GetValue('Body', $Fields, '');
             if (C('Conversations.Subjects.Visible')) {
                 $Story = ConcatSep("\n\n", GetValue('Subject', $Conversation, ''), $Story);
             }
             $ActivityModel->SendNotification($ActivityID, $Story);
         }
     }
     return $MessageID;
 }
 /**
  *
  *
  * @param $Path
  * @param bool $Text
  * @param null $Format
  * @param array $Options
  * @return mixed|null|string
  */
 public static function link($Path, $Text = false, $Format = null, $Options = array())
 {
     $Session = Gdn::session();
     $Class = val('class', $Options, '');
     $WithDomain = val('WithDomain', $Options);
     $Target = val('Target', $Options, '');
     if ($Target == 'current') {
         $Target = trim(url('', true), '/ ');
     }
     if (is_null($Format)) {
         $Format = '<a href="%url" class="%class">%text</a>';
     }
     switch ($Path) {
         case 'activity':
             touchValue('Permissions', $Options, 'Garden.Activity.View');
             break;
         case 'category':
             $Breadcrumbs = Gdn::controller()->data('Breadcrumbs');
             if (is_array($Breadcrumbs) && count($Breadcrumbs) > 0) {
                 $Last = array_pop($Breadcrumbs);
                 $Path = val('Url', $Last);
                 $DefaultText = val('Name', $Last, T('Back'));
             } else {
                 $Path = '/';
                 $DefaultText = c('Garden.Title', T('Back'));
             }
             if (!$Text) {
                 $Text = $DefaultText;
             }
             break;
         case 'dashboard':
             $Path = 'dashboard/settings';
             touchValue('Permissions', $Options, array('Garden.Settings.Manage', 'Garden.Settings.View'));
             if (!$Text) {
                 $Text = t('Dashboard');
             }
             break;
         case 'home':
             $Path = '/';
             if (!$Text) {
                 $Text = t('Home');
             }
             break;
         case 'inbox':
             $Path = 'messages/inbox';
             touchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text) {
                 $Text = t('Inbox');
             }
             if ($Session->isValid() && $Session->User->CountUnreadConversations) {
                 $Class = trim($Class . ' HasCount');
                 $Text .= ' <span class="Alert">' . $Session->User->CountUnreadConversations . '</span>';
             }
             if (!$Session->isValid() || !Gdn::applicationManager()->checkApplication('Conversations')) {
                 $Text = false;
             }
             break;
         case 'forumroot':
             $Route = Gdn::router()->getDestination('DefaultForumRoot');
             if (is_null($Route)) {
                 $Path = '/';
             } else {
                 $Path = combinePaths(array('/', $Route));
             }
             break;
         case 'profile':
             touchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text && $Session->isValid()) {
                 $Text = $Session->User->Name;
             }
             if ($Session->isValid() && $Session->User->CountNotifications) {
                 $Class = trim($Class . ' HasCount');
                 $Text .= ' <span class="Alert">' . $Session->User->CountNotifications . '</span>';
             }
             break;
         case 'user':
             $Path = 'profile';
             touchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text && $Session->isValid()) {
                 $Text = $Session->User->Name;
             }
             break;
         case 'photo':
             $Path = 'profile';
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text && $Session->isValid()) {
                 $IsFullPath = strtolower(substr($Session->User->Photo, 0, 7)) == 'http://' || strtolower(substr($Session->User->Photo, 0, 8)) == 'https://';
                 $PhotoUrl = $IsFullPath ? $Session->User->Photo : Gdn_Upload::url(changeBasename($Session->User->Photo, 'n%s'));
                 $Text = img($PhotoUrl, array('alt' => $Session->User->Name));
             }
             break;
         case 'drafts':
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text) {
                 $Text = t('My Drafts');
             }
             if ($Session->isValid() && $Session->User->CountDrafts) {
                 $Class = trim($Class . ' HasCount');
                 $Text .= ' <span class="Alert">' . $Session->User->CountDrafts . '</span>';
             }
             break;
         case 'discussions/bookmarked':
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text) {
                 $Text = t('My Bookmarks');
             }
             if ($Session->isValid() && $Session->User->CountBookmarks) {
                 $Class = trim($Class . ' HasCount');
                 $Text .= ' <span class="Count">' . $Session->User->CountBookmarks . '</span>';
             }
             break;
         case 'discussions/mine':
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text) {
                 $Text = t('My Discussions');
             }
             if ($Session->isValid() && $Session->User->CountDiscussions) {
                 $Class = trim($Class . ' HasCount');
                 $Text .= ' <span class="Count">' . $Session->User->CountDiscussions . '</span>';
             }
             break;
         case 'register':
             if (!$Text) {
                 $Text = t('Register');
             }
             $Path = registerUrl($Target);
             break;
         case 'signin':
         case 'signinout':
             // The destination is the signin/signout toggle link.
             if ($Session->isValid()) {
                 if (!$Text) {
                     $Text = T('Sign Out');
                 }
                 $Path = signOutUrl($Target);
                 $Class = concatSep(' ', $Class, 'SignOut');
             } else {
                 if (!$Text) {
                     $Text = t('Sign In');
                 }
                 $Path = signInUrl($Target);
                 if (signInPopup() && strpos(Gdn::Request()->Url(), 'entry') === false) {
                     $Class = concatSep(' ', $Class, 'SignInPopup');
                 }
             }
             break;
     }
     if ($Text == false && strpos($Format, '%text') !== false) {
         return '';
     }
     if (val('Permissions', $Options) && !$Session->checkPermission($Options['Permissions'], false)) {
         return '';
     }
     $Url = Gdn::request()->url($Path, $WithDomain);
     if ($TK = val('TK', $Options)) {
         if (in_array($TK, array(1, 'true'))) {
             $TK = 'TransientKey';
         }
         $Url .= (strpos($Url, '?') === false ? '?' : '&') . $TK . '=' . urlencode(Gdn::session()->transientKey());
     }
     if (strcasecmp(trim($Path, '/'), Gdn::request()->path()) == 0) {
         $Class = concatSep(' ', $Class, 'Selected');
     }
     // Build the final result.
     $Result = $Format;
     $Result = str_replace('%url', $Url, $Result);
     $Result = str_replace('%text', $Text, $Result);
     $Result = str_replace('%class', $Class, $Result);
     return $Result;
 }
 function FlashObject($Movie, $Attributes = array(), $FlashVars = False)
 {
     //static $Defaults = array('allowfullscreen' => 'true', 'allowscriptaccess' => 'always', 'quality' => 'best', 'menu' => 'false');
     //$Attributes = array_merge($Defaults, $Attributes);
     $ScriptRender = GetValue('ScriptRender', $Attributes, False, True);
     $FlashVars = GetValue('FlashVars', $Attributes, $FlashVars, True);
     $Params = GetValue('Params', $Attributes, array(), True);
     $Movie = Asset($Movie, True);
     $AltContent = GetValue('AltContent', $Attributes, Anchor(Img('http://wwwimages.adobe.com/www.adobe.com/images/shared/download_buttons/get_flash_player.gif', array('alt' => 'Get Adobe Flash player')), 'http://www.adobe.com/go/getflashplayer', '', array('rel' => 'nofollow'), True), True);
     foreach (array('wmode', 'allowfullscreen', 'allowscriptaccess', 'quality', 'menu') as $Name) {
         $Value = GetValue($Name, $Attributes, False, True);
         if ($Value !== False) {
             $Params[$Name] = $Value;
         }
     }
     if (!array_key_exists('width', $Attributes) || !array_key_exists('height', $Attributes)) {
         $ImageInfo = GetImageSize($Movie);
         TouchValue('width', $Attributes, $ImageInfo[0]);
         TouchValue('height', $Attributes, $ImageInfo[1]);
     }
     $Attributes['type'] = 'application/x-shockwave-flash';
     $Attributes['data'] = $Movie;
     $HtmlParams = Wrap('', 'param', array('name' => 'movie', 'value' => $Movie));
     foreach ($Params as $Name => $Value) {
         $HtmlParams .= Wrap('', 'param', array('name' => $Name, 'value' => $Value));
     }
     if (is_array($FlashVars)) {
         foreach ($FlashVars as $Name => $Value) {
             $Variables[] = $Name . '=' . urlencode($Value);
         }
     }
     if (isset($Variables)) {
         $HtmlParams .= Wrap('', 'param', array('name' => 'flashvars', 'value' => implode('&', $Variables)));
     }
     /*		$Agent = ArrayValue('HTTP_USER_AGENT', $_SERVER);
     		if ($Agent != False && stripos($Agent, 'MSIE ') > 0) {
     			$Attributes['classid'] = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000';
     		}*/
     $Return = Wrap($HtmlParams . $AltContent, 'object', $Attributes);
     //d($Return);
     if ($ScriptRender) {
         $Return = JavaScript($Return, True);
     }
     return $Return;
 }
 /**
  * Undocumented method.
  *
  * @todo Method RenderMaster() needs a description.
  */
 public function RenderMaster()
 {
     // Build the master view if necessary
     if (in_array($this->_DeliveryType, array(DELIVERY_TYPE_ALL))) {
         $this->MasterView = $this->MasterView();
         // Only get css & ui components if this is NOT a syndication request
         if ($this->SyndicationMethod == SYNDICATION_NONE && is_object($this->Head)) {
             //            if (ArrayHasValue($this->_CssFiles, 'style.css')) {
             //               $this->AddCssFile('custom.css');
             //
             //               // Add the theme option's css file.
             //               if ($this->Theme && $this->ThemeOptions) {
             //                  $Filenames = GetValueR('Styles.Value', $this->ThemeOptions);
             //                  if (is_string($Filenames) && $Filenames != '%s')
             //                     $this->_CssFiles[] = array('FileName' => ChangeBasename('custom.css', $Filenames), 'AppFolder' => FALSE, 'Options' => FALSE);
             //               }
             //            } elseif (ArrayHasValue($this->_CssFiles, 'admin.css')) {
             //               $this->AddCssFile('customadmin.css');
             //            }
             $this->EventArguments['CssFiles'] =& $this->_CssFiles;
             $this->FireEvent('BeforeAddCss');
             $ETag = AssetModel::ETag();
             $CombineAssets = C('Garden.CombineAssets');
             $ThemeType = IsMobile() ? 'mobile' : 'desktop';
             // And now search for/add all css files.
             foreach ($this->_CssFiles as $CssInfo) {
                 $CssFile = $CssInfo['FileName'];
                 // style.css and admin.css deserve some custom processing.
                 if (in_array($CssFile, array('style.css', 'admin.css'))) {
                     if (!$CombineAssets) {
                         // Grab all of the css files from the asset model.
                         $AssetModel = new AssetModel();
                         $CssFiles = $AssetModel->GetCssFiles($ThemeType, ucfirst(substr($CssFile, 0, -4)), $ETag);
                         foreach ($CssFiles as $Info) {
                             $this->Head->AddCss($Info[1], 'all', TRUE, $CssInfo);
                         }
                     } else {
                         $Basename = substr($CssFile, 0, -4);
                         $this->Head->AddCss(Url("/utility/css/{$ThemeType}/{$Basename}-{$ETag}.css", '//'), 'all', FALSE, $CssInfo['Options']);
                     }
                     continue;
                 }
                 if (StringBeginsWith($CssFile, 'http')) {
                     $this->Head->AddCss($CssFile, 'all', GetValue('AddVersion', $CssInfo, TRUE), $CssInfo['Options']);
                     continue;
                 } elseif (strpos($CssFile, '/') !== FALSE) {
                     // A direct path to the file was given.
                     $CssPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $CssFile))));
                 } else {
                     //                  $CssGlob = preg_replace('/(.*)(\.css)/', '\1*\2', $CssFile);
                     $AppFolder = $CssInfo['AppFolder'];
                     if ($AppFolder == '') {
                         $AppFolder = $this->ApplicationFolder;
                     }
                     // CSS comes from one of four places:
                     $CssPaths = array();
                     if ($this->Theme) {
                         // Use the default filename.
                         $CssPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'design' . DS . $CssFile;
                     }
                     // 3. Application or plugin.
                     if (StringBeginsWith($AppFolder, 'plugins/')) {
                         // The css is coming from a plugin.
                         $AppFolder = substr($AppFolder, strlen('plugins/'));
                         $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/design/{$CssFile}";
                         $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/{$CssFile}";
                     } elseif (in_array($AppFolder, array('static', 'resources'))) {
                         // This is a static css file.
                         $CssPaths[] = PATH_ROOT . "/resources/css/{$CssFile}";
                     } else {
                         // Application default. eg. root/applications/app_name/design/
                         $CssPaths[] = PATH_APPLICATIONS . DS . $AppFolder . DS . 'design' . DS . $CssFile;
                     }
                     // 4. Garden default. eg. root/applications/dashboard/design/
                     $CssPaths[] = PATH_APPLICATIONS . DS . 'dashboard' . DS . 'design' . DS . $CssFile;
                 }
                 // Find the first file that matches the path.
                 $CssPath = FALSE;
                 foreach ($CssPaths as $Glob) {
                     $Paths = SafeGlob($Glob);
                     if (is_array($Paths) && count($Paths) > 0) {
                         $CssPath = $Paths[0];
                         break;
                     }
                 }
                 // Check to see if there is a CSS cacher.
                 $CssCacher = Gdn::Factory('CssCacher');
                 if (!is_null($CssCacher)) {
                     $CssPath = $CssCacher->Get($CssPath, $AppFolder);
                 }
                 if ($CssPath !== FALSE) {
                     $CssPath = substr($CssPath, strlen(PATH_ROOT));
                     $CssPath = str_replace(DS, '/', $CssPath);
                     $this->Head->AddCss($CssPath, 'all', TRUE, $CssInfo['Options']);
                 }
             }
             // Add a custom js file.
             if (ArrayHasValue($this->_CssFiles, 'style.css')) {
                 $this->AddJsFile('custom.js');
             }
             // only to non-admin pages.
             // And now search for/add all JS files.
             $Cdns = array();
             if (Gdn::Request()->Scheme() != 'https' && !C('Garden.Cdns.Disable', FALSE)) {
                 $Cdns = array('jquery.js' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js');
             }
             $this->EventArguments['Cdns'] =& $Cdns;
             $this->FireEvent('AfterJsCdns');
             foreach ($this->_JsFiles as $Index => $JsInfo) {
                 $JsFile = $JsInfo['FileName'];
                 if (isset($Cdns[$JsFile])) {
                     $JsFile = $Cdns[$JsFile];
                 }
                 if (strpos($JsFile, '//') !== FALSE) {
                     // This is a link to an external file.
                     $this->Head->AddScript($JsFile, 'text/javascript', GetValue('Options', $JsInfo, array()));
                     continue;
                 } elseif (strpos($JsFile, '/') !== FALSE) {
                     // A direct path to the file was given.
                     $JsPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $JsFile)), DS));
                 } else {
                     $AppFolder = $JsInfo['AppFolder'];
                     if ($AppFolder == '') {
                         $AppFolder = $this->ApplicationFolder;
                     }
                     // JS can come from a theme, an any of the application folder, or it can come from the global js folder:
                     $JsPaths = array();
                     if ($this->Theme) {
                         // 1. Application-specific js. eg. root/themes/theme_name/app_name/design/
                         $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . $AppFolder . DS . 'js' . DS . $JsFile;
                         // 2. Garden-wide theme view. eg. root/themes/theme_name/design/
                         $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'js' . DS . $JsFile;
                     }
                     // 3. The application or plugin folder.
                     if (StringBeginsWith(trim($AppFolder, '/'), 'plugins/')) {
                         $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/js/{$JsFile}";
                         $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/{$JsFile}";
                     } else {
                         $JsPaths[] = PATH_APPLICATIONS . "/{$AppFolder}/js/{$JsFile}";
                     }
                     // 4. Global JS folder. eg. root/js/
                     $JsPaths[] = PATH_ROOT . DS . 'js' . DS . $JsFile;
                     // 5. Global JS library folder. eg. root/js/library/
                     $JsPaths[] = PATH_ROOT . DS . 'js' . DS . 'library' . DS . $JsFile;
                 }
                 // Find the first file that matches the path.
                 $JsPath = FALSE;
                 foreach ($JsPaths as $Glob) {
                     $Paths = SafeGlob($Glob);
                     if (is_array($Paths) && count($Paths) > 0) {
                         $JsPath = $Paths[0];
                         break;
                     }
                 }
                 if ($JsPath !== FALSE) {
                     $JsSrc = str_replace(array(PATH_ROOT, DS), array('', '/'), $JsPath);
                     $Options = (array) $JsInfo['Options'];
                     $Options['path'] = $JsPath;
                     $Version = GetValue('Version', $JsInfo);
                     if ($Version) {
                         TouchValue('version', $Options, $Version);
                     }
                     $this->Head->AddScript($JsSrc, 'text/javascript', $Options);
                 }
             }
         }
         // Add the favicon.
         $Favicon = C('Garden.FavIcon');
         if ($Favicon) {
             $this->Head->SetFavIcon(Gdn_Upload::Url($Favicon));
         }
         // Make sure the head module gets passed into the assets collection.
         $this->AddModule('Head');
     }
     // Master views come from one of four places:
     $MasterViewPaths = array();
     $MasterViewPath2 = ViewLocation($this->MasterView() . '.master', '', $this->ApplicationFolder);
     if (strpos($this->MasterView, '/') !== FALSE) {
         $MasterViewPaths[] = CombinePaths(array(PATH_ROOT, str_replace('/', DS, $this->MasterView) . '.master*'));
     } else {
         if ($this->Theme) {
             // 1. Application-specific theme view. eg. root/themes/theme_name/app_name/views/
             $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
             // 2. Garden-wide theme view. eg. /path/to/application/themes/theme_name/views/
             $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, 'views', $this->MasterView . '.master*'));
         }
         // 3. Application default. eg. root/app_name/views/
         $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
         // 4. Garden default. eg. root/dashboard/views/
         $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, 'dashboard', 'views', $this->MasterView . '.master*'));
     }
     // Find the first file that matches the path.
     $MasterViewPath = FALSE;
     foreach ($MasterViewPaths as $Glob) {
         $Paths = SafeGlob($Glob);
         if (is_array($Paths) && count($Paths) > 0) {
             $MasterViewPath = $Paths[0];
             break;
         }
     }
     if ($MasterViewPath != $MasterViewPath2) {
         Trace("Master views differ. Controller: {$MasterViewPath}, ViewLocation(): {$MasterViewPath2}", TRACE_WARNING);
     }
     $this->EventArguments['MasterViewPath'] =& $MasterViewPath;
     $this->FireEvent('BeforeFetchMaster');
     if ($MasterViewPath === FALSE) {
         trigger_error(ErrorMessage("Could not find master view: {$this->MasterView}.master*", $this->ClassName, '_FetchController'), E_USER_ERROR);
     }
     /// A unique identifier that can be used in the body tag of the master view if needed.
     $ControllerName = $this->ClassName;
     // Strip "Controller" from the body identifier.
     if (substr($ControllerName, -10) == 'Controller') {
         $ControllerName = substr($ControllerName, 0, -10);
     }
     // Strip "Gdn_" from the body identifier.
     if (substr($ControllerName, 0, 4) == 'Gdn_') {
         $ControllerName = substr($ControllerName, 4);
     }
     $this->SetData('CssClass', $this->Application . ' ' . $ControllerName . ' ' . $this->RequestMethod . ' ' . $this->CssClass, TRUE);
     // Check to see if there is a handler for this particular extension.
     $ViewHandler = Gdn::Factory('ViewHandler' . strtolower(strrchr($MasterViewPath, '.')));
     if (is_null($ViewHandler)) {
         $BodyIdentifier = strtolower($this->ApplicationFolder . '_' . $ControllerName . '_' . Gdn_Format::AlphaNumeric(strtolower($this->RequestMethod)));
         include $MasterViewPath;
     } else {
         $ViewHandler->Render($MasterViewPath, $this);
     }
 }
   /**
    * Generic save procedure.
    */
   public function Save($FormPostValues, $Settings = FALSE) {
      // See if the user's related roles should be saved or not.
      $SaveRoles = ArrayValue('SaveRoles', $Settings);

      // Define the primary key in this model's table.
      $this->DefineSchema();

      // Add & apply any extra validation rules:
      if (array_key_exists('Email', $FormPostValues))
         $this->Validation->ApplyRule('Email', 'Email');

      // Custom Rule: This will make sure that at least one role was selected if saving roles for this user.
      if ($SaveRoles) {
         $this->Validation->AddRule('OneOrMoreArrayItemRequired', 'function:ValidateOneOrMoreArrayItemRequired');
         // $this->Validation->AddValidationField('RoleID', $FormPostValues);
         $this->Validation->ApplyRule('RoleID', 'OneOrMoreArrayItemRequired');
      }

      // Make sure that the checkbox val for email is saved as the appropriate enum
      if (array_key_exists('ShowEmail', $FormPostValues))
         $FormPostValues['ShowEmail'] = ForceBool($FormPostValues['ShowEmail'], '0', '1', '0');

      // Validate the form posted values
      $UserID = GetValue('UserID', $FormPostValues);
      $Insert = $UserID > 0 ? FALSE : TRUE;
      if ($Insert) {
         $this->AddInsertFields($FormPostValues);
      } else {
         $this->AddUpdateFields($FormPostValues);
      }
      
      $this->EventArguments['FormPostValues'] = $FormPostValues;
      $this->FireEvent('BeforeSaveValidation');

      $RecordRoleChange = TRUE;
      if ($this->Validate($FormPostValues, $Insert) && $this->ValidateUniqueFields(GetValue('Name', $FormPostValues), GetValue('Email', $FormPostValues), $UserID)) {
         $Fields = $this->Validation->ValidationFields(); // All fields on the form that need to be validated (including non-schema field rules defined above)
         $RoleIDs = GetValue('RoleID', $Fields, 0);
         $Username = GetValue('Name', $Fields);
         $Email = GetValue('Email', $Fields);
         $Fields = $this->Validation->SchemaValidationFields(); // Only fields that are present in the schema
         // Remove the primary key from the fields collection before saving
         $Fields = RemoveKeyFromArray($Fields, $this->PrimaryKey);
         
         if (!$Insert && array_key_exists('Password', $Fields)) {
            // Encrypt the password for saving only if it won't be hashed in _Insert()
            $PasswordHash = new Gdn_PasswordHash();
            $Fields['Password'] = $PasswordHash->HashPassword($Fields['Password']);
            $Fields['HashMethod'] = 'Vanilla';
         }
         
         // Check for email confirmation.
         if (C('Garden.Registration.ConfirmEmail') && !GetValue('NoConfirmEmail', $Settings)) {
            if (isset($Fields['Email']) && $UserID == Gdn::Session()->UserID && $Fields['Email'] != Gdn::Session()->User->Email && !Gdn::Session()->CheckPermission('Garden.Users.Edit')) {
               $User = Gdn::Session()->User;
               $Attributes = Gdn::Session()->User->Attributes;
               $EmailKey = TouchValue('EmailKey', $Attributes, RandomString(8));

               if ($RoleIDs)
                  $ConfirmedEmailRoles = $RoleIDs;
               else
                  $ConfirmedEmailRoles = ConsolidateArrayValuesByKey($this->GetRoles($UserID), 'RoleID');
               $Attributes['ConfirmedEmailRoles'] = $ConfirmedEmailRoles;

               $RoleIDs = (array)C('Garden.Registration.ConfirmEmailRole');
               $SaveRoles = TRUE;
               $Fields['Attributes'] = serialize($Attributes);
            } 
         }
         
         $this->EventArguments['Fields'] = $Fields;
         $this->FireEvent('BeforeSave');
         
         // Check the validation results again in case something was added during the BeforeSave event.
         if (count($this->Validation->Results()) == 0) {
            // If the primary key exists in the validated fields and it is a
            // numeric value greater than zero, update the related database row.
            if ($UserID > 0) {
               // If they are changing the username & email, make sure they aren't
               // already being used (by someone other than this user)
               if (ArrayValue('Name', $Fields, '') != '' || ArrayValue('Email', $Fields, '') != '') {
                  if (!$this->ValidateUniqueFields($Username, $Email, $UserID))
                     return FALSE;
               }
   
               $this->SQL->Put($this->Name, $Fields, array($this->PrimaryKey => $UserID));
   
               // Record activity if the person changed his/her photo.
               $Photo = ArrayValue('Photo', $FormPostValues);
               if ($Photo !== FALSE) {
                  if (GetValue('CheckExisting', $Settings)) {
                     $User = $this->Get($UserID);
                     $OldPhoto = GetValue('Photo', $User);
                  }

                  if (!isset($OldPhoto) || $Photo != $Photo) {
                     if (strpos($Photo, '//'))
                        $PhotoUrl = $Photo;
                     else
                        $PhotoUrl = Gdn_Upload::Url(ChangeBasename($Photo, 't%s'));

                     AddActivity($UserID, 'PictureChange', Img($PhotoUrl, array('alt' => T('Thumbnail'))));
                  }
               }
   
            } else {
               $RecordRoleChange = FALSE;
               if (!$this->ValidateUniqueFields($Username, $Email))
                  return FALSE;
   
               // Define the other required fields:
               $Fields['Email'] = $Email;
   
               // And insert the new user
               $UserID = $this->_Insert($Fields);
   
               // Make sure that the user is assigned to one or more roles:
               $SaveRoles = TRUE;
   
               // Report that the user was created
               $Session = Gdn::Session();
               AddActivity(
                  $UserID,
                  GetValue('ActivityType', $Settings, 'JoinCreated'),
                  T('Welcome Aboard!'),
                  $Session->UserID > 0 ? $Session->UserID : ''
               );
            }
            // Now update the role settings if necessary.
            if ($SaveRoles) {
               // If no RoleIDs were provided, use the system defaults
               if (!is_array($RoleIDs))
                  $RoleIDs = Gdn::Config('Garden.Registration.DefaultRoles');
   
               $this->SaveRoles($UserID, $RoleIDs, $RecordRoleChange);
            }

            // Send the confirmation email.
            if (isset($EmailKey)) {
               $this->SendEmailConfirmationEmail((array)Gdn::Session()->User);
            }

            $this->EventArguments['UserID'] = $UserID;
            $this->FireEvent('AfterSave');
         } else {
            $UserID = FALSE;
         }
      } else {
         $UserID = FALSE;
      }
      return $UserID;
   }
   public static function Link($Path, $Text = FALSE, $Format = '<a href="%url" class="%class">%text</a>', $Options = array()) {
      $Session = Gdn::Session();
      $Class = GetValue('class', $Options, '');
      $WithDomain = GetValue('WithDomain', $Options);
      $Target = GetValue('Target', $Options, '');

      switch ($Path) {
         case 'activity':
            TouchValue('Permissions', $Options, 'Garden.Activity.View');
            break;
         case 'dashboard':
            $Path = 'dashboard/settings';
            TouchValue('Permissions', $Options, 'Garden.Settings.Manage');
            if (!$Text)
               $Text = T('Dashboard');
            break;
         case 'inbox':
            $Path = 'messages/inbox';
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text)
               $Text = T('Inbox');
            if ($Session->IsValid() && $Session->User->CountUnreadConversations) {
               $Class = trim($Class.' HasCount');
               $Text .= ' <span class="Alert">'.$Session->User->CountUnreadConversations.'</span>';
            }
            break;
         case 'profile':
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text && $Session->IsValid())
               $Text = $Session->User->Name;
            if ($Session->IsValid() && $Session->User->CountNotifications) {
               $Class = trim($Class.' HasCount');
               $Text .= ' <span class="Alert">'.$Session->User->CountNotifications.'</span>';
            }
            break;
         case 'user':
            $Path = 'profile';
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text && $Session->IsValid())
               $Text = $Session->User->Name;

            break;
         case 'photo':
            $Path = 'profile';
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text && $Session->IsValid()) {
               $IsFullPath = strtolower(substr($Session->User->Photo, 0, 7)) == 'http://' || strtolower(substr($Session->User->Photo, 0, 8)) == 'https://';
               $PhotoUrl = ($IsFullPath) ? $Session->User->Photo : Gdn_Upload::Url(ChangeBasename($Session->User->Photo, 'n%s'));
               $Text = Img($PhotoUrl, array('alt' => htmlspecialchars($Session->User->Name)));
            }

            break;
         case 'drafts':
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text)
               $Text = T('My Drafts');
            if ($Session->IsValid() && $Session->User->CountDrafts) {
               $Class = trim($Class.' HasCount');
               $Text .= ' <span class="Alert">'.$Session->User->CountDrafts.'</span>';
            }
            break;
         case 'discussions/bookmarked':
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text)
               $Text = T('My Bookmarks');
            if ($Session->IsValid() && $Session->User->CountBookmarks) {
               $Class = trim($Class.' HasCount');
               $Text .= ' <span class="Count">'.$Session->User->CountBookmarks.'</span>';
            }
            break;
         case 'discussions/mine':
            TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
            if (!$Text)
               $Text = T('My Discussions');
            if ($Session->IsValid() && $Session->User->CountDiscussions) {
               $Class = trim($Class.' HasCount');
               $Text .= ' <span class="Count">'.$Session->User->CountDiscussions.'</span>';
            }
            break;
         case 'signin':
         case 'signinout':
            // The destination is the signin/signout toggle link.
            if ($Session->IsValid()) {
               if(!$Text)
                  $Text = T('Sign Out');
               $Path =  SignOutUrl($Target);
               $Class = ConcatSep(' ', $Class, 'SignOut');
            } else {
               if(!$Text)
                  $Text = T('Sign In');
               $Attribs = array();

               $Path = SignInUrl($Target);
               if (SignInPopup() && strpos(Gdn::Request()->Url(), 'entry') === FALSE)
                  $Class = ConcatSep(' ', $Class, 'SignInPopup');
            }
            break;
      }

      if (GetValue('Permissions', $Options) && !$Session->CheckPermission($Options['Permissions']))
         return '';

      $Url = Gdn::Request()->Url($Path, $WithDomain);

      if (strcasecmp(trim($Path, '/'), Gdn::Request()->Path()) == 0)
         $Class = ConcatSep(' ', $Class, 'Selected');

      // Build the final result.
      $Result = $Format;
      $Result = str_replace('%url', $Url, $Result);
      $Result = str_replace('%text', $Text, $Result);
      $Result = str_replace('%class', $Class, $Result);

      return $Result;
   }
Exemple #13
0
 public static function JoinRecentPosts(&$Data)
 {
     $DiscussionIDs = array();
     $CommentIDs = array();
     $Joined = FALSE;
     foreach ($Data as &$Row) {
         if (isset($Row['LastTitle']) && $Row['LastTitle']) {
             continue;
         }
         if ($Row['LastDiscussionID']) {
             $DiscussionIDs[] = $Row['LastDiscussionID'];
         }
         if ($Row['LastCommentID']) {
             $CommentIDs[] = $Row['LastCommentID'];
         }
         $Joined = TRUE;
     }
     // Grab the discussions.
     if (count($DiscussionIDs) > 0) {
         $Discussions = Gdn::SQL()->WhereIn('DiscussionID', $DiscussionIDs)->Get('Discussion')->ResultArray();
         $Discussions = Gdn_DataSet::Index($Discussions, array('DiscussionID'));
     }
     if (count($CommentIDs) > 0) {
         $Comments = Gdn::SQL()->WhereIn('CommentID', $CommentIDs)->Get('Comment')->ResultArray();
         $Comments = Gdn_DataSet::Index($Comments, array('CommentID'));
     }
     foreach ($Data as &$Row) {
         $Discussion = GetValue($Row['LastDiscussionID'], $Discussions);
         if ($Discussion) {
             $Row['LastTitle'] = Gdn_Format::Text($Discussion['Name']);
             $Row['LastUserID'] = $Discussion['InsertUserID'];
             $Row['LastDateInserted'] = $Discussion['DateInserted'];
             $Row['LastUrl'] = "/discussion/{$Discussion['DiscussionID']}/" . Gdn_Format::Text($Discussion['Name']);
         }
         $Comment = GetValue($Row['LastCommentID'], $Comments);
         if ($Comment) {
             $Row['LastUserID'] = $Comment['InsertUserID'];
             $Row['LastDateInserted'] = $Comment['DateInserted'];
             $Row['LastUrl'] = "/discussion/comment/{$Comment['CommentID']}#Comment_{$Comment['CommentID']}";
         } else {
             $Row['NoComment'] = TRUE;
         }
         TouchValue('LastTitle', $Row, '');
         TouchValue('LastUserID', $Row, NULL);
         TouchValue('LastDateInserted', $Row, NULL);
         TouchValue('LastUrl', $Row, NULL);
     }
     return $Joined;
 }
 public function AddInsertFields(&$Fields)
 {
     $this->DefineSchema();
     // Set the hour offset based on the client's clock.
     $ClientHour = ArrayValue('ClientHour', $Fields, '');
     if (is_numeric($ClientHour) && $ClientHour >= 0 && $ClientHour < 24) {
         $HourOffset = $ClientHour - date('G', time());
         $Fields['HourOffset'] = $HourOffset;
     }
     // Set some required dates.
     $Now = Gdn_Format::ToDateTime();
     $Fields[$this->DateInserted] = $Now;
     TouchValue('DateFirstVisit', $Fields, $Now);
     $Fields['DateLastActive'] = $Now;
     $Fields['InsertIPAddress'] = Gdn::Request()->IpAddress();
     $Fields['LastIPAddress'] = Gdn::Request()->IpAddress();
 }
Exemple #15
0
 /**
  * Generic save procedure.
  */
 public function Save($FormPostValues, $Settings = FALSE)
 {
     // See if the user's related roles should be saved or not.
     $SaveRoles = GetValue('SaveRoles', $Settings);
     // Define the primary key in this model's table.
     $this->DefineSchema();
     // Custom Rule: This will make sure that at least one role was selected if saving roles for this user.
     if ($SaveRoles) {
         $this->Validation->AddRule('OneOrMoreArrayItemRequired', 'function:ValidateOneOrMoreArrayItemRequired');
         // $this->Validation->AddValidationField('RoleID', $FormPostValues);
         $this->Validation->ApplyRule('RoleID', 'OneOrMoreArrayItemRequired');
     }
     // Make sure that checkbox vals are saved as the appropriate value
     if (array_key_exists('ShowEmail', $FormPostValues)) {
         $FormPostValues['ShowEmail'] = ForceBool($FormPostValues['ShowEmail'], '0', '1', '0');
     }
     if (array_key_exists('Banned', $FormPostValues)) {
         $FormPostValues['Banned'] = ForceBool($FormPostValues['Banned'], '0', '1', '0');
     }
     if (array_key_exists('Confirmed', $FormPostValues)) {
         $FormPostValues['Confirmed'] = ForceBool($FormPostValues['Confirmed'], '0', '1', '0');
     }
     // Validate the form posted values
     $UserID = GetValue('UserID', $FormPostValues);
     $User = array();
     $Insert = $UserID > 0 ? FALSE : TRUE;
     if ($Insert) {
         $this->AddInsertFields($FormPostValues);
     } else {
         $this->AddUpdateFields($FormPostValues);
         $User = $this->GetID($UserID, DATASET_TYPE_ARRAY);
         // Block banning the superadmin or System accounts
         if (GetValue('Admin', $User) == 2 && GetValue('Banned', $FormPostValues)) {
             $this->Validation->AddValidationResult('Banned', 'You may not ban a System user.');
         } elseif (GetValue('Admin', $User) && GetValue('Banned', $FormPostValues)) {
             $this->Validation->AddValidationResult('Banned', 'You may not ban a user with the Admin flag set.');
         }
     }
     $this->EventArguments['FormPostValues'] = $FormPostValues;
     $this->FireEvent('BeforeSaveValidation');
     $RecordRoleChange = TRUE;
     if ($UserID && GetValue('FixUnique', $Settings)) {
         $UniqueValid = $this->ValidateUniqueFields(GetValue('Name', $FormPostValues), GetValue('Email', $FormPostValues), $UserID, TRUE);
         if (!$UniqueValid['Name']) {
             unset($FormPostValues['Name']);
         }
         if (!$UniqueValid['Email']) {
             unset($FormPostValues['Email']);
         }
         $UniqueValid = TRUE;
     } else {
         $UniqueValid = $this->ValidateUniqueFields(GetValue('Name', $FormPostValues), GetValue('Email', $FormPostValues), $UserID);
     }
     // Add & apply any extra validation rules:
     if (array_key_exists('Email', $FormPostValues) && GetValue('ValidateEmail', $Settings, TRUE)) {
         $this->Validation->ApplyRule('Email', 'Email');
     }
     if ($this->Validate($FormPostValues, $Insert) && $UniqueValid) {
         $Fields = $this->Validation->ValidationFields();
         // All fields on the form that need to be validated (including non-schema field rules defined above)
         $RoleIDs = GetValue('RoleID', $Fields, 0);
         $Username = GetValue('Name', $Fields);
         $Email = GetValue('Email', $Fields);
         $Fields = $this->Validation->SchemaValidationFields();
         // Only fields that are present in the schema
         // Remove the primary key from the fields collection before saving
         $Fields = RemoveKeyFromArray($Fields, $this->PrimaryKey);
         if (in_array('AllIPAddresses', $Fields) && is_array($Fields['AllIPAddresses'])) {
             $Fields['AllIPAddresses'] = implode(',', $Fields['AllIPAddresses']);
         }
         if (!$Insert && array_key_exists('Password', $Fields)) {
             // Encrypt the password for saving only if it won't be hashed in _Insert()
             $PasswordHash = new Gdn_PasswordHash();
             $Fields['Password'] = $PasswordHash->HashPassword($Fields['Password']);
             $Fields['HashMethod'] = 'Vanilla';
         }
         // Check for email confirmation.
         if (self::RequireConfirmEmail() && !GetValue('NoConfirmEmail', $Settings)) {
             // Email address has changed
             if (isset($Fields['Email']) && (array_key_exists('Confirmed', $Fields) && $Fields['Confirmed'] == 0 || $UserID == Gdn::Session()->UserID && $Fields['Email'] != Gdn::Session()->User->Email && !Gdn::Session()->CheckPermission('Garden.Users.Edit'))) {
                 $Attributes = GetValue('Attributes', Gdn::Session()->User);
                 if (is_string($Attributes)) {
                     $Attributes = @unserialize($Attributes);
                 }
                 $ConfirmEmailRoleID = C('Garden.Registration.ConfirmEmailRole');
                 if (RoleModel::Roles($ConfirmEmailRoleID)) {
                     // The confirm email role is set and it exists so go ahead with the email confirmation.
                     $NewKey = RandomString(8);
                     $EmailKey = TouchValue('EmailKey', $Attributes, $NewKey);
                     $Fields['Attributes'] = serialize($Attributes);
                     $Fields['Confirmed'] = 0;
                 }
             }
         }
         $this->EventArguments['SaveRoles'] =& $SaveRoles;
         $this->EventArguments['RoleIDs'] =& $RoleIDs;
         $this->EventArguments['Fields'] =& $Fields;
         $this->FireEvent('BeforeSave');
         $User = array_merge($User, $Fields);
         // Check the validation results again in case something was added during the BeforeSave event.
         if (count($this->Validation->Results()) == 0) {
             // If the primary key exists in the validated fields and it is a
             // numeric value greater than zero, update the related database row.
             if ($UserID > 0) {
                 // If they are changing the username & email, make sure they aren't
                 // already being used (by someone other than this user)
                 if (ArrayValue('Name', $Fields, '') != '' || ArrayValue('Email', $Fields, '') != '') {
                     if (!$this->ValidateUniqueFields($Username, $Email, $UserID)) {
                         return FALSE;
                     }
                 }
                 if (array_key_exists('Attributes', $Fields) && !is_string($Fields['Attributes'])) {
                     $Fields['Attributes'] = serialize($Fields['Attributes']);
                 }
                 // Perform save DB operation
                 $this->SQL->Put($this->Name, $Fields, array($this->PrimaryKey => $UserID));
                 // Record activity if the person changed his/her photo.
                 $Photo = ArrayValue('Photo', $FormPostValues);
                 if ($Photo !== FALSE) {
                     if (GetValue('CheckExisting', $Settings)) {
                         $User = $this->GetID($UserID);
                         $OldPhoto = GetValue('Photo', $User);
                     }
                     if (isset($OldPhoto) && $OldPhoto != $Photo) {
                         if (strpos($Photo, '//')) {
                             $PhotoUrl = $Photo;
                         } else {
                             $PhotoUrl = Gdn_Upload::Url(ChangeBasename($Photo, 'n%s'));
                         }
                         $ActivityModel = new ActivityModel();
                         if ($UserID == Gdn::Session()->UserID) {
                             $HeadlineFormat = T('HeadlineFormat.PictureChange', '{RegardingUserID,You} changed {ActivityUserID,your} profile picture.');
                         } else {
                             $HeadlineFormat = T('HeadlineFormat.PictureChange.ForUser', '{RegardingUserID,You} changed the profile picture for {ActivityUserID,user}.');
                         }
                         $ActivityModel->Save(array('ActivityUserID' => $UserID, 'RegardingUserID' => Gdn::Session()->UserID, 'ActivityType' => 'PictureChange', 'HeadlineFormat' => $HeadlineFormat, 'Story' => Img($PhotoUrl, array('alt' => T('Thumbnail')))));
                     }
                 }
             } else {
                 $RecordRoleChange = FALSE;
                 if (!$this->ValidateUniqueFields($Username, $Email)) {
                     return FALSE;
                 }
                 // Define the other required fields:
                 $Fields['Email'] = $Email;
                 $Fields['Roles'] = $RoleIDs;
                 // Make sure that the user is assigned to one or more roles:
                 $SaveRoles = FALSE;
                 // And insert the new user.
                 $UserID = $this->_Insert($Fields, $Settings);
                 if ($UserID) {
                     // Report that the user was created.
                     $ActivityModel = new ActivityModel();
                     $ActivityModel->Save(array('ActivityType' => 'Registration', 'ActivityUserID' => $UserID, 'HeadlineFormat' => T('HeadlineFormat.Registration', '{ActivityUserID,You} joined.'), 'Story' => T('Welcome Aboard!')), FALSE, array('GroupBy' => 'ActivityTypeID'));
                     // Report the creation for mods.
                     $ActivityModel->Save(array('ActivityType' => 'Registration', 'ActivityUserID' => Gdn::Session()->UserID, 'RegardingUserID' => $UserID, 'NotifyUserID' => ActivityModel::NOTIFY_MODS, 'HeadlineFormat' => T('HeadlineFormat.AddUser', '{ActivityUserID,user} added an account for {RegardingUserID,user}.')));
                 }
             }
             // Now update the role settings if necessary.
             if ($SaveRoles) {
                 // If no RoleIDs were provided, use the system defaults
                 if (!is_array($RoleIDs)) {
                     $RoleIDs = Gdn::Config('Garden.Registration.DefaultRoles');
                 }
                 $this->SaveRoles($UserID, $RoleIDs, $RecordRoleChange);
             }
             // Send the confirmation email.
             if (isset($EmailKey)) {
                 if (!is_array($User)) {
                     $User = $this->GetID($UserID, DATASET_TYPE_ARRAY);
                 }
                 $this->SendEmailConfirmationEmail($User, true);
             }
             $this->EventArguments['UserID'] = $UserID;
             $this->FireEvent('AfterSave');
         } else {
             $UserID = FALSE;
         }
     } else {
         $UserID = FALSE;
     }
     // Clear cached user data
     if (!$Insert && $UserID) {
         $this->ClearCache($UserID, array('user'));
     }
     return $UserID;
 }
 /**
  * Lists the connections to other sites.
  *
  * @param int|string $UserReference
  * @param string $Username
  * @since 2.1
  */
 public function Connections($UserReference = '', $Username = '')
 {
     $this->Permission('Garden.SignIn.Allow');
     $this->GetUserInfo($UserReference, $Username, '', TRUE);
     $UserID = GetValueR('User.UserID', $this);
     $this->_SetBreadcrumbs(T('Social'), UserUrl($this->User, '', 'connections'));
     $PModel = new Gdn_AuthenticationProviderModel();
     $Providers = $PModel->GetProviders();
     $this->SetData('_Providers', $Providers);
     $this->SetData('Connections', array());
     $this->EventArguments['User'] = $this->User;
     $this->FireEvent('GetConnections');
     // Add some connection information.
     foreach ($this->Data['Connections'] as &$Row) {
         $Provider = GetValue($Row['ProviderKey'], $Providers, array());
         TouchValue('Connected', $Row, !is_null(GetValue('UniqueID', $Provider, NULL)));
     }
     $this->CanonicalUrl(UserUrl($this->User, '', 'connections'));
     $this->Title(T('Social'));
     require_once $this->FetchViewLocation('connection_functions');
     $this->Render();
 }
 /**
  * Create or update a discussion.
  *
  * @since 2.0.0
  * @access public
  *
  * @param int $CategoryID Unique ID of the category to add the discussion to.
  */
 public function Discussion($CategoryUrlCode = '')
 {
     // Override CategoryID if categories are disabled
     $UseCategories = $this->ShowCategorySelector = (bool) C('Vanilla.Categories.Use');
     if (!$UseCategories) {
         $CategoryUrlCode = '';
     }
     // Setup head
     $this->AddJsFile('jquery.autosize.min.js');
     $this->AddJsFile('post.js');
     $this->AddJsFile('autosave.js');
     $Session = Gdn::Session();
     Gdn_Theme::Section('PostDiscussion');
     // Set discussion, draft, and category data
     $DiscussionID = isset($this->Discussion) ? $this->Discussion->DiscussionID : '';
     $DraftID = isset($this->Draft) ? $this->Draft->DraftID : 0;
     $Category = FALSE;
     if (isset($this->Discussion)) {
         $this->CategoryID = $this->Discussion->CategoryID;
         $Category = CategoryModel::Categories($this->CategoryID);
     } else {
         if ($CategoryUrlCode != '') {
             $CategoryModel = new CategoryModel();
             $Category = $CategoryModel->GetByCode($CategoryUrlCode);
             $this->CategoryID = $Category->CategoryID;
         }
     }
     if ($Category) {
         $this->Category = (object) $Category;
         $this->SetData('Category', $Category);
     } else {
         $this->CategoryID = 0;
         $this->Category = NULL;
     }
     $CategoryData = $UseCategories ? CategoryModel::Categories() : FALSE;
     // Check permission
     if (isset($this->Discussion)) {
         // Permission to edit
         if ($this->Discussion->InsertUserID != $Session->UserID) {
             $this->Permission('Vanilla.Discussions.Edit', TRUE, 'Category', $this->Category->PermissionCategoryID);
         }
         // Make sure that content can (still) be edited.
         $EditContentTimeout = C('Garden.EditContentTimeout', -1);
         $CanEdit = $EditContentTimeout == -1 || strtotime($this->Discussion->DateInserted) + $EditContentTimeout > time();
         if (!$CanEdit) {
             $this->Permission('Vanilla.Discussions.Edit', TRUE, 'Category', $this->Category->PermissionCategoryID);
         }
         // Make sure only moderators can edit closed things
         if ($this->Discussion->Closed) {
             $this->Permission('Vanilla.Discussions.Edit', TRUE, 'Category', $this->Category->PermissionCategoryID);
         }
         $this->Form->SetFormValue('DiscussionID', $this->Discussion->DiscussionID);
         $this->Title(T('Edit Discussion'));
         if ($this->Discussion->Type) {
             $this->SetData('Type', $this->Discussion->Type);
         } else {
             $this->SetData('Type', 'Discussion');
         }
     } else {
         // Permission to add
         $this->Permission('Vanilla.Discussions.Add');
         $this->Title(T('New Discussion'));
     }
     TouchValue('Type', $this->Data, 'Discussion');
     // See if we should hide the category dropdown.
     $AllowedCategories = CategoryModel::GetByPermission('Discussions.Add', $this->Form->GetValue('CategoryID', $this->CategoryID), array('Archived' => 0, 'AllowDiscussions' => 1), array('AllowedDiscussionTypes' => $this->Data['Type']));
     if (count($AllowedCategories) == 1) {
         $AllowedCategory = array_pop($AllowedCategories);
         $this->ShowCategorySelector = FALSE;
         $this->Form->AddHidden('CategoryID', $AllowedCategory['CategoryID']);
         if ($this->Form->IsPostBack() && !$this->Form->GetFormValue('CategoryID')) {
             $this->Form->SetFormValue('CategoryID', $AllowedCategory['CategoryID']);
         }
     }
     // Set the model on the form
     $this->Form->SetModel($this->DiscussionModel);
     if ($this->Form->IsPostBack() == FALSE) {
         // Prep form with current data for editing
         if (isset($this->Discussion)) {
             $this->Form->SetData($this->Discussion);
         } elseif (isset($this->Draft)) {
             $this->Form->SetData($this->Draft);
         } else {
             if ($this->Category !== NULL) {
                 $this->Form->SetData(array('CategoryID' => $this->Category->CategoryID));
             }
             $this->PopulateForm($this->Form);
         }
     } else {
         // Form was submitted
         // Save as a draft?
         $FormValues = $this->Form->FormValues();
         $FormValues = $this->DiscussionModel->FilterForm($FormValues);
         $this->DeliveryType(GetIncomingValue('DeliveryType', $this->_DeliveryType));
         if ($DraftID == 0) {
             $DraftID = $this->Form->GetFormValue('DraftID', 0);
         }
         $Draft = $this->Form->ButtonExists('Save Draft') ? TRUE : FALSE;
         $Preview = $this->Form->ButtonExists('Preview') ? TRUE : FALSE;
         if (!$Preview) {
             if (!is_object($this->Category) && is_array($CategoryData) && isset($FormValues['CategoryID'])) {
                 $this->Category = GetValue($FormValues['CategoryID'], $CategoryData);
             }
             if (is_object($this->Category)) {
                 // Check category permissions.
                 if ($this->Form->GetFormValue('Announce', '') && !$Session->CheckPermission('Vanilla.Discussions.Announce', TRUE, 'Category', $this->Category->PermissionCategoryID)) {
                     $this->Form->AddError('You do not have permission to announce in this category', 'Announce');
                 }
                 if ($this->Form->GetFormValue('Close', '') && !$Session->CheckPermission('Vanilla.Discussions.Close', TRUE, 'Category', $this->Category->PermissionCategoryID)) {
                     $this->Form->AddError('You do not have permission to close in this category', 'Close');
                 }
                 if ($this->Form->GetFormValue('Sink', '') && !$Session->CheckPermission('Vanilla.Discussions.Sink', TRUE, 'Category', $this->Category->PermissionCategoryID)) {
                     $this->Form->AddError('You do not have permission to sink in this category', 'Sink');
                 }
                 if (!isset($this->Discussion) && (!$Session->CheckPermission('Vanilla.Discussions.Add', TRUE, 'Category', $this->Category->PermissionCategoryID) || !$this->Category->AllowDiscussions)) {
                     $this->Form->AddError('You do not have permission to start discussions in this category', 'CategoryID');
                 }
             }
             // Make sure that the title will not be invisible after rendering
             $Name = trim($this->Form->GetFormValue('Name', ''));
             if ($Name != '' && Gdn_Format::Text($Name) == '') {
                 $this->Form->AddError(T('You have entered an invalid discussion title'), 'Name');
             } else {
                 // Trim the name.
                 $FormValues['Name'] = $Name;
                 $this->Form->SetFormValue('Name', $Name);
             }
             if ($this->Form->ErrorCount() == 0) {
                 if ($Draft) {
                     $DraftID = $this->DraftModel->Save($FormValues);
                     $this->Form->SetValidationResults($this->DraftModel->ValidationResults());
                 } else {
                     $DiscussionID = $this->DiscussionModel->Save($FormValues, $this->CommentModel);
                     $this->Form->SetValidationResults($this->DiscussionModel->ValidationResults());
                     if ($DiscussionID > 0) {
                         if ($DraftID > 0) {
                             $this->DraftModel->Delete($DraftID);
                         }
                     }
                     if ($DiscussionID == SPAM || $DiscussionID == UNAPPROVED) {
                         $this->StatusMessage = T('DiscussionRequiresApprovalStatus', 'Your discussion will appear after it is approved.');
                         $this->Render('Spam');
                         return;
                     }
                 }
             }
         } else {
             // If this was a preview click, create a discussion/comment shell with the values for this comment
             $this->Discussion = new stdClass();
             $this->Discussion->Name = $this->Form->GetValue('Name', '');
             $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->Comment->Format = GetValue('Format', $FormValues, C('Garden.InputFormatter'));
             $this->EventArguments['Discussion'] =& $this->Discussion;
             $this->EventArguments['Comment'] =& $this->Comment;
             $this->FireEvent('BeforeDiscussionPreview');
             if ($this->_DeliveryType == DELIVERY_TYPE_ALL) {
                 $this->AddAsset('Content', $this->FetchView('preview'));
             } else {
                 $this->View = 'preview';
             }
         }
         if ($this->Form->ErrorCount() > 0) {
             // Return the form errors
             $this->ErrorMessage($this->Form->Errors());
         } else {
             if ($DiscussionID > 0 || $DraftID > 0) {
                 // Make sure that the ajax request form knows about the newly created discussion or draft id
                 $this->SetJson('DiscussionID', $DiscussionID);
                 $this->SetJson('DraftID', $DraftID);
                 if (!$Preview) {
                     // If the discussion was not a draft
                     if (!$Draft) {
                         // Redirect to the new discussion
                         $Discussion = $this->DiscussionModel->GetID($DiscussionID, DATASET_TYPE_OBJECT, array('Slave' => FALSE));
                         $this->SetData('Discussion', $Discussion);
                         $this->EventArguments['Discussion'] = $Discussion;
                         $this->FireEvent('AfterDiscussionSave');
                         if ($this->_DeliveryType == DELIVERY_TYPE_ALL) {
                             Redirect(DiscussionUrl($Discussion)) . '?new=1';
                         } else {
                             $this->RedirectUrl = DiscussionUrl($Discussion, '', TRUE) . '?new=1';
                         }
                     } else {
                         // If this was a draft save, notify the user about the save
                         $this->InformMessage(sprintf(T('Draft saved at %s'), Gdn_Format::Date()));
                     }
                 }
             }
         }
     }
     // Add hidden fields for editing
     $this->Form->AddHidden('DiscussionID', $DiscussionID);
     $this->Form->AddHidden('DraftID', $DraftID, TRUE);
     $this->FireEvent('BeforeDiscussionRender');
     if ($this->CategoryID) {
         $Breadcrumbs = CategoryModel::GetAncestors($this->CategoryID);
     } else {
         $Breadcrumbs = array();
     }
     $Breadcrumbs[] = array('Name' => $this->Data('Title'), 'Url' => '/post/discussion');
     $this->SetData('Breadcrumbs', $Breadcrumbs);
     $this->SetData('_AnnounceOptions', $this->AnnounceOptions());
     // Render view (posts/discussion.php or post/preview.php)
     $this->Render();
 }
 function FancyZoomImage($Source, $Attributes = array())
 {
     // defaults
     if (!is_array($Attributes)) {
         $Attributes = array();
     }
     $NoHiding = GetValue('NoHiding', $Attributes, '', True);
     $bSaveImage = False;
     $Hash = Crc32Value($Source, $Attributes);
     $Filename = pathinfo($Source, PATHINFO_FILENAME);
     $Extension = pathinfo($Source, PATHINFO_EXTENSION);
     if (!array_key_exists('SmallImage', $Attributes)) {
         // make directory
         $TargetFolder = 'uploads/cached';
         // cache directory
         if (!is_dir($TargetFolder)) {
             mkdir($TargetFolder, 0777, True);
         }
         $SmallImage = GenerateCleanTargetName($TargetFolder, $Filename . '-' . $Hash, $Extension, False, True);
         $Attributes['SmallImage'] = $SmallImage;
         if (!file_exists($SmallImage)) {
             $bSaveImage = True;
         }
     }
     // get attributes
     $Width = ArrayValue('width', $Attributes, '');
     $Height = ArrayValue('height', $Attributes, '');
     $Crop = GetValue('Crop', $Attributes, False, True);
     $SmallImage = GetValue('SmallImage', $Attributes, '', True);
     $ZoomAttributes = array('id' => 'p' . $Hash);
     if (!$NoHiding) {
         $ZoomAttributes['style'] = 'display:none';
     }
     //if (!array_key_exists('alt', $Attributes)) $Attributes['alt'] = $Filename;
     TouchValue('alt', $Attributes, $Filename);
     if ($bSaveImage) {
         Gdn_UploadImage::SaveImageAs($Source, $SmallImage, $Height, $Width, $Crop);
     }
     $SmallImage = Img($SmallImage, $Attributes);
     $ZoomImage = Img($Source, array('alt' => ArrayValue('alt', $Attributes, '')));
     return "\n" . Wrap($SmallImage, 'a', array('href' => '#p' . $Hash)) . Wrap($ZoomImage, 'div', $ZoomAttributes);
 }
 protected function _Touch(&$Data)
 {
     TouchValue('ActivityType', $Data, 'Default');
     TouchValue('ActivityUserID', $Data, Gdn::Session()->UserID);
     TouchValue('NotifyUserID', $Data, self::NOTIFY_PUBLIC);
     TouchValue('Headline', $Data, NULL);
     TouchValue('Story', $Data, NULL);
     TouchValue('Notified', $Data, 0);
     TouchValue('Emailed', $Data, 0);
     TouchValue('Photo', $Data, NULL);
     TouchValue('Route', $Data, NULL);
     if (!isset($Data['Data']) || !is_array($Data['Data'])) {
         $Data['Data'] = array();
     }
 }
Exemple #20
0
 /**
  * Take all of the values that aren't in the schema and put them into the attributes column.
  *
  * @param array $Data
  * @param string $Name
  * @return array
  */
 protected function collapseAttributes($Data, $Name = 'Attributes')
 {
     $this->defineSchema();
     $Row = array_intersect_key($Data, $this->Schema->fields());
     $Attributes = array_diff_key($Data, $Row);
     TouchValue($Name, $Row, array());
     if (isset($Row[$Name]) && is_array($Row[$Name])) {
         $Row[$Name] = array_merge($Row[$Name], $Attributes);
     } else {
         $Row[$Name] = $Attributes;
     }
     return $Row;
 }
Exemple #21
0
 /**
  * Undocumented method.
  *
  * @todo Method RenderMaster() needs a description.
  */
 public function RenderMaster()
 {
     // Build the master view if necessary
     if (in_array($this->_DeliveryType, array(DELIVERY_TYPE_ALL))) {
         $this->MasterView = $this->MasterView();
         // Only get css & ui components if this is NOT a syndication request
         if ($this->SyndicationMethod == SYNDICATION_NONE && is_object($this->Head)) {
             if (ArrayHasValue($this->_CssFiles, 'style.css')) {
                 $this->AddCssFile('custom.css');
             }
             if (ArrayHasValue($this->_CssFiles, 'admin.css')) {
                 $this->AddCssFile('customadmin.css');
             }
             $this->EventArguments['CssFiles'] =& $this->_CssFiles;
             $this->FireEvent('BeforeAddCss');
             // And now search for/add all css files
             foreach ($this->_CssFiles as $CssInfo) {
                 $CssFile = $CssInfo['FileName'];
                 if (strpos($CssFile, '/') !== FALSE) {
                     // A direct path to the file was given.
                     $CssPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $CssFile))));
                 } else {
                     $CssGlob = preg_replace('/(.*)(\\.css)/', '\\1*\\2', $CssFile);
                     $AppFolder = $CssInfo['AppFolder'];
                     if ($AppFolder == '') {
                         $AppFolder = $this->ApplicationFolder;
                     }
                     // CSS comes from one of four places:
                     $CssPaths = array();
                     if ($this->Theme) {
                         // 1. Application-specific css. eg. root/themes/theme_name/app_name/design/
                         // $CssPaths[] = PATH_THEMES . DS . $this->Theme . DS . $AppFolder . DS . 'design' . DS . $CssGlob;
                         // 2. Theme-wide theme view. eg. root/themes/theme_name/design/
                         // a) Check to see if a customized version of the css is there.
                         if ($this->ThemeOptions) {
                             $Filenames = GetValueR('Styles.Value', $this->ThemeOptions);
                             if (is_string($Filenames) && $Filenames != '%s') {
                                 $CssPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'design' . DS . ChangeBasename($CssFile, $Filenames);
                             }
                         }
                         // b) Use the default filename.
                         $CssPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'design' . DS . $CssFile;
                     }
                     // 3. Application or plugin.
                     if (StringBeginsWith($AppFolder, 'plugins/')) {
                         // The css is coming from a plugin.
                         $AppFolder = substr($AppFolder, strlen('plugins/'));
                         $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/design/{$CssFile}";
                         $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/{$CssFile}";
                     } else {
                         // Application default. eg. root/applications/app_name/design/
                         $CssPaths[] = PATH_APPLICATIONS . DS . $AppFolder . DS . 'design' . DS . $CssFile;
                     }
                     // 4. Garden default. eg. root/applications/dashboard/design/
                     $CssPaths[] = PATH_APPLICATIONS . DS . 'dashboard' . DS . 'design' . DS . $CssFile;
                 }
                 // Find the first file that matches the path.
                 $CssPath = FALSE;
                 foreach ($CssPaths as $Glob) {
                     $Paths = SafeGlob($Glob);
                     if (is_array($Paths) && count($Paths) > 0) {
                         $CssPath = $Paths[0];
                         break;
                     }
                 }
                 // Check to see if there is a CSS cacher.
                 $CssCacher = Gdn::Factory('CssCacher');
                 if (!is_null($CssCacher)) {
                     $CssPath = $CssCacher->Get($CssPath, $AppFolder);
                 }
                 if ($CssPath !== FALSE) {
                     $CssPath = substr($CssPath, strlen(PATH_ROOT));
                     $CssPath = str_replace(DS, '/', $CssPath);
                     $this->Head->AddCss($CssPath, 'all', TRUE, $CssInfo['Options']);
                 }
             }
             // Add a custom js file.
             if (ArrayHasValue($this->_CssFiles, 'style.css')) {
                 $this->AddJsFile('custom.js');
             }
             // only to non-admin pages.
             // And now search for/add all JS files
             foreach ($this->_JsFiles as $Index => $JsInfo) {
                 $JsFile = $JsInfo['FileName'];
                 if (strpos($JsFile, '//') !== FALSE) {
                     // This is a link to an external file.
                     $this->Head->AddScript($JsFile);
                     continue;
                 }
                 if (strpos($JsFile, '/') !== FALSE) {
                     // A direct path to the file was given.
                     $JsPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $JsFile)), DS));
                 } else {
                     $AppFolder = $JsInfo['AppFolder'];
                     if ($AppFolder == '') {
                         $AppFolder = $this->ApplicationFolder;
                     }
                     // JS can come from a theme, an any of the application folder, or it can come from the global js folder:
                     $JsPaths = array();
                     if ($this->Theme) {
                         // 1. Application-specific js. eg. root/themes/theme_name/app_name/design/
                         $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . $AppFolder . DS . 'js' . DS . $JsFile;
                         // 2. Garden-wide theme view. eg. root/themes/theme_name/design/
                         $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'js' . DS . $JsFile;
                     }
                     // 3. The application or plugin folder.
                     if (StringBeginsWith(trim($AppFolder, '/'), 'plugins/')) {
                         $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/js/{$JsFile}";
                         $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/{$JsFile}";
                     } else {
                         $JsPaths[] = PATH_APPLICATIONS . "/{$AppFolder}/js/{$JsFile}";
                     }
                     // 4. Global JS folder. eg. root/js/
                     $JsPaths[] = PATH_ROOT . DS . 'js' . DS . $JsFile;
                     // 5. Global JS library folder. eg. root/js/library/
                     $JsPaths[] = PATH_ROOT . DS . 'js' . DS . 'library' . DS . $JsFile;
                 }
                 // Find the first file that matches the path.
                 $JsPath = FALSE;
                 foreach ($JsPaths as $Glob) {
                     $Paths = SafeGlob($Glob);
                     if (is_array($Paths) && count($Paths) > 0) {
                         $JsPath = $Paths[0];
                         break;
                     }
                 }
                 if ($JsPath !== FALSE) {
                     $JsSrc = str_replace(array(PATH_ROOT, DS), array('', '/'), $JsPath);
                     $Options = (array) $JsInfo['Options'];
                     $Options['path'] = $JsPath;
                     $Version = GetValue('Version', $JsInfo);
                     if ($Version) {
                         TouchValue('version', $Options, $Version);
                     }
                     $this->Head->AddScript($JsSrc, 'text/javascript', $Options);
                 }
             }
         }
         // Add the favicon
         $this->Head->SetFavIcon(C('Garden.FavIcon', Asset('themes/' . $this->Theme . '/design/favicon.png')));
         // Make sure the head module gets passed into the assets collection.
         $this->AddModule('Head');
     }
     // Master views come from one of four places:
     $MasterViewPaths = array();
     if (strpos($this->MasterView, '/') !== FALSE) {
         $MasterViewPaths[] = CombinePaths(array(PATH_ROOT, str_replace('/', DS, $this->MasterView) . '.master*'));
     } else {
         if ($this->Theme) {
             // 1. Application-specific theme view. eg. root/themes/theme_name/app_name/views/
             $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
             // 2. Garden-wide theme view. eg. /path/to/application/themes/theme_name/views/
             $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, 'views', $this->MasterView . '.master*'));
         }
         // 3. Application default. eg. root/app_name/views/
         $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
         // 4. Garden default. eg. root/dashboard/views/
         $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, 'dashboard', 'views', $this->MasterView . '.master*'));
     }
     // Find the first file that matches the path.
     $MasterViewPath = FALSE;
     foreach ($MasterViewPaths as $Glob) {
         $Paths = SafeGlob($Glob);
         if (is_array($Paths) && count($Paths) > 0) {
             $MasterViewPath = $Paths[0];
             break;
         }
     }
     $this->EventArguments['MasterViewPath'] =& $MasterViewPath;
     $this->FireEvent('BeforeFetchMaster');
     if ($MasterViewPath === FALSE) {
         trigger_error(ErrorMessage("Could not find master view: {$this->MasterView}.master*", $this->ClassName, '_FetchController'), E_USER_ERROR);
     }
     /// A unique identifier that can be used in the body tag of the master view if needed.
     $ControllerName = $this->ClassName;
     // Strip "Controller" from the body identifier.
     if (substr($ControllerName, -10) == 'Controller') {
         $ControllerName = substr($ControllerName, 0, -10);
     }
     // Strip "Gdn_" from the body identifier.
     if (substr($ControllerName, 0, 4) == 'Gdn_') {
         $ControllerName = substr($ControllerName, 4);
     }
     $this->SetData('CssClass', $this->Application . ' ' . $ControllerName . ' ' . $this->RequestMethod . ' ' . $this->CssClass, TRUE);
     // Check to see if there is a handler for this particular extension.
     $ViewHandler = Gdn::Factory('ViewHandler' . strtolower(strrchr($MasterViewPath, '.')));
     if (is_null($ViewHandler)) {
         $BodyIdentifier = strtolower($this->ApplicationFolder . '_' . $ControllerName . '_' . Gdn_Format::AlphaNumeric(strtolower($this->RequestMethod)));
         include $MasterViewPath;
     } else {
         $ViewHandler->Render($MasterViewPath, $this);
     }
 }
Exemple #22
0
 public static function Link($Path, $Text = FALSE, $Format = '<a href="%url" class="%class">%text</a>', $Options = array())
 {
     $Session = Gdn::Session();
     $Class = GetValue('Class', $Options, '');
     switch ($Path) {
         case 'dashboard':
             $Path = 'dashboard/settings';
             TouchValue('Permissions', $Options, 'Garden.Settings.Manage');
             if (!$Text) {
                 $Text = T('Dashboard');
             }
             break;
         case 'inbox':
             $Path = 'messages/inbox';
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text) {
                 $Text = T('Inbox');
             }
             if ($Session->IsValid() && $Session->User->CountUnreadConversations) {
                 $Text .= ' <span>' . $Session->User->CountUnreadConversations . '</span>';
             }
             break;
         case 'profile':
             TouchValue('Permissions', $Options, 'Garden.SignIn.Allow');
             if (!$Text && $Session->IsValid()) {
                 $Text = $Session->User->Name;
             }
             if ($Session->IsValid() && $Session->User->CountNotifications) {
                 $Text .= ' <span>' . $Session->User->CountNotifications . '</span>';
             }
             break;
         case 'signinout':
             // The destination is the signin/signout toggle link.
             if ($Session->IsValid()) {
                 if (!$Text) {
                     $Text = T('Sign Out');
                 }
                 $Path = Gdn::Authenticator()->SignOutUrl();
                 $Class = ConcatSep(' ', $Class, 'SignOut');
             } else {
                 if (!$Text && !$NoTag) {
                     $Text = T('Sign In');
                 }
                 $Attribs = array();
                 $Path = Gdn::Authenticator()->SignInUrl('');
                 if (C('Garden.SignIn.Popup') && strpos(Gdn::Request()->Url(), 'entry') === FALSE) {
                     $Class = ConcatSep(' ', $Class, 'SignInPopup');
                 }
             }
             break;
     }
     if (GetValue('Permissions', $Options) && !$Session->CheckPermission($Options['Permissions'])) {
         return '';
     }
     $Url = Gdn::Request()->Url($Path, GetValue('WithDomain', $Options));
     if (strcasecmp(trim($Path, '/'), Gdn::Request()->Path()) == 0) {
         $Class = ConcatSep(' ', $Class, 'Selected');
     }
     // Build the final result.
     $Result = $Format;
     $Result = str_replace('%url', $Url, $Result);
     $Result = str_replace('%text', $Text, $Result);
     $Result = str_replace('%class', $Class, $Result);
     return $Result;
 }
 public function Get($key, $options = array())
 {
     $startTime = microtime(TRUE);
     $finalOptions = array_merge($this->StoreDefaults, $options);
     $localData = array();
     $realKeys = array();
     if (is_array($key)) {
         $multi = true;
         foreach ($key as $multiKey) {
             $realKey = $this->MakeKey($multiKey, $finalOptions);
             // Skip this key if we already have it
             $local = Gdn_Cache::LocalGet($realKey);
             if ($local !== Gdn_Cache::CACHEOP_FAILURE) {
                 $localData[$realKey] = $local;
                 continue;
             }
             $realKeys[] = $realKey;
         }
     } else {
         $multi = false;
         $realKey = $this->MakeKey($key, $finalOptions);
         // Completely short circuit if we already have everything
         $local = Gdn_Cache::LocalGet($realKey);
         if ($local !== false) {
             return $local;
         }
         $realKeys = array($realKey);
     }
     $data = array();
     $hitCache = false;
     if ($numKeys = sizeof($realKeys)) {
         $hitCache = true;
         if ($numKeys > 1) {
             $data = $this->Memcache->getMulti($realKeys);
         } else {
             $data = $this->Memcache->get($realKey);
             $data = array($realKey => $data);
         }
         $storeData = array();
         foreach ($data as $localKey => $localValue) {
             if ($localValue !== false) {
                 $storeData[$localKey] = $localValue;
             }
         }
         $data = $storeData;
         unset($storeData);
         // Cache in process memory
         if (sizeof($data)) {
             Gdn_Cache::LocalSet($data);
         }
     }
     // Merge in local data
     $data = array_merge($data, $localData);
     // Track debug stats
     $elapsedTime = microtime(true) - $startTime;
     if (Gdn_Cache::$trace) {
         Gdn_Cache::$trackTime += $elapsedTime;
         Gdn_Cache::$trackGets++;
         $keyTime = sizeof($realKeys) ? $elapsedTime / sizeof($realKeys) : $elapsedTime;
         foreach ($realKeys as $realKey) {
             TouchValue($realKey, Gdn_Cache::$trackGet, array('hits' => 0, 'time' => 0, 'keysize' => null, 'transfer' => 0, 'wasted' => 0));
             $keyData = GetValue($realKey, $data, false);
             Gdn_Cache::$trackGet[$realKey]['hits']++;
             Gdn_Cache::$trackGet[$realKey]['time'] += $keyTime;
             if ($keyData !== false) {
                 $keyData = serialize($keyData);
                 $keySize = strlen($keyData);
                 if (is_null(Gdn_Cache::$trackGet[$realKey]['keysize'])) {
                     Gdn_Cache::$trackGet[$realKey]['keysize'] = $keySize;
                 } else {
                     Gdn_Cache::$trackGet[$realKey]['wasted'] += $keySize;
                 }
                 Gdn_Cache::$trackGet[$realKey]['transfer'] += Gdn_Cache::$trackGet[$realKey]['keysize'];
             }
         }
     }
     // Miss: return the fallback
     if ($data === false) {
         return $this->Fallback($key, $options);
     }
     // Hit: Single key. Return the value
     if (!$multi) {
         $val = sizeof($data) ? array_pop($data) : false;
         return $val;
     }
     // Hit: Multi key. Return stripped array.
     $dataStripped = array();
     foreach ($data as $index => $value) {
         $dataStripped[$this->StripKey($index, $finalOptions)] = $value;
     }
     $data = $dataStripped;
     unset($dataStripped);
     return $data;
 }
 /**
  * @param Gdn_Controller $Sender
  * @param array $Args
  */
 protected function Settings_AddEdit($Sender, $Args)
 {
     $client_id = $Sender->Request->Get('client_id');
     Gdn::Locale()->SetTranslation('AuthenticationKey', 'Client ID');
     Gdn::Locale()->SetTranslation('AssociationSecret', 'Secret');
     Gdn::Locale()->SetTranslation('AuthenticateUrl', 'Authentication Url');
     $Form = new Gdn_Form();
     $Sender->Form = $Form;
     if ($Form->AuthenticatedPostBack()) {
         if ($Form->GetFormValue('Generate') || $Sender->Request->Post('Generate')) {
             $Form->SetFormValue('AuthenticationKey', mt_rand());
             $Form->SetFormValue('AssociationSecret', md5(mt_rand()));
             $Sender->SetFormSaved(FALSE);
         } else {
             $Form->ValidateRule('AuthenticationKey', 'ValidateRequired');
             //          $Form->ValidateRule('AuthenticationKey', 'regex:`^[a-z0-9_-]+$`i', T('The client id must contain only letters, numbers and dashes.'));
             $Form->ValidateRule('AssociationSecret', 'ValidateRequired');
             $Form->ValidateRule('AuthenticateUrl', 'ValidateRequired');
             $Values = $Form->FormValues();
             //        $Values = ArrayTranslate($Values, array('Name', 'AuthenticationKey', 'URL', 'AssociationSecret', 'AuthenticateUrl', 'SignInUrl', 'RegisterUrl', 'SignOutUrl', 'IsDefault'));
             $Values['AuthenticationSchemeAlias'] = 'jsconnect';
             $Values['AssociationHashMethod'] = 'md5';
             $Values['Attributes'] = serialize(array('HashType' => $Form->GetFormValue('HashType'), 'TestMode' => $Form->GetFormValue('TestMode'), 'Trusted' => $Form->GetFormValue('Trusted', 0)));
             if ($Form->ErrorCount() == 0) {
                 if ($client_id) {
                     Gdn::SQL()->Put('UserAuthenticationProvider', $Values, array('AuthenticationKey' => $client_id));
                 } else {
                     Gdn::SQL()->Options('Ignore', TRUE)->Insert('UserAuthenticationProvider', $Values);
                 }
                 $Sender->RedirectUrl = Url('/settings/jsconnect');
             }
         }
     } else {
         if ($client_id) {
             $Provider = self::GetProvider($client_id);
             TouchValue('Trusted', $Provider, 1);
         } else {
             $Provider = array();
         }
         $Form->SetData($Provider);
     }
     $Sender->SetData('Title', sprintf(T($client_id ? 'Edit %s' : 'Add %s'), T('Connection')));
     $Sender->Render('Settings_AddEdit', '', 'plugins/jsconnect');
 }
 public static function JoinRecentPosts(&$Data)
 {
     $DiscussionIDs = array();
     $CommentIDs = array();
     $Joined = FALSE;
     foreach ($Data as &$Row) {
         if (isset($Row['LastTitle']) && $Row['LastTitle']) {
             continue;
         }
         if ($Row['LastDiscussionID']) {
             $DiscussionIDs[] = $Row['LastDiscussionID'];
         }
         if ($Row['LastCommentID']) {
             $CommentIDs[] = $Row['LastCommentID'];
         }
         $Joined = TRUE;
     }
     // Create a fresh copy of the Sql object so as not to pollute.
     $Sql = clone Gdn::SQL();
     $Sql->Reset();
     // Grab the discussions.
     if (count($DiscussionIDs) > 0) {
         $Discussions = $Sql->WhereIn('DiscussionID', $DiscussionIDs)->Get('Discussion')->ResultArray();
         $Discussions = Gdn_DataSet::Index($Discussions, array('DiscussionID'));
     }
     if (count($CommentIDs) > 0) {
         $Comments = $Sql->WhereIn('CommentID', $CommentIDs)->Get('Comment')->ResultArray();
         $Comments = Gdn_DataSet::Index($Comments, array('CommentID'));
     }
     foreach ($Data as &$Row) {
         $Discussion = GetValue($Row['LastDiscussionID'], $Discussions);
         $NameUrl = 'x';
         if ($Discussion) {
             $Row['LastTitle'] = Gdn_Format::Text($Discussion['Name']);
             $Row['LastUserID'] = $Discussion['InsertUserID'];
             $Row['LastDateInserted'] = $Discussion['DateInserted'];
             $NameUrl = Gdn_Format::Text($Discussion['Name'], TRUE);
             $Row['LastUrl'] = DiscussionUrl($Discussion, FALSE, '//') . '#latest';
         }
         $Comment = GetValue($Row['LastCommentID'], $Comments);
         if ($Comment) {
             $Row['LastUserID'] = $Comment['InsertUserID'];
             $Row['LastDateInserted'] = $Comment['DateInserted'];
         } else {
             $Row['NoComment'] = TRUE;
         }
         TouchValue('LastTitle', $Row, '');
         TouchValue('LastUserID', $Row, NULL);
         TouchValue('LastDateInserted', $Row, NULL);
         TouchValue('LastUrl', $Row, NULL);
     }
     return $Joined;
 }
 public function SetCalculatedFields(&$User)
 {
     if ($v = GetValue('Attributes', $User)) {
         if (is_string($v)) {
             SetValue('Attributes', $User, @unserialize($v));
         }
     }
     if ($v = GetValue('Permissions', $User)) {
         SetValue('Permissions', $User, @unserialize($v));
     }
     if ($v = GetValue('Preferences', $User)) {
         SetValue('Preferences', $User, @unserialize($v));
     }
     if ($v = GetValue('Photo', $User)) {
         if (!IsUrl($v)) {
             $PhotoUrl = Gdn_Upload::Url(ChangeBasename($v, 'n%s'));
         } else {
             $PhotoUrl = $v;
         }
         SetValue('PhotoUrl', $User, $PhotoUrl);
     }
     if ($v = GetValue('AllIPAddresses', $User)) {
         $IPAddresses = explode(',', $v);
         foreach ($IPAddresses as $i => $IPAddress) {
             $IPAddresses[$i] = ForceIPv4($IPAddress);
         }
         SetValue('AllIPAddresses', $User, $IPAddresses);
     }
     TouchValue('_CssClass', $User, '');
     if ($v = GetValue('Banned', $User)) {
         SetValue('_CssClass', $User, 'Banned');
     }
     $this->EventArguments['User'] =& $User;
     $this->FireEvent('SetCalculatedFields');
 }
Exemple #27
0
 /**
  * Generates a multi-field form from a schema.
  * @param array $Schema An array where each item of the array is a row that identifies a form field with the following information:
  *  - Name: The name of the form field.
  *  - Control: The type of control used for the field. This is one of the control methods on the Gdn_Form object.
  *  - LabelCode: The translation code for the label. Optional.
  *  - Description: An optional description for the field.
  *  - Items: If the control is a list control then its items are specified here.
  *  - Options: Additional options to be passed into the control.
  * @param type $Options Additional options to pass into the form.
  *  - Wrap: A two item array specifying the text to wrap the form in.
  *  - ItemWrap: A two item array specifying the text to wrap each form item in.
  */
 public function Simple($Schema, $Options = array())
 {
     $Result = GetValueR('Wrap.0', $Options, '<ul>');
     $ItemWrap = GetValue('ItemWrap', $Options, array("<li>\n  ", "\n</li>\n"));
     foreach ($Schema as $Index => $Row) {
         if (is_string($Row)) {
             $Row = array('Name' => $Index, 'Control' => $Row);
         }
         if (!isset($Row['Name'])) {
             $Row['Name'] = $Index;
         }
         if (!isset($Row['Options'])) {
             $Row['Options'] = array();
         }
         $Result .= $ItemWrap[0];
         $LabelCode = self::LabelCode($Row);
         $Description = GetValue('Description', $Row, '');
         if ($Description) {
             $Description = '<div class="Info">' . $Description . '</div>';
         }
         TouchValue('Control', $Row, 'TextBox');
         switch (strtolower($Row['Control'])) {
             case 'categorydropdown':
                 $Result .= $this->Label($LabelCode, $Row['Name']) . $Description . $this->CategoryDropDown($Row['Name'], $Row['Options']);
                 break;
             case 'checkbox':
                 $Result .= $Description . $this->CheckBox($Row['Name'], T($LabelCode));
                 break;
             case 'dropdown':
                 $Result .= $this->Label($LabelCode, $Row['Name']) . $Description . $this->DropDown($Row['Name'], $Row['Items'], $Row['Options']);
                 break;
             case 'radiolist':
                 $Result .= $Description . $this->RadioList($Row['Name'], $Row['Items'], $Row['Options']);
                 break;
             case 'checkboxlist':
                 $Result .= $this->Label($LabelCode, $Row['Name']) . $Description . $this->CheckBoxList($Row['Name'], $Row['Items'], NULL, $Row['Options']);
                 break;
             case 'textbox':
                 $Result .= $this->Label($LabelCode, $Row['Name']) . $Description . $this->TextBox($Row['Name'], $Row['Options']);
                 break;
             case 'callback':
                 $Row['DescriptionHtml'] = $Description;
                 $Row['LabelCode'] = $LabelCode;
                 $Result .= call_user_func($Row['Callback'], $this, $Row);
                 break;
             default:
                 $Result .= "Error a control type of {$Row['Control']} is not supported.";
                 break;
         }
         $Result .= $ItemWrap[1];
     }
     $Result .= GetValueR('Wrap.1', $Options, '</ul>');
     return $Result;
 }
 /**
  *
  *
  * @param string $key
  * @param array $options
  * @return array|bool|mixed
  */
 public function get($key, $options = array())
 {
     if (!$this->online()) {
         return Gdn_Cache::CACHEOP_FAILURE;
     }
     $startTime = microtime(true);
     $finalOptions = array_merge($this->StoreDefaults, $options);
     $useLocal = (bool) $finalOptions[Gdn_Cache::FEATURE_LOCAL];
     $localData = array();
     $realKeys = array();
     if (is_array($key)) {
         $multi = true;
         foreach ($key as $multiKey) {
             $realKey = $this->makeKey($multiKey, $finalOptions);
             // Skip this key if we already have it
             if ($useLocal) {
                 $local = $this->localGet($realKey);
                 if ($local !== Gdn_Cache::CACHEOP_FAILURE) {
                     $localData[$realKey] = $local;
                     continue;
                 }
             }
             $realKeys[] = $realKey;
         }
     } else {
         $multi = false;
         $realKey = $this->makeKey($key, $finalOptions);
         // Completely short circuit if we already have everything
         if ($useLocal) {
             $local = $this->localGet($realKey);
             if ($local !== false) {
                 return $local;
             }
         }
         $realKeys = array($realKey);
     }
     $data = array();
     $hitCache = false;
     $numKeys = sizeof($realKeys);
     if ($numKeys) {
         $hitCache = true;
         if ($numKeys > 1) {
             $data = $this->memcache->getMulti($realKeys);
             $ok = $this->lastAction();
         } else {
             $data = $this->memcache->get($realKey);
             // Check if things went ok
             $ok = $this->lastAction($realKey);
             $data = array($realKey => $data);
         }
         if (!$ok) {
             return Gdn_Cache::CACHEOP_FAILURE;
         }
         $storeData = array();
         foreach ($data as $localKey => &$localValue) {
             // Is this a sharded key manifest?
             if (is_object($localValue) && $localValue instanceof MemcachedShard) {
                 $manifest = $localValue;
                 // MultiGet sub-keys
                 $shardKeys = array();
                 foreach ($manifest->keys as $serverKey => $keys) {
                     $serverKeys = $this->memcache->getMultiByKey($serverKey, $keys);
                     $shardKeys = array_merge($shardKeys, $serverKeys);
                 }
                 ksort($shardKeys, SORT_NATURAL);
                 // Check subkeys for validity
                 $shardData = implode('', array_values($shardKeys));
                 unset($shardKeys);
                 $dataHash = md5($shardData);
                 if ($dataHash != $manifest->hash) {
                     continue;
                 }
                 $localValue = unserialize($shardData);
             }
             if ($localValue !== false) {
                 $storeData[$localKey] = $localValue;
             }
         }
         $data = $storeData;
         unset($storeData);
         // Cache in process memory
         if ($useLocal && sizeof($data)) {
             $this->localSet($data);
         }
     }
     // Merge in local data
     $data = array_merge($data, $localData);
     // Track debug stats
     $elapsedTime = microtime(true) - $startTime;
     if (Gdn_Cache::$trace) {
         Gdn_Cache::$trackTime += $elapsedTime;
         Gdn_Cache::$trackGets++;
         $keyTime = sizeof($realKeys) ? $elapsedTime / sizeof($realKeys) : $elapsedTime;
         foreach ($realKeys as $realKey) {
             TouchValue($realKey, Gdn_Cache::$trackGet, array('hits' => 0, 'time' => 0, 'keysize' => null, 'transfer' => 0, 'wasted' => 0));
             $keyData = val($realKey, $data, false);
             Gdn_Cache::$trackGet[$realKey]['hits']++;
             Gdn_Cache::$trackGet[$realKey]['time'] += $keyTime;
             if ($keyData !== false) {
                 $keyData = serialize($keyData);
                 $keySize = strlen($keyData);
                 if (is_null(Gdn_Cache::$trackGet[$realKey]['keysize'])) {
                     Gdn_Cache::$trackGet[$realKey]['keysize'] = $keySize;
                 } else {
                     Gdn_Cache::$trackGet[$realKey]['wasted'] += $keySize;
                 }
                 Gdn_Cache::$trackGet[$realKey]['transfer'] += Gdn_Cache::$trackGet[$realKey]['keysize'];
             }
         }
     }
     // Miss: return the fallback
     if ($data === false) {
         return $this->fallback($key, $options);
     }
     // Hit: Single key. Return the value
     if (!$multi) {
         $val = sizeof($data) ? array_pop($data) : false;
         return $val;
     }
     // Hit: Multi key. Return stripped array.
     $dataStripped = array();
     foreach ($data as $index => $value) {
         $dataStripped[$this->stripKey($index, $finalOptions)] = $value;
     }
     $data = $dataStripped;
     unset($dataStripped);
     return $data;
 }