Passed
Push — master ( e5c614...6595be )
by Siad
13:10
created

TargetHandler   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Test Coverage

Coverage 83.04%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 116
dl 0
loc 229
ccs 93
cts 112
cp 0.8304
rs 9.52
c 3
b 0
f 0
wmc 36

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
F init() 0 136 30
A startElement() 0 4 1
A finished() 0 7 4
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 target handler class.
22
 *
23
 * This class handles the occurrence of a <target> tag and it's possible
24
 * nested tags (datatypes and tasks).
25
 *
26
 * @author    Andreas Aderhold <[email protected]>
27
 * @copyright 2001,2002 THYRELL. All rights reserved
28
 * @package   phing.parser
29
 */
30
class TargetHandler extends AbstractHandler
31
{
32
33
    /**
34
     * Reference to the target object that represents the currently parsed
35
     * target.
36
     *
37
     * @var Target the target instance
38
     */
39
    private $target;
40
41
    /**
42
     * The phing project configurator object
43
     *
44
     * @var ProjectConfigurator
45
     */
46
    private $configurator;
47
48
    /**
49
     * @var PhingXMLContext
50
     */
51
    private $context;
52
53
    /**
54
     * Constructs a new TargetHandler
55
     *
56
     * @param    AbstractSAXParser $parser
57
     * @param    AbstractHandler $parentHandler
58
     * @param    ProjectConfigurator $configurator
59
     * @param    PhingXMLContext $context
60
     * @internal param the $object ExpatParser object
61
     * @internal param the $object parent handler that invoked this handler
62
     * @internal param the $object ProjectConfigurator object
63
     */
64 792
    public function __construct(
65
        AbstractSAXParser $parser,
66
        AbstractHandler $parentHandler,
67
        ProjectConfigurator $configurator,
68
        PhingXMLContext $context
69
    ) {
70 792
        parent::__construct($parser, $parentHandler);
71 792
        $this->configurator = $configurator;
72 792
        $this->context = $context;
73 792
    }
74
75
    /**
76
     * Executes initialization actions required to setup the data structures
77
     * related to the tag.
78
     * <p>
79
     * This includes:
80
     * <ul>
81
     * <li>creation of the target object</li>
82
     * <li>calling the setters for attributes</li>
83
     * <li>adding the target to the project</li>
84
     * <li>adding a reference to the target (if id attribute is given)</li>
85
     * </ul>
86
     *
87
     * @param    $tag
88
     * @param    $attrs
89
     * @throws   BuildException
90
     * @throws   ExpatParseException
91
     * @internal param the $string tag that comes in
92
     * @internal param attributes $array the tag carries
93
     */
94 792
    public function init($tag, $attrs)
95
    {
96 792
        $name = null;
97 792
        $depends = "";
98 792
        $extensionPoint = null;//'fail';
99 792
        $extensionPointMissing = null;
100 792
        $ifCond = null;
101 792
        $unlessCond = null;
102 792
        $id = null;
103 792
        $description = null;
104 792
        $isHidden = false;
105 792
        $logskipped = false;
106
107 792
        foreach ($attrs as $key => $value) {
108 792
            switch ($key) {
109 792
                case "name":
110 792
                    $name = (string) $value;
111 792
                    break;
112 418
                case "depends":
113 245
                    $depends = (string) $value;
114 245
                    break;
115 207
                case "if":
116 2
                    $ifCond = (string) $value;
117 2
                    break;
118 207
                case "unless":
119 7
                    $unlessCond = (string) $value;
120 7
                    break;
121 200
                case "id":
122
                    $id = (string) $value;
123
                    break;
124 200
                case "hidden":
125
                    $isHidden = ($value === 'true' || $value === '1');
126
                    break;
127 200
                case "description":
128 192
                    $description = (string) $value;
129 192
                    break;
130 8
                case "logskipped":
131
                    $logskipped = $value;
132
                    break;
133 8
                case "extensionof":
134 7
                    $extensionPoint = $value;
135 7
                    break;
136 3
                case "onmissingextensionpoint":
137 3
                    if (!in_array($value, ['fail', 'warn', 'ignore'], true)) {
138
                        throw new BuildException('Invalid onMissingExtensionPoint ' . $value);
139
                    }
140 3
                    $extensionPointMissing = $value;
141 3
                    break;
142
                default:
143
                    throw new ExpatParseException("Unexpected attribute '$key'", $this->parser->getLocation());
0 ignored issues
show
Bug introduced by
The method getLocation() does not exist on AbstractSAXParser. Since it exists in all sub-types, consider adding an abstract or default implementation to AbstractSAXParser. ( Ignorable by Annotation )

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

143
                    throw new ExpatParseException("Unexpected attribute '$key'", $this->parser->/** @scrutinizer ignore-call */ getLocation());
Loading history...
144
            }
145
        }
146
147 792
        if ($name === null) {
148
            throw new ExpatParseException(
149
                "target element appears without a name attribute",
150
                $this->parser->getLocation()
151
            );
152
        }
153
154
        // shorthand
155 792
        $project = $this->configurator->project;
156
157
        // check to see if this target is a dup within the same file
158 792
        if (isset($this->context->getCurrentTargets()[$name])) {
159
            throw new BuildException(
160
                "Duplicate target: $name",
161
                $this->parser->getLocation()
162
            );
163
        }
164
165 792
        $this->target = $tag === 'target' ? new Target() : new ExtensionPoint();
166 792
        $this->target->setProject($project);
167 792
        $this->target->setLocation($this->parser->getLocation());
168 792
        $this->target->setHidden($isHidden);
169 792
        $this->target->setIf($ifCond);
170 792
        $this->target->setUnless($unlessCond);
171 792
        $this->target->setDescription($description);
172 792
        $this->target->setLogSkipped(StringHelper::booleanValue($logskipped));
173
        // take care of dependencies
174 792
        if ($depends !== '') {
175 245
            $this->target->setDepends($depends);
176
        }
177
178
        // check to see if target with same name is already defined
179 792
        $projectTargets = $project->getTargets();
180 792
        if (isset($projectTargets[$name])) {
181
            if (
182 92
                $this->configurator->isIgnoringProjectTag()
183 92
                && $this->configurator->getCurrentProjectName() != null
184 92
                && strlen($this->configurator->getCurrentProjectName()) != 0
185
            ) {
186
                // In an impored file (and not completely
187
                // ignoring the project tag)
188 92
                $newName = $this->configurator->getCurrentProjectName() . "." . $name;
189 92
                $project->log(
190
                    "Already defined in main or a previous import, " .
191 92
                    "define {$name} as {$newName}",
192 92
                    Project::MSG_VERBOSE
193
                );
194 92
                $name = $newName;
195
            } else {
196
                $project->log(
197
                    "Already defined in main or a previous import, " .
198
                    "ignore {$name}",
199
                    Project::MSG_VERBOSE
200
                );
201
                $name = null;
202
            }
203
        }
204
205 792
        if ($name !== null) {
206 792
            $this->target->setName($name);
207 792
            $project->addOrReplaceTarget($name, $this->target);
208 792
            if ($id !== null && $id !== "") {
209
                $project->addReference($id, $this->target);
210
            }
211
        }
212
213 792
        if ($extensionPointMissing !== null && $extensionPoint === null) {
214 1
            throw new BuildException(
215
                "onMissingExtensionPoint attribute cannot " .
216 1
                "be specified unless extensionOf is specified",
217 1
                $this->target->getLocation()
218
            );
219
        }
220 792
        if ($extensionPoint !== null) {
221 7
            foreach (Target::parseDepends($extensionPoint, $name, 'extensionof') as $extPointName) {
222 7
                if ($extensionPointMissing === null) {
223 5
                    $extensionPointMissing = 'fail';
224
                }
225 7
                $this->context->addExtensionPoint([
226 7
                    $extPointName,
227 7
                    $this->target->getName(),
228 7
                    $extensionPointMissing,
229
                    null
230
                ]);
231
            }
232
        }
233 792
    }
234
235
    /**
236
     * Checks for nested tags within the current one. Creates and calls
237
     * handlers respectively.
238
     *
239
     * @param string $name the tag that comes in
240
     * @param array $attrs attributes the tag carries
241
     */
242 782
    public function startElement($name, $attrs)
243
    {
244 782
        $tmp = new ElementHandler($this->parser, $this, $this->configurator, null, null, $this->target);
245 782
        $tmp->init($name, $attrs);
246 782
    }
247
248
    /**
249
     * Checks if this target has dependencies and/or nested tasks.
250
     * If the target has neither, show a warning.
251
     */
252 792
    protected function finished()
253
    {
254 792
        if (!$this->target instanceof ExtensionPoint && !count($this->target->getDependencies()) && !count($this->target->getTasks())) {
255 143
            $this->configurator->project->log(
256 143
                "Warning: target '" . $this->target->getName() .
257 143
                "' has no tasks or dependencies",
258 143
                Project::MSG_WARN
259
            );
260
        }
261 792
    }
262
}
263