Storage::diffFilesystemCopy()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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