Completed
Push — master ( 83dc58...593e8c )
by Hong
02:51
created

Path::alterAction()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 19
rs 8.8571
cc 5
eloc 11
nc 3
nop 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Storage
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Storage;
16
17
use Phossa2\Storage\Message\Message;
18
use Phossa2\Shared\Base\ObjectAbstract;
19
use Phossa2\Shared\Error\ErrorAwareTrait;
20
use Phossa2\Shared\Error\ErrorAwareInterface;
21
use Phossa2\Storage\Interfaces\PathInterface;
22
use Phossa2\Storage\Traits\FilesystemAwareTrait;
23
use Phossa2\Shared\Extension\ExtensionAwareTrait;
24
use Phossa2\Storage\Interfaces\FilesystemInterface;
25
use Phossa2\Shared\Extension\ExtensionAwareInterface;
26
use Phossa2\Storage\Interfaces\FilesystemAwareInterface;
27
use Phossa2\Storage\Interfaces\DriverInterface;
28
29
/**
30
 * Path
31
 *
32
 * @package Phossa2\Storage
33
 * @author  Hong Zhang <[email protected]>
34
 * @see     ObjectAbstract
35
 * @see     PathInterface
36
 * @see     ErrorAwareInterface
37
 * @see     FilesystemAwareInterface
38
 * @version 2.0.0
39
 * @since   2.0.0 added
40
 */
