vendor/pimcore/pimcore/lib/Tool/Text.php line 63

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Tool;
  15. use Onnov\DetectEncoding\EncodingDetector;
  16. use Pimcore\Model\Asset;
  17. use Pimcore\Model\DataObject\Concrete;
  18. use Pimcore\Model\Document;
  19. use Pimcore\Model\Element;
  20. class Text
  21. {
  22.     /**
  23.      * @param string $text
  24.      *
  25.      * @return string
  26.      */
  27.     public static function removeLineBreaks($text '')
  28.     {
  29.         $text str_replace(["\r\n""\n""\r""\t"], ' '$text);
  30.         $text preg_replace('#[ ]+#'' '$text);
  31.         return $text;
  32.     }
  33.     /**
  34.      * @param string $text
  35.      * @param array $params
  36.      *
  37.      * @return string
  38.      */
  39.     public static function wysiwygText($text$params = [])
  40.     {
  41.         if (empty($text)) {
  42.             return $text;
  43.         }
  44.         $matches self::getElementsTagsInWysiwyg($text);
  45.         if (count($matches[2]) > 0) {
  46.             for ($i 0$i count($matches[2]); $i++) {
  47.                 preg_match('/[0-9]+/'$matches[2][$i], $idMatches);
  48.                 preg_match('/asset|object|document/'$matches[3][$i], $typeMatches);
  49.                 $linkAttr null;
  50.                 $path null;
  51.                 $additionalAttributes = [];
  52.                 $id $idMatches[0];
  53.                 $type $typeMatches[0];
  54.                 $element Element\Service::getElementById($type$id);
  55.                 $oldTag $matches[0][$i];
  56.                 if ($element instanceof Element\ElementInterface) {
  57.                     if ($matches[1][$i] == 'a') {
  58.                         $linkAttr 'href';
  59.                         $path $element->getFullPath();
  60.                         if (($element instanceof Document || $element instanceof Concrete) && !$element->isPublished()) {
  61.                             $path null;
  62.                         } elseif ($element instanceof Document) {
  63.                             // get parameters
  64.                             preg_match('/href="([^"]+)*"/'$oldTag$oldHref);
  65.                             if ($oldHref[1] && (strpos($oldHref[1], '?') !== false || strpos($oldHref[1], '#') !== false)) {
  66.                                 $urlParts parse_url($oldHref[1]);
  67.                                 if (array_key_exists('query'$urlParts) && !empty($urlParts['query'])) {
  68.                                     $path .= '?' $urlParts['query'];
  69.                                 }
  70.                                 if (array_key_exists('fragment'$urlParts) && !empty($urlParts['fragment'])) {
  71.                                     $path .= '#' $urlParts['fragment'];
  72.                                 }
  73.                             }
  74.                         } elseif ($element instanceof Concrete) {
  75.                             if ($linkGenerator $element->getClass()->getLinkGenerator()) {
  76.                                 $path $linkGenerator->generate(
  77.                                     $element,
  78.                                     $params
  79.                                 );
  80.                             } else {
  81.                                 // no object path without link generator!
  82.                                 $path null;
  83.                             }
  84.                         }
  85.                     } elseif ($matches[1][$i] == 'img') {
  86.                         $linkAttr 'src';
  87.                         // only for images
  88.                         if (!$element instanceof Asset\Image) {
  89.                             continue;
  90.                         }
  91.                         $path $element->getFullPath();
  92.                         // resize image to the given attributes
  93.                         $config null;
  94.                         preg_match('/width="([^"]+)*"/'$oldTag$widthAttr);
  95.                         preg_match('/height="([^"]+)*"/'$oldTag$heightAttr);
  96.                         preg_match('/style="([^"]+)*"/'$oldTag$styleAttr);
  97.                         if ((isset($widthAttr[1]) && $widthAttr[1]) || (isset($heightAttr[1]) && $heightAttr[1])) {
  98.                             $config = [
  99.                                 'width' => (int)(isset($widthAttr[1]) ? $widthAttr[1] : null),
  100.                                 'height' => (int)(isset($heightAttr[1]) ? $heightAttr[1] : null),
  101.                             ];
  102.                         }
  103.                         if (isset($styleAttr[1]) && $styleAttr[1] && preg_match('/(width|height)/'$styleAttr[1])) {
  104.                             $config = []; // reset the config if it was set already before (attributes)
  105.                             $cleanedStyle preg_replace('#[ ]+#'''$styleAttr[1]);
  106.                             $styles explode(';'$cleanedStyle);
  107.                             foreach ($styles as $style) {
  108.                                 if (strpos(trim($style), 'width') === 0) {
  109.                                     if (preg_match('/([0-9]+)(px)/i'$style$match)) {
  110.                                         $config['width'] = $match[1];
  111.                                     }
  112.                                 } elseif (strpos(trim($style), 'height') === 0) {
  113.                                     if (preg_match('/([0-9]+)(px)/i'$style$match)) {
  114.                                         $config['height'] = $match[1];
  115.                                     }
  116.                                 }
  117.                             }
  118.                         }
  119.                         // only create a thumbnail if it is not disabled
  120.                         if (!preg_match('/pimcore_disable_thumbnail="([^"]+)*"/'$oldTag)) {
  121.                             if (!empty($config)) {
  122.                                 $path $element->getThumbnail($config);
  123.                                 $pathHdpi $element->getThumbnail(array_merge($config, ['highResolution' => 2]));
  124.                                 $additionalAttributes = [
  125.                                     'srcset' => $path ' 1x, ' $pathHdpi ' 2x',
  126.                                 ];
  127.                             } elseif ($element->getWidth() > 2000 || $element->getHeight() > 2000) {
  128.                                 // if the image is too large, size it down to 2000px this is the max. for wysiwyg
  129.                                 // for those big images we don't generate a hdpi version
  130.                                 $path $element->getThumbnail([
  131.                                     'width' => 2000,
  132.                                 ]);
  133.                             } else {
  134.                                 // return the original
  135.                                 $path $element->getFullPath();
  136.                             }
  137.                         }
  138.                     }
  139.                     if ($path) {
  140.                         $pattern '/' $linkAttr '="[^"]*"/';
  141.                         $replacement $linkAttr '="' $path '"';
  142.                         if (!empty($additionalAttributes)) {
  143.                             $replacement .= ' ' array_to_html_attribute_string($additionalAttributes);
  144.                         }
  145.                         $newTag preg_replace($pattern$replacement$oldTag);
  146.                         $text str_replace($oldTag$newTag$text);
  147.                     }
  148.                 }
  149.                 if (!$path) {
  150.                     // in case there's a broken internal reference/link
  151.                     if ($matches[1][$i] == 'img') {
  152.                         // remove the entire tag for images
  153.                         $text str_replace($oldTag''$text);
  154.                     } elseif ($matches[1][$i] == 'a') {
  155.                         // just display the text for links
  156.                         $text preg_replace('@' preg_quote($oldTag'@') . '([^\<]+)\</a\>@i''$1'$text);
  157.                     }
  158.                 }
  159.             }
  160.         }
  161.         return $text;
  162.     }
  163.     /**
  164.      * @param string $text
  165.      *
  166.      * @return array
  167.      */
  168.     private static function getElementsTagsInWysiwyg($text)
  169.     {
  170.         if (!is_string($text) || strlen($text) < 1) {
  171.             return [];
  172.         }
  173.         $hash 'elements_raw_wysiwyg_text_' md5($text);
  174.         if (\Pimcore\Cache\Runtime::isRegistered($hash)) {
  175.             return \Pimcore\Cache\Runtime::get($hash);
  176.         }
  177.         //$text = Pimcore_Tool_Text::removeLineBreaks($text);
  178.         preg_match_all("@\<(a|img)[^>]*(pimcore_id=\"[0-9]+\")[^>]*(pimcore_type=\"[asset|document|object]+\")[^>]*\>@msUi"$text$matches);
  179.         \Pimcore\Cache\Runtime::set($hash$matches);
  180.         return $matches;
  181.     }
  182.     /**
  183.      * @param string $text
  184.      *
  185.      * @return array
  186.      */
  187.     private static function getElementsInWysiwyg($text)
  188.     {
  189.         $hash 'elements_wysiwyg_text_' md5($text);
  190.         if (\Pimcore\Cache\Runtime::isRegistered($hash)) {
  191.             return \Pimcore\Cache\Runtime::get($hash);
  192.         }
  193.         $elements = [];
  194.         $matches self::getElementsTagsInWysiwyg($text);
  195.         if (count($matches[2]) > 0) {
  196.             for ($i 0$i count($matches[2]); $i++) {
  197.                 preg_match('/[0-9]+/'$matches[2][$i], $idMatches);
  198.                 preg_match('/asset|object|document/'$matches[3][$i], $typeMatches);
  199.                 $id $idMatches[0];
  200.                 $type $typeMatches[0];
  201.                 if ($id && $type) {
  202.                     $elements[] = [
  203.                         'id' => $id,
  204.                         'type' => $type,
  205.                     ];
  206.                 }
  207.             }
  208.         }
  209.         \Pimcore\Cache\Runtime::set($hash$elements);
  210.         return $elements;
  211.     }
  212.     /**
  213.      * extracts all dependencies to other elements from wysiwyg text
  214.      *
  215.      * @param  string $text
  216.      *
  217.      * @return array
  218.      */
  219.     public static function getDependenciesOfWysiwygText($text)
  220.     {
  221.         $dependencies = [];
  222.         if (!empty($text)) {
  223.             $elements self::getElementsInWysiwyg($text);
  224.             foreach ($elements as $element) {
  225.                 $key $element['type'] . '_' $element['id'];
  226.                 $dependencies[$key] = [
  227.                     'id' => $element['id'],
  228.                     'type' => $element['type'],
  229.                 ];
  230.             }
  231.         }
  232.         return $dependencies;
  233.     }
  234.     /**
  235.      * @param string $text
  236.      * @param array $tags
  237.      *
  238.      * @return array
  239.      */
  240.     public static function getCacheTagsOfWysiwygText($text, array $tags = []): array
  241.     {
  242.         if (!empty($text)) {
  243.             $elements self::getElementsInWysiwyg($text);
  244.             foreach ($elements as $element) {
  245.                 $tag Element\Service::getElementCacheTag($element['type'], $element['id']);
  246.                 $tags[$tag] = $tag;
  247.             }
  248.         }
  249.         return $tags;
  250.     }
  251.     /**
  252.      * @param string $text
  253.      *
  254.      * @return string
  255.      */
  256.     public static function convertToUTF8($text)
  257.     {
  258.         $encoding self::detectEncoding($text);
  259.         if ($encoding) {
  260.             $text iconv($encoding'UTF-8'$text);
  261.         }
  262.         return $text;
  263.     }
  264.     /**
  265.      * @param string $text
  266.      *
  267.      * @return string
  268.      */
  269.     public static function detectEncoding($text)
  270.     {
  271.         // Detect UTF-8, UTF-16 and UTF-32 by BOM
  272.         $utf32_big_endian_bom chr(0x00) . chr(0x00) . chr(0xFE) . chr(0xFF);
  273.         $utf32_little_endian_bom chr(0xFF) . chr(0xFE) . chr(0x00) . chr(0x00);
  274.         $utf16_big_endian_bom chr(0xFE) . chr(0xFF);
  275.         $utf16_little_endian_bom chr(0xFF) . chr(0xFE);
  276.         $utf8_bom chr(0xEF) . chr(0xBB) . chr(0xBF);
  277.         $first2bytes substr($text02);
  278.         $first3bytes substr($text03);
  279.         $first4bytes substr($text03);
  280.         if ($first3bytes === $utf8_bom) {
  281.             return 'UTF-8';
  282.         } elseif ($first4bytes === $utf32_big_endian_bom) {
  283.             return 'UTF-32BE';
  284.         } elseif ($first4bytes === $utf32_little_endian_bom) {
  285.             return 'UTF-32LE';
  286.         } elseif ($first2bytes === $utf16_big_endian_bom) {
  287.             return 'UTF-16BE';
  288.         } elseif ($first2bytes === $utf16_little_endian_bom) {
  289.             return 'UTF-16LE';
  290.         }
  291.         $detector = new EncodingDetector();
  292.         $encoding $detector->getEncoding($text);
  293.         if (empty($encoding)) {
  294.             $encoding 'UTF-8';
  295.         }
  296.         return $encoding;
  297.     }
  298.     /**
  299.      * @param string $string
  300.      *
  301.      * @return string
  302.      */
  303.     public static function getStringAsOneLine($string)
  304.     {
  305.         $string str_replace("\r\n"' '$string);
  306.         $string str_replace("\n"' '$string);
  307.         $string str_replace("\r"' '$string);
  308.         $string str_replace("\t"''$string);
  309.         $string preg_replace('#[ ]+#'' '$string);
  310.         return $string;
  311.     }
  312.     /**
  313.      * @param string $string
  314.      * @param int $length
  315.      *
  316.      * @return string
  317.      */
  318.     public static function cutStringRespectingWhitespace($string$length)
  319.     {
  320.         if ($length strlen($string)) {
  321.             $text substr($string0$length);
  322.             if (false !== ($length strrpos($text' '))) {
  323.                 $text substr($text0$length);
  324.             }
  325.             $string $text '…';
  326.         }
  327.         return $string;
  328.     }
  329. }