1 | <?php |
||||
2 | |||||
3 | namespace Mostafaznv\PdfOptimizer\Actions; |
||||
4 | |||||
5 | use Mostafaznv\PdfOptimizer\DTOs\OptimizeResult; |
||||
6 | use Mostafaznv\PdfOptimizer\Laravel\Concerns\Disk; |
||||
7 | use Mostafaznv\PdfOptimizer\Laravel\Concerns\File; |
||||
8 | use Mostafaznv\PdfOptimizer\PdfOptimizerLogger; |
||||
9 | use Psr\Log\LoggerInterface; |
||||
10 | use Symfony\Component\Process\Process; |
||||
11 | |||||
12 | |||||
13 | class OptimizePdfAction |
||||
14 | { |
||||
15 | private readonly ?File $file; |
||||
16 | private readonly ?Disk $outputDisk; |
||||
17 | |||||
18 | private int $timeout = 60; |
||||
19 | private LoggerInterface $logger; |
||||
20 | |||||
21 | |||||
22 | public function __construct(?File $file = null, ?Disk $outputDisk = null) |
||||
23 | { |
||||
24 | $this->file = $file; |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
25 | $this->outputDisk = $outputDisk; |
||||
0 ignored issues
–
show
|
|||||
26 | |||||
27 | $this->logger(new PdfOptimizerLogger); |
||||
28 | } |
||||
29 | |||||
30 | public static function init(?File $file = null, ?Disk $outputDisk = null): self |
||||
31 | { |
||||
32 | return new self($file, $outputDisk); |
||||
33 | } |
||||
34 | |||||
35 | |||||
36 | public function setTimeout(int $timeout): self |
||||
37 | { |
||||
38 | $this->timeout = $timeout; |
||||
39 | |||||
40 | return $this; |
||||
41 | } |
||||
42 | |||||
43 | public function execute(array $command, string $input, string $output): OptimizeResult |
||||
44 | { |
||||
45 | $this->logger->info('Start optimizing'); |
||||
46 | |||||
47 | $originalOutput = $output; |
||||
48 | [$input, $output] = $this->io($input, $output); |
||||
49 | |||||
50 | $command = $this->command($command, $input, $output); |
||||
51 | |||||
52 | $process = new Process($command); |
||||
53 | $process->setTimeout($this->timeout); |
||||
54 | $process->run(); |
||||
55 | |||||
56 | $status = $process->isSuccessful(); |
||||
57 | |||||
58 | if ($status) { |
||||
59 | $this->store($output, $originalOutput); |
||||
60 | } |
||||
61 | |||||
62 | $this->cleanup(); |
||||
63 | $this->logResult($process); |
||||
64 | |||||
65 | return OptimizeResult::make( |
||||
66 | status: $status, |
||||
67 | message: !$status ? "error: {$process->getErrorOutput()}" : '' |
||||
68 | ); |
||||
69 | } |
||||
70 | |||||
71 | public function logger(?LoggerInterface $logger): self |
||||
72 | { |
||||
73 | if ($logger) { |
||||
74 | $this->logger = $logger; |
||||
75 | } |
||||
76 | |||||
77 | return $this; |
||||
78 | } |
||||
79 | |||||
80 | private function io(string $input, string $output): array |
||||
81 | { |
||||
82 | if ($this->file) { |
||||
83 | $input = $this->file->getLocalPath(); |
||||
84 | } |
||||
85 | |||||
86 | if ($this->outputDisk?->getAdapter()) { |
||||
87 | $output = ltrim($output, '/'); |
||||
88 | $dirname = pathinfo($output, PATHINFO_DIRNAME); |
||||
89 | |||||
90 | $disk = $this->outputDisk->isLocalDisk() |
||||
0 ignored issues
–
show
The method
isLocalDisk() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||
91 | ? $this->outputDisk->getAdapter() |
||||
92 | : $this->outputDisk->getTemporaryDisk(); |
||||
93 | |||||
94 | |||||
95 | if ($dirname != '.' and !$disk->directoryExists($dirname)) { |
||||
0 ignored issues
–
show
It seems like
$dirname can also be of type array ; however, parameter $path of Illuminate\Filesystem\Fi...pter::directoryExists() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
96 | $disk->makeDirectory($dirname); |
||||
0 ignored issues
–
show
It seems like
$dirname can also be of type array ; however, parameter $path of Illuminate\Filesystem\Fi...dapter::makeDirectory() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
97 | } |
||||
98 | |||||
99 | $output = $disk->path($output); |
||||
100 | } |
||||
101 | |||||
102 | $this->logger->info("Input: $input", [ |
||||
103 | 'input' => $input, |
||||
104 | ]); |
||||
105 | |||||
106 | $this->logger->info("Output: $output", [ |
||||
107 | 'output' => $output, |
||||
108 | ]); |
||||
109 | |||||
110 | return [$input, $output]; |
||||
111 | } |
||||
112 | |||||
113 | private function command(array $command, string $input, string $output): array |
||||
114 | { |
||||
115 | if ($output) { |
||||
116 | $exists = false; |
||||
117 | |||||
118 | foreach ($command as $value) { |
||||
119 | if (str_starts_with($value, '-sOutputFile')) { |
||||
120 | $exists = true; |
||||
121 | } |
||||
122 | } |
||||
123 | |||||
124 | if (!$exists) { |
||||
125 | $command[] = "-sOutputFile=$output"; |
||||
126 | } |
||||
127 | } |
||||
128 | |||||
129 | if ($input) { |
||||
130 | $exists = false; |
||||
131 | |||||
132 | foreach ($command as $value) { |
||||
133 | if (str_ends_with($value, '.pdf') and !str_starts_with($value, '-sOutputFile')) { |
||||
134 | $exists = true; |
||||
135 | } |
||||
136 | } |
||||
137 | |||||
138 | if (!$exists) { |
||||
139 | $command[] = $input; |
||||
140 | } |
||||
141 | } |
||||
142 | |||||
143 | $this->logger->info('Command: ' . implode(', ', $command), [ |
||||
144 | 'command' => $command, |
||||
145 | ]); |
||||
146 | |||||
147 | return $command; |
||||
148 | } |
||||
149 | |||||
150 | private function store(string $output, string $originalOutput): void |
||||
151 | { |
||||
152 | if ($this->outputDisk?->getAdapter()) { |
||||
153 | if (!$this->outputDisk->isLocalDisk()) { |
||||
154 | $this->logger->info('Store optimized file to remote disk', [ |
||||
155 | 'path' => $originalOutput |
||||
156 | ]); |
||||
157 | |||||
158 | $this->outputDisk->getAdapter()->writeStream( |
||||
159 | $originalOutput, |
||||
160 | fopen($output, 'r') |
||||
161 | ); |
||||
162 | } |
||||
163 | } |
||||
164 | } |
||||
165 | |||||
166 | private function cleanup(): void |
||||
167 | { |
||||
168 | $this->logger->info('Cleanup temporary files'); |
||||
169 | |||||
170 | $this->file?->cleanup(); |
||||
171 | $this->outputDisk?->cleanupTemporaryDirectory(); |
||||
172 | } |
||||
173 | |||||
174 | private function logResult(Process $process): void |
||||
175 | { |
||||
176 | if (!$process->isSuccessful()) { |
||||
177 | $this->logger->error('Process ended with error', [ |
||||
178 | 'output_log' => $process->getOutput(), |
||||
179 | 'error_output_log' => $process->getErrorOutput() |
||||
180 | ]); |
||||
181 | |||||
182 | return; |
||||
183 | } |
||||
184 | |||||
185 | $this->logger->info('Process successfully ended', [ |
||||
186 | 'output_log' => $process->getOutput() |
||||
187 | ]); |
||||
188 | } |
||||
189 | } |
||||
190 |