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
 * The base class for all Tasks.
22
 *
23
 * Use {@link Project#createTask} to register a new Task.
24
 *
25
 * @author    Andreas Aderhold <andi@binarycloud.com>
26
 * @copyright 2001,2002 THYRELL. All rights reserved
27
 * @see       Project#createTask()
28
 * @package   phing
29
 */
30
abstract class Task extends ProjectComponent
31
{
32

33
    /**
34
     * Owning Target object
35
     *
36
     * @var Target
37
     */
38
    protected $target;
39

40
    /**
41
     * Internal taskname (req)
42
     *
43
     * @var string
44
     */
45
    protected $taskType;
46

47
    /**
48
     * Taskname for logger
49
     *
50
     * @var string
51
     */
52
    protected $taskName;
53

54
    /**
55
     * Wrapper of the task
56
     *
57
     * @var RuntimeConfigurable
58
     */
59
    protected $wrapper;
60
    private $invalid;
61
    /**
62
     * Replacement element used if this task is invalidated.
63
     * @var UnknownElement
64
     */
65
    private $replacement;
66

67
    /**
68
     * @return RuntimeConfigurable
69
     */
70 1
    public function getWrapper()
71
    {
72 1
        return $this->wrapper;
73
    }
74

75
    /**
76
     * Provides a project level log event to the task.
77
     *
78
     * @param string $msg The message to log
79
     * @param int $level The priority of the message
80
     * @param Exception|null $t
81
     * @see   BuildEvent
82
     * @see   BuildListener
83
     */
84 1
    public function log($msg, $level = Project::MSG_INFO, Exception $t = null)
85
    {
86 1
        if ($this->getProject() !== null) {
87 1
            $this->getProject()->logObject($this, $msg, $level, $t);
88
        } else {
89 1
            parent::log($msg, $level);
90
        }
91
    }
92

93
    /**
94
     * Called by the parser to let the task initialize properly.
95
     * Should throw a BuildException if something goes wrong with the build
96
     *
97
     * This is abstract here, but may not be overloaded by subclasses.
98
     *
99
     * @throws BuildException
100
     */
101 1
    public function init()
102
    {
103
    }
104

105
    /**
106
     *  Called by the project to let the task do it's work. This method may be
107
     *  called more than once, if the task is invoked more than once. For
108
     *  example, if target1 and target2 both depend on target3, then running
109
     *  <em>phing target1 target2</em> will run all tasks in target3 twice.
110
     *
111
     *  Should throw a BuildException if someting goes wrong with the build
112
     *
113
     *  This is abstract here. Must be overloaded by real tasks.
114
     */
115
    abstract public function main();
116

117
    /**
118
     * Returns the wrapper object for runtime configuration
119
     *
120
     * @return RuntimeConfigurable The wrapper object used by this task
121
     */
122 1
    public function getRuntimeConfigurableWrapper()
123
    {
124 1
        if ($this->wrapper === null) {
125 0
            $this->wrapper = new RuntimeConfigurable($this, $this->getTaskName());
126
        }
127

128 1
        return $this->wrapper;
129
    }
130

131
    /**
132
     * Returns the name of task, used only for log messages
133
     *
134
     * @return string Name of this task
135
     */
136 1
    public function getTaskName()
137
    {
138 1
        if ($this->taskName === null) {
139
            // if no task name is set, then it's possible
140
            // this task was created from within another task.  We don't
141
            // therefore know the XML tag name for this task, so we'll just
142
            // use the class name stripped of "task" suffix.  This is only
143
            // for log messages, so we don't have to worry much about accuracy.
144 0
            return preg_replace('/task$/i', '', get_class($this));
145
        }
146

147 1
        return $this->taskName;
148
    }
149

150
    /**
151
     * Sets the name of this task for log messages
152
     *
153
     * @param string $name
154
     */
155 1
    public function setTaskName($name)
156
    {
157 1
        $this->taskName = (string) $name;
158
    }
159

160
    /**
161
     * Marks this task as invalid. Any further use of this task
162
     * will go through a replacement with the updated definition.
163
     */
164 0
    public function markInvalid()
165
    {
166 0
        $this->invalid = true;
167
    }
168

169
    /**
170
     * Perfrom this task
171
     *
172
     * @return void
173
     *
174
     * @throws BuildException
175
     * @throws Error
176
     */
177 1
    public function perform(): void
178
    {
179 1
        if ($this->invalid) {
180 0
            $this->getReplacement()->getTask()->perform();
181
        } else {
182 1
            $reason = null;
183
            try { // try executing task
184 1
                $this->project->fireTaskStarted($this);
185 1
                $this->maybeConfigure();
186 1
                DispatchUtils::main($this);
187 1
            } catch (\BuildException $ex) {
188 1
                $loc = $ex->getLocation();
189 1
                if ($loc === null || (string) $loc === '') {
190 1
                    $ex->setLocation($this->getLocation());
191
                }
192 1
                $reason = $ex;
193 1
                throw $ex;
194 1
            } catch (\Exception $ex) {
195 1
                $reason = $ex;
196 1
                $be = new \BuildException($ex);
197 1
                $be->setLocation($this->getLocation());
198 1
                throw $be;
199 0
            } catch (\Error $ex) {
200 0
                $reason = $ex;
201 0
                throw $ex;
202 1
            } finally {
203 1
                $this->project->fireTaskFinished($this, $reason);
204
            }
205
        }
206
    }
207

208
    /**
209
     *  Configure this task if it hasn't been done already.
210
     */
211 1
    public function maybeConfigure()
212
    {
213 1
        if ($this->invalid) {
214 0
            $this->getReplacement();
215 1
        } elseif ($this->wrapper !== null) {
216 1
            $this->wrapper->maybeConfigure($this->project);
217
        }
218
    }
219

220
    /**
221
     * Force the task to be reconfigured from its RuntimeConfigurable.
222
     */
223 0
    public function reconfigure()
224
    {
225 0
        if ($this->wrapper !== null) {
226 0
            $this->wrapper->reconfigure($this->getProject());
227
        }
228
    }
229

230 0
    private function getReplacement(): \UnknownElement
231
    {
232 0
        if ($this->replacement === null) {
233 0
            $this->replacement = new UnknownElement($this->taskType);
234 0
            $this->replacement->setProject($this->getProject());
235 0
            $this->replacement->setTaskType($this->taskType);
236 0
            $this->replacement->setTaskName($this->taskName);
237 0
            $this->replacement->setLocation($this->getLocation());
238 0
            $this->replacement->setOwningTarget($this->target);
239 0
            $this->replacement->setRuntimeConfigurableWrapper($this->wrapper);
240 0
            $this->wrapper->setProxy($this->replacement);
241 0
            $this->replaceChildren($this->wrapper, $this->replacement);
242 0
            $this->target->replaceChild($this, $this->replacement);
243 0
            $this->replacement->maybeConfigure();
244
        }
245 0
        return $this->replacement;
246
    }
247

248
    /**
249
     * Sets the owning target this task belongs to.
250
     *
251
     * @param Target Reference to owning target
252
     */
253 1
    public function setOwningTarget(Target $target): void
254
    {
255 1
        $this->target = $target;
256
    }
257

258
    /**
259
     *  Sets the wrapper object this task should use for runtime
260
     *  configurable elements.
261
     *
262
     * @param RuntimeConfigurable $wrapper The wrapper object this task should use
263
     */
264 1
    public function setRuntimeConfigurableWrapper(RuntimeConfigurable $wrapper): void
265
    {
266 1
        $this->wrapper = $wrapper;
267
    }
268

269
    /**
270
     * Recursively adds an UnknownElement instance for each child
271
     * element of replacement.
272
     * @param RuntimeConfigurable $wrapper
273
     * @param UnknownElement $parentElement
274
     */
275 0
    private function replaceChildren(RuntimeConfigurable $wrapper, UnknownElement $parentElement): void
276
    {
277 0
        foreach ($wrapper->getChildren() as $childWrapper) {
278 0
            $childElement = new UnknownElement($childWrapper->getElementTag());
279 0
            $parentElement->addChild($childElement);
280 0
            $childElement->setProject($this->getProject());
281 0
            $childElement->setRuntimeConfigurableWrapper($childWrapper);
282 0
            $childWrapper->setProxy($childElement);
283 0
            $this->replaceChildren($childWrapper, $childElement);
284
        }
285
    }
286

287
    /**
288
     * Bind a task to another; use this when configuring a newly created
289
     * task to do work on behalf of another.
290
     * Project, OwningTarget, TaskName, Location and Description are all copied
291
     *
292
     * Important: this method does not call {@link Task#init()}.
293
     * If you are creating a task to delegate work to, call {@link Task#init()}
294
     * to initialize it.
295
     *
296
     * @param Task $owner owning target
297
     */
298 1
    public function bindToOwner(Task $owner): void
299
    {
300 1
        $this->setProject($owner->getProject());
301 1
        $this->setOwningTarget($owner->getOwningTarget());
302 1
        $this->setTaskName($owner->getTaskName());
303 1
        $this->setDescription($owner->getDescription());
304 1
        $this->setLocation($owner->getLocation());
305 1
        $this->setTaskType($owner->getTaskType());
306
    }
307

308
    /**
309
     * Returns the owning target of this task.
310
     *
311
     * @return Target The target object that owns this task
312
     */
313 1
    public function getOwningTarget()
314
    {
315 1
        return $this->target;
316
    }
317

318
    /**
319
     * Returns the name of the task under which it was invoked,
320
     * usually the XML tagname
321
     *
322
     * @return string The type of this task (XML Tag)
323
     */
324 1
    public function getTaskType()
325
    {
326 1
        return $this->taskType;
327
    }
328

329
    /**
330
     * Sets the type of the task. Usually this is the name of the XML tag
331
     *
332
     * @param string $name The type of this task (XML Tag)
333
     */
334 1
    public function setTaskType($name)
335
    {
336 1
        $this->taskType = (string) $name;
337
    }
338

339
    /**
340
     * Returns a name
341
     *
342
     * @param string $slotName
343
     * @return \RegisterSlot
344
     */
345 1
    protected function getRegisterSlot($slotName)
346
    {
347 1
        return Register::getSlot('task.' . $this->getTaskName() . '.' . $slotName);
348
    }
349

350
    /**
351
     * Has this task been marked invalid?
352
     *
353
     * @return bool true if this task is no longer valid. A new task should be
354
     * configured in this case.
355
     */
356 0
    protected function isInvalid()
357
    {
358 0
        return $this->invalid;
359
    }
360
}

Read our documentation on viewing source code .

Loading