Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * Hoa
5
 *
6
 *
7
 * @license
8
 *
9
 * New BSD License
10
 *
11
 * Copyright © 2007-2017, Hoa community. All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *     * Redistributions of source code must retain the above copyright
16
 *       notice, this list of conditions and the following disclaimer.
17
 *     * Redistributions in binary form must reproduce the above copyright
18
 *       notice, this list of conditions and the following disclaimer in the
19
 *       documentation and/or other materials provided with the distribution.
20
 *     * Neither the name of the Hoa nor the names of its contributors may be
21
 *       used to endorse or promote products derived from this software without
22
 *       specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
 
37
namespace Psy\Readline\Hoa;
38
 
39
/**
40
 * Class \Hoa\File\Directory.
41
 *
42
 * Directory handler.
43
 */
44
class FileDirectory extends FileGeneric
45
{
46
    /**
47
     * Open for reading.
48
     */
49
    const MODE_READ = 'rb';
50
 
51
    /**
52
     * Open for reading and writing. If the directory does not exist, attempt to
53
     * create it.
54
     */
55
    const MODE_CREATE = 'xb';
56
 
57
    /**
58
     * Open for reading and writing. If the directory does not exist, attempt to
59
     * create it recursively.
60
     */
61
    const MODE_CREATE_RECURSIVE = 'xrb';
62
 
63
    /**
64
     * Open a directory.
65
     */
66
    public function __construct(
67
        string $streamName,
68
        string $mode = self::MODE_READ,
69
        string $context = null,
70
        bool $wait = false
71
    ) {
72
        $this->setMode($mode);
73
        parent::__construct($streamName, $context, $wait);
74
 
75
        return;
76
    }
77
 
78
    /**
79
     * Open the stream and return the associated resource.
80
     */
81
    protected function &_open(string $streamName, StreamContext $context = null)
82
    {
83
        if (false === \is_dir($streamName)) {
84
            if ($this->getMode() === self::MODE_READ) {
85
                throw new FileDoesNotExistException('Directory %s does not exist.', 0, $streamName);
86
            } else {
87
                self::create(
88
                    $streamName,
89
                    $this->getMode(),
90
                    null !== $context
91
                        ? $context->getContext()
92
                        : null
93
                );
94
            }
95
        }
96
 
97
        $out = null;
98
 
99
        return $out;
100
    }
101
 
102
    /**
103
     * Close the current stream.
104
     */
105
    protected function _close(): bool
106
    {
107
        return true;
108
    }
109
 
110
    /**
111
     * Recursive copy of a directory.
112
     */
113
    public function copy(string $to, bool $force = StreamTouchable::DO_NOT_OVERWRITE): bool
114
    {
115
        if (empty($to)) {
116
            throw new FileException('The destination path (to copy) is empty.', 1);
117
        }
118
 
119
        $from = $this->getStreamName();
120
        $fromLength = \strlen($from) + 1;
121
        $finder = new FileFinder();
122
        $finder->in($from);
123
 
124
        self::create($to, self::MODE_CREATE_RECURSIVE);
125
 
126
        foreach ($finder as $file) {
127
            $relative = \substr($file->getPathname(), $fromLength);
128
            $_to = $to.\DIRECTORY_SEPARATOR.$relative;
129
 
130
            if (true === $file->isDir()) {
131
                self::create($_to, self::MODE_CREATE);
132
 
133
                continue;
134
            }
135
 
136
            // This is not possible to do `$file->open()->copy();
137
            // $file->close();` because the file will be opened in read and
138
            // write mode. In a PHAR for instance, this operation is
139
            // forbidden. So a special care must be taken to open file in read
140
            // only mode.
141
            $handle = null;
142
 
143
            if (true === $file->isFile()) {
144
                $handle = new FileRead($file->getPathname());
145
            } elseif (true === $file->isDir()) {
146
                $handle = new self($file->getPathName());
147
            } elseif (true === $file->isLink()) {
148
                $handle = new FileLinkRead($file->getPathName());
149
            }
150
 
151
            if (null !== $handle) {
152
                $handle->copy($_to, $force);
153
                $handle->close();
154
            }
155
        }
156
 
157
        return true;
158
    }
159
 
160
    /**
161
     * Delete a directory.
162
     */
163
    public function delete(): bool
164
    {
165
        $from = $this->getStreamName();
166
        $finder = new FileFinder();
167
        $finder->in($from)
168
               ->childFirst();
169
 
170
        foreach ($finder as $file) {
171
            $file->open()->delete();
172
            $file->close();
173
        }
174
 
175
        if (null === $this->getStreamContext()) {
176
            return @\rmdir($from);
177
        }
178
 
179
        return @\rmdir($from, $this->getStreamContext()->getContext());
180
    }
181
 
182
    /**
183
     * Create a directory.
184
     */
185
    public static function create(
186
        string $name,
187
        string $mode = self::MODE_CREATE_RECURSIVE,
188
        string $context = null
189
    ): bool {
190
        if (true === \is_dir($name)) {
191
            return true;
192
        }
193
 
194
        if (empty($name)) {
195
            return false;
196
        }
197
 
198
        if (null !== $context) {
199
            if (false === StreamContext::contextExists($context)) {
200
                throw new FileException('Context %s was not previously declared, cannot retrieve '.'this context.', 2, $context);
201
            } else {
202
                $context = StreamContext::getInstance($context);
203
            }
204
        }
205
 
206
        if (null === $context) {
207
            return @\mkdir(
208
                $name,
209
                0755,
210
                self::MODE_CREATE_RECURSIVE === $mode
211
            );
212
        }
213
 
214
        return @\mkdir(
215
            $name,
216
            0755,
217
            self::MODE_CREATE_RECURSIVE === $mode,
218
            $context->getContext()
219
        );
220
    }
221
}