예제 #1
0
파일: check.php 프로젝트: vanilla/community
/**
 *
 *
 * @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>';
}
예제 #2
0
 /**
  *
  *
  * @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;
 }
예제 #3
0
 /**
  * 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;
 }
예제 #4
0
 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;
 }
예제 #5
0
 /**
  *
  *
  * @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;
     }
 }
예제 #6
0
 /**
  * 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;
 }
예제 #7
0
 /**
  * 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();
 }
예제 #9
0
 /**
  *
  *
  * @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;
 }
예제 #10
0
 /**
  * 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;
 }
예제 #11
0
 /**
  * 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;
 }
예제 #12
0
 /**
  * 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;
 }
예제 #13
0
 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);
     }
 }
예제 #14
0
 /**
  * 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);
     }
 }
예제 #15
0
 /**
  * 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();
    }
예제 #17
0
  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 
  }
예제 #18
0
 /**
  * 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;
 }
예제 #19
0
 /**
  * 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']);
     }
 }
예제 #20
0
/**
 * 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);
}
예제 #21
0
 /**
  * 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();
 }
예제 #23
0
 /**
  * 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;
 }
예제 #24
0
 /**
  * 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;
 }
예제 #25
0
 /**
  * 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;
 }
예제 #26
0
 /**
  *
  *
  * @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;
 }
예제 #27
0
 /**
  * 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;
 }