Passed
Pull Request — master (#2148)
by Arnaud
09:31 queued 04:12
created

File   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Test Coverage

Coverage 77.22%

Importance

Changes 9
Bugs 1 Features 0
Metric Value
eloc 73
c 9
b 1
f 0
dl 0
loc 173
ccs 61
cts 79
cp 0.7722
rs 10
wmc 26

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getFS() 0 7 2
A getMediaType() 0 15 4
A fileGetContents() 0 30 4
A isRemote() 0 3 1
A readExif() 0 26 5
A getExtension() 0 18 4
A getRealPath() 0 13 3
A isRemoteExists() 0 10 3
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 1
    public static function getFS(): Filesystem
29
    {
30 1
        if (!self::$fs instanceof Filesystem) {
31 1
            self::$fs = new Filesystem();
32
        }
33
34 1
        return self::$fs;
35
    }
36
37
    /**
38
     * file_get_contents() function with error handler.
39
     *
40
     * @return string|false
41
     */
42 1
    public static function fileGetContents(string $filename, bool $userAgent = false)
43
    {
44 1
        if (empty($filename)) {
45
            return false;
46
        }
47
48 1
        set_error_handler(
49 1
            function ($severity, $message, $file, $line) {
50 1
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
51 1
            }
52 1
        );
53
54
        try {
55 1
            if ($userAgent) {
56 1
                $options = [
57 1
                    'http' => [
58 1
                        'method'          => 'GET',
59 1
                        '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 1
                        'follow_location' => true,
61 1
                    ],
62 1
                ];
63
64 1
                return file_get_contents($filename, false, stream_context_create($options));
65
            }
66
67 1
            return file_get_contents($filename);
68 1
        } catch (\ErrorException) {
69 1
            return false;
70
        } finally {
71 1
            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 1
    public static function getMediaType(string $filename): array
81
    {
82
        try {
83 1
            if (false !== $subtype = mime_content_type($filename)) {
84 1
                return [explode('/', $subtype)[0], $subtype];
85
            }
86
            $mimeTypes = new MimeTypes();
87
            $subtype = $mimeTypes->guessMimeType($filename);
88
            if ($subtype === null) {
89
                throw new RuntimeException('Can\'t guess the media type.');
90
            }
91
92
            return [explode('/', $subtype)[0], $subtype];
93
        } catch (\Exception $e) {
94
            throw new RuntimeException(\sprintf('Can\'t get media type of "%s" (%s).', $filename, $e->getMessage()));
95
        }
96
    }
97
98
    /**
99
     * Returns the extension of a file.
100
     */
101 1
    public static function getExtension(string $filename): string
102
    {
103
        try {
104 1
            $ext = pathinfo($filename, PATHINFO_EXTENSION);
105 1
            if (!empty($ext)) {
106 1
                return $ext;
107
            }
108
            // guess the extension
109 1
            $mimeTypes = new MimeTypes();
110 1
            $mimeType = $mimeTypes->guessMimeType($filename);
111 1
            if ($mimeType === null) {
112
                throw new RuntimeException('Can\'t guess the media type.');
113
            }
114 1
            $exts = $mimeTypes->getExtensions($mimeType);
115
116 1
            return $exts[0];
117
        } catch (\Exception $e) {
118
            throw new RuntimeException(\sprintf('Can\'t get extension of "%s" (%s).', $filename, $e->getMessage()));
119
        }
120
    }
121
122
    /**
123
     * exif_read_data() function with error handler.
124
     */
125 1
    public static function readExif(string $filename): array
126
    {
127 1
        if (empty($filename)) {
128
            return [];
129
        }
130
131 1
        set_error_handler(
132 1
            function ($severity, $message, $file, $line) {
133
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
134 1
            }
135 1
        );
136
137
        try {
138 1
            if (!\function_exists('exif_read_data')) {
139
                throw new \ErrorException('`exif` extension is not available.');
140
            }
141 1
            $exif = exif_read_data($filename, null, true);
142 1
            if ($exif === false) {
143
                return [];
144
            }
145
146 1
            return $exif;
147
        } catch (\ErrorException) {
148
            return [];
149
        } finally {
150 1
            restore_error_handler();
151
        }
152
    }
153
154
    /**
155
     * Returns the real path of a relative file path.
156
     */
157 1
    public static function getRealPath(string $path): string
158
    {
159
        // if file exists
160 1
        $filePath = realpath(\Cecil\Util::joinFile(__DIR__, '/../', $path));
161 1
        if ($filePath !== false) {
162 1
            return $filePath;
163
        }
164
        // if Phar
165 1
        if (Platform::isPhar()) {
166
            return \Cecil\Util::joinPath(Platform::getPharPath(), str_replace('../', '/', $path));
167
        }
168
169 1
        throw new RuntimeException(\sprintf('Can\'t get the real path of file "%s".', $path));
170
    }
171
172
    /**
173
     * Tests if a file path is remote.
174
     */
175 1
    public static function isRemote(string $path): bool
176
    {
177 1
        return (bool) preg_match('~^(?:f|ht)tps?://~i', $path);
178
    }
179
180
    /**
181
     * Tests if a remote file exists.
182
     */
183 1
    public static function isRemoteExists(string $path): bool
184
    {
185 1
        if (self::isRemote($path)) {
186 1
            $handle = @fopen($path, 'r');
187 1
            if (\is_resource($handle)) {
188 1
                return true;
189
            }
190
        }
191
192 1
        return false;
193
    }
194
}
195