Failed Conditions
Push — master ( 5e65a4...91e9bd )
by Sébastien
03:12
created

InfoService::getSymfonyProcess()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 2
dl 0
loc 17
ccs 6
cts 6
cp 1
crap 1
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools\Video;
6
7
use Psr\Log\LoggerInterface;
8
use Psr\Log\LogLevel;
9
use Psr\Log\NullLogger;
10
use Soluble\MediaTools\Common\Assert\PathAssertionsTrait;
11
use Soluble\MediaTools\Common\Exception\FileNotFoundException;
12
use Soluble\MediaTools\Common\Process\ProcessFactory;
13
use Soluble\MediaTools\Common\Process\ProcessParamsInterface;
14
use Soluble\MediaTools\Video\Config\FFProbeConfigInterface;
15
use Soluble\MediaTools\Video\Exception\InfoExceptionInterface;
16
use Soluble\MediaTools\Video\Exception\InfoProcessExceptionInterface;
17
use Soluble\MediaTools\Video\Exception\MissingInputFileException;
18
use Soluble\MediaTools\Video\Exception\ProcessFailedException;
19
use Soluble\MediaTools\Video\Exception\RuntimeException;
20
use Symfony\Component\Process\Exception as SPException;
21
use Symfony\Component\Process\Process;
22
23
class InfoService implements InfoServiceInterface
24
{
25 2
    use PathAssertionsTrait;
26
27 2
    /** @var FFProbeConfigInterface */
28 2
    protected $ffprobeConfig;
29
30
    /** @var LoggerInterface|NullLogger */
31
    protected $logger;
32
33
    public function __construct(FFProbeConfigInterface $ffProbeConfig, ?LoggerInterface $logger = null)
34
    {
35
        $this->ffprobeConfig = $ffProbeConfig;
36
        $this->logger        = $logger ?? new NullLogger();
37
    }
38
39 1
    /**
40
     * Return ready-to-run symfony process object that you can use
41 1
     * to `run()` or `start()` programmatically. Useful if you want to make
42 1
     * things your way...
43 1
     *
44 1
     * @see https://symfony.com/doc/current/components/process.html
45 1
     */
46
    public function getSymfonyProcess(string $inputFile, ?ProcessParamsInterface $processParams = null): Process
47
    {
48
        $ffprobeCmd = trim(sprintf(
49
            '%s %s %s',
50 1
            $this->ffprobeConfig->getBinary(),
51
            implode(' ', [
52
                '-v quiet',
53 1
                '-print_format json',
54 1
                '-show_format',
55 1
                '-show_streams',
56 1
            ]),
57
            sprintf('-i %s', escapeshellarg($inputFile))
58 1
        ));
59
60
        $pp = $processParams ?? $this->ffprobeConfig->getProcessParams();
61
62
        return (new ProcessFactory($ffprobeCmd, $pp))();
63
    }
64
65
    /**
66
     * @throws InfoExceptionInterface
67
     * @throws InfoProcessExceptionInterface
68 2
     * @throws ProcessFailedException
69
     * @throws MissingInputFileException
70
     * @throws RuntimeException
71 2
     */
72 1
    public function getInfo(string $file): Info
73
    {
74 1
        try {
75 1
            try {
76 1
                $this->ensureFileExists($file);
77 1
                $process = $this->getSymfonyProcess($file);
78
79
                $process->mustRun();
80
                $output = $process->getOutput();
81
            } catch (FileNotFoundException $e) {
82
                throw new MissingInputFileException($e->getMessage());
83
            } catch (SPException\ProcessFailedException | SPException\ProcessTimedOutException | SPException\ProcessSignaledException $e) {
84 1
                throw new ProcessFailedException($e->getProcess(), $e);
85
            } catch (SPException\RuntimeException $e) {
86
                throw new RuntimeException($e->getMessage());
87
            }
88
        } catch (\Throwable $e) {
89
            $exceptionNs = explode('\\', get_class($e));
90
            $this->logger->log(
91
                ($e instanceof MissingInputFileException) ? LogLevel::WARNING : LogLevel::ERROR,
92
                sprintf(
93
                    'Video info retrieval failed \'%s\' with \'%s\'. "%s(%s)"',
94
                    $exceptionNs[count($exceptionNs) - 1],
95
                    __METHOD__,
96
                    $e->getMessage(),
97
                    $file
98
                )
99
            );
100
            throw $e;
101
        }
102
103
        return Info::createFromFFProbeJson($file, $output);
104
    }
105
}
106