PageRenderTime 49ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/generator/lib/model/Table.php

https://github.com/1989gaurav/Propel
PHP | 1909 lines | 973 code | 200 blank | 736 comment | 125 complexity | c3600e34dd9448b1e9a60e09f75872f5 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. require_once dirname(__FILE__) . '/ScopedElement.php';
  10. require_once dirname(__FILE__) . '/../exception/EngineException.php';
  11. require_once dirname(__FILE__) . '/IDMethod.php';
  12. require_once dirname(__FILE__) . '/NameFactory.php';
  13. require_once dirname(__FILE__) . '/Column.php';
  14. require_once dirname(__FILE__) . '/Unique.php';
  15. require_once dirname(__FILE__) . '/ForeignKey.php';
  16. require_once dirname(__FILE__) . '/IdMethodParameter.php';
  17. require_once dirname(__FILE__) . '/Validator.php';
  18. require_once dirname(__FILE__) . '/Behavior.php';
  19. /**
  20. * Data about a table used in an application.
  21. *
  22. * @author Hans Lellelid <hans@xmpl.org> (Propel)
  23. * @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
  24. * @author Jason van Zyl <jvanzyl@apache.org> (Torque)
  25. * @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
  26. * @author John McNally <jmcnally@collab.net> (Torque)
  27. * @author Daniel Rall <dlr@collab.net> (Torque)
  28. * @author Byron Foster <byron_foster@yahoo.com> (Torque)
  29. * @version $Revision$
  30. * @package propel.generator.model
  31. */
  32. class Table extends ScopedElement implements IDMethod
  33. {
  34. /**
  35. * Enables some debug printing.
  36. */
  37. const DEBUG = false;
  38. /**
  39. * Columns for this table.
  40. *
  41. * @var array Column[]
  42. */
  43. private $columnList = array();
  44. /**
  45. * Validators for this table.
  46. *
  47. * @var array Validator[]
  48. */
  49. private $validatorList = array();
  50. /**
  51. * Foreign keys for this table.
  52. *
  53. * @var array ForeignKey[]
  54. */
  55. private $foreignKeys = array();
  56. /**
  57. * Indexes for this table.
  58. *
  59. * @var array Index[]
  60. */
  61. private $indices = array();
  62. /**
  63. * Unique indexes for this table.
  64. *
  65. * @var array Unique[]
  66. */
  67. private $unices = array();
  68. /**
  69. * Any parameters for the ID method (currently supports changing sequence name).
  70. *
  71. * @var array
  72. */
  73. private $idMethodParameters = array();
  74. /**
  75. * Table name.
  76. *
  77. * @var string
  78. */
  79. private $commonName;
  80. /**
  81. * Table description.
  82. *
  83. * @var string
  84. */
  85. private $description;
  86. /**
  87. * phpName for the table.
  88. *
  89. * @var string
  90. */
  91. private $phpName;
  92. /**
  93. * ID method for the table (e.g. IDMethod::NATIVE, IDMethod::NONE).
  94. *
  95. * @var string
  96. */
  97. private $idMethod;
  98. /**
  99. * Wether an INSERT with set PK is allowed on tables with IDMethod::NATIVE
  100. *
  101. * @var boolean
  102. */
  103. private $allowPkInsert;
  104. /**
  105. * Strategry to use for converting column name to phpName.
  106. *
  107. * @var string
  108. */
  109. private $phpNamingMethod;
  110. /**
  111. * The Database that this table belongs to.
  112. *
  113. * @var Database
  114. */
  115. private $database;
  116. /**
  117. * Foreign Keys that refer to this table.
  118. *
  119. * @var array ForeignKey[]
  120. */
  121. private $referrers = array();
  122. /**
  123. * Names of foreign tables.
  124. *
  125. * @var array string[]
  126. */
  127. private $foreignTableNames;
  128. /**
  129. * Whether this table contains a foreign primary key.
  130. *
  131. * @var boolean
  132. */
  133. private $containsForeignPK;
  134. /**
  135. * The inheritance column for this table (if any).
  136. *
  137. * @var Column
  138. */
  139. private $inheritanceColumn;
  140. /**
  141. * Whether to skip generation of SQL for this table.
  142. *
  143. * @var boolean
  144. */
  145. private $skipSql;
  146. /**
  147. * Whether this table is "read-only".
  148. *
  149. * @var boolean
  150. */
  151. private $readOnly;
  152. /**
  153. * Whether this table should result in abstract OM classes.
  154. *
  155. * @var boolean
  156. */
  157. private $abstractValue;
  158. /**
  159. * Whether this table is an alias for another table.
  160. *
  161. * @var string
  162. */
  163. private $alias;
  164. /**
  165. * The interface that the generated "object" class should implement.
  166. *
  167. * @var string
  168. */
  169. private $enterface;
  170. /**
  171. * The base class to extend for the generated "object" class.
  172. *
  173. * @var string
  174. */
  175. private $baseClass;
  176. /**
  177. * The base peer class to extend for generated "peer" class.
  178. *
  179. * @var string
  180. */
  181. private $basePeer;
  182. /**
  183. * Map of columns by name.
  184. *
  185. * @var array
  186. */
  187. private $columnsByName = array();
  188. /**
  189. * Map of columns by lowercase name.
  190. *
  191. * @var array
  192. */
  193. private $columnsByLowercaseName = array();
  194. /**
  195. * Map of columns by phpName.
  196. *
  197. * @var array
  198. */
  199. private $columnsByPhpName = array();
  200. /**
  201. * Whether this table needs to use transactions in Postgres.
  202. *
  203. * @var string
  204. * @deprecated
  205. */
  206. private $needsTransactionInPostgres;
  207. /**
  208. * Whether to perform additional indexing on this table.
  209. *
  210. * @var boolean
  211. */
  212. private $heavyIndexing;
  213. /**
  214. * Whether this table is for reference only.
  215. *
  216. * @var boolean
  217. */
  218. private $forReferenceOnly;
  219. /**
  220. * The tree mode (nested set, etc.) implemented by this table.
  221. *
  222. * @var string
  223. */
  224. private $treeMode;
  225. /**
  226. * Whether to reload the rows in this table after insert.
  227. *
  228. * @var boolean
  229. */
  230. private $reloadOnInsert;
  231. /**
  232. * Whether to reload the rows in this table after update.
  233. *
  234. * @var boolean
  235. */
  236. private $reloadOnUpdate;
  237. /**
  238. * List of behaviors registered for this table
  239. *
  240. * @var array
  241. */
  242. protected $behaviors = array();
  243. /**
  244. * Whether this table is a cross-reference table for a many-to-many relationship
  245. *
  246. * @var boolean
  247. */
  248. protected $isCrossRef = false;
  249. /**
  250. * The default string format for objects based on this table
  251. * (e.g. 'XML', 'YAML', 'CSV', 'JSON')
  252. *
  253. * @var string
  254. */
  255. protected $defaultStringFormat;
  256. /**
  257. * Constructs a table object with a name
  258. *
  259. * @param string $name table name
  260. */
  261. public function __construct($name = null)
  262. {
  263. $this->commonName = $name;
  264. }
  265. /**
  266. * get a qualified name of this table with scheme and common name separated by '_'
  267. * if schemaAutoPrefix is set. Otherwise get the common name.
  268. * @return string
  269. */
  270. private function getStdSeparatedName()
  271. {
  272. if ($this->schema && $this->getBuildProperty('schemaAutoPrefix')) {
  273. return $this->schema . NameGenerator::STD_SEPARATOR_CHAR . $this->getCommonName();
  274. } else {
  275. return $this->getCommonName();
  276. }
  277. }
  278. /**
  279. * Sets up the Rule object based on the attributes that were passed to loadFromXML().
  280. * @see parent::loadFromXML()
  281. */
  282. public function setupObject()
  283. {
  284. parent::setupObject();
  285. $this->commonName = $this->getDatabase()->getTablePrefix() . $this->getAttribute("name");
  286. // retrieves the method for converting from specified name to a PHP name.
  287. $this->phpNamingMethod = $this->getAttribute("phpNamingMethod", $this->getDatabase()->getDefaultPhpNamingMethod());
  288. $this->phpName = $this->getAttribute("phpName", $this->buildPhpName($this->getStdSeparatedName()));
  289. $this->idMethod = $this->getAttribute("idMethod", $this->getDatabase()->getDefaultIdMethod());
  290. $this->allowPkInsert = $this->booleanValue($this->getAttribute("allowPkInsert"));
  291. $this->skipSql = $this->booleanValue($this->getAttribute("skipSql"));
  292. $this->readOnly = $this->booleanValue($this->getAttribute("readOnly"));
  293. $this->abstractValue = $this->booleanValue($this->getAttribute("abstract"));
  294. $this->baseClass = $this->getAttribute("baseClass");
  295. $this->basePeer = $this->getAttribute("basePeer");
  296. $this->alias = $this->getAttribute("alias");
  297. $this->heavyIndexing = ( $this->booleanValue($this->getAttribute("heavyIndexing"))
  298. || ("false" !== $this->getAttribute("heavyIndexing")
  299. && $this->getDatabase()->isHeavyIndexing() ) );
  300. $this->description = $this->getAttribute("description");
  301. $this->enterface = $this->getAttribute("interface"); // sic ('interface' is reserved word)
  302. $this->treeMode = $this->getAttribute("treeMode");
  303. $this->reloadOnInsert = $this->booleanValue($this->getAttribute("reloadOnInsert"));
  304. $this->reloadOnUpdate = $this->booleanValue($this->getAttribute("reloadOnUpdate"));
  305. $this->isCrossRef = $this->getAttribute("isCrossRef", false);
  306. $this->defaultStringFormat = $this->getAttribute('defaultStringFormat');
  307. }
  308. /**
  309. * get a build property for the database this table belongs to
  310. *
  311. * @param string $key key of the build property
  312. * @return string value of the property
  313. */
  314. public function getBuildProperty($key)
  315. {
  316. return $this->getDatabase() ? $this->getDatabase()->getBuildProperty($key) : '';
  317. }
  318. /**
  319. * Execute behavior table modifiers
  320. */
  321. public function applyBehaviors()
  322. {
  323. foreach ($this->getBehaviors() as $behavior) {
  324. if (!$behavior->isTableModified()) {
  325. $behavior->getTableModifier()->modifyTable();
  326. $behavior->setTableModified(true);
  327. }
  328. }
  329. }
  330. /**
  331. * <p>A hook for the SAX XML parser to call when this table has
  332. * been fully loaded from the XML, and all nested elements have
  333. * been processed.</p>
  334. *
  335. * <p>Performs heavy indexing and naming of elements which weren't
  336. * provided with a name.</p>
  337. */
  338. public function doFinalInitialization()
  339. {
  340. // Heavy indexing must wait until after all columns composing
  341. // a table's primary key have been parsed.
  342. if ($this->heavyIndexing) {
  343. $this->doHeavyIndexing();
  344. }
  345. // Name any indices which are missing a name using the
  346. // appropriate algorithm.
  347. $this->doNaming();
  348. // if idMethod is "native" and in fact there are no autoIncrement
  349. // columns in the table, then change it to "none"
  350. $anyAutoInc = false;
  351. foreach ($this->getColumns() as $col) {
  352. if ($col->isAutoIncrement()) {
  353. $anyAutoInc = true;
  354. }
  355. }
  356. if ($this->getIdMethod() === IDMethod::NATIVE && !$anyAutoInc) {
  357. $this->setIdMethod(IDMethod::NO_ID_METHOD);
  358. }
  359. // If there is no PK, then throw an error. Propel requires primary keys.
  360. if (!$this->hasPrimaryKey()) {
  361. throw new EngineException(sprintf('Table "%s" does not have a primary key defined. Propel requires all tables to have a primary key.', $this->getName()));
  362. }
  363. }
  364. /**
  365. * Adds extra indices for multi-part primary key columns.
  366. *
  367. * For databases like MySQL, values in a where clause much
  368. * match key part order from the left to right. So, in the key
  369. * definition <code>PRIMARY KEY (FOO_ID, BAR_ID)</code>,
  370. * <code>FOO_ID</code> <i>must</i> be the first element used in
  371. * the <code>where</code> clause of the SQL query used against
  372. * this table for the primary key index to be used. This feature
  373. * could cause problems under MySQL with heavily indexed tables,
  374. * as MySQL currently only supports 16 indices per table (i.e. it
  375. * might cause too many indices to be created).
  376. *
  377. * See the mysqm manual http://www.mysql.com/doc/E/X/EXPLAIN.html
  378. * for a better description of why heavy indexing is useful for
  379. * quickly searchable database tables.
  380. */
  381. private function doHeavyIndexing()
  382. {
  383. if (self::DEBUG) {
  384. print("doHeavyIndex() called on table " . $this->getName()."\n");
  385. }
  386. $pk = $this->getPrimaryKey();
  387. $size = count($pk);
  388. // We start at an offset of 1 because the entire column
  389. // list is generally implicitly indexed by the fact that
  390. // it's a primary key.
  391. for ($i=1; $i < $size; $i++) {
  392. $idx = new Index();
  393. $idx->setColumns(array_slice($pk, $i, $size));
  394. $this->addIndex($idx);
  395. }
  396. }
  397. /**
  398. * Adds extra indices for reverse foreign keys
  399. * This is required for MySQL databases,
  400. * and is called from Database::doFinalInitialization()
  401. */
  402. public function addExtraIndices()
  403. {
  404. /**
  405. * A collection of indexed columns. The keys is the column name
  406. * (concatenated with a comma in the case of multi-col index), the value is
  407. * an array with the names of the indexes that index these columns. We use
  408. * it to determine which additional indexes must be created for foreign
  409. * keys. It could also be used to detect duplicate indexes, but this is not
  410. * implemented yet.
  411. * @var array
  412. */
  413. $_indices = array();
  414. $this->collectIndexedColumns('PRIMARY', $this->getPrimaryKey(), $_indices);
  415. $_tableIndices = array_merge($this->getIndices(), $this->getUnices());
  416. foreach ($_tableIndices as $_index) {
  417. $this->collectIndexedColumns($_index->getName(), $_index->getColumns(), $_indices);
  418. }
  419. // we're determining which tables have foreign keys that point to this table,
  420. // since MySQL needs an index on any column that is referenced by another table
  421. // (yep, MySQL _is_ a PITA)
  422. $counter = 0;
  423. foreach ($this->getReferrers() as $foreignKey) {
  424. $referencedColumns = $foreignKey->getForeignColumnObjects();
  425. $referencedColumnsHash = $this->getColumnList($referencedColumns);
  426. if (!array_key_exists($referencedColumnsHash, $_indices)) {
  427. // no matching index defined in the schema, so we have to create one
  428. $index = new Index();
  429. $index->setName(sprintf('I_referenced_%s_%s', $foreignKey->getName(), ++$counter));
  430. $index->setColumns($referencedColumns);
  431. $index->resetColumnSize();
  432. $this->addIndex($index);
  433. // Add this new index to our collection, otherwise we might add it again (bug #725)
  434. $this->collectIndexedColumns($index->getName(), $referencedColumns, $_indices);
  435. }
  436. }
  437. // we're adding indices for this table foreign keys
  438. foreach ($this->getForeignKeys() as $foreignKey) {
  439. $localColumns = $foreignKey->getLocalColumnObjects();
  440. $localColumnsHash = $this->getColumnList($localColumns);
  441. if (!array_key_exists($localColumnsHash, $_indices)) {
  442. // no matching index defined in the schema, so we have to create one. MySQL needs indices on any columns that serve as foreign keys. these are not auto-created prior to 4.1.2
  443. $index = new Index();
  444. $index->setName(substr_replace($foreignKey->getName(), 'FI_', strrpos($foreignKey->getName(), 'FK_'), 3));
  445. $index->setColumns($localColumns);
  446. $index->resetColumnSize();
  447. $this->addIndex($index);
  448. $this->collectIndexedColumns($index->getName(), $localColumns, $_indices);
  449. }
  450. }
  451. }
  452. /**
  453. * Helper function to collect indexed columns.
  454. *
  455. * @param string $indexName The name of the index
  456. * @param array $columns The column names or objects
  457. * @param array $collectedIndexes The collected indexes
  458. */
  459. protected function collectIndexedColumns($indexName, $columns, &$collectedIndexes)
  460. {
  461. /**
  462. * "If the table has a multiple-column index, any leftmost prefix of the
  463. * index can be used by the optimizer to find rows. For example, if you
  464. * have a three-column index on (col1, col2, col3), you have indexed search
  465. * capabilities on (col1), (col1, col2), and (col1, col2, col3)."
  466. * @link http://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html
  467. */
  468. $indexedColumns = array();
  469. foreach ($columns as $column) {
  470. $indexedColumns[] = $column;
  471. $indexedColumnsHash = $this->getColumnList($indexedColumns);
  472. if (!array_key_exists($indexedColumnsHash, $collectedIndexes)) {
  473. $collectedIndexes[$indexedColumnsHash] = array();
  474. }
  475. $collectedIndexes[$indexedColumnsHash][] = $indexName;
  476. }
  477. }
  478. /**
  479. * Creates a delimiter-delimited string list of column names
  480. *
  481. * @see Platform::getColumnList() if quoting is required
  482. * @param array Column[] or string[]
  483. * @param string $delim The delimiter to use in separating the column names.
  484. * @return string
  485. */
  486. public function getColumnList($columns, $delim = ',')
  487. {
  488. $list = array();
  489. foreach ($columns as $col) {
  490. if ($col instanceof Column) {
  491. $col = $col->getName();
  492. }
  493. $list[] = $col;
  494. }
  495. return implode($delim, $list);
  496. }
  497. /**
  498. * Names composing objects which haven't yet been named. This
  499. * currently consists of foreign-key and index entities.
  500. */
  501. public function doNaming() {
  502. // Assure names are unique across all databases.
  503. try {
  504. for ($i=0, $size = count($this->foreignKeys); $i < $size; $i++) {
  505. $fk = $this->foreignKeys[$i];
  506. $name = $fk->getName();
  507. if (empty($name)) {
  508. $name = $this->acquireConstraintName("FK", $i + 1);
  509. $fk->setName($name);
  510. }
  511. }
  512. for ($i = 0, $size = count($this->indices); $i < $size; $i++) {
  513. $index = $this->indices[$i];
  514. $name = $index->getName();
  515. if (empty($name)) {
  516. $name = $this->acquireConstraintName("I", $i + 1);
  517. $index->setName($name);
  518. }
  519. }
  520. for ($i = 0, $size = count($this->unices); $i < $size; $i++) {
  521. $index = $this->unices[$i];
  522. $name = $index->getName();
  523. if (empty($name)) {
  524. $name = $this->acquireConstraintName("U", $i + 1);
  525. $index->setName($name);
  526. }
  527. }
  528. // NOTE: Most RDBMSes can apparently name unique column
  529. // constraints/indices themselves (using MySQL and Oracle
  530. // as test cases), so we'll assume that we needn't add an
  531. // entry to the system name list for these.
  532. } catch (EngineException $nameAlreadyInUse) {
  533. print $nameAlreadyInUse->getMessage() . "\n";
  534. print $nameAlreadyInUse->getTraceAsString();
  535. }
  536. }
  537. /**
  538. * Macro to a constraint name.
  539. *
  540. * @param nameType constraint type
  541. * @param nbr unique number for this constraint type
  542. * @return unique name for constraint
  543. * @throws EngineException
  544. */
  545. private function acquireConstraintName($nameType, $nbr)
  546. {
  547. $inputs = array();
  548. $inputs[] = $this->getDatabase();
  549. $inputs[] = $this->getCommonName();
  550. $inputs[] = $nameType;
  551. $inputs[] = $nbr;
  552. return NameFactory::generateName(NameFactory::CONSTRAINT_GENERATOR, $inputs);
  553. }
  554. /**
  555. * Gets the value of base class for classes produced from this table.
  556. *
  557. * @return The base class for classes produced from this table.
  558. */
  559. public function getBaseClass()
  560. {
  561. if ($this->isAlias() && $this->baseClass === null) {
  562. return $this->alias;
  563. } elseif ($this->baseClass === null) {
  564. return $this->getDatabase()->getBaseClass();
  565. } else {
  566. return $this->baseClass;
  567. }
  568. }
  569. /**
  570. * Set the value of baseClass.
  571. * @param v Value to assign to baseClass.
  572. */
  573. public function setBaseClass($v)
  574. {
  575. $this->baseClass = $v;
  576. }
  577. /**
  578. * Get the value of basePeer.
  579. * @return value of basePeer.
  580. */
  581. public function getBasePeer()
  582. {
  583. if ($this->isAlias() && $this->basePeer === null) {
  584. return $this->alias . "Peer";
  585. } elseif ($this->basePeer === null) {
  586. return $this->getDatabase()->getBasePeer();
  587. } else {
  588. return $this->basePeer;
  589. }
  590. }
  591. /**
  592. * Set the value of basePeer.
  593. * @param v Value to assign to basePeer.
  594. */
  595. public function setBasePeer($v)
  596. {
  597. $this->basePeer = $v;
  598. }
  599. /**
  600. * A utility function to create a new column from attrib and add it to this
  601. * table.
  602. *
  603. * @param $coldata xml attributes or Column class for the column to add
  604. * @return the added column
  605. */
  606. public function addColumn($data)
  607. {
  608. if ($data instanceof Column) {
  609. $col = $data;
  610. $col->setTable($this);
  611. if ($col->isInheritance()) {
  612. $this->inheritanceColumn = $col;
  613. }
  614. if (isset($this->columnsByName[$col->getName()])) {
  615. throw new EngineException('Duplicate column declared: ' . $col->getName());
  616. }
  617. $this->columnList[] = $col;
  618. $this->columnsByName[$col->getName()] = $col;
  619. $this->columnsByLowercaseName[strtolower($col->getName())] = $col;
  620. $this->columnsByPhpName[$col->getPhpName()] = $col;
  621. $col->setPosition(count($this->columnList));
  622. $this->needsTransactionInPostgres |= $col->requiresTransactionInPostgres();
  623. return $col;
  624. } else {
  625. $col = new Column();
  626. $col->setTable($this);
  627. $col->loadFromXML($data);
  628. return $this->addColumn($col); // call self w/ different param
  629. }
  630. }
  631. /**
  632. * Removed a column from the table
  633. * @param Column|string $col the column to remove
  634. */
  635. public function removeColumn($col)
  636. {
  637. if (is_string($col)) {
  638. $col = $this->getColumn($col);
  639. }
  640. $pos = array_search($col, $this->columnList);
  641. if(false === $pos) {
  642. throw new EngineException(sprintf('No column named %s found in table %s', $col->getName(), $table->getName()));
  643. }
  644. unset($this->columnList[$pos]);
  645. unset($this->columnsByName[$col->getName()]);
  646. unset($this->columnsByLowercaseName[strtolower($col->getName())]);
  647. unset($this->columnsByPhpName[$col->getPhpName()]);
  648. $this->adjustColumnPositions();
  649. // FIXME: also remove indexes and validators on this column?
  650. }
  651. public function adjustColumnPositions()
  652. {
  653. $this->columnList = array_values($this->columnList);
  654. $columnCount = $this->getNumColumns();
  655. for ($i=0; $i < $columnCount; $i++) {
  656. $this->columnList[$i]->setPosition($i + 1);
  657. }
  658. }
  659. /**
  660. * Add a validator to this table.
  661. *
  662. * Supports two signatures:
  663. * - addValidator(Validator $validator)
  664. * - addValidator(array $attribs)
  665. *
  666. * @param mixed $data Validator object or XML attribs (array) from <validator /> element.
  667. * @return Validator The added Validator.
  668. * @throws EngineException
  669. */
  670. public function addValidator($data)
  671. {
  672. if ($data instanceof Validator) {
  673. $validator = $data;
  674. $col = $this->getColumn($validator->getColumnName());
  675. if ($col == null) {
  676. throw new EngineException("Failed adding validator to table '" . $this->getName() .
  677. "': column '" . $validator->getColumnName() . "' does not exist !");
  678. }
  679. $validator->setColumn($col);
  680. $validator->setTable($this);
  681. $this->validatorList[] = $validator;
  682. return $validator;
  683. } else {
  684. $validator = new Validator();
  685. $validator->setTable($this);
  686. $validator->loadFromXML($data);
  687. return $this->addValidator($validator);
  688. }
  689. }
  690. /**
  691. * Removes validators based on a column name
  692. *
  693. * @param string the name of the column bearing a validator
  694. */
  695. public function removeValidatorForColumn($columnName)
  696. {
  697. foreach ($this->validatorList as $key => $validator) {
  698. if ($validator->getColumnName() == $columnName) {
  699. unset($this->validatorList[$key]);
  700. }
  701. }
  702. }
  703. /**
  704. * A utility function to create a new foreign key
  705. * from attrib and add it to this table.
  706. */
  707. public function addForeignKey($fkdata)
  708. {
  709. if ($fkdata instanceof ForeignKey) {
  710. $fk = $fkdata;
  711. $fk->setTable($this);
  712. $this->foreignKeys[] = $fk;
  713. if ($this->foreignTableNames === null) {
  714. $this->foreignTableNames = array();
  715. }
  716. if (!in_array($fk->getForeignTableName(), $this->foreignTableNames)) {
  717. $this->foreignTableNames[] = $fk->getForeignTableName();
  718. }
  719. return $fk;
  720. } else {
  721. $fk = new ForeignKey();
  722. $fk->setTable($this);
  723. $fk->loadFromXML($fkdata);
  724. return $this->addForeignKey($fk);
  725. }
  726. }
  727. /**
  728. * Gets the column that subclasses of the class representing this
  729. * table can be produced from.
  730. * @return Column
  731. */
  732. public function getChildrenColumn()
  733. {
  734. return $this->inheritanceColumn;
  735. }
  736. /**
  737. * Get the subclasses that can be created from this table.
  738. * @return array string[] Class names
  739. */
  740. public function getChildrenNames()
  741. {
  742. if ($this->inheritanceColumn === null
  743. || !$this->inheritanceColumn->isEnumeratedClasses()) {
  744. return null;
  745. }
  746. $children = $this->inheritanceColumn->getChildren();
  747. $names = array();
  748. for ($i = 0, $size=count($children); $i < $size; $i++) {
  749. $names[] = get_class($children[$i]);
  750. }
  751. return $names;
  752. }
  753. /**
  754. * Adds the foreign key from another table that refers to this table.
  755. */
  756. public function addReferrer(ForeignKey $fk)
  757. {
  758. if ($this->referrers === null) {
  759. $this->referrers = array();
  760. }
  761. $this->referrers[] = $fk;
  762. }
  763. /**
  764. * Get list of references to this table.
  765. */
  766. public function getReferrers()
  767. {
  768. return $this->referrers;
  769. }
  770. /**
  771. * Browses the foreign keys and creates referrers for the foreign table.
  772. * This method can be called several times on the same table. It only
  773. * adds the missing referrers and is non-destructive.
  774. * Warning: only use when all the tables were created.
  775. */
  776. public function setupReferrers($throwErrors = false)
  777. {
  778. foreach ($this->getForeignKeys() as $foreignKey) {
  779. // table referrers
  780. $foreignTable = $this->getDatabase()->getTable($foreignKey->getForeignTableName());
  781. if ($foreignTable !== null) {
  782. $referrers = $foreignTable->getReferrers();
  783. if ($referrers === null || !in_array($foreignKey, $referrers, true) ) {
  784. $foreignTable->addReferrer($foreignKey);
  785. }
  786. } elseif ($throwErrors) {
  787. throw new BuildException(sprintf(
  788. 'Table "%s" contains a foreign key to nonexistent table "%s"',
  789. $this->getName(),
  790. $foreignKey->getForeignTableName()
  791. ));
  792. }
  793. // foreign pk's
  794. $localColumnNames = $foreignKey->getLocalColumns();
  795. foreach ($localColumnNames as $localColumnName) {
  796. $localColumn = $this->getColumn($localColumnName);
  797. if ($localColumn !== null) {
  798. if ($localColumn->isPrimaryKey() && !$this->getContainsForeignPK()) {
  799. $this->setContainsForeignPK(true);
  800. }
  801. } elseif ($throwErrors) {
  802. // give notice of a schema inconsistency.
  803. // note we do not prevent the npe as there is nothing
  804. // that we can do, if it is to occur.
  805. throw new BuildException(sprintf(
  806. 'Table "%s" contains a foreign key with nonexistent local column "%s"',
  807. $this->getName(),
  808. $localColumnName
  809. ));
  810. }
  811. }
  812. // foreign column references
  813. $foreignColumnNames = $foreignKey->getForeignColumns();
  814. foreach ($foreignColumnNames as $foreignColumnName) {
  815. if ($foreignTable === null) {
  816. continue;
  817. }
  818. $foreignColumn = $foreignTable->getColumn($foreignColumnName);
  819. if ($foreignColumn !== null) {
  820. if (!$foreignColumn->hasReferrer($foreignKey)) {
  821. $foreignColumn->addReferrer($foreignKey);
  822. }
  823. } elseif ($throwErrors) {
  824. // if the foreign column does not exist, we may have an
  825. // external reference or a misspelling
  826. throw new BuildException(sprintf(
  827. 'Table "%s" contains a foreign key to table "%s" with nonexistent column "%s"',
  828. $this->getName(),
  829. $foreignTable->getName(),
  830. $foreignColumnName
  831. ));
  832. }
  833. }
  834. if ($this->getDatabase()->getPlatform() instanceof MysqlPLatform) {
  835. $this->addExtraIndices();
  836. }
  837. } // foreach foreign keys
  838. }
  839. public function getCrossFks()
  840. {
  841. $crossFks = array();
  842. foreach ($this->getReferrers() as $refFK) {
  843. if ($refFK->getTable()->getIsCrossRef()) {
  844. foreach ($refFK->getOtherFks() as $crossFK) {
  845. $crossFks[]= array($refFK, $crossFK);
  846. }
  847. }
  848. }
  849. return $crossFks;
  850. }
  851. /**
  852. * Set whether this table contains a foreign PK
  853. */
  854. public function setContainsForeignPK($b)
  855. {
  856. $this->containsForeignPK = (boolean) $b;
  857. }
  858. /**
  859. * Determine if this table contains a foreign PK
  860. */
  861. public function getContainsForeignPK()
  862. {
  863. return $this->containsForeignPK;
  864. }
  865. /**
  866. * A list of tables referenced by foreign keys in this table
  867. */
  868. public function getForeignTableNames()
  869. {
  870. if ($this->foreignTableNames === null) {
  871. $this->foreignTableNames = array();
  872. }
  873. return $this->foreignTableNames;
  874. }
  875. /**
  876. * Return true if the column requires a transaction in Postgres
  877. */
  878. public function requiresTransactionInPostgres()
  879. {
  880. return $this->needsTransactionInPostgres;
  881. }
  882. /**
  883. * A utility function to create a new id method parameter
  884. * from attrib or object and add it to this table.
  885. */
  886. public function addIdMethodParameter($impdata)
  887. {
  888. if ($impdata instanceof IdMethodParameter) {
  889. $imp = $impdata;
  890. $imp->setTable($this);
  891. if ($this->idMethodParameters === null) {
  892. $this->idMethodParameters = array();
  893. }
  894. $this->idMethodParameters[] = $imp;
  895. return $imp;
  896. } else {
  897. $imp = new IdMethodParameter();
  898. $imp->loadFromXML($impdata);
  899. return $this->addIdMethodParameter($imp); // call self w/ diff param
  900. }
  901. }
  902. /**
  903. * Adds a new index to the index list and set the
  904. * parent table of the column to the current table
  905. */
  906. public function addIndex($idxdata)
  907. {
  908. if ($idxdata instanceof Index) {
  909. $index = $idxdata;
  910. $index->setTable($this);
  911. $index->getName(); // we call this method so that the name is created now if it doesn't already exist.
  912. $this->indices[] = $index;
  913. return $index;
  914. } else {
  915. $index = new Index($this);
  916. $index->loadFromXML($idxdata);
  917. return $this->addIndex($index);
  918. }
  919. }
  920. /**
  921. * Adds a new Unique to the Unique list and set the
  922. * parent table of the column to the current table
  923. */
  924. public function addUnique($unqdata)
  925. {
  926. if ($unqdata instanceof Unique) {
  927. $unique = $unqdata;
  928. $unique->setTable($this);
  929. $unique->getName(); // we call this method so that the name is created now if it doesn't already exist.
  930. $this->unices[] = $unique;
  931. return $unique;
  932. } else {
  933. $unique = new Unique($this);
  934. $unique->loadFromXML($unqdata);
  935. return $this->addUnique($unique);
  936. }
  937. }
  938. /**
  939. * Retrieves the configuration object, filled by build.properties
  940. *
  941. * @return GeneratorConfig
  942. */
  943. public function getGeneratorConfig()
  944. {
  945. return $this->getDatabase()->getAppData()->getGeneratorConfig();
  946. }
  947. /**
  948. * Adds a new Behavior to the table
  949. * @return Behavior A behavior instance
  950. */
  951. public function addBehavior($bdata)
  952. {
  953. if ($bdata instanceof Behavior) {
  954. $behavior = $bdata;
  955. $behavior->setTable($this);
  956. $this->behaviors[$behavior->getName()] = $behavior;
  957. return $behavior;
  958. } else {
  959. $class = $this->getConfiguredBehavior($bdata['name']);
  960. $behavior = new $class();
  961. $behavior->loadFromXML($bdata);
  962. return $this->addBehavior($behavior);
  963. }
  964. }
  965. /**
  966. * Get the table behaviors
  967. * @return Array of Behavior objects
  968. */
  969. public function getBehaviors()
  970. {
  971. return $this->behaviors;
  972. }
  973. /**
  974. * Get the early table behaviors
  975. * @return Array of Behavior objects
  976. */
  977. public function getEarlyBehaviors()
  978. {
  979. $behaviors = array();
  980. foreach ($this->behaviors as $name => $behavior) {
  981. if ($behavior->isEarly()) {
  982. $behaviors[$name] = $behavior;
  983. }
  984. }
  985. return $behaviors;
  986. }
  987. /**
  988. * check if the table has a behavior by name
  989. *
  990. * @param string $name the behavior name
  991. * @return boolean True if the behavior exists
  992. */
  993. public function hasBehavior($name)
  994. {
  995. return array_key_exists($name, $this->behaviors);
  996. }
  997. /**
  998. * Get one table behavior by name
  999. *
  1000. * @param string $name the behavior name
  1001. * @return Behavior a behavior object
  1002. */
  1003. public function getBehavior($name)
  1004. {
  1005. return $this->behaviors[$name];
  1006. }
  1007. /**
  1008. * Check whether one of the table behaviors offer an additional builder
  1009. *
  1010. * @return boolean true in the table has at least one behavior
  1011. * with an additional builder, false otherwise
  1012. */
  1013. public function hasAdditionalBuilders()
  1014. {
  1015. foreach ($this->getBehaviors() as $behavior) {
  1016. if ($behavior->hasAdditionalBuilders()) {
  1017. return true;
  1018. }
  1019. }
  1020. return false;
  1021. }
  1022. /**
  1023. * Get the additional builders provided by the table behaviors
  1024. *
  1025. * @return array list of builder class names
  1026. */
  1027. public function getAdditionalBuilders()
  1028. {
  1029. $additionalBuilders = array();
  1030. foreach ($this->getBehaviors() as $behavior) {
  1031. $additionalBuilders = array_merge($additionalBuilders, $behavior->getAdditionalBuilders());
  1032. }
  1033. return $additionalBuilders;
  1034. }
  1035. /**
  1036. * Get the name of the Table
  1037. */
  1038. public function getName()
  1039. {
  1040. if ($this->schema && $this->getDatabase() && $this->getDatabase()->getPlatform() &&
  1041. $this->getDatabase()->getPlatform()->supportsSchemas()) {
  1042. return $this->schema . '.' . $this->commonName;
  1043. } else {
  1044. return $this->commonName;
  1045. }
  1046. }
  1047. /**
  1048. * Get the description for the Table
  1049. */
  1050. public function getDescription()
  1051. {
  1052. return $this->description;
  1053. }
  1054. /**
  1055. * Whether the Table has a description
  1056. */
  1057. public function hasDescription()
  1058. {
  1059. return (bool) $this->description;
  1060. }
  1061. /**
  1062. * Set the description for the Table
  1063. *
  1064. * @param newDescription description for the Table
  1065. */
  1066. public function setDescription($newDescription)
  1067. {
  1068. $this->description = $newDescription;
  1069. }
  1070. /**
  1071. * Get name to use in PHP sources
  1072. * @return string
  1073. */
  1074. public function getPhpName()
  1075. {
  1076. if ($this->phpName === null) {
  1077. $inputs = array();
  1078. $inputs[] = $this->getStdSeparatedName();
  1079. $inputs[] = $this->phpNamingMethod;
  1080. try {
  1081. $this->phpName = NameFactory::generateName(NameFactory::PHP_GENERATOR, $inputs);
  1082. } catch (EngineException $e) {
  1083. print $e->getMessage() . "\n";
  1084. print $e->getTraceAsString();
  1085. }
  1086. }
  1087. return $this->phpName;
  1088. }
  1089. /**
  1090. * Set name to use in PHP sources
  1091. * @param string $phpName
  1092. */
  1093. public function setPhpName($phpName)
  1094. {
  1095. $this->phpName = $phpName;
  1096. }
  1097. public function buildPhpName($name)
  1098. {
  1099. return NameFactory::generateName(NameFactory::PHP_GENERATOR, array($name, $this->phpNamingMethod));
  1100. }
  1101. /**
  1102. * Get studly version of PHP name.
  1103. *
  1104. * The studly name is the PHP name with the first character lowercase.
  1105. *
  1106. * @return string
  1107. */
  1108. public function getStudlyPhpName()
  1109. {
  1110. $phpname = $this->getPhpName();
  1111. if (strlen($phpname) > 1) {
  1112. return strtolower(substr($phpname, 0, 1)) . substr($phpname, 1);
  1113. } else { // 0 or 1 chars (I suppose that's rare)
  1114. return strtolower($phpname);
  1115. }
  1116. }
  1117. /**
  1118. * Get the name without schema
  1119. */
  1120. public function getCommonName()
  1121. {
  1122. return $this->commonName;
  1123. }
  1124. /**
  1125. * Set the common name of the table (without schema)
  1126. */
  1127. public function setCommonName($v)
  1128. {
  1129. $this->commonName = $v;
  1130. }
  1131. /**
  1132. * Set the default string format for ActiveRecord objects in this Table.
  1133. *
  1134. * @param string $defaultStringFormat Any of 'XML', 'YAML', 'JSON', or 'CSV'
  1135. */
  1136. public function setDefaultStringFormat($defaultStringFormat)
  1137. {
  1138. $this->defaultStringFormat = $defaultStringFormat;
  1139. }
  1140. /**
  1141. * Get the default string format for ActiveRecord objects in this Table,
  1142. * or the one for the whole database if not set.
  1143. *
  1144. * @return string The default string representation
  1145. */
  1146. public function getDefaultStringFormat()
  1147. {
  1148. if (!$this->defaultStringFormat && $this->getDatabase() && $this->getDatabase()->getDefaultStringFormat()) {
  1149. return $this->getDatabase()->getDefaultStringFormat();
  1150. }
  1151. return $this->defaultStringFormat;
  1152. }
  1153. /**
  1154. * Get the method for generating pk's
  1155. * [HL] changing behavior so that Database default method is returned
  1156. * if no method has been specified for the table.
  1157. *
  1158. * @return string
  1159. */
  1160. public function getIdMethod()
  1161. {
  1162. if ($this->idMethod === null) {
  1163. return IDMethod::NO_ID_METHOD;
  1164. } else {
  1165. return $this->idMethod;
  1166. }
  1167. }
  1168. /**
  1169. * Whether we allow to insert primary keys on tables with
  1170. * idMethod=native
  1171. *
  1172. * @return boolean
  1173. */
  1174. public function isAllowPkInsert()
  1175. {
  1176. return $this->allowPkInsert;
  1177. }
  1178. /**
  1179. * Set the method for generating pk's
  1180. */
  1181. public function setIdMethod($idMethod)
  1182. {
  1183. $this->idMethod = $idMethod;
  1184. }
  1185. /**
  1186. * Skip generating sql for this table (in the event it should
  1187. * not be created from scratch).
  1188. * @return boolean Value of skipSql.
  1189. */
  1190. public function isSkipSql()
  1191. {
  1192. return ($this->skipSql || $this->isAlias() || $this->isForReferenceOnly());
  1193. }
  1194. /**
  1195. * Is table read-only, in which case only accessors (and relationship setters)
  1196. * will be created.
  1197. * @return boolan Value of readOnly.
  1198. */
  1199. public function isReadOnly()
  1200. {
  1201. return $this->readOnly;
  1202. }
  1203. /**
  1204. * Set whether this table should have its creation sql generated.
  1205. * @param boolean $v Value to assign to skipSql.
  1206. */
  1207. public function setSkipSql($v)
  1208. {
  1209. $this->skipSql = $v;
  1210. }
  1211. /**
  1212. * Whether to force object to reload on INSERT.
  1213. * @return boolean
  1214. */
  1215. public function isReloadOnInsert()
  1216. {
  1217. return $this->reloadOnInsert;
  1218. }
  1219. /**
  1220. * Whether to force object to reload on UPDATE.
  1221. * @return boolean
  1222. */
  1223. public function isReloadOnUpdate()
  1224. {
  1225. return $this->reloadOnUpdate;
  1226. }
  1227. /**
  1228. * PhpName of om object this entry references.
  1229. * @return value of external.
  1230. */
  1231. public function getAlias()
  1232. {
  1233. return $this->alias;
  1234. }
  1235. /**
  1236. * Is this table specified in the schema or is there just
  1237. * a foreign key reference to it.
  1238. * @return value of external.
  1239. */
  1240. public function isAlias()
  1241. {
  1242. return ($this->alias !== null);
  1243. }
  1244. /**
  1245. * Set whether this table specified in the schema or is there just
  1246. * a foreign key reference to it.
  1247. * @param v Value to assign to alias.
  1248. */
  1249. public function setAlias($v)
  1250. {
  1251. $this->alias = $v;
  1252. }
  1253. /**
  1254. * Interface which objects for this table will implement
  1255. * @return value of interface.
  1256. */
  1257. public function getInterface()
  1258. {
  1259. return $this->enterface;
  1260. }
  1261. /**
  1262. * Interface which objects for this table will implement
  1263. * @param v Value to assign to interface.
  1264. */
  1265. public function setInterface($v)
  1266. {
  1267. $this->enterface = $v;
  1268. }
  1269. /**
  1270. * When a table is abstract, it marks the business object class that is
  1271. * generated as being abstract. If you have a table called "FOO", then the
  1272. * Foo BO will be <code>public abstract class Foo</code>
  1273. * This helps support class hierarchies
  1274. *
  1275. * @return value of abstractValue.
  1276. */
  1277. public function isAbstract()
  1278. {
  1279. return $this->abstractValue;
  1280. }
  1281. /**
  1282. * When a table is abstract, it marks the business object
  1283. * class that is generated as being abstract. If you have a
  1284. * table called "FOO", then the Foo BO will be
  1285. * <code>public abstract class Foo</code>
  1286. * This helps support class hierarchies
  1287. *
  1288. * @param v Value to assign to abstractValue.
  1289. */
  1290. public function setAbstract($v)
  1291. {
  1292. $this->abstractValue = (boolean) $v;
  1293. }
  1294. /**
  1295. * Returns an Array containing all the columns in the table
  1296. * @return array Column[]
  1297. */
  1298. public function getColumns()
  1299. {
  1300. return $this->columnList;
  1301. }
  1302. /**
  1303. * Utility method to get the number of columns in this table
  1304. */
  1305. public function getNumColumns()
  1306. {
  1307. return count($this->columnList);
  1308. }
  1309. /**
  1310. * Utility method to get the number of columns in this table
  1311. */
  1312. public function getNumLazyLoadColumns()
  1313. {
  1314. $count = 0;
  1315. foreach ($this->columnList as $col) {
  1316. if ($col->isLazyLoad()) {
  1317. $count++;
  1318. }
  1319. }
  1320. return $count;
  1321. }
  1322. /**
  1323. * Checks whether one of the columns is of type ENUM
  1324. * @return boolean
  1325. */
  1326. public function hasEnumColumns()
  1327. {
  1328. foreach ($this->getColumns() as $col) {
  1329. if ($col->isEnumType()) {
  1330. return true;
  1331. }
  1332. }
  1333. return false;
  1334. }
  1335. /**
  1336. * Returns an Array containing all the validators in the table
  1337. * @return array Validator[]
  1338. */
  1339. public function getValidators()
  1340. {
  1341. return $this->validatorList;
  1342. }
  1343. /**
  1344. * Returns an Array containing all the FKs in the table.
  1345. * @return array ForeignKey[]
  1346. */
  1347. public function getForeignKeys()
  1348. {
  1349. return $this->foreignKeys;
  1350. }
  1351. /**
  1352. * Returns a Collection of parameters relevant for the chosen
  1353. * id generation method.
  1354. */
  1355. public function getIdMethodParameters()
  1356. {
  1357. return $this->idMethodParameters;
  1358. }
  1359. /**
  1360. * Returns an Array containing all the FKs in the table
  1361. * @return array Index[]
  1362. */
  1363. public function getIndices()
  1364. {
  1365. return $this->indices;
  1366. }
  1367. /**
  1368. * Returns an Array containing all the UKs in the table
  1369. * @return array Unique[]
  1370. */
  1371. public function getUnices()
  1372. {
  1373. return $this->unices;
  1374. }
  1375. /**
  1376. * Check whether the table has a column.
  1377. * @param Column|string $col the column object or name (e.g. 'my_column')
  1378. * @param boolean $caseInsensitive Whether the check is case insensitive. False by default.
  1379. *
  1380. * @return boolean
  1381. */
  1382. public function hasColumn($col, $caseInsensitive = false)
  1383. {
  1384. if ($col instanceof Column) {
  1385. $col = $col->getName();
  1386. }
  1387. if ($caseInsensitive) {
  1388. return array_key_exists(strtolower($col), $this->columnsByLowercaseName);
  1389. } else {
  1390. return array_key_exists($col, $this->columnsByName);
  1391. }
  1392. }
  1393. /**
  1394. * Return the column with the specified name.
  1395. * @param string $name The name of the column (e.g. 'my_column')
  1396. * @param boolean $caseInsensitive Whether the check is case insensitive. False by default.
  1397. *
  1398. * @return Column a Column object or null if it doesn't exist
  1399. */
  1400. public function getColumn($name, $caseInsensitive = false)
  1401. {
  1402. if ($this->hasColumn($name, $caseInsensitive)) {
  1403. if ($caseInsensitive) {
  1404. return $this->columnsByLowercaseName[strtolower($name)];
  1405. } else {
  1406. return $this->columnsByName[$name];
  1407. }
  1408. }
  1409. return null; // just to be explicit
  1410. }
  1411. /**
  1412. * Returns a specified column.
  1413. * @return Column Return a Column object or null if it does not exist.
  1414. */
  1415. public function getColumnByPhpName($phpName)
  1416. {
  1417. if (isset($this->columnsByPhpName[$phpName])) {
  1418. return $this->columnsByPhpName[$phpName];
  1419. }
  1420. return null; // just to be explicit
  1421. }
  1422. /**
  1423. * Get all the foreign keys from this table to the specified table.
  1424. * @return array ForeignKey[]
  1425. */
  1426. public function getForeignKeysReferencingTable($tablename)
  1427. {
  1428. $matches = array();
  1429. $keys = $this->getForeignKeys();
  1430. foreach ($keys as $fk) {
  1431. if ($fk->getForeignTableName() === $tablename) {
  1432. $matches[] = $fk;
  1433. }
  1434. }
  1435. return $matches;
  1436. }
  1437. /**
  1438. * Return the foreign keys that includes col in it's list of local columns.
  1439. * Eg. Foreign key (a,b,c) refrences tbl(x,y,z) will be returned of col is either a,b or c.
  1440. * @param string $col
  1441. * @return array ForeignKey[] or null if there is no FK for specified column.
  1442. */
  1443. public function getColumnForeignKeys($colname)
  1444. {
  1445. $matches = array();
  1446. foreach ($this->foreignKeys as $fk) {
  1447. if (in_array($colname, $fk->getLocalColumns())) {
  1448. $matches[] = $fk;
  1449. }
  1450. }
  1451. return $matches;
  1452. }
  1453. /**
  1454. * Check whether the table has a column.
  1455. * @param Column|string $col the column object or name (e.g. 'my_column')
  1456. * @deprecated use hasColumn() instead
  1457. * @return boolean
  1458. */
  1459. public function containsColumn($col)
  1460. {
  1461. return $this->hasColumn($col);
  1462. }
  1463. /**
  1464. * Set the database that contains this table.
  1465. *
  1466. * @param Database $db
  1467. */
  1468. public function setDatabase(Database $db)
  1469. {
  1470. $this->database = $db;
  1471. }
  1472. /**
  1473. * Get the database that contains this table.
  1474. *
  1475. * @return Database
  1476. */
  1477. public function getDatabase()
  1478. {
  1479. return $this->database;
  1480. }
  1481. /**
  1482. * Flag to determine if code/sql gets created for this table.
  1483. * Table will be skipped, if return true.
  1484. * @return boolean
  1485. */
  1486. public function isForReferenceOnly()
  1487. {
  1488. return $this->forReferenceOnly;
  1489. }
  1490. /**
  1491. * Flag to determine if code/sql gets created for this table.
  1492. * Table will be skipped, if set to true.
  1493. * @param boolean $v
  1494. */
  1495. public function setForReferenceOnly($v)
  1496. {
  1497. $this->forReferenceOnly = (boolean) $v;
  1498. }
  1499. /**
  1500. * Flag to determine if tree node class should be generated for this table.
  1501. * @return valur of treeMode
  1502. */
  1503. public function treeMode()
  1504. {
  1505. return $this->treeMode;
  1506. }
  1507. /**
  1508. * Flag to determine if tree node class should be generated for this table.
  1509. * @param v Value to assign to treeMode.
  1510. */
  1511. public function setTreeMode($v)
  1512. {
  1513. $this->treeMode = $v;
  1514. }
  1515. /**
  1516. * Appends XML nodes to passed-in DOMNode.
  1517. *
  1518. * @param DOMNode $node
  1519. */
  1520. public function appendXml(DOMNode $node)
  1521. {
  1522. $doc = ($node instanceof DOMDocument) ? $node : $node->ownerDocument;
  1523. $tableNode = $node->appendChild($doc->createElement('table'));
  1524. $tableNode->setAttribute('name', $this->getCommonName());
  1525. if ($this->getSchema() !== null) {
  1526. $tableNode->setAttribute('schema', $this->getSchema());
  1527. }
  1528. if ($this->phpName !== null) {
  1529. $tableNode->setAttribute('phpName', $this->phpName);
  1530. }
  1531. if ($this->idMethod !== null) {
  1532. $tableNode->setAttribute('idMethod', $this->idMethod);
  1533. }
  1534. if ($this->skipSql !== null) {
  1535. $tableNode->setAttribute('idMethod', var_export($this->skipSql, true));
  1536. }
  1537. if ($this->readOnly !== null) {
  1538. $tableNode->setAttribute('readOnly', var_export($this->readOnly, true));
  1539. }
  1540. if ($this->treeMode !== null) {
  1541. $tableNode->setAttribute('treeMode', $this->treeMode);
  1542. }
  1543. if ($this->reloadOnInsert !== null) {
  1544. $tableNode->setAttribute('reloadOnInsert', var_export($this->reloadOnInsert, true));
  1545. }
  1546. if ($this->reloadOnUpdate !== null) {
  1547. $tableNode->setAttribute('reloadOnUpdate', var_export($this->reloadOnUpdate, true));
  1548. }
  1549. if ($this->forReferenceOnly !== null) {
  1550. $tableNode->setAttribute('forReferenceOnly', var_export($this->forReferenceOnly, true));
  1551. }
  1552. if ($this->abstractValue !== null) {
  1553. $tableNode->setAttribute('abstract', var_export($this->abstractValue, true));
  1554. }
  1555. if ($this->enterface !== null) {
  1556. $tableNode->setAttribute('interface', $this->enterface);
  1557. }
  1558. if ($this->description !== null) {
  1559. $tableNode->setAttribute('description', $this->description);
  1560. }
  1561. if ($this->namespace !== null) {
  1562. $tableNode->setAttribute('namespace', $this->namespace);
  1563. }
  1564. if ($this->pkg !== null && !$this->pkgOverridden) {
  1565. $tableNode->setAttribute('package', $this->pkg);
  1566. }
  1567. if ($this->baseClass !== null) {
  1568. $tableNode->setAttribute('baseClass', $this->baseClass);
  1569. }
  1570. if ($this->basePeer !== null) {
  1571. $tableNode->setAttribute('basePeer', $this->basePeer);
  1572. }
  1573. if ($this->getIsCrossRef()) {
  1574. $tableNode->setAttribute('isCrossRef', $this->getIsCrossRef());
  1575. }
  1576. foreach ($this->columnList as $col) {
  1577. $col->appendXml($tableNode);
  1578. }
  1579. foreach ($this->validatorList as $validator) {
  1580. $validator->appendXml($tableNode);
  1581. }
  1582. foreach ($this->foreignKeys as $fk) {
  1583. $fk->appendXml($tableNode);
  1584. }
  1585. foreach ($this->idMethodParameters as $param) {
  1586. $param->appendXml($tableNode);
  1587. }
  1588. foreach ($this->indices as $index) {
  1589. $index->appendXml($tableNode);
  1590. }
  1591. foreach ($this->unices as $unique) {
  1592. $unique->appendXml($tableNode);
  1593. }
  1594. foreach ($this->vendorInfos as $vi) {
  1595. $vi->appendXml($tableNode);
  1596. }
  1597. }
  1598. /**
  1599. * Returns the collection of Columns which make up the single primary
  1600. * key for this table.
  1601. *
  1602. * @return array Column[] A list of the primary key parts.
  1603. */
  1604. public function getPrimaryKey()
  1605. {
  1606. $pk = array();
  1607. foreach ($this->columnList as $col) {
  1608. if ($col->isPrimaryKey()) {
  1609. $pk[] = $col;
  1610. }
  1611. }
  1612. return $pk;
  1613. }
  1614. /**
  1615. * Determine whether this table has a primary key.
  1616. *
  1617. * @return boolean Whether this table has any primary key parts.
  1618. */
  1619. public function hasPrimaryKey()
  1620. {
  1621. return (count($this->getPrimaryKey()) > 0);
  1622. }
  1623. /**
  1624. * Determine whether this table has a composite primary key.
  1625. *
  1626. * @return boolean Whether this table has more than one primary key parts.
  1627. */
  1628. public function hasCompositePrimaryKey()
  1629. {
  1630. return (count($this->getPrimaryKey()) > 1);
  1631. }
  1632. /**
  1633. * Determine whether this table has any auto-increment primary key(s).
  1634. *
  1635. * @return boolean Whether this table has a non-"none" id method and has a primary key column that is auto-increment.
  1636. */
  1637. public function hasAutoIncrementPrimaryKey()
  1638. {
  1639. if ($this->getIdMethod() != IDMethod::NO_ID_METHOD) {
  1640. $pks =$this->getPrimaryKey();
  1641. foreach ($pks as $pk) {
  1642. if ($pk->isAutoIncrement()) {
  1643. return true;
  1644. }
  1645. }
  1646. }
  1647. return false;
  1648. }
  1649. /**
  1650. * Gets the auto increment PK
  1651. *
  1652. * @return Column if any auto increment PK column
  1653. */
  1654. public function getAutoIncrementPrimaryKey()
  1655. {
  1656. if ($this->getIdMethod() != IDMethod::NO_ID_METHOD) {
  1657. $pks =$this->getPrimaryKey();
  1658. foreach ($pks as $pk) {
  1659. if ($pk->isAutoIncrement()) {
  1660. return $pk;
  1661. }
  1662. }
  1663. }
  1664. return null;
  1665. }
  1666. /**
  1667. * Returns all parts of the primary key, separated by commas.
  1668. *
  1669. * @return A CSV list of primary key parts.
  1670. * @deprecated Use the Platform::getColumnListDDL() with the #getPrimaryKey() method.
  1671. */
  1672. public function printPrimaryKey()
  1673. {
  1674. return $this->printList($this->columnList);
  1675. }
  1676. /**
  1677. * Gets the crossRef status for this foreign key
  1678. * @return boolean
  1679. */
  1680. public function getIsCrossRef()
  1681. {
  1682. return $this->isCrossRef;
  1683. }
  1684. /**
  1685. * Sets a crossref status for this foreign key.
  1686. * @param boolean $isCrossRef
  1687. */
  1688. public function setIsCrossRef($isCrossRef)
  1689. {
  1690. $this->isCrossRef = (bool) $isCrossRef;
  1691. }
  1692. /**
  1693. * Returns the elements of the list, separated by commas.
  1694. * @param array $list
  1695. * @return A CSV list.
  1696. * @deprecated Use the Platform::getColumnListDDL() method.
  1697. */
  1698. private function printList($list) {
  1699. $result = "";
  1700. $comma = 0;
  1701. for ($i=0,$_i=count($list); $i < $_i; $i++) {
  1702. $col = $list[$i];
  1703. if ($col->isPrimaryKey()) {
  1704. $result .= ($comma++ ? ',' : '') . $this->getDatabase()->getPlatform()->quoteIdentifier($col->getName());
  1705. }
  1706. }
  1707. return $result;
  1708. }
  1709. }