Passed
Push — main ( 4889b2...808ce0 )
by Michiel
07:43
created

WaitForTask::convertUnit()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 9.2312

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 27
ccs 9
cts 14
cp 0.6429
rs 8.8333
c 0
b 0
f 0
cc 7
nc 7
nop 1
crap 9.2312
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\Project;
24
use Phing\Task\System\Condition\ConditionBase;
25
use Phing\Task\System\Condition\ConditionEnumeration;
26
27
/**
28
 *  Based on Apache Ant Wait For:
29
 *
30
 *  Licensed to the Apache Software Foundation (ASF) under one or more
31
 *  contributor license agreements.  See the NOTICE file distributed with
32
 *  this work for additional information regarding copyright ownership.
33
 *  The ASF licenses this file to You under the Apache License, Version 2.0
34
 *  (the "License"); you may not use this file except in compliance with
35
 *  the License.  You may obtain a copy of the License at
36
 *
37
 *      http://www.apache.org/licenses/LICENSE-2.0
38
 *
39
 *  Unless required by applicable law or agreed to in writing, software
40
 *  distributed under the License is distributed on an "AS IS" BASIS,
41
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42
 *  See the License for the specific language governing permissions and
43
 *  limitations under the License.
44
 *
45
 * @author  Michiel Rook <[email protected]>
46
 */
47
class WaitForTask extends ConditionBase
48
{
49
    public const ONE_MILLISECOND = 1;
50
    public const ONE_SECOND = 1000;
51
    public const ONE_MINUTE = 60000;
52
    public const ONE_HOUR = 3600000;
53
    public const ONE_DAY = 86400000;
54
    public const ONE_WEEK = 604800000;
55
56
    public const DEFAULT_MAX_WAIT_MILLIS = 180000;
57
    public const DEFAULT_CHECK_MILLIS = 500;
58
59
    protected $maxWait = self::DEFAULT_MAX_WAIT_MILLIS;
60
    protected $maxWaitMultiplier = self::ONE_MILLISECOND;
61
62
    protected $checkEvery = self::DEFAULT_CHECK_MILLIS;
63
    protected $checkEveryMultiplier = self::ONE_MILLISECOND;
64
65
    protected $timeoutProperty = null;
66
67 5
    public function __construct($taskName = 'waitfor')
68
    {
69 5
        parent::__construct($taskName);
70 5
    }
71
72
    /**
73
     * Set the maximum length of time to wait.
74
     *
75
     * @param int $maxWait
76
     */
77 5
    public function setMaxWait($maxWait)
78
    {
79 5
        $this->maxWait = (int) $maxWait;
80 5
    }
81
82
    /**
83
     * Set the max wait time unit
84
     *
85
     * @param string $maxWaitUnit
86
     */
87 5
    public function setMaxWaitUnit($maxWaitUnit)
88
    {
89 5
        $this->maxWaitMultiplier = $this->convertUnit($maxWaitUnit);
90 5
    }
91
92
    /**
93
     * Convert the unit to a multipler.
94
     *
95
     * @param  string $unit
96
     * @throws BuildException
97
     * @return int
98
     */
99 5
    protected function convertUnit($unit)
100
    {
101 5
        if ($unit === 'week') {
102
            return self::ONE_WEEK;
103
        }
104
105 5
        if ($unit === 'day') {
106
            return self::ONE_DAY;
107
        }
108
109 5
        if ($unit === 'hour') {
110
            return self::ONE_HOUR;
111
        }
112
113 5
        if ($unit === 'minute') {
114
            return self::ONE_MINUTE;
115
        }
116
117 5
        if ($unit === 'second') {
118 4
            return self::ONE_SECOND;
119
        }
120
121 1
        if ($unit === 'millisecond') {
122 1
            return self::ONE_MILLISECOND;
123
        }
124
125
        throw new BuildException("Illegal unit '$unit'");
126
    }
127
128
    /**
129
     * Set the time between each check
130
     *
131
     * @param int $checkEvery
132
     */
133
    public function setCheckEvery($checkEvery)
134
    {
135
        $this->checkEvery = (int) $checkEvery;
136
    }
137
138
    /**
139
     * Set the check every time unit
140
     *
141
     * @param  string $checkEveryUnit
142
     * @return void
143
     */
144
    public function setCheckEveryUnit($checkEveryUnit)
145
    {
146
        $this->checkEveryMultiplier = $this->convertUnit($checkEveryUnit);
147
    }
148
149
    /**
150
     * Name of the property to set after a timeout.
151
     *
152
     * @param  string $timeoutProperty
153
     * @return void
154
     */
155 3
    public function setTimeoutProperty($timeoutProperty)
156
    {
157 3
        $this->timeoutProperty = $timeoutProperty;
158 3
    }
159
160
    /**
161
     * Check repeatedly for the specified conditions until they become
162
     * true or the timeout expires.
163
     *
164
     * @throws BuildException
165
     */
166 5
    public function main()
167
    {
168 5
        if ($this->countConditions() > 1) {
169
            throw new BuildException("You must not nest more than one condition into <waitfor>");
170
        }
171
172 5
        if ($this->countConditions() < 1) {
173
            throw new BuildException("You must nest a condition into <waitfor>");
174
        }
175
176
        /**
177
         * @var ConditionEnumeration
178
         */
179 5
        $cs = $this->getIterator();
180 5
        $condition = $cs->current();
181
182 5
        $maxWaitMillis = $this->maxWait * $this->maxWaitMultiplier;
183 5
        $checkEveryMillis = $this->checkEvery * $this->checkEveryMultiplier;
184
185 5
        $start = microtime(true) * 1000;
186 5
        $end = $start + $maxWaitMillis;
187
188 5
        while (microtime(true) * 1000 < $end) {
189 5
            if ($condition->evaluate()) {
190 2
                $this->processSuccess();
191 2
                return;
192
            }
193
194 3
            usleep($checkEveryMillis * 1000);
195
        }
196
197 3
        $this->processTimeout();
198 2
    }
199
200 2
    protected function processSuccess()
201
    {
202 2
        $this->log($this->getTaskName() . ": condition was met", Project::MSG_VERBOSE);
203 2
    }
204
205 3
    protected function processTimeout()
206
    {
207 3
        $this->log($this->getTaskName() . ": timeout", Project::MSG_VERBOSE);
208
209 3
        if ($this->timeoutProperty != null) {
210 3
            $this->project->setNewProperty($this->timeoutProperty, "true");
211
        }
212 3
    }
213
}
214