vendor/pimcore/pimcore/lib/helper-functions.php line 245

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. /**
  15.  * @param string $file
  16.  *
  17.  * @return array
  18.  */
  19. function xmlToArray($file)
  20. {
  21.     $xml simplexml_load_file($filenullLIBXML_NOCDATA);
  22.     $json json_encode((array) $xml);
  23.     $array json_decode($jsontrue);
  24.     return $array;
  25. }
  26. /**
  27.  * @param string $source
  28.  * @param int|null $level
  29.  * @param string|null $target
  30.  *
  31.  * @return bool|string
  32.  */
  33. function gzcompressfile($source$level null$target null)
  34. {
  35.     // this is a very memory efficient way of gzipping files
  36.     if ($target) {
  37.         $dest $target;
  38.     } else {
  39.         $dest $source.'.gz';
  40.     }
  41.     $mode 'wb' $level;
  42.     $error false;
  43.     if ($fp_out gzopen($dest$mode)) {
  44.         if ($fp_in fopen($source'rb')) {
  45.             while (!feof($fp_in)) {
  46.                 gzwrite($fp_outfread($fp_in1024 512));
  47.             }
  48.             fclose($fp_in);
  49.         } else {
  50.             $error true;
  51.         }
  52.         gzclose($fp_out);
  53.     } else {
  54.         $error true;
  55.     }
  56.     if ($error) {
  57.         return false;
  58.     } else {
  59.         return $dest;
  60.     }
  61. }
  62. /**
  63.  * @param mixed $string
  64.  *
  65.  * @return bool
  66.  */
  67. function is_json($string)
  68. {
  69.     if (is_string($string)) {
  70.         json_decode($string);
  71.         return json_last_error() == JSON_ERROR_NONE;
  72.     }
  73.     return false;
  74. }
  75. /**
  76.  * @param string $path
  77.  *
  78.  * @return int
  79.  */
  80. function foldersize($path)
  81. {
  82.     $total_size 0;
  83.     $files scandir($path);
  84.     $cleanPath rtrim($path'/'). '/';
  85.     foreach ($files as $t) {
  86.         if ($t != '.' && $t != '..') {
  87.             $currentFile $cleanPath $t;
  88.             if (is_dir($currentFile)) {
  89.                 $size foldersize($currentFile);
  90.                 $total_size += $size;
  91.             } else {
  92.                 $size filesize($currentFile);
  93.                 $total_size += $size;
  94.             }
  95.         }
  96.     }
  97.     return $total_size;
  98. }
  99. /**
  100.  * @param string $string
  101.  * @param string[] $values
  102.  *
  103.  * @return string
  104.  */
  105. function replace_pcre_backreferences($string$values)
  106. {
  107.     array_unshift($values'');
  108.     $string str_replace('\$''###PCRE_PLACEHOLDER###'$string);
  109.     foreach ($values as $key => $value) {
  110.         $string str_replace('$'.$key$value$string);
  111.     }
  112.     $string str_replace('###URLENCODE_PLACEHOLDER###''$'$string);
  113.     return $string;
  114. }
  115. /**
  116.  * @param array $array
  117.  *
  118.  * @return array
  119.  */
  120. function array_htmlspecialchars($array)
  121. {
  122.     foreach ($array as $key => $value) {
  123.         if (is_string($value) || is_numeric($value)) {
  124.             $array[$key] = htmlspecialchars($valueENT_COMPAT'UTF-8');
  125.         } else {
  126.             if (is_array($value)) {
  127.                 $array[$key] = array_htmlspecialchars($value);
  128.             }
  129.         }
  130.     }
  131.     return $array;
  132. }
  133. /**
  134.  * @param string $needle
  135.  * @param array $haystack
  136.  *
  137.  * @return bool
  138.  */
  139. function in_arrayi(string $needle, array $haystack)
  140. {
  141.     return in_array(strtolower($needle), array_map('strtolower'$haystack));
  142. }
  143. /**
  144.  * @param string $needle
  145.  * @param array $haystack
  146.  *
  147.  * @return false|int|string the key for needle if it is found in the array, false otherwise.
  148.  */
  149. function array_searchi(string $needle, array $haystack)
  150. {
  151.     return array_search(strtolower($needle), array_map('strtolower'$haystack));
  152. }
  153. /**
  154.  * @param object $node
  155.  *
  156.  * @return array
  157.  */
  158. function object2array($node)
  159. {
  160.     // dirty hack, should be replaced
  161.     $paj json_encode($node);
  162.     if (JSON_ERROR_NONE !== json_last_error()) {
  163.         throw new \InvalidArgumentException(json_last_error_msg());
  164.     }
  165.     return @json_decode($pajtrue);
  166. }
  167. /**
  168.  * @param array $args
  169.  *
  170.  * @return false|string
  171.  */
  172. function array_urlencode($args)
  173. {
  174.     if (!is_array($args)) {
  175.         return false;
  176.     }
  177.     return http_build_query($args);
  178. }
  179. /**
  180.  * same as  array_urlencode but no urlencode()
  181.  *
  182.  * @param array $args
  183.  *
  184.  * @return false|string
  185.  */
  186. function array_toquerystring($args)
  187. {
  188.     if (!is_array($args)) {
  189.         return false;
  190.     }
  191.     return urldecode(http_build_query($args));
  192. }
  193. /**
  194.  * @param array $array with attribute names as keys, and values as values
  195.  *
  196.  * @return string
  197.  */
  198. function array_to_html_attribute_string($array)
  199. {
  200.     $data = [];
  201.     foreach ($array as $key => $value) {
  202.         if (is_scalar($value)) {
  203.             $data[] = $key '="' htmlspecialchars($value) . '"';
  204.         } elseif (is_string($key) && is_null($value)) {
  205.             $data[] = $key;
  206.         }
  207.     }
  208.     return implode(' '$data);
  209. }
  210. /**
  211.  * @param string $var
  212.  *
  213.  * @return string
  214.  */
  215. function urlencode_ignore_slash($var)
  216. {
  217.     $scheme parse_url($varPHP_URL_SCHEME);
  218.     if ($scheme) {
  219.         $var str_replace($scheme '://'''$var);
  220.     }
  221.     $placeholder 'x-X-x-ignore-' md5(microtime()) . '-slash-x-X-x';
  222.     $var str_replace('/'$placeholder$var);
  223.     $var rawurlencode($var);
  224.     $var str_replace($placeholder'/'$var);
  225.     if ($scheme) {
  226.         $var $scheme '://' $var;
  227.     }
  228.     // allow @2x for retina thumbnails, ...
  229.     $var preg_replace("/%40([\d]+)x\./"'@$1x.'$var);
  230.     return $var;
  231. }
  232. /**
  233.  * @param string $val
  234.  *
  235.  * @return int
  236.  */
  237. function return_bytes($val)
  238. {
  239.     $val trim($val);
  240.     $last strtolower($val[strlen($val) - 1]);
  241.     $bytes = (int)$val;
  242.     switch ($last) {
  243.         case 'g':
  244.             $bytes *= 1024;
  245.             // no break
  246.         case 'm':
  247.             $bytes *= 1024;
  248.             // no break
  249.         case 'k':
  250.             $bytes *= 1024;
  251.     }
  252.     return $bytes;
  253. }
  254. /**
  255.  * @param int $bytes
  256.  * @param int $precision
  257.  *
  258.  * @return string
  259.  */
  260. function formatBytes($bytes$precision 2)
  261. {
  262.     $units = ['B''KB''MB''GB''TB'];
  263.     $bytes max($bytes0);
  264.     $pow floor(($bytes log($bytes) : 0) / log(1000));
  265.     $pow min($powcount($units) - 1);
  266.     $bytes /= pow(1000$pow);
  267.     return round($bytes$precision) . ' ' $units[$pow];
  268. }
  269. /**
  270.  * @param string $str
  271.  *
  272.  * @return int
  273.  */
  274. function filesize2bytes($str)
  275. {
  276.     $bytes_array = [
  277.         'K' => 1024,
  278.         'M' => 1024 1024,
  279.         'G' => 1024 1024 1024,
  280.         'T' => 1024 1024 1024 1024,
  281.         'P' => 1024 1024 1024 1024 1024,
  282.     ];
  283.     $bytes = (float)$str;
  284.     if (preg_match('#([KMGTP])?B?$#si'$str$matches) && (array_key_exists(1$matches) && !empty($bytes_array[$matches[1]]))) {
  285.         $bytes *= $bytes_array[$matches[1]];
  286.     }
  287.     $bytes = (int)round($bytes2);
  288.     return $bytes;
  289. }
  290. /**
  291.  * @param string $base
  292.  * @param array $data
  293.  *
  294.  * @return array
  295.  */
  296. function rscandir($base '', &$data = [])
  297. {
  298.     if (substr($base, -11) != DIRECTORY_SEPARATOR) { //add trailing slash if it doesn't exists
  299.         $base .= DIRECTORY_SEPARATOR;
  300.     }
  301.     $array array_diff(scandir($base), ['.''..''.svn']);
  302.     foreach ($array as $value) {
  303.         if (is_dir($base $value)) {
  304.             $data[] = $base $value DIRECTORY_SEPARATOR;
  305.             $data rscandir($base $value DIRECTORY_SEPARATOR$data);
  306.         } elseif (is_file($base $value)) {
  307.             $data[] = $base $value;
  308.         }
  309.     }
  310.     return $data;
  311. }
  312. /**
  313.  * Wrapper for explode() to get a trimmed array
  314.  *
  315.  * @param string $delimiter
  316.  * @param string $string
  317.  * @param string $limit
  318.  * @param bool $useArrayFilter
  319.  *
  320.  * @return array
  321.  *
  322.  * @phpstan-param non-empty-string $delimiter
  323.  */
  324. function explode_and_trim($delimiter$string ''$limit ''$useArrayFilter true)
  325. {
  326.     if ($limit === '') {
  327.         $exploded explode($delimiter$string);
  328.     } else {
  329.         $exploded explode($delimiter$string$limit);
  330.     }
  331.     foreach ($exploded as $key => $value) {
  332.         $exploded[$key] = trim($value);
  333.     }
  334.     if ($useArrayFilter) {
  335.         $exploded array_filter($exploded);
  336.     }
  337.     return $exploded;
  338. }
  339. /**
  340.  * @param string $directory
  341.  * @param bool $empty
  342.  *
  343.  * @return bool
  344.  */
  345. function recursiveDelete($directory$empty true)
  346. {
  347.     if (is_dir($directory)) {
  348.         $directory rtrim($directory'/');
  349.         if (!file_exists($directory) || !is_dir($directory)) {
  350.             return false;
  351.         } elseif (!is_readable($directory)) {
  352.             return false;
  353.         } else {
  354.             $directoryHandle opendir($directory);
  355.             $contents '.';
  356.             while ($contents) {
  357.                 $contents readdir($directoryHandle);
  358.                 if (strlen($contents) && $contents != '.' && $contents != '..') {
  359.                     $path $directory '/' $contents;
  360.                     if (is_dir($path)) {
  361.                         recursiveDelete($path);
  362.                     } else {
  363.                         unlink($path);
  364.                     }
  365.                 }
  366.             }
  367.             closedir($directoryHandle);
  368.             if ($empty == true) {
  369.                 if (!rmdir($directory)) {
  370.                     return false;
  371.                 }
  372.             }
  373.             return true;
  374.         }
  375.     } elseif (is_file($directory)) {
  376.         return unlink($directory);
  377.     }
  378.     return false;
  379. }
  380. /**
  381.  * @param string $source
  382.  * @param string $destination
  383.  *
  384.  * @return bool
  385.  */
  386. function recursiveCopy($source$destination)
  387. {
  388.     if (is_dir($source)) {
  389.         if (!is_dir($destination)) {
  390.             \Pimcore\File::mkdir($destination);
  391.         }
  392.         foreach (
  393.             $iterator = new RecursiveIteratorIterator(
  394.                 new RecursiveDirectoryIterator($sourceRecursiveDirectoryIterator::SKIP_DOTS),
  395.                 RecursiveIteratorIterator::SELF_FIRST
  396.             ) as $item) {
  397.             if ($item->isDir()) {
  398.                 \Pimcore\File::mkdir($destination DIRECTORY_SEPARATOR $iterator->getSubPathName());
  399.             } else {
  400.                 copy($item$destination DIRECTORY_SEPARATOR $iterator->getSubPathName());
  401.             }
  402.         }
  403.     } elseif (is_file($source)) {
  404.         if (is_dir(dirname($destination))) {
  405.             \Pimcore\File::mkdir(dirname($destination));
  406.         }
  407.         copy($source$destination);
  408.     }
  409.     return true;
  410. }
  411. function p_r()
  412. {
  413.     $cloner = new \Symfony\Component\VarDumper\Cloner\VarCloner();
  414.     $dumper 'cli' === PHP_SAPI ? new \Symfony\Component\VarDumper\Dumper\CliDumper() : new \Symfony\Component\VarDumper\Dumper\HtmlDumper();
  415.     foreach (func_get_args() as $var) {
  416.         $dumper->dump($cloner->cloneVar($var));
  417.     }
  418. }
  419. /**
  420.  * @param array $array
  421.  * @param string $prefix
  422.  * @param string $suffix
  423.  *
  424.  * @return array
  425.  */
  426. function wrapArrayElements($array$prefix "'"$suffix "'")
  427. {
  428.     foreach ($array as $key => $value) {
  429.         $array[$key] = $prefix trim($value). $suffix;
  430.     }
  431.     return $array;
  432. }
  433. /**
  434.  * Checks if an array is associative
  435.  *
  436.  * @param array $arr
  437.  *
  438.  * @return bool
  439.  */
  440. function isAssocArray(array $arr)
  441. {
  442.     return array_keys($arr) !== range(0count($arr) - 1);
  443. }
  444. /**
  445.  * this is an alternative for realpath() which isn't able to handle symlinks correctly
  446.  *
  447.  * @param string $filename
  448.  *
  449.  * @return string
  450.  */
  451. function resolvePath($filename)
  452. {
  453.     $protocol '';
  454.     if (!stream_is_local($filename)) {
  455.         $protocol parse_url($filenamePHP_URL_SCHEME) . '://';
  456.         $filename str_replace($protocol''$filename);
  457.     }
  458.     $filename str_replace('//''/'$filename);
  459.     $parts explode('/'$filename);
  460.     $out = [];
  461.     foreach ($parts as $part) {
  462.         if ($part == '.') {
  463.             continue;
  464.         }
  465.         if ($part == '..') {
  466.             array_pop($out);
  467.             continue;
  468.         }
  469.         $out[] = $part;
  470.     }
  471.     $finalPath $protocol implode('/'$out);
  472.     return $finalPath;
  473. }
  474. /**
  475.  * @param Closure $closure
  476.  *
  477.  * @return string
  478.  */
  479. function closureHash(Closure $closure)
  480. {
  481.     $ref = new ReflectionFunction($closure);
  482.     $file = new SplFileObject($ref->getFileName());
  483.     $file->seek($ref->getStartLine() - 1);
  484.     $content '';
  485.     while ($file->key() < $ref->getEndLine()) {
  486.         $content .= $file->current();
  487.         $file->next();
  488.     }
  489.     $hash md5(json_encode([
  490.         $content,
  491.         $ref->getStaticVariables(),
  492.     ]));
  493.     return $hash;
  494. }
  495. /**
  496.  * Checks if the given directory is empty
  497.  *
  498.  * @param string $dir
  499.  *
  500.  * @return bool|null
  501.  */
  502. function is_dir_empty($dir)
  503. {
  504.     if (!is_readable($dir)) {
  505.         return null;
  506.     }
  507.     $handle opendir($dir);
  508.     while (false !== ($entry readdir($handle))) {
  509.         if ($entry != '.' && $entry != '..') {
  510.             return false;
  511.         }
  512.     }
  513.     return true;
  514. }
  515. /**
  516.  * @param mixed $var
  517.  * @param string $indent
  518.  *
  519.  * @return string
  520.  */
  521. function var_export_pretty($var$indent '')
  522. {
  523.     switch (gettype($var)) {
  524.         case 'string':
  525.             return '"' addcslashes($var"\\\$\"\r\n\t\v\f") . '"';
  526.         case 'array':
  527.             $indexed array_keys($var) === range(0count($var) - 1);
  528.             $r = [];
  529.             foreach ($var as $key => $value) {
  530.                 $r[] = "$indent    "
  531.                     . ($indexed '' var_export_pretty($key) . ' => ')
  532.                     . var_export_pretty($value"$indent    ");
  533.             }
  534.             return "[\n" implode(",\n"$r) . "\n" $indent ']';
  535.         case 'boolean':
  536.             return $var 'TRUE' 'FALSE';
  537.         default:
  538.             return var_export($vartrue);
  539.     }
  540. }
  541. /**
  542.  * @param mixed $contents
  543.  *
  544.  * @return string
  545.  */
  546. function to_php_data_file_format($contents$comments null)
  547. {
  548.     $contents var_export_pretty($contents);
  549.     $export '<?php';
  550.     if (!empty($comments)) {
  551.         $export .= "\n\n";
  552.         $export .= $comments;
  553.         $export .= "\n";
  554.     }
  555.     $export .= "\n\nreturn ".$contents.";\n";
  556.     return $export;
  557. }
  558. /**
  559.  * @return string
  560.  */
  561. function generateRandomSymfonySecret()
  562. {
  563.     return base64_encode(random_bytes(24));
  564. }
  565. /**
  566.  * @param array $array
  567.  * @param string $glue
  568.  *
  569.  * @return string
  570.  */
  571. function implode_recursive($array$glue)
  572. {
  573.     $ret '';
  574.     foreach ($array as $item) {
  575.         if (is_array($item)) {
  576.             $ret .= implode_recursive($item$glue) . $glue;
  577.         } else {
  578.             $ret .= $item $glue;
  579.         }
  580.     }
  581.     $ret substr($ret0strlen($glue));
  582.     return $ret;
  583. }