%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/tjamichg/cursos.tjamich.gob.mx/vendor/alchemy/phpexiftool/lib/PHPExiftool/
Upload File :
Create Path :
Current File : /home/tjamichg/cursos.tjamich.gob.mx/vendor/alchemy/phpexiftool/lib/PHPExiftool/Reader.php

<?php

/**
 * This file is part of the PHPExiftool package.
 *
 * (c) Alchemy <support@alchemy.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPExiftool;

use Doctrine\Common\Collections\ArrayCollection;
use PHPExiftool\Exception\EmptyCollectionException;
use PHPExiftool\Exception\LogicException;
use PHPExiftool\Exception\RuntimeException;
use Psr\Log\LoggerInterface;

/**
 *
 * Exiftool Reader, inspired by Symfony2 Finder.
 *
 * It scans files and directories, and provide an iterator on the FileEntities
 * generated based on the results.
 *
 * Example usage:
 *
 *      $Reader = new Reader();
 *
 *      $Reader->in('/path/to/directory')
 *              ->exclude('tests')
 *              ->extensions(array('jpg', 'xml));
 *
 *      //Throws an exception if no file found
 *      $first = $Reader->first();
 *
 *      //Returns null if no file found
 *      $first = $Reader->getOneOrNull();
 *
 *      foreach($Reader as $entity)
 *      {
 *          //Do your logic with FileEntity
 *      }
 *
 *
 * @todo implement match conditions (-if EXPR) (name or metadata tag)
 * @todo implement match filter
 * @todo implement sort
 * @todo implement -l
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class Reader implements \IteratorAggregate
{
    protected $files = array();
    protected $dirs = array();
    protected $excludeDirs = array();
    protected $extensions = array();
    protected $extensionsToggle = null;
    protected $followSymLinks = false;
    protected $recursive = true;
    protected $ignoreDotFile = false;
    protected $sort = array();
    protected $parser;
    protected $exiftool;
    protected $timeout = 60;

    /**
     *
     * @var ArrayCollection
     */
    protected $collection;
    protected $readers = array();

    /**
     *  Constructor
     */
    public function __construct(Exiftool $exiftool, RDFParser $parser)
    {
        $this->exiftool = $exiftool;
        $this->parser = $parser;
    }

    public function __destruct()
    {
        $this->parser = null;
        $this->collection = null;
    }

    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;

        return $this;
    }

    public function reset()
    {
        $this->files
            = $this->dirs
            = $this->excludeDirs
            = $this->extensions
            = $this->sort
            = $this->readers = array();

        $this->recursive = true;
        $this->ignoreDotFile = $this->followSymLinks = false;
        $this->extensionsToggle = null;

        return $this;
    }

    /**
     * Implements \IteratorAggregate Interface
     *
     * @return \Iterator
     */
    public function getIterator()
    {
        return $this->all()->getIterator();
    }

    /**
     * Add files to scan
     *
     * Example usage:
     *
     *      // Will scan 3 files : dc00.jpg in CWD and absolute
     *      // paths /tmp/image.jpg and /tmp/raw.CR2
     *      $Reader ->files('dc00.jpg')
     *              ->files(array('/tmp/image.jpg', '/tmp/raw.CR2'))
     *
     * @param  string|array $files The files
     * @return Reader
     */
    public function files($files)
    {
        $this->resetResults();
        $this->files = array_merge($this->files, (array) $files);

        return $this;
    }

    /**
     * Add dirs to scan
     *
     * Example usage:
     *
     *      // Will scan 3 dirs : documents in CWD and absolute
     *      // paths /usr and /var
     *      $Reader ->in('documents')
     *              ->in(array('/tmp', '/var'))
     *
     * @param  string|array $dirs The directories
     * @return Reader
     */
    public function in($dirs)
    {
        $this->resetResults();
        $this->dirs = array_merge($this->dirs, (array) $dirs);

        return $this;
    }

    /**
     * Append a reader to this one.
     * Finale result will be the sum of the current reader and all appended ones.
     *
     * @param  Reader $reader The reader to append
     * @return Reader
     */
    public function append(Reader $reader)
    {
        $this->resetResults();
        $this->readers[] = $reader;

        return $this;
    }

    /**
     * Sort results with one or many criteria
     *
     * Example usage:
     *
     *      // Will sort by directory then filename
     *      $Reader ->in('documents')
     *              ->sort(array('directory', 'filename'))
     *
     *      // Will sort by filename
     *      $Reader ->in('documents')
     *              ->sort('filename')
     *
     * @param  string|array $by
     * @return Reader
     */
    public function sort($by)
    {
        static $availableSorts = array(
        'directory', 'filename', 'createdate', 'modifydate', 'filesize'
        );

        foreach ((array) $by as $sort) {

            if ( ! in_array($sort, $availableSorts)) {
                continue;
            }
            $this->sort[] = $sort;
        }

        return $this;
    }

    /**
     * Exclude directories from scan
     *
     * Warning: only first depth directories can be excluded
     * Imagine a directory structure like below, With a scan in "root", only
     * sub1 or sub2 can be excluded, not subsub.
     *
     *      root
     *      ├── sub1
     *      └── sub2
     *          └── subsub
     *
     * Example usage:
     *
     *      // Will scan documents recursively, discarding documents/test
     *      $Reader ->in('documents')
     *              ->exclude(array('test'))
     *
     * @param  string|array $dirs The directories
     * @return Reader
     */
    public function exclude($dirs)
    {
        $this->resetResults();
        $this->excludeDirs = array_merge($this->excludeDirs, (array) $dirs);

        return $this;
    }

    /**
     * Restrict / Discard files based on extensions
     * Extensions are case insensitive
     *
     * @param  string|array   $extensions The list of extension
     * @param  Boolean        $restrict   Toggle restrict/discard method
     * @return Reader
     * @throws LogicException
     */
    public function extensions($extensions, $restrict = true)
    {
        $this->resetResults();

        if ( ! is_null($this->extensionsToggle)) {
            if ((boolean) $restrict !== $this->extensionsToggle) {
                throw new LogicException('You cannot restrict extensions AND exclude extension at the same time');
            }
        }

        $this->extensionsToggle = (boolean) $restrict;

        $this->extensions = array_merge($this->extensions, (array) $extensions);

        return $this;
    }

    /**
     * Toggle to enable follow Symbolic Links
     *
     * @return Reader
     */
    public function followSymLinks()
    {
        $this->resetResults();
        $this->followSymLinks = true;

        return $this;
    }

    /**
     * Ignore files starting with a dot (.)
     *
     * Folders starting with a dot are always exluded due to exiftool behaviour.
     * You should include them manually
     *
     * @return Reader
     */
    public function ignoreDotFiles()
    {
        $this->resetResults();
        $this->ignoreDotFile = true;

        return $this;
    }

    /**
     * Disable recursivity in directories scan.
     * If you only specify files, this toggle has no effect
     *
     * @return Reader
     */
    public function notRecursive()
    {
        $this->resetResults();
        $this->recursive = false;

        return $this;
    }

    /**
     * Return the first result. If no result available, null is returned
     *
     * @return FileEntity
     */
    public function getOneOrNull()
    {
        return count($this->all()) === 0 ? null : $this->all()->first();
    }

    /**
     * Return the first result. If no result available, throws an exception
     *
     * @return FileEntity
     * @throws EmptyCollectionException
     */
    public function first()
    {
        if (count($this->all()) === 0) {
            throw new EmptyCollectionException('Collection is empty');
        }

        return $this->all()->first();
    }

    /**
     * Perform the scan and returns all the results
     *
     * @return ArrayCollection
     */
    public function all()
    {
        if (! $this->collection) {
            $this->collection = $this->buildQueryAndExecute();
        }

        if ($this->readers) {
            $elements = $this->collection->toArray();

            $this->collection = null;

            foreach ($this->readers as $reader) {
                $elements = array_merge($elements, $reader->all()->toArray());
            }

            $this->collection = new ArrayCollection($elements);
        }

        return $this->collection;
    }

    public static function create(LoggerInterface $logger)
    {
        return new static(new Exiftool($logger), new RDFParser());
    }

    /**
     * Reset any computed result
     *
     * @return Reader
     */
    protected function resetResults()
    {
        $this->collection = null;

        return $this;
    }

    /**
     * Build the command returns an ArrayCollection of FileEntity
     *
     * @return ArrayCollection
     */
    protected function buildQueryAndExecute()
    {
        $result = '';

        try {
            $result = trim($this->exiftool->executeCommand($this->buildQuery(), $this->timeout));
        } catch (RuntimeException $e) {
            /**
             * In case no file found, an exit code 1 is returned
             */
            if (! $this->ignoreDotFile) {
                throw $e;
            }
        }

        if ($result === '') {
            return new ArrayCollection();
        }

        $this->parser->open($result);

        return $this->parser->ParseEntities();
    }

    /**
     * Compute raw exclude rules to simple ones, based on exclude dirs and search dirs
     *
     * @param  string           $rawExcludeDirs
     * @param  string           $rawDirs
     * @return array
     * @throws RuntimeException
     */
    protected function computeExcludeDirs($rawExcludeDirs, $rawSearchDirs)
    {
        $excludeDirs = array();

        foreach ($rawExcludeDirs as $excludeDir) {
            $found = false;
            /**
             * is this a relative path ?
             */
            foreach ($rawSearchDirs as $dir) {
                $currentPrefix = realpath($dir) . DIRECTORY_SEPARATOR;

                $supposedExcluded = str_replace($currentPrefix, '', realpath($currentPrefix . $excludeDir));

                if (! $supposedExcluded) {
                    continue;
                }

                if (strpos($supposedExcluded, DIRECTORY_SEPARATOR) === false) {
                    $excludeDirs[] = $supposedExcluded;
                    $found = true;
                    break;
                }
            }

            if ($found) {
                continue;
            }

            /**
             * is this an absolute path ?
             */
            $supposedExcluded = realpath($excludeDir);

            if ($supposedExcluded) {
                foreach ($rawSearchDirs as $dir) {
                    $searchDir = realpath($dir) . DIRECTORY_SEPARATOR;

                    $supposedRelative = str_replace($searchDir, '', $supposedExcluded);

                    if (strpos($supposedRelative, DIRECTORY_SEPARATOR) !== false) {
                        continue;
                    }

                    if (strpos($supposedExcluded, $searchDir) !== 0) {
                        continue;
                    }

                    if ( ! trim($supposedRelative)) {
                        continue;
                    }

                    $excludeDirs[] = $supposedRelative;
                    $found = true;
                    break;
                }
            }


            if (! $found) {
                throw new RuntimeException(sprintf("Invalid exclude dir %s ; Exclude dir is limited to the name of a directory at first depth", $excludeDir));
            }
        }

        return $excludeDirs;
    }

    /**
     * Build query from criterias
     *
     * @return string
     *
     * @throws LogicException
     */
    protected function buildQuery()
    {
        if (! $this->dirs && ! $this->files) {
            throw new LogicException('You have not set any files or directory');
        }

        $command = '-n -q -b -X -charset UTF8';

        if ($this->recursive) {
            $command .= ' -r';
        }

        if (!empty($this->extensions)) {
            if (! $this->extensionsToggle) {
                $extensionPrefix = ' --ext';
            } else {
                $extensionPrefix = ' -ext';
            }

            foreach ($this->extensions as $extension) {
                $command .= $extensionPrefix . ' ' . escapeshellarg($extension);
            }
        }

        if (! $this->followSymLinks) {
            $command .= ' -i SYMLINKS';
        }

        if ($this->ignoreDotFile) {
            $command .= " -if '\$filename !~ /^\./'";
        }

        foreach ($this->sort as $sort) {
            $command .= ' -fileOrder ' . $sort;
        }

        foreach ($this->computeExcludeDirs($this->excludeDirs, $this->dirs) as $excludedDir) {
            $command .= ' -i ' . escapeshellarg($excludedDir);
        }

        foreach ($this->dirs as $dir) {
            $command .= ' ' . escapeshellarg(realpath($dir));
        }

        foreach ($this->files as $file) {
            $command .= ' ' . escapeshellarg(realpath($file));
        }

        return $command;
    }
}

Zerion Mini Shell 1.0