PageRenderTime 41ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/pear/php/PEAR/DependencyDB.php

https://github.com/hnw/phpbugs
PHP | 713 lines | 527 code | 24 blank | 162 comment | 125 complexity | f48a05aee6a88319eb2b45a9a649b0f0 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * PEAR_DependencyDB, advanced installed packages dependency database
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: This source file is subject to version 3.0 of the PHP license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  10. * the PHP License and are unable to obtain it through the web, please
  11. * send a note to license@php.net so we can mail you a copy immediately.
  12. *
  13. * @category pear
  14. * @package PEAR
  15. * @author Tomas V. V. Cox <cox@idecnet.com>
  16. * @author Greg Beaver <cellog@php.net>
  17. * @copyright 1997-2008 The PHP Group
  18. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  19. * @version CVS: $Id: DependencyDB.php,v 1.37 2008/01/03 20:26:35 cellog Exp $
  20. * @link http://pear.php.net/package/PEAR
  21. * @since File available since Release 1.4.0a1
  22. */
  23. /**
  24. * Needed for error handling
  25. */
  26. require_once 'PEAR.php';
  27. require_once 'PEAR/Config.php';
  28. $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
  29. /**
  30. * Track dependency relationships between installed packages
  31. * @category pear
  32. * @package PEAR
  33. * @author Greg Beaver <cellog@php.net>
  34. * @author Tomas V.V.Cox <cox@idec.net.com>
  35. * @copyright 1997-2008 The PHP Group
  36. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  37. * @version Release: 1.7.2
  38. * @link http://pear.php.net/package/PEAR
  39. * @since Class available since Release 1.4.0a1
  40. */
  41. class PEAR_DependencyDB
  42. {
  43. // {{{ properties
  44. /**
  45. * This is initialized by {@link setConfig()}
  46. * @var PEAR_Config
  47. * @access private
  48. */
  49. var $_config;
  50. /**
  51. * This is initialized by {@link setConfig()}
  52. * @var PEAR_Registry
  53. * @access private
  54. */
  55. var $_registry;
  56. /**
  57. * Filename of the dependency DB (usually .depdb)
  58. * @var string
  59. * @access private
  60. */
  61. var $_depdb = false;
  62. /**
  63. * File name of the lockfile (usually .depdblock)
  64. * @var string
  65. * @access private
  66. */
  67. var $_lockfile = false;
  68. /**
  69. * Open file resource for locking the lockfile
  70. * @var resource|false
  71. * @access private
  72. */
  73. var $_lockFp = false;
  74. /**
  75. * API version of this class, used to validate a file on-disk
  76. * @var string
  77. * @access private
  78. */
  79. var $_version = '1.0';
  80. /**
  81. * Cached dependency database file
  82. * @var array|null
  83. * @access private
  84. */
  85. var $_cache;
  86. // }}}
  87. // {{{ & singleton()
  88. /**
  89. * Get a raw dependency database. Calls setConfig() and assertDepsDB()
  90. * @param PEAR_Config
  91. * @param string|false full path to the dependency database, or false to use default
  92. * @return PEAR_DependencyDB|PEAR_Error
  93. * @static
  94. */
  95. function &singleton(&$config, $depdb = false)
  96. {
  97. if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  98. [$config->get('php_dir', null, 'pear.php.net')])) {
  99. $a = new PEAR_DependencyDB;
  100. $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  101. [$config->get('php_dir', null, 'pear.php.net')] = &$a;
  102. $a->setConfig($config, $depdb);
  103. if (PEAR::isError($e = $a->assertDepsDB())) {
  104. return $e;
  105. }
  106. }
  107. return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  108. [$config->get('php_dir', null, 'pear.php.net')];
  109. }
  110. /**
  111. * Set up the registry/location of dependency DB
  112. * @param PEAR_Config|false
  113. * @param string|false full path to the dependency database, or false to use default
  114. */
  115. function setConfig(&$config, $depdb = false)
  116. {
  117. if (!$config) {
  118. $this->_config = &PEAR_Config::singleton();
  119. } else {
  120. $this->_config = &$config;
  121. }
  122. $this->_registry = &$this->_config->getRegistry();
  123. if (!$depdb) {
  124. $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
  125. DIRECTORY_SEPARATOR . '.depdb';
  126. } else {
  127. $this->_depdb = $depdb;
  128. }
  129. $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
  130. }
  131. // }}}
  132. function hasWriteAccess()
  133. {
  134. if (!file_exists($this->_depdb)) {
  135. $dir = $this->_depdb;
  136. while ($dir && $dir != '.') {
  137. $dir = dirname($dir); // cd ..
  138. if ($dir != '.' && file_exists($dir)) {
  139. if (is_writeable($dir)) {
  140. return true;
  141. } else {
  142. return false;
  143. }
  144. }
  145. }
  146. return false;
  147. }
  148. return is_writeable($this->_depdb);
  149. }
  150. // {{{ assertDepsDB()
  151. /**
  152. * Create the dependency database, if it doesn't exist. Error if the database is
  153. * newer than the code reading it.
  154. * @return void|PEAR_Error
  155. */
  156. function assertDepsDB()
  157. {
  158. if (!is_file($this->_depdb)) {
  159. $this->rebuildDB();
  160. } else {
  161. $depdb = $this->_getDepDB();
  162. // Datatype format has been changed, rebuild the Deps DB
  163. if ($depdb['_version'] < $this->_version) {
  164. $this->rebuildDB();
  165. }
  166. if ($depdb['_version']{0} > $this->_version{0}) {
  167. return PEAR::raiseError('Dependency database is version ' .
  168. $depdb['_version'] . ', and we are version ' .
  169. $this->_version . ', cannot continue');
  170. }
  171. }
  172. }
  173. /**
  174. * Get a list of installed packages that depend on this package
  175. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  176. * @return array|false
  177. */
  178. function getDependentPackages(&$pkg)
  179. {
  180. $data = $this->_getDepDB();
  181. if (is_object($pkg)) {
  182. $channel = strtolower($pkg->getChannel());
  183. $package = strtolower($pkg->getPackage());
  184. } else {
  185. $channel = strtolower($pkg['channel']);
  186. $package = strtolower($pkg['package']);
  187. }
  188. if (isset($data['packages'][$channel][$package])) {
  189. return $data['packages'][$channel][$package];
  190. }
  191. return false;
  192. }
  193. /**
  194. * Get a list of the actual dependencies of installed packages that depend on
  195. * a package.
  196. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  197. * @return array|false
  198. */
  199. function getDependentPackageDependencies(&$pkg)
  200. {
  201. $data = $this->_getDepDB();
  202. if (is_object($pkg)) {
  203. $channel = strtolower($pkg->getChannel());
  204. $package = strtolower($pkg->getPackage());
  205. } else {
  206. $channel = strtolower($pkg['channel']);
  207. $package = strtolower($pkg['package']);
  208. }
  209. $depend = $this->getDependentPackages($pkg);
  210. if (!$depend) {
  211. return false;
  212. }
  213. $dependencies = array();
  214. foreach ($depend as $info) {
  215. $temp = $this->getDependencies($info);
  216. foreach ($temp as $dep) {
  217. if (strtolower($dep['dep']['channel']) == strtolower($channel) &&
  218. strtolower($dep['dep']['name']) == strtolower($package)) {
  219. if (!isset($dependencies[$info['channel']])) {
  220. $dependencies[$info['channel']] = array();
  221. }
  222. if (!isset($dependencies[$info['channel']][$info['package']])) {
  223. $dependencies[$info['channel']][$info['package']] = array();
  224. }
  225. $dependencies[$info['channel']][$info['package']][] = $dep;
  226. }
  227. }
  228. }
  229. return $dependencies;
  230. }
  231. /**
  232. * Get a list of dependencies of this installed package
  233. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  234. * @return array|false
  235. */
  236. function getDependencies(&$pkg)
  237. {
  238. if (is_object($pkg)) {
  239. $channel = strtolower($pkg->getChannel());
  240. $package = strtolower($pkg->getPackage());
  241. } else {
  242. $channel = strtolower($pkg['channel']);
  243. $package = strtolower($pkg['package']);
  244. }
  245. $data = $this->_getDepDB();
  246. if (isset($data['dependencies'][$channel][$package])) {
  247. return $data['dependencies'][$channel][$package];
  248. }
  249. return false;
  250. }
  251. /**
  252. * Determine whether $parent depends on $child, near or deep
  253. * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  254. * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  255. */
  256. function dependsOn($parent, $child)
  257. {
  258. $c = array();
  259. $this->_getDepDB();
  260. return $this->_dependsOn($parent, $child, $c);
  261. }
  262. function _dependsOn($parent, $child, &$checked)
  263. {
  264. if (is_object($parent)) {
  265. $channel = strtolower($parent->getChannel());
  266. $package = strtolower($parent->getPackage());
  267. } else {
  268. $channel = strtolower($parent['channel']);
  269. $package = strtolower($parent['package']);
  270. }
  271. if (is_object($child)) {
  272. $depchannel = strtolower($child->getChannel());
  273. $deppackage = strtolower($child->getPackage());
  274. } else {
  275. $depchannel = strtolower($child['channel']);
  276. $deppackage = strtolower($child['package']);
  277. }
  278. if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
  279. return false; // avoid endless recursion
  280. }
  281. $checked[$channel][$package][$depchannel][$deppackage] = true;
  282. if (!isset($this->_cache['dependencies'][$channel][$package])) {
  283. return false;
  284. }
  285. foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  286. if (isset($info['dep']['uri'])) {
  287. if (is_object($child)) {
  288. if ($info['dep']['uri'] == $child->getURI()) {
  289. return true;
  290. }
  291. } elseif (isset($child['uri'])) {
  292. if ($info['dep']['uri'] == $child['uri']) {
  293. return true;
  294. }
  295. }
  296. return false;
  297. }
  298. if (strtolower($info['dep']['channel']) == strtolower($depchannel) &&
  299. strtolower($info['dep']['name']) == strtolower($deppackage)) {
  300. return true;
  301. }
  302. }
  303. foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  304. if (isset($info['dep']['uri'])) {
  305. if ($this->_dependsOn(array(
  306. 'uri' => $info['dep']['uri'],
  307. 'package' => $info['dep']['name']), $child, $checked)) {
  308. return true;
  309. }
  310. } else {
  311. if ($this->_dependsOn(array(
  312. 'channel' => $info['dep']['channel'],
  313. 'package' => $info['dep']['name']), $child, $checked)) {
  314. return true;
  315. }
  316. }
  317. }
  318. return false;
  319. }
  320. /**
  321. * Register dependencies of a package that is being installed or upgraded
  322. * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
  323. */
  324. function installPackage(&$package)
  325. {
  326. $data = $this->_getDepDB();
  327. unset($this->_cache);
  328. $this->_setPackageDeps($data, $package);
  329. $this->_writeDepDB($data);
  330. }
  331. /**
  332. * Remove dependencies of a package that is being uninstalled, or upgraded.
  333. *
  334. * Upgraded packages first uninstall, then install
  335. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
  336. * indices 'channel' and 'package'
  337. */
  338. function uninstallPackage(&$pkg)
  339. {
  340. $data = $this->_getDepDB();
  341. unset($this->_cache);
  342. if (is_object($pkg)) {
  343. $channel = strtolower($pkg->getChannel());
  344. $package = strtolower($pkg->getPackage());
  345. } else {
  346. $channel = strtolower($pkg['channel']);
  347. $package = strtolower($pkg['package']);
  348. }
  349. if (!isset($data['dependencies'][$channel][$package])) {
  350. return true;
  351. }
  352. foreach ($data['dependencies'][$channel][$package] as $dep) {
  353. $found = false;
  354. if (isset($dep['dep']['uri'])) {
  355. $depchannel = '__uri';
  356. } else {
  357. $depchannel = strtolower($dep['dep']['channel']);
  358. }
  359. if (isset($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  360. foreach ($data['packages'][$depchannel][strtolower($dep['dep']['name'])] as
  361. $i => $info) {
  362. if ($info['channel'] == $channel &&
  363. $info['package'] == $package) {
  364. $found = true;
  365. break;
  366. }
  367. }
  368. }
  369. if ($found) {
  370. unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])][$i]);
  371. if (!count($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  372. unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  373. if (!count($data['packages'][$depchannel])) {
  374. unset($data['packages'][$depchannel]);
  375. }
  376. } else {
  377. $data['packages'][$depchannel][strtolower($dep['dep']['name'])] =
  378. array_values(
  379. $data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  380. }
  381. }
  382. }
  383. unset($data['dependencies'][$channel][$package]);
  384. if (!count($data['dependencies'][$channel])) {
  385. unset($data['dependencies'][$channel]);
  386. }
  387. if (!count($data['dependencies'])) {
  388. unset($data['dependencies']);
  389. }
  390. if (!count($data['packages'])) {
  391. unset($data['packages']);
  392. }
  393. $this->_writeDepDB($data);
  394. }
  395. /**
  396. * Rebuild the dependency DB by reading registry entries.
  397. * @return true|PEAR_Error
  398. */
  399. function rebuildDB()
  400. {
  401. $depdb = array('_version' => $this->_version);
  402. if (!$this->hasWriteAccess()) {
  403. // allow startup for read-only with older Registry
  404. return $depdb;
  405. }
  406. $packages = $this->_registry->listAllPackages();
  407. if (PEAR::isError($packages)) {
  408. return $packages;
  409. }
  410. foreach ($packages as $channel => $ps) {
  411. foreach ($ps as $package) {
  412. $package = $this->_registry->getPackage($package, $channel);
  413. if (PEAR::isError($package)) {
  414. return $package;
  415. }
  416. $this->_setPackageDeps($depdb, $package);
  417. }
  418. }
  419. $error = $this->_writeDepDB($depdb);
  420. if (PEAR::isError($error)) {
  421. return $error;
  422. }
  423. $this->_cache = $depdb;
  424. return true;
  425. }
  426. /**
  427. * Register usage of the dependency DB to prevent race conditions
  428. * @param int one of the LOCK_* constants
  429. * @return true|PEAR_Error
  430. * @access private
  431. */
  432. function _lock($mode = LOCK_EX)
  433. {
  434. if (!eregi('Windows 9', php_uname())) {
  435. if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
  436. // XXX does not check type of lock (LOCK_SH/LOCK_EX)
  437. return true;
  438. }
  439. $open_mode = 'w';
  440. // XXX People reported problems with LOCK_SH and 'w'
  441. if ($mode === LOCK_SH) {
  442. if (!file_exists($this->_lockfile)) {
  443. touch($this->_lockfile);
  444. } elseif (!is_file($this->_lockfile)) {
  445. return PEAR::raiseError('could not create Dependency lock file, ' .
  446. 'it exists and is not a regular file');
  447. }
  448. $open_mode = 'r';
  449. }
  450. if (!is_resource($this->_lockFp)) {
  451. $this->_lockFp = @fopen($this->_lockfile, $open_mode);
  452. }
  453. if (!is_resource($this->_lockFp)) {
  454. return PEAR::raiseError("could not create Dependency lock file" .
  455. (isset($php_errormsg) ? ": " . $php_errormsg : ""));
  456. }
  457. if (!(int)flock($this->_lockFp, $mode)) {
  458. switch ($mode) {
  459. case LOCK_SH: $str = 'shared'; break;
  460. case LOCK_EX: $str = 'exclusive'; break;
  461. case LOCK_UN: $str = 'unlock'; break;
  462. default: $str = 'unknown'; break;
  463. }
  464. return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
  465. }
  466. }
  467. return true;
  468. }
  469. /**
  470. * Release usage of dependency DB
  471. * @return true|PEAR_Error
  472. * @access private
  473. */
  474. function _unlock()
  475. {
  476. $ret = $this->_lock(LOCK_UN);
  477. if (is_resource($this->_lockFp)) {
  478. fclose($this->_lockFp);
  479. }
  480. $this->_lockFp = null;
  481. return $ret;
  482. }
  483. /**
  484. * Load the dependency database from disk, or return the cache
  485. * @return array|PEAR_Error
  486. */
  487. function _getDepDB()
  488. {
  489. if (!$this->hasWriteAccess()) {
  490. return array('_version' => $this->_version);
  491. }
  492. if (isset($this->_cache)) {
  493. return $this->_cache;
  494. }
  495. if (!$fp = fopen($this->_depdb, 'r')) {
  496. $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
  497. return $err;
  498. }
  499. $rt = get_magic_quotes_runtime();
  500. set_magic_quotes_runtime(0);
  501. clearstatcache();
  502. fclose($fp);
  503. $data = unserialize(file_get_contents($this->_depdb));
  504. set_magic_quotes_runtime($rt);
  505. $this->_cache = $data;
  506. return $data;
  507. }
  508. /**
  509. * Write out the dependency database to disk
  510. * @param array the database
  511. * @return true|PEAR_Error
  512. * @access private
  513. */
  514. function _writeDepDB(&$deps)
  515. {
  516. if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
  517. return $e;
  518. }
  519. if (!$fp = fopen($this->_depdb, 'wb')) {
  520. $this->_unlock();
  521. return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
  522. }
  523. $rt = get_magic_quotes_runtime();
  524. set_magic_quotes_runtime(0);
  525. fwrite($fp, serialize($deps));
  526. set_magic_quotes_runtime($rt);
  527. fclose($fp);
  528. $this->_unlock();
  529. $this->_cache = $deps;
  530. return true;
  531. }
  532. /**
  533. * Register all dependencies from a package in the dependencies database, in essence
  534. * "installing" the package's dependency information
  535. * @param array the database
  536. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  537. * @access private
  538. */
  539. function _setPackageDeps(&$data, &$pkg)
  540. {
  541. $pkg->setConfig($this->_config);
  542. if ($pkg->getPackagexmlVersion() == '1.0') {
  543. $gen = &$pkg->getDefaultGenerator();
  544. $deps = $gen->dependenciesToV2();
  545. } else {
  546. $deps = $pkg->getDeps(true);
  547. }
  548. if (!$deps) {
  549. return;
  550. }
  551. if (!is_array($data)) {
  552. $data = array();
  553. }
  554. if (!isset($data['dependencies'])) {
  555. $data['dependencies'] = array();
  556. }
  557. if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) {
  558. $data['dependencies'][strtolower($pkg->getChannel())] = array();
  559. }
  560. $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())]
  561. = array();
  562. if (isset($deps['required']['package'])) {
  563. if (!isset($deps['required']['package'][0])) {
  564. $deps['required']['package'] = array($deps['required']['package']);
  565. }
  566. foreach ($deps['required']['package'] as $dep) {
  567. $this->_registerDep($data, $pkg, $dep, 'required');
  568. }
  569. }
  570. if (isset($deps['optional']['package'])) {
  571. if (!isset($deps['optional']['package'][0])) {
  572. $deps['optional']['package'] = array($deps['optional']['package']);
  573. }
  574. foreach ($deps['optional']['package'] as $dep) {
  575. $this->_registerDep($data, $pkg, $dep, 'optional');
  576. }
  577. }
  578. if (isset($deps['required']['subpackage'])) {
  579. if (!isset($deps['required']['subpackage'][0])) {
  580. $deps['required']['subpackage'] = array($deps['required']['subpackage']);
  581. }
  582. foreach ($deps['required']['subpackage'] as $dep) {
  583. $this->_registerDep($data, $pkg, $dep, 'required');
  584. }
  585. }
  586. if (isset($deps['optional']['subpackage'])) {
  587. if (!isset($deps['optional']['subpackage'][0])) {
  588. $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
  589. }
  590. foreach ($deps['optional']['subpackage'] as $dep) {
  591. $this->_registerDep($data, $pkg, $dep, 'optional');
  592. }
  593. }
  594. if (isset($deps['group'])) {
  595. if (!isset($deps['group'][0])) {
  596. $deps['group'] = array($deps['group']);
  597. }
  598. foreach ($deps['group'] as $group) {
  599. if (isset($group['package'])) {
  600. if (!isset($group['package'][0])) {
  601. $group['package'] = array($group['package']);
  602. }
  603. foreach ($group['package'] as $dep) {
  604. $this->_registerDep($data, $pkg, $dep, 'optional',
  605. $group['attribs']['name']);
  606. }
  607. }
  608. if (isset($group['subpackage'])) {
  609. if (!isset($group['subpackage'][0])) {
  610. $group['subpackage'] = array($group['subpackage']);
  611. }
  612. foreach ($group['subpackage'] as $dep) {
  613. $this->_registerDep($data, $pkg, $dep, 'optional',
  614. $group['attribs']['name']);
  615. }
  616. }
  617. }
  618. }
  619. if ($data['dependencies'][strtolower($pkg->getChannel())]
  620. [strtolower($pkg->getPackage())] == array()) {
  621. unset($data['dependencies'][strtolower($pkg->getChannel())]
  622. [strtolower($pkg->getPackage())]);
  623. if (!count($data['dependencies'][strtolower($pkg->getChannel())])) {
  624. unset($data['dependencies'][strtolower($pkg->getChannel())]);
  625. }
  626. }
  627. }
  628. /**
  629. * @param array the database
  630. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  631. * @param array the specific dependency
  632. * @param required|optional whether this is a required or an optional dep
  633. * @param string|false dependency group this dependency is from, or false for ordinary dep
  634. */
  635. function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
  636. {
  637. $info = array(
  638. 'dep' => $dep,
  639. 'type' => $type,
  640. 'group' => $group);
  641. if (isset($dep['channel'])) {
  642. $depchannel = $dep['channel'];
  643. } else {
  644. $depchannel = '__uri';
  645. }
  646. if (!isset($data['dependencies'])) {
  647. $data['dependencies'] = array();
  648. }
  649. if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) {
  650. $data['dependencies'][strtolower($pkg->getChannel())] = array();
  651. }
  652. if (!isset($data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())])) {
  653. $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] = array();
  654. }
  655. $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][]
  656. = $info;
  657. if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
  658. $found = false;
  659. foreach ($data['packages'][strtolower($depchannel)][strtolower($dep['name'])]
  660. as $i => $p) {
  661. if ($p['channel'] == strtolower($pkg->getChannel()) &&
  662. $p['package'] == strtolower($pkg->getPackage())) {
  663. $found = true;
  664. break;
  665. }
  666. }
  667. if (!$found) {
  668. $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  669. = array('channel' => strtolower($pkg->getChannel()),
  670. 'package' => strtolower($pkg->getPackage()));
  671. }
  672. } else {
  673. if (!isset($data['packages'])) {
  674. $data['packages'] = array();
  675. }
  676. if (!isset($data['packages'][strtolower($depchannel)])) {
  677. $data['packages'][strtolower($depchannel)] = array();
  678. }
  679. if (!isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
  680. $data['packages'][strtolower($depchannel)][strtolower($dep['name'])] = array();
  681. }
  682. $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  683. = array('channel' => strtolower($pkg->getChannel()),
  684. 'package' => strtolower($pkg->getPackage()));
  685. }
  686. }
  687. }
  688. ?>