/** * * * @param $Data */ function _checkTable($Data) { echo "<table class='Data' width='100%' style='table-layout: fixed;'>\n"; echo "<thead><tr><td width='20%'>Field</td><td width='45%'>Current</td><td width='35%'>File</td></tr></thead>"; $First = true; foreach ($Data as $Key => $Value) { if (stringBeginsWith($Key, 'File_') || is_array($Value) || $Key == 'Name') { continue; } $Value = Gdn_Format::html($Value); $FileValue = Gdn_Format::html(val('File_' . $Key, $Data)); if ($Key == 'MD5') { $Value = substr($Value, 0, 10); $FileValue = substr($FileValue, 0, 10); } if ($Key == 'FileSize') { $Value = Gdn_Upload::FormatFileSize($Value); } echo "<tr><td>{$Key}</td><td>{$Value}</td>"; if ($Error = val('File_Error', $Data)) { if ($First) { echo '<td rowspan="4">', htmlspecialchars($Error), '</td>'; } } else { echo "<td>{$FileValue}</td></tr>"; } echo "\n"; $First = false; } echo '</table>'; }
/** * * * @param $Provider * @param array $Options * @return string */ public static function connectButton($Provider, $Options = []) { if (!is_array($Provider)) { $Provider = self::getProvider($Provider); } $Url = htmlspecialchars(self::connectUrl($Provider)); $Data = $Provider; $Target = Gdn::request()->get('Target'); if (!$Target) { $Target = '/' . ltrim(Gdn::request()->path()); } if (stringBeginsWith($Target, '/entry/signin')) { $Target = '/'; } $ConnectQuery = ['client_id' => $Provider['AuthenticationKey'], 'Target' => $Target]; $Data['Target'] = urlencode(url('entry/jsconnect', true) . '?' . http_build_query($ConnectQuery)); $Data['Redirect'] = $Data['target'] = $Data['redirect'] = $Data['Target']; $SignInUrl = formatString(val('SignInUrl', $Provider, ''), $Data); $RegisterUrl = formatString(val('RegisterUrl', $Provider, ''), $Data); if ($RegisterUrl && !val('NoRegister', $Options)) { $RegisterLink = ' ' . anchor(sprintf(t('Register with %s', 'Register'), $Provider['Name']), $RegisterUrl, 'Button RegisterLink'); } else { $RegisterLink = ''; } if (val('NoConnectLabel', $Options)) { $ConnectLabel = ''; } else { $ConnectLabel = '<span class="Username"></span><div class="ConnectLabel TextColor">' . sprintf(t('Sign In with %s'), $Provider['Name']) . '</div>'; } if (!C('Plugins.JsConnect.NoGuestCheck')) { $Result = '<div style="display: none" class="JsConnect-Container ConnectButton Small UserInfo" rel="' . $Url . '">'; if (!val('IsDefault', $Provider)) { $Result .= '<div class="JsConnect-Guest">' . anchor(sprintf(t('Sign In with %s'), $Provider['Name']), $SignInUrl, 'Button Primary SignInLink') . $RegisterLink . '</div>'; } $Result .= '<div class="JsConnect-Connect"><a class="ConnectLink">' . img('https://images.v-cdn.net/usericon_50.png', ['class' => 'ProfilePhotoSmall UserPhoto']) . $ConnectLabel . '</a></div>'; $Result .= '</div>'; } else { if (!val('IsDefault', $Provider)) { $Result = '<div class="JsConnect-Guest">' . anchor(sprintf(t('Sign In with %s'), $Provider['Name']), $SignInUrl, 'Button Primary SignInLink') . $RegisterLink . '</div>'; } } return $Result; }
/** * Renders the banner logo, or just the banner title if the logo is not defined. * * @param array $Properties */ public static function logo($Properties = array()) { $Logo = C('Garden.Logo'); if ($Logo) { $Logo = ltrim($Logo, '/'); // Fix the logo path. if (stringBeginsWith($Logo, 'uploads/')) { $Logo = substr($Logo, strlen('uploads/')); } // Set optional title text. if (empty($Properties['title']) && C('Garden.LogoTitle')) { $Properties['title'] = C('Garden.LogoTitle'); } } // Use the site title as alt if none was given. $Title = C('Garden.Title', 'Title'); if (empty($Properties['alt'])) { $Properties['alt'] = $Title; } echo $Logo ? Img(Gdn_Upload::url($Logo), $Properties) : $Title; }
public function fetchPageInfo($Url, $ThrowError = false) { $PageInfo = FetchPageInfo($Url, 3, $ThrowError); $Title = val('Title', $PageInfo, ''); if ($Title == '') { if ($ThrowError) { throw new Gdn_UserException(t("The page didn't contain any information.")); } $Title = formatString(t('Undefined discussion subject.'), array('Url' => $Url)); } else { if ($Strip = c('Vanilla.Embed.StripPrefix')) { $Title = stringBeginsWith($Title, $Strip, true, true); } if ($Strip = c('Vanilla.Embed.StripSuffix')) { $Title = StringEndsWith($Title, $Strip, true, true); } } $Title = trim($Title); $Description = val('Description', $PageInfo, ''); $Images = val('Images', $PageInfo, array()); $Body = formatString(t('EmbeddedDiscussionFormat'), array('Title' => $Title, 'Excerpt' => $Description, 'Image' => count($Images) > 0 ? img(val(0, $Images), array('class' => 'LeftAlign')) : '', 'Url' => $Url)); if ($Body == '') { $Body = $Url; } if ($Body == '') { $Body = formatString(t('EmbeddedNoBodyFormat.'), array('Url' => $Url)); } $Result = array('Name' => $Title, 'Body' => $Body, 'Format' => 'Html'); return $Result; }
/** * * * @param $Url * @return bool|int|string */ public function reverseRoute($Url) { $Root = rtrim(Gdn::request()->domain() . '/' . Gdn::request()->webRoot(), '/'); if (stringBeginsWith($Url, $Root)) { $Url = stringBeginsWith($Url, $Root, true, true); $WithDomain = true; } else { $WithDomain = false; } $Url = '/' . ltrim($Url, '/'); foreach ($this->Routes as $Route => $RouteData) { if ($RouteData['Type'] != 'Internal' || $RouteData['Reserved'] && $RouteData['Route'] != 'DefaultController') { continue; } $Destination = '/' . ltrim($RouteData['Destination'], '/'); if ($Destination == $Url) { $Route = '/' . ltrim($RouteData['Route'], '/'); if ($Route == '/DefaultController') { $Route = '/'; } if ($WithDomain) { return $Root . $Route; } else { return $Route; } } } if ($WithDomain) { return $Root . $Url; } else { return $Url; } }
/** * Build a URL to an external site linked to this one. * * This function is used when an external site is configured with Vanilla in an embedding scenario. * * @param string $path The path within Vanilla. * @return string Returns the external URL. */ function externalUrl($path) { $urlFormat = c('Garden.ExternalUrlFormat'); if ($urlFormat && !isUrl($path)) { $result = sprintf($urlFormat, ltrim($path, '/')); } elseif (stringBeginsWith($path, '//')) { $result = Gdn::request()->scheme() . ':' . $path; } else { $result = Url($path, true); } return $result; }
/** * Crawl applications or plugins for its locale files. * * @param string $basePath The base path. Either the plugins or applications path. * @param string[] $folders The folders to crawl within the base path. * @param array $result The result array to put all the translation paths. */ protected function crawlAddonLocaleSources($basePath, $folders, &$result) { if (!is_array($folders)) { return; } $paths = array(); foreach ($folders as $folder) { $paths[] = $basePath . "/{$folder}/locale"; } // Get all of the locale files for the addons. foreach ($paths as $path) { // Look for individual locale files. $localePaths = safeGlob($path . '/*.php'); foreach ($localePaths as $localePath) { $locale = self::canonicalize(basename($localePath, '.php')); $result[$locale][] = $localePath; } // Look for locale files in a directory. // This should be deprecated very soon. $localePaths = safeGlob($path . '/*/definitions.php'); foreach ($localePaths as $localePath) { $locale = self::canonicalize(basename(dirname($localePath))); $result[$locale][] = $localePath; $subPath = stringBeginsWith($localePath, PATH_ROOT, true, true); $properPath = dirname($subPath) . '.php'; trigger_error("Locales in {$subPath} is deprecated. Use {$properPath} instead.", E_USER_DEPRECATED); } } }
/** * Banner management screen. * * @since 2.0.0 * @access public */ public function banner() { $this->permission('Garden.Community.Manage'); $this->addSideMenu('dashboard/settings/banner'); $this->title(t('Banner')); $Validation = new Gdn_Validation(); $ConfigurationModel = new Gdn_ConfigurationModel($Validation); $ConfigurationModel->setField(array('Garden.HomepageTitle' => c('Garden.Title'), 'Garden.Title', 'Garden.Description')); // Set the model on the form. $this->Form->setModel($ConfigurationModel); // Get the current logo. $Logo = c('Garden.Logo'); if ($Logo) { $Logo = ltrim($Logo, '/'); // Fix the logo path. if (stringBeginsWith($Logo, 'uploads/')) { $Logo = substr($Logo, strlen('uploads/')); } $this->setData('Logo', $Logo); } // Get the current mobile logo. $MobileLogo = c('Garden.MobileLogo'); if ($MobileLogo) { $MobileLogo = ltrim($MobileLogo, '/'); // Fix the logo path. if (stringBeginsWith($MobileLogo, 'uploads/')) { $MobileLogo = substr($MobileLogo, strlen('uploads/')); } $this->setData('MobileLogo', $MobileLogo); } // Get the current favicon. $Favicon = c('Garden.FavIcon'); $this->setData('Favicon', $Favicon); $ShareImage = c('Garden.ShareImage'); $this->setData('ShareImage', $ShareImage); // If seeing the form for the first time... if (!$this->Form->authenticatedPostBack()) { // Apply the config settings to the form. $this->Form->setData($ConfigurationModel->Data); } else { $SaveData = array(); if ($this->Form->save() !== false) { $Upload = new Gdn_Upload(); try { // Validate the upload $TmpImage = $Upload->validateUpload('Logo', false); if ($TmpImage) { // Generate the target image name $TargetImage = $Upload->generateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Delete any previously uploaded images. if ($Logo) { $Upload->delete($Logo); } // Save the uploaded image $Parts = $Upload->SaveAs($TmpImage, $ImageBaseName); $ImageBaseName = $Parts['SaveName']; $SaveData['Garden.Logo'] = $ImageBaseName; $this->setData('Logo', $ImageBaseName); } $TmpMobileImage = $Upload->validateUpload('MobileLogo', false); if ($TmpMobileImage) { // Generate the target image name $TargetImage = $Upload->generateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Delete any previously uploaded images. if ($MobileLogo) { $Upload->delete($MobileLogo); } // Save the uploaded image $Parts = $Upload->saveAs($TmpMobileImage, $ImageBaseName); $ImageBaseName = $Parts['SaveName']; $SaveData['Garden.MobileLogo'] = $ImageBaseName; $this->setData('MobileLogo', $ImageBaseName); } $ImgUpload = new Gdn_UploadImage(); $TmpFavicon = $ImgUpload->validateUpload('Favicon', false); if ($TmpFavicon) { $ICOName = 'favicon_' . substr(md5(microtime()), 16) . '.ico'; if ($Favicon) { $Upload->delete($Favicon); } // Resize the to a png. $Parts = $ImgUpload->SaveImageAs($TmpFavicon, $ICOName, 16, 16, array('OutputType' => 'ico', 'Crop' => true)); $SaveData['Garden.FavIcon'] = $Parts['SaveName']; $this->setData('Favicon', $Parts['SaveName']); } $TmpShareImage = $Upload->ValidateUpload('ShareImage', false); if ($TmpShareImage) { $TargetImage = $Upload->GenerateTargetName(PATH_UPLOADS, false); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); if ($ShareImage) { $Upload->delete($ShareImage); } $Parts = $Upload->SaveAs($TmpShareImage, $ImageBaseName); $SaveData['Garden.ShareImage'] = $Parts['SaveName']; $this->setData('ShareImage', $Parts['SaveName']); } } catch (Exception $ex) { $this->Form->addError($ex); } // If there were no errors, save the path to the logo in the config if ($this->Form->errorCount() == 0) { saveToConfig($SaveData); } $this->informMessage(t("Your settings have been saved.")); } } $this->render(); }
/** * * * @param $ThemeFile * @param null $VariableName * @return null|void */ public function scanThemeFile($ThemeFile, $VariableName = null) { // Find the $PluginInfo array if (!file_exists($ThemeFile)) { return; } $Lines = file($ThemeFile); $InfoBuffer = false; $ClassBuffer = false; $ClassName = ''; $ThemeInfoString = ''; if (!$VariableName) { $VariableName = 'ThemeInfo'; } $ParseVariableName = '$' . $VariableName; ${$VariableName} = array(); foreach ($Lines as $Line) { if ($InfoBuffer && substr(trim($Line), -2) == ');') { $ThemeInfoString .= $Line; $ClassBuffer = true; $InfoBuffer = false; } if (stringBeginsWith(trim($Line), $ParseVariableName)) { $InfoBuffer = true; } if ($InfoBuffer) { $ThemeInfoString .= $Line; } if ($ClassBuffer && strtolower(substr(trim($Line), 0, 6)) == 'class ') { $Parts = explode(' ', $Line); if (count($Parts) > 2) { $ClassName = $Parts[1]; } break; } } unset($Lines); if ($ThemeInfoString != '') { @eval($ThemeInfoString); } // Define the folder name and assign the class name for the newly added item if (isset(${$VariableName}) && is_array(${$VariableName})) { $Item = array_pop($Trash = array_keys(${$VariableName})); ${$VariableName}[$Item]['Index'] = $Item; ${$VariableName}[$Item]['AboutFile'] = $ThemeFile; ${$VariableName}[$Item]['RealAboutFile'] = realpath($ThemeFile); ${$VariableName}[$Item]['ThemeRoot'] = dirname($ThemeFile); if (!array_key_exists('Name', ${$VariableName}[$Item])) { ${$VariableName}[$Item]['Name'] = $Item; } if (!array_key_exists('Folder', ${$VariableName}[$Item])) { ${$VariableName}[$Item]['Folder'] = basename(dirname($ThemeFile)); } return ${$VariableName}[$Item]; } elseif ($VariableName !== null) { if (isset(${$VariableName})) { return ${$VariableName}; } } return null; }
/** * Resolve relative static resources into full paths * * This method is used to translate CSS, Js and Template relative file lists * into absolute paths. * * Element values should conform to the following format: * * [] => array( * 'FileName' => // filename (relative, absolute, or URL) * 'AppFolder' => // optional application folder to target (default controller app) * ); * * @param array $resourceList * @param string $stub * @param array $options Optional. List of check options. * - 'GlobalLibrary' // Check $Stub/library in global section * - 'StripRoot' // Strip PATH_ROOT from final results * - 'CDNS' // List of external CDN replacements * @param array $checkLocations Optional. List of locations to check. * - 'themes' * - 'plugins' * - 'applications' * - 'global' */ public static function resolveStaticResources($resourceList, $stub, $options = null, $checkLocations = null) { // All locations by default if (!is_array($checkLocations)) { $checkLocations = array('themes', 'plugins', 'applications', 'global'); } // Default options $defaultOptions = array('GlobalLibrary' => true, 'StripRoot' => true, 'CDNS' => array(), 'AutoVersion' => true); if (!is_array($options)) { $options = array(); } $options = array_merge($defaultOptions, $options); // Parse options $checkGlobalLibrary = val('GlobalLibrary', $options); $stripRoot = val('StripRoot', $options); $autoDetectVersion = val('AutoVersion', $options); // See if we're allowing any CDN replacements $CDNs = val('CDNS', $options, array()); // Pre-get controller info $controllerAppFolder = false; $controllerTheme = false; if (Gdn::Controller() instanceof Gdn_Controller) { $controllerAppFolder = Gdn::controller()->ApplicationFolder; $controllerTheme = Gdn::controller()->Theme; } $fileList = array(); foreach ($resourceList as $index => $resourceInfo) { $resourceFile = $resourceInfo['FileName']; $resourceFolder = val('AppFolder', $resourceInfo); $resourceOptions = (array) val('Options', $resourceInfo, false); if ($resourceFile === false) { if (!$resourceOptions) { continue; } $rawCSS = val('Css', $resourceOptions, false); if (!$rawCSS) { continue; } $cssHash = md5($rawCSS); $fileList[$resourceFolder] = array('options' => $resourceOptions); continue; } $skipFileCheck = false; // Resolve CDN resources if (array_key_exists($resourceFile, $CDNs)) { $resourceFile = $CDNs[$resourceFile]; } if (strpos($resourceFile, '//') !== false) { // This is a link to an external file. $skipFileCheck = true; $testPaths = array($resourceFile); } elseif (strpos($resourceFile, '/') === 0) { // A direct path to the file was given. $testPaths = array(paths(PATH_ROOT, $resourceFile)); } elseif (strpos($resourceFile, '~') === 0) { $skipFileCheck = true; $resourceFile = substr($resourceFile, 1); $testPaths = array(paths(PATH_ROOT, $resourceFile)); } else { // Relative path $appFolder = val('AppFolder', $resourceInfo, false); if ($appFolder == '') { $appFolder = $controllerAppFolder; } if ($appFolder == 'false') { $appFolder = false; } // Resources can come from: // - a theme // - an application // - a plugin // - global garden resource-specific folder // - global garden resource-specific library folder $testPaths = array(); // Theme if (in_array('themes', $checkLocations) && $controllerTheme) { // Application-specific theme override if ($appFolder) { $testPaths[] = paths(PATH_THEMES, $controllerTheme, $appFolder, $stub, $resourceFile); } // Garden-wide theme override $testPaths[] = paths(PATH_THEMES, $controllerTheme, $stub, $resourceFile); } // Application or plugin $isPluginFolder = stringBeginsWith(trim($appFolder, '/'), 'plugins/', true, false); if ($isPluginFolder) { $pluginFolder = stringBeginsWith(trim($appFolder, '/'), 'plugins/', true, true); } if (in_array('plugins', $checkLocations) && $isPluginFolder) { // Plugin $testPaths[] = paths(PATH_PLUGINS, $pluginFolder, $stub, $resourceFile); $testPaths[] = paths(PATH_PLUGINS, $pluginFolder, $resourceFile); } if (in_array('applications', $checkLocations) && !$isPluginFolder) { // Application if ($appFolder) { $testPaths[] = paths(PATH_APPLICATIONS, $appFolder, $stub, $resourceFile); } // Dashboard app is added by default if ($appFolder != 'dashboard') { $testPaths[] = paths(PATH_APPLICATIONS, 'dashboard', $stub, $resourceFile); } } if (in_array('global', $checkLocations)) { // Global folder. eg. root/js/ $testPaths[] = paths(PATH_ROOT, $stub, $resourceFile); if ($checkGlobalLibrary) { // Global library folder. eg. root/js/library/ $testPaths[] = paths(PATH_ROOT, $stub, 'library', $resourceFile); } } } // Find the first file that matches the path. $resourcePath = false; if (!$skipFileCheck) { foreach ($testPaths as $glob) { $paths = safeGlob($glob); if (is_array($paths) && count($paths) > 0) { $resourcePath = $paths[0]; break; } } // Get version $version = val('Version', $resourceInfo, false); // If a path was matched, make sure it has a version if ($resourcePath && !$version && $autoDetectVersion) { // Theme file if (!$version && preg_match('`themes/([^/]+)/`i', $resourcePath, $matches)) { $themeName = $matches[1]; $themeInfo = Gdn::themeManager()->getThemeInfo($themeName); $version = val('Version', $themeInfo); $versionSource = "theme {$themeName}"; } // Plugin file if (!$version && preg_match('`plugins/([^/]+)/`i', $resourcePath, $matches)) { $pluginName = $matches[1]; $pluginInfo = Gdn::pluginManager()->getPluginInfo($pluginName, Gdn_PluginManager::ACCESS_PLUGINNAME); $version = val('Version', $pluginInfo); $versionSource = "plugin {$pluginName}"; } // Application file if (!$version && preg_match('`applications/([^/]+)/`i', $resourcePath, $matches)) { $applicationName = $matches[1]; $applicationInfo = Gdn::applicationManager()->getApplicationInfo($applicationName); $version = val('Version', $applicationInfo); $versionSource = "app {$applicationName}"; } } } else { $version = null; } // Global file if (!$version) { $version = APPLICATION_VERSION; } // If a path was succesfully matched if ($resourcePath !== false || $skipFileCheck) { // We enact SkipFileCheck for virtual paths, targeting controllers // perhaps, or full URLs from the CDN resolver. if ($skipFileCheck) { $resourcePath = array_pop($testPaths); } // Strip PATH_ROOT from absolute path $resourceResolved = $resourcePath; if ($stripRoot) { $resourceResolved = str_replace(array(PATH_ROOT, DS), array('', '/'), $resourcePath); } // Bring options into response structure $resource = array('path' => $resourcePath); $resourceOptions = (array) val('Options', $resourceInfo, array()); touchValue('version', $resource, $version); if ($resourceOptions) { touchValue('options', $resource, $resourceOptions); } $fileList[$resourceResolved] = $resource; } } return $fileList; }
/** * Lookup the path to a JS file and return its info array * * @param string $filename name/relative path to js file * @param string $folder optional. app or plugin folder to search * @param string $themeType mobile or desktop * @return array|bool */ public static function jsPath($filename, $folder = '', $themeType = '') { if (!$themeType) { $themeType = isMobile() ? 'mobile' : 'desktop'; } // 1. Check for a url. if (isUrl($filename)) { return array($filename, $filename); } $paths = array(); // 2. Check for a full path. if (strpos($filename, '/') === 0) { $filename = ltrim($filename, '/'); // Direct path was given $filename = "/{$filename}"; $path = PATH_ROOT . $filename; if (file_exists($path)) { deprecated("AssetModel::JsPath() with direct paths"); return array($path, $filename); } return false; } // 3. Check the theme. $theme = Gdn::themeManager()->themeFromType($themeType); if ($theme) { $path = "/{$theme}/js/{$filename}"; $paths[] = array(PATH_THEMES . $path, "/themes{$path}"); } // 4. Static, Plugin, or App relative file if ($folder) { if (in_array($folder, array('resources', 'static'))) { $path = "/resources/js/{$filename}"; $paths[] = array(PATH_ROOT . $path, $path); // A plugin-relative path was given } elseif (stringBeginsWith($folder, 'plugins/')) { $folder = substr($folder, strlen('plugins/')); $path = "/{$folder}/js/{$filename}"; $paths[] = array(PATH_PLUGINS . $path, "/plugins{$path}"); // Allow direct-to-file links for plugins $paths[] = array(PATH_PLUGINS . "/{$folder}/{$filename}", "/plugins/{$folder}/{$filename}", true); // deprecated // An app-relative path was given } else { // App-relative path under the theme if ($theme) { $path = "/{$theme}/{$folder}/js/{$filename}"; $paths[] = array(PATH_THEMES . $path, "/themes{$path}"); } $path = "/{$folder}/js/{$filename}"; $paths[] = array(PATH_APPLICATIONS . $path, "/applications{$path}"); } } // 5. Check the global js folder. $paths[] = array(PATH_ROOT . "/js/{$filename}", "/js/{$filename}"); $paths[] = array(PATH_ROOT . "/js/library/{$filename}", "/js/library/{$filename}"); foreach ($paths as $info) { if (file_exists($info[0])) { if (!empty($info[2])) { // This path is deprecated. unset($info[2]); deprecated("The js file '{$filename}' in folder '{$folder}'"); } return $info; } } if (!stringEndsWith($filename, 'custom.js')) { trace("Could not find file '{$filename}' in folder '{$folder}'."); } return false; }
/** * Create a controller and initialize it with data from the dispatcher. * * @param string $controllerName The name of the controller to create. * @param Gdn_Request $request The current request. * @param array &$routeArgs Arguments from a call to {@link Gdn_Dispatcher::analyzeRequest}. * @return Gdn_Controller Returns a new {@link Gdn_Controller} object. */ private function createController($controllerName, $request, &$routeArgs) { /* @var Gdn_Controller $controller */ $controller = new $controllerName(); Gdn::controller($controller); $this->EventArguments['Controller'] =& $controller; $this->fireEvent('AfterControllerCreate'); // Pass along any assets if (is_array($this->controllerAssets)) { foreach ($this->controllerAssets as $AssetName => $Assets) { foreach ($Assets as $Asset) { $controller->addAsset($AssetName, $Asset); } } } // Instantiate Imported & Uses classes $controller->getImports(); // Pass along any objects foreach ($this->controllerProperties as $Name => $Mixed) { $controller->{$Name} = $Mixed; } // Pass along any data. if (!empty($this->controllerData)) { $controller->Data = $this->controllerData; } $controller->Request = $request; $controller->SelfUrl = $routeArgs['path']; /* @var Addon $addon */ $addon = $routeArgs['addon']; if ($addon) { $controller->Application = $addon->getKey(); $controller->ApplicationFolder = stringBeginsWith(ltrim($addon->getSubdir(), '/'), 'applications/', true, true); } $controller->Request = $request; $controller->deliveryType($routeArgs['deliveryType']); $controller->deliveryMethod($routeArgs['deliveryMethod']); $controller->SyndicationMethod = val('syndicationMethod', $routeArgs, SYNDICATION_NONE); $this->deliveryType = $routeArgs['deliveryType']; $this->deliveryMethod = $routeArgs['deliveryMethod']; // Kludge: We currently have a couple of plugins that modify the path arguments on initialize. $this->controllerArguments($routeArgs['pathArgs']); // End kludge. $controller->initialize(); // Kludge for controllers that modify the dispatcher. $pathArgs = $this->controllerArguments(); if (!empty($this->ControllerMethod)) { array_unshift($pathArgs, Gdn::Dispatcher()->ControllerMethod); } $routeArgs['pathArgs'] = $pathArgs; // End kluge. $this->EventArguments['Controller'] = $controller; $this->fireEvent('AfterControllerInit'); return $controller; }
public function _setBreadcrumbs($Name = null, $Url = null) { // Add the root link. if (val('UserID', $this->User) == Gdn::session()->UserID) { $Root = array('Name' => t('Profile'), 'Url' => '/profile'); $Breadcrumb = array('Name' => $Name, 'Url' => $Url); } else { $NameUnique = c('Garden.Registration.NameUnique'); $Root = array('Name' => val('Name', $this->User), 'Url' => userUrl($this->User)); $Breadcrumb = array('Name' => $Name, 'Url' => $Url . '/' . ($NameUnique ? '' : val('UserID', $this->User) . '/') . rawurlencode(val('Name', $this->User))); } $this->Data['Breadcrumbs'][] = $Root; if ($Name && !stringBeginsWith($Root['Url'], $Url)) { $this->Data['Breadcrumbs'][] = array('Name' => $Name, 'Url' => $Url); } }
/** * Execute a single validation rule and return its result. * * @param mixed $Value The value to validate. * @param string $FieldName The name of the field to put into the error result. * @param string|array $Rule The rule to validate which can be one of the following. * - string: The name of a function used to validate the value. * - 'regex:<regex>': The regular expression used to validate the value. * - array: An array with the following keys: * - Name: The name of the function used to validate. * - Args: An argument to pass to the function after the value. * @param string $CustomError A custom error message. * @return bool|string One of the following * - TRUE: The value passed validation. * - string: The error message associated with the error. */ public static function validateRule($Value, $FieldName, $Rule, $CustomError = false) { // Figure out the type of rule. if (is_string($Rule)) { if (stringBeginsWith($Rule, 'regex:', true)) { $RuleName = 'validateregex'; $Args = substr($Rule, 6); } elseif (stringBeginsWith($Rule, 'function:', true)) { $RuleName = substr($Rule, 9); } else { $RuleName = $Rule; } } elseif (is_array($Rule)) { $RuleName = val('Name', $Rule); $Args = val('Args', $Rule); } if (!isset($Args)) { $Args = null; } if (function_exists($RuleName)) { $Result = $RuleName($Value, $Args); if ($Result === true) { return true; } elseif ($CustomError) { return $CustomError; } elseif (is_string($Result)) { return $Result; } else { return sprintf(T($RuleName), T($FieldName)); } } else { return sprintf('Validation does not exist: %s.', $RuleName); } }
/** * Lookup the path to a CSS file and return its info array * * @param string $Filename name/relative path to css file * @param string $Folder optional. app or plugin folder to search * @param string $ThemeType mobile or desktop * @return array|bool */ public static function cssPath($Filename, $Folder = '', $ThemeType = '') { if (!$ThemeType) { $ThemeType = IsMobile() ? 'mobile' : 'desktop'; } // 1. Check for a url. if (IsUrl($Filename)) { return array($Filename, $Filename); } $Paths = array(); // 2. Check for a full path. if (strpos($Filename, '/') !== false) { $Filename = ltrim($Filename, '/'); // Direct path was given $Filename = "/{$Filename}"; $Path = PATH_ROOT . $Filename; if (file_exists($Path)) { Deprecated("AssetModel::CssPath() with direct paths"); return array($Path, $Filename); } return false; } // 3. Check the theme. $Theme = Gdn::ThemeManager()->ThemeFromType($ThemeType); if ($Theme) { $Path = "/{$Theme}/design/{$Filename}"; $Paths[] = array(PATH_THEMES . $Path, "/themes{$Path}"); } // 4. Static, Plugin, or App relative file if ($Folder) { if (in_array($Folder, array('resources', 'static'))) { $Path = "/resources/design/{$Filename}"; $Paths[] = array(PATH_ROOT . $Path, $Path); // A plugin-relative path was given } elseif (stringBeginsWith($Folder, 'plugins/')) { $Folder = substr($Folder, strlen('plugins/')); $Path = "/{$Folder}/design/{$Filename}"; $Paths[] = array(PATH_PLUGINS . $Path, "/plugins{$Path}"); // Allow direct-to-file links for plugins $Paths[] = array(PATH_PLUGINS . "/{$Folder}/{$Filename}", "/plugins/{$Folder}/{$Filename}", true); // deprecated // An app-relative path was given } else { $Path = "/{$Folder}/design/{$Filename}"; $Paths[] = array(PATH_APPLICATIONS . $Path, "/applications{$Path}"); } } // 5. Check the default application. if ($Folder != 'dashboard') { $Paths[] = array(PATH_APPLICATIONS . "/dashboard/design/{$Filename}", "/applications/dashboard/design/{$Filename}", true); // deprecated } foreach ($Paths as $Info) { if (file_exists($Info[0])) { if (!empty($Info[2])) { // This path is deprecated. unset($Info[2]); Deprecated("The css file '{$Filename}' in folder '{$Folder}'"); } return $Info; } } if (!(StringEndsWith($Filename, 'custom.css') || StringEndsWith($Filename, 'customadmin.css'))) { trace("Could not find file '{$Filename}' in folder '{$Folder}'."); } return false; }
/** * Alternate version of Index that uses the embed master view. * * @param int $DiscussionID Unique identifier, if discussion has been created. * @param string $DiscussionStub Deprecated. * @param int $Offset * @param int $Limit */ public function embed($DiscussionID = '', $DiscussionStub = '', $Offset = '', $Limit = '') { $this->title(t('Comments')); // Add theme data $this->Theme = c('Garden.CommentsTheme', $this->Theme); Gdn_Theme::section('Comments'); // Force view options $this->MasterView = 'empty'; $this->CanEditComments = false; // Don't show the comment checkboxes on the embed comments page // Add some css to help with the transparent bg on embedded comments if ($this->Head) { $this->Head->addString('<style type="text/css"> body { background: transparent !important; } </style>'); } // Javascript files & options $this->addJsFile('jquery.gardenmorepager.js'); $this->addJsFile('jquery.autosize.min.js'); $this->addJsFile('discussion.js'); $this->removeJsFile('autosave.js'); $this->addDefinition('DoInform', '0'); // Suppress inform messages on embedded page. $this->addDefinition('SelfUrl', Gdn::request()->PathAndQuery()); $this->addDefinition('Embedded', true); // Define incoming variables (prefer querystring parameters over method parameters) $DiscussionID = is_numeric($DiscussionID) && $DiscussionID > 0 ? $DiscussionID : 0; $DiscussionID = getIncomingValue('vanilla_discussion_id', $DiscussionID); $Offset = getIncomingValue('Offset', $Offset); $Limit = getIncomingValue('Limit', $Limit); $vanilla_identifier = getIncomingValue('vanilla_identifier', ''); // Only allow vanilla identifiers of 32 chars or less - md5 if larger if (strlen($vanilla_identifier) > 32) { $vanilla_identifier = md5($vanilla_identifier); } $vanilla_type = getIncomingValue('vanilla_type', 'page'); $vanilla_url = getIncomingValue('vanilla_url', ''); $vanilla_category_id = getIncomingValue('vanilla_category_id', ''); $ForeignSource = array('vanilla_identifier' => $vanilla_identifier, 'vanilla_type' => $vanilla_type, 'vanilla_url' => $vanilla_url, 'vanilla_category_id' => $vanilla_category_id); $this->setData('ForeignSource', $ForeignSource); // Set comment sorting $SortComments = c('Garden.Embed.SortComments') == 'desc' ? 'desc' : 'asc'; $this->setData('SortComments', $SortComments); // Retrieve the discussion record $Discussion = false; if ($DiscussionID > 0) { $Discussion = $this->DiscussionModel->getID($DiscussionID); } elseif ($vanilla_identifier != '' && $vanilla_type != '') { $Discussion = $this->DiscussionModel->GetForeignID($vanilla_identifier, $vanilla_type); } // Set discussion data if we have one for this page if ($Discussion) { // Allow Vanilla.Comments.View to be defined to limit access to embedded comments only. // Otherwise, go with normal discussion view permissions. Either will do. $this->permission(array('Vanilla.Discussions.View', 'Vanilla.Comments.View'), false, 'Category', $Discussion->PermissionCategoryID); $this->setData('Discussion', $Discussion, true); $this->setData('DiscussionID', $Discussion->DiscussionID, true); $this->title($Discussion->Name); // Actual number of comments, excluding the discussion itself $ActualResponses = $Discussion->CountComments; // Define the query offset & limit if (!is_numeric($Limit) || $Limit < 0) { $Limit = c('Garden.Embed.CommentsPerPage', 30); } $OffsetProvided = $Offset != ''; list($Offset, $Limit) = offsetLimit($Offset, $Limit); $this->Offset = $Offset; if (c('Vanilla.Comments.AutoOffset')) { if ($ActualResponses <= $Limit) { $this->Offset = 0; } if ($this->Offset == $ActualResponses) { $this->Offset -= $Limit; } } elseif ($this->Offset == '') { $this->Offset = 0; } if ($this->Offset < 0) { $this->Offset = 0; } // Set the canonical url to have the proper page title. $this->canonicalUrl(discussionUrl($Discussion, pageNumber($this->Offset, $Limit))); // Load the comments. $CurrentOrderBy = $this->CommentModel->orderBy(); if (stringBeginsWith(GetValueR('0.0', $CurrentOrderBy), 'c.DateInserted')) { $this->CommentModel->orderBy('c.DateInserted ' . $SortComments); // allow custom sort } $this->setData('Comments', $this->CommentModel->get($Discussion->DiscussionID, $Limit, $this->Offset), true); if (count($this->CommentModel->where()) > 0) { $ActualResponses = false; } $this->setData('_Count', $ActualResponses); // Build a pager $PagerFactory = new Gdn_PagerFactory(); $this->EventArguments['PagerType'] = 'MorePager'; $this->fireEvent('BeforeBuildPager'); $this->Pager = $PagerFactory->getPager($this->EventArguments['PagerType'], $this); $this->Pager->ClientID = 'Pager'; $this->Pager->MoreCode = 'More Comments'; $this->Pager->configure($this->Offset, $Limit, $ActualResponses, 'discussion/embed/' . $Discussion->DiscussionID . '/' . Gdn_Format::url($Discussion->Name) . '/%1$s'); $this->Pager->CurrentRecords = $this->Comments->numRows(); $this->fireEvent('AfterBuildPager'); } // Define the form for the comment input $this->Form = Gdn::Factory('Form', 'Comment'); $this->Form->Action = url('/post/comment/'); $this->Form->addHidden('CommentID', ''); $this->Form->addHidden('Embedded', 'true'); // Tell the post controller that this is an embedded page (in case there are custom views it needs to pick up from a theme). $this->Form->addHidden('DisplayNewCommentOnly', 'true'); // Only load/display the new comment after posting (don't load all new comments since the page last loaded). // Grab the page title if ($this->Request->get('title')) { $this->Form->setValue('Name', $this->Request->get('title')); } // Set existing DiscussionID for comment form if ($Discussion) { $this->Form->addHidden('DiscussionID', $Discussion->DiscussionID); } foreach ($ForeignSource as $Key => $Val) { // Drop the foreign source information into the form so it can be used if creating a discussion $this->Form->addHidden($Key, $Val); // Also drop it into the definitions so it can be picked up for stashing comments $this->addDefinition($Key, $Val); } // Retrieve & apply the draft if there is one: $Draft = false; if (Gdn::session()->UserID && $Discussion) { $DraftModel = new DraftModel(); $Draft = $DraftModel->get(Gdn::session()->UserID, 0, 1, $Discussion->DiscussionID)->firstRow(); $this->Form->addHidden('DraftID', $Draft ? $Draft->DraftID : ''); } if ($Draft) { $this->Form->setFormValue('Body', $Draft->Body); } else { // Look in the session stash for a comment $StashComment = Gdn::session()->getPublicStash('CommentForForeignID_' . $ForeignSource['vanilla_identifier']); if ($StashComment) { $this->Form->setValue('Body', $StashComment); $this->Form->setFormValue('Body', $StashComment); } } // Deliver JSON data if necessary if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { if ($this->Discussion) { $this->setJson('LessRow', $this->Pager->toString('less')); $this->setJson('MoreRow', $this->Pager->toString('more')); } $this->View = 'comments'; } // Ordering note for JS if ($SortComments == 'desc') { $this->addDefinition('PrependNewComments', '1'); } // Report the discussion id so js can use it. if ($Discussion) { $this->addDefinition('DiscussionID', $Discussion->DiscussionID); } $this->fireEvent('BeforeDiscussionRender'); $this->render(); }
function writeDiscussionSorter($Selected = null, $Options = null) { if ($Selected === null) { $Selected = Gdn::session()->GetPreference('Discussions.SortField', 'DateLastComment'); } $Selected = stringBeginsWith($Selected, 'd.', TRUE, true); $Options = array('DateLastComment' => t('Sort by Last Comment', 'by Last Comment'), 'DateInserted' => t('Sort by Start Date', 'by Start Date')); ?> <span class="ToggleFlyout SelectFlyout"> <?php if (isset($Options[$Selected])) { $Text = $Options[$Selected]; } else { $Text = reset($Options); } echo wrap($Text . ' ' . Sprite('', 'DropHandle'), 'span', array('class' => 'Selected')); ?> <div class="Flyout MenuItems"> <ul> <?php foreach ($Options as $SortField => $SortText) { echo wrap(Anchor($SortText, '#', array('class' => 'SortDiscussions', 'data-field' => $SortField)), 'li'); } ?> </ul> </div> </span> <?php }
/** * Deprecated. * * @param string $ThemeFile The path to the theme file. * @param string $VariableName The name of the theme info variable name. * @return null|array Returns the theme info. * @deprecated */ private function scanThemeFileOld($ThemeFile, $VariableName = '') { // Find the $PluginInfo array if (!file_exists($ThemeFile)) { return null; } $Lines = file($ThemeFile); $InfoBuffer = false; $ClassBuffer = false; $ClassName = ''; $ThemeInfoString = ''; if (!$VariableName) { $VariableName = 'ThemeInfo'; } $ParseVariableName = '$' . $VariableName; ${$VariableName} = array(); foreach ($Lines as $Line) { if ($InfoBuffer && substr(trim($Line), -2) == ');') { $ThemeInfoString .= $Line; $ClassBuffer = true; $InfoBuffer = false; } if (stringBeginsWith(trim($Line), $ParseVariableName)) { $InfoBuffer = true; } if ($InfoBuffer) { $ThemeInfoString .= $Line; } if ($ClassBuffer && strtolower(substr(trim($Line), 0, 6)) == 'class ') { $Parts = explode(' ', $Line); if (count($Parts) > 2) { $ClassName = $Parts[1]; } break; } } unset($Lines); if ($ThemeInfoString != '') { @eval($ThemeInfoString); } // Define the folder name and assign the class name for the newly added item. $var = ${$VariableName}; if (isset($var) && is_array($var)) { reset($var); $name = key($var); $var = current($var); $var['Index'] = $name; $var['AboutFile'] = $ThemeFile; $var['RealAboutFile'] = realpath($ThemeFile); $var['ThemeRoot'] = dirname($ThemeFile); touchValue('Name', $var, $name); touchValue('Folder', $var, basename(dirname($ThemeFile))); return $var; } elseif ($VariableName !== null) { if (isset($var)) { return $var; } } return null; }
/** * Set the emoji from a manifest. * * @param array $manifest An emoji manifest with the following keys: * - emoji: An array in the form: name => filename (ex. ['smile' => 'smile.png']) * - aliases (optional): An array of emoji short forms: alias => emojiName (ex. [':)' => 'smile']) * - editor (optional): An array of emoji that will display in the editor: emojiName (ex: [smile,..]) * - format (optional): The string format of the emoji replacement. * @param string $assetPath The asset path root to all of the emoji files. */ public function setFromManifest($manifest, $assetPath = '') { // Set the default asset root. if ($assetPath) { $this->setAssetPath(stringBeginsWith($assetPath, PATH_ROOT, true, true)); } // Set the emoji settings from the manifest. if (array_key_exists('emoji', $manifest)) { $this->setEmoji($manifest['emoji']); } if (array_key_exists('aliases', $manifest)) { $this->setAliases($manifest['aliases']); } else { $this->checkAliases(); } if (array_key_exists('archive', $manifest)) { $this->setArchive($manifest['archive']); } else { $this->setArchive(array()); } if (!empty($manifest['format'])) { $this->format = $manifest['format']; } if (array_key_exists('editor', $manifest)) { $this->setEditorList($manifest['editor']); } }
/** * Create a new permission exception. This is a convenience function that will create an exception with a standard message. * * @param string|null $Permission The name of the permission that was required. * @return Exception */ function forbiddenException($Resource = null) { if (!$Resource) { $Message = t('ForbiddenErrorMessage', "You are not allowed to do that."); } elseif (stringBeginsWith($Resource, '@')) { $Message = stringBeginsWith($Resource, '@', true, true); } else { $Message = sprintf(t('You are not allowed to %s.'), $Resource); } return new Gdn_UserException($Message, 403); }
/** * Calls the appropriate registration method based on the configuration setting. * * Events: Register * * @access public * @since 2.0.0 * * @param string $InvitationCode Unique code given to invited user. */ public function register($InvitationCode = '') { if (!$this->Request->isPostBack()) { $this->checkOverride('Register', $this->target()); } $this->fireEvent("Register"); $this->Form->setModel($this->UserModel); // Define gender dropdown options $this->GenderOptions = array('u' => t('Unspecified'), 'm' => t('Male'), 'f' => t('Female')); // Make sure that the hour offset for new users gets defined when their account is created $this->addJsFile('entry.js'); $this->Form->addHidden('ClientHour', date('Y-m-d H:00')); // Use the server's current hour as a default $this->Form->addHidden('Target', $this->target()); $this->setData('NoEmail', UserModel::noEmail()); $RegistrationMethod = $this->_registrationView(); $this->View = $RegistrationMethod; $this->setData('Method', stringBeginsWith($RegistrationMethod, 'Register', false, true)); $this->{$RegistrationMethod}($InvitationCode); }
/** * Connect the user with an external source. * * This controller method is meant to be used with plugins that set its data array to work. * Events: ConnectData * * @since 2.0.0 * @access public * * @param string $Method Used to register multiple providers on ConnectData event. */ public function connect($Method) { $this->addJsFile('entry.js'); $this->View = 'connect'; $IsPostBack = $this->Form->isPostBack() && $this->Form->getFormValue('Connect', null) !== null; $UserSelect = $this->Form->getFormValue('UserSelect'); if (!$IsPostBack) { // Here are the initial data array values. that can be set by a plugin. $Data = array('Provider' => '', 'ProviderName' => '', 'UniqueID' => '', 'FullName' => '', 'Name' => '', 'Email' => '', 'Photo' => '', 'Target' => $this->target()); $this->Form->setData($Data); $this->Form->addHidden('Target', $this->Request->get('Target', '/')); } // The different providers can check to see if they are being used and modify the data array accordingly. $this->EventArguments = array($Method); // Fire ConnectData event & error handling. $currentData = $this->Form->formValues(); // Filter the form data for users here. SSO plugins must reset validated data each postback. $filteredData = Gdn::userModel()->filterForm($currentData, true); $filteredData = array_replace($filteredData, arrayTranslate($currentData, ['TransientKey', 'hpt'])); unset($filteredData['Roles'], $filteredData['RoleID']); $this->Form->formValues($filteredData); try { $this->EventArguments['Form'] = $this->Form; $this->fireEvent('ConnectData'); $this->fireEvent('AfterConnectData'); } catch (Gdn_UserException $Ex) { $this->Form->addError($Ex); return $this->render('ConnectError'); } catch (Exception $Ex) { if (Debug()) { $this->Form->addError($Ex); } else { $this->Form->addError('There was an error fetching the connection data.'); } return $this->render('ConnectError'); } if (!UserModel::noEmail()) { if (!$this->Form->getFormValue('Email') || $this->Form->getFormValue('EmailVisible')) { $this->Form->setFormValue('EmailVisible', true); $this->Form->addHidden('EmailVisible', true); if ($IsPostBack) { $this->Form->setFormValue('Email', val('Email', $currentData)); } } } $FormData = $this->Form->formValues(); // debug // Make sure the minimum required data has been provided to the connect. if (!$this->Form->getFormValue('Provider')) { $this->Form->addError('ValidateRequired', t('Provider')); } if (!$this->Form->getFormValue('UniqueID')) { $this->Form->addError('ValidateRequired', t('UniqueID')); } if (!$this->data('Verified')) { // Whatever event handler catches this must Set the data 'Verified' to true to prevent a random site from connecting without credentials. // This must be done EVERY postback and is VERY important. $this->Form->addError('The connection data has not been verified.'); } if ($this->Form->errorCount() > 0) { return $this->render(); } $UserModel = Gdn::userModel(); // Check to see if there is an existing user associated with the information above. $Auth = $UserModel->getAuthentication($this->Form->getFormValue('UniqueID'), $this->Form->getFormValue('Provider')); $UserID = val('UserID', $Auth); // Check to synchronise roles upon connecting. if (($this->data('Trusted') || c('Garden.SSO.SyncRoles')) && $this->Form->getFormValue('Roles', null) !== null) { $SaveRoles = $SaveRolesRegister = true; // Translate the role names to IDs. $Roles = $this->Form->getFormValue('Roles', null); $Roles = RoleModel::getByName($Roles); $RoleIDs = array_keys($Roles); if (empty($RoleIDs)) { // The user must have at least one role. This protects that. $RoleIDs = $this->UserModel->newUserRoleIDs(); } if (c('Garden.SSO.SyncRolesBehavior') === 'register') { $SaveRoles = false; } $this->Form->setFormValue('RoleID', $RoleIDs); } else { $SaveRoles = false; $SaveRolesRegister = false; } if ($UserID) { // The user is already connected. $this->Form->setFormValue('UserID', $UserID); if (c('Garden.Registration.ConnectSynchronize', true)) { $User = Gdn::userModel()->getID($UserID, DATASET_TYPE_ARRAY); $Data = $this->Form->formValues(); // Don't overwrite the user photo if the user uploaded a new one. $Photo = val('Photo', $User); if (!val('Photo', $Data) || $Photo && !isUrl($Photo)) { unset($Data['Photo']); } // Synchronize the user's data. $UserModel->save($Data, array('NoConfirmEmail' => true, 'FixUnique' => true, 'SaveRoles' => $SaveRoles)); } // Always save the attributes because they may contain authorization information. if ($Attributes = $this->Form->getFormValue('Attributes')) { $UserModel->saveAttribute($UserID, $Attributes); } // Sign the user in. Gdn::session()->start($UserID, true, (bool) $this->Form->getFormValue('RememberMe', true)); Gdn::userModel()->fireEvent('AfterSignIn'); // $this->_setRedirect(TRUE); $this->_setRedirect($this->Request->get('display') == 'popup'); } elseif ($this->Form->getFormValue('Name') || $this->Form->getFormValue('Email')) { $NameUnique = c('Garden.Registration.NameUnique', true); $EmailUnique = c('Garden.Registration.EmailUnique', true); $AutoConnect = c('Garden.Registration.AutoConnect'); if ($IsPostBack && $this->Form->getFormValue('ConnectName')) { $searchName = $this->Form->getFormValue('ConnectName'); } else { $searchName = $this->Form->getFormValue('Name'); } // Get the existing users that match the name or email of the connection. $Search = false; if ($searchName && $NameUnique) { $UserModel->SQL->orWhere('Name', $searchName); $Search = true; } if ($this->Form->getFormValue('Email') && ($EmailUnique || $AutoConnect)) { $UserModel->SQL->orWhere('Email', $this->Form->getFormValue('Email')); $Search = true; } if (is_numeric($UserSelect)) { $UserModel->SQL->orWhere('UserID', $UserSelect); $Search = true; } if ($Search) { $ExistingUsers = $UserModel->getWhere()->resultArray(); } else { $ExistingUsers = array(); } // Check to automatically link the user. if ($AutoConnect && count($ExistingUsers) > 0) { if ($IsPostBack && $this->Form->getFormValue('ConnectName')) { $this->Form->setFormValue('Name', $this->Form->getFormValue('ConnectName')); } foreach ($ExistingUsers as $Row) { if (strcasecmp($this->Form->getFormValue('Email'), $Row['Email']) === 0) { $UserID = $Row['UserID']; $this->Form->setFormValue('UserID', $UserID); $Data = $this->Form->formValues(); if (c('Garden.Registration.ConnectSynchronize', true)) { // Don't overwrite a photo if the user has already uploaded one. $Photo = val('Photo', $Row); if (!val('Photo', $Data) || $Photo && !stringBeginsWith($Photo, 'http')) { unset($Data['Photo']); } $UserModel->save($Data, array('NoConfirmEmail' => true, 'FixUnique' => true, 'SaveRoles' => $SaveRoles)); } if ($Attributes = $this->Form->getFormValue('Attributes')) { $UserModel->saveAttribute($UserID, $Attributes); } // Save the userauthentication link. $UserModel->saveAuthentication(array('UserID' => $UserID, 'Provider' => $this->Form->getFormValue('Provider'), 'UniqueID' => $this->Form->getFormValue('UniqueID'))); // Sign the user in. Gdn::session()->start($UserID, true, (bool) $this->Form->getFormValue('RememberMe', true)); Gdn::userModel()->fireEvent('AfterSignIn'); // $this->_setRedirect(TRUE); $this->_setRedirect($this->Request->get('display') == 'popup'); $this->render(); return; } } } $CurrentUserID = Gdn::session()->UserID; // Massage the existing users. foreach ($ExistingUsers as $Index => $UserRow) { if ($EmailUnique && $UserRow['Email'] == $this->Form->getFormValue('Email')) { $EmailFound = $UserRow; break; } if ($UserRow['Name'] == $this->Form->getFormValue('Name')) { $NameFound = $UserRow; } if ($CurrentUserID > 0 && $UserRow['UserID'] == $CurrentUserID) { unset($ExistingUsers[$Index]); $CurrentUserFound = true; } } if (isset($EmailFound)) { // The email address was found and can be the only user option. $ExistingUsers = array($UserRow); $this->setData('NoConnectName', true); } elseif (isset($CurrentUserFound)) { $ExistingUsers = array_merge(array('UserID' => 'current', 'Name' => sprintf(t('%s (Current)'), Gdn::session()->User->Name)), $ExistingUsers); } if (!isset($NameFound) && !$IsPostBack) { $this->Form->setFormValue('ConnectName', $this->Form->getFormValue('Name')); } $this->setData('ExistingUsers', $ExistingUsers); if (UserModel::noEmail()) { $EmailValid = true; } else { $EmailValid = validateRequired($this->Form->getFormValue('Email')); } if ((!$UserSelect || $UserSelect == 'other') && $this->Form->getFormValue('Name') && $EmailValid && (!is_array($ExistingUsers) || count($ExistingUsers) == 0)) { // There is no existing user with the suggested name so we can just create the user. $User = $this->Form->formValues(); $User['Password'] = randomString(50); // some password is required $User['HashMethod'] = 'Random'; $User['Source'] = $this->Form->getFormValue('Provider'); $User['SourceID'] = $this->Form->getFormValue('UniqueID'); $User['Attributes'] = $this->Form->getFormValue('Attributes', null); $User['Email'] = $this->Form->getFormValue('ConnectEmail', $this->Form->getFormValue('Email', null)); $UserID = $UserModel->register($User, array('CheckCaptcha' => false, 'ValidateEmail' => false, 'NoConfirmEmail' => true, 'SaveRoles' => $SaveRolesRegister)); $User['UserID'] = $UserID; $this->Form->setValidationResults($UserModel->validationResults()); if ($UserID) { $UserModel->saveAuthentication(array('UserID' => $UserID, 'Provider' => $this->Form->getFormValue('Provider'), 'UniqueID' => $this->Form->getFormValue('UniqueID'))); $this->Form->setFormValue('UserID', $UserID); $this->Form->setFormValue('UserSelect', false); Gdn::session()->start($UserID, true, (bool) $this->Form->getFormValue('RememberMe', true)); Gdn::userModel()->fireEvent('AfterSignIn'); // Send the welcome email. if (c('Garden.Registration.SendConnectEmail', false)) { try { $UserModel->sendWelcomeEmail($UserID, '', 'Connect', array('ProviderName' => $this->Form->getFormValue('ProviderName', $this->Form->getFormValue('Provider', 'Unknown')))); } catch (Exception $Ex) { // Do nothing if emailing doesn't work. } } $this->_setRedirect(true); } } } // Save the user's choice. if ($IsPostBack) { // The user has made their decision. $PasswordHash = new Gdn_PasswordHash(); if (!$UserSelect || $UserSelect == 'other') { // The user entered a username. $ConnectNameEntered = true; if ($this->Form->validateRule('ConnectName', 'ValidateRequired')) { $ConnectName = $this->Form->getFormValue('ConnectName'); $User = false; if (c('Garden.Registration.NameUnique')) { // Check to see if there is already a user with the given name. $User = $UserModel->getWhere(array('Name' => $ConnectName))->firstRow(DATASET_TYPE_ARRAY); } if (!$User) { $this->Form->validateRule('ConnectName', 'ValidateUsername'); } } } else { // The user selected an existing user. $ConnectNameEntered = false; if ($UserSelect == 'current') { if (Gdn::session()->UserID == 0) { // This shouldn't happen, but a use could sign out in another browser and click submit on this form. $this->Form->addError('@You were unexpectedly signed out.'); } else { $UserSelect = Gdn::session()->UserID; } } $User = $UserModel->getID($UserSelect, DATASET_TYPE_ARRAY); } if (isset($User) && $User) { // Make sure the user authenticates. if (!$User['UserID'] == Gdn::session()->UserID) { if ($this->Form->validateRule('ConnectPassword', 'ValidateRequired', sprintf(t('ValidateRequired'), t('Password')))) { try { if (!$PasswordHash->checkPassword($this->Form->getFormValue('ConnectPassword'), $User['Password'], $User['HashMethod'], $this->Form->getFormValue('ConnectName'))) { if ($ConnectNameEntered) { $this->Form->addError('The username you entered has already been taken.'); } else { $this->Form->addError('The password you entered is incorrect.'); } } } catch (Gdn_UserException $Ex) { $this->Form->addError($Ex); } } } } elseif ($this->Form->errorCount() == 0) { // The user doesn't exist so we need to add another user. $User = $this->Form->formValues(); $User['Name'] = $User['ConnectName']; $User['Password'] = randomString(50); // some password is required $User['HashMethod'] = 'Random'; $UserID = $UserModel->register($User, array('CheckCaptcha' => false, 'NoConfirmEmail' => true, 'SaveRoles' => $SaveRolesRegister)); $User['UserID'] = $UserID; $this->Form->setValidationResults($UserModel->validationResults()); if ($UserID && c('Garden.Registration.SendConnectEmail', false)) { // Send the welcome email. $UserModel->sendWelcomeEmail($UserID, '', 'Connect', array('ProviderName' => $this->Form->getFormValue('ProviderName', $this->Form->getFormValue('Provider', 'Unknown')))); } } if ($this->Form->errorCount() == 0) { // Save the authentication. if (isset($User) && val('UserID', $User)) { $UserModel->saveAuthentication(array('UserID' => $User['UserID'], 'Provider' => $this->Form->getFormValue('Provider'), 'UniqueID' => $this->Form->getFormValue('UniqueID'))); $this->Form->setFormValue('UserID', $User['UserID']); } // Sign the appropriate user in. Gdn::session()->start($this->Form->getFormValue('UserID'), true, (bool) $this->Form->getFormValue('RememberMe', true)); Gdn::userModel()->fireEvent('AfterSignIn'); $this->_setRedirect(true); } } $this->render(); }
/** * Fetches the location of a view into a string and returns it. Returns * false on failure. * * @param string $View The name of the view to fetch. If not specified, it will use the value * of $this->View. If $this->View is not specified, it will use the value * of $this->RequestMethod (which is defined by the dispatcher class). * @param string $ControllerName The name of the controller that owns the view if it is not $this. * - If the controller name is FALSE then the name of the current controller will be used. * - If the controller name is an empty string then the view will be looked for in the base views folder. * @param string $ApplicationFolder The name of the application folder that contains the requested controller if it is not $this->ApplicationFolder. */ public function fetchViewLocation($View = '', $ControllerName = false, $ApplicationFolder = false, $ThrowError = true) { // Accept an explicitly defined view, or look to the method that was called on this controller if ($View == '') { $View = $this->View; } if ($View == '') { $View = $this->RequestMethod; } if ($ControllerName === false) { $ControllerName = $this->ControllerName; } if (StringEndsWith($ControllerName, 'controller', true)) { $ControllerName = substr($ControllerName, 0, -10); } if (strtolower(substr($ControllerName, 0, 4)) == 'gdn_') { $ControllerName = substr($ControllerName, 4); } if (!$ApplicationFolder) { $ApplicationFolder = $this->ApplicationFolder; } //$ApplicationFolder = strtolower($ApplicationFolder); $ControllerName = strtolower($ControllerName); if (strpos($View, DS) === false) { // keep explicit paths as they are. $View = strtolower($View); } // If this is a syndication request, append the method to the view if ($this->SyndicationMethod == SYNDICATION_ATOM) { $View .= '_atom'; } elseif ($this->SyndicationMethod == SYNDICATION_RSS) { $View .= '_rss'; } $LocationName = concatSep('/', strtolower($ApplicationFolder), $ControllerName, $View); $ViewPath = val($LocationName, $this->_ViewLocations, false); if ($ViewPath === false) { // Define the search paths differently depending on whether or not we are in a plugin or application. $ApplicationFolder = trim($ApplicationFolder, '/'); if (stringBeginsWith($ApplicationFolder, 'plugins/')) { $KeyExplode = explode('/', $ApplicationFolder); $PluginName = array_pop($KeyExplode); $PluginInfo = Gdn::pluginManager()->getPluginInfo($PluginName); $BasePath = val('SearchPath', $PluginInfo); $ApplicationFolder = val('Folder', $PluginInfo); } else { $BasePath = PATH_APPLICATIONS; $ApplicationFolder = strtolower($ApplicationFolder); } $SubPaths = array(); // Define the subpath for the view. // The $ControllerName used to default to '' instead of FALSE. // This extra search is added for backwards-compatibility. if (strlen($ControllerName) > 0) { $SubPaths[] = "views/{$ControllerName}/{$View}"; } else { $SubPaths[] = "views/{$View}"; $SubPaths[] = 'views/' . stringEndsWith($this->ControllerName, 'Controller', true, true) . "/{$View}"; } // Views come from one of four places: $ViewPaths = array(); // 1. An explicitly defined path to a view if (strpos($View, DS) !== false && stringBeginsWith($View, PATH_ROOT)) { $ViewPaths[] = $View; } if ($this->Theme) { // 2. Application-specific theme view. eg. /path/to/application/themes/theme_name/app_name/views/controller_name/ foreach ($SubPaths as $SubPath) { $ViewPaths[] = PATH_THEMES . "/{$this->Theme}/{$ApplicationFolder}/{$SubPath}.*"; // $ViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, $ApplicationFolder, 'views', $ControllerName, $View . '.*')); } // 3. Garden-wide theme view. eg. /path/to/application/themes/theme_name/views/controller_name/ foreach ($SubPaths as $SubPath) { $ViewPaths[] = PATH_THEMES . "/{$this->Theme}/{$SubPath}.*"; //$ViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, 'views', $ControllerName, $View . '.*')); } } // 4. Application/plugin default. eg. /path/to/application/app_name/views/controller_name/ foreach ($SubPaths as $SubPath) { $ViewPaths[] = "{$BasePath}/{$ApplicationFolder}/{$SubPath}.*"; //$ViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, $ApplicationFolder, 'views', $ControllerName, $View . '.*')); } // Find the first file that matches the path. $ViewPath = false; foreach ($ViewPaths as $Glob) { $Paths = safeGlob($Glob); if (is_array($Paths) && count($Paths) > 0) { $ViewPath = $Paths[0]; break; } } //$ViewPath = Gdn_FileSystem::Exists($ViewPaths); $this->_ViewLocations[$LocationName] = $ViewPath; } // echo '<div>['.$LocationName.'] RETURNS ['.$ViewPath.']</div>'; if ($ViewPath === false && $ThrowError) { Gdn::dispatcher()->passData('ViewPaths', $ViewPaths); throw NotFoundException('View'); // trigger_error(ErrorMessage("Could not find a '$View' view for the '$ControllerName' controller in the '$ApplicationFolder' application.", $this->ClassName, 'FetchViewLocation'), E_USER_ERROR); } return $ViewPath; }
/** * Get the path to a view. * * @param string $view the name of the view. * @param string $controller the name of the controller invoking the view or blank. * @param string $folder the application folder or plugins/<plugin> folder. * @param array|null $extensions optional. list of extensions to allow * @return string|false The path to the view or false if it wasn't found. */ public static function viewLocation($view, $controller, $folder, $extensions = null) { $paths = []; // If the first character is a forward slash, this is an absolute path if (strpos($view, '/') === 0) { // This is a path to the view from the root. $paths[] = $view; } else { $view = strtolower($view); // Trim "controller" from the end of controller name, if its there $controller = strtolower(stringEndsWith($controller, 'Controller', true, true)); if ($controller) { $controller = '/' . $controller; } // Get list of permitted view extensions if (is_null($extensions)) { $extensions = AssetModel::viewExtensions(); } // 1. Gather paths from the theme, if enabled if (Gdn::controller() instanceof Gdn_Controller) { $theme = Gdn::controller()->Theme; if ($theme) { foreach ($extensions as $ext) { $paths[] = PATH_THEMES . "/{$theme}/views{$controller}/{$view}.{$ext}"; } } } // 2a. Gather paths from the plugin, if the folder is a plugin folder if (stringBeginsWith($folder, 'plugins/')) { // This is a plugin view. foreach ($extensions as $ext) { $paths[] = PATH_ROOT . "/{$folder}/views{$controller}/{$view}.{$ext}"; } // 2b. Gather paths from the application as a fallback } else { // This is an application view. $folder = strtolower($folder); foreach ($extensions as $ext) { $paths[] = PATH_APPLICATIONS . "/{$folder}/views{$controller}/{$view}.{$ext}"; } if ($folder != 'dashboard' && stringEndsWith($view, '.master')) { // This is a master view that can always fall back to the dashboard. foreach ($extensions as $ext) { $paths[] = PATH_APPLICATIONS . "/dashboard/views{$controller}/{$view}.{$ext}"; } } } } // Now let's search the paths for the view. foreach ($paths as $path) { if (file_exists($path)) { return $path; } } trace(['view' => $view, 'controller' => $controller, 'folder' => $folder], 'View'); trace($paths, __METHOD__); return false; }
/** * Retries UserMeta information for a UserID / Key pair. * * This method takes a $UserID or array of $UserIDs, and a $Key. It converts the * $Key to fully qualified format and then queries for the associated value(s). $Key * can contain SQL wildcards, in which case multiple results can be returned. * * If $UserID is an array, the return value will be a multi dimensional array with the first * axis containing UserIDs and the second containing fully qualified UserMetaKeys, associated with * their values. * * If $UserID is a scalar, the return value will be a single dimensional array of $UserMetaKey => $Value * pairs. * * @param int $UserID UserID or array of UserIDs. * @param string $Key Relative user meta key. * @param string $Prefix * @param string $Default * @return array results or $Default */ public static function getMeta($UserID, $Key, $Prefix = '', $Default = '') { $Sql = Gdn::sql()->select('*')->from('UserMeta u'); if (is_array($UserID)) { $Sql->whereIn('u.UserID', $UserID); } else { $Sql->where('u.UserID', $UserID); } if (strpos($Key, '%') !== false) { $Sql->like('u.Name', $Key, 'none'); } else { $Sql->where('u.Name', $Key); } $Data = $Sql->get()->resultArray(); if (is_array($UserID)) { $Result = array_fill_keys($UserID, []); } else { if (strpos($Key, '%') === false) { $Result = [stringBeginsWith($Key, $Prefix, false, true) => $Default]; } else { $Result = []; } } foreach ($Data as $Row) { $Name = stringBeginsWith($Row['Name'], $Prefix, false, true); if (is_array($UserID)) { $Result[$Row['UserID']][$Name] = $Row['Value']; } else { $Result[$Name] = $Row['Value']; } } return $Result; }
/** * * * @param $Source * @param $Target * @param array $Options * @return array|bool * @throws Exception */ public function saveAs($Source, $Target, $Options = array()) { $this->EventArguments['Path'] = $Source; $Parsed = self::parse($Target); $this->EventArguments['Parsed'] =& $Parsed; $this->EventArguments['Options'] = $Options; $Handled = false; $this->EventArguments['Handled'] =& $Handled; $this->fireAs('Gdn_Upload')->fireEvent('SaveAs'); // Check to see if the event handled the save. if (!$Handled) { $Target = PATH_UPLOADS . '/' . $Parsed['Name']; if (!file_exists(dirname($Target))) { mkdir(dirname($Target)); } if (stringBeginsWith($Source, PATH_UPLOADS)) { rename($Source, $Target); } elseif (!move_uploaded_file($Source, $Target)) { throw new Exception(sprintf(t('Failed to move uploaded file to target destination (%s).'), $Target)); } } return $Parsed; }
/** * Offers a quick and dirty way of parsing an addon's info array without using eval(). * * @param string $Path The path to the info array. * @param string $Variable The name of variable containing the information. * @return array|false The info array or false if the file could not be parsed. */ public static function parseInfoArray($Path, $Variable = false) { $fp = fopen($Path, 'rb'); $Lines = array(); $InArray = false; // Get all of the lines in the info array. while (($Line = fgets($fp)) !== false) { // Remove comments from the line. $Line = preg_replace('`\\s//.*$`', '', $Line); if (!$Line) { continue; } if (!$InArray && preg_match('`\\$([A-Za-z]+Info)\\s*\\[`', trim($Line), $Matches)) { $Variable = $Matches[1]; if (preg_match('`\\[\\s*[\'"](.+?)[\'"]\\s*\\]`', $Line, $Matches)) { $GlobalKey = $Matches[1]; $InArray = true; } } elseif ($InArray && StringEndsWith(trim($Line), ';')) { break; } elseif ($InArray) { $Lines[] = trim($Line); } } fclose($fp); if (count($Lines) == 0) { return false; } // Parse the name/value information in the arrays. $Result = array(); foreach ($Lines as $Line) { // Get the name from the line. if (!preg_match('`[\'"](.+?)[\'"]\\s*=>`', $Line, $Matches) || !substr($Line, -1) == ',') { continue; } $Key = $Matches[1]; // Strip the key from the line. $Line = trim(trim(substr(strstr($Line, '=>'), 2)), ','); if (strlen($Line) == 0) { continue; } $Value = null; if (is_numeric($Line)) { $Value = $Line; } elseif (strcasecmp($Line, 'TRUE') == 0 || strcasecmp($Line, 'FALSE') == 0) { $Value = $Line; } elseif (in_array($Line[0], array('"', "'")) && substr($Line, -1) == $Line[0]) { $Quote = $Line[0]; $Value = trim($Line, $Quote); $Value = str_replace('\\' . $Quote, $Quote, $Value); } elseif (stringBeginsWith($Line, 'array(') && substr($Line, -1) == ')') { // Parse the line's array. $Line = substr($Line, 6, strlen($Line) - 7); $Items = explode(',', $Line); $Array = array(); foreach ($Items as $Item) { $SubItems = explode('=>', $Item); if (count($SubItems) == 1) { $Array[] = trim(trim($SubItems[0]), '"\''); } elseif (count($SubItems) == 2) { $SubKey = trim(trim($SubItems[0]), '"\''); $SubValue = trim(trim($SubItems[1]), '"\''); $Array[$SubKey] = $SubValue; } } $Value = $Array; } if ($Value != null) { $Result[$Key] = $Value; } } $Result = array($GlobalKey => $Result, 'Variable' => $Variable); return $Result; }
/** * Set user preference for sorting discussions. */ public function sort($Target = '') { if (!Gdn::session()->isValid()) { throw permissionException(); } if (!$this->Request->isAuthenticatedPostBack()) { throw forbiddenException('GET'); } // Get param $SortField = Gdn::request()->Post('DiscussionSort'); $SortField = 'd.' . stringBeginsWith($SortField, 'd.', true, true); // Use whitelist here too to keep database clean if (!in_array($SortField, DiscussionModel::AllowedSortFields())) { throw new Gdn_UserException("Unknown sort {$SortField}."); } // Set user pref Gdn::userModel()->SavePreference(Gdn::session()->UserID, 'Discussions.SortField', $SortField); if ($Target) { redirect($Target); } // Send sorted discussions. $this->deliveryMethod(DELIVERY_METHOD_JSON); $this->render(); }
/** * Main import page. * * @since 2.0.0 * @access public */ public function index() { $this->permission('Garden.Import'); // This permission doesn't exist, so only users with Admin == '1' will succeed. $Timer = new Gdn_Timer(); // Determine the current step. $this->Form = new Gdn_Form(); $Imp = new ImportModel(); $Imp->loadState(); // Search for the list of acceptable imports. $ImportPaths = array(); $ExistingPaths = SafeGlob(PATH_UPLOADS . '/export*', array('gz', 'txt')); $ExistingPaths2 = SafeGlob(PATH_UPLOADS . '/porter/export*', array('gz')); $ExistingPaths = array_merge($ExistingPaths, $ExistingPaths2); foreach ($ExistingPaths as $Path) { $ImportPaths[$Path] = basename($Path); } // Add the database as a path. $ImportPaths = array_merge(array('db:' => t('This Database')), $ImportPaths); if ($Imp->CurrentStep < 1) { // Check to see if there is a file. $ImportPath = c('Garden.Import.ImportPath'); $Validation = new Gdn_Validation(); if (strcasecmp(Gdn::request()->requestMethod(), 'post') == 0) { $Upload = new Gdn_Upload(); $Validation = new Gdn_Validation(); if (count($ImportPaths) > 0) { $Validation->applyRule('PathSelect', 'Required', t('You must select a file to import.')); } if (count($ImportPaths) == 0 || $this->Form->getFormValue('PathSelect') == 'NEW') { $TmpFile = $Upload->ValidateUpload('ImportFile', false); } else { $TmpFile = ''; } if ($TmpFile) { $Filename = $_FILES['ImportFile']['name']; $Extension = pathinfo($Filename, PATHINFO_EXTENSION); $TargetFolder = PATH_ROOT . DS . 'uploads' . DS . 'import'; if (!file_exists($TargetFolder)) { mkdir($TargetFolder, 0777, true); } $ImportPath = $Upload->GenerateTargetName(PATH_ROOT . DS . 'uploads' . DS . 'import', $Extension); $Upload->SaveAs($TmpFile, $ImportPath); $Imp->ImportPath = $ImportPath; $this->Form->setFormValue('PathSelect', $ImportPath); $UploadedFiles = val('UploadedFiles', $Imp->Data); $UploadedFiles[$ImportPath] = basename($Filename); $Imp->Data['UploadedFiles'] = $UploadedFiles; } elseif ($PathSelect = $this->Form->getFormValue('PathSelect')) { if ($PathSelect == 'NEW') { $Validation->addValidationResult('ImportFile', 'ValidateRequired'); } else { $Imp->ImportPath = $PathSelect; } } elseif (!$Imp->ImportPath && count($ImportPaths) == 0) { // There was no file uploaded this request or before. $Validation->addValidationResult('ImportFile', $Upload->Exception); } // Validate the overwrite. if (true || strcasecmp($this->Form->getFormValue('Overwrite'), 'Overwrite') == 0) { if (!stringBeginsWith($this->Form->getFormValue('PathSelect'), 'Db:', true)) { $Validation->applyRule('Email', 'Required'); } } if ($Validation->validate($this->Form->formValues())) { $this->Form->setFormValue('Overwrite', 'overwrite'); $Imp->fromPost($this->Form->formValues()); $this->View = 'Info'; } else { $this->Form->setValidationResults($Validation->results()); } } else { $this->Form->setFormValue('PathSelect', $Imp->ImportPath); } $Imp->saveState(); } else { $this->setData('Steps', $Imp->steps()); $this->View = 'Info'; } if (!stringBeginsWith($Imp->ImportPath, 'db:') && !file_exists($Imp->ImportPath)) { $Imp->deleteState(); } try { $UploadedFiles = val('UploadedFiles', $Imp->Data, array()); $ImportPaths = array_merge($ImportPaths, $UploadedFiles); $this->setData('ImportPaths', $ImportPaths); $this->setData('Header', $Imp->getImportHeader()); $this->setData('Stats', val('Stats', $Imp->Data, array())); $this->setData('GenerateSQL', val('GenerateSQL', $Imp->Data)); $this->setData('ImportPath', $Imp->ImportPath); $this->setData('OriginalFilename', val('OriginalFilename', $Imp->Data)); $this->setData('CurrentStep', $Imp->CurrentStep); $this->setData('LoadSpeedWarning', $Imp->loadTableType(false) == 'LoadTableWithInsert'); } catch (Gdn_UserException $Ex) { $this->Form->addError($Ex); $Imp->saveState(); $this->View = 'Index'; } $this->render(); }
/** * Run a query, replacing database prefixes. * * @param string $Sql The sql to execute. * - :_z will be replaced by the import prefix. * - :_ will be replaced by the database prefix. * @param array $Parameters PDO parameters to pass to the query. * @return Gdn_DataSet */ public function query($Sql, $Parameters = null) { $Db = Gdn::database(); // Replace db prefixes. $Sql = str_replace(array(':_z', ':_'), array($Db->DatabasePrefix . self::TABLE_PREFIX, $Db->DatabasePrefix), $Sql); // Figure out the type of the type of the query. if (stringBeginsWith($Sql, 'select')) { $Type = 'select'; } elseif (stringBeginsWith($Sql, 'truncate')) { $Type = 'truncate'; } elseif (stringBeginsWith($Sql, 'insert')) { $Type = 'insert'; } elseif (stringBeginsWith($Sql, 'update')) { $Type = 'update'; } elseif (stringBeginsWith($Sql, 'delete')) { $Type = 'delete'; } else { $Type = 'select'; } // Execute the query. if (is_array($Parameters)) { $this->SQL->namedParameters($Parameters); } $Result = $this->SQL->query($Sql, $Type); //$this->Timer->Split('Sql: '. str_replace("\n", "\n ", $Sql)); return $Result; }