You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
7.2 KiB

  1. <?php
  2. use Assetic\Asset\AssetCollection;
  3. use Assetic\Asset\FileAsset;
  4. use Assetic\AssetWriter;
  5. use Assetic\Filter\CssRewriteFilter;
  6. use Assetic\Filter\CssImportFilter;
  7. /**
  8. * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
  9. * This file is licensed under the Affero General Public License version 3 or
  10. * later.
  11. * See the COPYING-README file.
  12. */
  13. class OC_TemplateLayout extends OC_Template {
  14. private static $versionHash = '';
  15. /**
  16. * @param string $renderas
  17. * @param string $appid application id
  18. */
  19. public function __construct( $renderas, $appid = '' ) {
  20. // Decide which page we show
  21. if( $renderas == 'user' ) {
  22. parent::__construct( 'core', 'layout.user' );
  23. if(in_array(OC_APP::getCurrentApp(), array('settings','admin', 'help'))!==false) {
  24. $this->assign('bodyid', 'body-settings');
  25. }else{
  26. $this->assign('bodyid', 'body-user');
  27. }
  28. // Update notification
  29. if(OC_Config::getValue('updatechecker', true) === true) {
  30. $data=OC_Updater::check();
  31. if(isset($data['version']) && $data['version'] != '' and $data['version'] !== Array() && OC_User::isAdminUser(OC_User::getUser())) {
  32. $this->assign('updateAvailable', true);
  33. $this->assign('updateVersion', $data['versionstring']);
  34. $this->assign('updateLink', $data['web']);
  35. } else {
  36. $this->assign('updateAvailable', false); // No update available or not an admin user
  37. }
  38. } else {
  39. $this->assign('updateAvailable', false); // Update check is disabled
  40. }
  41. // Add navigation entry
  42. $this->assign( 'application', '', false );
  43. $this->assign( 'appid', $appid );
  44. $navigation = OC_App::getNavigation();
  45. $this->assign( 'navigation', $navigation);
  46. $this->assign( 'settingsnavigation', OC_App::getSettingsNavigation());
  47. foreach($navigation as $entry) {
  48. if ($entry['active']) {
  49. $this->assign( 'application', $entry['name'] );
  50. break;
  51. }
  52. }
  53. $user_displayname = OC_User::getDisplayName();
  54. $this->assign( 'user_displayname', $user_displayname );
  55. $this->assign( 'user_uid', OC_User::getUser() );
  56. $this->assign( 'appsmanagement_active', strpos(OC_Request::requestUri(), OC_Helper::linkToRoute('settings_apps')) === 0 );
  57. $this->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
  58. } else if ($renderas == 'error') {
  59. parent::__construct('core', 'layout.guest', '', false);
  60. $this->assign('bodyid', 'body-login');
  61. } else if ($renderas == 'guest') {
  62. parent::__construct('core', 'layout.guest');
  63. $this->assign('bodyid', 'body-login');
  64. } else {
  65. parent::__construct('core', 'layout.base');
  66. }
  67. if(empty(self::$versionHash)) {
  68. self::$versionHash = md5(implode(',', OC_App::getAppVersions()));
  69. }
  70. $useAssetPipeline = $this->isAssetPipelineEnabled();
  71. if ($useAssetPipeline) {
  72. $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config', array('v' => self::$versionHash)));
  73. $this->generateAssets();
  74. } else {
  75. // Add the js files
  76. $jsfiles = self::findJavascriptFiles(OC_Util::$scripts);
  77. $this->assign('jsfiles', array(), false);
  78. if (OC_Config::getValue('installed', false) && $renderas!='error') {
  79. $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config', array('v' => self::$versionHash)));
  80. }
  81. foreach($jsfiles as $info) {
  82. $web = $info[1];
  83. $file = $info[2];
  84. $this->append( 'jsfiles', $web.'/'.$file . '?v=' . self::$versionHash);
  85. }
  86. // Add the css files
  87. $cssfiles = self::findStylesheetFiles(OC_Util::$styles);
  88. $this->assign('cssfiles', array());
  89. foreach($cssfiles as $info) {
  90. $web = $info[1];
  91. $file = $info[2];
  92. $this->append( 'cssfiles', $web.'/'.$file . '?v=' . self::$versionHash);
  93. }
  94. }
  95. }
  96. /**
  97. * @param array $styles
  98. * @return array
  99. */
  100. static public function findStylesheetFiles($styles) {
  101. // Read the selected theme from the config file
  102. $theme = OC_Util::getTheme();
  103. // Read the detected formfactor and use the right file name.
  104. $fext = self::getFormFactorExtension();
  105. $locator = new \OC\Template\CSSResourceLocator( $theme, $fext,
  106. array( OC::$SERVERROOT => OC::$WEBROOT ),
  107. array( OC::$THIRDPARTYROOT => OC::$THIRDPARTYWEBROOT ));
  108. $locator->find($styles);
  109. return $locator->getResources();
  110. }
  111. /**
  112. * @param array $scripts
  113. * @return array
  114. */
  115. static public function findJavascriptFiles($scripts) {
  116. // Read the selected theme from the config file
  117. $theme = OC_Util::getTheme();
  118. // Read the detected formfactor and use the right file name.
  119. $fext = self::getFormFactorExtension();
  120. $locator = new \OC\Template\JSResourceLocator( $theme, $fext,
  121. array( OC::$SERVERROOT => OC::$WEBROOT ),
  122. array( OC::$THIRDPARTYROOT => OC::$THIRDPARTYWEBROOT ));
  123. $locator->find($scripts);
  124. return $locator->getResources();
  125. }
  126. public function generateAssets()
  127. {
  128. $jsFiles = self::findJavascriptFiles(OC_Util::$scripts);
  129. $jsHash = self::hashScriptNames($jsFiles);
  130. if (!file_exists("assets/$jsHash.js")) {
  131. $jsFiles = array_map(function ($item) {
  132. $root = $item[0];
  133. $file = $item[2];
  134. return new FileAsset($root . '/' . $file, array(), $root, $file);
  135. }, $jsFiles);
  136. $jsCollection = new AssetCollection($jsFiles);
  137. $jsCollection->setTargetPath("assets/$jsHash.js");
  138. $writer = new AssetWriter(\OC::$SERVERROOT);
  139. $writer->writeAsset($jsCollection);
  140. }
  141. $cssFiles = self::findStylesheetFiles(OC_Util::$styles);
  142. $cssHash = self::hashScriptNames($cssFiles);
  143. if (!file_exists("assets/$cssHash.css")) {
  144. $cssFiles = array_map(function ($item) {
  145. $root = $item[0];
  146. $file = $item[2];
  147. $assetPath = $root . '/' . $file;
  148. $sourceRoot = \OC::$SERVERROOT;
  149. $sourcePath = substr($assetPath, strlen(\OC::$SERVERROOT));
  150. return new FileAsset(
  151. $assetPath,
  152. array(
  153. new CssRewriteFilter(),
  154. new CssImportFilter()
  155. ),
  156. $sourceRoot,
  157. $sourcePath
  158. );
  159. }, $cssFiles);
  160. $cssCollection = new AssetCollection($cssFiles);
  161. $cssCollection->setTargetPath("assets/$cssHash.css");
  162. $writer = new AssetWriter(\OC::$SERVERROOT);
  163. $writer->writeAsset($cssCollection);
  164. }
  165. $this->append('jsfiles', OC_Helper::linkTo('assets', "$jsHash.js"));
  166. $this->append('cssfiles', OC_Helper::linkTo('assets', "$cssHash.css"));
  167. }
  168. /**
  169. * @param array $files
  170. * @return string
  171. */
  172. private static function hashScriptNames($files)
  173. {
  174. $files = array_map(function ($item) {
  175. $root = $item[0];
  176. $file = $item[2];
  177. return $root . '/' . $file;
  178. }, $files);
  179. sort($files);
  180. // include the apps' versions hash to invalidate the cached assets
  181. $files[]= self::$versionHash;
  182. return hash('md5', implode('', $files));
  183. }
  184. /**
  185. * @return bool
  186. */
  187. private function isAssetPipelineEnabled() {
  188. // asset management enabled?
  189. $useAssetPipeline = OC_Config::getValue('asset-pipeline.enabled', false);
  190. if (!$useAssetPipeline) {
  191. return false;
  192. }
  193. // assets folder exists?
  194. $assetDir = \OC::$SERVERROOT . '/assets';
  195. if (!is_dir($assetDir)) {
  196. if (!mkdir($assetDir)) {
  197. \OCP\Util::writeLog('assets',
  198. "Folder <$assetDir> does not exist and/or could not be generated.", \OCP\Util::ERROR);
  199. return false;
  200. }
  201. }
  202. // assets folder can be accessed?
  203. if (!touch($assetDir."/.oc")) {
  204. \OCP\Util::writeLog('assets',
  205. "Folder <$assetDir> could not be accessed.", \OCP\Util::ERROR);
  206. return false;
  207. }
  208. return $useAssetPipeline;
  209. }
  210. }