From be8f1fde299369bd4f1cc0173fe7161e4035e0bf Mon Sep 17 00:00:00 2001 From: jygaulier Date: Mon, 13 May 2024 11:39:41 +0200 Subject: [PATCH] allow to detach classes creation to client-side (callback) --- bin/console | 4 +- .../ClassUtils/tagGroupBuilder.php | 10 ++- lib/PHPExiftool/InformationDumper.php | 53 ++------------ lib/PHPExiftool/PHPExiftool.php | 71 +++++++++++++++---- ...sBuilder.php => ClassesBuilderCommand.php} | 24 +++++-- 5 files changed, 91 insertions(+), 71 deletions(-) rename lib/PHPExiftool/Tool/Command/{ClassesBuilder.php => ClassesBuilderCommand.php} (75%) diff --git a/bin/console b/bin/console index dc9182523..8621adb2b 100755 --- a/bin/console +++ b/bin/console @@ -10,9 +10,9 @@ * file that was distributed with this source code. */ +use PHPExiftool\Tool\Command\ClassesBuilderCommand; use PHPExiftool\Tool\Command\DumpCommand; use Symfony\Component\Console\Application; -use PHPExiftool\Tool\Command\ClassesBuilder; require __DIR__ . '/../vendor/autoload.php'; @@ -22,7 +22,7 @@ if (!class_exists('Symfony\Component\DomCrawler\Crawler')) { } $cli = new Application('PHPExiftool', '2.2'); -$cli->addCommands(array(new ClassesBuilder())); +$cli->addCommands(array(new ClassesBuilderCommand())); $cli->addCommands(array(new DumpCommand())); $cli->run(); diff --git a/lib/PHPExiftool/ClassUtils/tagGroupBuilder.php b/lib/PHPExiftool/ClassUtils/tagGroupBuilder.php index a13af1495..a2e1ec47b 100644 --- a/lib/PHPExiftool/ClassUtils/tagGroupBuilder.php +++ b/lib/PHPExiftool/ClassUtils/tagGroupBuilder.php @@ -12,7 +12,7 @@ class tagGroupBuilder extends Builder private ?int $writable = -1; private array $tags = []; private array $descriptions = []; - private array $flags = []; // count of occurences for eache flag + private array $flags = []; // count of occurences for each flag public function addTag(array $tagComments, array $tagProperties) { @@ -134,11 +134,12 @@ public function setFlags(array $flags) } } - public function write(string $path): Builder + public function computeProperties(): Builder { $this->properties['phpType'] = $this->php_type ?: "mixed"; $this->properties['isWritable'] = ($this->writable === 1); $this->properties['description'] = $this->descriptions; + $this->properties['tags'] = $this->tags; if(!is_null($this->count)) { // 0 = default parent value $this->properties['count'] = max(0, $this->count); } @@ -157,8 +158,11 @@ public function write(string $path): Builder $this->properties["flags"] = $binFlags; } - $this->properties['tags'] = $this->tags; + return $this; + } + public function write(string $path): Builder + { parent::write($path); return $this; } diff --git a/lib/PHPExiftool/InformationDumper.php b/lib/PHPExiftool/InformationDumper.php index fcb9d0866..e535360e7 100644 --- a/lib/PHPExiftool/InformationDumper.php +++ b/lib/PHPExiftool/InformationDumper.php @@ -56,17 +56,14 @@ class InformationDumper private Exiftool $exiftool; private LoggerInterface $logger; private int $currentXmlLine; - private string $rootPath; private string $rootNamespace; - public function __construct(Exiftool $exiftool, string $rootPath) + public function __construct(Exiftool $exiftool) { $this->exiftool = $exiftool; $this->logger = new NullLogger(); $this->rootNamespace = PHPExiftool::ROOT_NAMESPACE . '\\' . PHPExiftool::SUBDIR; - - $this->rootPath = $rootPath . '/' . PHPExiftool::SUBDIR; } public function setLogger(LoggerInterface $logger) @@ -123,29 +120,10 @@ public function listDatas(string $type = self::LISTTYPE_SUPPORTED_XML, array $op return $dom; } - public function dumpClasses(array $options, array $lngs) + public function dumpClasses(array $options, array $lngs, callable $callback = null) { $dom = $this->listDatas(InformationDumper::LISTTYPE_SUPPORTED_XML, $options); - @mkdir($this->rootPath, 0754, true); - - $this->logger->info(sprintf('Erasing previous files "%s/*" ', $this->rootPath)); - try { - $cmd = 'rm -Rf ' . $this->rootPath . '/* 2> /dev/null'; - $output = []; - @exec($cmd, $output); - } - catch (\Exception $e) { - // no-op - } - - $this->logger->info('Generating classes... '); - $this->extractDump($dom, $lngs); - } - - protected function extractDump(DOMDocument $dump, array $lngs) - { - $nGroups = 0; $nTags = 0; /** @var tagGroupBuilder[] $tagGroupBuilders */ @@ -153,7 +131,7 @@ protected function extractDump(DOMDocument $dump, array $lngs) $group_ids = []; // to check group_id belongs to only one class $crawler = new Crawler(); - $crawler->addDocument($dump); + $crawler->addDocument($dom); $tag_count = count($crawler->filter('table>tag')); $this->logger->info(sprintf('tag count : %d', $tag_count)); @@ -262,7 +240,6 @@ protected function extractDump(DOMDocument $dump, array $lngs) } $this->logger->info(sprintf("building \"%s\"", $fq_classname)); - $nGroups++; $tagGroupBuilder = new tagGroupBuilder( $this->rootNamespace, @@ -385,28 +362,12 @@ protected function extractDump(DOMDocument $dump, array $lngs) } } - $this->logger->info(sprintf("Writing %d classes... ", $nGroups)); - foreach ($tagGroupBuilders as $fq_classname => $builder) { - $builder->write($this->rootPath); + $builder->computeProperties(); + if($callback) { + $callback($fq_classname, $builder); + } } - - $this->logger->info(sprintf("%d classes covers %d tags.", $nGroups, $nTags)); - - $this->logger->info(sprintf("Writing helper Table")); - ksort($group_ids, SORT_NATURAL + SORT_FLAG_CASE); - $file = $this->rootPath . '/Helper.php'; - file_put_contents($file, - "rootNamespace . ";\n\n" - . "use PHPExiftool\\Driver\\HelperInterface;\n\n" - . "class Helper implements HelperInterface\n" - . "{\n" - . " static function getIndex(): array {\n" - . " return " . var_export($group_ids, true) . ";\n" - . " }\n" - . "}\n" - ); } protected function getPhpType(string $type): ?string diff --git a/lib/PHPExiftool/PHPExiftool.php b/lib/PHPExiftool/PHPExiftool.php index ef9ffba12..fcbae5812 100644 --- a/lib/PHPExiftool/PHPExiftool.php +++ b/lib/PHPExiftool/PHPExiftool.php @@ -2,6 +2,7 @@ namespace PHPExiftool; +use PHPExiftool\ClassUtils\tagGroupBuilder; use PHPExiftool\Driver\TagGroupFactory; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -9,44 +10,84 @@ class PHPExiftool { - const v = "3.1.2"; + const v = "4.1.0"; const ROOT_NAMESPACE = "PHPExiftool\\Driver"; const SUBDIR = "TagGroup"; - private string $classesRootDirectory; + private ?string $classesRootDirectory = null; private LoggerInterface $logger; private Factory $factory; - public function __construct(string $classesRootDirectory, ?LoggerInterface $logger = null) + public function __construct(?string $classesRootDirectory = null, ?LoggerInterface $logger = null) { - $c = substr($classesRootDirectory, 0, 1); - if($c !== '/') { - throw new DirectoryNotFoundException(sprintf("classesRootDirectory must be absolute, \"%s\" given", $classesRootDirectory)); - } - if(!file_exists($classesRootDirectory) || !is_writable($classesRootDirectory)) { - throw new DirectoryNotFoundException(sprintf("classesRootDirectory \"%s\" must exists and be writable", $classesRootDirectory)); + if($classesRootDirectory !== null) { + $this->setClassesRootDirectory($classesRootDirectory); } - - $this->classesRootDirectory = realpath($classesRootDirectory); if($logger === null) { $logger = new NullLogger(); } - $this->logger = $logger; + $this->setLogger($logger); $this->factory = new Factory($this); } + public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } + /** + * @param string|null $classesRootDirectory + */ + public function setClassesRootDirectory(?string $classesRootDirectory): void + { + $c = substr($classesRootDirectory, 0, 1); + if ($c !== '/') { + throw new DirectoryNotFoundException(sprintf("classesRootDirectory must be absolute, \"%s\" given", $classesRootDirectory)); + } + if (!file_exists($classesRootDirectory) || !is_writable($classesRootDirectory)) { + throw new DirectoryNotFoundException(sprintf("classesRootDirectory \"%s\" must exists and be writable", $classesRootDirectory)); + } - public function generateClasses(array $options, array $lngs = ['en']): void + $this->classesRootDirectory = realpath($classesRootDirectory); + } + + public function generateClasses(array $options, array $lngs = ['en'], ?callable $cb = null): int { - $dumper = new InformationDumper(new Exiftool(new NullLogger()), $this->classesRootDirectory); + $classesDirectory = $this->classesRootDirectory . '/' . self::SUBDIR; + $rootNamespace = self::ROOT_NAMESPACE . '\\' . self::SUBDIR; + + $dumper = new InformationDumper(new Exiftool($this->logger)); + + $group_ids = []; + $dumper->dumpClasses( + $options, + $lngs, + $cb ?: function (string $fq_classname, tagGroupBuilder $tgb) use($classesDirectory, &$group_ids) { + $tgb->write($classesDirectory); + $group_ids[$tgb->getProperty('id')] = $fq_classname; + } + ); + + if(!$cb) { + $this->logger->info(sprintf("Writing helper Table")); + ksort($group_ids, SORT_NATURAL + SORT_FLAG_CASE); + $file = $classesDirectory . '/Helper.php'; + file_put_contents($file, + "dumpClasses($options, $lngs); + return count($group_ids); } public function isClassesGenerated(): bool diff --git a/lib/PHPExiftool/Tool/Command/ClassesBuilder.php b/lib/PHPExiftool/Tool/Command/ClassesBuilderCommand.php similarity index 75% rename from lib/PHPExiftool/Tool/Command/ClassesBuilder.php rename to lib/PHPExiftool/Tool/Command/ClassesBuilderCommand.php index b96170321..79a05c21b 100644 --- a/lib/PHPExiftool/Tool/Command/ClassesBuilder.php +++ b/lib/PHPExiftool/Tool/Command/ClassesBuilderCommand.php @@ -15,6 +15,7 @@ use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; +use PHPExiftool\ClassUtils\tagGroupBuilder; use PHPExiftool\Exiftool; use PHPExiftool\InformationDumper; use PHPExiftool\PHPExiftool; @@ -29,7 +30,7 @@ * @author Romain Neutron - imprec@gmail.com * @license http://opensource.org/licenses/MIT MIT */ -class ClassesBuilder extends Command +class ClassesBuilderCommand extends Command { protected InputInterface $input; protected OutputInterface $output; @@ -80,14 +81,27 @@ protected function execute(InputInterface $input, OutputInterface $output): int } - $dumper = new InformationDumper(new Exiftool($logger), $input->getOption('path')); - $dumper->setLogger($logger); + $path = realpath($input->getOption('path')); + $subPath = $path . '/' . PHPExiftool::SUBDIR; // security : do NOT rm passed cli option + @mkdir($subPath, 0755, true); + $logger->info(sprintf('Erasing previous files "%s/*" ', $subPath)); + try { + $cmd = 'rm -Rf ' . $subPath . '/* 2> /dev/null'; + $output = []; + @exec($cmd, $output); + } + catch (\Exception $e) { + // no-op + } + $logger->info('Generating classes... '); - $dumper->dumpClasses($options, $input->getOption('lng')); + $PHPExiftool = new PHPExiftool($path, $logger); + $nClasses = $PHPExiftool->generateClasses($options, $input->getOption('lng')); $this->output->writeln( sprintf( - 'Generated in %d seconds (%d Mb)', + 'Generated %d classes in %d seconds (%d Mb)', + $nClasses, (microtime(true) - $start), memory_get_peak_usage() >> 20 )