Passed
Push — master ( f1e2bc...c4cbbf )
by Michiel
05:24
created

UpToDateTask::setValue()   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
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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\Task\System;
21
22
use Phing\Exception\BuildException;
23
use Phing\Io\File;
24
use Phing\Io\SourceFileScanner;
25
use Phing\Mapper\MergeMapper;
26
use Phing\Project;
27
use Phing\Task;
28
use Phing\Task\System\Condition\Condition;
29
use Phing\Type\Element\FileListAware;
30
use Phing\Type\Element\FileSetAware;
31
use Phing\Type\Mapper;
32
33
/**
34
 * Sets the given property if the specified target has a timestamp
35
 * greater than all of the source files.
36
 *
37
 * @author  Hans Lellelid <[email protected]> (Phing)
38
 * @author  William Ferguson <[email protected]> (Ant)
39
 * @author  Hiroaki Nakamura <[email protected]> (Ant)
40
 * @author  Stefan Bodewig <[email protected]> (Ant)
41
 */
42
class UpToDateTask extends Task implements Condition
43
{
44
    use FileListAware;
45
    use FileSetAware;
46
47
    /**
48
     * @var string
49
     */
50
    private $property;
51
52
    /**
53
     * @var string
54
     */
55
    private $value;
56
57
    /**
58
     * @var File
59
     */
60
    private $sourceFile;
61
62
    /**
63
     * @var File
64
     */
65
    private $targetFile;
66
67
    protected $mapperElement = null;
68
69
    /**
70
     * The property to set if the target file is more up-to-date than
71
     * (each of) the source file(s).
72
     *
73
     * @param string $property the name of the property to set if Target is up-to-date.
74
     */
75 2
    public function setProperty($property)
76
    {
77 2
        $this->property = $property;
78 2
    }
79
80
    /**
81
     * Get property name
82
     *
83
     * @return string property the name of the property to set if Target is up-to-date.
84
     */
85 2
    public function getProperty()
86
    {
87 2
        return $this->property;
88
    }
89
90
    /**
91
     * The value to set the named property to if the target file is more
92
     * up-to-date than (each of) the source file(s). Defaults to 'true'.
93
     *
94
     * @param mixed $value the value to set the property to if Target is up-to-date
95
     */
96 2
    public function setValue($value)
97
    {
98 2
        $this->value = $value;
99 2
    }
100
101
    /**
102
     * Returns the value, or "true" if a specific value wasn't provided.
103
     */
104 2
    private function getValue()
105
    {
106 2
        return $this->value ?? "true";
107
    }
108
109
    /**
110
     * The file which must be more up-to-date than (each of) the source file(s)
111
     * if the property is to be set.
112
     *
113
     * @param string|File $file the file we are checking against.
114
     */
115 2
    public function setTargetFile($file)
116
    {
117 2
        if (is_string($file)) {
118 2
            $file = new File($file);
119
        }
120 2
        $this->targetFile = $file;
121 2
    }
122
123
    /**
124
     * The file that must be older than the target file
125
     * if the property is to be set.
126
     *
127
     * @param string|File $file the file we are checking against the target file.
128
     */
129 2
    public function setSrcfile($file)
130
    {
131 2
        if (is_string($file)) {
132 2
            $file = new File($file);
133
        }
134 2
        $this->sourceFile = $file;
135 2
    }
136
137
    /**
138
     * Defines the FileNameMapper to use (nested mapper element).
139
     */
140
    public function createMapper()
141
    {
142
        if ($this->mapperElement !== null) {
143
            throw new BuildException(
144
                "Cannot define more than one mapper",
145
                $this->getLocation()
146
            );
147
        }
148
        $this->mapperElement = new Mapper($this->getProject());
149
150
        return $this->mapperElement;
151
    }
152
153
    /**
154
     * Evaluate (all) target and source file(s) to
155
     * see if the target(s) is/are up-to-date.
156
     *
157
     * @throws BuildException
158
     * @return boolean
159
     */
160 2
    public function evaluate()
161
    {
162 2
        if (count($this->filesets) == 0 && count($this->filelists) == 0 && $this->sourceFile === null) {
163
            throw new BuildException(
164
                "At least one srcfile or a nested "
165
                . "<fileset> or <filelist> element must be set."
166
            );
167
        }
168
169 2
        if ((count($this->filesets) > 0 || count($this->filelists) > 0) && $this->sourceFile !== null) {
170
            throw new BuildException(
171
                "Cannot specify both the srcfile "
172
                . "attribute and a nested <fileset> "
173
                . "or <filelist> element."
174
            );
175
        }
176
177 2
        if ($this->targetFile === null && $this->mapperElement === null) {
178
            throw new BuildException(
179
                "The targetfile attribute or a nested "
180
                . "mapper element must be set."
181
            );
182
        }
183
184
        // if the target file is not there, then it can't be up-to-date
185 2
        if ($this->targetFile !== null && !$this->targetFile->exists()) {
186
            return false;
187
        }
188
189
        // if the source file isn't there, throw an exception
190 2
        if ($this->sourceFile !== null && !$this->sourceFile->exists()) {
191
            throw new BuildException(
192
                $this->sourceFile->getAbsolutePath()
193
                . " not found."
194
            );
195
        }
196
197 2
        $upToDate = true;
198 2
        for ($i = 0, $size = count($this->filesets); $i < $size && $upToDate; $i++) {
199
            $fs = $this->filesets[$i];
200
            $ds = $fs->getDirectoryScanner($this->project);
201
            $upToDate = $upToDate && $this->scanDir(
202
                $fs->getDir($this->project),
203
                $ds->getIncludedFiles()
204
            );
205
        }
206
207 2
        for ($i = 0, $size = count($this->filelists); $i < $size && $upToDate; $i++) {
208
            $fl = $this->filelists[$i];
209
            $srcFiles = $fl->getFiles($this->project);
210
            $upToDate = $upToDate && $this->scanDir(
211
                $fl->getDir($this->project),
212
                $srcFiles
213
            );
214
        }
215
216 2
        if ($this->sourceFile !== null) {
217 2
            if ($this->mapperElement === null) {
218 2
                $upToDate = $upToDate &&
219 2
                    ($this->targetFile->lastModified() >= $this->sourceFile->lastModified());
220
            } else {
221
                $sfs = new SourceFileScanner($this);
222
                $files = [$this->sourceFile->getAbsolutePath()];
223
                $upToDate = $upToDate &&
224
                    count(
225
                        $sfs->restrict(
226
                            $files,
227
                            null,
228
                            null,
229
                            $this->mapperElement->getImplementation()
230
                        )
231
                    ) === 0;
232
            }
233
        }
234
235 2
        return $upToDate;
236
    }
237
238
239
    /**
240
     * Sets property to true if target file(s) have a more recent timestamp
241
     * than (each of) the corresponding source file(s).
242
     *
243
     * @throws BuildException
244
     */
245 2
    public function main()
246
    {
247 2
        if ($this->property === null) {
248
            throw new BuildException(
249
                "property attribute is required.",
250
                $this->getLocation()
251
            );
252
        }
253 2
        $upToDate = $this->evaluate();
254 2
        if ($upToDate) {
255 2
            $property = $this->project->createTask('property');
256 2
            $property->setName($this->getProperty());
0 ignored issues
show
Bug introduced by
The method setName() does not exist on Phing\Task. It seems like you code against a sub-type of Phing\Task such as Phing\Task\System\RecorderTask or Phing\Task\System\TaskdefTask or Phing\Task\Ext\PhkPackageTask or GrowlNotifyTask or Phing\Task\System\PropertyTask or PackageAsPathTask or PathToFileSet or Phing\Task\System\TypedefTask or Phing\Task\System\AdhocTypedefTask or Phing\Task\System\AdhocTaskdefTask or Phing\Task\Ext\GitTagTask or StopwatchTask or Phing\Task\Ext\HgTagTask. ( Ignorable by Annotation )

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

256
            $property->/** @scrutinizer ignore-call */ 
257
                       setName($this->getProperty());
Loading history...
257 2
            $property->setValue($this->getValue());
0 ignored issues
show
Bug introduced by
The method setValue() does not exist on Phing\Task. It seems like you code against a sub-type of Phing\Task such as Phing\Task\System\UpToDateTask or Phing\Task\System\AvailableTask or Phing\Task\System\SwitchTask or Phing\Task\System\PropertyTask or Phing\Task\System\CaseTask or URLEncodeTask or SortList. ( Ignorable by Annotation )

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

257
            $property->/** @scrutinizer ignore-call */ 
258
                       setValue($this->getValue());
Loading history...
258 2
            $property->setOverride(true);
0 ignored issues
show
Bug introduced by
The method setOverride() does not exist on Phing\Task. It seems like you code against a sub-type of Phing\Task such as AbstractPropertySetterTask or Phing\Task\System\PropertyTask. ( Ignorable by Annotation )

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

258
            $property->/** @scrutinizer ignore-call */ 
259
                       setOverride(true);
Loading history...
259 2
            $property->main(); // execute
260
261 2
            if ($this->mapperElement === null) {
262 2
                $this->log(
263 2
                    "File \"" . $this->targetFile->getAbsolutePath()
264 2
                    . "\" is up-to-date.",
265 2
                    Project::MSG_VERBOSE
266
                );
267
            } else {
268
                $this->log(
269
                    "All target files are up-to-date.",
270
                    Project::MSG_VERBOSE
271
                );
272
            }
273
        }
274 2
    }
275
276
    /**
277
     * @param File $srcDir
278
     * @param $files
279
     * @return bool
280
     */
281
    protected function scanDir(File $srcDir, $files)
282
    {
283
        $sfs = new SourceFileScanner($this);
284
        $mapper = null;
285
        $dir = $srcDir;
286
        if ($this->mapperElement === null) {
287
            $mm = new MergeMapper();
288
            $mm->setTo($this->targetFile->getAbsolutePath());
289
            $mapper = $mm;
290
            $dir = null;
291
        } else {
292
            $mapper = $this->mapperElement->getImplementation();
293
        }
294
295
        return (count($sfs->restrict($files, $srcDir, $dir, $mapper)) === 0);
296
    }
297
}
298