Passed
Push — master ( 4d6caf...4726e4 )
by Siad
10:49
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 64
    public function setFile(PhingFile $file)
43
    {
44 64
        $this->file = $file;
45 64
    }
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 206
    public function main()
118
    {
119
        if (
120 206
            $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 206
        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 206
        if ($this->file !== null) {
137 64
            if ($this->file->exists()) {
138 32
                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 27
                    $this->log("Deleting: " . $this->file->__toString());
144
                    try {
145 27
                        $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 45
                $message = "Could not find file " . $this->file->getAbsolutePath() . " to delete.";
157
158 45
                if ($this->failonerror) {
159 1
                    throw new BuildException($message);
160
                }
161
162 44
                $this->log($message, ($this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN));
163
            }
164
        }
165
166 206
        if ($this->dir !== null) {
167 135
            $this->dirsets[] = $this->dir;
168
        }
169 206
        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 206
        foreach ($this->filelists as $fl) {
200
            try {
201
                $files = $fl->getFiles($this->project);
202
                $this->removeFiles($fl->getDir($this->project), $files, $empty = []);
0 ignored issues
show
Bug introduced by
$empty = array() cannot be passed to DeleteTask::removeFiles() as the parameter $dirs expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
                $this->removeFiles($fl->getDir($this->project), $files, /** @scrutinizer ignore-type */ $empty = []);
Loading history...
203
            } catch (BuildException $be) {
204
                // directory doesn't exist or is not readable
205
                if ($this->failonerror) {
206
                    throw $be;
207
                }
208
209
                $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
210
            }
211
        }
212
213
        // delete the files in the filesets
214 206
        foreach ($this->filesets as $fs) {
215
            try {
216 10
                $ds = $fs->getDirectoryScanner($this->project);
217 10
                $files = $ds->getIncludedFiles();
218 10
                $dirs = $ds->getIncludedDirectories();
219 10
                $this->removeFiles($fs->getDir($this->project), $files, $dirs);
220
            } catch (BuildException $be) {
221
                // directory doesn't exist or is not readable
222
                if ($this->failonerror) {
223
                    throw $be;
224
                }
225
226
                $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
227
            }
228
        }
229 206
    }
230
231
    /**
232
     * Recursively removes a directory.
233
     *
234
     * @param  PhingFile $d The directory to remove.
235
     * @throws BuildException
236
     */
237 127
    private function removeDir($d)
238
    {
239 127
        $list = $d->listDir();
240 127
        if ($list === null) {
241
            $list = [];
242
        }
243
244 127
        foreach ($list as $s) {
245 109
            $f = new PhingFile($d, $s);
246 109
            if ($f->isDirectory()) {
247 37
                $this->removeDir($f);
248
            } else {
249 103
                $this->log("Deleting " . $f->__toString(), $this->verbosity);
250
                try {
251 103
                    $f->delete();
252
                } catch (Exception $e) {
253
                    $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
254
                    if ($this->failonerror) {
255
                        throw new BuildException($message);
256
                    }
257
258
                    $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
259
                }
260
            }
261
        }
262 127
        $this->log("Deleting directory " . $d->getAbsolutePath(), $this->verbosity);
263
        try {
264 127
            $d->delete();
265
        } catch (Exception $e) {
266
            $message = "Unable to delete directory " . $d->__toString() . ": " . $e->getMessage();
267
            if ($this->failonerror) {
268
                throw new BuildException($message);
269
            }
270
271
            $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
272
        }
273 127
    }
274
275
    /**
276
     * remove an array of files in a directory, and a list of subdirectories
277
     * which will only be deleted if 'includeEmpty' is true
278
     *
279
     * @param  PhingFile $d directory to work from
280
     * @param  array     &$files array of files to delete; can be of zero length
281
     * @param  array     &$dirs array of directories to delete; can of zero length
282
     * @throws BuildException
283
     */
284 10
    private function removeFiles(PhingFile $d, &$files, &$dirs)
285
    {
286 10
        if (count($files) > 0) {
287 1
            $this->log("Deleting " . count($files) . " files from " . $d->__toString());
288 1
            for ($j = 0, $_j = count($files); $j < $_j; $j++) {
289 1
                $f = new PhingFile($d, $files[$j]);
290 1
                $this->log("Deleting " . $f->getAbsolutePath(), $this->verbosity);
291
                try {
292 1
                    $f->delete();
293
                } catch (Exception $e) {
294
                    $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
295
                    if ($this->failonerror) {
296
                        throw new BuildException($message);
297
                    }
298
299
                    $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
300
                }
301
            }
302
        }
303
304 10
        if (count($dirs) > 0 && $this->includeEmpty) {
305 9
            $dirCount = 0;
306 9
            for ($j = count($dirs) - 1; $j >= 0; --$j) {
307 9
                $dir = new PhingFile($d, $dirs[$j]);
308 9
                $dirFiles = $dir->listDir();
309 9
                if ($dirFiles === null || count($dirFiles) === 0) {
310 9
                    $this->log("Deleting " . $dir->__toString(), $this->verbosity);
311
                    try {
312 9
                        $dir->delete();
313 9
                        $dirCount++;
314
                    } catch (Exception $e) {
315
                        $message = "Unable to delete directory " . $dir->__toString();
316
                        if ($this->failonerror) {
317
                            throw new BuildException($message);
318
                        }
319
320
                        $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
321
                    }
322
                }
323
            }
324 9
            if ($dirCount > 0) {
325 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...
326
            }
327
        }
328 10
    }
329
}
330