PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/install/phing/classes/phing/parser/ProjectConfigurator.php

https://github.com/chregu/fluxcms
PHP | 232 lines | 91 code | 23 blank | 118 comment | 10 complexity | 348b4115b4e479e54bae3fac78cf08c7 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. /*
  3. * $Id$
  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. include_once 'phing/system/io/BufferedReader.php';
  22. include_once 'phing/system/io/FileReader.php';
  23. include_once 'phing/BuildException.php';
  24. include_once 'phing/system/lang/FileNotFoundException.php';
  25. /**
  26. * The datatype handler class.
  27. *
  28. * This class handles the occurance of registered datatype tags like
  29. * FileSet
  30. *
  31. * @author Andreas Aderhold <andi@binarycloud.com>
  32. * @copyright © 2001,2002 THYRELL. All rights reserved
  33. * @version $Revision: 1.13 $ $Date: 2005/02/27 20:52:09 $
  34. * @access public
  35. * @package phing.parser
  36. */
  37. class ProjectConfigurator {
  38. public $project;
  39. public $locator;
  40. public $buildFile;
  41. public $buildFileParent;
  42. /**
  43. * Static call to ProjectConfigurator. Use this to configure a
  44. * project. Do not use the new operator.
  45. *
  46. * @param object the Project instance this configurator should use
  47. * @param object the buildfile object the parser should use
  48. * @access public
  49. */
  50. function configureProject(Project $project, File $buildFile) {
  51. $pc = new ProjectConfigurator($project, $buildFile);
  52. $pc->parse();
  53. }
  54. /**
  55. * Constructs a new ProjectConfigurator object
  56. * This constructor is private. Use a static call to
  57. * <code>configureProject</code> to configure a project.
  58. *
  59. * @param object the Project instance this configurator should use
  60. * @param object the buildfile object the parser should use
  61. * @access private
  62. */
  63. function __construct(Project $project, File $buildFile) {
  64. $this->project = $project;
  65. $this->buildFile = new File($buildFile->getAbsolutePath());
  66. $this->buildFileParent = new File($this->buildFile->getParent());
  67. }
  68. /**
  69. * Creates the ExpatParser, sets root handler and kick off parsing
  70. * process.
  71. *
  72. * @throws BuildException if there is any kind of execption during
  73. * the parsing process
  74. * @access private
  75. */
  76. protected function parse() {
  77. try {
  78. $reader = new BufferedReader(new FileReader($this->buildFile));
  79. $reader->open();
  80. $parser = new ExpatParser($reader);
  81. $parser->parserSetOption(XML_OPTION_CASE_FOLDING,0);
  82. $parser->setHandler(new RootHandler($parser, $this));
  83. $this->project->log("parsing buildfile ".$this->buildFile->getName(), PROJECT_MSG_VERBOSE);
  84. $parser->parse();
  85. $reader->close();
  86. } catch (Exception $exc) {
  87. throw new BuildException("Error reading project file", $exc);
  88. }
  89. }
  90. /**
  91. * Configures an element and resolves eventually given properties.
  92. *
  93. * @param object the element to configure
  94. * @param array the element's attributes
  95. * @param object the project this element belongs to
  96. * @throws Exception if arguments are not valid
  97. * @throws BuildException if attributes can not be configured
  98. * @access public
  99. */
  100. function configure($target, $attrs, Project $project) {
  101. if ($target instanceof TaskAdapter) {
  102. $target = $target->getProxy();
  103. }
  104. $bean = get_class($target);
  105. $ih = IntrospectionHelper::getHelper($bean);
  106. foreach ($attrs as $key => $value) {
  107. if ($key == 'id') {
  108. continue;
  109. // throw new BuildException("Id must be set Extermnally");
  110. }
  111. $value = self::replaceProperties($project, $value, $project->getProperties());
  112. try { // try to set the attribute
  113. $ih->setAttribute($project, $target, strtolower($key), $value);
  114. } catch (BuildException $be) {
  115. // id attribute must be set externally
  116. if ($key !== "id") {
  117. throw $be;
  118. }
  119. }
  120. }
  121. }
  122. /**
  123. * Configures the #CDATA of an element.
  124. *
  125. * @param object the project this element belongs to
  126. * @param object the element to configure
  127. * @param string the element's #CDATA
  128. * @access public
  129. */
  130. function addText($project, $target, $text = null) {
  131. if ($text === null || strlen(trim($text)) === 0) {
  132. return;
  133. }
  134. $ih = IntrospectionHelper::getHelper(get_class($target));
  135. $text = self::replaceProperties($project, $text, $project->getProperties());
  136. $ih->addText($project, $target, $text);
  137. }
  138. /**
  139. * Stores a configured child element into its parent object
  140. *
  141. * @param object the project this element belongs to
  142. * @param object the parent element
  143. * @param object the child element
  144. * @param string the XML tagname
  145. * @access public
  146. */
  147. function storeChild($project, $parent, $child, $tag) {
  148. $ih = IntrospectionHelper::getHelper(get_class($parent));
  149. $ih->storeElement($project, $parent, $child, $tag);
  150. }
  151. // The following two properties are a sort of hack
  152. // to enable a static function to serve as the callback
  153. // for preg_replace_callback(). Clearly we cannot use object
  154. // variables, since the replaceProperties() is called statically.
  155. // This is IMO better than using global variables in the callback.
  156. private static $propReplaceProject;
  157. private static $propReplaceProperties;
  158. /**
  159. * Replace ${} style constructions in the given value with the
  160. * string value of the corresponding data types. This method is
  161. * static.
  162. *
  163. * @param object the project that should be used for property look-ups
  164. * @param string the string to be scanned for property references
  165. * @param array proeprty keys
  166. * @return string the replaced string or <code>null</code> if the string
  167. * itself was null
  168. */
  169. public static function replaceProperties(Project $project, $value, $keys) {
  170. if ($value === null) {
  171. return null;
  172. }
  173. // These are a "hack" to support static callback for preg_replace_callback()
  174. // make sure these get initialized every time
  175. self::$propReplaceProperties = $keys;
  176. self::$propReplaceProject = $project;
  177. // Because we're not doing anything special (like multiple passes),
  178. // regex is the simplest / fastest. PropertyTask, though, uses
  179. // the old parsePropertyString() method, since it has more stringent
  180. // requirements.
  181. $sb = preg_replace_callback('/\$\{([^}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $value);
  182. return $sb;
  183. }
  184. /**
  185. * Private [static] function for use by preg_replace_callback to replace a single param.
  186. * This method makes use of a static variable to hold the
  187. */
  188. private static function replacePropertyCallback($matches)
  189. {
  190. $propertyName = $matches[1];
  191. if (!isset(self::$propReplaceProperties[$propertyName])) {
  192. self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', PROJECT_MSG_VERBOSE);
  193. return $matches[0];
  194. }
  195. return self::$propReplaceProperties[$propertyName];
  196. }
  197. /**
  198. * Scan Attributes for the id attribute and maybe add a reference to
  199. * project.
  200. *
  201. * @param object the element's object
  202. * @param array the element's attributes
  203. */
  204. function configureId(&$target, $attr) {
  205. if (isset($attr['id']) && $attr['id'] !== null) {
  206. $this->project->addReference($attr['id'], $target);
  207. }
  208. }
  209. }