/concrete/src/Asset/Asset.php

https://github.com/jasteele12/concrete5 · PHP · 425 lines · 253 code · 50 blank · 122 comment · 35 complexity · 194fa558b18ddea5ad3c6e0f5e9d2845 MD5 · raw file

  1. <?php
  2. namespace Concrete\Core\Asset;
  3. use Concrete\Core\Package\Package;
  4. use Concrete\Core\Support\Facade\Application;
  5. use Environment;
  6. use Symfony\Component\HttpFoundation\Response;
  7. abstract class Asset implements AssetInterface
  8. {
  9. /**
  10. * @var string
  11. */
  12. protected $location;
  13. /**
  14. * @var bool
  15. */
  16. protected $assetHasBeenMapped = false;
  17. /**
  18. * @var string
  19. */
  20. protected $assetVersion = '0';
  21. /**
  22. * @var string
  23. */
  24. protected $assetHandle;
  25. /**
  26. * @var bool
  27. */
  28. protected $local = true;
  29. /**
  30. * @var string
  31. */
  32. protected $filename;
  33. /**
  34. * @var string
  35. */
  36. protected $assetURL;
  37. /**
  38. * @var string
  39. */
  40. protected $assetPath;
  41. /**
  42. * @var bool
  43. */
  44. protected $assetSupportsMinification = false;
  45. /**
  46. * @var bool
  47. */
  48. protected $assetSupportsCombination = false;
  49. /**
  50. * @var \Package
  51. */
  52. protected $pkg;
  53. /**
  54. * @var array
  55. */
  56. protected $combinedAssetSourceFiles = [];
  57. const ASSET_POSITION_HEADER = 'H';
  58. const ASSET_POSITION_FOOTER = 'F';
  59. public function getOutputAssetType()
  60. {
  61. return $this->getAssetType();
  62. }
  63. /**
  64. * @param Asset[] $assets
  65. *
  66. * @return Asset[]
  67. *
  68. * @abstract
  69. */
  70. public static function process($assets)
  71. {
  72. return $assets;
  73. }
  74. /**
  75. * @return bool
  76. */
  77. public function assetSupportsMinification()
  78. {
  79. return $this->local && $this->assetSupportsMinification;
  80. }
  81. /**
  82. * @return bool
  83. */
  84. public function assetSupportsCombination()
  85. {
  86. return $this->local && $this->assetSupportsCombination;
  87. }
  88. /**
  89. * @param mixed $location
  90. */
  91. public function setAssetLocation($location)
  92. {
  93. $this->location = $location;
  94. }
  95. /**
  96. * @param bool $minify
  97. */
  98. public function setAssetSupportsMinification($minify)
  99. {
  100. $this->assetSupportsMinification = $minify;
  101. }
  102. /**
  103. * @param bool $combine
  104. */
  105. public function setAssetSupportsCombination($combine)
  106. {
  107. $this->assetSupportsCombination = $combine;
  108. }
  109. /**
  110. * @return string
  111. */
  112. public function getAssetURL()
  113. {
  114. if (!$this->assetHasBeenMapped) {
  115. $this->mapAssetLocation($this->location);
  116. }
  117. return $this->assetURL;
  118. }
  119. /**
  120. * @return string
  121. */
  122. public function getAssetHashKey()
  123. {
  124. $result = $this->assetURL;
  125. if ($this->isAssetLocal()) {
  126. $filename = $this->getAssetPath();
  127. if (is_file($filename)) {
  128. if (is_readable($filename) && \Config::get('concrete.cache.full_contents_assets_hash')) {
  129. $sha1 = @sha1_file($filename);
  130. if ($sha1 !== false) {
  131. $result = $sha1;
  132. }
  133. } else {
  134. $mtime = @filemtime($filename);
  135. if ($mtime !== false) {
  136. $result .= '@' . $mtime;
  137. }
  138. }
  139. }
  140. }
  141. return $result;
  142. }
  143. public function getAssetPointer()
  144. {
  145. $pointer = new AssetPointer($this->getAssetType(), $this->getAssetHandle());
  146. return $pointer;
  147. }
  148. /**
  149. * @return string
  150. */
  151. public function getAssetPath()
  152. {
  153. if (!$this->assetHasBeenMapped) {
  154. $this->mapAssetLocation($this->location);
  155. }
  156. return $this->assetPath;
  157. }
  158. /**
  159. * @return string
  160. */
  161. public function getAssetHandle()
  162. {
  163. return $this->assetHandle;
  164. }
  165. /**
  166. * @param bool|string $assetHandle
  167. */
  168. public function __construct($assetHandle = false)
  169. {
  170. $this->assetHandle = $assetHandle;
  171. $this->position = $this->getAssetDefaultPosition();
  172. }
  173. /**
  174. * @return string
  175. */
  176. public function getAssetFilename()
  177. {
  178. return $this->filename;
  179. }
  180. /**
  181. * @param string $version
  182. */
  183. public function setAssetVersion($version)
  184. {
  185. $this->assetVersion = $version;
  186. }
  187. /**
  188. * @param array $paths
  189. */
  190. public function setCombinedAssetSourceFiles($paths)
  191. {
  192. $this->combinedAssetSourceFiles = $paths;
  193. }
  194. /**
  195. * @return string
  196. */
  197. public function getAssetVersion()
  198. {
  199. return $this->assetVersion;
  200. }
  201. /**
  202. * @param string $position
  203. */
  204. public function setAssetPosition($position)
  205. {
  206. $this->position = $position;
  207. }
  208. /**
  209. * @param \Package $pkg
  210. */
  211. public function setPackageObject($pkg)
  212. {
  213. $this->pkg = $pkg;
  214. }
  215. /**
  216. * @param string $url
  217. */
  218. public function setAssetURL($url)
  219. {
  220. $this->assetHasBeenMapped = true;
  221. $this->assetURL = $url;
  222. }
  223. /**
  224. * @param string $path
  225. */
  226. public function setAssetPath($path)
  227. {
  228. $this->assetHasBeenMapped = true;
  229. $this->assetPath = $path;
  230. }
  231. public function hasAssetBeenMapped()
  232. {
  233. return $this->assetHasBeenMapped;
  234. }
  235. /**
  236. * @return string
  237. */
  238. public function getAssetURLPath()
  239. {
  240. return substr($this->getAssetURL(), 0, strrpos($this->getAssetURL(), '/'));
  241. }
  242. /**
  243. * @return bool
  244. */
  245. public function isAssetLocal()
  246. {
  247. return $this->local;
  248. }
  249. /**
  250. * @param bool $isLocal
  251. */
  252. public function setAssetIsLocal($isLocal)
  253. {
  254. $this->local = $isLocal;
  255. }
  256. /**
  257. * @return string
  258. */
  259. public function getAssetPosition()
  260. {
  261. return $this->position;
  262. }
  263. /**
  264. * @param string $path
  265. */
  266. public function mapAssetLocation($path)
  267. {
  268. if ($this->isAssetLocal()) {
  269. $env = Environment::get();
  270. $pkgHandle = false;
  271. if (is_object($this->pkg)) {
  272. $pkgHandle = $this->pkg->getPackageHandle();
  273. }
  274. $r = $env->getRecord($path, $pkgHandle);
  275. $this->setAssetPath($r->file);
  276. $this->setAssetURL($r->url);
  277. } else {
  278. $this->setAssetURL($path);
  279. }
  280. }
  281. /**
  282. * @return string|null
  283. */
  284. public function getAssetContents()
  285. {
  286. $result = @file_get_contents($this->getAssetPath());
  287. return ($result === false) ? null : $result;
  288. }
  289. /**
  290. * @param string $route
  291. *
  292. * @return string|null
  293. */
  294. protected static function getAssetContentsByRoute($route)
  295. {
  296. $result = null;
  297. try {
  298. $routes = \Route::getList();
  299. /* @var $routes \Symfony\Component\Routing\RouteCollection */
  300. $context = new \Symfony\Component\Routing\RequestContext();
  301. $request = \Request::getInstance();
  302. $context->fromRequest($request);
  303. $matcher = new \Symfony\Component\Routing\Matcher\UrlMatcher($routes, $context);
  304. $matched = null;
  305. try {
  306. $matched = $matcher->match($route);
  307. } catch (\Exception $x) {
  308. $m = null;
  309. // Route matcher requires that paths ends with a slash
  310. if (preg_match('/^(.*[^\/])($|\?.*)$/', $route, $m)) {
  311. try {
  312. $matched = $matcher->match($m[1] . '/' . (isset($m[2]) ? $m[2] : ''));
  313. } catch (\Exception $x) {
  314. }
  315. }
  316. }
  317. if ($matched !== null) {
  318. $callable = null;
  319. $controller = $matched['_controller'];
  320. if (is_string($controller)) {
  321. $chunks = explode('::', $controller, 2);
  322. if (count($chunks) === 2) {
  323. if (class_exists($chunks[0])) {
  324. $array = [Application::getFacadeApplication()->make($chunks[0]), $chunks[1]];
  325. if (is_callable($array)) {
  326. $callable = $array;
  327. }
  328. }
  329. } else {
  330. if (class_exists($controller) && method_exists($controller, '__invoke')) {
  331. $callable = Application::getFacadeApplication()->make($controller);
  332. }
  333. }
  334. } elseif (is_callable($controller)) {
  335. $callable = $controller;
  336. }
  337. if ($callable !== null) {
  338. ob_start();
  339. $r = call_user_func($callable, false);
  340. if ($r instanceof Response) {
  341. $result = $r->getContent();
  342. } elseif ($r !== false) {
  343. $result = ob_get_contents();
  344. }
  345. ob_end_clean();
  346. }
  347. }
  348. } catch (\Exception $x) {
  349. }
  350. return $result;
  351. }
  352. public function register($filename, $args, $pkg = false)
  353. {
  354. if ($pkg != false) {
  355. if ($pkg !== false && is_string($pkg)) {
  356. $pkg = Package::getByHandle($pkg);
  357. }
  358. $this->setPackageObject($pkg);
  359. }
  360. $this->setAssetIsLocal($args['local']);
  361. $this->setAssetLocation($filename);
  362. if ($args['minify'] === true || $args['minify'] === false) {
  363. $this->setAssetSupportsMinification($args['minify']);
  364. }
  365. if ($args['combine'] === true || $args['combine'] === false) {
  366. $this->setAssetSupportsCombination($args['combine']);
  367. }
  368. if ($args['version']) {
  369. $this->setAssetVersion($args['version']);
  370. }
  371. if ($args['position']) {
  372. $this->setAssetPosition($args['position']);
  373. }
  374. }
  375. }