/** * Undocumented method. * * @todo Method RenderMaster() needs a description. */ public function RenderMaster() { // Build the master view if necessary if (in_array($this->_DeliveryType, array(DELIVERY_TYPE_ALL))) { $this->MasterView = $this->MasterView(); // Only get css & ui components if this is NOT a syndication request if ($this->SyndicationMethod == SYNDICATION_NONE && is_object($this->Head)) { // if (ArrayHasValue($this->_CssFiles, 'style.css')) { // $this->AddCssFile('custom.css'); // // // Add the theme option's css file. // if ($this->Theme && $this->ThemeOptions) { // $Filenames = GetValueR('Styles.Value', $this->ThemeOptions); // if (is_string($Filenames) && $Filenames != '%s') // $this->_CssFiles[] = array('FileName' => ChangeBasename('custom.css', $Filenames), 'AppFolder' => FALSE, 'Options' => FALSE); // } // } elseif (ArrayHasValue($this->_CssFiles, 'admin.css')) { // $this->AddCssFile('customadmin.css'); // } $this->EventArguments['CssFiles'] =& $this->_CssFiles; $this->FireEvent('BeforeAddCss'); $ETag = AssetModel::ETag(); $CombineAssets = C('Garden.CombineAssets'); $ThemeType = IsMobile() ? 'mobile' : 'desktop'; // And now search for/add all css files. foreach ($this->_CssFiles as $CssInfo) { $CssFile = $CssInfo['FileName']; // style.css and admin.css deserve some custom processing. if (in_array($CssFile, array('style.css', 'admin.css'))) { if (!$CombineAssets) { // Grab all of the css files from the asset model. $AssetModel = new AssetModel(); $CssFiles = $AssetModel->GetCssFiles($ThemeType, ucfirst(substr($CssFile, 0, -4)), $ETag); foreach ($CssFiles as $Info) { $this->Head->AddCss($Info[1], 'all', TRUE, $CssInfo); } } else { $Basename = substr($CssFile, 0, -4); $this->Head->AddCss(Url("/utility/css/{$ThemeType}/{$Basename}-{$ETag}.css", '//'), 'all', FALSE, $CssInfo['Options']); } continue; } if (StringBeginsWith($CssFile, 'http')) { $this->Head->AddCss($CssFile, 'all', GetValue('AddVersion', $CssInfo, TRUE), $CssInfo['Options']); continue; } elseif (strpos($CssFile, '/') !== FALSE) { // A direct path to the file was given. $CssPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $CssFile)))); } else { // $CssGlob = preg_replace('/(.*)(\.css)/', '\1*\2', $CssFile); $AppFolder = $CssInfo['AppFolder']; if ($AppFolder == '') { $AppFolder = $this->ApplicationFolder; } // CSS comes from one of four places: $CssPaths = array(); if ($this->Theme) { // Use the default filename. $CssPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'design' . DS . $CssFile; } // 3. Application or plugin. if (StringBeginsWith($AppFolder, 'plugins/')) { // The css is coming from a plugin. $AppFolder = substr($AppFolder, strlen('plugins/')); $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/design/{$CssFile}"; $CssPaths[] = PATH_PLUGINS . "/{$AppFolder}/{$CssFile}"; } elseif (in_array($AppFolder, array('static', 'resources'))) { // This is a static css file. $CssPaths[] = PATH_ROOT . "/resources/css/{$CssFile}"; } else { // Application default. eg. root/applications/app_name/design/ $CssPaths[] = PATH_APPLICATIONS . DS . $AppFolder . DS . 'design' . DS . $CssFile; } // 4. Garden default. eg. root/applications/dashboard/design/ $CssPaths[] = PATH_APPLICATIONS . DS . 'dashboard' . DS . 'design' . DS . $CssFile; } // Find the first file that matches the path. $CssPath = FALSE; foreach ($CssPaths as $Glob) { $Paths = SafeGlob($Glob); if (is_array($Paths) && count($Paths) > 0) { $CssPath = $Paths[0]; break; } } // Check to see if there is a CSS cacher. $CssCacher = Gdn::Factory('CssCacher'); if (!is_null($CssCacher)) { $CssPath = $CssCacher->Get($CssPath, $AppFolder); } if ($CssPath !== FALSE) { $CssPath = substr($CssPath, strlen(PATH_ROOT)); $CssPath = str_replace(DS, '/', $CssPath); $this->Head->AddCss($CssPath, 'all', TRUE, $CssInfo['Options']); } } // Add a custom js file. if (ArrayHasValue($this->_CssFiles, 'style.css')) { $this->AddJsFile('custom.js'); } // only to non-admin pages. // And now search for/add all JS files. $Cdns = array(); if (Gdn::Request()->Scheme() != 'https' && !C('Garden.Cdns.Disable', FALSE)) { $Cdns = array('jquery.js' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'); } $this->EventArguments['Cdns'] =& $Cdns; $this->FireEvent('AfterJsCdns'); foreach ($this->_JsFiles as $Index => $JsInfo) { $JsFile = $JsInfo['FileName']; if (isset($Cdns[$JsFile])) { $JsFile = $Cdns[$JsFile]; } if (strpos($JsFile, '//') !== FALSE) { // This is a link to an external file. $this->Head->AddScript($JsFile, 'text/javascript', GetValue('Options', $JsInfo, array())); continue; } elseif (strpos($JsFile, '/') !== FALSE) { // A direct path to the file was given. $JsPaths = array(CombinePaths(array(PATH_ROOT, str_replace('/', DS, $JsFile)), DS)); } else { $AppFolder = $JsInfo['AppFolder']; if ($AppFolder == '') { $AppFolder = $this->ApplicationFolder; } // JS can come from a theme, an any of the application folder, or it can come from the global js folder: $JsPaths = array(); if ($this->Theme) { // 1. Application-specific js. eg. root/themes/theme_name/app_name/design/ $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . $AppFolder . DS . 'js' . DS . $JsFile; // 2. Garden-wide theme view. eg. root/themes/theme_name/design/ $JsPaths[] = PATH_THEMES . DS . $this->Theme . DS . 'js' . DS . $JsFile; } // 3. The application or plugin folder. if (StringBeginsWith(trim($AppFolder, '/'), 'plugins/')) { $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/js/{$JsFile}"; $JsPaths[] = PATH_PLUGINS . strstr($AppFolder, '/') . "/{$JsFile}"; } else { $JsPaths[] = PATH_APPLICATIONS . "/{$AppFolder}/js/{$JsFile}"; } // 4. Global JS folder. eg. root/js/ $JsPaths[] = PATH_ROOT . DS . 'js' . DS . $JsFile; // 5. Global JS library folder. eg. root/js/library/ $JsPaths[] = PATH_ROOT . DS . 'js' . DS . 'library' . DS . $JsFile; } // Find the first file that matches the path. $JsPath = FALSE; foreach ($JsPaths as $Glob) { $Paths = SafeGlob($Glob); if (is_array($Paths) && count($Paths) > 0) { $JsPath = $Paths[0]; break; } } if ($JsPath !== FALSE) { $JsSrc = str_replace(array(PATH_ROOT, DS), array('', '/'), $JsPath); $Options = (array) $JsInfo['Options']; $Options['path'] = $JsPath; $Version = GetValue('Version', $JsInfo); if ($Version) { TouchValue('version', $Options, $Version); } $this->Head->AddScript($JsSrc, 'text/javascript', $Options); } } } // Add the favicon. $Favicon = C('Garden.FavIcon'); if ($Favicon) { $this->Head->SetFavIcon(Gdn_Upload::Url($Favicon)); } // Make sure the head module gets passed into the assets collection. $this->AddModule('Head'); } // Master views come from one of four places: $MasterViewPaths = array(); $MasterViewPath2 = ViewLocation($this->MasterView() . '.master', '', $this->ApplicationFolder); if (strpos($this->MasterView, '/') !== FALSE) { $MasterViewPaths[] = CombinePaths(array(PATH_ROOT, str_replace('/', DS, $this->MasterView) . '.master*')); } else { if ($this->Theme) { // 1. Application-specific theme view. eg. root/themes/theme_name/app_name/views/ $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, $this->ApplicationFolder, 'views', $this->MasterView . '.master*')); // 2. Garden-wide theme view. eg. /path/to/application/themes/theme_name/views/ $MasterViewPaths[] = CombinePaths(array(PATH_THEMES, $this->Theme, 'views', $this->MasterView . '.master*')); } // 3. Application default. eg. root/app_name/views/ $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, $this->ApplicationFolder, 'views', $this->MasterView . '.master*')); // 4. Garden default. eg. root/dashboard/views/ $MasterViewPaths[] = CombinePaths(array(PATH_APPLICATIONS, 'dashboard', 'views', $this->MasterView . '.master*')); } // Find the first file that matches the path. $MasterViewPath = FALSE; foreach ($MasterViewPaths as $Glob) { $Paths = SafeGlob($Glob); if (is_array($Paths) && count($Paths) > 0) { $MasterViewPath = $Paths[0]; break; } } if ($MasterViewPath != $MasterViewPath2) { Trace("Master views differ. Controller: {$MasterViewPath}, ViewLocation(): {$MasterViewPath2}", TRACE_WARNING); } $this->EventArguments['MasterViewPath'] =& $MasterViewPath; $this->FireEvent('BeforeFetchMaster'); if ($MasterViewPath === FALSE) { trigger_error(ErrorMessage("Could not find master view: {$this->MasterView}.master*", $this->ClassName, '_FetchController'), E_USER_ERROR); } /// A unique identifier that can be used in the body tag of the master view if needed. $ControllerName = $this->ClassName; // Strip "Controller" from the body identifier. if (substr($ControllerName, -10) == 'Controller') { $ControllerName = substr($ControllerName, 0, -10); } // Strip "Gdn_" from the body identifier. if (substr($ControllerName, 0, 4) == 'Gdn_') { $ControllerName = substr($ControllerName, 4); } $this->SetData('CssClass', $this->Application . ' ' . $ControllerName . ' ' . $this->RequestMethod . ' ' . $this->CssClass, TRUE); // Check to see if there is a handler for this particular extension. $ViewHandler = Gdn::Factory('ViewHandler' . strtolower(strrchr($MasterViewPath, '.'))); if (is_null($ViewHandler)) { $BodyIdentifier = strtolower($this->ApplicationFolder . '_' . $ControllerName . '_' . Gdn_Format::AlphaNumeric(strtolower($this->RequestMethod))); include $MasterViewPath; } else { $ViewHandler->Render($MasterViewPath, $this); } }
/** * Remove all CSS and JS files and add minified versions. * * @param HeadModule $Head */ public function HeadModule_BeforeToString_Handler($Head) { // Set BasePath for the plugin $this->BasePath = Gdn::Request()->WebRoot(); // Get current tags $Tags = $Head->Tags(); // Grab all of the CSS $CssToCache = array(); $JsToCache = array(); // Add the global js files $GlobalJS = array( 'jquery.js', 'jquery.livequery.js', 'jquery.form.js', 'jquery.popup.js', 'jquery.gardenhandleajaxform.js', 'global.js' ); // Process all tags, finding JS & CSS files foreach ($Tags as $Index => $Tag) { $IsJs = GetValue(HeadModule::TAG_KEY, $Tag) == 'script'; $IsCss = (GetValue(HeadModule::TAG_KEY, $Tag) == 'link' && GetValue('rel', $Tag) == 'stylesheet'); if (!$IsJs && !$IsCss) continue; if ($IsCss) $Href = GetValue('href', $Tag, '!'); else $Href = GetValue('src', $Tag, '!'); // Skip the rest if path doesn't start with a slash if ($Href[0] != '/') continue; // Strip any querystring off the href. $Href = preg_replace('`\?.*`', '', $Href); // Strip BasePath & extra slash from Href (Minify adds an extra slash when substituting basepath) if($this->BasePath != '') $Href = preg_replace("`^/{$this->BasePath}/`U", '', $Href); // Skip the rest if the file doesn't exist $FixPath = ($Href[0] != '/') ? '/' : ''; // Put that slash back to test for it in file structure $Path = PATH_ROOT . $FixPath . $Href; if (!file_exists($Path)) continue; // Remove the css from the tag because minifier is taking care of it. unset($Tags[$Index]); // Add the reference to the appropriate cache collection. if ($IsCss) { $CssToCache[] = $Href; } elseif ($IsJs) { // Don't include the file if it's in the global js. $Filename = basename($Path); if (in_array($Filename, $GlobalJS)) { continue; } $JsToCache[] = $Href; } } // Add minified css & js directly to the head module. $Url = 'plugins/Minify/min/?' . ($this->BasePath != '' ? "b={$this->BasePath}&" : ''); // Update HeadModule's $Tags $Head->Tags($Tags); // Add minified CSS to HeadModule $Head->AddCss($Url . 'token=' . $this->_PrepareToken($CssToCache), 'screen'); // Add global minified JS separately (and first) $Head->AddScript($Url . 'g=globaljs', 'text/javascript', -100); // Add other minified JS to HeadModule $Head->AddScript($Url . 'token=' . $this->_PrepareToken($JsToCache)); }
public function Base_AfterBody_Handler($Sender) { if (!empty($this->DeferJs)) { $Head = new HeadModule(); $SortLast = 0; foreach ($this->ExternalJs as $ExternalJs) { if (intval($ExternalJs['_sort']) > $SortLast) { $SortLast = intval($ExternalJs['_sort']); } } foreach ($this->DeferJs as $Token) { $SortLast++; $Head->AddScript("/cache/Consolidate/{$Token}", 'text/javascript', stripos($Token, '_jquery_js') !== FALSE ? -100 : $SortLast); } $Tags = $Head->GetTags(); $Tags = array_merge($Tags, $this->ExternalJs); $Tags = array_merge($Tags, $this->InlineJs); $Head->Tags($Tags); $HeadParts = split("\n", $Head->ToString()); foreach ($HeadParts as $HeadPart) { if (stripos($HeadPart, '<script') !== FALSE) { echo trim($HeadPart) . "\n"; } } foreach ($this->InlineJsStrings as $InlineJsString) { echo trim($InlineJsString) . "\n"; } } }
/** * * @param HeadModule $Head */ public function HeadModule_BeforeToString_Handler($Head) { $Tags = $Head->Tags(); // Grab all of the css. $CssToCache = array(); $JsToCache = array(); // Add the global js files $GlobalJS = array('jquery.js', 'jquery.livequery.js', 'jquery.form.js', 'jquery.popup.js', 'jquery.gardenhandleajaxform.js', 'global.js'); foreach ($Tags as $Index => $Tag) { $IsJs = GetValue(HeadModule::TAG_KEY, $Tag) == 'script'; $IsCss = GetValue(HeadModule::TAG_KEY, $Tag) == 'link' && GetValue('rel', $Tag) == 'stylesheet'; if (!$IsJs && !$IsCss) { continue; } if ($IsCss) { $Href = GetValue('href', $Tag, '!'); } else { $Href = GetValue('src', $Tag, '!'); } if ($Href[0] != '/') { continue; } // Strip any querystring off the href. $Href = preg_replace('`\\?.*`', '', $Href); $Path = PATH_ROOT . $Href; if (!file_exists($Path)) { continue; } // Remove the css from the tag because minifier is taking care of it. unset($Tags[$Index]); // Add the reference to the appropriate cache collection. if ($IsCss) { $CssToCache[] = $Href; } elseif ($IsJs) { // Don't include the file if it's in the global js. $Filename = basename($Path); if (in_array($Filename, $GlobalJS)) { $GlobalJsFound = TRUE; continue; } $JsToCache[] = $Href; } } // Add minified css & js directly to the head module. $Url = 'plugins/Minify/min/?'; $BasePath = Gdn::Request()->WebRoot(); if ($BasePath != '') { $BasePath = 'b=' . $BasePath . '&'; } $Head->Tags($Tags); $Head->AddCss($Url . $BasePath . 'f=' . implode(',', $CssToCache), 'screen'); $Head->AddScript($Url . 'g=globaljs', 'text/javascript', -100); $Head->AddScript($Url . $BasePath . 'f=' . implode(',', $JsToCache)); }