/** * 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; }
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(); }
/** * 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(); } }
/** * 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; }
/** * 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); } }
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'); }
/** * 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; }