tikiwiki/packages/tiki-pkg-mediaalchemyst/alchemy/phpexiftool/lib/PHPExiftool/ExiftoolServer.php

143 lines
3.8 KiB
PHP
Raw Permalink Normal View History

2023-11-20 21:52:04 +01:00
<?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 PHPExiftool\Exception\RuntimeException;
use Symfony\Component\Process\Process;
class ExiftoolServer extends Exiftool
{
private $pipefile;
private $server;
private $offset = 0;
public function __construct()
{
$this->setUp();
}
public function __destruct()
{
$this->cleanup();
}
public function reset()
{
$this->cleanup();
$this->setUp();
}
public function start()
{
$this->server->start();
}
public function stop()
{
if ($this->isRunning()) {
file_put_contents($this->pipefile, "-stay_open False\n", FILE_APPEND);
}
$this->server->stop();
}
public function isRunning()
{
return null !== $this->server && $this->server->isRunning();
}
public function executeCommand($commands, $timeout = 4)
{
$optwithargs = array('-i', '-charset', '-if', '-w', '-common_args');
if (true !== $this->isRunning()) {
throw new RuntimeException('Server is not running');
}
$prev = null;
// // first split execute (sub queries)
//
// if (false !== $pos = strpos($commands, '-common_args')) {
// $common_args = substr($commands, $pos + 12);
//
// $recomposed = array();
//
// foreach (explode(' -execute ', substr($commands, 0, $pos)) as $subcommand) {
// $recomposed[] = $subcommand . ' ' . $common_args;
// }
// $commands = implode(' -execute ', $recomposed);
// }
foreach (explode(' ', $commands) as $command) {
if ($command == '-q') {
continue;
}
if (substr($command, 0, 1) === "'" && substr($command, -1) === "'") {
$command = substr($command, 1, -1);
}
if (substr($command, 0, 1) === '"' && substr($command, -1) === '"') {
$command = substr($command, 1, -1);
}
$end = "\n";
file_put_contents($this->pipefile, $command . $end, FILE_APPEND);
}
file_put_contents($this->pipefile, "\n-execute\n", FILE_APPEND);
// here we send sigcont
//$this->server->signal(SIGCONT);
$start = microtime(true);
while ((strlen($this->server->getOutput()) <= $this->offset || substr(substr($this->server->getOutput(), $this->offset), -8) !== "{ready}\n") && (microtime(true) - $start) < $timeout) {
usleep(25000);
}
// var_dump(microtime(true) - $start);
// server output should be cached here because streams are polled
// everytime I request the output
$outputIsValid = substr($this->server->getOutput(), -8) === "{ready}\n";
$output = $outputIsValid ? substr($this->server->getOutput(), $this->offset, -8) : '';
$this->offset = strlen($this->server->getOutput());
if (trim($output) === '' && $outputIsValid === false && $this->server->getErrorOutput()) {
throw new RuntimeException('Command failed');
}
return $output;
}
private function setUp()
{
$this->pipefile = tempnam(sys_get_temp_dir(), 'exiftool-pipe');
$this->server = new Process(self::getBinary() . ' -stay_open True -@ ' . $this->pipefile);
}
private function cleanup()
{
$this->stop();
if (file_exists($this->pipefile) && is_writable($this->pipefile)) {
unlink($this->pipefile);
$this->pipefile = null;
}
$this->server = null;
}
}