Excerpts.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * @package Grav\Common\Helpers
  4. *
  5. * @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common\Helpers;
  9. use DOMDocument;
  10. use DOMElement;
  11. use Grav\Common\Page\Interfaces\PageInterface;
  12. use Grav\Common\Page\Markdown\Excerpts as ExcerptsObject;
  13. use Grav\Common\Page\Medium\Link;
  14. use Grav\Common\Page\Medium\Medium;
  15. use function is_array;
  16. /**
  17. * Class Excerpts
  18. * @package Grav\Common\Helpers
  19. */
  20. class Excerpts
  21. {
  22. /**
  23. * Process Grav image media URL from HTML tag
  24. *
  25. * @param string $html HTML tag e.g. `<img src="image.jpg" />`
  26. * @param PageInterface|null $page Page, defaults to the current page object
  27. * @return string Returns final HTML string
  28. */
  29. public static function processImageHtml($html, PageInterface $page = null)
  30. {
  31. $excerpt = static::getExcerptFromHtml($html, 'img');
  32. $original_src = $excerpt['element']['attributes']['src'];
  33. $excerpt['element']['attributes']['href'] = $original_src;
  34. $excerpt = static::processLinkExcerpt($excerpt, $page, 'image');
  35. $excerpt['element']['attributes']['src'] = $excerpt['element']['attributes']['href'];
  36. unset($excerpt['element']['attributes']['href']);
  37. $excerpt = static::processImageExcerpt($excerpt, $page);
  38. $excerpt['element']['attributes']['data-src'] = $original_src;
  39. $html = static::getHtmlFromExcerpt($excerpt);
  40. return $html;
  41. }
  42. /**
  43. * Process Grav page link URL from HTML tag
  44. *
  45. * @param string $html HTML tag e.g. `<a href="../foo">Page Link</a>`
  46. * @param PageInterface|null $page Page, defaults to the current page object
  47. * @return string Returns final HTML string
  48. */
  49. public static function processLinkHtml($html, PageInterface $page = null)
  50. {
  51. $excerpt = static::getExcerptFromHtml($html, 'a');
  52. $original_href = $excerpt['element']['attributes']['href'];
  53. $excerpt = static::processLinkExcerpt($excerpt, $page, 'link');
  54. $excerpt['element']['attributes']['data-href'] = $original_href;
  55. $html = static::getHtmlFromExcerpt($excerpt);
  56. return $html;
  57. }
  58. /**
  59. * Get an Excerpt array from a chunk of HTML
  60. *
  61. * @param string $html Chunk of HTML
  62. * @param string $tag A tag, for example `img`
  63. * @return array|null returns nested array excerpt
  64. */
  65. public static function getExcerptFromHtml($html, $tag)
  66. {
  67. $doc = new DOMDocument('1.0', 'UTF-8');
  68. $internalErrors = libxml_use_internal_errors(true);
  69. $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
  70. libxml_use_internal_errors($internalErrors);
  71. $elements = $doc->getElementsByTagName($tag);
  72. $excerpt = null;
  73. $inner = [];
  74. /** @var DOMElement $element */
  75. foreach ($elements as $element) {
  76. $attributes = [];
  77. foreach ($element->attributes as $name => $value) {
  78. $attributes[$name] = $value->value;
  79. }
  80. $excerpt = [
  81. 'element' => [
  82. 'name' => $element->tagName,
  83. 'attributes' => $attributes
  84. ]
  85. ];
  86. foreach ($element->childNodes as $node) {
  87. $inner[] = $doc->saveHTML($node);
  88. }
  89. $excerpt = array_merge_recursive($excerpt, ['element' => ['text' => implode('', $inner)]]);
  90. }
  91. return $excerpt;
  92. }
  93. /**
  94. * Rebuild HTML tag from an excerpt array
  95. *
  96. * @param array $excerpt
  97. * @return string
  98. */
  99. public static function getHtmlFromExcerpt($excerpt)
  100. {
  101. $element = $excerpt['element'];
  102. $html = '<'.$element['name'];
  103. if (isset($element['attributes'])) {
  104. foreach ($element['attributes'] as $name => $value) {
  105. if ($value === null) {
  106. continue;
  107. }
  108. $html .= ' '.$name.'="'.$value.'"';
  109. }
  110. }
  111. if (isset($element['text'])) {
  112. $html .= '>';
  113. $html .= is_array($element['text']) ? static::getHtmlFromExcerpt(['element' => $element['text']]) : $element['text'];
  114. $html .= '</'.$element['name'].'>';
  115. } else {
  116. $html .= ' />';
  117. }
  118. return $html;
  119. }
  120. /**
  121. * Process a Link excerpt
  122. *
  123. * @param array $excerpt
  124. * @param PageInterface|null $page Page, defaults to the current page object
  125. * @param string $type
  126. * @return mixed
  127. */
  128. public static function processLinkExcerpt($excerpt, PageInterface $page = null, $type = 'link')
  129. {
  130. $excerpts = new ExcerptsObject($page);
  131. return $excerpts->processLinkExcerpt($excerpt, $type);
  132. }
  133. /**
  134. * Process an image excerpt
  135. *
  136. * @param array $excerpt
  137. * @param PageInterface|null $page Page, defaults to the current page object
  138. * @return array
  139. */
  140. public static function processImageExcerpt(array $excerpt, PageInterface $page = null)
  141. {
  142. $excerpts = new ExcerptsObject($page);
  143. return $excerpts->processImageExcerpt($excerpt);
  144. }
  145. /**
  146. * Process media actions
  147. *
  148. * @param Medium $medium
  149. * @param string|array $url
  150. * @param PageInterface|null $page Page, defaults to the current page object
  151. * @return Medium|Link
  152. */
  153. public static function processMediaActions($medium, $url, PageInterface $page = null)
  154. {
  155. $excerpts = new ExcerptsObject($page);
  156. return $excerpts->processMediaActions($medium, $url);
  157. }
  158. }