Passed
Push — analysis-Znp5Gg ( 8e87eb )
by Arnaud
04:53 queued 10s
created

File::isRemoteExists()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 10
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Cecil\Util;
15
16
use Cecil\Exception\RuntimeException;
17
use Symfony\Component\Filesystem\Filesystem;
18
use Symfony\Component\Mime\MimeTypes;
19
20
class File
21
{
22
    /** @var Filesystem */
23
    protected static $fs;
24
25
    /**
26
     * Returns a Symfony\Component\Filesystem instance.
27
     */
28
    public static function getFS(): Filesystem
29
    {
30
        if (!self::$fs instanceof Filesystem) {
31
            self::$fs = new Filesystem();
32
        }
33
34
        return self::$fs;
35
    }
36
37
    /**
38
     * file_get_contents() function with error handler.
39
     *
40
     * @return string|false
41
     */
42
    public static function fileGetContents(string $filename, bool $userAgent = false)
43
    {
44
        if (empty($filename)) {
45
            return false;
46
        }
47
48
        set_error_handler(
49
            function ($severity, $message, $file, $line) {
50
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
51
            }
52
        );
53
54
        try {
55
            if ($userAgent) {
56
                $options = [
57
                    'http' => [
58
                        'method'          => 'GET',
59
                        'header'          => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.47 Safari/537.36',
60
                        'follow_location' => true,
61
                    ],
62
                ];
63
64
                return file_get_contents($filename, false, stream_context_create($options));
65
            }
66
67
            return file_get_contents($filename);
68
        } catch (\ErrorException) {
69
            return false;
70
        } finally {
71
            restore_error_handler();
72
        }
73
    }
74
75
    /**
76
     * Returns the media type and subtype of a file.
77
     *
78
     * ie: ['text', 'text/plain']
79
     */
80
    public static function getMediaType(string $filename): array
81
    {
82
        try {
83
            $mimeTypes = new MimeTypes();
84
            $mimeType = $mimeTypes->guessMimeType($filename);
85
        } catch (\Exception $e) {
86
            throw new RuntimeException(\sprintf('Can\'t get media type of "%s" (%s).', $filename, $e->getMessage()));
87
        }
88
        $type = explode('/', $mimeType)[0];
0 ignored issues
show
Bug introduced by
It seems like $mimeType can also be of type null; however, parameter $string of explode() 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 ignore-type  annotation

88
        $type = explode('/', /** @scrutinizer ignore-type */ $mimeType)[0];
Loading history...
89
90
        return [
91
            $type,     // type
92
            $mimeType, // subtype
93
        ];
94
    }
95
96
    /**
97
     * Returns the extension of a file.
98
     */
99
    public static function getExtension(string $filename): string
100
    {
101
        try {
102
            $mimeTypes = new MimeTypes();
103
            $mimeType = $mimeTypes->guessMimeType($filename);
104
            $exts = $mimeTypes->getExtensions($mimeType);
0 ignored issues
show
Bug introduced by
It seems like $mimeType can also be of type null; however, parameter $mimeType of Symfony\Component\Mime\MimeTypes::getExtensions() 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 ignore-type  annotation

104
            $exts = $mimeTypes->getExtensions(/** @scrutinizer ignore-type */ $mimeType);
Loading history...
105
        } catch (\Exception $e) {
106
            throw new RuntimeException(\sprintf('Can\'t get extension of "%s" (%s).', $filename, $e->getMessage()));
107
        }
108
109
        return $exts[0];
110
    }
111
112
    /**
113
     * exif_read_data() function with error handler.
114
     */
115
    public static function readExif(string $filename): array
116
    {
117
        if (empty($filename)) {
118
            return [];
119
        }
120
121
        set_error_handler(
122
            function ($severity, $message, $file, $line) {
123
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
124
            }
125
        );
126
127
        try {
128
            if (!\function_exists('exif_read_data')) {
129
                throw new \ErrorException('`exif` extension is not available.');
130
            }
131
            $exif = exif_read_data($filename, null, true);
132
            if ($exif === false) {
133
                return [];
134
            }
135
136
            return $exif;
137
        } catch (\ErrorException) {
138
            return [];
139
        } finally {
140
            restore_error_handler();
141
        }
142
    }
143
144
    /**
145
     * Returns the real path of a relative file path.
146
     */
147
    public static function getRealPath(string $path): string
148
    {
149
        // if file exists
150
        $filePath = realpath(\Cecil\Util::joinFile(__DIR__, '/../', $path));
151
        if ($filePath !== false) {
152
            return $filePath;
153
        }
154
        // if Phar
155
        if (Platform::isPhar()) {
156
            return \Cecil\Util::joinPath(Platform::getPharPath(), str_replace('../', '/', $path));
157
        }
158
159
        throw new RuntimeException(\sprintf('Can\'t get the real path of file "%s".', $path));
160
    }
161
162
    /**
163
     * Tests if a file path is remote.
164
     */
165
    public static function isRemote(string $path): bool
166
    {
167
        return (bool) preg_match('~^(?:f|ht)tps?://~i', $path);
168
    }
169
170
    /**
171
     * Tests if a remote file exists.
172
     */
173
    public static function isRemoteExists(string $path): bool
174
    {
175
        if (self::isRemote($path)) {
176
            $handle = @fopen($path, 'r');
177
            if (\is_resource($handle)) {
178
                return true;
179
            }
180
        }
181
182
        return false;
183
    }
184
}
185