Completed
Push — master ( 79d0be...0a8746 )
by Siad
14:20
created

MoveTask::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * Moves a file or directory to a new file or directory.
22
 *
23
 * By default, the destination file is overwritten if it
24
 * already exists.  When overwrite is turned off, then files
25
 * are only moved if the source file is newer than the
26
 * destination file, or when the destination file does not
27
 * exist.
28
 *
29
 * Source files and directories are only deleted when the file or
30
 * directory has been copied to the destination successfully.
31
 *
32
 * @package phing.tasks.system
33
 */
34
class MoveTask extends CopyTask
35
{
36 5
    public function __construct()
37
    {
38 5
        parent::__construct();
39 5
        $this->overwrite = true;
40 5
    }
41
42
    /**
43
     * Validates attributes coming in from XML
44
     *
45
     * @return void
46
     *
47
     * @throws BuildException
48
     */
49 5
    protected function validateAttributes()
50
    {
51 5
        if ($this->file !== null && $this->file->isDirectory()) {
52
            if (
53 1
                ($this->destFile !== null
54 1
                && $this->destDir !== null)
55 1
                || ($this->destFile === null
56
                && $this->destDir === null)
57
            ) {
58
                throw new BuildException("One and only one of tofile and todir must be set.");
59
            }
60
61 1
            if ($this->destFile === null) {
62
                $this->destFile = new PhingFile($this->destDir, $this->file->getName());
63
            }
64
65 1
            if ($this->destDir === null) {
66 1
                $this->destDir = $this->destFile->getParentFile();
67
            }
68
69 1
            $this->completeDirMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath();
70
71 1
            $this->file = null;
72
        } else {
73 4
            parent::validateAttributes();
74
        }
75 5
    }
76
77 5
    protected function doWork()
78
    {
79 5
        if (count($this->completeDirMap) > 0) {
80 1
            foreach ($this->completeDirMap as $from => $to) {
81 1
                $f = new PhingFile($from);
82 1
                $d = new PhingFile($to);
83
84
                try { // try to rename
85 1
                    $this->log("Attempting to rename $from to $to", $this->verbosity);
86 1
                    if (!empty($this->filterChains)) {
87
                        $this->fileUtils->copyFile(
88
                            $f,
89
                            $d,
90
                            $this->getProject(),
91
                            $this->overwrite,
92
                            $this->preserveLMT,
93
                            $this->filterChains,
94
                            $this->mode
95
                        );
96
                        $f->delete(true);
97
                    } else {
98 1
                        $this->fileUtils->renameFile($f, $d, $this->overwrite);
99
                    }
100
                } catch (IOException $ioe) {
101
                    $this->logError("Failed to rename $from to $to: " . $ioe->getMessage());
102
                }
103
            }
104
        }
105
106 5
        $copyMapSize = count($this->fileCopyMap);
107 5
        if ($copyMapSize > 0) {
108
            // files to move
109 3
            $this->log("Moving $copyMapSize files to " . $this->destDir->getAbsolutePath());
110
111 3
            foreach ($this->fileCopyMap as $from => $to) {
112 3
                if ($from == $to) {
113
                    $this->log("Skipping self-move of $from", $this->verbosity);
114
                    continue;
115
                }
116
117 3
                $f = new PhingFile($from);
118 3
                $d = new PhingFile($to);
119
120
                try { // try to move
121 3
                    $this->log("Moving $from to $to", $this->verbosity);
122
123 3
                    $this->fileUtils->copyFile(
124 3
                        $f,
125 3
                        $d,
126 3
                        $this->getProject(),
127 3
                        $this->overwrite,
128 3
                        $this->preserveLMT,
129 3
                        $this->filterChains,
130 3
                        $this->mode
131
                    );
132
133 3
                    $f->delete();
134
                } catch (IOException $ioe) {
135
                    $this->logError("Failed to move $from to $to: " . $ioe->getMessage(), $this->getLocation());
136
                }
137
            } // foreach fileCopyMap
138
        } // if copyMapSize
139
140
        // handle empty dirs if appropriate
141 5
        if ($this->includeEmpty) {
142 5
            $count = 0;
143 5
            foreach ($this->dirCopyMap as $srcDir => $destDir) {
144
                $d = new PhingFile((string) $destDir);
145
                if (!$d->exists()) {
146
                    if (!$d->mkdirs()) {
147
                        $this->logError("Unable to create directory " . $d->getAbsolutePath());
148
                    } else {
149
                        $count++;
150
                    }
151
                }
152
            }
153 5
            if ($count > 0) {
154
                $this->log(
155
                    "moved $count empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath(
156
                    )
157
                );
158
            }
159
        }
160
161 5
        if (count($this->filesets) > 0) {
162
            // process filesets
163 1
            foreach ($this->filesets as $fs) {
164 1
                $dir = $fs->getDir($this->project);
165 1
                if ($this->okToDelete($dir)) {
166 1
                    $this->deleteDir($dir);
167
                }
168
            }
169
        }
170
171 5
        $dirsets = $this->getDirSets();
172 5
        if (count($dirsets) > 0) {
173
            // process dirsets
174
            foreach ($dirsets as $ds) {
175
                $dir = $ds->getDir($this->project);
176
                if ($this->okToDelete($dir)) {
177
                    $this->deleteDir($dir);
178
                }
179
            }
180
        }
181 5
    }
182
183
    /**
184
     * Its only ok to delete a dir tree if there are no files in it.
185
     *
186
     * @param $d
187
     *
188
     * @throws IOException
189
     *
190
     * @return bool
191
     */
192 1
    private function okToDelete(PhingFile $d)
193
    {
194 1
        $list = $d->listDir();
195 1
        if ($list === null) {
196
            return false; // maybe io error?
197
        }
198
199 1
        foreach ($list as $s) {
200 1
            $f = new PhingFile($d, $s);
201 1
            if ($f->isDirectory()) {
202 1
                if (!$this->okToDelete($f)) {
203
                    return false;
204
                }
205
            } else {
206
                // found a file
207
                return false;
208
            }
209
        }
210
211 1
        return true;
212
    }
213
214
    /**
215
     * Go and delete the directory tree.
216
     *
217
     * @param $d
218
     *
219
     * @throws BuildException
220
     * @throws IOException
221
     */
222 1
    private function deleteDir(PhingFile $d)
223
    {
224 1
        $list = $d->listDir();
225 1
        if ($list === null) {
226
            return; // on an io error list() can return null
227
        }
228
229 1
        foreach ($list as $fname) {
230 1
            $f = new PhingFile($d, $fname);
231 1
            if ($f->isDirectory()) {
232 1
                $this->deleteDir($f);
233
            } else {
234
                throw new BuildException("UNEXPECTED ERROR - The file " . $f->getAbsolutePath() . " should not exist!");
235
            }
236
        }
237
238 1
        $this->log("Deleting directory " . $d->getPath(), $this->verbosity);
239
        try {
240 1
            $d->delete();
241
        } catch (Exception $e) {
242
            $this->logError("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage());
243
        }
244 1
    }
245
}
246