41
class Path extends ObjectAbstract implements PathInterface, ErrorAwareInterface, FilesystemAwareInterface, ExtensionAwareInterface
42
{
43
    use FilesystemAwareTrait, ErrorAwareTrait, ExtensionAwareTrait;
44
45
    /**
46
     * Full path with mount point
47
     *
48
     * @var    string
49
     * @access protected
50
     */
51
    protected $full;
52
53
    /**
54
     * relative path without mount point prefix
55
     *
56
     * @var    string
57
     * @access protected
58
     */
59
    protected $path;
60
61
    /**
62
     * Instantiate the path object
63
     *
64
     * @param  string $full full path
65
     * @param  string $path relative path without mount point
66
     * @param  FilesystemInterface $filesystem
67
     * @access public
68
     * @api
69
     */
70
    public function __construct(
71
        /*# string */ $full,
72
        /*# string */ $path,
73
        FilesystemInterface $filesystem
74
    ) {
75
        $this->setFilesystem($filesystem);
76
        $this->full = $full;
77
        $this->path = $path;
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function exists()/*# : bool */
84
    {
85
        if (!$this->getDriver()->exists($this->path)) {
86
            return $this->setError(
87
                Message::get(Message::MSG_PATH_NOTFOUND, $this->full),
88
                Message::MSG_PATH_NOTFOUND
89
            );
90
        }
91
        return true;
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97 View Code Duplication
    public function getContent(/*# bool */ $stream = false)
98
    {
99
        // not exists or filesystem not readable
100
        if (!$this->exists() || !$this->isFilesystemReadable()) {
101
            return null;
102
        }
103
104
        $res = $this->getDriver()->getContent($this->path, $stream);
105
        $this->resetError();
106
        return $res;
107
    }
108
109
    /**
110
     * {@inheritDoc}
111
     */
112
    public function getMeta()/*# : array */
113
    {
114
        if (!$this->exists()) {
115
            return [];
116
        }
117
118
        $res = $this->getDriver()->getMeta($this->path);
119
        $this->resetError();
120
        return $res;
121
    }
122
123
    /**
124
     * {@inheritDoc}
125
     */
126
    public function getPath()/*# : string */
127
    {
128
        return $this->path;
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    public function getFullPath()/*# : string */
135
    {
136
        return $this->full;
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142
    public function setContent($content)/*# : bool */
143
    {
144
        if ($this->isFilesystemWritable() &&
145
            !$this->hasTrailingSlash($this->path)
146
        ) {
147
            $res = $this->getDriver()->setContent($this->path, $content);
148
            $this->resetError();
149
            return $res;
150
        }
151
        return false;
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157 View Code Duplication
    public function setMeta(array $meta)/*# : bool */
158
    {
159
        if (!$this->exists()) {
160
            return false;
161
        }
162
163
        if (!empty($meta)) {
164
            $res = $this->getDriver()->setMeta($this->path, $meta);
165
            $this->resetError();
166
            return $res;
167
        }
168
        return true;
169
    }
170
171
    /**
172
     * {@inheritDoc}
173
     */
174
    public function isDir()/*# : bool */
175
    {
176
        if ($this->hasTrailingSlash($this->path) ||
177
            $this->getDriver()->isDir($this->path)
178
        ) {
179
            return true;
180
        }
181
        return false;
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187
    public function rename(/*# string */ $destination)/*# : bool */
188
    {
189
        return $this->alterAction($destination, 'rename');
190
    }
191
192
    /**
193
     * {@inheritDoc}
194
     */
195
    public function copy(/*# string */ $destination)/*# : bool */
196
    {
197
        return $this->alterAction($destination, 'copy');
198
    }
199
200
    /**
201
     * {@inheritDoc}
202
     */
203 View Code Duplication
    public function delete()/*# : bool */
204
    {
205
        if ($this->exists()) {
206
            if (!$this->isFilesystemDeletable()) {
207
                return false;
208
            }
209
210
            $res = $this->getDriver()->delete($this->path);
211
            $this->resetError();
212
            return $res;
213
        }
214
        return true;
215
    }
216
217
    /**
218
     * Reset error to driver's error
219
     *
220
     * @access protected
221
     */
222
    protected function resetError()
223
    {
224
        $this->copyError($this->getFilesystem()->getDriver());
225
    }
226
227
    /**
228
     * Get the driver
229
     *
230
     * @return DriverInterface
231
     * @access protected
232
     */
233
    protected function getDriver()/*# : DriverInterface */
234
    {
235
        return $this->getFilesystem()->getDriver();
236
    }
237
238
    /**
239
     * Do copy or rename in same filesystem
240
     *
241
     * @param  string $destination
242
     * @param  string $action 'copy' or 'rename'
243
     * @return bool
244
     * @access protected
245
     */
246
    protected function alterAction(
247
        /*# string */ $destination,
248
        /*# string */ $action
249
    )/*# : bool */ {
250
        if (!$this->exists() || !$this->isFilesystemWritable()) {
251
            return false;
252
        }
253
254
        // destination is direcotry
255
        if ($this->hasTrailingSlash($destination) ||
256
            $this->getDriver()->isDir($destination)
257
        ) {
258
            $destination = rtrim($destination, '/') . '/' . basename($this->path);
259
        }
260
261
        $res = $this->getDriver()->{$action}($this->path, $destination);
262
        $this->resetError();
263
        return (bool) $res;
264
    }
265
266
    /**
267
     * Is current path has trailing '/'
268
     *
269
     * @param  string $path
270
     * @return bool
271
     * @access protected
272
     */
273
    protected function hasTrailingSlash(/*# string */ $path)/*# : bool */
274
    {
275
        if ($path && '/' == $path[strlen($path)-1]) {
276
            return true;
277
        } else {
278
            return false;
279
        }
280
    }
281
282
    /**
283
     * Check filesystem readable or not
284
     *
285
     * @return bool
286
     * @access protected
287
     */
288
    protected function isFilesystemReadable()/*# : bool */
289
    {
290
        if ($this->getFilesystem()->isReadable()) {
291
            return true;
292
        } else {
293
            return $this->setError(
294
                Message::get(Message::STR_FS_NONREADABLE, $this->full),
295
                Message::STR_FS_NONREADABLE
296
            );
297
        }
298
    }
299
300
    /**
301
     * Check filesystem writable or not
302
     *
303
     * @return bool
304
     * @access protected
305
     */
306
    protected function isFilesystemWritable()/*# : bool */
307
    {
308
        if ($this->getFilesystem()->isWritable()) {
309
            return true;
310
        } else {
311
            return $this->setError(
312
                Message::get(Message::STR_FS_NONWRITABLE, $this->full),
313
                Message::STR_FS_NONWRITABLE
314
            );
315
        }
316
    }
317
318
    /**
319
     * Check filesystem file deletable or not
320
     *
321
     * @return bool
322
     * @access protected
323
     */
324
    protected function isFilesystemDeletable()/*# : bool */
325
    {
326
        if ($this->getFilesystem()->isDeletable()) {
327
            return true;
328
        } else {
329
            return $this->setError(
330
                Message::get(Message::STR_FS_NONDELETABLE, $this->full),
331
                Message::STR_FS_NONDELETABLE
332
            );
333
        }
334
    }
335
}
336