Passed
Push — master ( e1f86a...4e1a3a )
by Siad
05:23
created

DeleteTask   F

Complexity

Total Complexity 68

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Test Coverage

Coverage 67.65%

Importance

Changes 0
Metric Value
eloc 141
dl 0
loc 302
ccs 92
cts 136
cp 0.6765
rs 2.96
c 0
b 0
f 0
wmc 68

9 Methods

Rating   Name   Duplication   Size   Complexity  
C removeFiles() 0 42 16
A setFailOnError() 0 3 1
B removeDir() 0 35 10
A setIncludeEmptyDirs() 0 3 1
A setDir() 0 3 1
A setFile() 0 3 1
A setVerbose() 0 6 2
F main() 0 111 34
A setQuiet() 0 5 2

How to fix   Complexity   

Complex Class

Complex classes like DeleteTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DeleteTask, and based on these observations, apply Extract Interface, too.

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