Completed
Push — master ( 6ea042...f995da )
by Hong
02:12
created

Path::alterAction()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 17
rs 9.2
cc 4
eloc 10
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(/*# string */ $path = '')/*# : bool */
175
    {
176
        $p = $path ?: $this->path;
177
        if ($this->hasTrailingSlash($p) || $this->getDriver()->isDir($p)) {
178
            return true;
179
        }
180
        return false;
181
    }
182
183
    /**
184
     * {@inheritDoc}
185
     */
186
    public function rename(/*# string */ $destination)/*# : bool */
187
    {
188
        return $this->alterAction($destination, 'rename');
189
    }
190
191
    /**
192
     * {@inheritDoc}
193
     */
194
    public function copy(/*# string */ $destination)/*# : bool */
195
    {
196
        return $this->alterAction($destination, 'copy');
197
    }
198
199
    /**
200
     * {@inheritDoc}
201
     */
202 View Code Duplication
    public function delete()/*# : bool */
203
    {
204
        if ($this->exists()) {
205
            if (!$this->isFilesystemDeletable()) {
206
                return false;
207
            }
208
209
            $res = $this->getDriver()->delete($this->path);
210
            $this->resetError();
211
            return $res;
212
        }
213
        return true;
214
    }
215
216
    /**
217
     * Reset error to driver's error
218
     *
219
     * @access protected
220
     */
221
    protected function resetError()
222
    {
223
        $this->copyError($this->getFilesystem()->getDriver());
224
    }
225
226
    /**
227
     * Get the driver
228
     *
229
     * @return DriverInterface
230
     * @access protected
231
     */
232
    protected function getDriver()/*# : DriverInterface */
233
    {
234
        return $this->getFilesystem()->getDriver();
235
    }
236
237
    /**
238
     * Do copy or rename in same filesystem
239
     *
240
     * @param  string $destination
241
     * @param  string $action 'copy' or 'rename'
242
     * @return bool
243
     * @access protected
244
     */
245
    protected function alterAction(
246
        /*# string */ $destination,
247
        /*# string */ $action
248
    )/*# : bool */ {
249
        if (!$this->exists() || !$this->isFilesystemWritable()) {
250
            return false;
251
        }
252
253
        // destination is direcotry
254
        if ($this->isDir($destination)) {
255
            $destination = rtrim($destination, '/') . '/' . basename($this->path);
256
        }
257
258
        $res = $this->getDriver()->{$action}($this->path, $destination);
259
        $this->resetError();
260
        return (bool) $res;
261
    }
262
263
    /**
264
     * Is current path has trailing '/'
265
     *
266
     * @param  string $path
267
     * @return bool
268
     * @access protected
269
     */
270
    protected function hasTrailingSlash(/*# string */ $path)/*# : bool */
271
    {
272
        if ($path && '/' == $path[strlen($path)-1]) {
273
            return true;
274
        } else {
275
            return false;
276
        }
277
    }
278
279
    /**
280
     * Check filesystem readable or not
281
     *
282
     * @return bool
283
     * @access protected
284
     */
285
    protected function isFilesystemReadable()/*# : bool */
286
    {
287
        if ($this->getFilesystem()->isReadable()) {
288
            return true;
289
        } else {
290
            return $this->setError(
291
                Message::get(Message::STR_FS_NONREADABLE, $this->full),
292
                Message::STR_FS_NONREADABLE
293
            );
294
        }
295
    }
296
297
    /**
298
     * Check filesystem writable or not
299
     *
300
     * @return bool
301
     * @access protected
302
     */
303
    protected function isFilesystemWritable()/*# : bool */
304
    {
305
        if ($this->getFilesystem()->isWritable()) {
306
            return true;
307
        } else {
308
            return $this->setError(
309
                Message::get(Message::STR_FS_NONWRITABLE, $this->full),
310
                Message::STR_FS_NONWRITABLE
311
            );
312
        }
313
    }
314
315
    /**
316
     * Check filesystem file deletable or not
317
     *
318
     * @return bool
319
     * @access protected
320
     */
321
    protected function isFilesystemDeletable()/*# : bool */
322
    {
323
        if ($this->getFilesystem()->isDeletable()) {
324
            return true;
325
        } else {
326
            return $this->setError(
327
                Message::get(Message::STR_FS_NONDELETABLE, $this->full),
328
                Message::STR_FS_NONDELETABLE
329
            );
330
        }
331
    }
332
}
333