Completed
Push — master ( ab824b...23728e )
by Vladimir
02:13
created

File::isSafeToRead()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0072

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 24
rs 8.6845
c 2
b 0
f 0
ccs 12
cts 13
cp 0.9231
cc 4
eloc 12
nc 4
nop 0
crap 4.0072
1
<?php
2
3
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Filesystem;
9
10
use allejo\stakx\Service;
11
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
12
13
/**
14
 * A representation of a file on a given filesystem, virtual or physical.
15
 *
16
 * This class extends \SplFileInfo and adds new methods along with overriding some methods solely because I feel that
17
 * some of the naming can be misleading.
18
 *
19
 * @since 0.2.0
20
 */
21
final class File extends \SplFileInfo
22
{
23
    /** @var string The path relative to the site's working directory. */
24
    private $relativePath;
25
26
    /** @var string The original raw path given to the constructor. */
27
    private $rawPath;
28
29
    /**
30
     * File Constructor.
31
     *
32
     * @param string $filePath An absolute file path or a path relative to the current working directory.
33
     *
34
     * @since 0.2.0
35
     */
36 156
    public function __construct($filePath)
37
    {
38 156
        $this->rawPath = $filePath;
39
40 156
        parent::__construct(self::realpath($filePath));
41
42 156
        $this->relativePath = str_replace(Service::getWorkingDirectory() . DIRECTORY_SEPARATOR, '', $this->getAbsolutePath());
43 156
    }
44
45
    /**
46
     * Get a new File object for another file relative to this file.
47
     *
48
     * @param string $path
49
     *
50
     * @return File
51
     */
52 11
    public function createFileForRelativePath($path)
53
    {
54 11
        return new File(Service::getWorkingDirectory() . DIRECTORY_SEPARATOR . $path);
55
    }
56
57
    /**
58
     * Whether or not this file exists on the filesystem.
59
     *
60
     * @return bool
61
     */
62 148
    public function exists()
63
    {
64 148
        return file_exists($this->getAbsolutePath());
65
    }
66
67
    /**
68
     * Get the name of the file without an extension.
69
     *
70
     * @param  null $suffix This value will be discarded and is only needed to be able to override the \SplFileInfo
71
     *                      definition.
72
     *
73
     * @since 0.2.0
74
     *
75
     * @return string
76
     */
77 5
    public function getBasename($suffix = null)
78
    {
79 5
        return parent::getBasename('.' . $this->getExtension());
80
    }
81
82
    /**
83
     * Get the name of the with the extension.
84
     *
85
     * @since 0.2.0
86
     *
87
     * @return string
88
     */
89 1
    public function getFilename()
90
    {
91 1
        return parent::getBasename();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getBasename() instead of getFilename()). Are you sure this is correct? If so, you might want to change this to $this->getBasename().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
92
    }
93
94
    /**
95
     * Get the absolute path to this file.
96
     *
97
     * @since 0.2.0
98
     *
99
     * @return string
100
     */
101 156
    public function getAbsolutePath()
102
    {
103 156
        return $this->getPathname();
104
    }
105
106
    /**
107
     * Get the path to the parent folder of this file.
108
     *
109
     * @since 0.2.0
110
     *
111
     * @return string
112
     */
113 1
    public function getParentFolder()
114
    {
115 1
        return $this->getPath();
116
    }
117
118
    /**
119
     * Get the file path to this file, relative to where it was created; likely the current working directory.
120
     *
121
     * @since 0.2.0
122
     *
123
     * @return string
124
     */
125 126
    public function getRelativeFilePath()
126
    {
127 126
        return $this->relativePath;
128
    }
129
130
    /**
131
     * Get the path to the parent folder this file, relative to where it was created; likely the current working directory.
132
     *
133
     * @since 0.2.0
134
     *
135
     * @return string
136
     */
137 2
    public function getRelativeParentFolder()
138
    {
139 2
        return dirname($this->getRelativeFilePath());
140
    }
141
142
    /**
143
     * Get the contents of this file.
144
     *
145
     * @since 0.2.0
146
     *
147
     * @throws \RuntimeException When the file could not be read.
148
     *
149
     * @return string
150
     */
151 146
    public function getContents()
152
    {
153 146
        $this->isSafeToRead();
154
155 145
        $content = file_get_contents($this->getAbsolutePath());
156
157 145
        if ($content === false)
158
        {
159
            $error = error_get_last();
160
            throw new \RuntimeException($error['message']);
161
        }
162
163 145
        return $content;
164
    }
165
166
    /**
167
     * Check if a file is safe to read.
168
     */
169 146
    private function isSafeToRead()
170
    {
171 146
        $e = new FileNotFoundException(
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $e. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
172 146
            sprintf('The given path "%s" does not exist or is outside the website working directory', $this->rawPath),
173 146
            0,
174 146
            null,
175 146
            $this->rawPath
176
        );
177
178 146
        if (!$this->exists())
179
        {
180 2
            throw $e;
181
        }
182
183 145
        if (self::isVFS($this->getAbsolutePath()))
184
        {
185 107
            return;
186
        }
187
188 43
        if (strpos($this->getAbsolutePath(), Service::getWorkingDirectory()) !== 0)
189
        {
190
            throw $e;
191
        }
192 43
    }
193
194
    /**
195
     * A vfsStream friendly way of getting the realpath() of something.
196
     *
197
     * @param string $path
198
     *
199
     * @return string
200
     */
201 156
    public static function realpath($path)
202
    {
203 156
        return self::isVFS($path) ? $path : realpath($path);
204
    }
205
206
    /**
207
     * Check whether a given path is on the virtual filesystem.
208
     *
209
     * @param string $path
210
     *
211
     * @return bool
212
     */
213 156
    private static function isVFS($path)
214
    {
215 156
        return substr($path, 0, 6) == 'vfs://';
216
    }
217
}
218