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
 * Component creation and configuration
22
 *
23
 * @author Michiel Rook <mrook@php.net>
24
 *
25
 * @package phing
26
 */
27
class ComponentHelper
28
{
29
    public const COMPONENT_HELPER_REFERENCE = "phing.ComponentHelper";
30

31
    /**
32
     * @var Project
33
     */
34
    private $project;
35

36
    /**
37
     * task definitions for this project
38
     *
39
     * @var string[]
40
     */
41
    private $taskdefs = [];
42

43
    /**
44
     * type definitions for this project
45
     *
46
     * @var string[]
47
     */
48
    private $typedefs = [];
49

50
    /**
51
     * ComponentHelper constructor.
52
     *
53
     * @param Project $project
54
     */
55 1
    public function __construct(Project $project)
56
    {
57 1
        $this->project = $project;
58
    }
59

60
    /**
61
     * @param Project $project
62
     * @return ComponentHelper
63
     */
64 1
    public static function getComponentHelper(Project $project)
65
    {
66 1
        if ($project === null) {
67 0
            return null;
68
        }
69

70
        /**
71
         * @var ComponentHelper $componentHelper
72
         */
73 1
        $componentHelper = $project->getReference(self::COMPONENT_HELPER_REFERENCE);
74

75 1
        if ($componentHelper !== null) {
76 1
            return $componentHelper;
77
        }
78

79 1
        $componentHelper = new ComponentHelper($project);
80 1
        $project->addReference(self::COMPONENT_HELPER_REFERENCE, $componentHelper);
81

82 1
        return $componentHelper;
83
    }
84

85
    /**
86
     * Initializes the default tasks and data types
87
     */
88 1
    public function initDefaultDefinitions()
89
    {
90 1
        $this->initDefaultTasks();
91 1
        $this->initDefaultDataTypes();
92 1
        $this->initCustomTasks();
93 1
        $this->initCustomDataTypes();
94
    }
95

96
    /**
97
     * Adds a task definition.
98
     *
99
     * @param string $name Name of tag.
100
     * @param string $class The class path to use.
101
     * @param string $classpath The classpat to use.
102
     */
103 1
    public function addTaskDefinition($name, $class, $classpath = null)
104
    {
105 1
        if ($class === "") {
106 0
            $this->project->log("Task $name has no class defined.", Project::MSG_ERR);
107 1
        } elseif (!isset($this->taskdefs[$name])) {
108 1
            Phing::import($class, $classpath);
109 1
            $this->taskdefs[$name] = $class;
110 1
            $this->project->log("  +Task definition: $name ($class)", Project::MSG_DEBUG);
111
        } else {
112 1
            $this->project->log("Task $name ($class) already registered, skipping", Project::MSG_VERBOSE);
113
        }
114
    }
115

116
    /**
117
     * Returns the task definitions
118
     *
119
     * @return array
120
     */
121 1
    public function getTaskDefinitions()
122
    {
123 1
        return $this->taskdefs;
124
    }
125

126
    /**
127
     * Adds a data type definition.
128
     *
129
     * @param string $typeName Name of the type.
130
     * @param string $typeClass The class to use.
131
     * @param string $classpath The classpath to use.
132
     */
133 1
    public function addDataTypeDefinition($typeName, $typeClass, $classpath = null)
134
    {
135 1
        if (!isset($this->typedefs[$typeName])) {
136 1
            Phing::import($typeClass, $classpath);
137 1
            $this->typedefs[$typeName] = $typeClass;
138 1
            $this->project->log("  +User datatype: $typeName ($typeClass)", Project::MSG_DEBUG);
139
        } else {
140 1
            $this->project->log("Type $typeName ($typeClass) already registered, skipping", Project::MSG_VERBOSE);
141
        }
142
    }
143

144 1
    public static function getElementName(Project $p = null, $o = null, $brief = false)
145
    {
146
        //if ($p === null) {
147
        //    TODO Project::getProject($o)
148
        //}
149

150 1
        return $p === null
151 1
            ? self::getUnmappedElementName($o, $brief)
152 1
            : self::getComponentHelper($p)->getElementName(null, $o, $brief);
153
    }
154

155 1
    private static function getUnmappedElementName($c, $brief)
156
    {
157 1
        $clazz = new ReflectionClass($c);
158 1
        $name = $clazz->getName();
159

160 1
        if ($brief) {
161 1
            return $clazz->getShortName();
162
        }
163

164 0
        return $name;
165
    }
166

167
    /**
168
     * Returns the data type definitions
169
     *
170
     * @return array
171
     */
172 1
    public function getDataTypeDefinitions()
173
    {
174 1
        return $this->typedefs;
175
    }
176

177
    /**
178
     * Create a new task instance and return reference to it.
179
     *
180
     * @param  string $taskType Task name
181
     * @return Task           A task object
182
     * @throws BuildException
183
     */
184 1
    public function createTask($taskType)
185
    {
186
        try {
187 1
            $classname = "";
188 1
            $tasklwr = strtolower($taskType);
189 1
            foreach ($this->taskdefs as $name => $class) {
190 1
                if (strtolower($name) === $tasklwr) {
191 1
                    $classname = $class;
192 1
                    break;
193
                }
194
            }
195

196 1
            if ($classname === "") {
197 1
                return null;
198
            }
199

200 1
            $o = $this->createObject($classname);
201

202 1
            if ($o instanceof Task) {
203 1
                $task = $o;
204
            } else {
205 1
                $this->project->log("  (Using TaskAdapter for: $taskType)", Project::MSG_DEBUG);
206
                // not a real task, try adapter
207 1
                $taskA = new TaskAdapter();
208 1
                $taskA->setProxy($o);
209 1
                $task = $taskA;
210
            }
211 1
            $task->setProject($this->project);
212 1
            $task->setTaskType($taskType);
213
            // set default value, can be changed by the user
214 1
            $task->setTaskName($taskType);
215 1
            $this->project->log("  +Task: " . $taskType, Project::MSG_DEBUG);
216 0
        } catch (Exception $t) {
217 0
            throw new BuildException("Could not create task of type: " . $taskType, $t);
218
        }
219
        // everything fine return reference
220 1
        return $task;
221
    }
222

223
    /**
224
     * Creates a new condition and returns the reference to it
225
     *
226
     * @param  string $conditionType
227
     * @return Condition
228
     * @throws BuildException
229
     */
230 1
    public function createCondition($conditionType)
231
    {
232
        try {
233 1
            $classname = "";
234 1
            $tasklwr = strtolower($conditionType);
235 1
            foreach ($this->typedefs as $name => $class) {
236 1
                if (strtolower($name) === $tasklwr) {
237 1
                    $classname = $class;
238 1
                    break;
239
                }
240
            }
241

242 1
            if ($classname === "") {
243 0
                return null;
244
            }
245

246 1
            $o = $this->createObject($classname);
247

248 1
            if ($o instanceof Condition) {
249 1
                return $o;
250
            }
251

252 0
            throw new BuildException("Not actually a condition");
253 0
        } catch (Exception $e) {
254 0
            throw new BuildException("Could not create condition of type: " . $conditionType, $e);
255
        }
256
    }
257

258 1
    private function createObject(string $classname)
259
    {
260 1
        if ($classname === "") {
261 0
            return null;
262
        }
263

264 1
        $cls = Phing::import($classname);
265

266 1
        if (!class_exists($cls)) {
267 0
            throw new BuildException(
268 0
                "Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)"
269
            );
270
        }
271

272 1
        return new $cls();
273
    }
274

275
    /**
276
     * Create a datatype instance and return reference to it
277
     * See createTask() for explanation how this works
278
     *
279
     * @param  string $typeName Type name
280
     * @return object         A datatype object
281
     * @throws BuildException
282
     *                                 Exception
283
     */
284 1
    public function createDataType($typeName)
285
    {
286
        try {
287 1
            $cls = "";
288 1
            $typelwr = strtolower($typeName);
289 1
            foreach ($this->typedefs as $name => $class) {
290 1
                if (strtolower($name) === $typelwr) {
291 1
                    $cls = StringHelper::unqualify($class);
292 1
                    break;
293
                }
294
            }
295

296 1
            if ($cls === "") {
297 0
                return null;
298
            }
299

300 1
            if (!class_exists($cls)) {
301 0
                throw new BuildException(
302 0
                    "Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)"
303
                );
304
            }
305

306 1
            $type = new $cls();
307 1
            $this->project->log("  +Type: $typeName", Project::MSG_DEBUG);
308 1
            if (!($type instanceof DataType)) {
309 0
                throw new Exception("$class is not an instance of phing.types.DataType");
310
            }
311 1
            if ($type instanceof ProjectComponent) {
312 1
                $type->setProject($this->project);
313
            }
314 0
        } catch (Exception $t) {
315 0
            throw new BuildException("Could not create type: $typeName", $t);
316
        }
317
        // everything fine return reference
318 1
        return $type;
319
    }
320

321 1
    private function initDefaultTasks()
322
    {
323 1
        $taskdefs = Phing::getResourcePath("phing/tasks/defaults.properties");
324

325
        try { // try to load taskdefs
326 1
            $props = new Properties();
327 1
            $in = new PhingFile((string) $taskdefs);
328

329 1
            if ($in === null) {
330 0
                throw new BuildException("Can't load default task list");
331
            }
332 1
            $props->load($in);
333

334 1
            $enum = $props->propertyNames();
335 1
            foreach ($enum as $key) {
336 1
                $value = $props->getProperty($key);
337 1
                $this->addTaskDefinition($key, $value);
338
            }
339 0
        } catch (IOException $ioe) {
340 0
            throw new BuildException("Can't load default task list");
341
        }
342
    }
343

344 1
    private function initDefaultDataTypes()
345
    {
346 1
        $typedefs = Phing::getResourcePath("phing/types/defaults.properties");
347

348
        try { // try to load typedefs
349 1
            $props = new Properties();
350 1
            $in = new PhingFile((string) $typedefs);
351 1
            if ($in === null) {
352 0
                throw new BuildException("Can't load default datatype list");
353
            }
354 1
            $props->load($in);
355

356 1
            $enum = $props->propertyNames();
357 1
            foreach ($enum as $key) {
358 1
                $value = $props->getProperty($key);
359 1
                $this->addDataTypeDefinition($key, $value);
360
            }
361 0
        } catch (IOException $ioe) {
362 0
            throw new BuildException("Can't load default datatype list");
363
        }
364
    }
365

366 1
    private function initCustomTasks()
367
    {
368 1
        $taskdefs = Phing::getResourcePath("custom.task.properties");
369
        try { // try to load typedefs
370 1
            $props = new Properties();
371 1
            $in = new PhingFile((string) $taskdefs);
372 1
            if (!$in->exists()) {
373 0
                return;
374
            }
375 1
            $props->load($in);
376 1
            $enum = $props->propertyNames();
377 1
            foreach ($enum as $key) {
378 1
                $value = $props->getProperty($key);
379 1
                $this->addTaskDefinition($key, $value);
380
            }
381 0
        } catch (IOException $ioe) {
382 0
            throw new BuildException("Can't load custom task list");
383
        }
384
    }
385

386 1
    private function initCustomDataTypes()
387
    {
388 1
        $typedefs = Phing::getResourcePath("custom.type.properties");
389
        try { // try to load typedefs
390 1
            $props = new Properties();
391 1
            $in = new PhingFile((string) $typedefs);
392 1
            if (!$in->exists()) {
393 0
                return;
394
            }
395 1
            $props->load($in);
396 1
            $enum = $props->propertyNames();
397 1
            foreach ($enum as $key) {
398 1
                $value = $props->getProperty($key);
399 1
                $this->addDataTypeDefinition($key, $value);
400
            }
401 0
        } catch (IOException $ioe) {
402 0
            throw new BuildException("Can't load custom type list");
403
        }
404
    }
405

406 1
    public function initSubProject(ComponentHelper $helper): void
407
    {
408 1
        $dataTypes = $helper->getDataTypeDefinitions();
409 1
        foreach ($dataTypes as $name => $class) {
410 1
            $this->addDataTypeDefinition($name, $class);
411
        }
412
    }
413
}

Read our documentation on viewing source code .

Loading