FileSystem.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View;
  7. /**
  8. * Model that finds file paths by their fileId
  9. *
  10. * @api
  11. * @since 100.0.2
  12. */
  13. class FileSystem
  14. {
  15. /**
  16. * @var \Magento\Framework\View\Design\FileResolution\Fallback\File
  17. */
  18. protected $_fileResolution;
  19. /**
  20. * @var \Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile
  21. */
  22. protected $_templateFileResolution;
  23. /**
  24. * @var \Magento\Framework\View\Design\FileResolution\Fallback\LocaleFile
  25. */
  26. protected $_localeFileResolution;
  27. /**
  28. * @var \Magento\Framework\View\Design\FileResolution\Fallback\StaticFile
  29. */
  30. protected $_staticFileResolution;
  31. /**
  32. * @var \Magento\Framework\View\Design\FileResolution\Fallback\EmailTemplateFile
  33. */
  34. protected $_emailTemplateFileResolution;
  35. /**
  36. * View service
  37. *
  38. * @var \Magento\Framework\View\Asset\Repository
  39. */
  40. protected $_assetRepo;
  41. /**
  42. * Constructor
  43. *
  44. * @param \Magento\Framework\View\Design\FileResolution\Fallback\File $fallbackFile
  45. * @param \Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile $fallbackTemplateFile
  46. * @param \Magento\Framework\View\Design\FileResolution\Fallback\LocaleFile $fallbackLocaleFile
  47. * @param \Magento\Framework\View\Design\FileResolution\Fallback\StaticFile $fallbackStaticFile
  48. * @param \Magento\Framework\View\Design\FileResolution\Fallback\EmailTemplateFile $fallbackEmailTemplateFile
  49. * @param \Magento\Framework\View\Asset\Repository $assetRepo
  50. */
  51. public function __construct(
  52. \Magento\Framework\View\Design\FileResolution\Fallback\File $fallbackFile,
  53. \Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile $fallbackTemplateFile,
  54. \Magento\Framework\View\Design\FileResolution\Fallback\LocaleFile $fallbackLocaleFile,
  55. \Magento\Framework\View\Design\FileResolution\Fallback\StaticFile $fallbackStaticFile,
  56. \Magento\Framework\View\Design\FileResolution\Fallback\EmailTemplateFile $fallbackEmailTemplateFile,
  57. \Magento\Framework\View\Asset\Repository $assetRepo
  58. ) {
  59. $this->_fileResolution = $fallbackFile;
  60. $this->_templateFileResolution = $fallbackTemplateFile;
  61. $this->_localeFileResolution = $fallbackLocaleFile;
  62. $this->_staticFileResolution = $fallbackStaticFile;
  63. $this->_emailTemplateFileResolution = $fallbackEmailTemplateFile;
  64. $this->_assetRepo = $assetRepo;
  65. }
  66. /**
  67. * Get existing file name with fallback to default
  68. *
  69. * @param string $fileId
  70. * @param array $params
  71. * @return string
  72. */
  73. public function getFilename($fileId, array $params = [])
  74. {
  75. list($module, $filePath) = \Magento\Framework\View\Asset\Repository::extractModule(
  76. $this->normalizePath($fileId)
  77. );
  78. if ($module) {
  79. $params['module'] = $module;
  80. }
  81. $this->_assetRepo->updateDesignParams($params);
  82. $file = $this->_fileResolution
  83. ->getFile($params['area'], $params['themeModel'], $filePath, $params['module']);
  84. return $file;
  85. }
  86. /**
  87. * Get a locale file
  88. *
  89. * @param string $file
  90. * @param array $params
  91. * @return string
  92. */
  93. public function getLocaleFileName($file, array $params = [])
  94. {
  95. $this->_assetRepo->updateDesignParams($params);
  96. return $this->_localeFileResolution
  97. ->getFile($params['area'], $params['themeModel'], $params['locale'], $file);
  98. }
  99. /**
  100. * Get a template file
  101. *
  102. * @param string $fileId
  103. * @param array $params
  104. * @return string|bool
  105. */
  106. public function getTemplateFileName($fileId, array $params = [])
  107. {
  108. list($module, $filePath) = \Magento\Framework\View\Asset\Repository::extractModule(
  109. $this->normalizePath($fileId)
  110. );
  111. if ($module) {
  112. $params['module'] = $module;
  113. }
  114. $this->_assetRepo->updateDesignParams($params);
  115. return $this->_templateFileResolution
  116. ->getFile($params['area'], $params['themeModel'], $filePath, $params['module']);
  117. }
  118. /**
  119. * Find a static view file using fallback mechanism
  120. *
  121. * @param string $fileId
  122. * @param array $params
  123. * @return string
  124. */
  125. public function getStaticFileName($fileId, array $params = [])
  126. {
  127. list($module, $filePath) = \Magento\Framework\View\Asset\Repository::extractModule(
  128. $this->normalizePath($fileId)
  129. );
  130. if ($module) {
  131. $params['module'] = $module;
  132. }
  133. $this->_assetRepo->updateDesignParams($params);
  134. return $this->_staticFileResolution
  135. ->getFile($params['area'], $params['themeModel'], $params['locale'], $filePath, $params['module']);
  136. }
  137. /**
  138. * Get an email template file
  139. *
  140. * @param string $fileId
  141. * @param array $params
  142. * @param string $module
  143. * @return string|bool
  144. */
  145. public function getEmailTemplateFileName($fileId, array $params, $module)
  146. {
  147. $this->_assetRepo->updateDesignParams($params);
  148. return $this->_emailTemplateFileResolution
  149. ->getFile($params['area'], $params['themeModel'], $params['locale'], $fileId, $module);
  150. }
  151. /**
  152. * Remove excessive "." and ".." parts from a path
  153. *
  154. * For example foo/bar/../file.ext -> foo/file.ext
  155. *
  156. * @param string $path
  157. * @return string
  158. */
  159. public static function normalizePath($path)
  160. {
  161. $parts = explode('/', $path);
  162. $result = [];
  163. foreach ($parts as $part) {
  164. if ('..' === $part) {
  165. if (!count($result) || ($result[count($result) - 1] == '..')) {
  166. $result[] = $part;
  167. } else {
  168. array_pop($result);
  169. }
  170. } elseif ('.' !== $part) {
  171. $result[] = $part;
  172. }
  173. }
  174. return implode('/', $result);
  175. }
  176. /**
  177. * Get a relative path between $relatedPath and $path paths as if $path was to refer to $relatedPath
  178. * relatively of itself
  179. *
  180. * Returns new calculated relative path.
  181. * Examples:
  182. * $path: /some/directory/one/file.ext
  183. * $relatedPath: /some/directory/two/another/file.ext
  184. * Result: ../two/another
  185. *
  186. * $path: http://example.com/themes/demo/css/styles.css
  187. * $relatedPath: http://example.com/images/logo.gif
  188. * Result: ../../../images
  189. *
  190. * @param string $relatedPath
  191. * @param string $path
  192. * @return string
  193. */
  194. public static function offsetPath($relatedPath, $path)
  195. {
  196. $relatedPath = self::normalizePath($relatedPath);
  197. $path = self::normalizePath($path);
  198. list($relatedPath, $path) = self::ltrimSamePart($relatedPath, $path);
  199. $toDir = ltrim(dirname($path), '/');
  200. if ($toDir == '.') {
  201. $offset = '';
  202. } else {
  203. $offset = str_repeat('../', count(explode('/', $toDir)));
  204. }
  205. return rtrim($offset . dirname($relatedPath), '/');
  206. }
  207. /**
  208. * Concatenate/normalize a path to another path as a relative, assuming it will be relative to its directory
  209. *
  210. * @param string $relativeTo
  211. * @param string $path
  212. * @return string
  213. */
  214. public static function getRelatedPath($relativeTo, $path)
  215. {
  216. return self::normalizePath(dirname($relativeTo) . '/' . $path);
  217. }
  218. /**
  219. * Left-trim same part of two paths
  220. *
  221. * @param string $pathOne
  222. * @param string $pathTwo
  223. * @return array
  224. */
  225. private static function ltrimSamePart($pathOne, $pathTwo)
  226. {
  227. $one = explode('/', $pathOne);
  228. $two = explode('/', $pathTwo);
  229. while (isset($one[0]) && isset($two[0]) && $one[0] == $two[0]) {
  230. array_shift($one);
  231. array_shift($two);
  232. }
  233. return [implode('/', $one), implode('/', $two)];
  234. }
  235. }