Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 * $Id: ProjectConfigurator.php 147 2007-02-06 20:32:22Z hans $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information please see
19
 * <http://phing.info>.
20
 */
21
 
22
include_once 'phing/system/io/BufferedReader.php';
23
include_once 'phing/system/io/FileReader.php';
24
include_once 'phing/BuildException.php';
25
include_once 'phing/system/lang/FileNotFoundException.php';
26
include_once 'phing/system/io/PhingFile.php';
27
 
28
/**
29
 * The datatype handler class.
30
 *
31
 * This class handles the occurance of registered datatype tags like
32
 * FileSet
33
 *
34
 * @author      Andreas Aderhold <andi@binarycloud.com>
35
 * @copyright � 2001,2002 THYRELL. All rights reserved
36
 * @version   $Revision: 1.17 $ $Date: 2007-02-06 21:32:22 +0100 (Tue, 06 Feb 2007) $
37
 * @access    public
38
 * @package   phing.parser
39
 */
40
class ProjectConfigurator {
41
 
42
    public $project;
43
    public $locator;
44
 
45
    public $buildFile;
46
    public $buildFileParent;
47
 
48
    /**
49
     * Static call to ProjectConfigurator. Use this to configure a
50
     * project. Do not use the new operator.
51
     *
52
     * @param  object  the Project instance this configurator should use
53
     * @param  object  the buildfile object the parser should use
54
     * @access public
55
     */
56
    public static function configureProject(Project $project, PhingFile $buildFile) {
57
        $pc = new ProjectConfigurator($project, $buildFile);
58
        $pc->parse();
59
    }
60
 
61
    /**
62
     * Constructs a new ProjectConfigurator object
63
     * This constructor is private. Use a static call to
64
     * <code>configureProject</code> to configure a project.
65
     *
66
     * @param  object  the Project instance this configurator should use
67
     * @param  object  the buildfile object the parser should use
68
     * @access private
69
     */
70
    function __construct(Project $project, PhingFile $buildFile) {
71
        $this->project = $project;
72
        $this->buildFile = new PhingFile($buildFile->getAbsolutePath());
73
        $this->buildFileParent = new PhingFile($this->buildFile->getParent());
74
    }
75
 
76
    /**
77
     * Creates the ExpatParser, sets root handler and kick off parsing
78
     * process.
79
     *
80
     * @throws BuildException if there is any kind of execption during
81
     *         the parsing process
82
     * @access private
83
     */
84
    protected function parse() {
85
        try {
86
            $reader = new BufferedReader(new FileReader($this->buildFile));
87
            $parser = new ExpatParser($reader);
88
            $parser->parserSetOption(XML_OPTION_CASE_FOLDING,0);
89
            $parser->setHandler(new RootHandler($parser, $this));
90
            $this->project->log("parsing buildfile ".$this->buildFile->getName(), Project::MSG_VERBOSE);
91
            $parser->parse();
92
            $reader->close();
93
        } catch (Exception $exc) {
94
            throw new BuildException("Error reading project file", $exc);
95
        }
96
    }
97
 
98
    /**
99
     * Configures an element and resolves eventually given properties.
100
     *
101
     * @param  object  the element to configure
102
     * @param  array   the element's attributes
103
     * @param  object  the project this element belongs to
104
     * @throws Exception if arguments are not valid
105
     * @throws BuildException if attributes can not be configured
106
     * @access public
107
     */
108
    public static function configure($target, $attrs, Project $project) {
109
 
110
        if ($target instanceof TaskAdapter) {
111
            $target = $target->getProxy();
112
        }
113
 
114
		// if the target is an UnknownElement, this means that the tag had not been registered
115
		// when the enclosing element (task, target, etc.) was configured.  It is possible, however,
116
		// that the tag was registered (e.g. using <taskdef>) after the original configuration.
117
		// ... so, try to load it again:
118
		if ($target instanceof UnknownElement) {
119
			$tryTarget = $project->createTask($target->getTaskType());
120
			if ($tryTarget) {
121
				$target = $tryTarget;
122
			}
123
		}
124
 
125
        $bean = get_class($target);
126
        $ih = IntrospectionHelper::getHelper($bean);
127
 
128
        foreach ($attrs as $key => $value) {
129
            if ($key == 'id') {
130
                continue;
131
                // throw new BuildException("Id must be set Extermnally");
132
            }
133
            $value = self::replaceProperties($project, $value, $project->getProperties());
134
            try { // try to set the attribute
135
                $ih->setAttribute($project, $target, strtolower($key), $value);
136
            } catch (BuildException $be) {
137
                // id attribute must be set externally
138
                if ($key !== "id") {
139
                    throw $be;
140
                }
141
            }
142
        }
143
    }
144
 
145
    /**
146
     * Configures the #CDATA of an element.
147
     *
148
     * @param  object  the project this element belongs to
149
     * @param  object  the element to configure
150
     * @param  string  the element's #CDATA
151
     * @access public
152
     */
153
    public static function addText($project, $target, $text = null) {
154
        if ($text === null || strlen(trim($text)) === 0) {
155
            return;
156
        }
157
        $ih = IntrospectionHelper::getHelper(get_class($target));
158
        $text = self::replaceProperties($project, $text, $project->getProperties());
159
        $ih->addText($project, $target, $text);
160
    }
161
 
162
    /**
163
     * Stores a configured child element into its parent object
164
     *
165
     * @param  object  the project this element belongs to
166
     * @param  object  the parent element
167
     * @param  object  the child element
168
     * @param  string  the XML tagname
169
     * @access public
170
     */
171
    public static function storeChild($project, $parent, $child, $tag) {
172
        $ih = IntrospectionHelper::getHelper(get_class($parent));
173
        $ih->storeElement($project, $parent, $child, $tag);
174
    }
175
 
176
    // The following two properties are a sort of hack
177
    // to enable a static function to serve as the callback
178
    // for preg_replace_callback().  Clearly we cannot use object
179
    // variables, since the replaceProperties() is called statically.
180
    // This is IMO better than using global variables in the callback.
181
 
182
    private static $propReplaceProject;
183
    private static $propReplaceProperties;
184
 
185
    /**
186
     * Replace ${} style constructions in the given value with the
187
     * string value of the corresponding data types. This method is
188
     * static.
189
     *
190
     * @param  object  the project that should be used for property look-ups
191
     * @param  string  the string to be scanned for property references
192
     * @param  array   proeprty keys
193
     * @return string  the replaced string or <code>null</code> if the string
194
     *                 itself was null
195
     */
196
    public static function replaceProperties(Project $project, $value, $keys) {
197
 
198
        if ($value === null) {
199
            return null;
200
        }
201
 
202
        // These are a "hack" to support static callback for preg_replace_callback()
203
 
204
        // make sure these get initialized every time
205
        self::$propReplaceProperties = $keys;
206
        self::$propReplaceProject = $project;
207
 
208
        // Because we're not doing anything special (like multiple passes),
209
        // regex is the simplest / fastest.  PropertyTask, though, uses
210
        // the old parsePropertyString() method, since it has more stringent
211
        // requirements.
212
 
213
        $sb = preg_replace_callback('/\$\{([^}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $value);
214
        return $sb;
215
    }
216
 
217
    /**
218
     * Private [static] function for use by preg_replace_callback to replace a single param.
219
     * This method makes use of a static variable to hold the
220
     */
221
    private static function replacePropertyCallback($matches)
222
    {
223
        $propertyName = $matches[1];
224
        if (!isset(self::$propReplaceProperties[$propertyName])) {
225
                    self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', Project::MSG_VERBOSE);
226
                    return $matches[0];
227
        } else {
228
			self::$propReplaceProject->log('Property ${'.$propertyName.'} => ' . self::$propReplaceProperties[$propertyName], Project::MSG_DEBUG);
229
		}
230
        return self::$propReplaceProperties[$propertyName];
231
    }
232
 
233
    /**
234
     * Scan Attributes for the id attribute and maybe add a reference to
235
     * project.
236
     *
237
     * @param object the element's object
238
     * @param array  the element's attributes
239
     */
240
    public function configureId($target, $attr) {
241
        if (isset($attr['id']) && $attr['id'] !== null) {
242
            $this->project->addReference($attr['id'], $target);
243
        }
244
    }
245
}