/**
  *
  */
 public function renderMaster()
 {
     // Build the master view if necessary
     if (in_array($this->_DeliveryType, array(DELIVERY_TYPE_ALL))) {
         $this->MasterView = $this->masterView();
         // Only get css & ui components if this is NOT a syndication request
         if ($this->SyndicationMethod == SYNDICATION_NONE && is_object($this->Head)) {
             $CssAnchors = AssetModel::getAnchors();
             $this->EventArguments['CssFiles'] =& $this->_CssFiles;
             $this->fireEvent('BeforeAddCss');
             $ETag = AssetModel::eTag();
             $CombineAssets = c('Garden.CombineAssets');
             $ThemeType = isMobile() ? 'mobile' : 'desktop';
             // And now search for/add all css files.
             foreach ($this->_CssFiles as $CssInfo) {
                 $CssFile = $CssInfo['FileName'];
                 if (!array_key_exists('Options', $CssInfo) || !is_array($CssInfo['Options'])) {
                     $CssInfo['Options'] = array();
                 }
                 $Options =& $CssInfo['Options'];
                 // style.css and admin.css deserve some custom processing.
                 if (in_array($CssFile, $CssAnchors)) {
                     if (!$CombineAssets) {
                         // Grab all of the css files from the asset model.
                         $AssetModel = new AssetModel();
                         $CssFiles = $AssetModel->getCssFiles($ThemeType, ucfirst(substr($CssFile, 0, -4)), $ETag);
                         foreach ($CssFiles as $Info) {
                             $this->Head->addCss($Info[1], 'all', true, $CssInfo);
                         }
                     } else {
                         $Basename = substr($CssFile, 0, -4);
                         $this->Head->addCss(url("/asset/css/{$ThemeType}/{$Basename}-{$ETag}.css", '//'), 'all', false, $CssInfo['Options']);
                     }
                     continue;
                 }
                 $AppFolder = $CssInfo['AppFolder'];
                 $LookupFolder = !empty($AppFolder) ? $AppFolder : $this->ApplicationFolder;
                 $Search = AssetModel::CssPath($CssFile, $LookupFolder, $ThemeType);
                 if (!$Search) {
                     continue;
                 }
                 list($Path, $UrlPath) = $Search;
                 if (isUrl($Path)) {
                     $this->Head->AddCss($Path, 'all', val('AddVersion', $Options, true), $Options);
                     continue;
                 } else {
                     // Check to see if there is a CSS cacher.
                     $CssCacher = Gdn::factory('CssCacher');
                     if (!is_null($CssCacher)) {
                         $Path = $CssCacher->get($Path, $AppFolder);
                     }
                     if ($Path !== false) {
                         $Path = substr($Path, strlen(PATH_ROOT));
                         $Path = str_replace(DS, '/', $Path);
                         $this->Head->addCss($Path, 'all', true, $Options);
                     }
                 }
             }
             // Add a custom js file.
             if (arrayHasValue($this->_CssFiles, 'style.css')) {
                 $this->addJsFile('custom.js');
                 // only to non-admin pages.
             }
             $Cdns = array();
             if (!c('Garden.Cdns.Disable', false)) {
                 $Cdns = array('jquery.js' => "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js");
             }
             // And now search for/add all JS files.
             $this->EventArguments['Cdns'] =& $Cdns;
             $this->fireEvent('AfterJsCdns');
             $this->Head->addScript('', 'text/javascript', false, array('content' => $this->definitionList(false)));
             foreach ($this->_JsFiles as $Index => $JsInfo) {
                 $JsFile = $JsInfo['FileName'];
                 if (!is_array($JsInfo['Options'])) {
                     $JsInfo['Options'] = array();
                 }
                 $Options =& $JsInfo['Options'];
                 if (isset($Cdns[$JsFile])) {
                     $JsFile = $Cdns[$JsFile];
                 }
                 $AppFolder = $JsInfo['AppFolder'];
                 $LookupFolder = !empty($AppFolder) ? $AppFolder : $this->ApplicationFolder;
                 $Search = AssetModel::JsPath($JsFile, $LookupFolder, $ThemeType);
                 if (!$Search) {
                     continue;
                 }
                 list($Path, $UrlPath) = $Search;
                 if ($Path !== false) {
                     $AddVersion = true;
                     if (!isUrl($Path)) {
                         $Path = substr($Path, strlen(PATH_ROOT));
                         $Path = str_replace(DS, '/', $Path);
                         $AddVersion = val('AddVersion', $Options, true);
                     }
                     $this->Head->addScript($Path, 'text/javascript', $AddVersion, $Options);
                     continue;
                 }
             }
         }
         // Add the favicon.
         $Favicon = C('Garden.FavIcon');
         if ($Favicon) {
             $this->Head->setFavIcon(Gdn_Upload::url($Favicon));
         }
         // Make sure the head module gets passed into the assets collection.
         $this->addModule('Head');
     }
     // Master views come from one of four places:
     $MasterViewPaths = array();
     if (strpos($this->MasterView, '/') !== false) {
         $MasterViewPaths[] = combinePaths(array(PATH_ROOT, str_replace('/', DS, $this->MasterView) . '.master*'));
     } else {
         if ($this->Theme) {
             // 1. Application-specific theme view. eg. root/themes/theme_name/app_name/views/
             $MasterViewPaths[] = combinePaths(array(PATH_THEMES, $this->Theme, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
             // 2. Garden-wide theme view. eg. /path/to/application/themes/theme_name/views/
             $MasterViewPaths[] = combinePaths(array(PATH_THEMES, $this->Theme, 'views', $this->MasterView . '.master*'));
         }
         // 3. Plugin default. eg. root/plugin_name/views/
         $MasterViewPaths[] = combinePaths(array(PATH_ROOT, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
         // 4. Application default. eg. root/app_name/views/
         $MasterViewPaths[] = combinePaths(array(PATH_APPLICATIONS, $this->ApplicationFolder, 'views', $this->MasterView . '.master*'));
         // 5. Garden default. eg. root/dashboard/views/
         $MasterViewPaths[] = combinePaths(array(PATH_APPLICATIONS, 'dashboard', 'views', $this->MasterView . '.master*'));
     }
     // Find the first file that matches the path.
     $MasterViewPath = false;
     foreach ($MasterViewPaths as $Glob) {
         $Paths = safeGlob($Glob);
         if (is_array($Paths) && count($Paths) > 0) {
             $MasterViewPath = $Paths[0];
             break;
         }
     }
     $this->EventArguments['MasterViewPath'] =& $MasterViewPath;
     $this->fireEvent('BeforeFetchMaster');
     if ($MasterViewPath === false) {
         trigger_error(errorMessage("Could not find master view: {$this->MasterView}.master*", $this->ClassName, '_FetchController'), E_USER_ERROR);
     }
     /// A unique identifier that can be used in the body tag of the master view if needed.
     $ControllerName = $this->ClassName;
     // Strip "Controller" from the body identifier.
     if (substr($ControllerName, -10) == 'Controller') {
         $ControllerName = substr($ControllerName, 0, -10);
     }
     // Strip "Gdn_" from the body identifier.
     if (substr($ControllerName, 0, 4) == 'Gdn_') {
         $ControllerName = substr($ControllerName, 4);
     }
     $this->setData('CssClass', $this->Application . ' ' . $ControllerName . ' ' . $this->RequestMethod . ' ' . $this->CssClass, true);
     // Check to see if there is a handler for this particular extension.
     $ViewHandler = Gdn::factory('ViewHandler' . strtolower(strrchr($MasterViewPath, '.')));
     if (is_null($ViewHandler)) {
         $BodyIdentifier = strtolower($this->ApplicationFolder . '_' . $ControllerName . '_' . Gdn_Format::alphaNumeric(strtolower($this->RequestMethod)));
         include $MasterViewPath;
     } else {
         $ViewHandler->render($MasterViewPath, $this);
     }
 }
Exemple #2
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;
 }
 /**
  * Crawl the various addons and locales for all of the applicable translation files.
  *
  * @param string[] $applicationWhiteList An array of enabled application folders.
  * @param string[] $pluginWhiteList An array of enabled plugin folders.
  * @return array Returns an array keyed by locale names where each value is an array of translation paths for that locale.
  */
 public function crawlAllLocaleSources($applicationWhiteList, $pluginWhiteList)
 {
     $result = array();
     // Get all of the locale files for the applications.
     $this->crawlAddonLocaleSources(PATH_APPLICATIONS, $applicationWhiteList, $result);
     // Get locale-based locale definition files.
     $enabledLocales = C('EnabledLocales');
     if (is_array($enabledLocales)) {
         foreach ($enabledLocales as $localeKey => $locale) {
             $locale = self::canonicalize($locale);
             // Grab all of the files in the locale's folder.
             $translationPaths = safeGlob(PATH_ROOT . "/locales/{$localeKey}/*.php");
             foreach ($translationPaths as $translationPath) {
                 $result[$locale][] = $translationPath;
             }
         }
     }
     // Get all of the locale files for plugins.
     // Notice that the plugins are processed here so that they have overriding power.
     $this->crawlAddonLocaleSources(PATH_PLUGINS, $pluginWhiteList, $result);
     // Get theme-based locale definition files.
     $theme = C('Garden.Theme');
     if ($theme) {
         $this->crawlAddonLocaleSources(PATH_THEMES, array($theme), $result);
     }
     // Look for a global locale.
     $configLocale = PATH_CONF . '/locale.php';
     if (file_exists($configLocale)) {
         foreach (array_keys($result) as $locale) {
             $result[$locale][] = $configLocale;
         }
     }
     // Look for locale specific config locales.
     $paths = SafeGlob(PATH_CONF . '/locale-*.php');
     foreach ($paths as $path) {
         if (preg_match('`^locale-([\\w-]+)$`i', basename($path, '.php'), $matches)) {
             $locale = self::canonicalize($matches[1]);
             $result[$locale][] = $path;
         }
     }
     return $result;
 }
 /**
  *
  *
  * @param $Path
  * @param null $Skip
  * @return array
  */
 public function loadDefinitions($Path, $Skip = null)
 {
     $Skip = (array) $Skip;
     $Paths = safeGlob($Path . '/*.php');
     $Definition = array();
     foreach ($Paths as $Path) {
         if (in_array($Path, $Skip)) {
             continue;
         }
         include $Path;
     }
     return $Definition;
 }