Completed
Push — 4.0 ( 3b08f9...a100dc )
by Marco
14:07
created

File::getFileName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 2
cp 0
rs 9.4285
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php namespace Comodojo\Dispatcher\Request;
2
3
use \Exception;
4
use \Comodojo\Exception\DispatcherException;
5
6
/**
7
 * @package     Comodojo Dispatcher
8
 * @author      Marco Giovinazzi <[email protected]>
9
 * @author      Marco Castiello <[email protected]>
10
 * @license     GPL-3.0+
11
 *
12
 * LICENSE:
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26
 */
27
28
class File {
29
30
    private $path  = '';
31
32
    private $slug  = '';
33
34
    private $fname = '';
35
36
    private $tname = '';
37
38
    private $upld  = '';
39
40
    private $ctype = 'text/plain';
41
42
    private $size  = 0;
43
44
    public function __construct($fileControl = null, $repository = '') {
45
46
        $this->path = $repository;
47
48
        if (!is_null($fileControl)) {
49
50
            $this->load($fileControl);
51
52
        }
53
54
    }
55
56
    public function getTemporaryName() {
57
58
        return $this->tname;
59
60
    }
61
62
    public function getLocalName() {
63
64
        if (!empty($this->path))
65
            return $this->path . "/" . $this->slug;
66
        else
67
            return '';
68
69
    }
70
71
    public function getFileName() {
72
73
        return $this->fname;
74
75
    }
76
77
    public function getSlug() {
78
79
        return $this->slug;
80
81
    }
82
83
    public function getContentType() {
84
85
        return $this->ctype;
86
87
    }
88
89
    public function getSize() {
90
91
        return $this->size;
92
93
    }
94
95
    public function getUploadTime() {
96
97
        return $this->upld;
98
99
    }
100
101
    public function getFileData() {
102
103
        $file = $this->getTemporaryName();
104
        if (empty($file))
105
            $file = $this->getLocalName();
106
107
        if (file_exists($file))
108
            return file_get_contents($file);
109
110
        throw new DispatcherException("File does not exists");
111
112
    }
113
114
    public function fileIsSaved() {
115
116
        return (
117
            !empty($this->path) &&
118
            !empty($this->slug) &&
119
            file_exists($this->getLocalName()) &&
120
            file_exists($this->getLocalName() . ".data")
121
        );
122
123
    }
124
125
    public function load($slugOrControl) {
0 ignored issues
show
Coding Style introduced by
load uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
126
127
        if (isset($_FILES) && isset($_FILES[$slugOrControl])) {
128
129
            $this->loadFromUploadedFile($slugOrControl);
130
131
        } else {
132
133
            $this->loadFromLocalRepository($slugOrControl);
134
135
        }
136
137
        return $this;
138
139
    }
140
141
    public function save($repository = '') {
142
143
        if (!empty($repository)) {
144
145
            $this->path = $repository;
146
147
        }
148
149
        if (!empty($this->path) && file_exists($this->path)) {
150
151
            if (move_uploaded_file($this->getTemporaryName(), $this->getLocalName())) {
152
153
                return $this->saveFileInfo();
154
155
            }
156
157
            throw new DispatcherException("Unable to save file");
158
159
        }
160
161
        throw new DispatcherException("Repository path is not available");
162
163
    }
164
165
    private function loadFromUploadedFile($fileControl) {
0 ignored issues
show
Coding Style introduced by
loadFromUploadedFile uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
166
167
        if (isset($_FILES[$fileControl])) {
168
169
            $file = $_FILES[$fileControl];
170
171
            $this->tname = $file['tmp_name'];
172
            $this->fname = $file['name'];
173
            $this->ctype = $file['type'];
174
            $this->size  = intval($file['size']);
175
            $this->upld  = filectime($file['tmp_name']);
0 ignored issues
show
Documentation Bug introduced by
The property $upld was declared of type string, but filectime($file['tmp_name']) is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
176
177
            $this->createSlug();
178
179
            return $this;
180
181
        }
182
183
        throw new DispatcherException("File not uploaded");
184
185
    }
186
187
    private function loadFromLocalRepository($slug) {
188
189
        $this->slug = $slug;
190
191
        if ($this->fileIsSaved()) {
192
193
            $this->loadFileInfo();
194
195
            return $this;
196
197
        }
198
199
        throw new DispatcherException("File not found");
200
201
    }
202
203
    private function loadFileInfo() {
204
205
        $info = $this->getLocalName() . ".data";
206
207
        if (file_exists($info)) {
208
209
            $data = unserialize(file_get_contents($info));
210
211
            $this->fname = $data[0];
212
            $this->ctype = $data[1];
213
            $this->size  = intval($data[2]);
214
            $this->upld  = intval($data[3]);
0 ignored issues
show
Documentation Bug introduced by
The property $upld was declared of type string, but intval($data[3]) is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
215
216
            return $this;
217
218
        }
219
220
        throw new DispatcherException("Unable to load file info");
221
222
    }
223
224
    private function saveFileInfo() {
225
226
        $info = $this->getLocalName() . ".data";
227
228
        if (!empty($this->path) && file_exists($this->path)) {
229
230
            file_put_contents($info, serialize(
231
                array(
232
                    $this->fname,
233
                    $this->ctype,
234
                    $this->size,
235
                    $this->upld
236
                )
237
            ));
238
239
            return $this;
240
241
        }
242
243
        throw new DispatcherException("Unable to save file info");
244
245
    }
246
247
    private function createSlug() {
248
249
        preg_match_all("/[a-z0-9]+/", iconv("UTF-8", "ASCII//TRANSLIT", strtolower(preg_replace('/\..*?$/', '', $this->fname))), $matches);
250
251
        $this->slug  = implode('-', $matches[0]);
252
253
        if (!empty($this->path)) {
254
255
            $files = glob($this->path . "/" . $slug . "*");
0 ignored issues
show
Bug introduced by
The variable $slug does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
256
257
            $count = count ($files);
258
259
            if ($count > 0) {
260
261
                $this->slug .= "-" . $count;
262
263
            }
264
265
        }
266
267
    }
268
269 5
    public static function fromUploadedFiles($repository = '') {
0 ignored issues
show
Coding Style introduced by
fromUploadedFiles uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
270
271 5
        $files = array();
272
273 5
        foreach ($_FILES as $idx => $data) {
274
275
            $files[] = new File($idx, $repository);
276
277 5
        }
278
279 5
        return $files;
280
281
    }
282
283
}
284