• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Cecilapp / Cecil / 14728316204

29 Apr 2025 09:48AM UTC coverage: 83.256% (-0.3%) from 83.512%
14728316204

push

github

ArnaudLigny
Merge branch 'master' of https://github.com/Cecilapp/Cecil

13 of 27 new or added lines in 6 files covered. (48.15%)

111 existing lines in 5 files now uncovered.

3043 of 3655 relevant lines covered (83.26%)

0.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.43
/src/Util/File.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <arnaud@ligny.fr>
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) {
1✔
31
            self::$fs = new Filesystem();
1✔
32
        }
33

34
        return self::$fs;
1✔
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)) {
1✔
45
            return false;
×
46
        }
47

48
        set_error_handler(
1✔
49
            function ($severity, $message, $file, $line) {
1✔
50
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
1✔
51
            }
1✔
52
        );
1✔
53

54
        try {
55
            if ($userAgent) {
1✔
56
                $options = [
1✔
57
                    'http' => [
1✔
58
                        'method'          => 'GET',
1✔
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',
1✔
60
                        'follow_location' => true,
1✔
61
                    ],
1✔
62
                ];
1✔
63

64
                return file_get_contents($filename, false, stream_context_create($options));
1✔
65
            }
66

67
            return file_get_contents($filename);
1✔
68
        } catch (\ErrorException) {
1✔
69
            return false;
1✔
70
        } finally {
71
            restore_error_handler();
1✔
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
            if (false !== $subtype = mime_content_type($filename)) {
1✔
84
                return [explode('/', $subtype)[0], $subtype];
1✔
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
    public static function getExtension(string $filename): string
102
    {
103
        try {
104
            $ext = pathinfo($filename, PATHINFO_EXTENSION);
1✔
105
            if (!empty($ext)) {
1✔
106
                return $ext;
1✔
107
            }
108
            // guess the extension
109
            $mimeTypes = new MimeTypes();
1✔
110
            $mimeType = $mimeTypes->guessMimeType($filename);
1✔
111
            if ($mimeType === null) {
1✔
112
                throw new RuntimeException('Can\'t guess the media type.');
×
113
            }
114
            $exts = $mimeTypes->getExtensions($mimeType);
1✔
115

116
            return $exts[0];
1✔
117
        } catch (\Exception $e) {
×
118
            throw new RuntimeException(
×
UNCOV
119
                \sprintf('Can\'t get extension of "%s".', $filename),
×
UNCOV
120
                previous: $e,
×
UNCOV
121
            );
×
122
        }
123
    }
124

125
    /**
126
     * exif_read_data() function with error handler.
127
     */
128
    public static function readExif(string $filename): array
129
    {
130
        if (empty($filename)) {
1✔
UNCOV
131
            return [];
×
132
        }
133

134
        set_error_handler(
1✔
135
            function ($severity, $message, $file, $line) {
1✔
UNCOV
136
                throw new \ErrorException($message, 0, $severity, $file, $line, null);
×
137
            }
1✔
138
        );
1✔
139

140
        try {
141
            if (!\function_exists('exif_read_data')) {
1✔
UNCOV
142
                throw new \ErrorException('`exif` extension is not available.');
×
143
            }
144
            $exif = exif_read_data($filename, null, true);
1✔
145
            if ($exif === false) {
1✔
UNCOV
146
                return [];
×
147
            }
148

149
            return $exif;
1✔
UNCOV
150
        } catch (\ErrorException) {
×
UNCOV
151
            return [];
×
152
        } finally {
153
            restore_error_handler();
1✔
154
        }
155
    }
156

157
    /**
158
     * Returns the real path of a relative file path.
159
     */
160
    public static function getRealPath(string $path): string
161
    {
162
        // if file exists
163
        $filePath = realpath(\Cecil\Util::joinFile(__DIR__, '/../', $path));
1✔
164
        if ($filePath !== false) {
1✔
165
            return $filePath;
1✔
166
        }
167
        // if Phar
168
        if (Platform::isPhar()) {
1✔
UNCOV
169
            return \Cecil\Util::joinPath(Platform::getPharPath(), str_replace('../', '/', $path));
×
170
        }
171

172
        throw new RuntimeException(\sprintf('Can\'t get the real path of file "%s".', $path));
1✔
173
    }
174

175
    /**
176
     * Tests if a file path is remote.
177
     */
178
    public static function isRemote(string $path): bool
179
    {
180
        return (bool) preg_match('~^(?:f|ht)tps?://~i', $path);
1✔
181
    }
182

183
    /**
184
     * Tests if a remote file exists.
185
     */
186
    public static function isRemoteExists(string $path): bool
187
    {
188
        if (self::isRemote($path)) {
1✔
189
            $handle = @fopen($path, 'r');
1✔
190
            if (!empty($http_response_header)) {
1✔
191
                if (400 < (int) explode(' ', $http_response_header[0])[1]) {
1✔
192
                    return false;
1✔
193
                }
194
            }
195
            if (\is_resource($handle)) {
1✔
196
                return true;
1✔
197
            }
198
        }
199

UNCOV
200
        return false;
×
201
    }
202
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc