1 <?php 
declare(strict_types
=1); 
   4  * This file is part of the Rapsys PackBundle package. 
   6  * (c) Raphaël Gertz <symfony@rapsys.eu> 
   8  * For the full copyright and license information, please view the LICENSE 
   9  * file that was distributed with this source code. 
  12 namespace Rapsys\PackBundle\Util
; 
  14 use Psr\Container\ContainerInterface
; 
  16 use Rapsys\PackBundle\RapsysPackBundle
; 
  17 use Rapsys\PackBundle\Util\ImageUtil
; 
  18 use Rapsys\PackBundle\Util\IntlUtil
; 
  19 use Rapsys\PackBundle\Util\SluggerUtil
; 
  21 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
; 
  22 use Symfony\Component\Routing\RouterInterface
; 
  23 use Symfony\Contracts\Translation\TranslatorInterface
; 
  26  * Manages file informations 
  32         protected string $alias; 
  37         protected array $config; 
  40          * Creates a new file util 
  42          * @param ContainerInterface $container The container instance 
  43          * @param ImageUtil $image The ImageUtil instance 
  44          * @param IntlUtil $intl The IntlUtil instance 
  45          * @param RouterInterface $router The router instance 
  46          * @param SluggerUtil $slugger The SluggerUtil instance 
  47          * @param TranslatorInterface $translator The translator instance 
  49         public function __construct(protected ContainerInterface 
$container, protected ImageUtil 
$image, protected IntlUtil 
$intl, protected RouterInterface 
$router, protected SluggerUtil 
$slugger, protected TranslatorInterface 
$translator) { 
  51                 $this->config 
= $container->getParameter($this->alias 
= RapsysPackBundle
::getAlias()); 
  57          * @param string $path The base path 
  58          * @param string $realpath The real path 
  59          * @param string $name The route name 
  60          * @param array $parameters The route parameters 
  61          * @param bool $si Use si unit 
  63         public function getFile(string $path, string $realpath, string $name, array $parameters = [], bool $si = true): array { 
  65                 $file = new \
SplFileObject($realpath); 
  68                 $size = $file->getSize(); 
  71                 $unit = $si ? 1000 : 1024; 
  74                 $index = [ '', $si ? 'k' : 'K', 'M', 'G', 'T', 'P', 'E' ]; 
  77                 $exp = intval((log($size) / log($unit))); 
  80                 $number = round($size / pow($unit, $exp), 2); 
  82                 //Set ext, height, image, mime, preview, thumb and width 
  83                 $ext = $height = $image = $mime = $preview = $thumb = $width = false; 
  85                 //With supporter format extension 
  86                 if (($pos = strrpos($realpath, '.')) && ($ext = substr($realpath, $pos + 
1)) && in_array($ext, $this->config
['formats'])) { 
  88                         //XXX: getimagesize is too slow to run against all files 
  89                         if (($image = getimagesize($realpath)) !== false) { 
  91                                 if (($ext = image_type_to_extension($image[2], false)) === false) { 
  93                                         throw new \
Exception(sprintf('Unable to get "%s" file image extension', $realpath)); 
 100                                 $mime = image_type_to_mime_type($image[2]); 
 106                                 $preview = $this->image
->getThumb($realpath, $height, $width, $ext); 
 109                                 $thumb = $this->image
->getThumb($realpath, $this->config
['thumb']['height'], $this->config
['thumb']['weight'], $ext); 
 115                         'created' => (new \
DateTime())->setTimestamp($file->getCTime()), 
 117                         'intlsize' => $intlsize = $this->intl
->number($number), 
 118                         'intlunit' => $intlunit = $this->translator
->trans($index[$exp].($si ? '' : 'i').'B'), 
 119                         'link' => $this->router
->generate($name, ['path' => substr($realpath, strlen($path) + 
1)] + 
$parameters), 
 120                         'download' => $this->router
->generate('rapsyspack_download', ['path' => $short = $this->slugger
->short($realpath), 'hash' => $this->slugger
->hash($short), 'u' => $mtime = $file->getMTime()]), 
 122                         'modified' => (new \
DateTime())->setTimestamp($mtime), 
 123                         'name' => basename($realpath).' ('.$intlsize.' '.$intlunit.')', 
 124                         'preview' => $preview, 
 128                         //TODO: preview for images ? 
 129                         //TODO: extra fields ? (preview, miniature, etc ?) 
 130                         //TODO: mimetype decided extra fields ? (.pdf for doc, webm preview, img preview, etc ?) 
 131                         //TODO: XXX: finish this !!! 
 138          * @param string $path The base path 
 139          * @param string $realpath The real path 
 140          * @param string $name The route name 
 141          * @param array $parameters The route parameters 
 142          * @param bool $si Use si unit 
 144         //Route object instead of shitty array ? 
 145         public function getInfos(string $path, string $realpath, string $slug, string $name, array $parameters = []) { 
 148                         'breadcrumbs' => [/*$breadcrumb*/], 
 157                 //Iterate on breadcrumbs 
 158                 foreach (explode('/', substr($realpath, strlen($path))) as $value) { 
 159                         $result['breadcrumbs'][] = [ 
 160                                 'name' => $value ? '/ '.$value : $slug, 
 161                                 'link' => $this->router
->generate($name, ['path' => ($base .= ($base == '' ? '' : '/').$value)] + 
$parameters) 
 166                 if (is_file($realpath)) { 
 168                         $result['file'] = $this->getFile($path, $realpath, $name, $parameters); 
 170                 //TODO: for pagination, files and directories are to be placed in a single array 
 171                 //TODO: only get informations on files and directories inside the pagination window ! 
 172                 } elseif (is_dir($realpath)) { 
 174                         $dir = dir($realpath); 
 176                         //Iterate on directory 
 177                         while (($item = $dir->read()) !== false) { 
 178                                 //Skip ., .., .git, .svn, .htpasswd, .htgroup and .*.un~ items 
 179                                 //TODO: set this regexp in config ? 
 180                                 if (preg_match('/^(\.|\.\.|\.git|\.svn|\.ht(access|passwd|group)|\..*\.un~)$/', $item)) { 
 187                                         //Without item realpath 
 188                                         !($itempath = realpath($realpath.'/'.$item)) || 
 189                                         //Item realpath not matching album path 
 190                                         //XXX: skip files outside of album/element path (symlink outside of tree) 
 191                                         //TODO: make it configurable ? by album/element/admin ? 
 192                                         $path !== substr($itempath, 0, strlen($path)) 
 199                                 if (is_dir($itempath)) { 
 201                                         //TODO: use this structure or revert to old $item.'/' => $link form 
 202                                         $result['directories'][] = [ 
 204                                                 'link' => $this->router
->generate($name, ['path' => substr($itempath, strlen($path) + 
1)] + 
$parameters) 
 205                                                 //TODO: add stats here ? like number of files ? 
 208                                 } elseif (is_file($itempath)) { 
 210                                         $result['files'][] = $this->getFile($path, $itempath, $name, $parameters); 
 214                                         throw new \
Exception(sprintf('Unknown file "%s" type', $itempath)); 
 220                         throw new \
Exception(sprintf('Unknown file "%s" type', $realpath)); 
 230          * @param string $path The file path 
 231          * @param bool $si Use si units 
 232          * @return array The file infos 
 234         public function infos(string $path, bool $si = true): array { 
 239                 $unit = $si ? 1000 : 1024; 
 242                 $index = [ '', $si ? 'k' : 'K', 'M', 'G', 'T', 'P', 'E' ]; 
 245                 $exp = intval((log($stat['size']) / log($unit))); 
 248                 $number = round($stat['size'] / pow($unit, $exp), 2); 
 252                         'intlsize' => $intlsize = $this->intl->number($number), 
 253                         'intlunit' => $intlunit = $this->translator->trans($index[$exp].($si ? '' : 'i').'B'), 
 254                         'name' => basename($path).' ('.$intlsize.' '.$intlunit.')', 
 255                         'size' => $stat['size'], 
 256                         'ctime' => $stat['ctime'], 
 257                         'mtime' => $stat['mtime'], 
 258                         //TODO: preview for images ? 
 259                         //TODO: extra fields ? (preview, miniature, etc ?) 
 260                         //TODO: mimetype decided extra fields ? (.pdf for doc, webm preview, img preview, etc ?) 
 261                         //TODO: XXX: finish this !!! 
 265                 if (($mimetype = mime_content_type($path)) !== false) { 
 267                         $fileinfos['mimetype'] = $mimetype; 
 269                         //TODO: with image preview, movie webm preview, others a imagemagick file with format initials ? 
 273                                 $mimetype == 'image/jpeg' || 
 274                                 $mimetype == 'image/png' || 
 275                                 $mimetype == 'image/bmp' || 
 276                                 $mimetype == 'image/tiff' || 
 277                                 $mimetype == 'image/svg+xml' 
 279                                 //Get image width and height 
 280                                 if (($fileinfos['image'] = getimagesize($path)) === false) { 
 282                                         throw new \Exception(sprintf('Unable to get "%s" file image size', $path)); 
 286                                 $fileinfos['thumb'] = $this->image->getThumb($path, 64, 64); 
 291                                 //With location user source image 
 292                                 if (($isFile = is_file($source = $this->config['path'].'/location/'.$location['id'].'/'.$id.'.png')) && ($mtime = stat($source)['mtime'])) { 
 294                                         $this->context['locations'][$locationId]['image'] = $this->image->getThumb($location['miniature'], $mtime, $source); 
 296                         //With image mimetype 
 297                         if (in_array($fileinfos['mimetype'], [ 'image/jpeg', 'image/png', 'image/webp' ])) { 
 298                                 header('Content-Type: text/plain'); 
 299                                 var_dump($fileinfos); 
 301                                 $file['thumb'] = $this->router->generate('rapsyspack_thumb', [ 'hash' => $this->slugger->hash(''), 'path' => $path, 'slug' => $slug ]); 
 302                                 #public function thumb(Request $request, string $hash, int $updated, string $path, int $width, int $height): Response {