Passed
Push — master ( 20660a...ab558f )
by Amin
02:37
created

Export::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the PHP-FFmpeg-video-streaming package.
5
 *
6
 * (c) Amin Yazdanpanah <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Streaming;
13
14
use FFMpeg\Exception\ExceptionInterface;
15
use Streaming\Clouds\AWS;
16
use Streaming\Clouds\Cloud;
17
use Streaming\Clouds\CloudInterface;
18
use Streaming\Clouds\GoogleCloudStorage;
19
use Streaming\Clouds\MicrosoftAzure;
20
use Streaming\Exception\Exception;
21
use Streaming\Exception\InvalidArgumentException;
22
use Streaming\Exception\RuntimeException;
23
use Streaming\Filters\Filter;
24
use Streaming\Traits\Formats;
25
26
abstract class Export
27
{
28
    use Formats;
29
30
    /** @var object */
31
    protected $media;
32
33
    /** @var array */
34
    protected $path_info;
35
36
    /** @var string */
37
    protected $strict = "-2";
38
39
    /** @var string */
40
    protected $tmp_dir;
41
42
    /**
43
     * Export constructor.
44
     * @param Media $media
45
     */
46
    public function __construct(Media $media)
47
    {
48
        $this->media = $media;
49
        $this->path_info = pathinfo($media->getPath());
50
    }
51
52
    /**
53
     * @param string $path
54
     * @param array $clouds
55
     * @param bool $metadata
56
     * @return mixed
57
     * @throws Exception
58
     */
59
    public function save(string $path = null, array $clouds = [], bool $metadata = true)
60
    {
61
        $save_to = $this->getPath($path, $clouds);
62
63
        try {
64
            $this->media
65
                ->addFilter($this->getFilter())
66
                ->save($this->getFormat(), $save_to);
67
        } catch (ExceptionInterface $e) {
68
            throw new RuntimeException(sprintf("There was an error saving files: \n\n reason: \n %s", $e->getMessage()),
69
                $e->getCode(),
70
                $e
71
            );
72
        }
73
74
        $this->saveToClouds($clouds);
75
        $this->moveTmpFolder($path);
76
77
        return ($metadata) ? (new Metadata($this))->extract() : $this;
78
    }
79
80
    /**
81
     * @return Filter
82
     */
83
    abstract protected function getFilter(): Filter;
84
85
    /**
86
     * @param $path
87
     * @param $clouds
88
     * @return string
89
     * @throws Exception
90
     */
91
    private function getPath($path, $clouds): string
92
    {
93
        if (null !== $path) {
94
            $this->path_info = pathinfo($path);
95
        }
96
97
        if ($clouds) {
98
            $this->tmpDirectory($path);
99
        }
100
101
        if (null === $path && $this->media->isTmp() && !$clouds) {
102
            throw new InvalidArgumentException("You need to specify a path. It is not possible to save to a tmp directory");
103
        }
104
105
        $dirname = str_replace("\\", "/", $this->path_info["dirname"]);
106
        $filename = substr($this->path_info["filename"], -50);
107
108
        FileManager::makeDir($dirname);
109
110
        if ($this instanceof DASH) {
111
            $path = $dirname . "/" . $filename . ".mpd";
112
        } elseif ($this instanceof HLS) {
113
            $representations = $this->getRepresentations();
114
            $path = $dirname . "/" . $filename . "_" . end($representations)->getHeight() . "p.m3u8";
115
            ExportHLSPlaylist::savePlayList($dirname . DIRECTORY_SEPARATOR . $filename . ".m3u8", $this->getRepresentations(), $filename);
116
        }
117
118
        return $path;
119
    }
120
121
    /**
122
     * @param string $url
123
     * @param string $name
124
     * @param string|null $path
125
     * @param string $method
126
     * @param array $headers
127
     * @param array $options
128
     * @return mixed
129
     * @throws Exception
130
     * @deprecated this method is deprecated
131
     */
132
    // @TODO: should be removed in the next releases.
133
    public function saveToCloud(
134
        string $url,
135
        string $name,
136
        string $path = null,
137
        string $method = 'GET',
138
        array $headers = [],
139
        array $options = []
140
    )
141
    {
142
        @trigger_error('saveToCloud method is deprecated and will be removed in a future release. Use Cloud instead', E_USER_DEPRECATED);
143
        if ($this instanceof HLS && $this->getTsSubDirectory()) {
144
            throw new InvalidArgumentException("It is not possible to create subdirectory in a cloud");
145
        }
146
        $results = $this->saveToTemporaryFolder($path);
0 ignored issues
show
Deprecated Code introduced by
The function Streaming\Export::saveToTemporaryFolder() has been deprecated: this method is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

146
        $results = /** @scrutinizer ignore-deprecated */ $this->saveToTemporaryFolder($path);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
147
        sleep(1);
148
149
        $cloud = new Cloud($url, $method, $options);
150
        $cloud->uploadDirectory($this->tmp_dir, ['name' => $name, 'headers' => $headers]);
151
152
        $this->moveTmpFolder($path);
153
154
        return $results;
155
    }
156
157
    /**
158
     * @param array $config
159
     * @param string $dest
160
     * @param string|null $path
161
     * @return mixed
162
     * @throws Exception
163
     * @deprecated this method is deprecated
164
     */
165
    // @TODO: should be removed in the next releases.
166
    public function saveToS3(
167
        array $config,
168
        string $dest,
169
        string $path = null
170
    )
171
    {
172
        @trigger_error('saveToS3 method is deprecated and will be removed in a future release. Use AWS instead', E_USER_DEPRECATED);
173
        $results = $this->saveToTemporaryFolder($path);
0 ignored issues
show
Deprecated Code introduced by
The function Streaming\Export::saveToTemporaryFolder() has been deprecated: this method is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

173
        $results = /** @scrutinizer ignore-deprecated */ $this->saveToTemporaryFolder($path);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
174
        sleep(1);
175
176
        $aws = new AWS($config);
177
        $aws->uploadDirectory($this->tmp_dir, ['dest' => $dest]);
178
179
        $this->moveTmpFolder($path);
180
181
        return $results;
182
    }
183
184
    /**
185
     * @param array $config
186
     * @param string $bucket
187
     * @param string|null $path
188
     * @param array $options
189
     * @param bool $userProject
190
     * @return mixed
191
     * @throws Exception
192
     * @deprecated this method is deprecated
193
     */
194
    // @TODO: should be removed in the next releases.
195
    public function saveToGCS(
196
        array $config,
197
        string $bucket,
198
        string $path = null,
199
        array $options = [],
200
        bool $userProject = false
201
    )
202
    {
203
        @trigger_error('saveToGCS method is deprecated and will be removed in a future release. Use GoogleCloudStorage instead', E_USER_DEPRECATED);
204
        if ($this instanceof HLS && $this->getTsSubDirectory()) {
205
            throw new InvalidArgumentException("It is not possible to create subdirectory in a cloud");
206
        }
207
208
        $results = $this->saveToTemporaryFolder($path);
0 ignored issues
show
Deprecated Code introduced by
The function Streaming\Export::saveToTemporaryFolder() has been deprecated: this method is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

208
        $results = /** @scrutinizer ignore-deprecated */ $this->saveToTemporaryFolder($path);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
209
        sleep(1);
210
211
        $google_cloud = new GoogleCloudStorage($config, $bucket, $userProject);
212
        $google_cloud->uploadDirectory($this->tmp_dir, $options);
213
214
        $this->moveTmpFolder($path);
215
216
        return $results;
217
    }
218
219
    /**
220
     * @param string $connectionString
221
     * @param string $container
222
     * @param string|null $path
223
     * @return mixed
224
     * @throws Exception
225
     * @deprecated this method is deprecated
226
     */
227
    // @TODO: should be removed in the next releases.
228
    public function saveToMAS(
229
        string $connectionString,
230
        string $container,
231
        string $path = null
232
    )
233
    {
234
        @trigger_error('saveToMAS method is deprecated and will be removed in a future release. Use MicrosoftAzure instead', E_USER_DEPRECATED);
235
236
        if ($this instanceof HLS && $this->getTsSubDirectory()) {
237
            throw new InvalidArgumentException("It is not possible to create subdirectory in a cloud");
238
        }
239
240
        $results = $this->saveToTemporaryFolder($path);
0 ignored issues
show
Deprecated Code introduced by
The function Streaming\Export::saveToTemporaryFolder() has been deprecated: this method is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

240
        $results = /** @scrutinizer ignore-deprecated */ $this->saveToTemporaryFolder($path);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
241
        sleep(1);
242
243
        $google_cloud = new MicrosoftAzure($connectionString);
244
        $google_cloud->uploadDirectory($this->tmp_dir, ['container' => $container]);
245
246
        $this->moveTmpFolder($path);
247
248
        return $results;
249
    }
250
251
    /**
252
     * @return array
253
     */
254
    public function getPathInfo(): array
255
    {
256
        return $this->path_info;
257
    }
258
259
    /**
260
     * @return object|Media
261
     */
262
    public function getMedia(): Media
263
    {
264
        return $this->media;
265
    }
266
267
    /**
268
     * @param $path
269
     * @return array
270
     * @throws Exception
271
     * @deprecated this method is deprecated
272
     */
273
    // @TODO: should be removed in the next releases.
274
    private function saveToTemporaryFolder($path)
275
    {
276
        $basename = Helper::randomString();
277
278
        if (null !== $path) {
279
            $basename = pathinfo($path, PATHINFO_BASENAME);
280
        }
281
282
        $this->tmp_dir = FileManager::tmpDir();
283
284
        return $this->save($this->tmp_dir . $basename);
285
    }
286
287
    /**
288
     * clear tmp files
289
     */
290
    public function __destruct()
291
    {
292
        sleep(1);
293
294
        if ($this->media->isTmp()) {
295
            @unlink($this->media->getPath());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

295
            /** @scrutinizer ignore-unhandled */ @unlink($this->media->getPath());

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
296
        }
297
298
        if ($this->tmp_dir) {
299
            FileManager::deleteDirectory($this->tmp_dir);
300
        }
301
    }
302
303
    /**
304
     * @param string|null $path
305
     * @throws Exception
306
     */
307
    private function moveTmpFolder(?string $path)
308
    {
309
        if ($this->tmp_dir && $path) {
310
            FileManager::moveDir($this->tmp_dir, pathinfo($path, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR);
311
        }
312
    }
313
314
    /**
315
     * @param string $strict
316
     * @return Export
317
     */
318
    public function setStrict(string $strict): Export
319
    {
320
        $this->strict = $strict;
321
        return $this;
322
    }
323
324
    /**
325
     * @return string
326
     */
327
    public function getStrict(): string
328
    {
329
        return $this->strict;
330
    }
331
332
    /**
333
     * @param $path
334
     * @throws Exception
335
     */
336
    private function tmpDirectory($path)
337
    {
338
        if (null !== $path) {
339
            $basename = pathinfo($path, PATHINFO_BASENAME);
340
        } else {
341
            $basename = Helper::randomString();
342
        }
343
344
        $this->tmp_dir = FileManager::tmpDir();
345
        $this->path_info = pathinfo($this->tmp_dir . $basename);
346
    }
347
348
    /**
349
     * @param array $clouds
350
     */
351
    private function saveToClouds(array $clouds): void
352
    {
353
        if ($clouds) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $clouds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
354
355
            if (!is_array(current($clouds))) {
356
                $clouds = [$clouds];
357
            }
358
359
            sleep(1);
360
361
            foreach ($clouds as $cloud) {
362
                if (is_array($cloud) && $cloud['cloud'] instanceof CloudInterface) {
363
                    $cloud_obj = $cloud['cloud'];
364
                    $options = (isset($cloud['options']) && is_array($cloud['options'])) ? $cloud['options'] : [];
365
366
                    $cloud_obj->uploadDirectory($this->tmp_dir, $options);
367
                } else {
368
                    throw new InvalidArgumentException('You must pass an array of clouds to the save method. 
369
                    and the cloud must be instance of CloudInterface');
370
                }
371
            }
372
        }
373
    }
374
}