PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/system/src/Grav/Framework/ContentBlock/HtmlBlock.php

https://bitbucket.org/nick_zou/dialsmart-grav
PHP | 385 lines | 249 code | 49 blank | 87 comment | 24 complexity | 77962fc79029cd09fb458c8ec2907f4a MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, BSD-2-Clause
  1. <?php
  2. /**
  3. * @package Grav\Framework\ContentBlock
  4. *
  5. * @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Framework\ContentBlock;
  9. /**
  10. * HtmlBlock
  11. *
  12. * @package Grav\Framework\ContentBlock
  13. */
  14. class HtmlBlock extends ContentBlock implements HtmlBlockInterface
  15. {
  16. protected $frameworks = [];
  17. protected $styles = [];
  18. protected $scripts = [];
  19. protected $html = [];
  20. /**
  21. * @return array
  22. */
  23. public function getAssets()
  24. {
  25. $assets = $this->getAssetsFast();
  26. $this->sortAssets($assets['styles']);
  27. $this->sortAssets($assets['scripts']);
  28. $this->sortAssets($assets['html']);
  29. return $assets;
  30. }
  31. /**
  32. * @return array
  33. */
  34. public function getFrameworks()
  35. {
  36. $assets = $this->getAssetsFast();
  37. return array_keys($assets['frameworks']);
  38. }
  39. /**
  40. * @param string $location
  41. * @return array
  42. */
  43. public function getStyles($location = 'head')
  44. {
  45. return $this->getAssetsInLocation('styles', $location);
  46. }
  47. /**
  48. * @param string $location
  49. * @return array
  50. */
  51. public function getScripts($location = 'head')
  52. {
  53. return $this->getAssetsInLocation('scripts', $location);
  54. }
  55. /**
  56. * @param string $location
  57. * @return array
  58. */
  59. public function getHtml($location = 'bottom')
  60. {
  61. return $this->getAssetsInLocation('html', $location);
  62. }
  63. /**
  64. * @return array[]
  65. */
  66. public function toArray()
  67. {
  68. $array = parent::toArray();
  69. if ($this->frameworks) {
  70. $array['frameworks'] = $this->frameworks;
  71. }
  72. if ($this->styles) {
  73. $array['styles'] = $this->styles;
  74. }
  75. if ($this->scripts) {
  76. $array['scripts'] = $this->scripts;
  77. }
  78. if ($this->html) {
  79. $array['html'] = $this->html;
  80. }
  81. return $array;
  82. }
  83. /**
  84. * @param array $serialized
  85. * @throws \RuntimeException
  86. */
  87. public function build(array $serialized)
  88. {
  89. parent::build($serialized);
  90. $this->frameworks = isset($serialized['frameworks']) ? (array) $serialized['frameworks'] : [];
  91. $this->styles = isset($serialized['styles']) ? (array) $serialized['styles'] : [];
  92. $this->scripts = isset($serialized['scripts']) ? (array) $serialized['scripts'] : [];
  93. $this->html = isset($serialized['html']) ? (array) $serialized['html'] : [];
  94. }
  95. /**
  96. * @param string $framework
  97. * @return $this
  98. */
  99. public function addFramework($framework)
  100. {
  101. $this->frameworks[$framework] = 1;
  102. return $this;
  103. }
  104. /**
  105. * @param string|array $element
  106. * @param int $priority
  107. * @param string $location
  108. * @return bool
  109. *
  110. * @example $block->addStyle('assets/js/my.js');
  111. * @example $block->addStyle(['href' => 'assets/js/my.js', 'media' => 'screen']);
  112. */
  113. public function addStyle($element, $priority = 0, $location = 'head')
  114. {
  115. if (!is_array($element)) {
  116. $element = ['href' => (string) $element];
  117. }
  118. if (empty($element['href'])) {
  119. return false;
  120. }
  121. if (!isset($this->styles[$location])) {
  122. $this->styles[$location] = [];
  123. }
  124. $id = !empty($element['id']) ? ['id' => (string) $element['id']] : [];
  125. $href = $element['href'];
  126. $type = !empty($element['type']) ? (string) $element['type'] : 'text/css';
  127. $media = !empty($element['media']) ? (string) $element['media'] : null;
  128. unset(
  129. $element['tag'],
  130. $element['id'],
  131. $element['rel'],
  132. $element['content'],
  133. $element['href'],
  134. $element['type'],
  135. $element['media']
  136. );
  137. $this->styles[$location][md5($href) . sha1($href)] = [
  138. ':type' => 'file',
  139. ':priority' => (int) $priority,
  140. 'href' => $href,
  141. 'type' => $type,
  142. 'media' => $media,
  143. 'element' => $element
  144. ] + $id;
  145. return true;
  146. }
  147. /**
  148. * @param string|array $element
  149. * @param int $priority
  150. * @param string $location
  151. * @return bool
  152. */
  153. public function addInlineStyle($element, $priority = 0, $location = 'head')
  154. {
  155. if (!is_array($element)) {
  156. $element = ['content' => (string) $element];
  157. }
  158. if (empty($element['content'])) {
  159. return false;
  160. }
  161. if (!isset($this->styles[$location])) {
  162. $this->styles[$location] = [];
  163. }
  164. $content = (string) $element['content'];
  165. $type = !empty($element['type']) ? (string) $element['type'] : 'text/css';
  166. $this->styles[$location][md5($content) . sha1($content)] = [
  167. ':type' => 'inline',
  168. ':priority' => (int) $priority,
  169. 'content' => $content,
  170. 'type' => $type
  171. ];
  172. return true;
  173. }
  174. /**
  175. * @param string|array $element
  176. * @param int $priority
  177. * @param string $location
  178. * @return bool
  179. */
  180. public function addScript($element, $priority = 0, $location = 'head')
  181. {
  182. if (!is_array($element)) {
  183. $element = ['src' => (string) $element];
  184. }
  185. if (empty($element['src'])) {
  186. return false;
  187. }
  188. if (!isset($this->scripts[$location])) {
  189. $this->scripts[$location] = [];
  190. }
  191. $src = $element['src'];
  192. $type = !empty($element['type']) ? (string) $element['type'] : 'text/javascript';
  193. $defer = isset($element['defer']) ? true : false;
  194. $async = isset($element['async']) ? true : false;
  195. $handle = !empty($element['handle']) ? (string) $element['handle'] : '';
  196. $this->scripts[$location][md5($src) . sha1($src)] = [
  197. ':type' => 'file',
  198. ':priority' => (int) $priority,
  199. 'src' => $src,
  200. 'type' => $type,
  201. 'defer' => $defer,
  202. 'async' => $async,
  203. 'handle' => $handle
  204. ];
  205. return true;
  206. }
  207. /**
  208. * @param string|array $element
  209. * @param int $priority
  210. * @param string $location
  211. * @return bool
  212. */
  213. public function addInlineScript($element, $priority = 0, $location = 'head')
  214. {
  215. if (!is_array($element)) {
  216. $element = ['content' => (string) $element];
  217. }
  218. if (empty($element['content'])) {
  219. return false;
  220. }
  221. if (!isset($this->scripts[$location])) {
  222. $this->scripts[$location] = [];
  223. }
  224. $content = (string) $element['content'];
  225. $type = !empty($element['type']) ? (string) $element['type'] : 'text/javascript';
  226. $this->scripts[$location][md5($content) . sha1($content)] = [
  227. ':type' => 'inline',
  228. ':priority' => (int) $priority,
  229. 'content' => $content,
  230. 'type' => $type
  231. ];
  232. return true;
  233. }
  234. /**
  235. * @param string $html
  236. * @param int $priority
  237. * @param string $location
  238. * @return bool
  239. */
  240. public function addHtml($html, $priority = 0, $location = 'bottom')
  241. {
  242. if (empty($html) || !is_string($html)) {
  243. return false;
  244. }
  245. if (!isset($this->html[$location])) {
  246. $this->html[$location] = [];
  247. }
  248. $this->html[$location][md5($html) . sha1($html)] = [
  249. ':priority' => (int) $priority,
  250. 'html' => $html
  251. ];
  252. return true;
  253. }
  254. /**
  255. * @return array
  256. */
  257. protected function getAssetsFast()
  258. {
  259. $assets = [
  260. 'frameworks' => $this->frameworks,
  261. 'styles' => $this->styles,
  262. 'scripts' => $this->scripts,
  263. 'html' => $this->html
  264. ];
  265. foreach ($this->blocks as $block) {
  266. if ($block instanceof HtmlBlock) {
  267. $blockAssets = $block->getAssetsFast();
  268. $assets['frameworks'] += $blockAssets['frameworks'];
  269. foreach ($blockAssets['styles'] as $location => $styles) {
  270. if (!isset($assets['styles'][$location])) {
  271. $assets['styles'][$location] = $styles;
  272. } elseif ($styles) {
  273. $assets['styles'][$location] += $styles;
  274. }
  275. }
  276. foreach ($blockAssets['scripts'] as $location => $scripts) {
  277. if (!isset($assets['scripts'][$location])) {
  278. $assets['scripts'][$location] = $scripts;
  279. } elseif ($scripts) {
  280. $assets['scripts'][$location] += $scripts;
  281. }
  282. }
  283. foreach ($blockAssets['html'] as $location => $htmls) {
  284. if (!isset($assets['html'][$location])) {
  285. $assets['html'][$location] = $htmls;
  286. } elseif ($htmls) {
  287. $assets['html'][$location] += $htmls;
  288. }
  289. }
  290. }
  291. }
  292. return $assets;
  293. }
  294. /**
  295. * @param string $type
  296. * @param string $location
  297. * @return array
  298. */
  299. protected function getAssetsInLocation($type, $location)
  300. {
  301. $assets = $this->getAssetsFast();
  302. if (empty($assets[$type][$location])) {
  303. return [];
  304. }
  305. $styles = $assets[$type][$location];
  306. $this->sortAssetsInLocation($styles);
  307. return $styles;
  308. }
  309. /**
  310. * @param array $items
  311. */
  312. protected function sortAssetsInLocation(array &$items)
  313. {
  314. $count = 0;
  315. foreach ($items as &$item) {
  316. $item[':order'] = ++$count;
  317. }
  318. unset($item);
  319. uasort(
  320. $items,
  321. function ($a, $b) {
  322. return ($a[':priority'] === $b[':priority'])
  323. ? $a[':order'] - $b[':order'] : $a[':priority'] - $b[':priority'];
  324. }
  325. );
  326. }
  327. /**
  328. * @param array $array
  329. */
  330. protected function sortAssets(array &$array)
  331. {
  332. foreach ($array as $location => &$items) {
  333. $this->sortAssetsInLocation($items);
  334. }
  335. }
  336. }