PageRenderTime 41ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 1ms

/generator/lib/builder/om/PHP5ObjectBuilder.php

https://github.com/Tactics/Propel
PHP | 5578 lines | 3397 code | 532 blank | 1649 comment | 400 complexity | 171963c55c7556b4ee39bf6d3083bade 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__) . '/ObjectBuilder.php';
  10. /**
  11. * Generates a PHP5 base Object class for user object model (OM).
  12. *
  13. * This class produces the base object class (e.g. BaseMyTable) which contains all
  14. * the custom-built accessor and setter methods.
  15. *
  16. * @author Hans Lellelid <hans@xmpl.org>
  17. * @package propel.generator.builder.om
  18. */
  19. class PHP5ObjectBuilder extends ObjectBuilder
  20. {
  21. /**
  22. * Gets the package for the [base] object classes.
  23. * @return string
  24. */
  25. public function getPackage()
  26. {
  27. return parent::getPackage() . ".om";
  28. }
  29. public function getNamespace()
  30. {
  31. if ($namespace = parent::getNamespace()) {
  32. if ($this->getGeneratorConfig() && $omns = $this->getGeneratorConfig()->getBuildProperty('namespaceOm')) {
  33. return $namespace . '\\' . $omns;
  34. } else {
  35. return $namespace;
  36. }
  37. }
  38. }
  39. /**
  40. * Returns default key type. if not presented in configuration default will be 'TYPE_PHPNAME'
  41. * @return string
  42. */
  43. public function getDefaultKeyType()
  44. {
  45. $defaultKeyType = $this->getBuildProperty('defaultKeyType') ? $this->getBuildProperty('defaultKeyType') : 'phpName';
  46. return "TYPE_".strtoupper($defaultKeyType);
  47. }
  48. /**
  49. * Returns the name of the current class being built.
  50. * @return string
  51. */
  52. public function getUnprefixedClassname()
  53. {
  54. return $this->getBuildProperty('basePrefix') . $this->getStubObjectBuilder()->getUnprefixedClassname();
  55. }
  56. /**
  57. * Validates the current table to make sure that it won't
  58. * result in generated code that will not parse.
  59. *
  60. * This method may emit warnings for code which may cause problems
  61. * and will throw exceptions for errors that will definitely cause
  62. * problems.
  63. */
  64. protected function validateModel()
  65. {
  66. parent::validateModel();
  67. $table = $this->getTable();
  68. // Check to see whether any generated foreign key names
  69. // will conflict with column names.
  70. $colPhpNames = array();
  71. $fkPhpNames = array();
  72. foreach ($table->getColumns() as $col) {
  73. $colPhpNames[] = $col->getPhpName();
  74. }
  75. foreach ($table->getForeignKeys() as $fk) {
  76. $fkPhpNames[] = $this->getFKPhpNameAffix($fk, $plural = false);
  77. }
  78. $intersect = array_intersect($colPhpNames, $fkPhpNames);
  79. if (!empty($intersect)) {
  80. throw new EngineException("One or more of your column names for [" . $table->getName() . "] table conflict with foreign key names (" . implode(", ", $intersect) . ")");
  81. }
  82. // Check foreign keys to see if there are any foreign keys that
  83. // are also matched with an inversed referencing foreign key
  84. // (this is currently unsupported behavior)
  85. // see: http://propel.phpdb.org/trac/ticket/549
  86. foreach ($table->getForeignKeys() as $fk) {
  87. if ($fk->isMatchedByInverseFK()) {
  88. throw new EngineException("The 1:1 relationship expressed by foreign key " . $fk->getName() . " is defined in both directions; Propel does not currently support this (if you must have both foreign key constraints, consider adding this constraint with a custom SQL file.)" );
  89. }
  90. }
  91. }
  92. /**
  93. * Returns the appropriate formatter (from platform) for a date/time column.
  94. * @param Column $col
  95. * @return string
  96. */
  97. protected function getTemporalFormatter(Column $col)
  98. {
  99. $fmt = null;
  100. if ($col->getType() === PropelTypes::DATE) {
  101. $fmt = $this->getPlatform()->getDateFormatter();
  102. } elseif ($col->getType() === PropelTypes::TIME) {
  103. $fmt = $this->getPlatform()->getTimeFormatter();
  104. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  105. $fmt = $this->getPlatform()->getTimestampFormatter();
  106. }
  107. return $fmt;
  108. }
  109. /**
  110. * Returns the type-casted and stringified default value for the specified Column.
  111. * This only works for scalar default values currently.
  112. * @return string The default value or 'null' if there is none.
  113. * @throws EngineException
  114. */
  115. protected function getDefaultValueString(Column $col)
  116. {
  117. $defaultValue = var_export(null, true);
  118. $val = $col->getPhpDefaultValue();
  119. if ($val === null) {
  120. return $defaultValue;
  121. }
  122. if ($col->isTemporalType()) {
  123. $fmt = $this->getTemporalFormatter($col);
  124. try {
  125. if (!($this->getPlatform() instanceof MysqlPlatform &&
  126. ($val === '0000-00-00 00:00:00' || $val === '0000-00-00'))) {
  127. // while technically this is not a default value of null,
  128. // this seems to be closest in meaning.
  129. $defDt = new DateTime($val);
  130. $defaultValue = var_export($defDt->format($fmt), true);
  131. }
  132. } catch (Exception $x) {
  133. // prevent endless loop when timezone is undefined
  134. date_default_timezone_set('America/Los_Angeles');
  135. throw new EngineException(sprintf('Unable to parse default temporal value "%s" for column "%s"', $col->getDefaultValueString(), $col->getFullyQualifiedName()), $x);
  136. }
  137. } elseif ($col->isEnumType()) {
  138. $valueSet = $col->getValueSet();
  139. if (!in_array($val, $valueSet)) {
  140. throw new EngineException(sprintf('Default Value "%s" is not among the enumerated values', $val));
  141. }
  142. $defaultValue = array_search($val, $valueSet);
  143. } elseif ($col->isPhpPrimitiveType()) {
  144. settype($val, $col->getPhpType());
  145. $defaultValue = var_export($val, true);
  146. } elseif ($col->isPhpObjectType()) {
  147. $defaultValue = 'new '.$col->getPhpType().'(' . var_export($val, true) . ')';
  148. } elseif ($col->isPhpArrayType()) {
  149. $defaultValue = var_export($val, true);
  150. } else {
  151. throw new EngineException("Cannot get default value string for " . $col->getFullyQualifiedName());
  152. }
  153. return $defaultValue;
  154. }
  155. /**
  156. * Adds the include() statements for files that this class depends on or utilizes.
  157. * @param string &$script The script will be modified in this method.
  158. */
  159. protected function addIncludes(&$script)
  160. {
  161. } // addIncludes()
  162. /**
  163. * Adds class phpdoc comment and openning of class.
  164. * @param string &$script The script will be modified in this method.
  165. */
  166. protected function addClassOpen(&$script)
  167. {
  168. $table = $this->getTable();
  169. $tableName = $table->getName();
  170. $tableDesc = $table->getDescription();
  171. $interface = $this->getInterface();
  172. $parentClass = $this->getBehaviorContent('parentClass');
  173. $parentClass = (null !== $parentClass) ? $parentClass : ClassTools::classname($this->getBaseClass());
  174. if ($this->getBuildProperty('addClassLevelComment')) {
  175. $script .= "
  176. /**
  177. * Base class that represents a row from the '$tableName' table.
  178. *
  179. * $tableDesc
  180. *";
  181. if ($this->getBuildProperty('addTimeStamp')) {
  182. $now = strftime('%c');
  183. $script .= "
  184. * This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
  185. *
  186. * $now
  187. *";
  188. }
  189. $script .= "
  190. * @package propel.generator.".$this->getPackage()."
  191. */";
  192. }
  193. $script .= "
  194. abstract class ".$this->getClassname()." extends ".$parentClass." ";
  195. if ($interface = $this->getTable()->getInterface()) {
  196. $script .= "implements " . ClassTools::classname($interface);
  197. if ($interface !== ClassTools::classname($interface)) {
  198. $this->declareClass($interface);
  199. } else {
  200. $this->declareClassFromBuilder($this->getInterfaceBuilder());
  201. }
  202. } elseif ($interface = ClassTools::getInterface($table)) {
  203. $script .= "implements " . ClassTools::classname($interface);
  204. }
  205. $script .= "
  206. {";
  207. }
  208. /**
  209. * Specifies the methods that are added as part of the basic OM class.
  210. * This can be overridden by subclasses that wish to add more methods.
  211. * @see ObjectBuilder::addClassBody()
  212. */
  213. protected function addClassBody(&$script)
  214. {
  215. $this->declareClassFromBuilder($this->getStubObjectBuilder());
  216. $this->declareClassFromBuilder($this->getStubPeerBuilder());
  217. $this->declareClassFromBuilder($this->getStubQueryBuilder());
  218. $this->declareClasses(
  219. 'Propel', 'PropelException', 'PDO', 'PropelPDO', 'Criteria',
  220. 'BaseObject', 'Persistent', 'BasePeer', 'PropelCollection',
  221. 'PropelObjectCollection', 'Exception'
  222. );
  223. $table = $this->getTable();
  224. if (!$table->isAlias()) {
  225. $this->addConstants($script);
  226. $this->addAttributes($script);
  227. }
  228. if ($table->hasCrossForeignKeys()) {
  229. foreach ($table->getCrossFks() as $fkList) {
  230. list($refFK, $crossFK) = $fkList;
  231. $fkName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  232. $this->addScheduledForDeletionAttribute($script, $fkName);
  233. }
  234. }
  235. foreach ($table->getReferrers() as $refFK) {
  236. $fkName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  237. $this->addScheduledForDeletionAttribute($script, $fkName);
  238. }
  239. if ($this->hasDefaultValues()) {
  240. $this->addApplyDefaultValues($script);
  241. $this->addConstructor($script);
  242. }
  243. $this->addColumnAccessorMethods($script);
  244. $this->addColumnMutatorMethods($script);
  245. $this->addHasOnlyDefaultValues($script);
  246. $this->addHydrate($script);
  247. $this->addEnsureConsistency($script);
  248. if (!$table->isReadOnly()) {
  249. $this->addManipulationMethods($script);
  250. }
  251. if ($this->isAddValidateMethod()) {
  252. $this->addValidationMethods($script);
  253. }
  254. if ($this->isAddGenericAccessors()) {
  255. $this->addGetByName($script);
  256. $this->addGetByPosition($script);
  257. $this->addToArray($script);
  258. }
  259. if ($this->isAddGenericMutators()) {
  260. $this->addSetByName($script);
  261. $this->addSetByPosition($script);
  262. $this->addFromArray($script);
  263. }
  264. $this->addBuildCriteria($script);
  265. $this->addBuildPkeyCriteria($script);
  266. $this->addGetPrimaryKey($script);
  267. $this->addSetPrimaryKey($script);
  268. $this->addIsPrimaryKeyNull($script);
  269. $this->addCopy($script);
  270. if (!$table->isAlias()) {
  271. $this->addGetPeer($script);
  272. }
  273. $this->addFKMethods($script);
  274. $this->addRefFKMethods($script);
  275. $this->addCrossFKMethods($script);
  276. $this->addClear($script);
  277. $this->addClearAllReferences($script);
  278. $this->addPrimaryString($script);
  279. $this->addIsAlreadyInSave($script);
  280. // apply behaviors
  281. $this->applyBehaviorModifier('objectMethods', $script, " ");
  282. $this->addMagicCall($script);
  283. }
  284. /**
  285. * Closes class.
  286. * @param string &$script The script will be modified in this method.
  287. */
  288. protected function addClassClose(&$script)
  289. {
  290. $script .= "
  291. }
  292. ";
  293. $this->applyBehaviorModifier('objectFilter', $script, "");
  294. }
  295. /**
  296. * Adds any constants to the class.
  297. * @param string &$script The script will be modified in this method.
  298. */
  299. protected function addConstants(&$script)
  300. {
  301. $script .= "
  302. /**
  303. * Peer class name
  304. */
  305. const PEER = '" . addslashes($this->getStubPeerBuilder()->getFullyQualifiedClassname()) . "';
  306. ";
  307. }
  308. /**
  309. * Adds class attributes.
  310. * @param string &$script The script will be modified in this method.
  311. */
  312. protected function addAttributes(&$script)
  313. {
  314. $table = $this->getTable();
  315. $script .= "
  316. /**
  317. * The Peer class.
  318. * Instance provides a convenient way of calling static methods on a class
  319. * that calling code may not be able to identify.
  320. * @var ".$this->getPeerClassname()."
  321. */
  322. protected static \$peer;
  323. /**
  324. * The flag var to prevent infinit loop in deep copy
  325. * @var boolean
  326. */
  327. protected \$startCopy = false;
  328. ";
  329. if (!$table->isAlias()) {
  330. $this->addColumnAttributes($script);
  331. }
  332. foreach ($table->getForeignKeys() as $fk) {
  333. $this->addFKAttributes($script, $fk);
  334. }
  335. foreach ($table->getReferrers() as $refFK) {
  336. $this->addRefFKAttributes($script, $refFK);
  337. }
  338. // many-to-many relationships
  339. foreach ($table->getCrossFks() as $fkList) {
  340. $crossFK = $fkList[1];
  341. $this->addCrossFKAttributes($script, $crossFK);
  342. }
  343. $this->addAlreadyInSaveAttribute($script);
  344. $this->addAlreadyInValidationAttribute($script);
  345. // apply behaviors
  346. $this->applyBehaviorModifier('objectAttributes', $script, " ");
  347. }
  348. /**
  349. * Adds variables that store column values.
  350. * @param string &$script The script will be modified in this method.
  351. * @see addColumnNameConstants()
  352. */
  353. protected function addColumnAttributes(&$script)
  354. {
  355. $table = $this->getTable();
  356. foreach ($table->getColumns() as $col) {
  357. $this->addColumnAttributeComment($script, $col);
  358. $this->addColumnAttributeDeclaration($script, $col);
  359. if ($col->isLazyLoad() ) {
  360. $this->addColumnAttributeLoaderComment($script, $col);
  361. $this->addColumnAttributeLoaderDeclaration($script, $col);
  362. }
  363. if ($col->getType() == PropelTypes::OBJECT || $col->getType() == PropelTypes::PHP_ARRAY) {
  364. $this->addColumnAttributeUnserializedComment($script, $col);
  365. $this->addColumnAttributeUnserializedDeclaration($script, $col);
  366. }
  367. }
  368. }
  369. /**
  370. * Add comment about the attribute (variable) that stores column values
  371. * @param string &$script The script will be modified in this method.
  372. * @param Column $col
  373. **/
  374. protected function addColumnAttributeComment(&$script, Column $col)
  375. {
  376. $cptype = $col->getPhpType();
  377. $clo = strtolower($col->getName());
  378. $script .= "
  379. /**
  380. * The value for the $clo field.";
  381. if ($col->getDefaultValue()) {
  382. if ($col->getDefaultValue()->isExpression()) {
  383. $script .= "
  384. * Note: this column has a database default value of: (expression) ".$col->getDefaultValue()->getValue();
  385. } else {
  386. $script .= "
  387. * Note: this column has a database default value of: ". $this->getDefaultValueString($col);
  388. }
  389. }
  390. $script .= "
  391. * @var $cptype
  392. */";
  393. }
  394. /**
  395. * Adds the declaration of a column value storage attribute
  396. * @param string &$script The script will be modified in this method.
  397. * @param Column $col
  398. **/
  399. protected function addColumnAttributeDeclaration(&$script, Column $col)
  400. {
  401. $clo = strtolower($col->getName());
  402. $script .= "
  403. protected \$" . $clo . ";
  404. ";
  405. }
  406. /**
  407. * Adds the comment about the attribute keeping track if an attribute value has been loaded
  408. * @param string &$script The script will be modified in this method.
  409. * @param Column $col
  410. **/
  411. protected function addColumnAttributeLoaderComment(&$script, Column $col)
  412. {
  413. $clo = strtolower($col->getName());
  414. $script .= "
  415. /**
  416. * Whether the lazy-loaded \$$clo value has been loaded from database.
  417. * This is necessary to avoid repeated lookups if \$$clo column is null in the db.
  418. * @var boolean
  419. */";
  420. }
  421. /**
  422. * Adds the declaration of the attribute keeping track of an attribute's loaded state
  423. * @param string &$script The script will be modified in this method.
  424. * @param Column $col
  425. **/
  426. protected function addColumnAttributeLoaderDeclaration(&$script, Column $col)
  427. {
  428. $clo = strtolower($col->getName());
  429. $script .= "
  430. protected \$".$clo."_isLoaded = false;
  431. ";
  432. }
  433. /**
  434. * Adds the comment about the serialized attribute
  435. * @param string &$script The script will be modified in this method.
  436. * @param Column $col
  437. **/
  438. protected function addColumnAttributeUnserializedComment(&$script, Column $col)
  439. {
  440. $clo = strtolower($col->getName());
  441. $script .= "
  442. /**
  443. * The unserialized \$$clo value - i.e. the persisted object.
  444. * This is necessary to avoid repeated calls to unserialize() at runtime.
  445. * @var object
  446. */";
  447. }
  448. /**
  449. * Adds the declaration of the serialized attribute
  450. * @param string &$script The script will be modified in this method.
  451. * @param Column $col
  452. **/
  453. protected function addColumnAttributeUnserializedDeclaration(&$script, Column $col)
  454. {
  455. $clo = strtolower($col->getName()) . "_unserialized";
  456. $script .= "
  457. protected \$" . $clo . ";
  458. ";
  459. }
  460. /**
  461. * Adds the getPeer() method.
  462. * This is a convenient, non introspective way of getting the Peer class for a particular object.
  463. * @param string &$script The script will be modified in this method.
  464. */
  465. protected function addGetPeer(&$script)
  466. {
  467. $this->addGetPeerComment($script);
  468. $this->addGetPeerFunctionOpen($script);
  469. $this->addGetPeerFunctionBody($script);
  470. $this->addGetPeerFunctionClose($script);
  471. }
  472. /**
  473. * Add the comment for the getPeer method
  474. * @param string &$script The script will be modified in this method.
  475. **/
  476. protected function addGetPeerComment(&$script)
  477. {
  478. $script .= "
  479. /**
  480. * Returns a peer instance associated with this om.
  481. *
  482. * Since Peer classes are not to have any instance attributes, this method returns the
  483. * same instance for all member of this class. The method could therefore
  484. * be static, but this would prevent one from overriding the behavior.
  485. *
  486. * @return ".$this->getPeerClassname()."
  487. */";
  488. }
  489. /**
  490. * Adds the function declaration (function opening) for the getPeer method
  491. * @param string &$script The script will be modified in this method.
  492. **/
  493. protected function addGetPeerFunctionOpen(&$script)
  494. {
  495. $script .= "
  496. public function getPeer()
  497. {";
  498. }
  499. /**
  500. * Adds the body of the getPeer method
  501. * @param string &$script The script will be modified in this method.
  502. **/
  503. protected function addGetPeerFunctionBody(&$script)
  504. {
  505. $script .= "
  506. if (self::\$peer === null) {
  507. " . $this->buildObjectInstanceCreationCode('self::$peer', $this->getPeerClassname()) . "
  508. }
  509. return self::\$peer;";
  510. }
  511. /**
  512. * Add the function close for the getPeer method
  513. * Note: this is just a } and the body ends with a return statement, so it's quite useless. But it's here anyway for consisency, cause there's a close function for all functions and in some other instances, they are useful
  514. * @param string &$script The script will be modified in this method.
  515. **/
  516. protected function addGetPeerFunctionClose(&$script)
  517. {
  518. $script .= "
  519. }
  520. ";
  521. }
  522. /**
  523. * Adds the constructor for this object.
  524. * @param string &$script The script will be modified in this method.
  525. * @see addConstructor()
  526. */
  527. protected function addConstructor(&$script)
  528. {
  529. $this->addConstructorComment($script);
  530. $this->addConstructorOpen($script);
  531. $this->addConstructorBody($script);
  532. $this->addConstructorClose($script);
  533. }
  534. /**
  535. * Adds the comment for the constructor
  536. * @param string &$script The script will be modified in this method.
  537. **/
  538. protected function addConstructorComment(&$script)
  539. {
  540. $script .= "
  541. /**
  542. * Initializes internal state of ".$this->getClassname()." object.
  543. * @see applyDefaults()
  544. */";
  545. }
  546. /**
  547. * Adds the function declaration for the constructor
  548. * @param string &$script The script will be modified in this method.
  549. **/
  550. protected function addConstructorOpen(&$script)
  551. {
  552. $script .= "
  553. public function __construct()
  554. {";
  555. }
  556. /**
  557. * Adds the function body for the constructor
  558. * @param string &$script The script will be modified in this method.
  559. **/
  560. protected function addConstructorBody(&$script)
  561. {
  562. $script .= "
  563. parent::__construct();
  564. \$this->applyDefaultValues();";
  565. }
  566. /**
  567. * Adds the function close for the constructor
  568. * @param string &$script The script will be modified in this method.
  569. **/
  570. protected function addConstructorClose(&$script)
  571. {
  572. $script .= "
  573. }
  574. ";
  575. }
  576. /**
  577. * Adds the applyDefaults() method, which is called from the constructor.
  578. * @param string &$script The script will be modified in this method.
  579. * @see addConstructor()
  580. */
  581. protected function addApplyDefaultValues(&$script)
  582. {
  583. $this->addApplyDefaultValuesComment($script);
  584. $this->addApplyDefaultValuesOpen($script);
  585. $this->addApplyDefaultValuesBody($script);
  586. $this->addApplyDefaultValuesClose($script);
  587. }
  588. /**
  589. * Adds the comment for the applyDefaults method
  590. * @param string &$script The script will be modified in this method.
  591. * @see addApplyDefaultValues()
  592. **/
  593. protected function addApplyDefaultValuesComment(&$script)
  594. {
  595. $script .= "
  596. /**
  597. * Applies default values to this object.
  598. * This method should be called from the object's constructor (or
  599. * equivalent initialization method).
  600. * @see __construct()
  601. */";
  602. }
  603. /**
  604. * Adds the function declaration for the applyDefaults method
  605. * @param string &$script The script will be modified in this method.
  606. * @see addApplyDefaultValues()
  607. **/
  608. protected function addApplyDefaultValuesOpen(&$script)
  609. {
  610. $script .= "
  611. public function applyDefaultValues()
  612. {";
  613. }
  614. /**
  615. * Adds the function body of the applyDefault method
  616. * @param string &$script The script will be modified in this method.
  617. * @see addApplyDefaultValues()
  618. **/
  619. protected function addApplyDefaultValuesBody(&$script)
  620. {
  621. $table = $this->getTable();
  622. // FIXME - Apply support for PHP default expressions here
  623. // see: http://propel.phpdb.org/trac/ticket/378
  624. $colsWithDefaults = array();
  625. foreach ($table->getColumns() as $col) {
  626. $def = $col->getDefaultValue();
  627. if ($def !== null && !$def->isExpression()) {
  628. $colsWithDefaults[] = $col;
  629. }
  630. }
  631. $colconsts = array();
  632. foreach ($colsWithDefaults as $col) {
  633. $clo = strtolower($col->getName());
  634. $defaultValue = $this->getDefaultValueString($col);
  635. $script .= "
  636. \$this->".$clo." = $defaultValue;";
  637. }
  638. }
  639. /**
  640. * Adds the function close for the applyDefaults method
  641. * @param string &$script The script will be modified in this method.
  642. * @see addApplyDefaultValues()
  643. **/
  644. protected function addApplyDefaultValuesClose(&$script)
  645. {
  646. $script .= "
  647. }
  648. ";
  649. }
  650. // --------------------------------------------------------------
  651. //
  652. // A C C E S S O R M E T H O D S
  653. //
  654. // --------------------------------------------------------------
  655. /**
  656. * Adds a date/time/timestamp getter method.
  657. * @param string &$script The script will be modified in this method.
  658. * @param Column $col The current column.
  659. * @see parent::addColumnAccessors()
  660. */
  661. protected function addTemporalAccessor(&$script, Column $col)
  662. {
  663. $this->addTemporalAccessorComment($script, $col);
  664. $this->addTemporalAccessorOpen($script, $col);
  665. $this->addTemporalAccessorBody($script, $col);
  666. $this->addTemporalAccessorClose($script, $col);
  667. } // addTemporalAccessor
  668. /**
  669. * Adds the comment for a temporal accessor
  670. * @param string &$script The script will be modified in this method.
  671. * @param Column $col The current column.
  672. * @see addTemporalAccessor
  673. **/
  674. public function addTemporalAccessorComment(&$script, Column $col)
  675. {
  676. $clo = strtolower($col->getName());
  677. $useDateTime = $this->getBuildProperty('useDateTimeClass');
  678. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  679. if (!$dateTimeClass) {
  680. $dateTimeClass = 'DateTime';
  681. }
  682. $handleMysqlDate = false;
  683. if ($this->getPlatform() instanceof MysqlPlatform) {
  684. if ($col->getType() === PropelTypes::TIMESTAMP) {
  685. $handleMysqlDate = true;
  686. $mysqlInvalidDateString = '0000-00-00 00:00:00';
  687. } elseif ($col->getType() === PropelTypes::DATE) {
  688. $handleMysqlDate = true;
  689. $mysqlInvalidDateString = '0000-00-00';
  690. }
  691. // 00:00:00 is a valid time, so no need to check for that.
  692. }
  693. $script .= "
  694. /**
  695. * Get the [optionally formatted] temporal [$clo] column value.
  696. * ".$col->getDescription();
  697. if (!$useDateTime) {
  698. $script .= "
  699. * This accessor only only work with unix epoch dates. Consider enabling the propel.useDateTimeClass
  700. * option in order to avoid converstions to integers (which are limited in the dates they can express).";
  701. }
  702. $script .= "
  703. *
  704. * @param string \$format The date/time format string (either date()-style or strftime()-style).
  705. * If format is null, then the raw ".($useDateTime ? 'DateTime object' : 'unix timestamp integer')." will be returned.";
  706. if ($useDateTime) {
  707. $script .= "
  708. * @return mixed Formatted date/time value as string or $dateTimeClass object (if format is null), null if column is null" .($handleMysqlDate ? ', and 0 if column value is ' . $mysqlInvalidDateString : '');
  709. } else {
  710. $script .= "
  711. * @return mixed Formatted date/time value as string or (integer) unix timestamp (if format is null), null if column is null".($handleMysqlDate ? ', and 0 if column value is ' . $mysqlInvalidDateString : '');
  712. }
  713. $script .= "
  714. * @throws PropelException - if unable to parse/validate the date/time value.
  715. */";
  716. }
  717. /**
  718. * Adds the function declaration for a temporal accessor
  719. * @param string &$script The script will be modified in this method.
  720. * @param Column $col The current column.
  721. * @see addTemporalAccessor
  722. **/
  723. public function addTemporalAccessorOpen(&$script, Column $col)
  724. {
  725. $cfc = $col->getPhpName();
  726. $defaultfmt = null;
  727. $visibility = $col->getAccessorVisibility();
  728. // Default date/time formatter strings are specified in build.properties
  729. if ($col->getType() === PropelTypes::DATE) {
  730. $defaultfmt = $this->getBuildProperty('defaultDateFormat');
  731. } elseif ($col->getType() === PropelTypes::TIME) {
  732. $defaultfmt = $this->getBuildProperty('defaultTimeFormat');
  733. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  734. $defaultfmt = $this->getBuildProperty('defaultTimeStampFormat');
  735. }
  736. if (empty($defaultfmt)) {
  737. $defaultfmt = 'null';
  738. } else {
  739. $defaultfmt = var_export($defaultfmt, true);
  740. }
  741. $script .= "
  742. ".$visibility." function get$cfc(\$format = ".$defaultfmt."";
  743. if ($col->isLazyLoad()) $script .= ", \$con = null";
  744. $script .= ")
  745. {";
  746. }
  747. protected function getAccessorLazyLoadSnippet(Column $col)
  748. {
  749. if ($col->isLazyLoad()) {
  750. $clo = strtolower($col->getName());
  751. $defaultValueString = 'null';
  752. $def = $col->getDefaultValue();
  753. if ($def !== null && !$def->isExpression()) {
  754. $defaultValueString = $this->getDefaultValueString($col);
  755. }
  756. return "
  757. if (!\$this->{$clo}_isLoaded && \$this->{$clo} === {$defaultValueString} && !\$this->isNew()) {
  758. \$this->load{$col->getPhpName()}(\$con);
  759. }
  760. ";
  761. }
  762. }
  763. /**
  764. * Adds the body of the temporal accessor
  765. * @param string &$script The script will be modified in this method.
  766. * @param Column $col The current column.
  767. * @see addTemporalAccessor
  768. **/
  769. protected function addTemporalAccessorBody(&$script, Column $col)
  770. {
  771. $cfc = $col->getPhpName();
  772. $clo = strtolower($col->getName());
  773. $useDateTime = $this->getBuildProperty('useDateTimeClass');
  774. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  775. if (!$dateTimeClass) {
  776. $dateTimeClass = 'DateTime';
  777. }
  778. $this->declareClasses($dateTimeClass);
  779. $defaultfmt = null;
  780. // Default date/time formatter strings are specified in build.properties
  781. if ($col->getType() === PropelTypes::DATE) {
  782. $defaultfmt = $this->getBuildProperty('defaultDateFormat');
  783. } elseif ($col->getType() === PropelTypes::TIME) {
  784. $defaultfmt = $this->getBuildProperty('defaultTimeFormat');
  785. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  786. $defaultfmt = $this->getBuildProperty('defaultTimeStampFormat');
  787. }
  788. if (empty($defaultfmt)) {
  789. $defaultfmt = null;
  790. }
  791. $handleMysqlDate = false;
  792. if ($this->getPlatform() instanceof MysqlPlatform) {
  793. if ($col->getType() === PropelTypes::TIMESTAMP) {
  794. $handleMysqlDate = true;
  795. $mysqlInvalidDateString = '0000-00-00 00:00:00';
  796. } elseif ($col->getType() === PropelTypes::DATE) {
  797. $handleMysqlDate = true;
  798. $mysqlInvalidDateString = '0000-00-00';
  799. }
  800. // 00:00:00 is a valid time, so no need to check for that.
  801. }
  802. if ($col->isLazyLoad()) {
  803. $script .= $this->getAccessorLazyLoadSnippet($col);
  804. }
  805. $script .= "
  806. if (\$this->$clo === null) {
  807. return null;
  808. }
  809. ";
  810. if ($handleMysqlDate) {
  811. $script .= "
  812. if (\$this->$clo === '$mysqlInvalidDateString') {
  813. // while technically this is not a default value of null,
  814. // this seems to be closest in meaning.
  815. return null;
  816. } else {
  817. try {
  818. \$dt = new $dateTimeClass(\$this->$clo);
  819. } catch (Exception \$x) {
  820. throw new PropelException(\"Internally stored date/time/timestamp value could not be converted to $dateTimeClass: \" . var_export(\$this->$clo, true), \$x);
  821. }
  822. }
  823. ";
  824. } else {
  825. $script .= "
  826. try {
  827. \$dt = new $dateTimeClass(\$this->$clo);
  828. } catch (Exception \$x) {
  829. throw new PropelException(\"Internally stored date/time/timestamp value could not be converted to $dateTimeClass: \" . var_export(\$this->$clo, true), \$x);
  830. }
  831. ";
  832. } // if handleMyqlDate
  833. $script .= "
  834. if (\$format === null) {";
  835. if ($useDateTime) {
  836. $script .= "
  837. // Because propel.useDateTimeClass is true, we return a $dateTimeClass object.
  838. return \$dt;";
  839. } else {
  840. $script .= "
  841. // We cast here to maintain BC in API; obviously we will lose data if we're dealing with pre-/post-epoch dates.
  842. return (int) \$dt->format('U');";
  843. }
  844. $script .= "
  845. } elseif (strpos(\$format, '%') !== false) {
  846. return strftime(\$format, \$dt->format('U'));
  847. } else {
  848. return \$dt->format(\$format);
  849. }";
  850. }
  851. /**
  852. * Adds the body of the temporal accessor
  853. * @param string &$script The script will be modified in this method.
  854. * @param Column $col The current column.
  855. * @see addTemporalAccessorClose
  856. **/
  857. protected function addTemporalAccessorClose(&$script, Column $col)
  858. {
  859. $script .= "
  860. }
  861. ";
  862. }
  863. /**
  864. * Adds an object getter method.
  865. * @param string &$script The script will be modified in this method.
  866. * @param Column $col The current column.
  867. * @see parent::addColumnAccessors()
  868. */
  869. protected function addObjectAccessor(&$script, Column $col)
  870. {
  871. $this->addDefaultAccessorComment($script, $col);
  872. $this->addDefaultAccessorOpen($script, $col);
  873. $this->addObjectAccessorBody($script, $col);
  874. $this->addDefaultAccessorClose($script, $col);
  875. }
  876. /**
  877. * Adds the function body for an object accessor method
  878. * @param string &$script The script will be modified in this method.
  879. * @param Column $col The current column.
  880. * @see addDefaultAccessor()
  881. **/
  882. protected function addObjectAccessorBody(&$script, Column $col)
  883. {
  884. $cfc = $col->getPhpName();
  885. $clo = strtolower($col->getName());
  886. $cloUnserialized = $clo.'_unserialized';
  887. if ($col->isLazyLoad()) {
  888. $script .= $this->getAccessorLazyLoadSnippet($col);
  889. }
  890. $script .= "
  891. if (null == \$this->$cloUnserialized && null !== \$this->$clo) {
  892. \$this->$cloUnserialized = unserialize(\$this->$clo);
  893. }
  894. return \$this->$cloUnserialized;";
  895. }
  896. /**
  897. * Adds an array getter method.
  898. * @param string &$script The script will be modified in this method.
  899. * @param Column $col The current column.
  900. * @see parent::addColumnAccessors()
  901. */
  902. protected function addArrayAccessor(&$script, Column $col)
  903. {
  904. $this->addDefaultAccessorComment($script, $col);
  905. $this->addDefaultAccessorOpen($script, $col);
  906. $this->addArrayAccessorBody($script, $col);
  907. $this->addDefaultAccessorClose($script, $col);
  908. }
  909. /**
  910. * Adds the function body for an array accessor method
  911. * @param string &$script The script will be modified in this method.
  912. * @param Column $col The current column.
  913. * @see addDefaultAccessor()
  914. **/
  915. protected function addArrayAccessorBody(&$script, Column $col)
  916. {
  917. $cfc = $col->getPhpName();
  918. $clo = strtolower($col->getName());
  919. $cloUnserialized = $clo.'_unserialized';
  920. if ($col->isLazyLoad()) {
  921. $script .= $this->getAccessorLazyLoadSnippet($col);
  922. }
  923. $script .= "
  924. if (null === \$this->$cloUnserialized) {
  925. \$this->$cloUnserialized = array();
  926. }
  927. if (!\$this->$cloUnserialized && null !== \$this->$clo) {
  928. \$$cloUnserialized = substr(\$this->$clo, 2, -2);
  929. \$this->$cloUnserialized = \$$cloUnserialized ? explode(' | ', \$$cloUnserialized) : array();
  930. }
  931. return \$this->$cloUnserialized;";
  932. }
  933. /**
  934. * Adds an enum getter method.
  935. * @param string &$script The script will be modified in this method.
  936. * @param Column $col The current column.
  937. * @see parent::addColumnAccessors()
  938. */
  939. protected function addEnumAccessor(&$script, Column $col)
  940. {
  941. $clo = strtolower($col->getName());
  942. $script .= "
  943. /**
  944. * Get the [$clo] column value.
  945. * ".$col->getDescription();
  946. if ($col->isLazyLoad()) {
  947. $script .= "
  948. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  949. }
  950. $script .= "
  951. * @return ".$col->getPhpType()."
  952. * @throws PropelException - if the stored enum key is unknown.
  953. */";
  954. $this->addDefaultAccessorOpen($script, $col);
  955. $this->addEnumAccessorBody($script, $col);
  956. $this->addDefaultAccessorClose($script, $col);
  957. }
  958. /**
  959. * Adds the function body for an enum accessor method
  960. * @param string &$script The script will be modified in this method.
  961. * @param Column $col The current column.
  962. * @see addDefaultAccessor()
  963. **/
  964. protected function addEnumAccessorBody(&$script, Column $col)
  965. {
  966. $cfc = $col->getPhpName();
  967. $clo = strtolower($col->getName());
  968. if ($col->isLazyLoad()) {
  969. $script .= $this->getAccessorLazyLoadSnippet($col);
  970. }
  971. $script .= "
  972. if (null === \$this->$clo) {
  973. return null;
  974. }
  975. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  976. if (!isset(\$valueSet[\$this->$clo])) {
  977. throw new PropelException('Unknown stored enum key: ' . \$this->$clo);
  978. }
  979. return \$valueSet[\$this->$clo];";
  980. }
  981. /**
  982. * Adds a tester method for an array column.
  983. * @param string &$script The script will be modified in this method.
  984. * @param Column $col The current column.
  985. */
  986. protected function addHasArrayElement(&$script, Column $col)
  987. {
  988. $clo = strtolower($col->getName());
  989. $cfc = $col->getPhpName();
  990. $visibility = $col->getAccessorVisibility();
  991. $singularPhpName = rtrim($cfc, 's');
  992. $script .= "
  993. /**
  994. * Test the presence of a value in the [$clo] array column value.
  995. * @param mixed \$value
  996. * ".$col->getDescription();
  997. if ($col->isLazyLoad()) {
  998. $script .= "
  999. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1000. }
  1001. $script .= "
  1002. * @return boolean
  1003. */
  1004. $visibility function has$singularPhpName(\$value";
  1005. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1006. $script .= ")
  1007. {
  1008. return in_array(\$value, \$this->get$cfc(";
  1009. if ($col->isLazyLoad()) $script .= "\$con";
  1010. $script .= "));
  1011. } // has$singularPhpName()
  1012. ";
  1013. }
  1014. /**
  1015. * Adds a normal (non-temporal) getter method.
  1016. * @param string &$script The script will be modified in this method.
  1017. * @param Column $col The current column.
  1018. * @see parent::addColumnAccessors()
  1019. */
  1020. protected function addDefaultAccessor(&$script, Column $col)
  1021. {
  1022. $this->addDefaultAccessorComment($script, $col);
  1023. $this->addDefaultAccessorOpen($script, $col);
  1024. $this->addDefaultAccessorBody($script, $col);
  1025. $this->addDefaultAccessorClose($script, $col);
  1026. }
  1027. /**
  1028. * Add the comment for a default accessor method (a getter)
  1029. * @param string &$script The script will be modified in this method.
  1030. * @param Column $col The current column.
  1031. * @see addDefaultAccessor()
  1032. **/
  1033. public function addDefaultAccessorComment(&$script, Column $col)
  1034. {
  1035. $clo=strtolower($col->getName());
  1036. $script .= "
  1037. /**
  1038. * Get the [$clo] column value.
  1039. * ".$col->getDescription();
  1040. if ($col->isLazyLoad()) {
  1041. $script .= "
  1042. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1043. }
  1044. $script .= "
  1045. * @return ".$col->getPhpType()."
  1046. */";
  1047. }
  1048. /**
  1049. * Adds the function declaration for a default accessor
  1050. * @param string &$script The script will be modified in this method.
  1051. * @param Column $col The current column.
  1052. * @see addDefaultAccessor()
  1053. **/
  1054. public function addDefaultAccessorOpen(&$script, Column $col)
  1055. {
  1056. $cfc = $col->getPhpName();
  1057. $visibility = $col->getAccessorVisibility();
  1058. $script .= "
  1059. ".$visibility." function get$cfc(";
  1060. if ($col->isLazyLoad()) $script .= "PropelPDO \$con = null";
  1061. $script .= ")
  1062. {";
  1063. }
  1064. /**
  1065. * Adds the function body for a default accessor method
  1066. * @param string &$script The script will be modified in this method.
  1067. * @param Column $col The current column.
  1068. * @see addDefaultAccessor()
  1069. **/
  1070. protected function addDefaultAccessorBody(&$script, Column $col)
  1071. {
  1072. $cfc = $col->getPhpName();
  1073. $clo = strtolower($col->getName());
  1074. if ($col->isLazyLoad()) {
  1075. $script .= $this->getAccessorLazyLoadSnippet($col);
  1076. }
  1077. $script .= "
  1078. return \$this->$clo;";
  1079. }
  1080. /**
  1081. * Adds the function close for a default accessor method
  1082. * @param string &$script The script will be modified in this method.
  1083. * @param Column $col The current column.
  1084. * @see addDefaultAccessor()
  1085. **/
  1086. protected function addDefaultAccessorClose(&$script, Column $col)
  1087. {
  1088. $script .= "
  1089. }
  1090. ";
  1091. }
  1092. /**
  1093. * Adds the lazy loader method.
  1094. * @param string &$script The script will be modified in this method.
  1095. * @param Column $col The current column.
  1096. * @see parent::addColumnAccessors()
  1097. */
  1098. protected function addLazyLoader(&$script, Column $col)
  1099. {
  1100. $this->addLazyLoaderComment($script, $col);
  1101. $this->addLazyLoaderOpen($script, $col);
  1102. $this->addLazyLoaderBody($script, $col);
  1103. $this->addLazyLoaderClose($script, $col);
  1104. }
  1105. /**
  1106. * Adds the comment for the lazy loader method
  1107. * @param string &$script The script will be modified in this method.
  1108. * @param Column $col The current column.
  1109. * @see addLazyLoader()
  1110. **/
  1111. protected function addLazyLoaderComment(&$script, Column $col)
  1112. {
  1113. $clo = strtolower($col->getName());
  1114. $script .= "
  1115. /**
  1116. * Load the value for the lazy-loaded [$clo] column.
  1117. *
  1118. * This method performs an additional query to return the value for
  1119. * the [$clo] column, since it is not populated by
  1120. * the hydrate() method.
  1121. *
  1122. * @param PropelPDO \$con (optional) The PropelPDO connection to use.
  1123. * @return void
  1124. * @throws PropelException - any underlying error will be wrapped and re-thrown.
  1125. */";
  1126. }
  1127. /**
  1128. * Adds the function declaration for the lazy loader method
  1129. * @param string &$script The script will be modified in this method.
  1130. * @param Column $col The current column.
  1131. * @see addLazyLoader()
  1132. **/
  1133. protected function addLazyLoaderOpen(&$script, Column $col)
  1134. {
  1135. $cfc = $col->getPhpName();
  1136. $script .= "
  1137. protected function load$cfc(PropelPDO \$con = null)
  1138. {";
  1139. }
  1140. /**
  1141. * Adds the function body for the lazy loader method
  1142. * @param string &$script The script will be modified in this method.
  1143. * @param Column $col The current column.
  1144. * @see addLazyLoader()
  1145. **/
  1146. protected function addLazyLoaderBody(&$script, Column $col)
  1147. {
  1148. $platform = $this->getPlatform();
  1149. $clo = strtolower($col->getName());
  1150. // pdo_sqlsrv driver requires the use of PDOStatement::bindColumn() or a hex string will be returned
  1151. if ($col->getType() === PropelTypes::BLOB && $platform instanceof SqlsrvPlatform) {
  1152. $script .= "
  1153. \$c = \$this->buildPkeyCriteria();
  1154. \$c->addSelectColumn(".$this->getColumnConstant($col).");
  1155. try {
  1156. \$row = array(0 => null);
  1157. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$c, \$con);
  1158. \$stmt->bindColumn(1, \$row[0], PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
  1159. \$stmt->fetch(PDO::FETCH_BOUND);
  1160. \$stmt->closeCursor();";
  1161. } else {
  1162. $script .= "
  1163. \$c = \$this->buildPkeyCriteria();
  1164. \$c->addSelectColumn(".$this->getColumnConstant($col).");
  1165. try {
  1166. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$c, \$con);
  1167. \$row = \$stmt->fetch(PDO::FETCH_NUM);
  1168. \$stmt->closeCursor();";
  1169. }
  1170. if ($col->getType() === PropelTypes::CLOB && $platform instanceof OraclePlatform) {
  1171. // PDO_OCI returns a stream for CLOB objects, while other PDO adapters return a string...
  1172. $script .= "
  1173. \$this->$clo = stream_get_contents(\$row[0]);";
  1174. } elseif ($col->isLobType() && !$platform->hasStreamBlobImpl()) {
  1175. $script .= "
  1176. if (\$row[0] !== null) {
  1177. \$this->$clo = fopen('php://memory', 'r+');
  1178. fwrite(\$this->$clo, \$row[0]);
  1179. rewind(\$this->$clo);
  1180. } else {
  1181. \$this->$clo = null;
  1182. }";
  1183. } elseif ($col->isPhpPrimitiveType()) {
  1184. $script .= "
  1185. \$this->$clo = (\$row[0] !== null) ? (".$col->getPhpType().") \$row[0] : null;";
  1186. } elseif ($col->isPhpObjectType()) {
  1187. $script .= "
  1188. \$this->$clo = (\$row[0] !== null) ? new ".$col->getPhpType()."(\$row[0]) : null;";
  1189. } else {
  1190. $script .= "
  1191. \$this->$clo = \$row[0];";
  1192. }
  1193. $script .= "
  1194. \$this->".$clo."_isLoaded = true;
  1195. } catch (Exception \$e) {
  1196. throw new PropelException(\"Error loading value for [$clo] column on demand.\", \$e);
  1197. }";
  1198. }
  1199. /**
  1200. * Adds the function close for the lazy loader
  1201. * @param string &$script The script will be modified in this method.
  1202. * @param Column $col The current column.
  1203. * @see addLazyLoader()
  1204. **/
  1205. protected function addLazyLoaderClose(&$script, Column $col)
  1206. {
  1207. $script .= "
  1208. }";
  1209. } // addLazyLoader()
  1210. // --------------------------------------------------------------
  1211. //
  1212. // M U T A T O R M E T H O D S
  1213. //
  1214. // --------------------------------------------------------------
  1215. /**
  1216. * Adds the open of the mutator (setter) method for a column.
  1217. * @param string &$script The script will be modified in this method.
  1218. * @param Column $col The current column.
  1219. */
  1220. protected function addMutatorOpen(&$script, Column $col)
  1221. {
  1222. $this->addMutatorComment($script, $col);
  1223. $this->addMutatorOpenOpen($script, $col);
  1224. $this->addMutatorOpenBody($script, $col);
  1225. }
  1226. /**
  1227. * Adds the comment for a mutator
  1228. * @param string &$script The script will be modified in this method.
  1229. * @param Column $col The current column.
  1230. * @see addMutatorOpen()
  1231. **/
  1232. public function addMutatorComment(&$script, Column $col)
  1233. {
  1234. $clo = strtolower($col->getName());
  1235. $script .= "
  1236. /**
  1237. * Set the value of [$clo] column.
  1238. * ".$col->getDescription()."
  1239. * @param ".$col->getPhpType()." \$v new value
  1240. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1241. */";
  1242. }
  1243. /**
  1244. * Adds the mutator function declaration
  1245. * @param string &$script The script will be modified in this method.
  1246. * @param Column $col The current column.
  1247. * @see addMutatorOpen()
  1248. **/
  1249. public function addMutatorOpenOpen(&$script, Column $col)
  1250. {
  1251. $cfc = $col->getPhpName();
  1252. $visibility = $col->getMutatorVisibility();
  1253. $script .= "
  1254. ".$visibility." function set$cfc(\$v)
  1255. {";
  1256. }
  1257. /**
  1258. * Adds the mutator open body part
  1259. * @param string &$script The script will be modified in this method.
  1260. * @param Column $col The current column.
  1261. * @see addMutatorOpen()
  1262. **/
  1263. protected function addMutatorOpenBody(&$script, Column $col)
  1264. {
  1265. $clo = strtolower($col->getName());
  1266. $cfc = $col->getPhpName();
  1267. if ($col->isLazyLoad()) {
  1268. $script .= "
  1269. // Allow unsetting the lazy loaded column even when its not loaded.
  1270. if (!\$this->".$clo."_isLoaded && \$v === null) {
  1271. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1272. }
  1273. // explicitly set the is-loaded flag to true for this lazy load col;
  1274. // it doesn't matter if the value is actually set or not (logic below) as
  1275. // any attempt to set the value means that no db lookup should be performed
  1276. // when the get$cfc() method is called.
  1277. \$this->".$clo."_isLoaded = true;
  1278. ";
  1279. }
  1280. }
  1281. /**
  1282. * Adds the close of the mutator (setter) method for a column.
  1283. *
  1284. * @param string &$script The script will be modified in this method.
  1285. * @param Column $col The current column.
  1286. */
  1287. protected function addMutatorClose(&$script, Column $col)
  1288. {
  1289. $this->addMutatorCloseBody($script, $col);
  1290. $this->addMutatorCloseClose($script, $col);
  1291. }
  1292. /**
  1293. * Adds the body of the close part of a mutator
  1294. * @param string &$script The script will be modified in this method.
  1295. * @param Column $col The current column.
  1296. * @see addMutatorClose()
  1297. **/
  1298. protected function addMutatorCloseBody(&$script, Column $col)
  1299. {
  1300. $table = $this->getTable();
  1301. $cfc = $col->getPhpName();
  1302. $clo = strtolower($col->getName());
  1303. if ($col->isForeignKey()) {
  1304. foreach ($col->getForeignKeys() as $fk) {
  1305. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  1306. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  1307. $varName = $this->getFKVarName($fk);
  1308. $script .= "
  1309. if (\$this->$varName !== null && \$this->".$varName."->get".$colFK->getPhpName()."() !== \$v) {
  1310. \$this->$varName = null;
  1311. }
  1312. ";
  1313. } // foreach fk
  1314. } /* if col is foreign key */
  1315. foreach ($col->getReferrers() as $refFK) {
  1316. $tblFK = $this->getDatabase()->getTable($refFK->getForeignTableName());
  1317. if ( $tblFK->getName() != $table->getName() ) {
  1318. foreach ($col->getForeignKeys() as $fk) {
  1319. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  1320. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  1321. if ($refFK->isLocalPrimaryKey()) {
  1322. $varName = $this->getPKRefFKVarName($refFK);
  1323. $script .= "
  1324. // update associated ".$tblFK->getPhpName()."
  1325. if (\$this->$varName !== null) {
  1326. \$this->{$varName}->set".$colFK->getPhpName()."(\$v);
  1327. }
  1328. ";
  1329. } else {
  1330. $collName = $this->getRefFKCollVarName($refFK);
  1331. $script .= "
  1332. // update associated ".$tblFK->getPhpName()."
  1333. if (\$this->$collName !== null) {
  1334. foreach (\$this->$collName as \$referrerObject) {
  1335. \$referrerObject->set".$colFK->getPhpName()."(\$v);
  1336. }
  1337. }
  1338. ";
  1339. } // if (isLocalPrimaryKey
  1340. } // foreach col->getPrimaryKeys()
  1341. } // if tablFk != table
  1342. } // foreach
  1343. }
  1344. /**
  1345. * Adds the close for the mutator close
  1346. * @param string &$script The script will be modified in this method.
  1347. * @param Column $col The current column.
  1348. * @see addMutatorClose()
  1349. **/
  1350. protected function addMutatorCloseClose(&$script, Column $col)
  1351. {
  1352. $cfc = $col->getPhpName();
  1353. $script .= "
  1354. return \$this;
  1355. } // set$cfc()
  1356. ";
  1357. }
  1358. /**
  1359. * Adds a setter for BLOB columns.
  1360. * @param string &$script The script will be modified in this method.
  1361. * @param Column $col The current column.
  1362. * @see parent::addColumnMutators()
  1363. */
  1364. protected function addLobMutator(&$script, Column $col)
  1365. {
  1366. $this->addMutatorOpen($script, $col);
  1367. $clo = strtolower($col->getName());
  1368. $script .= "
  1369. // Because BLOB columns are streams in PDO we have to assume that they are
  1370. // always modified when a new value is passed in. For example, the contents
  1371. // of the stream itself may have changed externally.
  1372. if (!is_resource(\$v) && \$v !== null) {
  1373. \$this->$clo = fopen('php://memory', 'r+');
  1374. fwrite(\$this->$clo, \$v);
  1375. rewind(\$this->$clo);
  1376. } else { // it's already a stream
  1377. \$this->$clo = \$v;
  1378. }
  1379. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1380. ";
  1381. $this->addMutatorClose($script, $col);
  1382. } // addLobMutatorSnippet
  1383. /**
  1384. * Adds a setter method for date/time/timestamp columns.
  1385. * @param string &$script The script will be modified in this method.
  1386. * @param Column $col The current column.
  1387. * @see parent::addColumnMutators()
  1388. */
  1389. protected function addTemporalMutator(&$script, Column $col)
  1390. {
  1391. $cfc = $col->getPhpName();
  1392. $clo = strtolower($col->getName());
  1393. $visibility = $col->getMutatorVisibility();
  1394. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  1395. if (!$dateTimeClass) {
  1396. $dateTimeClass = 'DateTime';
  1397. }
  1398. $this->declareClasses($dateTimeClass, 'DateTimeZone', 'PropelDateTime');
  1399. $this->addTemporalMutatorComment($script, $col);
  1400. $this->addMutatorOpenOpen($script, $col);
  1401. $this->addMutatorOpenBody($script, $col);
  1402. $fmt = var_export($this->getTemporalFormatter($col), true);
  1403. $script .= "
  1404. \$dt = PropelDateTime::newInstance(\$v, null, '$dateTimeClass');
  1405. if (\$this->$clo !== null || \$dt !== null) {
  1406. \$currentDateAsString = (\$this->$clo !== null && \$tmpDt = new $dateTimeClass(\$this->$clo)) ? \$tmpDt->format($fmt) : null;
  1407. \$newDateAsString = \$dt ? \$dt->format($fmt) : null;";
  1408. if (($def = $col->getDefaultValue()) !== null && !$def->isExpression()) {
  1409. $defaultValue = $this->getDefaultValueString($col);
  1410. $script .= "
  1411. if ( (\$currentDateAsString !== \$newDateAsString) // normalized values don't match
  1412. || (\$dt->format($fmt) === $defaultValue) // or the entered value matches the default
  1413. ) {";
  1414. } else {
  1415. $script .= "
  1416. if (\$currentDateAsString !== \$newDateAsString) {";
  1417. }
  1418. $script .= "
  1419. \$this->$clo = \$newDateAsString;
  1420. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1421. }
  1422. } // if either are not null
  1423. ";
  1424. $this->addMutatorClose($script, $col);
  1425. }
  1426. public function addTemporalMutatorComment(&$script, Column $col)
  1427. {
  1428. $cfc = $col->getPhpName();
  1429. $clo = strtolower($col->getName());
  1430. $script .= "
  1431. /**
  1432. * Sets the value of [$clo] column to a normalized version of the date/time value specified.
  1433. * ".$col->getDescription()."
  1434. * @param mixed \$v string, integer (timestamp), or DateTime value.
  1435. * Empty strings are treated as null.
  1436. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1437. */";
  1438. }
  1439. /**
  1440. * Adds a setter for Object columns.
  1441. * @param string &$script The script will be modified in this method.
  1442. * @param Column $col The current column.
  1443. * @see parent::addColumnMutators()
  1444. */
  1445. protected function addObjectMutator(&$script, Column $col)
  1446. {
  1447. $clo = strtolower($col->getName());
  1448. $cloUnserialized = $clo.'_unserialized';
  1449. $this->addMutatorOpen($script, $col);
  1450. $script .= "
  1451. if (\$this->$cloUnserialized !== \$v) {
  1452. \$this->$cloUnserialized = \$v;
  1453. \$this->$clo = serialize(\$v);
  1454. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1455. }
  1456. ";
  1457. $this->addMutatorClose($script, $col);
  1458. }
  1459. /**
  1460. * Adds a setter for Array columns.
  1461. * @param string &$script The script will be modified in this method.
  1462. * @param Column $col The current column.
  1463. * @see parent::addColumnMutators()
  1464. */
  1465. protected function addArrayMutator(&$script, Column $col)
  1466. {
  1467. $clo = strtolower($col->getName());
  1468. $cloUnserialized = $clo.'_unserialized';
  1469. $this->addMutatorOpen($script, $col);
  1470. $script .= "
  1471. if (\$this->$cloUnserialized !== \$v) {
  1472. \$this->$cloUnserialized = \$v;
  1473. \$this->$clo = '| ' . implode(' | ', \$v) . ' |';
  1474. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1475. }
  1476. ";
  1477. $this->addMutatorClose($script, $col);
  1478. }
  1479. /**
  1480. * Adds a push method for an array column.
  1481. * @param string &$script The script will be modified in this method.
  1482. * @param Column $col The current column.
  1483. */
  1484. protected function addAddArrayElement(&$script, Column $col)
  1485. {
  1486. $clo = strtolower($col->getName());
  1487. $cfc = $col->getPhpName();
  1488. $visibility = $col->getAccessorVisibility();
  1489. $singularPhpName = rtrim($cfc, 's');
  1490. $script .= "
  1491. /**
  1492. * Adds a value to the [$clo] array column value.
  1493. * @param mixed \$value
  1494. * ".$col->getDescription();
  1495. if ($col->isLazyLoad()) {
  1496. $script .= "
  1497. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1498. }
  1499. $script .= "
  1500. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1501. */
  1502. $visibility function add$singularPhpName(\$value";
  1503. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1504. $script .= ")
  1505. {
  1506. \$currentArray = \$this->get$cfc(";
  1507. if ($col->isLazyLoad()) $script .= "\$con";
  1508. $script .= ");
  1509. \$currentArray []= \$value;
  1510. \$this->set$cfc(\$currentArray);
  1511. return \$this;
  1512. } // add$singularPhpName()
  1513. ";
  1514. }
  1515. /**
  1516. * Adds a remove method for an array column.
  1517. * @param string &$script The script will be modified in this method.
  1518. * @param Column $col The current column.
  1519. */
  1520. protected function addRemoveArrayElement(&$script, Column $col)
  1521. {
  1522. $clo = strtolower($col->getName());
  1523. $cfc = $col->getPhpName();
  1524. $visibility = $col->getAccessorVisibility();
  1525. $singularPhpName = rtrim($cfc, 's');
  1526. $script .= "
  1527. /**
  1528. * Removes a value from the [$clo] array column value.
  1529. * @param mixed \$value
  1530. * ".$col->getDescription();
  1531. if ($col->isLazyLoad()) {
  1532. $script .= "
  1533. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1534. }
  1535. $script .= "
  1536. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1537. */
  1538. $visibility function remove$singularPhpName(\$value";
  1539. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1540. // we want to reindex the array, so array_ functions are not the best choice
  1541. $script .= ")
  1542. {
  1543. \$targetArray = array();
  1544. foreach (\$this->get$cfc(";
  1545. if ($col->isLazyLoad()) $script .= "\$con";
  1546. $script .= ") as \$element) {
  1547. if (\$element != \$value) {
  1548. \$targetArray []= \$element;
  1549. }
  1550. }
  1551. \$this->set$cfc(\$targetArray);
  1552. return \$this;
  1553. } // remove$singularPhpName()
  1554. ";
  1555. }
  1556. /**
  1557. * Adds a setter for Enum columns.
  1558. * @param string &$script The script will be modified in this method.
  1559. * @param Column $col The current column.
  1560. * @see parent::addColumnMutators()
  1561. */
  1562. protected function addEnumMutator(&$script, Column $col)
  1563. {
  1564. $clo = strtolower($col->getName());
  1565. $script .= "
  1566. /**
  1567. * Set the value of [$clo] column.
  1568. * ".$col->getDescription()."
  1569. * @param ".$col->getPhpType()." \$v new value
  1570. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1571. * @throws PropelException - if the value is not accepted by this enum.
  1572. */";
  1573. $this->addMutatorOpenOpen($script, $col);
  1574. $this->addMutatorOpenBody($script, $col);
  1575. $script .= "
  1576. if (\$v !== null) {
  1577. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  1578. if (!in_array(\$v, \$valueSet)) {
  1579. throw new PropelException(sprintf('Value \"%s\" is not accepted in this enumerated column', \$v));
  1580. }
  1581. \$v = array_search(\$v, \$valueSet);
  1582. }
  1583. if (\$this->$clo !== \$v) {
  1584. \$this->$clo = \$v;
  1585. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1586. }
  1587. ";
  1588. $this->addMutatorClose($script, $col);
  1589. }
  1590. /**
  1591. * Adds setter method for boolean columns.
  1592. * @param string &$script The script will be modified in this method.
  1593. * @param Column $col The current column.
  1594. * @see parent::addColumnMutators()
  1595. */
  1596. protected function addBooleanMutator(&$script, Column $col)
  1597. {
  1598. $clo = strtolower($col->getName());
  1599. $this->addBooleanMutatorComment($script, $col);
  1600. $this->addMutatorOpenOpen($script, $col);
  1601. $this->addMutatorOpenBody($script, $col);
  1602. $script .= "
  1603. if (\$v !== null) {
  1604. if (is_string(\$v)) {
  1605. \$v = in_array(strtolower(\$v), array('false', 'off', '-', 'no', 'n', '0', '')) ? false : true;
  1606. } else {
  1607. \$v = (boolean) \$v;
  1608. }
  1609. }
  1610. ";
  1611. $script .= "
  1612. if (\$this->$clo !== \$v) {
  1613. \$this->$clo = \$v;
  1614. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1615. }
  1616. ";
  1617. $this->addMutatorClose($script, $col);
  1618. }
  1619. public function addBooleanMutatorComment(&$script, Column $col)
  1620. {
  1621. $cfc = $col->getPhpName();
  1622. $clo = strtolower($col->getName());
  1623. $script .= "
  1624. /**
  1625. * Sets the value of the [$clo] column.
  1626. * Non-boolean arguments are converted using the following rules:
  1627. * * 1, '1', 'true', 'on', and 'yes' are converted to boolean true
  1628. * * 0, '0', 'false', 'off', and 'no' are converted to boolean false
  1629. * Check on string values is case insensitive (so 'FaLsE' is seen as 'false').
  1630. * ".$col->getDescription()."
  1631. * @param boolean|integer|string \$v The new value
  1632. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1633. */";
  1634. }
  1635. /**
  1636. * Adds setter method for "normal" columns.
  1637. * @param string &$script The script will be modified in this method.
  1638. * @param Column $col The current column.
  1639. * @see parent::addColumnMutators()
  1640. */
  1641. protected function addDefaultMutator(&$script, Column $col)
  1642. {
  1643. $clo = strtolower($col->getName());
  1644. $this->addMutatorOpen($script, $col);
  1645. // Perform type-casting to ensure that we can use type-sensitive
  1646. // checking in mutators.
  1647. if ($col->isPhpPrimitiveType()) {
  1648. $script .= "
  1649. if (\$v !== null) {
  1650. \$v = (".$col->getPhpType().") \$v;
  1651. }
  1652. ";
  1653. }
  1654. $script .= "
  1655. if (\$this->$clo !== \$v) {
  1656. \$this->$clo = \$v;
  1657. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1658. }
  1659. ";
  1660. $this->addMutatorClose($script, $col);
  1661. }
  1662. /**
  1663. * Adds the hasOnlyDefaultValues() method.
  1664. * @param string &$script The script will be modified in this method.
  1665. */
  1666. protected function addHasOnlyDefaultValues(&$script)
  1667. {
  1668. $this->addHasOnlyDefaultValuesComment($script);
  1669. $this->addHasOnlyDefaultValuesOpen($script);
  1670. $this->addHasOnlyDefaultValuesBody($script);
  1671. $this->addHasOnlyDefaultValuesClose($script);
  1672. }
  1673. /**
  1674. * Adds the comment for the hasOnlyDefaultValues method
  1675. * @param string &$script The script will be modified in this method.
  1676. * @see addHasOnlyDefaultValues
  1677. **/
  1678. protected function addHasOnlyDefaultValuesComment(&$script)
  1679. {
  1680. $script .= "
  1681. /**
  1682. * Indicates whether the columns in this object are only set to default values.
  1683. *
  1684. * This method can be used in conjunction with isModified() to indicate whether an object is both
  1685. * modified _and_ has some values set which are non-default.
  1686. *
  1687. * @return boolean Whether the columns in this object are only been set with default values.
  1688. */";
  1689. }
  1690. /**
  1691. * Adds the function declaration for the hasOnlyDefaultValues method
  1692. * @param string &$script The script will be modified in this method.
  1693. * @see addHasOnlyDefaultValues
  1694. **/
  1695. protected function addHasOnlyDefaultValuesOpen(&$script)
  1696. {
  1697. $script .= "
  1698. public function hasOnlyDefaultValues()
  1699. {";
  1700. }
  1701. /**
  1702. * Adds the function body for the hasOnlyDefaultValues method
  1703. * @param string &$script The script will be modified in this method.
  1704. * @see addHasOnlyDefaultValues
  1705. **/
  1706. protected function addHasOnlyDefaultValuesBody(&$script)
  1707. {
  1708. $table = $this->getTable();
  1709. $colsWithDefaults = array();
  1710. foreach ($table->getColumns() as $col) {
  1711. $def = $col->getDefaultValue();
  1712. if ($def !== null && !$def->isExpression()) {
  1713. $colsWithDefaults[] = $col;
  1714. }
  1715. }
  1716. foreach ($colsWithDefaults as $col) {
  1717. $clo = strtolower($col->getName());
  1718. $def = $col->getDefaultValue();
  1719. $script .= "
  1720. if (\$this->$clo !== " . $this->getDefaultValueString($col).") {
  1721. return false;
  1722. }
  1723. ";
  1724. }
  1725. }
  1726. /**
  1727. * Adds the function close for the hasOnlyDefaultValues method
  1728. * @param string &$script The script will be modified in this method.
  1729. * @see addHasOnlyDefaultValues
  1730. **/
  1731. protected function addHasOnlyDefaultValuesClose(&$script)
  1732. {
  1733. $script .= "
  1734. // otherwise, everything was equal, so return true
  1735. return true;";
  1736. $script .= "
  1737. } // hasOnlyDefaultValues()
  1738. ";
  1739. }
  1740. /**
  1741. * Adds the hydrate() method, which sets attributes of the object based on a ResultSet.
  1742. * @param string &$script The script will be modified in this method.
  1743. */
  1744. protected function addHydrate(&$script)
  1745. {
  1746. $this->addHydrateComment($script);
  1747. $this->addHydrateOpen($script);
  1748. $this->addHydrateBody($script);
  1749. $this->addHydrateClose($script);
  1750. }
  1751. /**
  1752. * Adds the comment for the hydrate method
  1753. * @param string &$script The script will be modified in this method.
  1754. * @see addHydrate()
  1755. */
  1756. protected function addHydrateComment(&$script)
  1757. {
  1758. $script .= "
  1759. /**
  1760. * Hydrates (populates) the object variables with values from the database resultset.
  1761. *
  1762. * An offset (0-based \"start column\") is specified so that objects can be hydrated
  1763. * with a subset of the columns in the resultset rows. This is needed, for example,
  1764. * for results of JOIN queries where the resultset row includes columns from two or
  1765. * more tables.
  1766. *
  1767. * @param array \$row The row returned by PDOStatement->fetch(PDO::FETCH_NUM)
  1768. * @param int \$startcol 0-based offset column which indicates which restultset column to start with.
  1769. * @param boolean \$rehydrate Whether this object is being re-hydrated from the database.
  1770. * @return int next starting column
  1771. * @throws PropelException - Any caught Exception will be rewrapped as a PropelException.
  1772. */";
  1773. }
  1774. /**
  1775. * Adds the function declaration for the hydrate method
  1776. * @param string &$script The script will be modified in this method.
  1777. * @see addHydrate()
  1778. */
  1779. protected function addHydrateOpen(&$script)
  1780. {
  1781. $script .= "
  1782. public function hydrate(\$row, \$startcol = 0, \$rehydrate = false)
  1783. {";
  1784. }
  1785. /**
  1786. * Adds the function body for the hydrate method
  1787. * @param string &$script The script will be modified in this method.
  1788. * @see addHydrate()
  1789. */
  1790. protected function addHydrateBody(&$script)
  1791. {
  1792. $table = $this->getTable();
  1793. $platform = $this->getPlatform();
  1794. $script .= "
  1795. try {
  1796. ";
  1797. $n = 0;
  1798. foreach ($table->getColumns() as $col) {
  1799. if (!$col->isLazyLoad()) {
  1800. $clo = strtolower($col->getName());
  1801. if ($col->getType() === PropelTypes::CLOB_EMU && $this->getPlatform() instanceof OraclePlatform) {
  1802. // PDO_OCI returns a stream for CLOB objects, while other PDO adapters return a string...
  1803. $script .= "
  1804. \$this->$clo = stream_get_contents(\$row[\$startcol + $n]);";
  1805. } elseif ($col->isLobType() && !$platform->hasStreamBlobImpl()) {
  1806. $script .= "
  1807. if (\$row[\$startcol + $n] !== null) {
  1808. \$this->$clo = fopen('php://memory', 'r+');
  1809. fwrite(\$this->$clo, \$row[\$startcol + $n]);
  1810. rewind(\$this->$clo);
  1811. } else {
  1812. \$this->$clo = null;
  1813. }";
  1814. } elseif ($col->isPhpPrimitiveType()) {
  1815. $script .= "
  1816. \$this->$clo = (\$row[\$startcol + $n] !== null) ? (".$col->getPhpType().") \$row[\$startcol + $n] : null;";
  1817. } elseif ($col->getType() === PropelTypes::OBJECT) {
  1818. $script .= "
  1819. \$this->$clo = \$row[\$startcol + $n];";
  1820. } elseif ($col->getType() === PropelTypes::PHP_ARRAY) {
  1821. $cloUnserialized = $clo . '_unserialized';
  1822. $script .= "
  1823. \$this->$clo = \$row[\$startcol + $n];
  1824. \$this->$cloUnserialized = null;";
  1825. } elseif ($col->isPhpObjectType()) {
  1826. $script .= "
  1827. \$this->$clo = (\$row[\$startcol + $n] !== null) ? new ".$col->getPhpType()."(\$row[\$startcol + $n]) : null;";
  1828. } else {
  1829. $script .= "
  1830. \$this->$clo = \$row[\$startcol + $n];";
  1831. }
  1832. $n++;
  1833. } // if col->isLazyLoad()
  1834. } /* foreach */
  1835. if ($this->getBuildProperty("addSaveMethod")) {
  1836. $script .= "
  1837. \$this->resetModified();
  1838. ";
  1839. }
  1840. $script .= "
  1841. \$this->setNew(false);
  1842. if (\$rehydrate) {
  1843. \$this->ensureConsistency();
  1844. }
  1845. \$this->postHydrate(\$row, \$startcol, \$rehydrate);";
  1846. $this->applyBehaviorModifier('postHydrate', $script, " ");
  1847. $script .= "
  1848. return \$startcol + $n; // $n = ".$this->getPeerClassname()."::NUM_HYDRATE_COLUMNS.
  1849. } catch (Exception \$e) {
  1850. throw new PropelException(\"Error populating ".$this->getStubObjectBuilder()->getClassname()." object\", \$e);
  1851. }";
  1852. }
  1853. /**
  1854. * Adds the function close for the hydrate method
  1855. * @param string &$script The script will be modified in this method.
  1856. * @see addHydrate()
  1857. */
  1858. protected function addHydrateClose(&$script)
  1859. {
  1860. $script .= "
  1861. }
  1862. ";
  1863. }
  1864. /**
  1865. * Adds the buildPkeyCriteria method
  1866. * @param string &$script The script will be modified in this method.
  1867. **/
  1868. protected function addBuildPkeyCriteria(&$script)
  1869. {
  1870. $this->addBuildPkeyCriteriaComment($script);
  1871. $this->addBuildPkeyCriteriaOpen($script);
  1872. $this->addBuildPkeyCriteriaBody($script);
  1873. $this->addBuildPkeyCriteriaClose($script);
  1874. }
  1875. /**
  1876. * Adds the comment for the buildPkeyCriteria method
  1877. * @param string &$script The script will be modified in this method.
  1878. * @see addBuildPkeyCriteria()
  1879. **/
  1880. protected function addBuildPkeyCriteriaComment(&$script)
  1881. {
  1882. $script .= "
  1883. /**
  1884. * Builds a Criteria object containing the primary key for this object.
  1885. *
  1886. * Unlike buildCriteria() this method includes the primary key values regardless
  1887. * of whether or not they have been modified.
  1888. *
  1889. * @return Criteria The Criteria object containing value(s) for primary key(s).
  1890. */";
  1891. }
  1892. /**
  1893. * Adds the function declaration for the buildPkeyCriteria method
  1894. * @param string &$script The script will be modified in this method.
  1895. * @see addBuildPkeyCriteria()
  1896. **/
  1897. protected function addBuildPkeyCriteriaOpen(&$script)
  1898. {
  1899. $script .= "
  1900. public function buildPkeyCriteria()
  1901. {";
  1902. }
  1903. /**
  1904. * Adds the function body for the buildPkeyCriteria method
  1905. * @param string &$script The script will be modified in this method.
  1906. * @see addBuildPkeyCriteria()
  1907. **/
  1908. protected function addBuildPkeyCriteriaBody(&$script)
  1909. {
  1910. $script .= "
  1911. \$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);";
  1912. foreach ($this->getTable()->getPrimaryKey() as $col) {
  1913. $clo = strtolower($col->getName());
  1914. $script .= "
  1915. \$criteria->add(".$this->getColumnConstant($col).", \$this->$clo);";
  1916. }
  1917. }
  1918. /**
  1919. * Adds the function close for the buildPkeyCriteria method
  1920. * @param string &$script The script will be modified in this method.
  1921. * @see addBuildPkeyCriteria()
  1922. **/
  1923. protected function addBuildPkeyCriteriaClose(&$script)
  1924. {
  1925. $script .= "
  1926. return \$criteria;
  1927. }
  1928. ";
  1929. }
  1930. /**
  1931. * Adds the buildCriteria method
  1932. * @param string &$script The script will be modified in this method.
  1933. **/
  1934. protected function addBuildCriteria(&$script)
  1935. {
  1936. $this->addBuildCriteriaComment($script);
  1937. $this->addBuildCriteriaOpen($script);
  1938. $this->addBuildCriteriaBody($script);
  1939. $this->addBuildCriteriaClose($script);
  1940. }
  1941. /**
  1942. * Adds comment for the buildCriteria method
  1943. * @param string &$script The script will be modified in this method.
  1944. * @see addBuildCriteria()
  1945. **/
  1946. protected function addBuildCriteriaComment(&$script)
  1947. {
  1948. $script .= "
  1949. /**
  1950. * Build a Criteria object containing the values of all modified columns in this object.
  1951. *
  1952. * @return Criteria The Criteria object containing all modified values.
  1953. */";
  1954. }
  1955. /**
  1956. * Adds the function declaration of the buildCriteria method
  1957. * @param string &$script The script will be modified in this method.
  1958. * @see addBuildCriteria()
  1959. **/
  1960. protected function addBuildCriteriaOpen(&$script)
  1961. {
  1962. $script .= "
  1963. public function buildCriteria()
  1964. {";
  1965. }
  1966. /**
  1967. * Adds the function body of the buildCriteria method
  1968. * @param string &$script The script will be modified in this method.
  1969. * @see addBuildCriteria()
  1970. **/
  1971. protected function addBuildCriteriaBody(&$script)
  1972. {
  1973. $script .= "
  1974. \$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);
  1975. ";
  1976. foreach ($this->getTable()->getColumns() as $col) {
  1977. $clo = strtolower($col->getName());
  1978. $script .= "
  1979. if (\$this->isColumnModified(".$this->getColumnConstant($col).")) \$criteria->add(".$this->getColumnConstant($col).", \$this->$clo);";
  1980. }
  1981. }
  1982. /**
  1983. * Adds the function close of the buildCriteria method
  1984. * @param string &$script The script will be modified in this method.
  1985. * @see addBuildCriteria()
  1986. **/
  1987. protected function addBuildCriteriaClose(&$script)
  1988. {
  1989. $script .= "
  1990. return \$criteria;
  1991. }
  1992. ";
  1993. }
  1994. /**
  1995. * Adds the toArray method
  1996. * @param string &$script The script will be modified in this method.
  1997. **/
  1998. protected function addToArray(&$script)
  1999. {
  2000. $fks = $this->getTable()->getForeignKeys();
  2001. $referrers = $this->getTable()->getReferrers();
  2002. $hasFks = count($fks) > 0 || count($referrers) > 0;
  2003. $objectClassName = $this->getObjectClassname();
  2004. $pkGetter = $this->getTable()->hasCompositePrimaryKey() ? 'serialize($this->getPrimaryKey())' : '$this->getPrimaryKey()';
  2005. $defaultKeyType = $this->getDefaultKeyType();
  2006. $script .= "
  2007. /**
  2008. * Exports the object as an array.
  2009. *
  2010. * You can specify the key type of the array by passing one of the class
  2011. * type constants.
  2012. *
  2013. * @param string \$keyType (optional) One of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME,
  2014. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2015. * Defaults to BasePeer::$defaultKeyType.
  2016. * @param boolean \$includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to true.
  2017. * @param array \$alreadyDumpedObjects List of objects to skip to avoid recursion";
  2018. if ($hasFks) {
  2019. $script .= "
  2020. * @param boolean \$includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE.";
  2021. }
  2022. $script .= "
  2023. *
  2024. * @return array an associative array containing the field names (as keys) and field values
  2025. */
  2026. public function toArray(\$keyType = BasePeer::$defaultKeyType, \$includeLazyLoadColumns = true, \$alreadyDumpedObjects = array()" . ($hasFks ? ", \$includeForeignObjects = false" : '') . ")
  2027. {
  2028. if (isset(\$alreadyDumpedObjects['$objectClassName'][$pkGetter])) {
  2029. return '*RECURSION*';
  2030. }
  2031. \$alreadyDumpedObjects['$objectClassName'][$pkGetter] = true;
  2032. \$keys = ".$this->getPeerClassname()."::getFieldNames(\$keyType);
  2033. \$result = array(";
  2034. foreach ($this->getTable()->getColumns() as $num => $col) {
  2035. if ($col->isLazyLoad()) {
  2036. $script .= "
  2037. \$keys[$num] => (\$includeLazyLoadColumns) ? \$this->get".$col->getPhpName()."() : null,";
  2038. } else {
  2039. $script .= "
  2040. \$keys[$num] => \$this->get".$col->getPhpName()."(),";
  2041. }
  2042. }
  2043. $script .= "
  2044. );";
  2045. if ($hasFks) {
  2046. $script .= "
  2047. if (\$includeForeignObjects) {";
  2048. foreach ($fks as $fk) {
  2049. $script .= "
  2050. if (null !== \$this->" . $this->getFKVarName($fk) . ") {
  2051. \$result['" . $this->getFKPhpNameAffix($fk, $plural = false) . "'] = \$this->" . $this->getFKVarName($fk) . "->toArray(\$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects, true);
  2052. }";
  2053. }
  2054. foreach ($referrers as $fk) {
  2055. if ($fk->isLocalPrimaryKey()) {
  2056. $script .= "
  2057. if (null !== \$this->" . $this->getPKRefFKVarName($fk) . ") {
  2058. \$result['" . $this->getRefFKPhpNameAffix($fk, $plural = false) . "'] = \$this->" . $this->getPKRefFKVarName($fk) . "->toArray(\$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects, true);
  2059. }";
  2060. } else {
  2061. $script .= "
  2062. if (null !== \$this->" . $this->getRefFKCollVarName($fk) . ") {
  2063. \$result['" . $this->getRefFKPhpNameAffix($fk, $plural = true) . "'] = \$this->" . $this->getRefFKCollVarName($fk) . "->toArray(null, true, \$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects);
  2064. }";
  2065. }
  2066. }
  2067. $script .= "
  2068. }";
  2069. }
  2070. $script .= "
  2071. return \$result;
  2072. }
  2073. ";
  2074. } // addToArray()
  2075. /**
  2076. * Adds the getByName method
  2077. * @param string &$script The script will be modified in this method.
  2078. **/
  2079. protected function addGetByName(&$script)
  2080. {
  2081. $this->addGetByNameComment($script);
  2082. $this->addGetByNameOpen($script);
  2083. $this->addGetByNameBody($script);
  2084. $this->addGetByNameClose($script);
  2085. }
  2086. /**
  2087. * Adds the comment for the getByName method
  2088. * @param string &$script The script will be modified in this method.
  2089. * @see addGetByName
  2090. **/
  2091. protected function addGetByNameComment(&$script)
  2092. {
  2093. $defaultKeyType = $this->getDefaultKeyType();
  2094. $script .= "
  2095. /**
  2096. * Retrieves a field from the object by name passed in as a string.
  2097. *
  2098. * @param string \$name name
  2099. * @param string \$type The type of fieldname the \$name is of:
  2100. * one of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME
  2101. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2102. * Defaults to BasePeer::$defaultKeyType
  2103. * @return mixed Value of field.
  2104. */";
  2105. }
  2106. /**
  2107. * Adds the function declaration for the getByName method
  2108. * @param string &$script The script will be modified in this method.
  2109. * @see addGetByName
  2110. **/
  2111. protected function addGetByNameOpen(&$script)
  2112. {
  2113. $defaultKeyType = $this->getDefaultKeyType();
  2114. $script .= "
  2115. public function getByName(\$name, \$type = BasePeer::$defaultKeyType)
  2116. {";
  2117. }
  2118. /**
  2119. * Adds the function body for the getByName method
  2120. * @param string &$script The script will be modified in this method.
  2121. * @see addGetByName
  2122. **/
  2123. protected function addGetByNameBody(&$script)
  2124. {
  2125. $script .= "
  2126. \$pos = ".$this->getPeerClassname()."::translateFieldName(\$name, \$type, BasePeer::TYPE_NUM);
  2127. \$field = \$this->getByPosition(\$pos);";
  2128. }
  2129. /**
  2130. * Adds the function close for the getByName method
  2131. * @param string &$script The script will be modified in this method.
  2132. * @see addGetByName
  2133. **/
  2134. protected function addGetByNameClose(&$script)
  2135. {
  2136. $script .= "
  2137. return \$field;
  2138. }
  2139. ";
  2140. }
  2141. /**
  2142. * Adds the getByPosition method
  2143. * @param string &$script The script will be modified in this method.
  2144. **/
  2145. protected function addGetByPosition(&$script)
  2146. {
  2147. $this->addGetByPositionComment($script);
  2148. $this->addGetByPositionOpen($script);
  2149. $this->addGetByPositionBody($script);
  2150. $this->addGetByPositionClose($script);
  2151. }
  2152. /**
  2153. * Adds comment for the getByPosition method
  2154. * @param string &$script The script will be modified in this method.
  2155. * @see addGetByPosition
  2156. **/
  2157. protected function addGetByPositionComment(&$script)
  2158. {
  2159. $script .= "
  2160. /**
  2161. * Retrieves a field from the object by Position as specified in the xml schema.
  2162. * Zero-based.
  2163. *
  2164. * @param int \$pos position in xml schema
  2165. * @return mixed Value of field at \$pos
  2166. */";
  2167. }
  2168. /**
  2169. * Adds the function declaration for the getByPosition method
  2170. * @param string &$script The script will be modified in this method.
  2171. * @see addGetByPosition
  2172. **/
  2173. protected function addGetByPositionOpen(&$script)
  2174. {
  2175. $script .= "
  2176. public function getByPosition(\$pos)
  2177. {";
  2178. }
  2179. /**
  2180. * Adds the function body for the getByPosition method
  2181. * @param string &$script The script will be modified in this method.
  2182. * @see addGetByPosition
  2183. **/
  2184. protected function addGetByPositionBody(&$script)
  2185. {
  2186. $table = $this->getTable();
  2187. $script .= "
  2188. switch (\$pos) {";
  2189. $i = 0;
  2190. foreach ($table->getColumns() as $col) {
  2191. $cfc = $col->getPhpName();
  2192. $script .= "
  2193. case $i:
  2194. return \$this->get$cfc();
  2195. break;";
  2196. $i++;
  2197. } /* foreach */
  2198. $script .= "
  2199. default:
  2200. return null;
  2201. break;
  2202. } // switch()";
  2203. }
  2204. /**
  2205. * Adds the function close for the getByPosition method
  2206. * @param string &$script The script will be modified in this method.
  2207. * @see addGetByPosition
  2208. **/
  2209. protected function addGetByPositionClose(&$script)
  2210. {
  2211. $script .= "
  2212. }
  2213. ";
  2214. }
  2215. protected function addSetByName(&$script)
  2216. {
  2217. $table = $this->getTable();
  2218. $defaultKeyType = $this->getDefaultKeyType();
  2219. $script .= "
  2220. /**
  2221. * Sets a field from the object by name passed in as a string.
  2222. *
  2223. * @param string \$name peer name
  2224. * @param mixed \$value field value
  2225. * @param string \$type The type of fieldname the \$name is of:
  2226. * one of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME
  2227. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2228. * Defaults to BasePeer::$defaultKeyType
  2229. * @return void
  2230. */
  2231. public function setByName(\$name, \$value, \$type = BasePeer::$defaultKeyType)
  2232. {
  2233. \$pos = ".$this->getPeerClassname()."::translateFieldName(\$name, \$type, BasePeer::TYPE_NUM);
  2234. \$this->setByPosition(\$pos, \$value);
  2235. }
  2236. ";
  2237. }
  2238. protected function addSetByPosition(&$script)
  2239. {
  2240. $table = $this->getTable();
  2241. $script .= "
  2242. /**
  2243. * Sets a field from the object by Position as specified in the xml schema.
  2244. * Zero-based.
  2245. *
  2246. * @param int \$pos position in xml schema
  2247. * @param mixed \$value field value
  2248. * @return void
  2249. */
  2250. public function setByPosition(\$pos, \$value)
  2251. {
  2252. switch (\$pos) {";
  2253. $i = 0;
  2254. foreach ($table->getColumns() as $col) {
  2255. $cfc = $col->getPhpName();
  2256. $cptype = $col->getPhpType();
  2257. $script .= "
  2258. case $i:";
  2259. if (PropelTypes::ENUM === $col->getType()) {
  2260. $script .= "
  2261. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  2262. if (isset(\$valueSet[\$value])) {
  2263. \$value = \$valueSet[\$value];
  2264. }";
  2265. } elseif (PropelTypes::PHP_ARRAY === $col->getType()) {
  2266. $script .= "
  2267. if (!is_array(\$value)) {
  2268. \$v = trim(substr(\$value, 2, -2));
  2269. \$value = \$v ? explode(' | ', \$v) : array();
  2270. }";
  2271. }
  2272. $script .= "
  2273. \$this->set$cfc(\$value);
  2274. break;";
  2275. $i++;
  2276. } /* foreach */
  2277. $script .= "
  2278. } // switch()
  2279. }
  2280. ";
  2281. } // addSetByPosition()
  2282. protected function addFromArray(&$script)
  2283. {
  2284. $defaultKeyType = $this->getDefaultKeyType();
  2285. $table = $this->getTable();
  2286. $script .= "
  2287. /**
  2288. * Populates the object using an array.
  2289. *
  2290. * This is particularly useful when populating an object from one of the
  2291. * request arrays (e.g. \$_POST). This method goes through the column
  2292. * names, checking to see whether a matching key exists in populated
  2293. * array. If so the setByName() method is called for that column.
  2294. *
  2295. * You can specify the key type of the array by additionally passing one
  2296. * of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME,
  2297. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2298. * The default key type is the column's BasePeer::$defaultKeyType
  2299. *
  2300. * @param array \$arr An array to populate the object from.
  2301. * @param string \$keyType The type of keys the array uses.
  2302. * @return void
  2303. */
  2304. public function fromArray(\$arr, \$keyType = BasePeer::$defaultKeyType)
  2305. {
  2306. \$keys = ".$this->getPeerClassname()."::getFieldNames(\$keyType);
  2307. ";
  2308. foreach ($table->getColumns() as $num => $col) {
  2309. $cfc = $col->getPhpName();
  2310. //TODO: remove. not used
  2311. $cptype = $col->getPhpType();
  2312. $script .= "
  2313. if (array_key_exists(\$keys[$num], \$arr)) \$this->set$cfc(\$arr[\$keys[$num]]);";
  2314. } /* foreach */
  2315. $script .= "
  2316. }
  2317. ";
  2318. } // addFromArray
  2319. /**
  2320. * Adds a delete() method to remove the object form the datastore.
  2321. * @param string &$script The script will be modified in this method.
  2322. */
  2323. protected function addDelete(&$script)
  2324. {
  2325. $this->addDeleteComment($script);
  2326. $this->addDeleteOpen($script);
  2327. $this->addDeleteBody($script);
  2328. $this->addDeleteClose($script);
  2329. }
  2330. /**
  2331. * Adds the comment for the delete function
  2332. * @param string &$script The script will be modified in this method.
  2333. * @see addDelete()
  2334. **/
  2335. protected function addDeleteComment(&$script)
  2336. {
  2337. $script .= "
  2338. /**
  2339. * Removes this object from datastore and sets delete attribute.
  2340. *
  2341. * @param PropelPDO \$con
  2342. * @return void
  2343. * @throws PropelException
  2344. * @throws Exception
  2345. * @see BaseObject::setDeleted()
  2346. * @see BaseObject::isDeleted()
  2347. */";
  2348. }
  2349. /**
  2350. * Adds the function declaration for the delete function
  2351. * @param string &$script The script will be modified in this method.
  2352. * @see addDelete()
  2353. **/
  2354. protected function addDeleteOpen(&$script)
  2355. {
  2356. $script .= "
  2357. public function delete(PropelPDO \$con = null)
  2358. {";
  2359. }
  2360. /**
  2361. * Adds the function body for the delete function
  2362. * @param string &$script The script will be modified in this method.
  2363. * @see addDelete()
  2364. **/
  2365. protected function addDeleteBody(&$script)
  2366. {
  2367. $script .= "
  2368. if (\$this->isDeleted()) {
  2369. throw new PropelException(\"This object has already been deleted.\");
  2370. }
  2371. if (\$con === null) {
  2372. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE);
  2373. }
  2374. \$con->beginTransaction();
  2375. try {
  2376. \$deleteQuery = ".$this->getQueryClassname()."::create()
  2377. ->filterByPrimaryKey(\$this->getPrimaryKey());";
  2378. if ($this->getGeneratorConfig()->getBuildProperty('addHooks')) {
  2379. $script .= "
  2380. \$ret = \$this->preDelete(\$con);";
  2381. // apply behaviors
  2382. $this->applyBehaviorModifier('preDelete', $script, " ");
  2383. $script .= "
  2384. if (\$ret) {
  2385. \$deleteQuery->delete(\$con);
  2386. \$this->postDelete(\$con);";
  2387. // apply behaviors
  2388. $this->applyBehaviorModifier('postDelete', $script, " ");
  2389. $script .= "
  2390. \$con->commit();
  2391. \$this->setDeleted(true);
  2392. } else {
  2393. \$con->commit();
  2394. }";
  2395. } else {
  2396. // apply behaviors
  2397. $this->applyBehaviorModifier('preDelete', $script, " ");
  2398. $script .= "
  2399. \$deleteQuery->delete(\$con);";
  2400. // apply behaviors
  2401. $this->applyBehaviorModifier('postDelete', $script, " ");
  2402. $script .= "
  2403. \$con->commit();
  2404. \$this->setDeleted(true);";
  2405. }
  2406. $script .= "
  2407. } catch (Exception \$e) {
  2408. \$con->rollBack();
  2409. throw \$e;
  2410. }";
  2411. }
  2412. /**
  2413. * Adds the function close for the delete function
  2414. * @param string &$script The script will be modified in this method.
  2415. * @see addDelete()
  2416. **/
  2417. protected function addDeleteClose(&$script)
  2418. {
  2419. $script .= "
  2420. }
  2421. ";
  2422. } // addDelete()
  2423. /**
  2424. * Adds a reload() method to re-fetch the data for this object from the database.
  2425. * @param string &$script The script will be modified in this method.
  2426. */
  2427. protected function addReload(&$script)
  2428. {
  2429. $table = $this->getTable();
  2430. $script .= "
  2431. /**
  2432. * Reloads this object from datastore based on primary key and (optionally) resets all associated objects.
  2433. *
  2434. * This will only work if the object has been saved and has a valid primary key set.
  2435. *
  2436. * @param boolean \$deep (optional) Whether to also de-associated any related objects.
  2437. * @param PropelPDO \$con (optional) The PropelPDO connection to use.
  2438. * @return void
  2439. * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db
  2440. */
  2441. public function reload(\$deep = false, PropelPDO \$con = null)
  2442. {
  2443. if (\$this->isDeleted()) {
  2444. throw new PropelException(\"Cannot reload a deleted object.\");
  2445. }
  2446. if (\$this->isNew()) {
  2447. throw new PropelException(\"Cannot reload an unsaved object.\");
  2448. }
  2449. if (\$con === null) {
  2450. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ);
  2451. }
  2452. // We don't need to alter the object instance pool; we're just modifying this instance
  2453. // already in the pool.
  2454. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$this->buildPkeyCriteria(), \$con);
  2455. \$row = \$stmt->fetch(PDO::FETCH_NUM);
  2456. \$stmt->closeCursor();
  2457. if (!\$row) {
  2458. throw new PropelException('Cannot find matching row in the database to reload object values.');
  2459. }
  2460. \$this->hydrate(\$row, 0, true); // rehydrate
  2461. ";
  2462. // support for lazy load columns
  2463. foreach ($table->getColumns() as $col) {
  2464. if ($col->isLazyLoad()) {
  2465. $clo = strtolower($col->getName());
  2466. $script .= "
  2467. // Reset the $clo lazy-load column
  2468. \$this->" . $clo . " = null;
  2469. \$this->".$clo."_isLoaded = false;
  2470. ";
  2471. }
  2472. }
  2473. $script .= "
  2474. if (\$deep) { // also de-associate any related objects?
  2475. ";
  2476. foreach ($table->getForeignKeys() as $fk) {
  2477. $varName = $this->getFKVarName($fk);
  2478. $script .= "
  2479. \$this->".$varName." = null;";
  2480. }
  2481. foreach ($table->getReferrers() as $refFK) {
  2482. if ($refFK->isLocalPrimaryKey()) {
  2483. $script .= "
  2484. \$this->".$this->getPKRefFKVarName($refFK)." = null;
  2485. ";
  2486. } else {
  2487. $script .= "
  2488. \$this->".$this->getRefFKCollVarName($refFK)." = null;
  2489. ";
  2490. }
  2491. }
  2492. foreach ($table->getCrossFks() as $fkList) {
  2493. list($refFK, $crossFK) = $fkList;
  2494. $script .= "
  2495. \$this->" . $this->getCrossFKVarName($crossFK). " = null;";
  2496. }
  2497. $script .= "
  2498. } // if (deep)
  2499. }
  2500. ";
  2501. } // addReload()
  2502. /**
  2503. * Adds the methods related to refreshing, saving and deleting the object.
  2504. * @param string &$script The script will be modified in this method.
  2505. */
  2506. protected function addManipulationMethods(&$script)
  2507. {
  2508. $this->addReload($script);
  2509. $this->addDelete($script);
  2510. $this->addSave($script);
  2511. $this->addDoSave($script);
  2512. $script .= $this->addDoInsert();
  2513. $script .= $this->addDoUpdate();
  2514. }
  2515. /**
  2516. * Adds the methods related to validationg the object.
  2517. * @param string &$script The script will be modified in this method.
  2518. */
  2519. protected function addValidationMethods(&$script)
  2520. {
  2521. $this->addValidationFailuresAttribute($script);
  2522. $this->addGetValidationFailures($script);
  2523. $this->addValidate($script);
  2524. $this->addDoValidate($script);
  2525. }
  2526. /**
  2527. * Adds the $validationFailures attribute to store ValidationFailed objects.
  2528. * @param string &$script The script will be modified in this method.
  2529. */
  2530. protected function addValidationFailuresAttribute(&$script)
  2531. {
  2532. $script .= "
  2533. /**
  2534. * Array of ValidationFailed objects.
  2535. * @var array ValidationFailed[]
  2536. */
  2537. protected \$validationFailures = array();
  2538. ";
  2539. }
  2540. /**
  2541. * Adds the getValidationFailures() method.
  2542. * @param string &$script The script will be modified in this method.
  2543. */
  2544. protected function addGetValidationFailures(&$script)
  2545. {
  2546. $script .= "
  2547. /**
  2548. * Gets any ValidationFailed objects that resulted from last call to validate().
  2549. *
  2550. *
  2551. * @return array ValidationFailed[]
  2552. * @see validate()
  2553. */
  2554. public function getValidationFailures()
  2555. {
  2556. return \$this->validationFailures;
  2557. }
  2558. ";
  2559. } // addGetValidationFailures()
  2560. /**
  2561. * Adds the correct getPrimaryKey() method for this object.
  2562. * @param string &$script The script will be modified in this method.
  2563. */
  2564. protected function addGetPrimaryKey(&$script)
  2565. {
  2566. $pkeys = $this->getTable()->getPrimaryKey();
  2567. if (count($pkeys) == 1) {
  2568. $this->addGetPrimaryKey_SinglePK($script);
  2569. } elseif (count($pkeys) > 1) {
  2570. $this->addGetPrimaryKey_MultiPK($script);
  2571. } else {
  2572. // no primary key -- this is deprecated, since we don't *need* this method anymore
  2573. $this->addGetPrimaryKey_NoPK($script);
  2574. }
  2575. }
  2576. /**
  2577. * Adds the getPrimaryKey() method for tables that contain a single-column primary key.
  2578. * @param string &$script The script will be modified in this method.
  2579. */
  2580. protected function addGetPrimaryKey_SinglePK(&$script)
  2581. {
  2582. $table = $this->getTable();
  2583. $pkeys = $table->getPrimaryKey();
  2584. $cptype = $pkeys[0]->getPhpType();
  2585. $script .= "
  2586. /**
  2587. * Returns the primary key for this object (row).
  2588. * @return $cptype
  2589. */
  2590. public function getPrimaryKey()
  2591. {
  2592. return \$this->get".$pkeys[0]->getPhpName()."();
  2593. }
  2594. ";
  2595. } // addetPrimaryKey_SingleFK
  2596. /**
  2597. * Adds the setPrimaryKey() method for tables that contain a multi-column primary key.
  2598. * @param string &$script The script will be modified in this method.
  2599. */
  2600. protected function addGetPrimaryKey_MultiPK(&$script)
  2601. {
  2602. $script .= "
  2603. /**
  2604. * Returns the composite primary key for this object.
  2605. * The array elements will be in same order as specified in XML.
  2606. * @return array
  2607. */
  2608. public function getPrimaryKey()
  2609. {
  2610. \$pks = array();";
  2611. $i = 0;
  2612. foreach ($this->getTable()->getPrimaryKey() as $pk) {
  2613. $script .= "
  2614. \$pks[$i] = \$this->get".$pk->getPhpName()."();";
  2615. $i++;
  2616. } /* foreach */
  2617. $script .= "
  2618. return \$pks;
  2619. }
  2620. ";
  2621. } // addGetPrimaryKey_MultiFK()
  2622. /**
  2623. * Adds the getPrimaryKey() method for objects that have no primary key.
  2624. * This "feature" is dreprecated, since the getPrimaryKey() method is not required
  2625. * by the Persistent interface (or used by the templates). Hence, this method is also
  2626. * deprecated.
  2627. * @param string &$script The script will be modified in this method.
  2628. * @deprecated
  2629. */
  2630. protected function addGetPrimaryKey_NoPK(&$script)
  2631. {
  2632. $script .= "
  2633. /**
  2634. * Returns null since this table doesn't have a primary key.
  2635. * This method exists only for BC and is deprecated!
  2636. * @return null
  2637. */
  2638. public function getPrimaryKey()
  2639. {
  2640. return null;
  2641. }
  2642. ";
  2643. }
  2644. /**
  2645. * Adds the correct setPrimaryKey() method for this object.
  2646. * @param string &$script The script will be modified in this method.
  2647. */
  2648. protected function addSetPrimaryKey(&$script)
  2649. {
  2650. $pkeys = $this->getTable()->getPrimaryKey();
  2651. if (count($pkeys) == 1) {
  2652. $this->addSetPrimaryKey_SinglePK($script);
  2653. } elseif (count($pkeys) > 1) {
  2654. $this->addSetPrimaryKey_MultiPK($script);
  2655. } else {
  2656. // no primary key -- this is deprecated, since we don't *need* this method anymore
  2657. $this->addSetPrimaryKey_NoPK($script);
  2658. }
  2659. }
  2660. /**
  2661. * Adds the setPrimaryKey() method for tables that contain a single-column primary key.
  2662. * @param string &$script The script will be modified in this method.
  2663. */
  2664. protected function addSetPrimaryKey_SinglePK(&$script)
  2665. {
  2666. $pkeys = $this->getTable()->getPrimaryKey();
  2667. $col = $pkeys[0];
  2668. $clo=strtolower($col->getName());
  2669. $ctype = $col->getPhpType();
  2670. $script .= "
  2671. /**
  2672. * Generic method to set the primary key ($clo column).
  2673. *
  2674. * @param $ctype \$key Primary key.
  2675. * @return void
  2676. */
  2677. public function setPrimaryKey(\$key)
  2678. {
  2679. \$this->set".$col->getPhpName()."(\$key);
  2680. }
  2681. ";
  2682. } // addSetPrimaryKey_SinglePK
  2683. /**
  2684. * Adds the setPrimaryKey() method for tables that contain a multi-columnprimary key.
  2685. * @param string &$script The script will be modified in this method.
  2686. */
  2687. protected function addSetPrimaryKey_MultiPK(&$script)
  2688. {
  2689. $script .="
  2690. /**
  2691. * Set the [composite] primary key.
  2692. *
  2693. * @param array \$keys The elements of the composite key (order must match the order in XML file).
  2694. * @return void
  2695. */
  2696. public function setPrimaryKey(\$keys)
  2697. {";
  2698. $i = 0;
  2699. foreach ($this->getTable()->getPrimaryKey() as $pk) {
  2700. $pktype = $pk->getPhpType();
  2701. $script .= "
  2702. \$this->set".$pk->getPhpName()."(\$keys[$i]);";
  2703. $i++;
  2704. } /* foreach ($table->getPrimaryKey() */
  2705. $script .= "
  2706. }
  2707. ";
  2708. } // addSetPrimaryKey_MultiPK
  2709. /**
  2710. * Adds the setPrimaryKey() method for objects that have no primary key.
  2711. * This "feature" is dreprecated, since the setPrimaryKey() method is not required
  2712. * by the Persistent interface (or used by the templates). Hence, this method is also
  2713. * deprecated.
  2714. * @param string &$script The script will be modified in this method.
  2715. * @deprecated
  2716. */
  2717. protected function addSetPrimaryKey_NoPK(&$script)
  2718. {
  2719. $script .="
  2720. /**
  2721. * Dummy primary key setter.
  2722. *
  2723. * This function only exists to preserve backwards compatibility. It is no longer
  2724. * needed or required by the Persistent interface. It will be removed in next BC-breaking
  2725. * release of Propel.
  2726. *
  2727. * @deprecated
  2728. */
  2729. public function setPrimaryKey(\$pk)
  2730. {
  2731. // do nothing, because this object doesn't have any primary keys
  2732. }
  2733. ";
  2734. }
  2735. /**
  2736. * Adds the isPrimaryKeyNull() method
  2737. * @param string &$script The script will be modified in this method.
  2738. */
  2739. protected function addIsPrimaryKeyNull(&$script)
  2740. {
  2741. $table = $this->getTable();
  2742. $pkeys = $table->getPrimaryKey();
  2743. $script .= "
  2744. /**
  2745. * Returns true if the primary key for this object is null.
  2746. * @return boolean
  2747. */
  2748. public function isPrimaryKeyNull()
  2749. {";
  2750. if (count($pkeys) == 1) {
  2751. $script .= "
  2752. return null === \$this->get" . $pkeys[0]->getPhpName() . "();";
  2753. } else {
  2754. $tests = array();
  2755. foreach ($pkeys as $pkey) {
  2756. $tests[]= "(null === \$this->get" . $pkey->getPhpName() . "())";
  2757. }
  2758. $script .= "
  2759. return " . join(' && ', $tests) . ";";
  2760. }
  2761. $script .= "
  2762. }
  2763. ";
  2764. } // addetPrimaryKey_SingleFK
  2765. // --------------------------------------------------------------------
  2766. // Complex OM Methods
  2767. // --------------------------------------------------------------------
  2768. /**
  2769. * Constructs variable name for fkey-related objects.
  2770. * @param ForeignKey $fk
  2771. * @return string
  2772. */
  2773. public function getFKVarName(ForeignKey $fk)
  2774. {
  2775. return 'a' . $this->getFKPhpNameAffix($fk, $plural = false);
  2776. }
  2777. /**
  2778. * Constructs variable name for objects which referencing current table by specified foreign key.
  2779. * @param ForeignKey $fk
  2780. * @return string
  2781. */
  2782. public function getRefFKCollVarName(ForeignKey $fk)
  2783. {
  2784. return 'coll' . $this->getRefFKPhpNameAffix($fk, $plural = true);
  2785. }
  2786. /**
  2787. * Constructs variable name for single object which references current table by specified foreign key
  2788. * which is ALSO a primary key (hence one-to-one relationship).
  2789. * @param ForeignKey $fk
  2790. * @return string
  2791. */
  2792. public function getPKRefFKVarName(ForeignKey $fk)
  2793. {
  2794. return 'single' . $this->getRefFKPhpNameAffix($fk, $plural = false);
  2795. }
  2796. // ----------------------------------------------------------------
  2797. //
  2798. // F K M E T H O D S
  2799. //
  2800. // ----------------------------------------------------------------
  2801. /**
  2802. * Adds the methods that get & set objects related by foreign key to the current object.
  2803. * @param string &$script The script will be modified in this method.
  2804. */
  2805. protected function addFKMethods(&$script)
  2806. {
  2807. foreach ($this->getTable()->getForeignKeys() as $fk) {
  2808. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($fk->getForeignTable()));
  2809. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($fk->getForeignTable()));
  2810. $this->addFKMutator($script, $fk);
  2811. $this->addFKAccessor($script, $fk);
  2812. } // foreach fk
  2813. }
  2814. /**
  2815. * Adds the class attributes that are needed to store fkey related objects.
  2816. * @param string &$script The script will be modified in this method.
  2817. */
  2818. protected function addFKAttributes(&$script, ForeignKey $fk)
  2819. {
  2820. $className = $this->getForeignTable($fk)->getPhpName();
  2821. $varName = $this->getFKVarName($fk);
  2822. $script .= "
  2823. /**
  2824. * @var $className
  2825. */
  2826. protected $".$varName.";
  2827. ";
  2828. }
  2829. /**
  2830. * Adds the mutator (setter) method for setting an fkey related object.
  2831. * @param string &$script The script will be modified in this method.
  2832. */
  2833. protected function addFKMutator(&$script, ForeignKey $fk)
  2834. {
  2835. $table = $this->getTable();
  2836. $tblFK = $this->getForeignTable($fk);
  2837. $joinTableObjectBuilder = $this->getNewObjectBuilder($tblFK);
  2838. $className = $joinTableObjectBuilder->getObjectClassname();
  2839. $varName = $this->getFKVarName($fk);
  2840. $script .= "
  2841. /**
  2842. * Declares an association between this object and a $className object.
  2843. *
  2844. * @param $className \$v
  2845. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  2846. * @throws PropelException
  2847. */
  2848. public function set".$this->getFKPhpNameAffix($fk, $plural = false)."($className \$v = null)
  2849. {";
  2850. foreach ($fk->getLocalColumns() as $columnName) {
  2851. $column = $table->getColumn($columnName);
  2852. $lfmap = $fk->getLocalForeignMapping();
  2853. $colFKName = $lfmap[$columnName];
  2854. $colFK = $tblFK->getColumn($colFKName);
  2855. $script .= "
  2856. if (\$v === null) {
  2857. \$this->set".$column->getPhpName()."(".$this->getDefaultValueString($column).");
  2858. } else {
  2859. \$this->set".$column->getPhpName()."(\$v->get".$colFK->getPhpName()."());
  2860. }
  2861. ";
  2862. } /* foreach local col */
  2863. $script .= "
  2864. \$this->$varName = \$v;
  2865. ";
  2866. // Now add bi-directional relationship binding, taking into account whether this is
  2867. // a one-to-one relationship.
  2868. if ($fk->isLocalPrimaryKey()) {
  2869. $script .= "
  2870. // Add binding for other direction of this 1:1 relationship.
  2871. if (\$v !== null) {
  2872. \$v->set".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);
  2873. }
  2874. ";
  2875. } else {
  2876. $script .= "
  2877. // Add binding for other direction of this n:n relationship.
  2878. // If this object has already been added to the $className object, it will not be re-added.
  2879. if (\$v !== null) {
  2880. \$v->add".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);
  2881. }
  2882. ";
  2883. }
  2884. $script .= "
  2885. return \$this;
  2886. }
  2887. ";
  2888. }
  2889. /**
  2890. * Adds the accessor (getter) method for getting an fkey related object.
  2891. * @param string &$script The script will be modified in this method.
  2892. */
  2893. protected function addFKAccessor(&$script, ForeignKey $fk)
  2894. {
  2895. $table = $this->getTable();
  2896. $varName = $this->getFKVarName($fk);
  2897. $fkQueryBuilder = $this->getNewStubQueryBuilder($this->getForeignTable($fk));
  2898. $fkObjectBuilder = $this->getNewObjectBuilder($this->getForeignTable($fk))->getStubObjectBuilder();
  2899. $className = $fkObjectBuilder->getClassname(); // get the Classname that has maybe a prefix
  2900. $and = "";
  2901. $conditional = "";
  2902. $localColumns = array(); // foreign key local attributes names
  2903. // If the related columns are a primary key on the foreign table
  2904. // then use retrieveByPk() instead of doSelect() to take advantage
  2905. // of instance pooling
  2906. $useRetrieveByPk = $fk->isForeignPrimaryKey();
  2907. foreach ($fk->getLocalColumns() as $columnName) {
  2908. $lfmap = $fk->getLocalForeignMapping();
  2909. $localColumn = $table->getColumn($columnName);
  2910. $foreignColumn = $fk->getForeignTable()->getColumn($lfmap[$columnName]);
  2911. $column = $table->getColumn($columnName);
  2912. $cptype = $column->getPhpType();
  2913. $clo = strtolower($column->getName());
  2914. $localColumns[$foreignColumn->getPosition()] = '$this->'.$clo;
  2915. if ($cptype == "integer" || $cptype == "float" || $cptype == "double") {
  2916. $conditional .= $and . "\$this->". $clo ." != 0";
  2917. } elseif ($cptype == "string") {
  2918. $conditional .= $and . "(\$this->" . $clo ." !== \"\" && \$this->".$clo." !== null)";
  2919. } else {
  2920. $conditional .= $and . "\$this->" . $clo ." !== null";
  2921. }
  2922. $and = " && ";
  2923. }
  2924. ksort($localColumns); // restoring the order of the foreign PK
  2925. $localColumns = count($localColumns) > 1 ?
  2926. ('array('.implode(', ', $localColumns).')') : reset($localColumns);
  2927. $script .= "
  2928. /**
  2929. * Get the associated $className object
  2930. *
  2931. * @param PropelPDO \$con Optional Connection object.
  2932. * @return $className The associated $className object.
  2933. * @throws PropelException
  2934. */
  2935. public function get".$this->getFKPhpNameAffix($fk, $plural = false)."(PropelPDO \$con = null)
  2936. {";
  2937. $script .= "
  2938. if (\$this->$varName === null && ($conditional)) {";
  2939. if ($useRetrieveByPk) {
  2940. $script .= "
  2941. \$this->$varName = ".$fkQueryBuilder->getClassname()."::create()->findPk($localColumns, \$con);";
  2942. } else {
  2943. $script .= "
  2944. \$this->$varName = ".$fkQueryBuilder->getClassname()."::create()
  2945. ->filterBy" . $this->getRefFKPhpNameAffix($fk, $plural = false) . "(\$this) // here
  2946. ->findOne(\$con);";
  2947. }
  2948. if ($fk->isLocalPrimaryKey()) {
  2949. $script .= "
  2950. // Because this foreign key represents a one-to-one relationship, we will create a bi-directional association.
  2951. \$this->{$varName}->set".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);";
  2952. } else {
  2953. $script .= "
  2954. /* The following can be used additionally to
  2955. guarantee the related object contains a reference
  2956. to this object. This level of coupling may, however, be
  2957. undesirable since it could result in an only partially populated collection
  2958. in the referenced object.
  2959. \$this->{$varName}->add".$this->getRefFKPhpNameAffix($fk, $plural = true)."(\$this);
  2960. */";
  2961. }
  2962. $script .= "
  2963. }
  2964. return \$this->$varName;
  2965. }
  2966. ";
  2967. } // addFKAccessor
  2968. /**
  2969. * Adds a convenience method for setting a related object by specifying the primary key.
  2970. * This can be used in conjunction with the getPrimaryKey() for systems where nothing is known
  2971. * about the actual objects being related.
  2972. * @param string &$script The script will be modified in this method.
  2973. */
  2974. protected function addFKByKeyMutator(&$script, ForeignKey $fk)
  2975. {
  2976. $table = $this->getTable();
  2977. #$className = $this->getForeignTable($fk)->getPhpName();
  2978. $methodAffix = $this->getFKPhpNameAffix($fk);
  2979. #$varName = $this->getFKVarName($fk);
  2980. $script .= "
  2981. /**
  2982. * Provides convenient way to set a relationship based on a
  2983. * key. e.g.
  2984. * <code>\$bar->setFooKey(\$foo->getPrimaryKey())</code>
  2985. *";
  2986. if (count($fk->getLocalColumns()) > 1) {
  2987. $script .= "
  2988. * Note: It is important that the xml schema used to create this class
  2989. * maintains consistency in the order of related columns between
  2990. * ".$table->getName()." and ". $tblFK->getName().".
  2991. * If for some reason this is impossible, this method should be
  2992. * overridden in <code>".$table->getPhpName()."</code>.";
  2993. }
  2994. $script .= "
  2995. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  2996. * @throws PropelException
  2997. */
  2998. public function set".$methodAffix."Key(\$key)
  2999. {
  3000. ";
  3001. if (count($fk->getLocalColumns()) > 1) {
  3002. $i = 0;
  3003. foreach ($fk->getLocalColumns() as $colName) {
  3004. $col = $table->getColumn($colName);
  3005. $fktype = $col->getPhpType();
  3006. $script .= "
  3007. \$this->set".$col->getPhpName()."( ($fktype) \$key[$i] );
  3008. ";
  3009. $i++;
  3010. } /* foreach */
  3011. } else {
  3012. $lcols = $fk->getLocalColumns();
  3013. $colName = $lcols[0];
  3014. $col = $table->getColumn($colName);
  3015. $fktype = $col->getPhpType();
  3016. $script .= "
  3017. \$this->set".$col->getPhpName()."( ($fktype) \$key);
  3018. ";
  3019. }
  3020. $script .= "
  3021. return \$this;
  3022. }
  3023. ";
  3024. } // addFKByKeyMutator()
  3025. /**
  3026. * Adds the method that fetches fkey-related (referencing) objects but also joins in data from another table.
  3027. * @param string &$script The script will be modified in this method.
  3028. */
  3029. protected function addRefFKGetJoinMethods(&$script, ForeignKey $refFK)
  3030. {
  3031. $table = $this->getTable();
  3032. $tblFK = $refFK->getTable();
  3033. $join_behavior = $this->getGeneratorConfig()->getBuildProperty('useLeftJoinsInDoJoinMethods') ? 'Criteria::LEFT_JOIN' : 'Criteria::INNER_JOIN';
  3034. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3035. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3036. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural=true);
  3037. $collName = $this->getRefFKCollVarName($refFK);
  3038. $fkPeerBuilder = $this->getNewPeerBuilder($tblFK);
  3039. $className = $fkPeerBuilder->getObjectClassname();
  3040. $lastTable = "";
  3041. foreach ($tblFK->getForeignKeys() as $fk2) {
  3042. $tblFK2 = $this->getForeignTable($fk2);
  3043. $doJoinGet = !$tblFK2->isForReferenceOnly();
  3044. // it doesn't make sense to join in rows from the curent table, since we are fetching
  3045. // objects related to *this* table (i.e. the joined rows will all be the same row as current object)
  3046. if ($this->getTable()->getPhpName() == $tblFK2->getPhpName()) {
  3047. $doJoinGet = false;
  3048. }
  3049. $relCol2 = $this->getFKPhpNameAffix($fk2, $plural = false);
  3050. if ( $this->getRelatedBySuffix($refFK) != "" &&
  3051. ($this->getRelatedBySuffix($refFK) == $this->getRelatedBySuffix($fk2))) {
  3052. $doJoinGet = false;
  3053. }
  3054. if ($doJoinGet) {
  3055. $script .= "
  3056. /**
  3057. * If this collection has already been initialized with
  3058. * an identical criteria, it returns the collection.
  3059. * Otherwise if this ".$table->getPhpName()." is new, it will return
  3060. * an empty collection; or if this ".$table->getPhpName()." has previously
  3061. * been saved, it will retrieve related $relCol from storage.
  3062. *
  3063. * This method is protected by default in order to keep the public
  3064. * api reasonable. You can provide public methods for those you
  3065. * actually need in ".$table->getPhpName().".
  3066. *
  3067. * @param Criteria \$criteria optional Criteria object to narrow the query
  3068. * @param PropelPDO \$con optional connection object
  3069. * @param string \$join_behavior optional join type to use (defaults to $join_behavior)
  3070. * @return PropelObjectCollection|{$className}[] List of $className objects
  3071. */
  3072. public function get".$relCol."Join".$relCol2."(\$criteria = null, \$con = null, \$join_behavior = $join_behavior)
  3073. {";
  3074. $script .= "
  3075. \$query = $fkQueryClassname::create(null, \$criteria);
  3076. \$query->joinWith('" . $this->getFKPhpNameAffix($fk2, $plural=false) . "', \$join_behavior);
  3077. return \$this->get". $relCol . "(\$query, \$con);
  3078. }
  3079. ";
  3080. } /* end if ($doJoinGet) */
  3081. } /* end foreach ($tblFK->getForeignKeys() as $fk2) { */
  3082. } // function
  3083. // ----------------------------------------------------------------
  3084. //
  3085. // R E F E R R E R F K M E T H O D S
  3086. //
  3087. // ----------------------------------------------------------------
  3088. /**
  3089. * Adds the attributes used to store objects that have referrer fkey relationships to this object.
  3090. * <code>protected collVarName;</code>
  3091. * <code>private lastVarNameCriteria = null;</code>
  3092. * @param string &$script The script will be modified in this method.
  3093. */
  3094. protected function addRefFKAttributes(&$script, ForeignKey $refFK)
  3095. {
  3096. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3097. $className = $joinedTableObjectBuilder->getObjectClassname();
  3098. if ($refFK->isLocalPrimaryKey()) {
  3099. $script .= "
  3100. /**
  3101. * @var $className one-to-one related $className object
  3102. */
  3103. protected $".$this->getPKRefFKVarName($refFK).";
  3104. ";
  3105. } else {
  3106. $script .= "
  3107. /**
  3108. * @var PropelObjectCollection|{$className}[] Collection to store aggregation of $className objects.
  3109. */
  3110. protected $".$this->getRefFKCollVarName($refFK).";
  3111. protected $".$this->getRefFKCollVarName($refFK)."Partial;
  3112. ";
  3113. }
  3114. }
  3115. /**
  3116. * Adds the methods for retrieving, initializing, adding objects that are related to this one by foreign keys.
  3117. * @param string &$script The script will be modified in this method.
  3118. */
  3119. protected function addRefFKMethods(&$script)
  3120. {
  3121. if (!$referrers = $this->getTable()->getReferrers()) {
  3122. return;
  3123. }
  3124. $this->addInitRelations($script, $referrers);
  3125. foreach ($referrers as $refFK) {
  3126. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($refFK->getTable()));
  3127. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($refFK->getTable()));
  3128. if ($refFK->isLocalPrimaryKey()) {
  3129. $this->addPKRefFKGet($script, $refFK);
  3130. $this->addPKRefFKSet($script, $refFK);
  3131. } else {
  3132. $this->addRefFKClear($script, $refFK);
  3133. $this->addRefFKPartial($script, $refFK);
  3134. $this->addRefFKInit($script, $refFK);
  3135. $this->addRefFKGet($script, $refFK);
  3136. $this->addRefFKSet($script, $refFK);
  3137. $this->addRefFKCount($script, $refFK);
  3138. $this->addRefFKAdd($script, $refFK);
  3139. $this->addRefFKDoAdd($script, $refFK);
  3140. $this->addRefFKRemove($script, $refFK);
  3141. $this->addRefFKGetJoinMethods($script, $refFK);
  3142. }
  3143. }
  3144. }
  3145. protected function addInitRelations(&$script, $referrers)
  3146. {
  3147. $script .= "
  3148. /**
  3149. * Initializes a collection based on the name of a relation.
  3150. * Avoids crafting an 'init[\$relationName]s' method name
  3151. * that wouldn't work when StandardEnglishPluralizer is used.
  3152. *
  3153. * @param string \$relationName The name of the relation to initialize
  3154. * @return void
  3155. */
  3156. public function initRelation(\$relationName)
  3157. {";
  3158. foreach ($referrers as $refFK) {
  3159. if (!$refFK->isLocalPrimaryKey()) {
  3160. $relationName = $this->getRefFKPhpNameAffix($refFK);
  3161. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3162. $script .= "
  3163. if ('$relationName' == \$relationName) {
  3164. \$this->init$relCol();
  3165. }";
  3166. }
  3167. }
  3168. $script .= "
  3169. }
  3170. ";
  3171. }
  3172. /**
  3173. * Adds the method that clears the referrer fkey collection.
  3174. * @param string &$script The script will be modified in this method.
  3175. */
  3176. protected function addRefFKClear(&$script, ForeignKey $refFK)
  3177. {
  3178. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3179. $collName = $this->getRefFKCollVarName($refFK);
  3180. $script .= "
  3181. /**
  3182. * Clears out the $collName collection
  3183. *
  3184. * This does not modify the database; however, it will remove any associated objects, causing
  3185. * them to be refetched by subsequent calls to accessor method.
  3186. *
  3187. * @return void
  3188. * @see add$relCol()
  3189. */
  3190. public function clear$relCol()
  3191. {
  3192. \$this->$collName = null; // important to set this to null since that means it is uninitialized
  3193. \$this->{$collName}Partial = null;
  3194. }
  3195. ";
  3196. } // addRefererClear()
  3197. /**
  3198. * Adds the method that clears the referrer fkey collection.
  3199. * @param string &$script The script will be modified in this method.
  3200. */
  3201. protected function addRefFKPartial(&$script, ForeignKey $refFK)
  3202. {
  3203. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3204. $collName = $this->getRefFKCollVarName($refFK);
  3205. $script .= "
  3206. /**
  3207. * reset is the $collName collection loaded partially
  3208. *
  3209. * @return void
  3210. */
  3211. public function resetPartial{$relCol}(\$v = true)
  3212. {
  3213. \$this->{$collName}Partial = \$v;
  3214. }
  3215. ";
  3216. } // addRefFKPartial()
  3217. /**
  3218. * Adds the method that initializes the referrer fkey collection.
  3219. * @param string &$script The script will be modified in this method.
  3220. */
  3221. protected function addRefFKInit(&$script, ForeignKey $refFK)
  3222. {
  3223. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3224. $collName = $this->getRefFKCollVarName($refFK);
  3225. $script .= "
  3226. /**
  3227. * Initializes the $collName collection.
  3228. *
  3229. * By default this just sets the $collName collection to an empty array (like clear$collName());
  3230. * however, you may wish to override this method in your stub class to provide setting appropriate
  3231. * to your application -- for example, setting the initial array to the values stored in database.
  3232. *
  3233. * @param boolean \$overrideExisting If set to true, the method call initializes
  3234. * the collection even if it is not empty
  3235. *
  3236. * @return void
  3237. */
  3238. public function init$relCol(\$overrideExisting = true)
  3239. {
  3240. if (null !== \$this->$collName && !\$overrideExisting) {
  3241. return;
  3242. }
  3243. \$this->$collName = new PropelObjectCollection();
  3244. \$this->{$collName}->setModel('" . $this->getNewStubObjectBuilder($refFK->getTable())->getClassname() . "');
  3245. }
  3246. ";
  3247. } // addRefererInit()
  3248. /**
  3249. * Adds the method that adds an object into the referrer fkey collection.
  3250. * @param string &$script The script will be modified in this method.
  3251. */
  3252. protected function addRefFKAdd(&$script, ForeignKey $refFK)
  3253. {
  3254. $tblFK = $refFK->getTable();
  3255. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3256. $className = $joinedTableObjectBuilder->getObjectClassname();
  3257. if ($tblFK->getChildrenColumn()) {
  3258. $className = 'Base' . $className;
  3259. $namespace = $joinedTableObjectBuilder->getNamespace();
  3260. $this->declareClass($namespace.'\\'.$className);
  3261. }
  3262. $collName = $this->getRefFKCollVarName($refFK);
  3263. $script .= "
  3264. /**
  3265. * Method called to associate a $className object to this object
  3266. * through the $className foreign key attribute.
  3267. *
  3268. * @param $className \$l $className
  3269. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3270. */
  3271. public function add".$this->getRefFKPhpNameAffix($refFK, $plural = false)."($className \$l)
  3272. {
  3273. if (\$this->$collName === null) {
  3274. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."();
  3275. \$this->{$collName}Partial = true;
  3276. }
  3277. if (!in_array(\$l, \$this->{$collName}->getArrayCopy(), true)) { // only add it if the **same** object is not already associated
  3278. \$this->doAdd" . $this->getRefFKPhpNameAffix($refFK, $plural = false) . "(\$l);
  3279. }
  3280. return \$this;
  3281. }
  3282. ";
  3283. } // addRefererAdd
  3284. /**
  3285. * Adds the method that returns the size of the referrer fkey collection.
  3286. * @param string &$script The script will be modified in this method.
  3287. */
  3288. protected function addRefFKCount(&$script, ForeignKey $refFK)
  3289. {
  3290. $table = $this->getTable();
  3291. $tblFK = $refFK->getTable();
  3292. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3293. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3294. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3295. $collName = $this->getRefFKCollVarName($refFK);
  3296. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3297. $className = $joinedTableObjectBuilder->getObjectClassname();
  3298. $script .= "
  3299. /**
  3300. * Returns the number of related $className objects.
  3301. *
  3302. * @param Criteria \$criteria
  3303. * @param boolean \$distinct
  3304. * @param PropelPDO \$con
  3305. * @return int Count of related $className objects.
  3306. * @throws PropelException
  3307. */
  3308. public function count$relCol(Criteria \$criteria = null, \$distinct = false, PropelPDO \$con = null)
  3309. {
  3310. \$partial = \$this->{$collName}Partial && !\$this->isNew();
  3311. if (null === \$this->$collName || null !== \$criteria || \$partial) {
  3312. if (\$this->isNew() && null === \$this->$collName) {
  3313. return 0;
  3314. } else {
  3315. if(\$partial && !\$criteria) {
  3316. return count(\$this->get$relCol());
  3317. }
  3318. \$query = $fkQueryClassname::create(null, \$criteria);
  3319. if (\$distinct) {
  3320. \$query->distinct();
  3321. }
  3322. return \$query
  3323. ->filterBy" . $this->getFKPhpNameAffix($refFK) . "(\$this)
  3324. ->count(\$con);
  3325. }
  3326. } else {
  3327. return count(\$this->$collName);
  3328. }
  3329. }
  3330. ";
  3331. } // addRefererCount
  3332. /**
  3333. * Adds the method that returns the referrer fkey collection.
  3334. * @param string &$script The script will be modified in this method.
  3335. */
  3336. protected function addRefFKGet(&$script, ForeignKey $refFK)
  3337. {
  3338. $table = $this->getTable();
  3339. $tblFK = $refFK->getTable();
  3340. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3341. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3342. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3343. $collName = $this->getRefFKCollVarName($refFK);
  3344. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3345. $className = $joinedTableObjectBuilder->getObjectClassname();
  3346. $script .= "
  3347. /**
  3348. * Gets an array of $className objects which contain a foreign key that references this object.
  3349. *
  3350. * If the \$criteria is not null, it is used to always fetch the results from the database.
  3351. * Otherwise the results are fetched from the database the first time, then cached.
  3352. * Next time the same method is called without \$criteria, the cached collection is returned.
  3353. * If this ".$this->getObjectClassname()." is new, it will return
  3354. * an empty collection or the current collection; the criteria is ignored on a new object.
  3355. *
  3356. * @param Criteria \$criteria optional Criteria object to narrow the query
  3357. * @param PropelPDO \$con optional connection object
  3358. * @return PropelObjectCollection|{$className}[] List of $className objects
  3359. * @throws PropelException
  3360. */
  3361. public function get$relCol(\$criteria = null, PropelPDO \$con = null)
  3362. {
  3363. \$partial = \$this->{$collName}Partial && !\$this->isNew();
  3364. if (null === \$this->$collName || null !== \$criteria || \$partial) {
  3365. if (\$this->isNew() && null === \$this->$collName) {
  3366. // return empty collection
  3367. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."();
  3368. } else {
  3369. \$$collName = $fkQueryClassname::create(null, \$criteria)
  3370. ->filterBy" . $this->getFKPhpNameAffix($refFK) . "(\$this)
  3371. ->find(\$con);
  3372. if (null !== \$criteria) {
  3373. if (false !== \$this->{$collName}Partial && count(\$$collName)) {
  3374. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."(false);
  3375. foreach(\$$collName as \$obj) {
  3376. if (false == \$this->{$collName}->contains(\$obj)) {
  3377. \$this->{$collName}->append(\$obj);
  3378. }
  3379. }
  3380. \$this->{$collName}Partial = true;
  3381. }
  3382. return \$$collName;
  3383. }
  3384. if(\$partial && \$this->$collName) {
  3385. foreach(\$this->$collName as \$obj) {
  3386. if(\$obj->isNew()) {
  3387. \${$collName}[] = \$obj;
  3388. }
  3389. }
  3390. }
  3391. \$this->$collName = \$$collName;
  3392. \$this->{$collName}Partial = false;
  3393. }
  3394. }
  3395. return \$this->$collName;
  3396. }
  3397. ";
  3398. } // addRefererGet()
  3399. protected function addRefFKSet(&$script, $refFK)
  3400. {
  3401. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3402. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3403. // No lcfirst() in PHP < 5.3
  3404. $inputCollection = $relatedName;
  3405. $inputCollection[0] = strtolower($inputCollection[0]);
  3406. // No lcfirst() in PHP < 5.3
  3407. $inputCollectionEntry = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3408. $inputCollectionEntry[0] = strtolower($inputCollectionEntry[0]);
  3409. $collName = $this->getRefFKCollVarName($refFK);
  3410. $relCol = $this->getFKPhpNameAffix($refFK, $plural = false);
  3411. $script .= "
  3412. /**
  3413. * Sets a collection of $relatedObjectClassName objects related by a one-to-many relationship
  3414. * to the current object.
  3415. * It will also schedule objects for deletion based on a diff between old objects (aka persisted)
  3416. * and new objects from the given Propel collection.
  3417. *
  3418. * @param PropelCollection \${$inputCollection} A Propel collection.
  3419. * @param PropelPDO \$con Optional connection object
  3420. */
  3421. public function set{$relatedName}(PropelCollection \${$inputCollection}, PropelPDO \$con = null)
  3422. {
  3423. \$this->{$inputCollection}ScheduledForDeletion = \$this->get{$relatedName}(new Criteria(), \$con)->diff(\${$inputCollection});
  3424. foreach (\$this->{$inputCollection}ScheduledForDeletion as \${$inputCollectionEntry}Removed) {
  3425. \${$inputCollectionEntry}Removed->set{$relCol}(null);
  3426. }
  3427. \$this->{$collName} = null;
  3428. foreach (\${$inputCollection} as \${$inputCollectionEntry}) {
  3429. \$this->add{$relatedObjectClassName}(\${$inputCollectionEntry});
  3430. }
  3431. \$this->{$collName} = \${$inputCollection};
  3432. \$this->{$collName}Partial = false;
  3433. }
  3434. ";
  3435. }
  3436. /**
  3437. * @param string &$script The script will be modified in this method.
  3438. * @param ForeignKey $refFK
  3439. * @param ForeignKey $crossFK
  3440. */
  3441. protected function addRefFKDoAdd(&$script, $refFK)
  3442. {
  3443. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3444. // lcfirst() doesn't exist in PHP < 5.3
  3445. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3446. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3447. $collName = $this->getRefFKCollVarName($refFK);
  3448. $script .= "
  3449. /**
  3450. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to add.
  3451. */
  3452. protected function doAdd{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3453. {
  3454. \$this->{$collName}[]= \${$lowerRelatedObjectClassName};
  3455. \${$lowerRelatedObjectClassName}->set" . $this->getFKPhpNameAffix($refFK, $plural = false)."(\$this);
  3456. }
  3457. ";
  3458. }
  3459. /**
  3460. * @param string &$script The script will be modified in this method.
  3461. * @param ForeignKey $refFK
  3462. * @param ForeignKey $crossFK
  3463. */
  3464. protected function addRefFKRemove(&$script, $refFK)
  3465. {
  3466. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3467. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3468. // No lcfirst() in PHP < 5.3
  3469. $inputCollection = $relatedName . 'ScheduledForDeletion';
  3470. $inputCollection[0] = strtolower($inputCollection[0]);
  3471. // lcfirst() doesn't exist in PHP < 5.3
  3472. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3473. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3474. $collName = $this->getRefFKCollVarName($refFK);
  3475. $relCol = $this->getFKPhpNameAffix($refFK, $plural = false);
  3476. $script .= "
  3477. /**
  3478. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to remove.
  3479. */
  3480. public function remove{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3481. {
  3482. if (\$this->get{$relatedName}()->contains(\${$lowerRelatedObjectClassName})) {
  3483. \$this->{$collName}->remove(\$this->{$collName}->search(\${$lowerRelatedObjectClassName}));
  3484. if (null === \$this->{$inputCollection}) {
  3485. \$this->{$inputCollection} = clone \$this->{$collName};
  3486. \$this->{$inputCollection}->clear();
  3487. }
  3488. \$this->{$inputCollection}[]= \${$lowerRelatedObjectClassName};
  3489. \${$lowerRelatedObjectClassName}->set{$relCol}(null);
  3490. }
  3491. }
  3492. ";
  3493. }
  3494. /**
  3495. * Adds the method that gets a one-to-one related referrer fkey.
  3496. * This is for one-to-one relationship special case.
  3497. * @param string &$script The script will be modified in this method.
  3498. */
  3499. protected function addPKRefFKGet(&$script, ForeignKey $refFK)
  3500. {
  3501. $table = $this->getTable();
  3502. $tblFK = $refFK->getTable();
  3503. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3504. $className = $joinedTableObjectBuilder->getObjectClassname();
  3505. $queryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3506. $varName = $this->getPKRefFKVarName($refFK);
  3507. $script .= "
  3508. /**
  3509. * Gets a single $className object, which is related to this object by a one-to-one relationship.
  3510. *
  3511. * @param PropelPDO \$con optional connection object
  3512. * @return $className
  3513. * @throws PropelException
  3514. */
  3515. public function get".$this->getRefFKPhpNameAffix($refFK, $plural = false)."(PropelPDO \$con = null)
  3516. {
  3517. ";
  3518. $script .= "
  3519. if (\$this->$varName === null && !\$this->isNew()) {
  3520. \$this->$varName = $queryClassname::create()->findPk(\$this->getPrimaryKey(), \$con);
  3521. }
  3522. return \$this->$varName;
  3523. }
  3524. ";
  3525. } // addPKRefFKGet()
  3526. /**
  3527. * Adds the method that sets a one-to-one related referrer fkey.
  3528. * This is for one-to-one relationships special case.
  3529. * @param string &$script The script will be modified in this method.
  3530. * @param ForeignKey $refFK The referencing foreign key.
  3531. */
  3532. protected function addPKRefFKSet(&$script, ForeignKey $refFK)
  3533. {
  3534. $tblFK = $refFK->getTable();
  3535. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3536. $className = $joinedTableObjectBuilder->getObjectClassname();
  3537. $varName = $this->getPKRefFKVarName($refFK);
  3538. $script .= "
  3539. /**
  3540. * Sets a single $className object as related to this object by a one-to-one relationship.
  3541. *
  3542. * @param $className \$v $className
  3543. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3544. * @throws PropelException
  3545. */
  3546. public function set".$this->getRefFKPhpNameAffix($refFK, $plural = false)."($className \$v = null)
  3547. {
  3548. \$this->$varName = \$v;
  3549. // Make sure that that the passed-in $className isn't already associated with this object
  3550. if (\$v !== null && \$v->get".$this->getFKPhpNameAffix($refFK, $plural = false)."() === null) {
  3551. \$v->set".$this->getFKPhpNameAffix($refFK, $plural = false)."(\$this);
  3552. }
  3553. return \$this;
  3554. }
  3555. ";
  3556. } // addPKRefFKSet
  3557. protected function addCrossFKAttributes(&$script, ForeignKey $crossFK)
  3558. {
  3559. $joinedTableObjectBuilder = $this->getNewObjectBuilder($crossFK->getForeignTable());
  3560. $className = $joinedTableObjectBuilder->getObjectClassname();
  3561. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3562. $script .= "
  3563. /**
  3564. * @var PropelObjectCollection|{$className}[] Collection to store aggregation of $className objects.
  3565. */
  3566. protected $" . $this->getCrossFKVarName($crossFK) . ";
  3567. ";
  3568. }
  3569. protected function addScheduledForDeletionAttribute(&$script, $fkName)
  3570. {
  3571. // No lcfirst() in PHP < 5.3
  3572. $fkName[0] = strtolower($fkName[0]);
  3573. $script .= "
  3574. /**
  3575. * An array of objects scheduled for deletion.
  3576. * @var PropelObjectCollection
  3577. */
  3578. protected \${$fkName}ScheduledForDeletion = null;
  3579. ";
  3580. }
  3581. protected function addCrossFkScheduledForDeletion(&$script, $refFK, $crossFK)
  3582. {
  3583. $queryClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false) . 'Query';
  3584. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3585. // No lcfirst() in PHP < 5.3
  3586. $lowerRelatedName = $relatedName;
  3587. $lowerRelatedName[0] = strtolower($lowerRelatedName[0]);
  3588. // No lcfirst() in PHP < 5.3
  3589. $lowerSingleRelatedName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3590. $lowerSingleRelatedName[0] = strtolower($lowerSingleRelatedName[0]);
  3591. $middelFks = $refFK->getTable()->getForeignKeys();
  3592. $isFirstPk = ($middelFks[0]->getForeignTableCommonName() == $this->getTable()->getCommonName());
  3593. $script .= "
  3594. if (\$this->{$lowerRelatedName}ScheduledForDeletion !== null) {
  3595. if (!\$this->{$lowerRelatedName}ScheduledForDeletion->isEmpty()) {
  3596. \$pks = array();
  3597. \$pk = \$this->getPrimaryKey();
  3598. foreach (\$this->{$lowerRelatedName}ScheduledForDeletion->getPrimaryKeys(false) as \$remotePk) {";
  3599. if ($isFirstPk) {
  3600. $script .= "
  3601. \$pks[] = array(\$pk, \$remotePk);";
  3602. } else {
  3603. $script .= "
  3604. \$pks[] = array(\$remotePk, \$pk);";
  3605. }
  3606. $script .= "
  3607. }
  3608. $queryClassName::create()
  3609. ->filterByPrimaryKeys(\$pks)
  3610. ->delete(\$con);
  3611. \$this->{$lowerRelatedName}ScheduledForDeletion = null;
  3612. }
  3613. foreach (\$this->get{$relatedName}() as \${$lowerSingleRelatedName}) {
  3614. if (\${$lowerSingleRelatedName}->isModified()) {
  3615. \${$lowerSingleRelatedName}->save(\$con);
  3616. }
  3617. }
  3618. }
  3619. ";
  3620. }
  3621. protected function addRefFkScheduledForDeletion(&$script, $refFK)
  3622. {
  3623. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3624. // No lcfirst() in PHP < 5.3
  3625. $lowerRelatedName = $relatedName;
  3626. $lowerRelatedName[0] = strtolower($lowerRelatedName[0]);
  3627. // No lcfirst() in PHP < 5.3
  3628. $lowerSingleRelatedName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3629. $lowerSingleRelatedName[0] = strtolower($lowerSingleRelatedName[0]);
  3630. $queryClassName = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3631. $localColumn = $refFK->getLocalColumn();
  3632. $script .= "
  3633. if (\$this->{$lowerRelatedName}ScheduledForDeletion !== null) {
  3634. if (!\$this->{$lowerRelatedName}ScheduledForDeletion->isEmpty()) {";
  3635. if (!$refFK->isComposite() && !$localColumn->isNotNull()) {
  3636. $script .= "
  3637. foreach (\$this->{$lowerRelatedName}ScheduledForDeletion as \${$lowerSingleRelatedName}) {
  3638. // need to save related object because we set the relation to null
  3639. \${$lowerSingleRelatedName}->save(\$con);
  3640. }";
  3641. } else {
  3642. $script .= "
  3643. $queryClassName::create()
  3644. ->filterByPrimaryKeys(\$this->{$lowerRelatedName}ScheduledForDeletion->getPrimaryKeys(false))
  3645. ->delete(\$con);";
  3646. }
  3647. $script .= "
  3648. \$this->{$lowerRelatedName}ScheduledForDeletion = null;
  3649. }
  3650. }
  3651. ";
  3652. }
  3653. protected function getCrossFKVarName(ForeignKey $crossFK)
  3654. {
  3655. return 'coll' . $this->getFKPhpNameAffix($crossFK, $plural = true);
  3656. }
  3657. protected function addCrossFKMethods(&$script)
  3658. {
  3659. foreach ($this->getTable()->getCrossFks() as $fkList) {
  3660. list($refFK, $crossFK) = $fkList;
  3661. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($crossFK->getForeignTable()));
  3662. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($crossFK->getForeignTable()));
  3663. $this->addCrossFKClear($script, $crossFK);
  3664. $this->addCrossFKInit($script, $crossFK);
  3665. $this->addCrossFKGet($script, $refFK, $crossFK);
  3666. $this->addCrossFKSet($script, $refFK, $crossFK);
  3667. $this->addCrossFKCount($script, $refFK, $crossFK);
  3668. $this->addCrossFKAdd($script, $refFK, $crossFK);
  3669. $this->addCrossFKDoAdd($script, $refFK, $crossFK);
  3670. $this->addCrossFKRemove($script, $refFK, $crossFK);
  3671. }
  3672. }
  3673. /**
  3674. * Adds the method that clears the referrer fkey collection.
  3675. * @param string &$script The script will be modified in this method.
  3676. */
  3677. protected function addCrossFKClear(&$script, ForeignKey $crossFK)
  3678. {
  3679. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3680. $collName = $this->getCrossFKVarName($crossFK);
  3681. $script .= "
  3682. /**
  3683. * Clears out the $collName collection
  3684. *
  3685. * This does not modify the database; however, it will remove any associated objects, causing
  3686. * them to be refetched by subsequent calls to accessor method.
  3687. *
  3688. * @return void
  3689. * @see add$relCol()
  3690. */
  3691. public function clear$relCol()
  3692. {
  3693. \$this->$collName = null; // important to set this to null since that means it is uninitialized
  3694. \$this->{$collName}Partial = null;
  3695. }
  3696. ";
  3697. } // addRefererClear()
  3698. /**
  3699. * Adds the method that initializes the referrer fkey collection.
  3700. * @param string &$script The script will be modified in this method.
  3701. */
  3702. protected function addCrossFKInit(&$script, ForeignKey $crossFK)
  3703. {
  3704. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3705. $collName = $this->getCrossFKVarName($crossFK);
  3706. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3707. $script .= "
  3708. /**
  3709. * Initializes the $collName collection.
  3710. *
  3711. * By default this just sets the $collName collection to an empty collection (like clear$relCol());
  3712. * however, you may wish to override this method in your stub class to provide setting appropriate
  3713. * to your application -- for example, setting the initial array to the values stored in database.
  3714. *
  3715. * @return void
  3716. */
  3717. public function init$relCol()
  3718. {
  3719. \$this->$collName = new PropelObjectCollection();
  3720. \$this->{$collName}->setModel('$relatedObjectClassName');
  3721. }
  3722. ";
  3723. }
  3724. protected function addCrossFKGet(&$script, $refFK, $crossFK)
  3725. {
  3726. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3727. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3728. $selfRelationName = $this->getFKPhpNameAffix($refFK, $plural = false);
  3729. $relatedQueryClassName = $this->getNewStubQueryBuilder($crossFK->getForeignTable())->getClassname();
  3730. $crossRefTableName = $crossFK->getTableName();
  3731. $collName = $this->getCrossFKVarName($crossFK);
  3732. $script .= "
  3733. /**
  3734. * Gets a collection of $relatedObjectClassName objects related by a many-to-many relationship
  3735. * to the current object by way of the $crossRefTableName cross-reference table.
  3736. *
  3737. * If the \$criteria is not null, it is used to always fetch the results from the database.
  3738. * Otherwise the results are fetched from the database the first time, then cached.
  3739. * Next time the same method is called without \$criteria, the cached collection is returned.
  3740. * If this ".$this->getObjectClassname()." is new, it will return
  3741. * an empty collection or the current collection; the criteria is ignored on a new object.
  3742. *
  3743. * @param Criteria \$criteria Optional query object to filter the query
  3744. * @param PropelPDO \$con Optional connection object
  3745. *
  3746. * @return PropelObjectCollection|{$relatedObjectClassName}[] List of {$relatedObjectClassName} objects
  3747. */
  3748. public function get{$relatedName}(\$criteria = null, PropelPDO \$con = null)
  3749. {
  3750. if (null === \$this->$collName || null !== \$criteria) {
  3751. if (\$this->isNew() && null === \$this->$collName) {
  3752. // return empty collection
  3753. \$this->init{$relatedName}();
  3754. } else {
  3755. \$$collName = $relatedQueryClassName::create(null, \$criteria)
  3756. ->filterBy{$selfRelationName}(\$this)
  3757. ->find(\$con);
  3758. if (null !== \$criteria) {
  3759. return \$$collName;
  3760. }
  3761. \$this->$collName = \$$collName;
  3762. }
  3763. }
  3764. return \$this->$collName;
  3765. }
  3766. ";
  3767. }
  3768. protected function addCrossFKSet(&$script, $refFK, $crossFK)
  3769. {
  3770. $relatedNamePlural = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3771. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3772. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3773. $crossRefTableName = $crossFK->getTableName();
  3774. $collName = $this->getCrossFKVarName($crossFK);
  3775. // No lcfirst() in PHP < 5.3
  3776. $inputCollection = $relatedNamePlural;
  3777. $inputCollection[0] = strtolower($inputCollection[0]);
  3778. // No lcfirst() in PHP < 5.3
  3779. $inputCollectionEntry = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3780. $inputCollectionEntry[0] = strtolower($inputCollectionEntry[0]);
  3781. $script .= "
  3782. /**
  3783. * Sets a collection of $relatedObjectClassName objects related by a many-to-many relationship
  3784. * to the current object by way of the $crossRefTableName cross-reference table.
  3785. * It will also schedule objects for deletion based on a diff between old objects (aka persisted)
  3786. * and new objects from the given Propel collection.
  3787. *
  3788. * @param PropelCollection \${$inputCollection} A Propel collection.
  3789. * @param PropelPDO \$con Optional connection object
  3790. */
  3791. public function set{$relatedNamePlural}(PropelCollection \${$inputCollection}, PropelPDO \$con = null)
  3792. {
  3793. \$this->clear{$relatedNamePlural}();
  3794. \$current{$relatedNamePlural} = \$this->get{$relatedNamePlural}();
  3795. \$this->{$inputCollection}ScheduledForDeletion = \$current{$relatedNamePlural}->diff(\${$inputCollection});
  3796. foreach (\${$inputCollection} as \${$inputCollectionEntry}) {
  3797. if (!\$current{$relatedNamePlural}->contains(\${$inputCollectionEntry})) {
  3798. \$this->doAdd{$relatedName}(\${$inputCollectionEntry});
  3799. }
  3800. }
  3801. \$this->$collName = \${$inputCollection};
  3802. }
  3803. ";
  3804. }
  3805. protected function addCrossFKCount(&$script, $refFK, $crossFK)
  3806. {
  3807. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3808. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3809. $selfRelationName = $this->getFKPhpNameAffix($refFK, $plural = false);
  3810. $relatedQueryClassName = $this->getNewStubQueryBuilder($crossFK->getForeignTable())->getClassname();
  3811. $crossRefTableName = $refFK->getTableName();
  3812. $collName = $this->getCrossFKVarName($crossFK);
  3813. $script .= "
  3814. /**
  3815. * Gets the number of $relatedObjectClassName objects related by a many-to-many relationship
  3816. * to the current object by way of the $crossRefTableName cross-reference table.
  3817. *
  3818. * @param Criteria \$criteria Optional query object to filter the query
  3819. * @param boolean \$distinct Set to true to force count distinct
  3820. * @param PropelPDO \$con Optional connection object
  3821. *
  3822. * @return int the number of related $relatedObjectClassName objects
  3823. */
  3824. public function count{$relatedName}(\$criteria = null, \$distinct = false, PropelPDO \$con = null)
  3825. {
  3826. if (null === \$this->$collName || null !== \$criteria) {
  3827. if (\$this->isNew() && null === \$this->$collName) {
  3828. return 0;
  3829. } else {
  3830. \$query = $relatedQueryClassName::create(null, \$criteria);
  3831. if (\$distinct) {
  3832. \$query->distinct();
  3833. }
  3834. return \$query
  3835. ->filterBy{$selfRelationName}(\$this)
  3836. ->count(\$con);
  3837. }
  3838. } else {
  3839. return count(\$this->$collName);
  3840. }
  3841. }
  3842. ";
  3843. }
  3844. /**
  3845. * Adds the method that adds an object into the referrer fkey collection.
  3846. * @param string &$script The script will be modified in this method.
  3847. */
  3848. protected function addCrossFKAdd(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3849. {
  3850. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3851. $collName = $this->getCrossFKVarName($crossFK);
  3852. $tblFK = $refFK->getTable();
  3853. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3854. $className = $joinedTableObjectBuilder->getObjectClassname();
  3855. $crossObjectName = '$' . $crossFK->getForeignTable()->getStudlyPhpName();
  3856. $crossObjectClassName = $this->getNewObjectBuilder($crossFK->getForeignTable())->getObjectClassname();
  3857. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3858. $script .= "
  3859. /**
  3860. * Associate a " . $crossObjectClassName . " object to this object
  3861. * through the " . $tblFK->getName() . " cross reference table.
  3862. *
  3863. * @param " . $crossObjectClassName . " " . $crossObjectName . " The $className object to relate
  3864. * @return void
  3865. */
  3866. public function add{$relatedObjectClassName}($crossObjectClassName $crossObjectName)
  3867. {
  3868. if (\$this->" . $collName . " === null) {
  3869. \$this->init" . $relCol . "();
  3870. }
  3871. if (!\$this->" . $collName . "->contains(" . $crossObjectName . ")) { // only add it if the **same** object is not already associated
  3872. \$this->doAdd{$relatedObjectClassName}($crossObjectName);
  3873. \$this->" . $collName . "[]= " . $crossObjectName . ";
  3874. }
  3875. }
  3876. ";
  3877. }
  3878. /**
  3879. * @param string &$script The script will be modified in this method.
  3880. * @param ForeignKey $refFK
  3881. * @param ForeignKey $crossFK
  3882. */
  3883. protected function addCrossFKDoAdd(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3884. {
  3885. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3886. // lcfirst() doesn't exist in PHP < 5.3
  3887. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3888. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3889. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3890. $className = $joinedTableObjectBuilder->getObjectClassname();
  3891. $refKObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3892. $tblFK = $refFK->getTable();
  3893. $foreignObjectName = '$' . $tblFK->getStudlyPhpName();
  3894. $script .= "
  3895. /**
  3896. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to add.
  3897. */
  3898. protected function doAdd{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3899. {
  3900. {$foreignObjectName} = new {$className}();
  3901. {$foreignObjectName}->set{$relatedObjectClassName}(\${$lowerRelatedObjectClassName});
  3902. \$this->add{$refKObjectClassName}({$foreignObjectName});
  3903. }
  3904. ";
  3905. }
  3906. /**
  3907. * Adds the method that remove an object from the referrer fkey collection.
  3908. * @param string $script The script will be modified in this method.
  3909. */
  3910. protected function addCrossFKRemove(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3911. {
  3912. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3913. $collName = 'coll' . $relCol;
  3914. $tblFK = $refFK->getTable();
  3915. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3916. $className = $joinedTableObjectBuilder->getObjectClassname();
  3917. $lowerRelCol = $relCol;
  3918. $lowerRelCol[0] = strtolower($lowerRelCol[0]);
  3919. $M2MScheduledForDeletion = $lowerRelCol . "ScheduledForDeletion";
  3920. $crossObjectName = '$' . $crossFK->getForeignTable()->getStudlyPhpName();
  3921. $crossObjectClassName = $this->getNewObjectBuilder($crossFK->getForeignTable())->getObjectClassname();
  3922. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3923. $script .= "
  3924. /**
  3925. * Remove a {$crossObjectClassName} object to this object
  3926. * through the {$tblFK->getName()} cross reference table.
  3927. *
  3928. * @param {$crossObjectClassName} {$crossObjectName} The $className object to relate
  3929. * @return void
  3930. */
  3931. public function remove{$relatedObjectClassName}($crossObjectClassName $crossObjectName)
  3932. {
  3933. if (\$this->get{$relCol}()->contains({$crossObjectName})) {
  3934. \$this->{$collName}->remove(\$this->{$collName}->search({$crossObjectName}));
  3935. if (null === \$this->{$M2MScheduledForDeletion}) {
  3936. \$this->{$M2MScheduledForDeletion} = clone \$this->{$collName};
  3937. \$this->{$M2MScheduledForDeletion}->clear();
  3938. }
  3939. \$this->{$M2MScheduledForDeletion}[]= {$crossObjectName};
  3940. }
  3941. }
  3942. ";
  3943. }
  3944. // ----------------------------------------------------------------
  3945. //
  3946. // M A N I P U L A T I O N M E T H O D S
  3947. //
  3948. // ----------------------------------------------------------------
  3949. /**
  3950. * Adds the workhourse doSave() method.
  3951. * @param string &$script The script will be modified in this method.
  3952. */
  3953. protected function addDoSave(&$script)
  3954. {
  3955. $table = $this->getTable();
  3956. $reloadOnUpdate = $table->isReloadOnUpdate();
  3957. $reloadOnInsert = $table->isReloadOnInsert();
  3958. $script .= "
  3959. /**
  3960. * Performs the work of inserting or updating the row in the database.
  3961. *
  3962. * If the object is new, it inserts it; otherwise an update is performed.
  3963. * All related objects are also updated in this method.
  3964. *
  3965. * @param PropelPDO \$con";
  3966. if ($reloadOnUpdate || $reloadOnInsert) {
  3967. $script .= "
  3968. * @param boolean \$skipReload Whether to skip the reload for this object from database.";
  3969. }
  3970. $script .= "
  3971. * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  3972. * @throws PropelException
  3973. * @see save()
  3974. */
  3975. protected function doSave(PropelPDO \$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").")
  3976. {
  3977. \$affectedRows = 0; // initialize var to track total num of affected rows
  3978. if (!\$this->alreadyInSave) {
  3979. \$this->alreadyInSave = true;
  3980. ";
  3981. if ($reloadOnInsert || $reloadOnUpdate) {
  3982. $script .= "
  3983. \$reloadObject = false;
  3984. ";
  3985. }
  3986. if (count($table->getForeignKeys())) {
  3987. $script .= "
  3988. // We call the save method on the following object(s) if they
  3989. // were passed to this object by their coresponding set
  3990. // method. This object relates to these object(s) by a
  3991. // foreign key reference.
  3992. ";
  3993. foreach ($table->getForeignKeys() as $fk) {
  3994. $aVarName = $this->getFKVarName($fk);
  3995. $script .= "
  3996. if (\$this->$aVarName !== null) {
  3997. if (\$this->" . $aVarName . "->isModified() || \$this->" . $aVarName . "->isNew()) {
  3998. \$affectedRows += \$this->" . $aVarName . "->save(\$con);
  3999. }
  4000. \$this->set".$this->getFKPhpNameAffix($fk, $plural = false)."(\$this->$aVarName);
  4001. }
  4002. ";
  4003. } // foreach foreign k
  4004. } // if (count(foreign keys))
  4005. $script .= "
  4006. if (\$this->isNew() || \$this->isModified()) {
  4007. // persist changes
  4008. if (\$this->isNew()) {
  4009. \$this->doInsert(\$con);";
  4010. if ($reloadOnInsert) {
  4011. $script .= "
  4012. if (!\$skipReload) {
  4013. \$reloadObject = true;
  4014. }";
  4015. }
  4016. $script .= "
  4017. } else {
  4018. \$this->doUpdate(\$con);";
  4019. if ($reloadOnUpdate) {
  4020. $script .= "
  4021. if (!\$skipReload) {
  4022. \$reloadObject = true;
  4023. }";
  4024. }
  4025. $script .= "
  4026. }
  4027. \$affectedRows += 1;";
  4028. // We need to rewind any LOB columns
  4029. foreach ($table->getColumns() as $col) {
  4030. $clo = strtolower($col->getName());
  4031. if ($col->isLobType()) {
  4032. $script .= "
  4033. // Rewind the $clo LOB column, since PDO does not rewind after inserting value.
  4034. if (\$this->$clo !== null && is_resource(\$this->$clo)) {
  4035. rewind(\$this->$clo);
  4036. }
  4037. ";
  4038. }
  4039. }
  4040. $script .= "
  4041. \$this->resetModified();
  4042. }
  4043. ";
  4044. if ($table->hasCrossForeignKeys()) {
  4045. foreach ($table->getCrossFks() as $fkList) {
  4046. list($refFK, $crossFK) = $fkList;
  4047. $this->addCrossFkScheduledForDeletion($script, $refFK, $crossFK);
  4048. }
  4049. }
  4050. foreach ($table->getReferrers() as $refFK) {
  4051. $this->addRefFkScheduledForDeletion($script, $refFK);
  4052. if ($refFK->isLocalPrimaryKey()) {
  4053. $varName = $this->getPKRefFKVarName($refFK);
  4054. $script .= "
  4055. if (\$this->$varName !== null) {
  4056. if (!\$this->{$varName}->isDeleted()) {
  4057. \$affectedRows += \$this->{$varName}->save(\$con);
  4058. }
  4059. }
  4060. ";
  4061. } else {
  4062. $collName = $this->getRefFKCollVarName($refFK);
  4063. $script .= "
  4064. if (\$this->$collName !== null) {
  4065. foreach (\$this->$collName as \$referrerFK) {
  4066. if (!\$referrerFK->isDeleted()) {
  4067. \$affectedRows += \$referrerFK->save(\$con);
  4068. }
  4069. }
  4070. }
  4071. ";
  4072. } // if refFK->isLocalPrimaryKey()
  4073. } /* foreach getReferrers() */
  4074. $script .= "
  4075. \$this->alreadyInSave = false;
  4076. ";
  4077. if ($reloadOnInsert || $reloadOnUpdate) {
  4078. $script .= "
  4079. if (\$reloadObject) {
  4080. \$this->reload(\$con);
  4081. }
  4082. ";
  4083. }
  4084. $script .= "
  4085. }
  4086. return \$affectedRows;
  4087. } // doSave()
  4088. ";
  4089. }
  4090. /**
  4091. * get the doInsert() method code
  4092. *
  4093. * @return string the doInsert() method code
  4094. */
  4095. protected function addDoInsert()
  4096. {
  4097. $table = $this->getTable();
  4098. $script = "
  4099. /**
  4100. * Insert the row in the database.
  4101. *
  4102. * @param PropelPDO \$con
  4103. *
  4104. * @throws PropelException
  4105. * @see doSave()
  4106. */
  4107. protected function doInsert(PropelPDO \$con)
  4108. {";
  4109. if ($this->getPlatform() instanceof MssqlPlatform) {
  4110. if ($table->hasAutoIncrementPrimaryKey() ) {
  4111. $script .= "
  4112. \$this->modifiedColumns[] = " . $this->getColumnConstant($table->getAutoIncrementPrimaryKey() ) . ";";
  4113. }
  4114. $script .= "
  4115. \$criteria = \$this->buildCriteria();";
  4116. if ($this->getTable()->getIdMethod() != IDMethod::NO_ID_METHOD) {
  4117. $script .= $this->addDoInsertBodyWithIdMethod();
  4118. } else {
  4119. $script .= $this->addDoInsertBodyStandard();
  4120. }
  4121. } else {
  4122. $script .= $this->addDoInsertBodyRaw();
  4123. }
  4124. $script .= "
  4125. \$this->setNew(false);
  4126. }
  4127. ";
  4128. return $script;
  4129. }
  4130. protected function addDoInsertBodyStandard()
  4131. {
  4132. return "
  4133. \$pk = " . $this->getNewPeerBuilder($this->getTable())->getBasePeerClassname() . "::doInsert(\$criteria, \$con);";
  4134. }
  4135. protected function addDoInsertBodyWithIdMethod()
  4136. {
  4137. $table = $this->getTable();
  4138. $reloadOnInsert = $table->isReloadOnInsert();
  4139. $basePeerClassname = $this->getNewPeerBuilder($table)->getBasePeerClassname();
  4140. $script = '';
  4141. foreach ($table->getPrimaryKey() as $col) {
  4142. if (!$col->isAutoIncrement()) {
  4143. continue;
  4144. }
  4145. $colConst = $this->getColumnConstant($col);
  4146. if (!$table->isAllowPkInsert()) {
  4147. $script .= "
  4148. if (\$criteria->keyContainsValue($colConst) ) {
  4149. throw new PropelException('Cannot insert a value for auto-increment primary key (' . $colConst . ')');
  4150. }";
  4151. if (!$this->getPlatform()->supportsInsertNullPk()) {
  4152. $script .= "
  4153. // remove pkey col since this table uses auto-increment and passing a null value for it is not valid
  4154. \$criteria->remove($colConst);";
  4155. }
  4156. } elseif (!$this->getPlatform()->supportsInsertNullPk()) {
  4157. $script .= "
  4158. // remove pkey col if it is null since this table does not accept that
  4159. if (\$criteria->containsKey($colConst) && !\$criteria->keyContainsValue($colConst) ) {
  4160. \$criteria->remove($colConst);
  4161. }";
  4162. }
  4163. }
  4164. $script .= $this->addDoInsertBodyStandard();
  4165. foreach ($table->getPrimaryKey() as $col) {
  4166. if (!$col->isAutoIncrement()) {
  4167. continue;
  4168. }
  4169. if ($table->isAllowPkInsert()) {
  4170. $script .= "
  4171. if (\$pk !== null) {
  4172. \$this->set".$col->getPhpName()."(\$pk); //[IMV] update autoincrement primary key
  4173. }";
  4174. } else {
  4175. $script .= "
  4176. \$this->set".$col->getPhpName()."(\$pk); //[IMV] update autoincrement primary key";
  4177. }
  4178. }
  4179. return $script;
  4180. }
  4181. /**
  4182. * Boosts ActiveRecord::doInsert() by doing more calculations at buildtime.
  4183. */
  4184. protected function addDoInsertBodyRaw()
  4185. {
  4186. $this->declareClasses('Propel', 'PDO');
  4187. $table = $this->getTable();
  4188. $peerClassname = $this->getPeerClassname();
  4189. $platform = $this->getPlatform();
  4190. $primaryKeyMethodInfo = '';
  4191. if ($table->getIdMethodParameters()) {
  4192. $params = $table->getIdMethodParameters();
  4193. $imp = $params[0];
  4194. $primaryKeyMethodInfo = $imp->getValue();
  4195. } elseif ($table->getIdMethod() == IDMethod::NATIVE && ($platform->getNativeIdMethod() == PropelPlatformInterface::SEQUENCE || $platform->getNativeIdMethod() == PropelPlatformInterface::SERIAL)) {
  4196. $primaryKeyMethodInfo = $platform->getSequenceName($table);
  4197. }
  4198. $query = 'INSERT INTO ' . $platform->quoteIdentifier($table->getName()) . ' (%s) VALUES (%s)';
  4199. $script = "
  4200. \$modifiedColumns = array();
  4201. \$index = 0;
  4202. ";
  4203. foreach ($table->getPrimaryKey() as $column) {
  4204. if (!$column->isAutoIncrement()) {
  4205. continue;
  4206. }
  4207. $constantName = $this->getColumnConstant($column);
  4208. if ($platform->supportsInsertNullPk()) {
  4209. $script .= "
  4210. \$this->modifiedColumns[] = $constantName;";
  4211. }
  4212. $columnProperty = strtolower($column->getName());
  4213. if (!$table->isAllowPkInsert()) {
  4214. $script .= "
  4215. if (null !== \$this->{$columnProperty}) {
  4216. throw new PropelException('Cannot insert a value for auto-increment primary key (' . $constantName . ')');
  4217. }";
  4218. } elseif (!$platform->supportsInsertNullPk()) {
  4219. $script .= "
  4220. // add primary key column only if it is not null since this database does not accept that
  4221. if (null !== \$this->{$columnProperty}) {
  4222. \$this->modifiedColumns[] = $constantName;
  4223. }";
  4224. }
  4225. }
  4226. // if non auto-increment but using sequence, get the id first
  4227. if (!$platform->isNativeIdMethodAutoIncrement() && $table->getIdMethod() == "native") {
  4228. $column = $table->getFirstPrimaryKeyColumn();
  4229. $columnProperty = strtolower($column->getName());
  4230. $script .= "
  4231. if (null === \$this->{$columnProperty}) {
  4232. try {";
  4233. $script .= $platform->getIdentifierPhp('$this->'. $columnProperty, '$con', $primaryKeyMethodInfo, ' ');
  4234. $script .= "
  4235. } catch (Exception \$e) {
  4236. throw new PropelException('Unable to get sequence id.', \$e);
  4237. }
  4238. }
  4239. ";
  4240. }
  4241. $script .= "
  4242. // check the columns in natural order for more readable SQL queries";
  4243. foreach ($table->getColumns() as $column) {
  4244. $constantName = $this->getColumnConstant($column);
  4245. $identifier = var_export($platform->quoteIdentifier(strtoupper($column->getName())), true);
  4246. $script .= "
  4247. if (\$this->isColumnModified($constantName)) {
  4248. \$modifiedColumns[':p' . \$index++] = $identifier;
  4249. }";
  4250. }
  4251. $script .= "
  4252. \$sql = sprintf(
  4253. '$query',
  4254. implode(', ', \$modifiedColumns),
  4255. implode(', ', array_keys(\$modifiedColumns))
  4256. );
  4257. try {
  4258. \$stmt = \$con->prepare(\$sql);
  4259. foreach (\$modifiedColumns as \$identifier => \$columnName) {
  4260. switch (\$columnName) {";
  4261. foreach ($table->getColumns() as $column) {
  4262. $columnNameCase = var_export($platform->quoteIdentifier(strtoupper($column->getName())), true);
  4263. $script .= "
  4264. case $columnNameCase:";
  4265. $script .= $platform->getColumnBindingPHP($column, "\$identifier", '$this->' . strtolower($column->getName()), ' ');
  4266. $script .= "
  4267. break;";
  4268. }
  4269. $script .= "
  4270. }
  4271. }
  4272. \$stmt->execute();
  4273. } catch (Exception \$e) {
  4274. Propel::log(\$e->getMessage(), Propel::LOG_ERR);
  4275. throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', \$sql), \$e);
  4276. }
  4277. ";
  4278. // if auto-increment, get the id after
  4279. if ($platform->isNativeIdMethodAutoIncrement() && $table->getIdMethod() == "native") {
  4280. $column = $table->getFirstPrimaryKeyColumn();
  4281. $columnProperty = strtolower($column->getName());
  4282. $script .= "
  4283. try {";
  4284. $script .= $platform->getIdentifierPhp('$pk', '$con', $primaryKeyMethodInfo);
  4285. $script .= "
  4286. } catch (Exception \$e) {
  4287. throw new PropelException('Unable to get autoincrement id.', \$e);
  4288. }";
  4289. if ($table->isAllowPkInsert()) {
  4290. $script .= "
  4291. if (\$pk !== null) {
  4292. \$this->set".$column->getPhpName()."(\$pk);
  4293. }";
  4294. } else {
  4295. $script .= "
  4296. \$this->set".$column->getPhpName()."(\$pk);";
  4297. }
  4298. $script .= "
  4299. ";
  4300. }
  4301. return $script;
  4302. }
  4303. /**
  4304. * get the doUpdate() method code
  4305. *
  4306. * @return string the doUpdate() method code
  4307. */
  4308. protected function addDoUpdate()
  4309. {
  4310. $basePeerClassname = $this->getNewPeerBuilder($this->getTable())->getBasePeerClassname();
  4311. return "
  4312. /**
  4313. * Update the row in the database.
  4314. *
  4315. * @param PropelPDO \$con
  4316. *
  4317. * @see doSave()
  4318. */
  4319. protected function doUpdate(PropelPDO \$con)
  4320. {
  4321. \$selectCriteria = \$this->buildPkeyCriteria();
  4322. \$valuesCriteria = \$this->buildCriteria();
  4323. {$basePeerClassname}::doUpdate(\$selectCriteria, \$valuesCriteria, \$con);
  4324. }
  4325. ";
  4326. }
  4327. /**
  4328. * Adds the $alreadyInSave attribute, which prevents attempting to re-save the same object.
  4329. * @param string &$script The script will be modified in this method.
  4330. */
  4331. protected function addAlreadyInSaveAttribute(&$script)
  4332. {
  4333. $script .= "
  4334. /**
  4335. * Flag to prevent endless save loop, if this object is referenced
  4336. * by another object which falls in this transaction.
  4337. * @var boolean
  4338. */
  4339. protected \$alreadyInSave = false;
  4340. ";
  4341. }
  4342. /**
  4343. * Adds the save() method.
  4344. * @param string &$script The script will be modified in this method.
  4345. */
  4346. protected function addSave(&$script)
  4347. {
  4348. $this->addSaveComment($script);
  4349. $this->addSaveOpen($script);
  4350. $this->addSaveBody($script);
  4351. $this->addSaveClose($script);
  4352. }
  4353. /**
  4354. * Adds the comment for the save method
  4355. * @param string &$script The script will be modified in this method.
  4356. * @see addSave()
  4357. **/
  4358. protected function addSaveComment(&$script)
  4359. {
  4360. $table = $this->getTable();
  4361. $reloadOnUpdate = $table->isReloadOnUpdate();
  4362. $reloadOnInsert = $table->isReloadOnInsert();
  4363. $script .= "
  4364. /**
  4365. * Persists this object to the database.
  4366. *
  4367. * If the object is new, it inserts it; otherwise an update is performed.
  4368. * All modified related objects will also be persisted in the doSave()
  4369. * method. This method wraps all precipitate database operations in a
  4370. * single transaction.";
  4371. if ($reloadOnUpdate) {
  4372. $script .= "
  4373. *
  4374. * Since this table was configured to reload rows on update, the object will
  4375. * be reloaded from the database if an UPDATE operation is performed (unless
  4376. * the \$skipReload parameter is true).";
  4377. }
  4378. if ($reloadOnInsert) {
  4379. $script .= "
  4380. *
  4381. * Since this table was configured to reload rows on insert, the object will
  4382. * be reloaded from the database if an INSERT operation is performed (unless
  4383. * the \$skipReload parameter is true).";
  4384. }
  4385. $script .= "
  4386. *
  4387. * @param PropelPDO \$con";
  4388. if ($reloadOnUpdate || $reloadOnInsert) {
  4389. $script .= "
  4390. * @param boolean \$skipReload Whether to skip the reload for this object from database.";
  4391. }
  4392. $script .= "
  4393. * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  4394. * @throws PropelException
  4395. * @throws Exception
  4396. * @see doSave()
  4397. */";
  4398. }
  4399. /**
  4400. * Adds the function declaration for the save method
  4401. * @param string &$script The script will be modified in this method.
  4402. * @see addSave()
  4403. **/
  4404. protected function addSaveOpen(&$script)
  4405. {
  4406. $table = $this->getTable();
  4407. $reloadOnUpdate = $table->isReloadOnUpdate();
  4408. $reloadOnInsert = $table->isReloadOnInsert();
  4409. $script .= "
  4410. public function save(PropelPDO \$con = null".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").")
  4411. {";
  4412. }
  4413. /**
  4414. * Adds the function body for the save method
  4415. * @param string &$script The script will be modified in this method.
  4416. * @see addSave()
  4417. **/
  4418. protected function addSaveBody(&$script)
  4419. {
  4420. $table = $this->getTable();
  4421. $reloadOnUpdate = $table->isReloadOnUpdate();
  4422. $reloadOnInsert = $table->isReloadOnInsert();
  4423. $script .= "
  4424. if (\$this->isDeleted()) {
  4425. throw new PropelException(\"You cannot save an object that has been deleted.\");
  4426. }
  4427. if (\$con === null) {
  4428. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE);
  4429. }
  4430. \$con->beginTransaction();
  4431. \$isInsert = \$this->isNew();
  4432. try {";
  4433. if ($this->getGeneratorConfig()->getBuildProperty('addHooks')) {
  4434. // save with runtime hools
  4435. $script .= "
  4436. \$ret = \$this->preSave(\$con);";
  4437. $this->applyBehaviorModifier('preSave', $script, " ");
  4438. $script .= "
  4439. if (\$isInsert) {
  4440. \$ret = \$ret && \$this->preInsert(\$con);";
  4441. $this->applyBehaviorModifier('preInsert', $script, " ");
  4442. $script .= "
  4443. } else {
  4444. \$ret = \$ret && \$this->preUpdate(\$con);";
  4445. $this->applyBehaviorModifier('preUpdate', $script, " ");
  4446. $script .= "
  4447. }
  4448. if (\$ret) {
  4449. \$affectedRows = \$this->doSave(\$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload" : "").");
  4450. if (\$isInsert) {
  4451. \$this->postInsert(\$con);";
  4452. $this->applyBehaviorModifier('postInsert', $script, " ");
  4453. $script .= "
  4454. } else {
  4455. \$this->postUpdate(\$con);";
  4456. $this->applyBehaviorModifier('postUpdate', $script, " ");
  4457. $script .= "
  4458. }
  4459. \$this->postSave(\$con);";
  4460. $this->applyBehaviorModifier('postSave', $script, " ");
  4461. $script .= "
  4462. ".$this->getPeerClassname()."::addInstanceToPool(\$this);
  4463. } else {
  4464. \$affectedRows = 0;
  4465. }
  4466. \$con->commit();
  4467. return \$affectedRows;";
  4468. } else {
  4469. // save without runtime hooks
  4470. $this->applyBehaviorModifier('preSave', $script, " ");
  4471. if ($this->hasBehaviorModifier('preUpdate')) {
  4472. $script .= "
  4473. if (!\$isInsert) {";
  4474. $this->applyBehaviorModifier('preUpdate', $script, " ");
  4475. $script .= "
  4476. }";
  4477. }
  4478. if ($this->hasBehaviorModifier('preInsert')) {
  4479. $script .= "
  4480. if (\$isInsert) {";
  4481. $this->applyBehaviorModifier('preInsert', $script, " ");
  4482. $script .= "
  4483. }";
  4484. }
  4485. $script .= "
  4486. \$affectedRows = \$this->doSave(\$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload" : "").");";
  4487. $this->applyBehaviorModifier('postSave', $script, " ");
  4488. if ($this->hasBehaviorModifier('postUpdate')) {
  4489. $script .= "
  4490. if (!\$isInsert) {";
  4491. $this->applyBehaviorModifier('postUpdate', $script, " ");
  4492. $script .= "
  4493. }";
  4494. }
  4495. if ($this->hasBehaviorModifier('postInsert')) {
  4496. $script .= "
  4497. if (\$isInsert) {";
  4498. $this->applyBehaviorModifier('postInsert', $script, " ");
  4499. $script .= "
  4500. }";
  4501. }
  4502. $script .= "
  4503. \$con->commit();
  4504. ".$this->getPeerClassname()."::addInstanceToPool(\$this);
  4505. return \$affectedRows;";
  4506. }
  4507. $script .= "
  4508. } catch (Exception \$e) {
  4509. \$con->rollBack();
  4510. throw \$e;
  4511. }";
  4512. }
  4513. /**
  4514. * Adds the function close for the save method
  4515. * @param string &$script The script will be modified in this method.
  4516. * @see addSave()
  4517. **/
  4518. protected function addSaveClose(&$script)
  4519. {
  4520. $script .= "
  4521. }
  4522. ";
  4523. }
  4524. /**
  4525. * Adds the $alreadyInValidation attribute, which prevents attempting to re-validate the same object.
  4526. * @param string &$script The script will be modified in this method.
  4527. */
  4528. protected function addAlreadyInValidationAttribute(&$script)
  4529. {
  4530. $script .= "
  4531. /**
  4532. * Flag to prevent endless validation loop, if this object is referenced
  4533. * by another object which falls in this transaction.
  4534. * @var boolean
  4535. */
  4536. protected \$alreadyInValidation = false;
  4537. ";
  4538. }
  4539. /**
  4540. * Adds the validate() method.
  4541. * @param string &$script The script will be modified in this method.
  4542. */
  4543. protected function addValidate(&$script)
  4544. {
  4545. $script .= "
  4546. /**
  4547. * Validates the objects modified field values and all objects related to this table.
  4548. *
  4549. * If \$columns is either a column name or an array of column names
  4550. * only those columns are validated.
  4551. *
  4552. * @param mixed \$columns Column name or an array of column names.
  4553. * @return boolean Whether all columns pass validation.
  4554. * @see doValidate()
  4555. * @see getValidationFailures()
  4556. */
  4557. public function validate(\$columns = null)
  4558. {
  4559. \$res = \$this->doValidate(\$columns);
  4560. if (\$res === true) {
  4561. \$this->validationFailures = array();
  4562. return true;
  4563. } else {
  4564. \$this->validationFailures = \$res;
  4565. return false;
  4566. }
  4567. }
  4568. ";
  4569. } // addValidate()
  4570. /**
  4571. * Adds the workhourse doValidate() method.
  4572. * @param string &$script The script will be modified in this method.
  4573. */
  4574. protected function addDoValidate(&$script)
  4575. {
  4576. $table = $this->getTable();
  4577. $script .= "
  4578. /**
  4579. * This function performs the validation work for complex object models.
  4580. *
  4581. * In addition to checking the current object, all related objects will
  4582. * also be validated. If all pass then <code>true</code> is returned; otherwise
  4583. * an aggreagated array of ValidationFailed objects will be returned.
  4584. *
  4585. * @param array \$columns Array of column names to validate.
  4586. * @return mixed <code>true</code> if all validations pass; array of <code>ValidationFailed</code> objets otherwise.
  4587. */
  4588. protected function doValidate(\$columns = null)
  4589. {
  4590. if (!\$this->alreadyInValidation) {
  4591. \$this->alreadyInValidation = true;
  4592. \$retval = null;
  4593. \$failureMap = array();
  4594. ";
  4595. if (count($table->getForeignKeys()) != 0) {
  4596. $script .= "
  4597. // We call the validate method on the following object(s) if they
  4598. // were passed to this object by their coresponding set
  4599. // method. This object relates to these object(s) by a
  4600. // foreign key reference.
  4601. ";
  4602. foreach ($table->getForeignKeys() as $fk) {
  4603. $aVarName = $this->getFKVarName($fk);
  4604. $script .= "
  4605. if (\$this->".$aVarName." !== null) {
  4606. if (!\$this->".$aVarName."->validate(\$columns)) {
  4607. \$failureMap = array_merge(\$failureMap, \$this->".$aVarName."->getValidationFailures());
  4608. }
  4609. }
  4610. ";
  4611. } /* for () */
  4612. } /* if count(fkeys) */
  4613. $script .= "
  4614. if ((\$retval = ".$this->getPeerClassname()."::doValidate(\$this, \$columns)) !== true) {
  4615. \$failureMap = array_merge(\$failureMap, \$retval);
  4616. }
  4617. ";
  4618. foreach ($table->getReferrers() as $refFK) {
  4619. if ($refFK->isLocalPrimaryKey()) {
  4620. $varName = $this->getPKRefFKVarName($refFK);
  4621. $script .= "
  4622. if (\$this->$varName !== null) {
  4623. if (!\$this->".$varName."->validate(\$columns)) {
  4624. \$failureMap = array_merge(\$failureMap, \$this->".$varName."->getValidationFailures());
  4625. }
  4626. }
  4627. ";
  4628. } else {
  4629. $collName = $this->getRefFKCollVarName($refFK);
  4630. $script .= "
  4631. if (\$this->$collName !== null) {
  4632. foreach (\$this->$collName as \$referrerFK) {
  4633. if (!\$referrerFK->validate(\$columns)) {
  4634. \$failureMap = array_merge(\$failureMap, \$referrerFK->getValidationFailures());
  4635. }
  4636. }
  4637. }
  4638. ";
  4639. }
  4640. } /* foreach getReferrers() */
  4641. $script .= "
  4642. \$this->alreadyInValidation = false;
  4643. }
  4644. return (!empty(\$failureMap) ? \$failureMap : true);
  4645. }
  4646. ";
  4647. } // addDoValidate()
  4648. /**
  4649. * Adds the ensureConsistency() method to ensure that internal state is correct.
  4650. * @param string &$script The script will be modified in this method.
  4651. */
  4652. protected function addEnsureConsistency(&$script)
  4653. {
  4654. $table = $this->getTable();
  4655. $script .= "
  4656. /**
  4657. * Checks and repairs the internal consistency of the object.
  4658. *
  4659. * This method is executed after an already-instantiated object is re-hydrated
  4660. * from the database. It exists to check any foreign keys to make sure that
  4661. * the objects related to the current object are correct based on foreign key.
  4662. *
  4663. * You can override this method in the stub class, but you should always invoke
  4664. * the base method from the overridden method (i.e. parent::ensureConsistency()),
  4665. * in case your model changes.
  4666. *
  4667. * @throws PropelException
  4668. */
  4669. public function ensureConsistency()
  4670. {
  4671. ";
  4672. foreach ($table->getColumns() as $col) {
  4673. $clo=strtolower($col->getName());
  4674. if ($col->isForeignKey()) {
  4675. foreach ($col->getForeignKeys() as $fk) {
  4676. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  4677. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  4678. $varName = $this->getFKVarName($fk);
  4679. $script .= "
  4680. if (\$this->".$varName." !== null && \$this->$clo !== \$this->".$varName."->get".$colFK->getPhpName()."()) {
  4681. \$this->$varName = null;
  4682. }";
  4683. } // foraech
  4684. } /* if col is foreign key */
  4685. } // foreach
  4686. $script .= "
  4687. } // ensureConsistency
  4688. ";
  4689. } // addCheckRelConsistency
  4690. /**
  4691. * Adds the copy() method, which (in complex OM) includes the $deepCopy param for making copies of related objects.
  4692. * @param string &$script The script will be modified in this method.
  4693. */
  4694. protected function addCopy(&$script)
  4695. {
  4696. $this->addCopyInto($script);
  4697. $table = $this->getTable();
  4698. $script .= "
  4699. /**
  4700. * Makes a copy of this object that will be inserted as a new row in table when saved.
  4701. * It creates a new object filling in the simple attributes, but skipping any primary
  4702. * keys that are defined for the table.
  4703. *
  4704. * If desired, this method can also make copies of all associated (fkey referrers)
  4705. * objects.
  4706. *
  4707. * @param boolean \$deepCopy Whether to also copy all rows that refer (by fkey) to the current row.
  4708. * @return ".$this->getObjectClassname()." Clone of current object.
  4709. * @throws PropelException
  4710. */
  4711. public function copy(\$deepCopy = false)
  4712. {
  4713. // we use get_class(), because this might be a subclass
  4714. \$clazz = get_class(\$this);
  4715. " . $this->buildObjectInstanceCreationCode('$copyObj', '$clazz') . "
  4716. \$this->copyInto(\$copyObj, \$deepCopy);
  4717. return \$copyObj;
  4718. }
  4719. ";
  4720. } // addCopy()
  4721. /**
  4722. * Adds the copyInto() method, which takes an object and sets contents to match current object.
  4723. * In complex OM this method includes the $deepCopy param for making copies of related objects.
  4724. * @param string &$script The script will be modified in this method.
  4725. */
  4726. protected function addCopyInto(&$script)
  4727. {
  4728. $table = $this->getTable();
  4729. $script .= "
  4730. /**
  4731. * Sets contents of passed object to values from current object.
  4732. *
  4733. * If desired, this method can also make copies of all associated (fkey referrers)
  4734. * objects.
  4735. *
  4736. * @param object \$copyObj An object of ".$this->getObjectClassname()." (or compatible) type.
  4737. * @param boolean \$deepCopy Whether to also copy all rows that refer (by fkey) to the current row.
  4738. * @param boolean \$makeNew Whether to reset autoincrement PKs and make the object new.
  4739. * @throws PropelException
  4740. */
  4741. public function copyInto(\$copyObj, \$deepCopy = false, \$makeNew = true)
  4742. {";
  4743. $autoIncCols = array();
  4744. if ($table->hasCompositePrimaryKey()) {
  4745. foreach ($table->getColumns() as $col) {
  4746. /* @var $col Column */
  4747. if ($col->isAutoIncrement()) {
  4748. $autoIncCols[] = $col;
  4749. }
  4750. }
  4751. } else {
  4752. $autoIncCols = $table->getPrimaryKey();
  4753. }
  4754. foreach ($table->getColumns() as $col) {
  4755. if (!in_array($col, $autoIncCols, true)) {
  4756. $script .= "
  4757. \$copyObj->set".$col->getPhpName()."(\$this->get".$col->getPhpName()."());";
  4758. }
  4759. } // foreach
  4760. // Avoid useless code by checking to see if there are any referrers
  4761. // to this table:
  4762. if (count($table->getReferrers()) > 0 || count($table->getForeignKeys()) > 0 ) {
  4763. $script .= "
  4764. if (\$deepCopy && !\$this->startCopy) {
  4765. // important: temporarily setNew(false) because this affects the behavior of
  4766. // the getter/setter methods for fkey referrer objects.
  4767. \$copyObj->setNew(false);
  4768. // store object hash to prevent cycle
  4769. \$this->startCopy = true;
  4770. ";
  4771. foreach ($table->getReferrers() as $fk) {
  4772. //HL: commenting out self-referrential check below
  4773. // it seems to work as expected and is probably desireable to have those referrers from same table deep-copied.
  4774. //if ( $fk->getTable()->getName() != $table->getName() ) {
  4775. if ($fk->isLocalPrimaryKey()) {
  4776. $afx = $this->getRefFKPhpNameAffix($fk, $plural = false);
  4777. $script .= "
  4778. \$relObj = \$this->get$afx();
  4779. if (\$relObj) {
  4780. \$copyObj->set$afx(\$relObj->copy(\$deepCopy));
  4781. }
  4782. ";
  4783. } else {
  4784. $script .= "
  4785. foreach (\$this->get".$this->getRefFKPhpNameAffix($fk, true)."() as \$relObj) {
  4786. if (\$relObj !== \$this) { // ensure that we don't try to copy a reference to ourselves
  4787. \$copyObj->add".$this->getRefFKPhpNameAffix($fk)."(\$relObj->copy(\$deepCopy));
  4788. }
  4789. }
  4790. ";
  4791. }
  4792. // HL: commenting out close of self-referential check
  4793. // } /* if tblFK != table */
  4794. } /* foreach */
  4795. // do deep copy for one to one relation
  4796. foreach ($table->getForeignKeys() as $fk) {
  4797. if ($fk->isLocalPrimaryKey()) {
  4798. $afx = $this->getFKPhpNameAffix($fk, $plural = false);
  4799. $script .= "
  4800. \$relObj = \$this->get$afx();
  4801. if (\$relObj) {
  4802. \$copyObj->set$afx(\$relObj->copy(\$deepCopy));
  4803. }
  4804. ";
  4805. }
  4806. }
  4807. $script .= "
  4808. //unflag object copy
  4809. \$this->startCopy = false;
  4810. } // if (\$deepCopy)
  4811. ";
  4812. } /* if (count referrers > 0 ) */
  4813. $script .= "
  4814. if (\$makeNew) {
  4815. \$copyObj->setNew(true);";
  4816. // Note: we're no longer resetting non-autoincrement primary keys to default values
  4817. // due to: http://propel.phpdb.org/trac/ticket/618
  4818. foreach ($autoIncCols as $col) {
  4819. $coldefval = $col->getPhpDefaultValue();
  4820. $coldefval = var_export($coldefval, true);
  4821. $script .= "
  4822. \$copyObj->set".$col->getPhpName() ."($coldefval); // this is a auto-increment column, so set to default value";
  4823. } // foreach
  4824. $script .= "
  4825. }
  4826. }
  4827. ";
  4828. } // addCopyInto()
  4829. /**
  4830. * Adds clear method
  4831. * @param string &$script The script will be modified in this method.
  4832. */
  4833. protected function addClear(&$script)
  4834. {
  4835. $table = $this->getTable();
  4836. $script .= "
  4837. /**
  4838. * Clears the current object and sets all attributes to their default values
  4839. */
  4840. public function clear()
  4841. {";
  4842. foreach ($table->getColumns() as $col) {
  4843. $clo = strtolower($col->getName());
  4844. $script .= "
  4845. \$this->".$clo." = null;";
  4846. if ($col->isLazyLoad()) {
  4847. $script .= "
  4848. \$this->".$clo."_isLoaded = false;";
  4849. }
  4850. if ($col->getType() == PropelTypes::OBJECT || $col->getType() == PropelTypes::PHP_ARRAY) {
  4851. $cloUnserialized = $clo.'_unserialized';
  4852. $script .="
  4853. \$this->$cloUnserialized = null;";
  4854. }
  4855. }
  4856. $script .= "
  4857. \$this->alreadyInSave = false;
  4858. \$this->alreadyInValidation = false;
  4859. \$this->clearAllReferences();";
  4860. if ($this->hasDefaultValues()) {
  4861. $script .= "
  4862. \$this->applyDefaultValues();";
  4863. }
  4864. $script .= "
  4865. \$this->resetModified();
  4866. \$this->setNew(true);
  4867. \$this->setDeleted(false);
  4868. }
  4869. ";
  4870. }
  4871. /**
  4872. * Adds clearAllReferencers() method which resets all the collections of referencing
  4873. * fk objects.
  4874. * @param string &$script The script will be modified in this method.
  4875. */
  4876. protected function addClearAllReferences(&$script)
  4877. {
  4878. $table = $this->getTable();
  4879. $script .= "
  4880. /**
  4881. * Resets all references to other model objects or collections of model objects.
  4882. *
  4883. * This method is a user-space workaround for PHP's inability to garbage collect
  4884. * objects with circular references (even in PHP 5.3). This is currently necessary
  4885. * when using Propel in certain daemon or large-volumne/high-memory operations.
  4886. *
  4887. * @param boolean \$deep Whether to also clear the references on all referrer objects.
  4888. */
  4889. public function clearAllReferences(\$deep = false)
  4890. {
  4891. if (\$deep) {";
  4892. $vars = array();
  4893. foreach ($this->getTable()->getReferrers() as $refFK) {
  4894. if ($refFK->isLocalPrimaryKey()) {
  4895. $varName = $this->getPKRefFKVarName($refFK);
  4896. $script .= "
  4897. if (\$this->$varName) {
  4898. \$this->{$varName}->clearAllReferences(\$deep);
  4899. }";
  4900. } else {
  4901. $varName = $this->getRefFKCollVarName($refFK);
  4902. $script .= "
  4903. if (\$this->$varName) {
  4904. foreach (\$this->$varName as \$o) {
  4905. \$o->clearAllReferences(\$deep);
  4906. }
  4907. }";
  4908. }
  4909. $vars[] = $varName;
  4910. }
  4911. foreach ($this->getTable()->getCrossFks() as $fkList) {
  4912. list($refFK, $crossFK) = $fkList;
  4913. $varName = $this->getCrossFKVarName($crossFK);
  4914. $script .= "
  4915. if (\$this->$varName) {
  4916. foreach (\$this->$varName as \$o) {
  4917. \$o->clearAllReferences(\$deep);
  4918. }
  4919. }";
  4920. $vars[] = $varName;
  4921. }
  4922. $script .= "
  4923. } // if (\$deep)
  4924. ";
  4925. $this->applyBehaviorModifier('objectClearReferences', $script, " ");
  4926. foreach ($vars as $varName) {
  4927. $script .= "
  4928. if (\$this->$varName instanceof PropelCollection) {
  4929. \$this->{$varName}->clearIterator();
  4930. }
  4931. \$this->$varName = null;";
  4932. }
  4933. foreach ($table->getForeignKeys() as $fk) {
  4934. $varName = $this->getFKVarName($fk);
  4935. $script .= "
  4936. \$this->$varName = null;";
  4937. }
  4938. $script .= "
  4939. }
  4940. ";
  4941. }
  4942. /**
  4943. * Adds a magic __toString() method if a string column was defined as primary string
  4944. * @param string &$script The script will be modified in this method.
  4945. */
  4946. protected function addPrimaryString(&$script)
  4947. {
  4948. foreach ($this->getTable()->getColumns() as $column) {
  4949. if ($column->isPrimaryString()) {
  4950. $script .= "
  4951. /**
  4952. * return the string representation of this object
  4953. *
  4954. * @return string The value of the '{$column->getName()}' column
  4955. */
  4956. public function __toString()
  4957. {
  4958. return (string) \$this->get{$column->getPhpName()}();
  4959. }
  4960. ";
  4961. return;
  4962. }
  4963. }
  4964. // no primary string column, falling back to default string format
  4965. $script .= "
  4966. /**
  4967. * return the string representation of this object
  4968. *
  4969. * @return string
  4970. */
  4971. public function __toString()
  4972. {
  4973. return (string) \$this->exportTo(" . $this->getPeerClassname() . "::DEFAULT_STRING_FORMAT);
  4974. }
  4975. ";
  4976. }
  4977. /**
  4978. * Adds a magic __call() method
  4979. * @param string &$script The script will be modified in this method.
  4980. */
  4981. protected function addMagicCall(&$script)
  4982. {
  4983. $behaviorCallScript = '';
  4984. $this->applyBehaviorModifier('objectCall', $behaviorCallScript, " ");
  4985. if ($behaviorCallScript) {
  4986. $script .= "
  4987. /**
  4988. * Catches calls to virtual methods
  4989. */
  4990. public function __call(\$name, \$params)
  4991. {
  4992. $behaviorCallScript
  4993. return parent::__call(\$name, \$params);
  4994. }
  4995. ";
  4996. }
  4997. }
  4998. protected function addIsAlreadyInSave(&$script)
  4999. {
  5000. $script .= "
  5001. /**
  5002. * return true is the object is in saving state
  5003. *
  5004. * @return boolean
  5005. */
  5006. public function isAlreadyInSave()
  5007. {
  5008. return \$this->alreadyInSave;
  5009. }
  5010. ";
  5011. }
  5012. } // PHP5ObjectBuilder