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

UpToDateTask::evaluate()   D

Complexity

Conditions 23
Paths 50

Size

Total Lines 75
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 179.7641

Importance

Changes 0
Metric Value
cc 23
eloc 47
nc 50
nop 0
dl 0
loc 75
ccs 14
cts 42
cp 0.3333
crap 179.7641
rs 4.1666
c 0
b 0
f 0

How to fix   Long Method    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
namespace Phing\Tasks\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\Tasks\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
 * @package phing.tasks.system
42
 */
43
class UpToDateTask extends Task implements Condition
44
{
45
    use FileListAware;
46
    use FileSetAware;
47
48
    /**
49
     * @var string
50
     */
51
    private $property;
52
53
    /**
54
     * @var string
55
     */
56
    private $value;
57
58
    /**
59
     * @var File
60
     */
61
    private $sourceFile;
62
63
    /**
64
     * @var File
65
     */
66
    private $targetFile;
67
68
    protected $mapperElement = null;
69
70
    /**
71
     * The property to set if the target file is more up-to-date than
72
     * (each of) the source file(s).
73
     *
74
     * @param string $property the name of the property to set if Target is up-to-date.
75
     */
76 2
    public function setProperty($property)
77
    {
78 2
        $this->property = $property;
79 2
    }
80
81
    /**
82
     * Get property name
83
     *
84
     * @return string property the name of the property to set if Target is up-to-date.
85
     */
86 2
    public function getProperty()
87
    {
88 2
        return $this->property;
89
    }
90
91
    /**
92
     * The value to set the named property to if the target file is more
93
     * up-to-date than (each of) the source file(s). Defaults to 'true'.
94
     *
95
     * @param mixed $value the value to set the property to if Target is up-to-date
96
     */
97 2
    public function setValue($value)
98
    {
99 2
        $this->value = $value;
100 2
    }
101
102
    /**
103
     * Returns the value, or "true" if a specific value wasn't provided.
104
     */
105 2
    private function getValue()
106
    {
107 2
        return $this->value ?? "true";
108
    }
109
110
    /**
111
     * The file which must be more up-to-date than (each of) the source file(s)
112
     * if the property is to be set.
113
     *
114
     * @param string|File $file the file we are checking against.
115
     */
116 2
    public function setTargetFile($file)
117
    {
118 2
        if (is_string($file)) {
119 2
            $file = new File($file);
120
        }
121 2
        $this->targetFile = $file;
122 2
    }
123
124
    /**
125
     * The file that must be older than the target file
126
     * if the property is to be set.
127
     *
128
     * @param string|File $file the file we are checking against the target file.
129
     */
130 2
    public function setSrcfile($file)
131
    {
132 2
        if (is_string($file)) {
133 2
            $file = new File($file);
134
        }
135 2
        $this->sourceFile = $file;
136 2
    }
137
138
    /**
139
     * Defines the FileNameMapper to use (nested mapper element).
140
     */
141
    public function createMapper()
142
    {
143
        if ($this->mapperElement !== null) {
144
            throw new BuildException(
145
                "Cannot define more than one mapper",
146
                $this->getLocation()
147
            );
148
        }
149
        $this->mapperElement = new Mapper($this->getProject());
150
151
        return $this->mapperElement;
152
    }
153
154
    /**
155
     * Evaluate (all) target and source file(s) to
156
     * see if the target(s) is/are up-to-date.
157
     *
158
     * @throws BuildException
159
     * @return boolean
160
     */
161 2
    public function evaluate()
162
    {
163 2
        if (count($this->filesets) == 0 && count($this->filelists) == 0 && $this->sourceFile === null) {
164
            throw new BuildException(
165
                "At least one srcfile or a nested "
166
                . "<fileset> or <filelist> element must be set."
167
            );
168
        }
169
170 2
        if ((count($this->filesets) > 0 || count($this->filelists) > 0) && $this->sourceFile !== null) {
171
            throw new BuildException(
172
                "Cannot specify both the srcfile "
173
                . "attribute and a nested <fileset> "
174
                . "or <filelist> element."
175
            );
176
        }
177
178 2
        if ($this->targetFile === null && $this->mapperElement === null) {
179
            throw new BuildException(
180
                "The targetfile attribute or a nested "
181
                . "mapper element must be set."
182
            );
183
        }
184
185
        // if the target file is not there, then it can't be up-to-date
186 2
        if ($this->targetFile !== null && !$this->targetFile->exists()) {
187
            return false;
188
        }
189
190
        // if the source file isn't there, throw an exception
191 2
        if ($this->sourceFile !== null && !$this->sourceFile->exists()) {
192
            throw new BuildException(
193
                $this->sourceFile->getAbsolutePath()
194
                . " not found."
195
            );
196
        }
197
198 2
        $upToDate = true;
199 2
        for ($i = 0, $size = count($this->filesets); $i < $size && $upToDate; $i++) {
200
            $fs = $this->filesets[$i];
201
            $ds = $fs->getDirectoryScanner($this->project);
202
            $upToDate = $upToDate && $this->scanDir(
203
                $fs->getDir($this->project),
204
                $ds->getIncludedFiles()
205
            );
206
        }
207
208 2
        for ($i = 0, $size = count($this->filelists); $i < $size && $upToDate; $i++) {
209
            $fl = $this->filelists[$i];
210
            $srcFiles = $fl->getFiles($this->project);
211
            $upToDate = $upToDate && $this->scanDir(
212
                $fl->getDir($this->project),
213
                $srcFiles
214
            );
215
        }
216
217 2
        if ($this->sourceFile !== null) {
218 2
            if ($this->mapperElement === null) {
219 2
                $upToDate = $upToDate &&
220 2
                    ($this->targetFile->lastModified() >= $this->sourceFile->lastModified());
221
            } else {
222
                $sfs = new SourceFileScanner($this);
223
                $upToDate = $upToDate &&
224
                    count(
225
                        $sfs->restrict(
226
                            $this->sourceFile->getAbsolutePath(),
0 ignored issues
show
Bug introduced by
$this->sourceFile->getAbsolutePath() of type string is incompatible with the type iterable expected by parameter $files of Phing\Io\SourceFileScanner::restrict(). ( Ignorable by Annotation )

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

226
                            /** @scrutinizer ignore-type */ $this->sourceFile->getAbsolutePath(),
Loading history...
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\Tasks\System\TypedefTask or GrowlNotifyTask or Phing\Tasks\System\RecorderTask or Phing\Tasks\System\TaskdefTask or PackageAsPathTask or Phing\Tasks\System\PropertyTask or Phing\Tasks\Ext\PhkPackageTask or PathToFileSet or StopwatchTask or Phing\Tasks\Ext\HgTagTask or Phing\Tasks\System\AdhocTypedefTask or Phing\Tasks\System\AdhocTaskdefTask or Phing\Tasks\Ext\GitTagTask. ( 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\Tasks\System\SwitchTask or Phing\Tasks\System\UpToDateTask or Phing\Tasks\System\AvailableTask or Phing\Tasks\System\PropertyTask or URLEncodeTask or SortList or Phing\Tasks\System\CaseTask. ( 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\Tasks\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