Completed
Push — master ( 233e03...986f2c )
by Hong
02:42
created

Storage::copy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 10
rs 9.4285
nc 2
cc 2
eloc 7
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\Storage\Traits\PathAwareTrait;
21
use Phossa2\Shared\Error\ErrorAwareInterface;
22
use Phossa2\Storage\Interfaces\StorageInterface;
23
use Phossa2\Shared\Extension\ExtensionAwareTrait;
24
use Phossa2\Shared\Extension\ExtensionAwareInterface;
25
use Phossa2\Storage\Interfaces\FilesystemInterface;
26
27
/**
28
 * Storage
29
 *
30
 * @package Phossa2\Storage
31
 * @author  Hong Zhang <[email protected]>
32
 * @see     ObjectAbstract
33
 * @see     StorageInterface
34
 * @see     ErrorAwareInterface
35
 * @see     ExtensionAwareInterface
36
 * @version 2.0.0
37
 * @since   2.0.0 added
38
 */
39
class Storage extends ObjectAbstract implements StorageInterface, ErrorAwareInterface, ExtensionAwareInterface
40
{
41
    use PathAwareTrait, ErrorAwareTrait, ExtensionAwareTrait;
42
43
    /**
44
     * @param  string $mountPoint
45
     * @param  FilesystemInterface $filesystem
46
     * @access public
47
     */
48
    public function __construct(
49
        /*# string */ $mountPoint,
50
        FilesystemInterface $filesystem
51
    ) {
52
        $this->mount($mountPoint, $filesystem);
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     */
58
    public function has(/*# string */ $path)/*# : bool */
59
    {
60
        // found
61
        if ($this->path($path)->exists()) {
62
            return true;
63
        }
64
65
        // not found
66
        return $this->setError(
67
            Message::get(Message::MSG_PATH_NOTFOUND, $path),
68
            Message::MSG_PATH_NOTFOUND
69
        );
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75
    public function get(/*# string */ $path, /*# bool */ $stream = false)
76
    {
77
        $obj = $this->path($path);
78
        $res = $obj->getContent($stream);
79
80
        // append mount point if result is array
81
        if (is_array($res)) {
82
            return $this->prependMountPoint(
83
                $res, $this->getMountPoint($obj->getFullPath())
84
            );
85
        }
86
87
        $this->copyError($obj);
88
89
        return $res;
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     */
95
    public function put(
96
        /*# string */ $path,
97
        $content,
98
        array $meta = []
99
    )/*# : bool */ {
100
        $obj = $this->path($path);
101
102
        // write content
103
        if (null !== $content && !$obj->setContent($content)) {
104
            $this->copyError($obj);
105
            return false;
106
        }
107
108
        // set meta if any
109
        $res = $obj->setMeta($meta);
110
        $this->copyError($obj);
111
        return $res;
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117
    public function meta(/*# string */ $path)/*# : array */
118
    {
119
        $obj = $this->path($path);
120
        $res = $obj->getMeta();
121
        $this->copyError($obj);
122
        return $res;
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function copy(
129
        /*# string */ $from,
130
        /*# string */ $to
131
    )/*# : bool */ {
132
        if ($this->isSameFilesystem($from, $to)) {
133
            return $this->sameFilesystemAction($from, $to, 'copy');
134
        } else {
135
            return $this->diffFilesystemCopy($from, $to);
136
        }
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142
    public function move(
143
        /*# string */ $from,
144
        /*# string */ $to
145
    )/*# : bool */ {
146
        if ($this->isSameFilesystem($from, $to)) {
147
            return $this->sameFilesystemAction($from, $to, 'rename');
148
        } elseif ($this->copy($from, $to)) {
149
            return $this->delete($from);
150
        }
151
        return false;
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157
    public function delete(/*# string */ $path)/*# : bool */
158
    {
159
        $obj = $this->path($path);
160
        $res = $obj->delete();
161
        $this->copyError($obj);
162
        return $res;
163
    }
164
165
    /**
166
     * {@inheritDoc}
167
     */
168
    public function isDir(/*# string */ $path)/*# : bool */
169
    {
170
        return $this->path($path)->isDir();
171
    }
172
173
    /**
174
     * Copy or rename
175
     *
176
     * @param  string $from
177
     * @param  string $to
178
     * @param  string $action 'copy' or 'rename'
179
     * @return bool
180
     * @access protected
181
     */
182
    protected function sameFilesystemAction(
183
        /*# string */ $from,
184
        /*# string */ $to,
185
        /*# string */ $action = 'copy'
186
    )/*# : bool */ {
187
        $obj = $this->path($from);
188
        $res = $obj->{$action}($this->path($to)->getPath());
189
        $this->copyError($obj);
190
        return $res;
191
    }
192
193
    /**
194
     * Copy between different filesystem
195
     *
196
     * @param  string $from
197
     * @param  string $to
198
     * @return bool
199
     * @access protected
200
     */
201
    protected function diffFilesystemCopy(
202
        /*# string */ $from,
203
        /*# string */ $to
204
    )/*# : bool */ {
205
        if ($this->isDir($to)) {
206
            $to = $this->mergePath($to, basename($from));
207
        }
208
209
        $content = $this->get($from);
210
211
        if (is_null($content)) {
212
            return false;
213
214
        } elseif (is_array($content)) {
215
            return $this->copyDir($content, $to);
216
217
        } else {
218
            return $this->put($to, $content);
219
        }
220
    }
221
222
    /**
223
     * Exists on same filesystem ?
224
     *
225
     * @param  string $path1
226
     * @param  string $path2
227
     * @return bool
228
     * @access protected
229
     */
230
    protected function isSameFilesystem(
231
        /*# string */ $path1,
232
        /*# string */ $path2
233
    )/*# : bool */ {
234
        return $this->path($path1)->getFilesystem() === $this->path($path2)->getFilesystem();
235
    }
236
237
    /**
238
     * Copy an array of paths to destination
239
     *
240
     * @param  array $paths
241
     * @param  string $destination
242
     * @access protected
243
     */
244
    protected function copyDir(array $paths, /*# string */ $destination)
245
    {
246
        foreach ($paths as $path) {
247
            $dest = $this->mergePath($destination, basename($path));
248
            if (!$this->copy($path, $dest)) {
249
                return false;
250
            }
251
        }
252
        return true;
253
    }
254
255
    /**
256
     * Prepend mount point prefix to the array of paths
257
     *
258
     * @param  array $paths
259
     * @param  string $mountPoint
260
     * @return array
261
     * @access protected
262
     */
263
    protected function prependMountPoint(
264
        array $paths,
265
        /*# string */ $mountPoint
266
    )/*# : array */ {
267
        $res = [];
268
        foreach ($paths as $p) {
269
            $res[] = $this->mergePath($mountPoint, $p);
270
        }
271
        return $res;
272
    }
273
}
274