PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/common/libraries/plugin/pear/phing/tasks/ext/PearPackageTask.php

https://bitbucket.org/chamilo/chamilo-dev/
PHP | 500 lines | 256 code | 73 blank | 171 comment | 21 complexity | 2222dd9aaff3037bb9e098dbabe6cf8a MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  1. <?php
  2. /*
  3. * $Id: PearPackageTask.php 843 2010-09-02 14:39:13Z mrook $
  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. require_once 'phing/tasks/system/MatchingTask.php';
  22. include_once 'phing/types/FileSet.php';
  23. /**
  24. * A task to create PEAR package.xml file.
  25. *
  26. * This class uses the PEAR_PackageFileMaintainer class to perform the work.
  27. *
  28. * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o
  29. * requiring changes to this class. We've accomplished this by having generic <option> and <mapping>
  30. * nested elements. All options are set using PEAR_PackageFileMaintainer::setOptions().
  31. *
  32. * The <option> tag is used to set a simple option value.
  33. * <code>
  34. * <option name="option_name" value="option_value"/>
  35. * or <option name="option_name">option_value</option>
  36. * </code>
  37. *
  38. * The <mapping> tag represents a complex data type. You can use nested <element> (and nested <element> with
  39. * <element> tags) to represent the full complexity of the structure. Bear in mind that what you are creating
  40. * will be mapped to an associative array that will be passed in via PEAR_PackageFileMaintainer::setOptions().
  41. * <code>
  42. * <mapping name="option_name">
  43. * <element key="key_name" value="key_val"/>
  44. * <element key="key_name" value="key_val"/>
  45. * </mapping>
  46. * </code>
  47. *
  48. * Here's an over-simple example of how this could be used:
  49. * <code>
  50. * <pearpkg name="phing" dir="${build.src.dir}" destFile="${build.base.dir}/package.xml">
  51. * <fileset>
  52. * <include name="**"/>
  53. * </fileset>
  54. * <option name="notes">Sample release notes here.</option>
  55. * <option name="description">Package description</option>
  56. * <option name="summary">Short description</option>
  57. * <option name="version" value="2.0.0b1"/>
  58. * <option name="state" value="beta"/>
  59. * <mapping name="maintainers">
  60. * <element>
  61. * <element key="handle" value="hlellelid"/>
  62. * <element key="name" value="Hans"/>
  63. * <element key="email" value="hans@xmpl.org"/>
  64. * <element key="role" value="lead"/>
  65. * </element>
  66. * </mapping>
  67. * </pearpkg>
  68. * </code>
  69. *
  70. * Look at the build.xml in the Phing base directory (assuming you have the full distro / CVS version of Phing) to
  71. * see a more complete example of how to call this script.
  72. *
  73. * @author Hans Lellelid <hans@xmpl.org>
  74. * @package phing.tasks.ext
  75. * @version $Id: PearPackageTask.php 843 2010-09-02 14:39:13Z mrook $
  76. */
  77. class PearPackageTask extends MatchingTask
  78. {
  79. /** */
  80. protected $package;
  81. /** Base directory for reading files. */
  82. protected $dir;
  83. /** Package file */
  84. private $packageFile;
  85. /** @var array FileSet[] */
  86. private $filesets = array();
  87. /** @var PEAR_PackageFileManager */
  88. protected $pkg;
  89. private $preparedOptions = array();
  90. /** @var array PearPkgOption[] */
  91. protected $options = array();
  92. /** Nested <mapping> (complex options) types. */
  93. protected $mappings = array();
  94. public function init()
  95. {
  96. include_once 'PEAR/PackageFileManager.php';
  97. if (! class_exists('PEAR_PackageFileManager'))
  98. {
  99. throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml file.");
  100. }
  101. }
  102. /**
  103. * Sets PEAR package.xml options, based on class properties.
  104. * @return void
  105. */
  106. protected function setOptions()
  107. {
  108. // 1) first prepare/populate options
  109. $this->populateOptions();
  110. // 2) make any final adjustments (this could move into populateOptions() also)
  111. // default PEAR basedir would be the name of the package (e.g."phing")
  112. if (! isset($this->preparedOptions['baseinstalldir']))
  113. {
  114. $this->preparedOptions['baseinstalldir'] = $this->package;
  115. }
  116. // unless filelistgenerator has been overridden, we use Phing FileSet generator
  117. if (! isset($this->preparedOptions['filelistgenerator']))
  118. {
  119. if (empty($this->filesets))
  120. {
  121. throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
  122. }
  123. $this->preparedOptions['filelistgenerator'] = 'Fileset';
  124. $this->preparedOptions['usergeneratordir'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pearpackage';
  125. // Some PHING-specific options needed by our Fileset reader
  126. $this->preparedOptions['phing_project'] = $this->project;
  127. $this->preparedOptions['phing_filesets'] = $this->filesets;
  128. }
  129. elseif ($this->preparedOptions['filelistgeneragor'] != 'Fileset' && ! empty($this->filesets))
  130. {
  131. throw new BuildException("You cannot use <fileset> element if you have specified the \"filelistgenerator\" option.");
  132. }
  133. // 3) Set the options
  134. // No need for excessive validation here, since the PEAR class will do its own
  135. // validation & return errors
  136. $e = $this->pkg->setOptions($this->preparedOptions);
  137. if (PEAR :: isError($e))
  138. {
  139. throw new BuildException("Unable to set options.", new Exception($e->getMessage()));
  140. }
  141. }
  142. /**
  143. * Fixes the boolean in optional dependencies
  144. */
  145. private function fixDeps($deps)
  146. {
  147. foreach (array_keys($deps) as $dep)
  148. {
  149. if (isset($deps[$dep]['optional']) && $deps[$dep]['optional'])
  150. {
  151. $deps[$dep]['optional'] = "yes";
  152. }
  153. }
  154. return $deps;
  155. }
  156. /**
  157. * Adds the options that are set via attributes and the nested tags to the options array.
  158. */
  159. private function populateOptions()
  160. {
  161. // These values could be overridden if explicitly defined using nested tags
  162. $this->preparedOptions['package'] = $this->package;
  163. $this->preparedOptions['packagedirectory'] = $this->dir->getAbsolutePath();
  164. if ($this->packageFile !== null)
  165. {
  166. // create one w/ full path
  167. $f = new PhingFile($this->packageFile->getAbsolutePath());
  168. $this->preparedOptions['packagefile'] = $f->getName();
  169. // must end in trailing slash
  170. $this->preparedOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
  171. $this->log("Creating package file: " . $f->__toString(), Project :: MSG_INFO);
  172. }
  173. else
  174. {
  175. $this->log("Creating [default] package.xml file in base directory.", Project :: MSG_INFO);
  176. }
  177. // converts option objects and mapping objects into
  178. // key => value options that can be passed to PEAR_PackageFileManager
  179. foreach ($this->options as $opt)
  180. {
  181. $this->preparedOptions[$opt->getName()] = $opt->getValue(); //no arrays yet. preg_split('/\s*,\s*/', $opt->getValue());
  182. }
  183. foreach ($this->mappings as $map)
  184. {
  185. $value = $map->getValue(); // getValue returns complex value
  186. if ($map->getName() == 'deps')
  187. {
  188. $value = $this->fixDeps($value);
  189. }
  190. $this->preparedOptions[$map->getName()] = $value;
  191. }
  192. }
  193. /**
  194. * Main entry point.
  195. * @return void
  196. */
  197. public function main()
  198. {
  199. if ($this->dir === null)
  200. {
  201. throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
  202. }
  203. if ($this->package === null)
  204. {
  205. throw new BuildException("You must specify the \"name\" attribute for PEAR package task.");
  206. }
  207. $this->pkg = new PEAR_PackageFileManager();
  208. $this->setOptions();
  209. $e = $this->pkg->writePackageFile();
  210. if (PEAR :: isError($e))
  211. {
  212. throw new BuildException("Unable to write package file.", new Exception($e->getMessage()));
  213. }
  214. }
  215. /**
  216. * Used by the PEAR_PackageFileManager_PhingFileSet lister.
  217. * @return array FileSet[]
  218. */
  219. public function getFileSets()
  220. {
  221. return $this->filesets;
  222. }
  223. // -------------------------------
  224. // Set properties from XML
  225. // -------------------------------
  226. /**
  227. * Nested creator, creates a FileSet for this task
  228. *
  229. * @return FileSet The created fileset object
  230. */
  231. public function createFileSet()
  232. {
  233. $num = array_push($this->filesets, new FileSet());
  234. return $this->filesets[$num - 1];
  235. }
  236. /**
  237. * Set "package" property from XML.
  238. * @see setName()
  239. * @param string $v
  240. * @return void
  241. */
  242. public function setPackage($v)
  243. {
  244. $this->package = $v;
  245. }
  246. /**
  247. * Sets "dir" property from XML.
  248. * @param PhingFile $f
  249. * @return void
  250. */
  251. public function setDir(PhingFile $f)
  252. {
  253. $this->dir = $f;
  254. }
  255. /**
  256. * Sets "name" property from XML.
  257. * @param string $v
  258. * @return void
  259. */
  260. public function setName($v)
  261. {
  262. $this->package = $v;
  263. }
  264. /**
  265. * Sets the file to use for generated package.xml
  266. */
  267. public function setDestFile(PhingFile $f)
  268. {
  269. $this->packageFile = $f;
  270. }
  271. /**
  272. * Handles nested generic <option> elements.
  273. */
  274. public function createOption()
  275. {
  276. $o = new PearPkgOption();
  277. $this->options[] = $o;
  278. return $o;
  279. }
  280. /**
  281. * Handles nested generic <option> elements.
  282. */
  283. public function createMapping()
  284. {
  285. $o = new PearPkgMapping();
  286. $this->mappings[] = $o;
  287. return $o;
  288. }
  289. }
  290. /**
  291. * Generic option class is used for non-complex options.
  292. *
  293. * @package phing.tasks.ext
  294. */
  295. class PearPkgOption
  296. {
  297. private $name;
  298. private $value;
  299. public function setName($v)
  300. {
  301. $this->name = $v;
  302. }
  303. public function getName()
  304. {
  305. return $this->name;
  306. }
  307. public function setValue($v)
  308. {
  309. $this->value = $v;
  310. }
  311. public function getValue()
  312. {
  313. return $this->value;
  314. }
  315. public function addText($txt)
  316. {
  317. $this->value = trim($txt);
  318. }
  319. }
  320. /**
  321. * Handles complex options <mapping> elements which are hashes (assoc arrays).
  322. *
  323. * @package phing.tasks.ext
  324. */
  325. class PearPkgMapping
  326. {
  327. private $name;
  328. private $elements = array();
  329. public function setName($v)
  330. {
  331. $this->name = $v;
  332. }
  333. public function getName()
  334. {
  335. return $this->name;
  336. }
  337. public function createElement()
  338. {
  339. $e = new PearPkgMappingElement();
  340. $this->elements[] = $e;
  341. return $e;
  342. }
  343. public function getElements()
  344. {
  345. return $this->elements;
  346. }
  347. /**
  348. * Returns the PHP hash or array of hashes (etc.) that this mapping represents.
  349. * @return array
  350. */
  351. public function getValue()
  352. {
  353. $value = array();
  354. foreach ($this->getElements() as $el)
  355. {
  356. if ($el->getKey() !== null)
  357. {
  358. $value[$el->getKey()] = $el->getValue();
  359. }
  360. else
  361. {
  362. $value[] = $el->getValue();
  363. }
  364. }
  365. return $value;
  366. }
  367. }
  368. /**
  369. * Sub-element of <mapping>.
  370. *
  371. * @package phing.tasks.ext
  372. */
  373. class PearPkgMappingElement
  374. {
  375. private $key;
  376. private $value;
  377. private $elements = array();
  378. public function setKey($v)
  379. {
  380. $this->key = $v;
  381. }
  382. public function getKey()
  383. {
  384. return $this->key;
  385. }
  386. public function setValue($v)
  387. {
  388. $this->value = $v;
  389. }
  390. /**
  391. * Returns either the simple value or
  392. * the calculated value (array) of nested elements.
  393. * @return mixed
  394. */
  395. public function getValue()
  396. {
  397. if (! empty($this->elements))
  398. {
  399. $value = array();
  400. foreach ($this->elements as $el)
  401. {
  402. if ($el->getKey() !== null)
  403. {
  404. $value[$el->getKey()] = $el->getValue();
  405. }
  406. else
  407. {
  408. $value[] = $el->getValue();
  409. }
  410. }
  411. return $value;
  412. }
  413. else
  414. {
  415. return $this->value;
  416. }
  417. }
  418. /**
  419. * Handles nested <element> tags.
  420. */
  421. public function createElement()
  422. {
  423. $e = new PearPkgMappingElement();
  424. $this->elements[] = $e;
  425. return $e;
  426. }
  427. }