Passed
Push — master ( fedd27...f10ad5 )
by Michiel
11:13
created

TouchTask::checkConfiguration()   B

Complexity

Conditions 11
Paths 5

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 15.4801

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 11
eloc 15
c 1
b 1
f 0
nc 5
nop 0
dl 0
loc 27
ccs 10
cts 15
cp 0.6667
crap 15.4801
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
 * Touch a file and/or fileset(s); corresponds to the Unix touch command.
22
 *
23
 * If the file to touch doesn't exist, an empty one is created.
24
 *
25
 * @package phing.tasks.system
26
 */
27
class TouchTask extends Task
28
{
29
    use FileListAware;
30
    use FileSetAware;
31
32
    /**
33
     * @var PhingFile $file
34
     */
35
    private $file;
36
    private $millis = -1;
37
    private $dateTime;
38
    private $fileUtils;
39
    private $mkdirs = false;
40
    private $verbose = true;
41
42
    /** @var Mapper $mapperElement */
43
    private $mapperElement;
44
45
    /**
46
     *
47
     */
48 66
    public function __construct()
49
    {
50 66
        parent::__construct();
51 66
        $this->fileUtils = new FileUtils();
52 66
    }
53
54
    /**
55
     * Sets a single source file to touch.  If the file does not exist
56
     * an empty file will be created.
57
     *
58
     * @param  PhingFile $file
59
     * @return void
60
     */
61 64
    public function setFile(PhingFile $file)
62
    {
63 64
        $this->file = $file;
64 64
    }
65
66
    /**
67
     * the new modification time of the file
68
     * in milliseconds since midnight Jan 1 1970.
69
     * Optional, default=now
70
     *
71
     * @param  $millis
72
     * @return void
73
     */
74 8
    public function setMillis($millis)
75
    {
76 8
        $this->millis = (int) $millis;
77 8
    }
78
79
    /**
80
     * the new modification time of the file
81
     * in the format MM/DD/YYYY HH:MM AM or PM;
82
     * Optional, default=now
83
     *
84
     * @param  $dateTime
85
     * @return void
86
     */
87 6
    public function setDatetime($dateTime)
88
    {
89 6
        $this->dateTime = (string) $dateTime;
90 6
        $this->setMillis(strtotime($this->dateTime));
91 6
    }
92
93
    /**
94
     * Set whether nonexistent parent directories should be created
95
     * when touching new files.
96
     *
97
     * @param boolean $mkdirs whether to create parent directories.
98
     */
99 8
    public function setMkdirs($mkdirs)
100
    {
101 8
        $this->mkdirs = $mkdirs;
102 8
    }
103
104
    /**
105
     * Set whether the touch task will report every file it creates;
106
     * defaults to <code>true</code>.
107
     *
108
     * @param boolean $verbose flag.
109
     */
110
    public function setVerbose($verbose)
111
    {
112
        $this->verbose = $verbose;
113
    }
114
115
    /**
116
     * Execute the touch operation.
117
     *
118
     * @throws BuildException
119
     * @throws IOException
120
     */
121 2
    public function createMapper()
122
    {
123 2
        if ($this->mapperElement !== null) {
124
            throw new BuildException("Cannot define more than one mapper", $this->getLocation());
125
        }
126 2
        $this->mapperElement = new Mapper($this->project);
127
128 2
        return $this->mapperElement;
129
    }
130
131 66
    protected function checkConfiguration()
132
    {
133 66
        $savedMillis = $this->millis;
134
135 66
        if ($this->file === null && count($this->filesets) === 0 && count($this->filelists) === 0) {
136
            throw new BuildException("Specify at least one source - a file, a fileset or a filelist.");
137
        }
138
139 66
        if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) {
140
            throw new BuildException("Use a fileset to touch directories.");
141
        }
142
143
        try { // try to touch file
144 66
            if ($this->dateTime !== null) {
145 6
                if ($this->millis < 0) {
146
                    throw new BuildException("Date of {$this->dateTime} results in negative milliseconds value relative to epoch (January 1, 1970, 00:00:00 GMT).");
147
                }
148
            }
149
        } catch (Exception $ex) {
150
            throw new BuildException("Error touch()ing file", $ex, $this->getLocation());
151
        }
152 66
        $this->log(
153 66
            "Setting millis to " . $savedMillis . " from datetime attribute",
154 66
            ($this->millis < 0 ? Project::MSG_DEBUG : Project::MSG_VERBOSE)
155
        );
156
157 66
        $this->millis = $savedMillis;
158 66
    }
