Passed
Push — master ( 7563db...2d2c6c )
by Siad
12:02
created

DeleteTask::setFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
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
 * Deletes a file or directory, or set of files defined by a fileset.
22
 *
23
 * @package phing.tasks.system
24
 */
25
class DeleteTask extends Task
26
{
27
    use ResourceAware;
28
29
    protected $file;
30
    protected $dir;
31
    protected $includeEmpty = false;
32
33
    protected $quiet = false;
34
    protected $failonerror = false;
35
    protected $verbosity = Project::MSG_VERBOSE;
36
37
    /**
38
     * Set the name of a single file to be removed.
39
     *
40
     * @param PhingFile $file
41
     */
42 80
    public function setFile(PhingFile $file)
43
    {
44 80
        $this->file = $file;
45 80
    }
46
47
    /**
48
     * Set the directory from which files are to be deleted.
49
     *
50
     * @param PhingFile $dir
51
     */
52 135
    public function setDir(PhingFile $dir)
53
    {
54 135
        $this->dir = $dir;
55 135
    }
56
57
    /**
58
     * Used to force listing of all names of deleted files.
59
     *
60
     * @param boolean $verbosity
61
     */
62
    public function setVerbose($verbosity)
63
    {
64
        if ($verbosity) {
65
            $this->verbosity = Project::MSG_INFO;
66
        } else {
67
            $this->verbosity = Project::MSG_VERBOSE;
68
        }
69
    }
70
71
    /**
72
     * If the file does not exist, do not display a diagnostic
73
     * message or modify the exit status to reflect an error.
74
     * This means that if a file or directory cannot be deleted,
75
     * then no error is reported. This setting emulates the
76
     * -f option to the Unix rm command. Default is false
77
     * meaning things are verbose
78
     *
79
     * @param  bool $bool
80
     * @return void
81
     */
82 19
    public function setQuiet($bool)
83
    {
84 19
        $this->quiet = $bool;
85 19
        if ($this->quiet) {
86 19
            $this->failonerror = false;
87
        }
88 19
    }
89
90
    /**
91
     * this flag means 'note errors to the output, but keep going'
92
     *
93
     * @param   bool $bool
94
     * @retujrn void
95
     */
96 2
    public function setFailOnError($bool)
97
    {
98 2
        $this->failonerror = $bool;
99 2
    }
100
101
    /**
102
     * Used to delete empty directories.
103
     *
104
     * @param  bool $includeEmpty
105
     * @return void
106
     */
107 9
    public function setIncludeEmptyDirs($includeEmpty)
108
    {
109 9
        $this->includeEmpty = (bool) $includeEmpty;
110 9
    }
111
112
    /**
113
     * Delete the file(s).
114
     *
115
     * @throws BuildException
116
     */
117 222
    public function main()
118
    {
119
        if (
120 222
            $this->file === null
121 144
            && $this->dir === null
122 11
            && count($this->dirsets) === 0
123 10
            && count($this->filesets) === 0
124
            && count($this->filelists) === 0
125
        ) {
126
            throw new BuildException(
127
                "At least one of the file or dir attributes, or a fileset, filelist or dirset element must be set."
128
            );
129
        }
130
131 222
        if ($this->quiet && $this->failonerror) {
132
            throw new BuildException("quiet and failonerror cannot both be set to true", $this->getLocation());
133
        }
134
135
        // delete a single file
136 222
        if ($this->file !== null) {
137 80
            if ($this->file->exists()) {
138 46
                if ($this->file->isDirectory()) {
139 5
                    $this->log(
140 5
                        "Directory " . $this->file->__toString() . " cannot be removed using the file attribute. Use dir instead."
141
                    );
142
                } else {
143 41
                    $this->log("Deleting: " . $this->file->__toString());
144
                    try {
145 41
                        $this->file->delete();
146
                    } catch (Exception $e) {
147
                        $message = "Unable to delete file " . $this->file->__toString() . ": " . $e->getMessage();
148
                        if ($this->failonerror) {
149
                            throw new BuildException($message);
150
                        }
151
152
                        $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
153
                    }
154
                }
155
            } else {
156 47
                $message = "Could not find file " . $this->file->getAbsolutePath() . " to delete.";
157
158 47
                if ($this->failonerror) {
159 1
                    throw new BuildException($message);
160
                }
161
162 46
                $this->log($message, ($this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN));
163
            }
164
        }
165
166 222
        if ($this->dir !== null) {
167 135
            $this->dirsets[] = $this->dir;
168
        }
169 222
        foreach ($this->dirsets as $dirset) {
170 135
            if (!$dirset instanceof PhingFile) {
171 1
                $ds = $dirset->getDirectoryScanner($this->getProject());
172 1
                $dirs = $ds->getIncludedDirectories();
173 1
                $baseDir = $ds->getBasedir();
174
            } else {
175 135
                $dirs[0] = $dirset;
176
            }
177 135
            foreach ($dirs as $dir) {
178 135
                if (!$dir instanceof PhingFile) {
179 1
                    $dir = new PhingFile($baseDir, $dir);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $baseDir does not seem to be defined for all execution paths leading up to this point.
Loading history...
180
                }
181 135
                if ($dir->exists() && $dir->isDirectory()) {
182 127
                    if ($this->verbosity === Project::MSG_VERBOSE) {
183 127
                        $this->log("Deleting directory " . $dir->__toString());
184
                    }
185 127
                    $this->removeDir($dir);
186
                } else {
187 10
                    $message = "Directory " . $dir->getAbsolutePath() . " does not exist or is not a directory.";
188
189 10
                    if ($this->failonerror) {
190 1
                        throw new BuildException($message);
191
                    }
192
193 9
                    $this->log($message, ($this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN));
194
                }
195
            }
196
        }
197
198
        // delete the files in the filelists
199 222
        foreach ($this->filelists as $fl) {
200
            try {
201
                $files = $fl->getFiles($this->project);
202
                $empty = [];
203
                $this->removeFiles($fl->getDir($this->project), $files, $empty);
204
            } catch (BuildException $be) {
205
                // directory doesn't exist or is not readable
206
                if ($this->failonerror) {
207
                    throw $be;
208
                }
209
210
                $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
211
            }
212
        }
213
214
        // delete the files in the filesets
215 222
        foreach ($this->filesets as $fs) {
216
            try {
217 10
                $ds = $fs->getDirectoryScanner($this->project);
218 10
                $files = $ds->getIncludedFiles();
219 10
                $dirs = $ds->getIncludedDirectories();
220 10
                $this->removeFiles($fs->getDir($this->project), $files, $dirs);
221
            } catch (BuildException $be) {
222
                // directory doesn't exist or is not readable
223
                if ($this->failonerror) {
224
                    throw $be;
225
                }
226
227
                $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
228
            }
229
        }
230 222
    }
231
232
    /**
233
     * Recursively removes a directory.
234
     *
235
     * @param  PhingFile $d The directory to remove.
236
     * @throws BuildException
237
     */
238 127
    private function removeDir($d)
239
    {
240 127
        $list = $d->listDir();
241 127
        if ($list === null) {
242
            $list = [];
243
        }
244
245 127
        foreach ($list as $s) {
246 109
            $f = new PhingFile($d, $s);
247 109
            if ($f->isDirectory()) {
248 37
                $this->removeDir($f);
249
            } else {
250 103
                $this->log("Deleting " . $f->__toString(), $this->verbosity);
251
                try {
252 103
                    $f->delete();
253
                } catch (Exception $e) {
254
                    $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
255
                    if ($this->failonerror) {
256
                        throw new BuildException($message);
257
                    }
258
259
                    $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
260
                }
261
            }
262
        }
263 127
        $this->log("Deleting directory " . $d->getAbsolutePath(), $this->verbosity);
264
        try {
265 127
            $d->delete();
266
        } catch (Exception $e) {
267
            $message = "Unable to delete directory " . $d->__toString() . ": " . $e->getMessage();
268
            if ($this->failonerror) {
269
                throw new BuildException($message);
270
            }
271
272
            $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
273
        }
274 127
    }
275
276
    /**
277
     * remove an array of files in a directory, and a list of subdirectories
278
     * which will only be deleted if 'includeEmpty' is true
279
     *
280
     * @param  PhingFile $d directory to work from
281
     * @param  array     &$files array of files to delete; can be of zero length
282
     * @param  array     &$dirs array of directories to delete; can of zero length
283
     * @throws BuildException
284
     */
285 10
    private function removeFiles(PhingFile $d, &$files, &$dirs)
286
    {
287 10
        if (count($files) > 0) {
288 1
            $this->log("Deleting " . count($files) . " files from " . $d->__toString());
289 1
            for ($j = 0, $_j = count($files); $j < $_j; $j++) {
290 1
                $f = new PhingFile($d, $files[$j]);
291 1
                $this->log("Deleting " . $f->getAbsolutePath(), $this->verbosity);
292
                try {
293 1
                    $f->delete();
294
                } catch (Exception $e) {
295
                    $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
296
                    if ($this->failonerror) {
297
                        throw new BuildException($message);
298
                    }
299
300
                    $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
301
                }
302
            }
303
        }
304
305 10
        if (count($dirs) > 0 && $this->includeEmpty) {
306 9
            $dirCount = 0;
307 9
            for ($j = count($dirs) - 1; $j >= 0; --$j) {
308 9
                $dir = new PhingFile($d, $dirs[$j]);
309 9
                $dirFiles = $dir->listDir();
310 9
                if ($dirFiles === null || count($dirFiles) === 0) {
311 9
                    $this->log("Deleting " . $dir->__toString(), $this->verbosity);
312
                    try {
313 9
                        $dir->delete();
314 9
                        $dirCount++;
315
                    } catch (Exception $e) {
316
                        $message = "Unable to delete directory " . $dir->__toString();
317
                        if ($this->failonerror) {
318
                            throw new BuildException($message);
319
                        }
320
321
                        $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
322
                    }
323
                }
324
            }
325 9
            if ($dirCount > 0) {
326 9
                $this->log("Deleted $dirCount director" . ($dirCount == 1 ? "y" : "ies") . " from " . $d->__toString());
0 ignored issues
show
introduced by
The condition $dirCount == 1 is always false.
Loading history...
327
            }
328
        }
329 10
    }
330
}
331