Passed
Push — master ( 02e769...327609 )
by Siad
05:24
created

TouchTask::setSeconds()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
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
 * 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 $seconds = -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 82
    public function __construct()
49
    {
50 82
        parent::__construct();
51 82
        $this->fileUtils = new FileUtils();
52 82
    }
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 73
    public function setFile(PhingFile $file)
62
    {
63 73
        $this->file = $file;
64 73
    }
65
66
    /**
67
     * The new modification time of the file in milliseconds since midnight
68
     * Jan 1 1970. Negative values are not accepted nor are values less than
69
     * 1000. Note that PHP is actually based on seconds so the value passed
70
     * in will be divided by 1000.
71
     *
72
     * Optional, default=now
73
     *
74
     * @param  $millis
75
     * @return void
76
     */
77 6
    public function setMillis($millis)
78
    {
79 6
        if ($millis >= 0) {
80 4
            if ($millis >= 1000) {
81 3
                $this->seconds = (int) $millis / 1000;
82
            } else {
83 4
                throw new BuildException("Millis less than 1000 would be treated as 0");
84
            }
85
        } else {
86 2
            throw new BuildException("Millis attribute cannot be negative");
87
        }
88 3
    }
89
90
    /**
91
     * the new modification time of the file
92
     * in seconds since midnight Jan 1 1970.
93
     * Optional, default=now
94
     *
95
     * @param  $seconds
96
     * @return void
97
     */
98 9
    public function setSeconds($seconds)
99
    {
100 9
        if ($seconds >= 0) {
101 8
            $this->seconds = (int) $seconds;
102
        } else {
103 1
            throw new BuildException("Seconds attribute cannot be negative");
104
        }
105 8
    }
106
107
    /**
108
     * the new modification time of the file
109
     * in the format MM/DD/YYYY HH:MM AM or PM;
110
     * Optional, default=now
111
     *
112
     * @param  $dateTime
113
     * @return void
114
     */
115 9
    public function setDatetime($dateTime)
116
    {
117 9
        $timestmap = strtotime($dateTime);
118 9
        if (false !== $timestmap) {
119 8
            $this->dateTime = (string) $dateTime;
120 8
            $this->setSeconds($timestmap);
121
        } else {
122 1
            throw new BuildException("Date of ${dateTime} cannot be parsed correctly. It should be in a format parsable by PHP's strtotime() function." . PHP_EOL);
123
        }
124 7
    }
125
126
    /**
127
     * Set whether nonexistent parent directories should be created
128
     * when touching new files.
129
     *
130
     * @param boolean $mkdirs whether to create parent directories.
131
     */
132 8
    public function setMkdirs($mkdirs)
133
    {
134 8
        $this->mkdirs = $mkdirs;
135 8
    }
136
137
    /**
138
     * Set whether the touch task will report every file it creates;
139
     * defaults to <code>true</code>.
140
     *
141
     * @param boolean $verbose flag.
142
     */
143
    public function setVerbose($verbose)
144
    {
145
        $this->verbose = $verbose;
146
    }
147
148
    /**
149
     * Execute the touch operation.
150
     *
151
     * @throws BuildException
152
     * @throws IOException
153
     */
154 2
    public function createMapper()
155
    {
156 2
        if ($this->mapperElement !== null) {
157
            throw new BuildException("Cannot define more than one mapper", $this->getLocation());
158
        }
159 2
        $this->mapperElement = new Mapper($this->project);
160
161 2
        return $this->mapperElement;
162
    }
163
164 77
    protected function checkConfiguration()
165
    {
166 77
        $savedSeconds = $this->seconds;
167
168 77
        if ($this->file === null && count($this->filesets) === 0 && count($this->filelists) === 0) {
169 1
            throw new BuildException("Specify at least one source - a file, a fileset or a filelist.");
170
        }
171
172 76
        if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) {
173 1
            throw new BuildException("Use a fileset to touch directories.");
174
        }
175
176 75
        $this->log(
177 75
            "Setting seconds to " . $savedSeconds . " from datetime attribute",
178 75
            ($this->seconds < 0 ? Project::MSG_DEBUG : Project::MSG_VERBOSE)
179
        );