159
160
    /**
161
     * Execute the touch operation.
162
     * @throws BuildException
163
     */
164 66
    public function main()
165
    {
166 66
        $this->checkConfiguration();
167 66
        $this->_touch();
168 65
    }
169
170
    /**
171
     * Does the actual work.
172
     */
173 66
    public function _touch()
174
    {
175 66
        if ($this->file !== null) {
176 64
            if (!$this->file->exists()) {
177 57
                $this->log(
178 57
                    "Creating " . $this->file,
179 57
                    $this->verbose ? Project::MSG_INFO : Project::MSG_VERBOSE
180
                );
181
                try { // try to create file
182 57
                    $this->file->createNewFile($this->mkdirs);
183 1
                } catch (IOException  $ioe) {
184 1
                    throw new BuildException(
185 1
                        "Error creating new file " . $this->file,
186
                        $ioe,
187 1
                        $this->getLocation()
188
                    );
189
                }
190
            }
191
        }
192
193 65
        $resetMillis = false;
194 65
        if ($this->millis < 0) {
195 59
            $resetMillis = true;
196 59
            $this->millis = Phing::currentTimeMillis();
197
        }
198
199 65
        if ($this->file !== null) {
200 63
            $this->touchFile($this->file);
201
        }
202
203 65
        $project = $this->getProject();
204 65
        foreach ($this->filesets as $fs) {
205 2
            $ds = $fs->getDirectoryScanner($project);
206 2
            $fromDir = $fs->getDir($project);
207
208 2
            $srcFiles = $ds->getIncludedFiles();
209 2
            $srcDirs = $ds->getIncludedDirectories();
210
211 2
            for ($j = 0, $_j = count($srcFiles); $j < $_j; $j++) {
212 2
                foreach ($this->getMappedFileNames((string) $srcFiles[$j]) as $fileName) {
213 2
                    $this->touchFile(new PhingFile($fromDir, $fileName));
214
                }
215
            }
216
217 2
            for ($j = 0, $_j = count($srcDirs); $j < $_j; $j++) {
218
                foreach ($this->getMappedFileNames((string) $srcDirs[$j]) as $fileName) {
219
                    $this->touchFile(new PhingFile($fromDir, $fileName));
220
                }
221
            }
222
        }
223
224
        // deal with the filelists
225 65
        foreach ($this->filelists as $fl) {
226 2
            $fromDir = $fl->getDir($this->getProject());
227
228 2
            $srcFiles = $fl->getFiles($this->getProject());
229
230 2
            for ($j = 0, $_j = count($srcFiles); $j < $_j; $j++) {
231 2
                foreach ($this->getMappedFileNames((string) $srcFiles[$j]) as $fileName) {
232 2
                    $this->touchFile(new PhingFile($fromDir, $fileName));
233
                }
234
            }
235
        }
236
237 65
        if ($resetMillis) {
238 59
            $this->millis = -1;
239
        }
240 65
    }
241
242 4
    private function getMappedFileNames($file)
243
    {
244 4
        if ($this->mapperElement !== null) {
245 2
            $mapper = $this->mapperElement->getImplementation();
246 2
            $results = $mapper->main($file);
247 2
            if ($results === null) {
0 ignored issues
show
introduced by
The condition $results === null is always false.
Loading history...
248
                return '';
249
            }
250 2
            $fileNames = $results;
251
        } else {
252 2
            $fileNames = [$file];
253
        }
254
255 4
        return $fileNames;
256
    }
257
258
    /**
259
     * @param $file
260
     * @throws BuildException
261
     */
262 65
    private function touchFile(PhingFile $file)
263
    {
264 65
        if (!$file->canWrite()) {
265
            throw new BuildException("Can not change modification date of read-only file " . (string) $file);
266
        }
267 65
        $file->setLastModified($this->millis);
268 65
    }
269
}
270