Get the addon manager.
public static addonManager ( ) : |
||
return |
/** * */ public function __construct() { $this->Dispatcher = new Gdn_Dispatcher(Gdn::addonManager()); $EnabledApplications = Gdn::config('EnabledApplications'); $this->Dispatcher->enabledApplicationFolders($EnabledApplications); $this->Dispatcher->passProperty('EnabledApplications', $EnabledApplications); }
/** * Find available social plugins. * * @return array|mixed * @throws Exception */ protected function getConnections() { $this->fireEvent('GetConnections'); $connections = []; $addons = Gdn::addonManager()->lookupAllByType(\Vanilla\Addon::TYPE_ADDON); foreach ($addons as $addonName => $addon) { $addonInfo = $addon->getInfo(); // Limit to designated social addons. if (!array_key_exists('socialConnect', $addonInfo)) { continue; } // See if addon is enabled. $isEnabled = Gdn::addonManager()->isEnabled($addonName, \Vanilla\Addon::TYPE_ADDON); setValue('enabled', $addonInfo, $isEnabled); // See if we can detect whether connection is configured. $isConfigured = null; if ($isEnabled) { $pluginInstance = Gdn::pluginManager()->getPluginInstance($addonName, Gdn_PluginManager::ACCESS_PLUGINNAME); if (method_exists($pluginInstance, 'isConfigured')) { $isConfigured = $pluginInstance->isConfigured(); } } setValue('configured', $addonInfo, $isConfigured); // Add the connection. $connections[$addonName] = $addonInfo; } return $connections; }
/** * QnAPlugin constructor. */ public function __construct() { parent::__construct(); if (Gdn::addonManager()->isEnabled('Reactions', \Vanilla\Addon::TYPE_ADDON) && c('Plugins.QnA.Reactions', true)) { $this->Reactions = true; } if ((Gdn::addonManager()->isEnabled('Reputation', \Vanilla\Addon::TYPE_ADDON) || Gdn::addonManager()->isEnabled('badges', \Vanilla\Addon::TYPE_ADDON)) && c('Plugins.QnA.Badges', true)) { $this->Badges = true; } }
public function enablePlugin($pluginName, $filter = 'all') { if (!Gdn::request()->isAuthenticatedPostBack(true)) { throw new Exception('Requires POST', 405); } $this->permission('Garden.Settings.Manage'); $action = 'none'; if ($filter == 'disabled') { $action = 'SlideUp'; } $addon = Gdn::addonManager()->lookupAddon($pluginName); try { $validation = new Gdn_Validation(); if (!Gdn::pluginManager()->enablePlugin($pluginName, $validation)) { $this->Form->setValidationResults($validation->results()); } else { Gdn_LibraryMap::ClearCache(); $this->informMessage(sprintf(t('%s Enabled.'), val('name', $addon->getInfo(), t('Plugin')))); } $this->EventArguments['PluginName'] = $pluginName; $this->EventArguments['Validation'] = $validation; $this->fireEvent('AfterEnablePlugin'); } catch (Exception $e) { $this->Form->addError($e); } $this->handleAddonToggle($pluginName, $addon->getInfo(), 'plugins', true, $filter, $action); }
/** * Parses the query string looking for supplied request parameters. * * Places anything useful into this object's Controller properties. * * @param Gdn_Request $request The request to analyze. */ private function analyzeRequest($request) { // Initialize the result of our request. $result = ['method' => $request->requestMethod(), 'path' => $request->path(), 'addon' => null, 'controller' => '', 'controllerMethod' => '', 'pathArgs' => [], 'query' => array_change_key_case($request->get()), 'post' => $request->post()]; // Here is the basic format of a request: // [/application]/controller[/method[.json|.xml]]/argn|argn=valn // Here are some examples of what this method could/would receive: // /application/controller/method/argn // /controller/method/argn // /application/controller/argn // /controller/argn // /controller $parts = explode('/', str_replace('\\', '/', $request->path())); // Decode path parts at the dispatcher level. array_walk($parts, function (&$value) { $value = rawurldecode($value); }); // Parse the file extension. list($parts, $deliveryMethod) = $this->parseDeliveryMethod($parts); // Set some special properties based on the deliver method. $deliveryType = $this->deliveryType; switch ($deliveryMethod) { case DELIVERY_METHOD_JSON: case DELIVERY_METHOD_XML: $deliveryType = DELIVERY_TYPE_DATA; break; case DELIVERY_METHOD_ATOM: case DELIVERY_METHOD_RSS: $result['syndicationMethod'] = DELIVERY_METHOD_RSS; //$deliveryMethod; break; case DELIVERY_METHOD_TEXT: $deliveryType = DELIVERY_TYPE_VIEW; break; } // An explicitly passed delivery type/method overrides the default. $result['deliveryMethod'] = self::requestVal('DeliveryMethod', $result['query'], $result['post'], $deliveryMethod ?: $this->deliveryMethod); $result['deliveryType'] = self::requestVal('DeliveryType', $result['query'], $result['post'], $deliveryType); // Figure out the controller. list($controllerName, $pathArgs) = $this->findController($parts); $result['pathArgs'] = $pathArgs; if ($controllerName) { // The controller was found based on the path. $result['controller'] = $controllerName; } elseif (Gdn::pluginManager()->hasNewMethod('RootController', val(0, $parts))) { // There is a plugin defining a new root method. $result['controller'] = 'RootController'; } else { // No controller was found, fire a not found event. // TODO: Move this outside this method. $this->EventArguments['Handled'] = false; $Handled =& $this->EventArguments['Handled']; $this->fireEvent('NotFound'); if (!$Handled) { safeHeader("HTTP/1.1 404 Not Found"); return $this->passData('Reason', 'controller_notfound')->analyzeRequest($request->withRoute('Default404')); } return; } // A controller has been found. Find the addon that manages it. $addon = Gdn::addonManager()->lookupByClassname($result['controller']); // The result should be properly set now. Set the legacy properties though. if ($addon) { $result['addon'] = $addon; $this->applicationFolder = stringBeginsWith($addon->getSubdir(), 'applications/', true, true); } $this->ControllerName = $result['controller']; $this->controllerMethodArgs = []; $this->syndicationMethod = val('syndicationMethod', $result, SYNDICATION_NONE); $this->deliveryMethod = $result['deliveryMethod']; return $result; }
/** * Converts addon info into a media item. * * @param $addonName * @param $addonInfo * @param $isEnabled * @param $addonType * @param $filter */ function writeAddonMedia($addonName, $addonInfo, $isEnabled, $addonType, $filter) { $capitalCaseSheme = new \Vanilla\Utility\CapitalCaseScheme(); $addonInfo = $capitalCaseSheme->convertArrayKeys($addonInfo, ['RegisterPermissions']); $screenName = Gdn_Format::display(val('Name', $addonInfo, $addonName)); $description = Gdn_Format::html(t(val('Name', $addonInfo, $addonName) . ' Description', val('Description', $addonInfo, ''))); $id = Gdn_Format::url($addonName) . '-addon'; $media = new MediaItemModule($screenName, '', $description, 'li', ['id' => $id]); $media->setView('media-addon'); // Icon $addon = Gdn::addonManager()->lookupAddon($addonName); $iconPath = ''; if ($addon) { $iconPath = $addon->getIcon(); } if (!$iconPath) { $iconPath = val('IconUrl', $addonInfo, 'applications/dashboard/design/images/addon-placeholder.png'); } $media->setImage($iconPath); // Settings button $settingsUrl = $isEnabled ? val('SettingsUrl', $addonInfo, '') : ''; $settingsPopupClass = val('UsePopupSettings', $addonInfo, true) ? ' js-modal' : ''; if ($settingsUrl != '') { $attr['class'] = 'btn btn-icon-border' . $settingsPopupClass; $attr['aria-label'] = sprintf(t('Settings for %s'), $screenName); $attr['data-reload-page-on-save'] = false; $media->addButton(dashboardSymbol('settings'), $settingsUrl, $attr); } // Toggle if ($addonType === 'locales') { $action = $isEnabled ? 'disable' : 'enable'; } else { $action = $filter; } if ($isEnabled) { $label = sprintf(t('Disable %s'), $screenName); } else { $label = sprintf(t('Enable %s'), $screenName); } $url = '/settings/' . $addonType . '/' . $action . '/' . $addonName; $media->setToggle(slugify($addonName), $isEnabled, $url, $label); // Meta $info = []; // Requirements $requiredApplications = val('RequiredApplications', $addonInfo, false); $requiredPlugins = val('RequiredPlugins', $addonInfo, false); $requirements = []; if (is_array($requiredApplications)) { foreach ($requiredApplications as $requiredApplication => $versionInfo) { $requirements[] = sprintf(t('%1$s Version %2$s'), $requiredApplication, $versionInfo); } } if (is_array($requiredPlugins)) { foreach ($requiredPlugins as $requiredPlugin => $versionInfo) { $requirements[] = sprintf(t('%1$s Version %2$s'), $requiredPlugin, $versionInfo); } } if (!empty($requirements)) { $requirementsMeta = sprintf(t('Requires: %s'), implode(', ', $requirements)); $info[] = $requirementsMeta; } // Authors $author = val('Author', $addonInfo, ''); $authors = []; // Check if singular author is set if ($author) { $authorUrl = val('AuthorUrl', $addonInfo, ''); if ($authorUrl) { $authors[] = anchor($author, $authorUrl); } else { $authors[] = $author; } } // Check for multiple authors foreach (val('Authors', $addonInfo, []) as $author) { if (val('Homepage', $author)) { $authors[] = anchor(val('Name', $author), val('Homepage', $author)); } else { $authors[] = val('Name', $author); } } if ($authors) { $authors = implode(', ', $authors); $info[] = sprintf(t('Created by %s'), $authors); } // Version Info $version = Gdn_Format::display(val('Version', $addonInfo, '')); $newVersion = val('NewVersion', $addonInfo, ''); $upgrade = $newVersion != '' && version_compare($newVersion, $version, '>'); if ($version != '') { $info[] = sprintf(t('Version %s'), $version); } $pluginUrl = val('PluginUrl', $addonInfo, ''); if ($upgrade && $pluginUrl) { $info[] = anchor(printf(t('%1$s version %2$s is available.'), $screenName, $newVersion), combinePaths(array($pluginUrl, 'find', urlencode($screenName)), '/')); } if ($pluginUrl != '') { $info[] = anchor(t('Visit Site'), $pluginUrl); } // Extra meta in addon array if ($meta = val('Meta', $addonInfo)) { foreach ($meta as $key => $value) { if (is_numeric($key)) { $info[] = $value; } else { $info[] = t($key) . ': ' . $value; } } } $media->setMeta($info); echo $media; }
/** * Generate an e-tag for the application from the versions of all of its enabled applications/plugins. * * @return string etag **/ public static function eTag() { $data = []; $data['vanilla-core-' . APPLICATION_VERSION] = true; // Look through the enabled addons. /* @var Addon $addon */ foreach (Gdn::addonManager()->getEnabled() as $addon) { if ($addon->getType() == Addon::TYPE_THEME) { // Themes have to figured out separately. continue; } $key = $addon->getKey(); $version = $addon->getVersion(); $type = $addon->getType(); $data[strtolower("{$key}-{$type}-{$version}")] = true; } // Add the desktop theme version. $themes = ['' => Gdn::addonManager()->lookupTheme(Gdn::themeManager()->desktopTheme()), 'Mobile' => Gdn::addonManager()->lookupTheme(Gdn::themeManager()->mobileTheme())]; foreach ($themes as $optionsPx => $theme) { if (!$theme instanceof Addon) { continue; } $data[$theme->getKey() . '-theme-' . $theme->getVersion()] = true; // Look for theme options. $options = c("Garden.{$optionsPx}ThemeOptions"); if (!empty($options)) { $data[valr('Styles.Value', $options)] = true; } } $info = Gdn::themeManager()->getThemeInfo(Gdn::themeManager()->desktopTheme()); if (!empty($info)) { $version = val('Version', $info, 'v0'); $data[strtolower("{$info['Index']}-theme-{$version}")] = true; if (Gdn::controller()->Theme && Gdn::controller()->ThemeOptions) { $filenames = valr('Styles.Value', Gdn::controller()->ThemeOptions); $data[$filenames] = true; } } // Add the mobile theme version. $info = Gdn::themeManager()->getThemeInfo(Gdn::themeManager()->mobileTheme()); if (!empty($info)) { $version = val('Version', $info, 'v0'); $data[strtolower("{$info['Index']}-theme-{$version}")] = true; } Gdn::pluginManager()->EventArguments['ETagData'] =& $data; $suffix = ''; Gdn::pluginManager()->EventArguments['Suffix'] =& $suffix; Gdn::pluginManager()->fireAs('AssetModel')->fireEvent('GenerateETag'); unset(Gdn::pluginManager()->EventArguments['ETagData']); ksort($data); $result = substr(md5(implode(',', array_keys($data))), 0, 8) . $suffix; return $result; }
/** * Handle toggling this version of embedding on and off. Take care of disabling the other version of embed (the old plugin). * * @param string $Toggle * @param string $TransientKey * @return boolean * @throws Gdn_UserException */ private function toggle($Toggle = '', $TransientKey = '') { if (in_array($Toggle, array('enable', 'disable')) && Gdn::session()->validateTransientKey($TransientKey)) { if ($Toggle == 'enable' && Gdn::addonManager()->isEnabled('embedvanilla', \Vanilla\Addon::TYPE_ADDON)) { throw new Gdn_UserException('You must disable the "Embed Vanilla" plugin before continuing.'); } // Do the toggle saveToConfig('Garden.Embed.Allow', $Toggle == 'enable' ? true : false); return true; } return false; }
/** * Display flood control options. * * @since 2.0.0 * @access public */ public function floodControl() { // Check permission $this->permission('Garden.Settings.Manage'); // Display options $this->title(t('Flood Control')); Gdn_Theme::section('Moderation'); $this->setHighlightRoute('vanilla/settings/floodcontrol'); // Check to see if Conversation is enabled. $IsConversationsEnabled = Gdn::addonManager()->isEnabled('Conversations', \Vanilla\Addon::TYPE_ADDON); $this->setData('IsConversationsEnabled', $IsConversationsEnabled); $ConfigurationFields = array('Vanilla.Discussion.SpamCount', 'Vanilla.Discussion.SpamTime', 'Vanilla.Discussion.SpamLock', 'Vanilla.Comment.SpamCount', 'Vanilla.Comment.SpamTime', 'Vanilla.Comment.SpamLock'); if ($IsConversationsEnabled) { $ConfigurationFields = array_merge($ConfigurationFields, array('Conversations.Conversation.SpamCount', 'Conversations.Conversation.SpamTime', 'Conversations.Conversation.SpamLock', 'Conversations.ConversationMessage.SpamCount', 'Conversations.ConversationMessage.SpamTime', 'Conversations.ConversationMessage.SpamLock')); } // Load up config options we'll be setting $Validation = new Gdn_Validation(); $ConfigurationModel = new Gdn_ConfigurationModel($Validation); $ConfigurationModel->setField($ConfigurationFields); // Set the model on the form. $this->Form->setModel($ConfigurationModel); // If seeing the form for the first time... if ($this->Form->authenticatedPostBack() === false) { // Apply the config settings to the form. $this->Form->setData($ConfigurationModel->Data); } else { // Define some validation rules for the fields being saved $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamCount', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamCount', 'Integer'); $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamTime', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamTime', 'Integer'); $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamLock', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Discussion.SpamLock', 'Integer'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamCount', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamCount', 'Integer'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamTime', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamTime', 'Integer'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamLock', 'Required'); $ConfigurationModel->Validation->applyRule('Vanilla.Comment.SpamLock', 'Integer'); if ($IsConversationsEnabled) { $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamCount', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamCount', 'Integer'); $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamTime', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamTime', 'Integer'); $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamLock', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.Conversation.SpamLock', 'Integer'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamCount', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamCount', 'Integer'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamTime', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamTime', 'Integer'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamLock', 'Required'); $ConfigurationModel->Validation->applyRule('Conversations.ConversationMessage.SpamLock', 'Integer'); } if ($this->Form->save() !== false) { $this->informMessage(t("Your changes have been saved.")); } } // Render default view $this->render(); }
} // Define 'Answer' badges if (Gdn::addonManager()->isEnabled('badges', \Vanilla\Addon::TYPE_ADDON) && c('Plugins.QnA.Badges', true)) { $this->Badges = true; } if ($this->Badges && class_exists('BadgeModel')) { $BadgeModel = new BadgeModel(); // Answer Counts $BadgeModel->define(array('Name' => 'First Answer', 'Slug' => 'answer', 'Type' => 'UserCount', 'Body' => 'Answering questions is a great way to show your support for a community!', 'Photo' => 'http://badges.vni.la/100/answer.png', 'Points' => 2, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 1, 'Class' => 'Answerer', 'Level' => 1, 'CanDelete' => 0)); $BadgeModel->define(array('Name' => '5 Answers', 'Slug' => 'answer-5', 'Type' => 'UserCount', 'Body' => 'Your willingness to share knowledge has definitely been noticed.', 'Photo' => 'http://badges.vni.la/100/answer-2.png', 'Points' => 3, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 5, 'Class' => 'Answerer', 'Level' => 2, 'CanDelete' => 0)); $BadgeModel->define(array('Name' => '25 Answers', 'Slug' => 'answer-25', 'Type' => 'UserCount', 'Body' => 'Looks like you’re starting to make a name for yourself as someone who knows the score!', 'Photo' => 'http://badges.vni.la/100/answer-3.png', 'Points' => 5, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 25, 'Class' => 'Answerer', 'Level' => 3, 'CanDelete' => 0)); $BadgeModel->define(array('Name' => '50 Answers', 'Slug' => 'answer-50', 'Type' => 'UserCount', 'Body' => 'Why use Google when we could just ask you?', 'Photo' => 'http://badges.vni.la/100/answer-4.png', 'Points' => 10, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 50, 'Class' => 'Answerer', 'Level' => 4, 'CanDelete' => 0)); $BadgeModel->define(array('Name' => '100 Answers', 'Slug' => 'answer-100', 'Type' => 'UserCount', 'Body' => 'Admit it, you read Wikipedia in your spare time.', 'Photo' => 'http://badges.vni.la/100/answer-5.png', 'Points' => 15, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 100, 'Class' => 'Answerer', 'Level' => 5, 'CanDelete' => 0)); $BadgeModel->define(array('Name' => '250 Answers', 'Slug' => 'answer-250', 'Type' => 'UserCount', 'Body' => 'Is there *anything* you don’t know?', 'Photo' => 'http://badges.vni.la/100/answer-6.png', 'Points' => 20, 'Attributes' => array('Column' => 'CountAcceptedAnswers'), 'Threshold' => 250, 'Class' => 'Answerer', 'Level' => 6, 'CanDelete' => 0)); } // Define 'Accept' reaction if (Gdn::addonManager()->isEnabled('Reactions', \Vanilla\Addon::TYPE_ADDON) && c('Plugins.QnA.Reactions', true)) { $this->Reactions = true; } if ($this->Reactions && class_exists('ReactionModel')) { $Rm = new ReactionModel(); if (Gdn::structure()->table('ReactionType')->columnExists('Hidden')) { $points = 3; if (c('QnA.Points.Enabled', false)) { $points = c('QnA.Points.AcceptedAnswer', 1); } // AcceptAnswer $Rm->defineReactionType(['UrlCode' => 'AcceptAnswer', 'Name' => 'Accept Answer', 'Sort' => 0, 'Class' => 'Positive', 'IncrementColumn' => 'Score', 'IncrementValue' => 5, 'Points' => $points, 'Permission' => 'Garden.Curation.Manage', 'Hidden' => 1, 'Description' => "When someone correctly answers a question, they are rewarded with this reaction."]); } Gdn::structure()->reset(); }
protected function PollFeed($FeedURL, $LastImportDate) { $Pr = new ProxyRequest(); $FeedRSS = $Pr->Request(array('URL' => $FeedURL)); if (!$FeedRSS) { return FALSE; } $RSSData = simplexml_load_string($FeedRSS); if (!$RSSData) { return FALSE; } $Channel = GetValue('channel', $RSSData, FALSE); if (!$Channel) { return FALSE; } if (!array_key_exists('item', $Channel)) { return FALSE; } $Feed = $this->GetFeed($FeedURL, FALSE); $DiscussionModel = new DiscussionModel(); $DiscussionModel->SpamCheck = FALSE; $LastPublishDate = GetValue('LastPublishDate', $Feed, date('c')); $LastPublishTime = strtotime($LastPublishDate); $FeedLastPublishTime = 0; foreach (GetValue('item', $Channel) as $Item) { $FeedItemGUID = trim((string) GetValue('guid', $Item)); if (empty($FeedItemGUID)) { Trace('guid is not set in each item of the RSS. Will attempt to use link as unique identifier.'); $FeedItemGUID = GetValue('link', $Item); } $FeedItemID = substr(md5($FeedItemGUID), 0, 30); $ItemPubDate = (string) GetValue('pubDate', $Item, NULL); if (is_null($ItemPubDate)) { $ItemPubTime = time(); } else { $ItemPubTime = strtotime($ItemPubDate); } if ($ItemPubTime > $FeedLastPublishTime) { $FeedLastPublishTime = $ItemPubTime; } if ($ItemPubTime < $LastPublishTime && !$Feed['Historical']) { continue; } $ExistingDiscussion = $DiscussionModel->GetWhere(array('ForeignID' => $FeedItemID)); if ($ExistingDiscussion && $ExistingDiscussion->NumRows()) { continue; } $this->EventArguments['Publish'] = TRUE; $this->EventArguments['FeedURL'] = $FeedURL; $this->EventArguments['Feed'] =& $Feed; $this->EventArguments['Item'] =& $Item; $this->FireEvent('FeedItem'); if (!$this->EventArguments['Publish']) { continue; } $StoryTitle = array_shift($Trash = explode("\n", (string) GetValue('title', $Item))); $StoryBody = (string) GetValue('description', $Item); $StoryPublished = date("Y-m-d H:i:s", $ItemPubTime); $ParsedStoryBody = $StoryBody; $ParsedStoryBody = '<div class="AutoFeedDiscussion">' . $ParsedStoryBody . '</div> <br /><div class="AutoFeedSource">Source: ' . $FeedItemGUID . '</div>'; $DiscussionData = array('Name' => $StoryTitle, 'Format' => 'Html', 'CategoryID' => $Feed['Category'], 'ForeignID' => substr($FeedItemID, 0, 30), 'Body' => $ParsedStoryBody); // Post as Minion (if one exists) or the system user if (Gdn::addonManager()->isEnabled('Minion', \Vanilla\Addon::TYPE_ADDON)) { $Minion = Gdn::PluginManager()->GetPluginInstance('MinionPlugin'); $InsertUserID = $Minion->GetMinionUserID(); } else { $InsertUserID = Gdn::UserModel()->GetSystemUserID(); } $DiscussionData[$DiscussionModel->DateInserted] = $StoryPublished; $DiscussionData[$DiscussionModel->InsertUserID] = $InsertUserID; $DiscussionData[$DiscussionModel->DateUpdated] = $StoryPublished; $DiscussionData[$DiscussionModel->UpdateUserID] = $InsertUserID; $this->EventArguments['FeedDiscussion'] =& $DiscussionData; $this->FireEvent('Publish'); if (!$this->EventArguments['Publish']) { continue; } $InsertID = $DiscussionModel->Save($DiscussionData); $this->EventArguments['DiscussionID'] = $InsertID; $this->EventArguments['Validation'] = $DiscussionModel->Validation; $this->FireEvent('Published'); // Reset discussion validation $DiscussionModel->Validation->Results(TRUE); } $FeedKey = self::EncodeFeedKey($FeedURL); $this->UpdateFeed($FeedKey, array('LastImport' => date('Y-m-d H:i:s'), 'LastPublishDate' => date('c', $FeedLastPublishTime))); }
/** * * * @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::addonManager()->lookupAddon('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; }
$CNotifications = is_numeric($CountNotifications) && $CountNotifications > 0 ? '<span class="Alert NotificationsAlert">' . $CountNotifications . '</span>' : ''; echo '<span class="ToggleFlyout" rel="/profile/notificationspopin">'; echo anchor(sprite('SpNotifications', 'Sprite Sprite16') . Wrap(t('Notifications'), 'em') . $CNotifications, userUrl($User), 'MeButton FlyoutButton js-clear-notifications', array('title' => t('Notifications'))); echo sprite('SpFlyoutHandle', 'Arrow'); echo '<div class="Flyout FlyoutMenu"></div></span>'; // Inbox if (Gdn::addonManager()->lookupAddon('conversations')) { $CountInbox = val('CountUnreadConversations', Gdn::session()->User); $CInbox = is_numeric($CountInbox) && $CountInbox > 0 ? ' <span class="Alert">' . $CountInbox . '</span>' : ''; echo '<span class="ToggleFlyout" rel="/messages/popin">'; echo anchor(sprite('SpInbox', 'Sprite Sprite16') . Wrap(t('Inbox'), 'em') . $CInbox, '/messages/all', 'MeButton FlyoutButton', array('title' => t('Inbox'))); echo sprite('SpFlyoutHandle', 'Arrow'); echo '<div class="Flyout FlyoutMenu"></div></span>'; } // Bookmarks if (Gdn::addonManager()->lookupAddon('Vanilla')) { echo '<span class="ToggleFlyout" rel="/discussions/bookmarkedpopin">'; echo anchor(sprite('SpBookmarks', 'Sprite Sprite16') . Wrap(t('Bookmarks'), 'em'), '/discussions/bookmarked', 'MeButton FlyoutButton', array('title' => t('Bookmarks'))); echo sprite('SpFlyoutHandle', 'Arrow'); echo '<div class="Flyout FlyoutMenu"></div></span>'; } // Profile Settings & Logout echo '<span class="ToggleFlyout">'; $CDashboard = $DashboardCount > 0 ? wrap($DashboardCount, 'span class="Alert"') : ''; echo anchor(sprite('SpOptions', 'Sprite Sprite16') . Wrap(t('Account Options'), 'em') . $CDashboard, '/profile/edit', 'MeButton FlyoutButton', array('title' => t('Account Options'))); echo sprite('SpFlyoutHandle', 'Arrow'); echo '<div class="Flyout MenuItems">'; echo '<ul>'; // echo wrap(Wrap(t('My Account'), 'strong'), 'li'); // echo wrap('<hr />', 'li'); if (hasEditProfile(Gdn::session()->UserID)) {
/** * Run the structure for all addons. * * The structure runs the addons in priority order so that higher priority addons override lower priority ones. * * @param bool $captureOnly Run the structure or just capture the SQL changes. * @throws Exception Throws an exception if in debug mode and something goes wrong. */ public function runStructure($captureOnly = false) { $addons = array_reverse(Gdn::addonManager()->getEnabled()); // These variables are required for included structure files. $Database = Gdn::database(); $SQL = $this->SQL; $SQL->CaptureModifications = $captureOnly; $Structure = Gdn::structure(); $Structure->CaptureOnly = $captureOnly; /* @var Addon $addon */ foreach ($addons as $addon) { // Look for a structure file. if ($structure = $addon->getSpecial('structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'file']); try { include $addon->path($structure); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } // Look for a structure method on the plugin. if ($addon->getPluginClass()) { $plugin = Gdn::pluginManager()->getPluginInstance($addon->getPluginClass(), Gdn_PluginManager::ACCESS_CLASSNAME); if (is_object($plugin) && method_exists($plugin, 'structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'method']); try { call_user_func([$plugin, 'structure']); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } } // Register permissions. $permissions = $addon->getInfoValue('registerPermissions'); if (!empty($permissions)) { Logger::event('addon_permissions', Logger::INFO, "Defining permissions for {addonKey}.", ['addonKey' => $addon->getKey(), 'permissions' => $permissions]); Gdn::permissionModel()->define($permissions); } } $this->fireEvent('AfterStructure'); if ($captureOnly && property_exists($Structure->Database, 'CapturedSql')) { return $Structure->Database->CapturedSql; } return []; }
<?php // Only show the vanilla pages if Vanilla is enabled $CurrentTarget = $this->data('CurrentTarget'); if (Gdn::addonManager()->isEnabled('Vanilla', \Vanilla\Addon::TYPE_ADDON)) { echo WriteHomepageOption('Discussions', 'discussions', 'disc-modern', $CurrentTarget); echo WriteHomepageOption('Categories', 'categories', 'cat-modern', $CurrentTarget); // echo WriteHomepageOption('Categories & Discussions', 'categories/discussions', 'categoriesdiscussions', $CurrentTarget); } //echo WriteHomepageOption('Activity', 'activity', 'SpActivity', $CurrentTarget); if (Gdn::addonManager()->isEnabled('Reactions', \Vanilla\Addon::TYPE_ADDON)) { echo WriteHomepageOption('Best Of', 'bestof', 'best-of', $CurrentTarget); } ?> </div> <?php if (Gdn::addonManager()->isEnabled('Vanilla', \Vanilla\Addon::TYPE_ADDON)) { ?> <?php echo subheading(t('Discussions Layout'), t('Choose the preferred layout for the discussions page.')); ?> <div class="LayoutOptions DiscussionsLayout label-selector"> <?php echo WriteHomepageOption('Modern Layout', 'modern', 'disc-modern', $CurrentDiscussionLayout, t('Modern non-table-based layout')); echo WriteHomepageOption('Table Layout', 'table', 'disc-table', $CurrentDiscussionLayout, t('Classic table layout used by traditional forums')); ?> </div> <?php echo subheading(t('Categories Layout'), t('Choose the preferred layout for the categories page.')); ?> <div class="LayoutOptions CategoriesLayout label-selector"> <?php
$bootstrapPath = $addon->path($bootstrapPath); include $bootstrapPath; } } // Themes startup Gdn::themeManager()->start(); // Plugins startup Gdn::pluginManager()->start(); /** * Locales * * Install any custom locales provided by applications and plugins, and set up * the locale management system. */ // Load the Garden locale system $gdnLocale = new Gdn_Locale(c('Garden.Locale', 'en'), Gdn::addonManager()); Gdn::factoryInstall(Gdn::AliasLocale, 'Gdn_Locale', null, Gdn::FactorySingleton, $gdnLocale); unset($gdnLocale); require_once PATH_LIBRARY_CORE . '/functions.validation.php'; // Start Authenticators Gdn::authenticator()->startAuthenticator(); /** * Bootstrap After * * After the bootstrap has finished loading, this hook allows developers a last * chance to customize Garden's runtime environment before the actual request * is handled. */ if (file_exists(PATH_ROOT . '/conf/bootstrap.after.php')) { require_once PATH_ROOT . '/conf/bootstrap.after.php'; }
/** * Get a version string for a given asset. * * @param string $destination The path of the asset. * @param string|null $version A known version for the asset or **null** to grab it from the addon's info array. * @return string Returns a version string. */ function assetVersion($destination, $version = null) { static $gracePeriod = 90; // Figure out which version to put after the asset. if (is_null($version)) { $version = APPLICATION_VERSION; if (preg_match('`^/([^/]+)/([^/]+)/`', $destination, $matches)) { $type = $matches[1]; $key = $matches[2]; static $themeVersion = null; switch ($type) { case 'plugins': case 'applications': $addon = Gdn::addonManager()->lookupAddon($key); if ($addon) { $version = $addon->getVersion(); } break; case 'themes': if ($themeVersion === null) { $theme = Gdn::addonManager()->lookupTheme(theme()); if ($theme) { $themeVersion = $theme->getVersion(); } } $version = $themeVersion; break; } } } // Add a timestamp component to the version if available. if ($timestamp = c('Garden.Deployed')) { $graced = $timestamp + $gracePeriod; if (time() >= $graced) { $timestamp = $graced; } $version .= '.' . dechex($timestamp); } return $version; }