180
181 75
        $this->seconds = $savedSeconds;
182 75
    }
183
184
    /**
185
     * Execute the touch operation.
186
     * @throws BuildException
187
     */
188 77
    public function main()
189
    {
190 77
        $this->checkConfiguration();
191 75
        $this->_touch();
192 73
    }
193
194
    /**
195
     * Does the actual work.
196
     */
197 75
    public function _touch()
198
    {
199 75
        if ($this->file !== null) {
200 67
            if (!$this->file->exists()) {
201 59
                $this->log(
202 59
                    "Creating " . $this->file,
203 59
                    $this->verbose ? Project::MSG_INFO : Project::MSG_VERBOSE
204
                );
205
                try { // try to create file
206 59
                    $this->file->createNewFile($this->mkdirs);
207 1
                } catch (IOException  $ioe) {
208 1
                    throw new BuildException(
209 1
                        "Error creating new file " . $this->file,
210
                        $ioe,
211 1
                        $this->getLocation()
212
                    );
213
                }
214
            }
215
        }
216
217 74
        $resetSeconds = false;
218 74
        if ($this->seconds < 0) {
219 65
            $resetSeconds = true;
220
            // Note: this function actually returns seconds, not milliseconds (e.g. 1606505920.2657)
221 65
            $this->seconds = Phing::currentTimeMillis();
222
        }
223
224 74
        if ($this->file !== null) {
225 66
            $this->touchFile($this->file);
226
        }
227
228 73
        $project = $this->getProject();
229 73
        foreach ($this->filesets as $fs) {
230 2
            $ds = $fs->getDirectoryScanner($project);
231 2
            $fromDir = $fs->getDir($project);
232
233 2
            $srcFiles = $ds->getIncludedFiles();
234 2
            $srcDirs = $ds->getIncludedDirectories();
235
236 2
            for ($j = 0, $_j = count($srcFiles); $j < $_j; $j++) {
237 2
                foreach ($this->getMappedFileNames((string) $srcFiles[$j]) as $fileName) {
238 2
                    $this->touchFile(new PhingFile($fromDir, $fileName));
239
                }
240
            }
241
242 2
            for ($j = 0, $_j = count($srcDirs); $j < $_j; $j++) {
243
                foreach ($this->getMappedFileNames((string) $srcDirs[$j]) as $fileName) {
244
                    $this->touchFile(new PhingFile($fromDir, $fileName));
245
                }
246
            }
247
        }
248
249
        // deal with the filelists
250 73
        foreach ($this->filelists as $fl) {
251 8
            $fromDir = $fl->getDir($this->getProject());
252
253 8
            $srcFiles = $fl->getFiles($this->getProject());
254
255 8
            for ($j = 0, $_j = count($srcFiles); $j < $_j; $j++) {
256 8
                foreach ($this->getMappedFileNames((string) $srcFiles[$j]) as $fileName) {
257 8
                    $this->touchFile(new PhingFile($fromDir, $fileName));
258
                }
259
            }
260
        }
261
262 73
        if ($resetSeconds) {
263 64
            $this->seconds = -1;
264
        }
265 73
    }
266
267 10
    private function getMappedFileNames($file)
268
    {
269 10
        if ($this->mapperElement !== null) {
270 2
            $mapper = $this->mapperElement->getImplementation();
271 2
            $results = $mapper->main($file);
272 2
            if ($results === null) {
0 ignored issues
show
introduced by
The condition $results === null is always false.
Loading history...
273
                return '';
274
            }
275 2
            $fileNames = $results;
276
        } else {
277 8
            $fileNames = [$file];
278
        }
279
280 10
        return $fileNames;
281
    }
282
283
    /**
284
     * @param $file
285
     * @throws BuildException
286
     */
287 74
    private function touchFile(PhingFile $file)
288
    {
289 74
        if (!$file->canWrite()) {
290 1
            throw new BuildException("Can not change modification date of read-only file " . (string) $file);
291
        }
292 73
        $file->setLastModified($this->seconds);
293 73
    }
294
}
295