Completed
Pull Request — master (#91)
by Vladimir
02:23
created

File::getLastModified()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * @copyright 2018 Vladimir Jimenez
5
 * @license   https://github.com/stakx-io/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Filesystem;
9
10
use allejo\stakx\Service;
11
use allejo\stakx\Filesystem\FilesystemLoader as fs;
12
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
13
14
/**
15
 * A representation of a file on a given filesystem, virtual or physical.
16
 *
17
 * This class extends \SplFileInfo and adds new methods along with overriding some methods solely because I feel that
18
 * some of the naming can be misleading.
19
 *
20
 * @since 0.2.0
21
 */
22
final class File extends \SplFileInfo
23
{
24
    /** @var string The path relative to the site's working directory. */
25
    private $relativePath;
26
27
    /** @var string The original raw path given to the constructor. */
28
    private $rawPath;
29
30
    /**
31
     * File Constructor.
32
     *
33
     * @param string $filePath an absolute file path or a path relative to the current working directory
34
     *
35
     * @since 0.2.0
36
     *
37
     * @throws FileNotFoundException
38
     */
39 178
    public function __construct($filePath)
40
    {
41 178
        $this->rawPath = $filePath;
42 178
        $realPath = fs::realpath($filePath);
0 ignored issues
show
Documentation introduced by
$filePath is of type string, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
43
44 178
        if ($realPath === false)
45
        {
46 3
            throw $this->buildNotFoundException();
47
        }
48
49 176
        parent::__construct($realPath);
50
51 176
        $this->relativePath = str_replace(Service::getWorkingDirectory() . DIRECTORY_SEPARATOR, '', $this->getAbsolutePath());
52
53 176
        $this->isSafeToRead();
54 176
    }
55
56
    /**
57
     * Get a new File object for another file relative to this file.
58
     *
59
     * @param string $path
60
     *
61
     * @return File
62
     */
63 11
    public function createFileForRelativePath($path)
64
    {
65 11
        return new File(Service::getWorkingDirectory() . DIRECTORY_SEPARATOR . $path);
66
    }
67
68
    /**
69
     * Whether or not this file exists on the filesystem.
70
     *
71
     * @return bool
72
     */
73 158
    public function exists()
74
    {
75 158
        return file_exists($this->getAbsolutePath());
76
    }
77
78
    /**
79
     * Get the name of the file without an extension.
80
     *
81
     * @param null $suffix this value will be discarded and is only needed to be able to override the \SplFileInfo
82
     *                     definition
83
     *
84
     * @since 0.2.0
85
     *
86
     * @return string
87
     */
88 97
    public function getBasename($suffix = null)
89
    {
90 97
        return parent::getBasename('.' . $this->getExtension());
91
    }
92
93
    /**
94
     * Get the name of the with the extension.
95
     *
96
     * @since 0.2.0
97
     *
98
     * @return string
99
     */
100 100
    public function getFilename()
101
    {
102 100
        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...
103
    }
104
105
    /**
106
     * Get the absolute path to this file.
107
     *
108
     * @since 0.2.0
109
     *
110
     * @return string
111
     */
112 176
    public function getAbsolutePath()
113
    {
114 176
        return $this->getPathname();
115
    }
116
117
    /**
118
     * Get the path to the parent folder of this file.
119
     *
120
     * @since 0.2.0
121
     *
122
     * @return string
123
     */
124 1
    public function getParentFolder()
125
    {
126 1
        return $this->getPath();
127
    }
128
129
    /**
130
     * Get the file path to this file, relative to where it was created; likely the current working directory.
131
     *
132
     * @since 0.2.0
133
     *
134
     * @return string
135
     */
136 149
    public function getRelativeFilePath()
137
    {
138 149
        return $this->relativePath;
139
    }
140
141
    /**
142
     * Get the path to the parent folder this file, relative to where it was created; likely the current working directory.
143
     *
144
     * @since 0.2.0
145
     *
146
     * @return string
147
     */
148 2
    public function getRelativeParentFolder()
149
    {
150 2
        return dirname($this->getRelativeFilePath());
151
    }
152
153
    /**
154
     * Gets the last modified time.
155
     *
156
     * @return int The last modified time for the file, in a Unix timestamp
157
     */
158
    public function getLastModified()
159
    {
160
        return $this->getMTime();
161
    }
162
163
    /**
164
     * Get the contents of this file.
165
     *
166
     * @since 0.2.0
167
     *
168
     * @throws \RuntimeException when the file could not be read
169
     *
170
     * @return string
171
     */
172 157
    public function getContents()
173
    {
174 157
        if (!$this->exists())
175
        {
176 1
            throw $this->buildNotFoundException();
177
        }
178
179 157
        $content = file_get_contents($this->getAbsolutePath());
180
181 157
        if ($content === false)
182
        {
183
            $error = error_get_last();
184
            throw new \RuntimeException($error['message']);
185
        }
186
187 157
        return $content;
188
    }
189
190
    /**
191
     * Check if a file is safe to read.
192
     *
193
     * @throws FileNotFoundException
194
     */
195 176
    private function isSafeToRead()
196
    {
197 176
        if (fs::isVFS($this->getAbsolutePath()))
0 ignored issues
show
Documentation introduced by
$this->getAbsolutePath() is of type string, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
198
        {
199 130
            return;
200
        }
201
202 51
        if (strpos($this->getAbsolutePath(), Service::getWorkingDirectory()) !== 0)
203
        {
204
            throw $this->buildNotFoundException();
205
        }
206 51
    }
207
208 4
    private function buildNotFoundException()
209
    {
210 4
        return new FileNotFoundException(
211 4
            sprintf('The given path "%s" does not exist or is outside the website working directory', $this->rawPath),
212 4
            0,
213 4
            null,
214 4
            $this->rawPath
215
        );
216
    }
217
218
}
219