Completed
Push — 4.0 ( bf6233...a1234e )
by Marco
13:59
created

File::getLocalName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
1
<?php namespace Comodojo\Dispatcher\Response;
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
    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
        $files = array();
272
    
273
        foreach ($_FILES as $idx => $data) {
274
        
275
            $files[] = new File($idx, $repository);
276
        
277
        }
278
    
279
        return $files;
280
    
281
    }
282
283
}
284