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

/sbweb/sbweb_logica/lib/symfony/plugins/sfPropelPlugin/lib/form/sfFormPropel.class.php

http://opac-sbweb.googlecode.com/
PHP | 531 lines | 292 code | 65 blank | 174 comment | 34 complexity | ba9ed1e2c37d0b76380939c8f47c85cc MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * sfFormPropel is the base class for forms based on Propel objects.
  11. *
  12. * @package symfony
  13. * @subpackage form
  14. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  15. * @version SVN: $Id: sfFormPropel.class.php 15033 2009-01-28 22:40:25Z FabianLange $
  16. */
  17. abstract class sfFormPropel extends sfForm
  18. {
  19. protected
  20. $isNew = true,
  21. $object = null;
  22. /**
  23. * Constructor.
  24. *
  25. * @param BaseObject $object A Propel object used to initialize default values
  26. * @param array $options An array of options
  27. * @param string $CSRFSecret A CSRF secret (false to disable CSRF protection, null to use the global CSRF secret)
  28. *
  29. * @see sfForm
  30. */
  31. public function __construct(BaseObject $object = null, $options = array(), $CSRFSecret = null)
  32. {
  33. $class = $this->getModelName();
  34. if (is_null($object))
  35. {
  36. $this->object = new $class();
  37. }
  38. else
  39. {
  40. if (!$object instanceof $class)
  41. {
  42. throw new sfException(sprintf('The "%s" form only accepts a "%s" object.', get_class($this), $class));
  43. }
  44. $this->object = $object;
  45. $this->isNew = $this->object->isNew();
  46. }
  47. parent::__construct(array(), $options, $CSRFSecret);
  48. $this->updateDefaultsFromObject();
  49. }
  50. /**
  51. * Returns the default connection for the current model.
  52. *
  53. * @return PropelPDO A database connection
  54. */
  55. public function getConnection()
  56. {
  57. return Propel::getConnection(constant(sprintf('%s::DATABASE_NAME', get_class($this->object->getPeer()))));
  58. }
  59. /**
  60. * Returns the current model name.
  61. */
  62. abstract public function getModelName();
  63. /**
  64. * Returns true if the current form embeds a new object.
  65. *
  66. * @return Boolean true if the current form embeds a new object, false otherwise
  67. */
  68. public function isNew()
  69. {
  70. return $this->isNew;
  71. }
  72. /**
  73. * Embeds i18n objects into the current form.
  74. *
  75. * @param array $cultures An array of cultures
  76. * @param string $decorator A HTML decorator for the embedded form
  77. */
  78. public function embedI18n($cultures, $decorator = null)
  79. {
  80. if (!$this->isI18n())
  81. {
  82. throw new sfException(sprintf('The model "%s" is not internationalized.', $this->getModelName()));
  83. }
  84. $class = $this->getI18nFormClass();
  85. foreach ($cultures as $culture)
  86. {
  87. $method = sprintf('getCurrent%s', $this->getI18nModelName($culture));
  88. $i18nObject = $this->object->$method($culture);
  89. $i18n = new $class($i18nObject);
  90. unset($i18n['id'], $i18n['culture']);
  91. $this->embedForm($culture, $i18n, $decorator);
  92. }
  93. }
  94. /**
  95. * Returns the current object for this form.
  96. *
  97. * @return BaseObject The current object.
  98. */
  99. public function getObject()
  100. {
  101. return $this->object;
  102. }
  103. /**
  104. * Binds the current form and save the to the database in one step.
  105. *
  106. * @param array $taintedValues An array of tainted values to use to bind the form
  107. * @param array $taintedFiles An array of uploaded files (in the $_FILES or $_GET format)
  108. * @param PropelPDO $con An optional PropelPDO object
  109. *
  110. * @return Boolean true if the form is valid, false otherwise
  111. */
  112. public function bindAndSave($taintedValues, $taintedFiles = null, $con = null)
  113. {
  114. $this->bind($taintedValues, $taintedFiles);
  115. if ($this->isValid())
  116. {
  117. $this->save($con);
  118. return true;
  119. }
  120. return false;
  121. }
  122. /**
  123. * Saves the current object to the database.
  124. *
  125. * The object saving is done in a transaction and handled by the doSave() method.
  126. *
  127. * If the form is not valid, it throws an sfValidatorError.
  128. *
  129. * @param PropelPDO $con An optional PropelPDO object
  130. *
  131. * @return BaseObject The current saved object
  132. *
  133. * @see doSave()
  134. */
  135. public function save($con = null)
  136. {
  137. if (!$this->isValid())
  138. {
  139. throw $this->getErrorSchema();
  140. }
  141. if (is_null($con))
  142. {
  143. $con = $this->getConnection();
  144. }
  145. try
  146. {
  147. $con->beginTransaction();
  148. $this->doSave($con);
  149. $con->commit();
  150. }
  151. catch (Exception $e)
  152. {
  153. $con->rollBack();
  154. throw $e;
  155. }
  156. return $this->object;
  157. }
  158. /**
  159. * Updates the values of the object with the cleaned up values.
  160. *
  161. * @param array $values An array of values
  162. *
  163. * @return BaseObject The current updated object
  164. */
  165. public function updateObject($values = null)
  166. {
  167. if (is_null($values))
  168. {
  169. $values = $this->values;
  170. }
  171. $values = $this->processValues($values);
  172. $this->object->fromArray($values, BasePeer::TYPE_FIELDNAME);
  173. // embedded forms
  174. $this->updateObjectEmbeddedForms($values);
  175. return $this->object;
  176. }
  177. /**
  178. * Updates the values of the objects in embedded forms.
  179. *
  180. * @param array $values An array of values
  181. * @param array $forms An array of forms
  182. */
  183. public function updateObjectEmbeddedForms($values, $forms = null)
  184. {
  185. if (is_null($forms))
  186. {
  187. $forms = $this->embeddedForms;
  188. }
  189. foreach ($forms as $name => $form)
  190. {
  191. if (!is_array($values[$name]))
  192. {
  193. continue;
  194. }
  195. if ($form instanceof sfFormPropel)
  196. {
  197. $form->updateObject($values[$name]);
  198. }
  199. else
  200. {
  201. $this->updateObjectEmbeddedForms($values[$name], $form->getEmbeddedForms());
  202. }
  203. }
  204. }
  205. /**
  206. * Processes cleaned up values with user defined methods.
  207. *
  208. * To process a value before it is used by the updateObject() method,
  209. * you need to define an updateXXXColumn() method where XXX is the PHP name
  210. * of the column.
  211. *
  212. * The method must return the processed value or false to remove the value
  213. * from the array of cleaned up values.
  214. *
  215. * @param array $values An array of values
  216. *
  217. * @return array An array of cleaned up values processed by the user defined methods
  218. */
  219. public function processValues($values)
  220. {
  221. // see if the user has overridden some column setter
  222. $valuesToProcess = $values;
  223. foreach ($valuesToProcess as $field => $value)
  224. {
  225. try
  226. {
  227. $method = sprintf('update%sColumn', call_user_func(array(constant(get_class($this->object).'::PEER'), 'translateFieldName'), $field, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME));
  228. }
  229. catch (Exception $e)
  230. {
  231. // not a "real" column of this object
  232. if (!method_exists($this, $method = sprintf('update%sColumn', self::camelize($field))))
  233. {
  234. continue;
  235. }
  236. }
  237. if (method_exists($this, $method))
  238. {
  239. if (false === $ret = $this->$method($value))
  240. {
  241. unset($values[$field]);
  242. }
  243. else
  244. {
  245. $values[$field] = $ret;
  246. }
  247. }
  248. else
  249. {
  250. // save files
  251. if ($this->validatorSchema[$field] instanceof sfValidatorFile)
  252. {
  253. $values[$field] = $this->processUploadedFile($field, null, $valuesToProcess);
  254. }
  255. }
  256. }
  257. return $values;
  258. }
  259. /**
  260. * Returns true if the current form has some associated i18n objects.
  261. *
  262. * @return Boolean true if the current form has some associated i18n objects, false otherwise
  263. */
  264. public function isI18n()
  265. {
  266. return !is_null($this->getI18nFormClass());
  267. }
  268. /**
  269. * Returns the name of the i18n model.
  270. *
  271. * @return string The name of the i18n model
  272. */
  273. public function getI18nModelName()
  274. {
  275. return null;
  276. }
  277. /**
  278. * Returns the name of the i18n form class.
  279. *
  280. * @return string The name of the i18n form class
  281. */
  282. public function getI18nFormClass()
  283. {
  284. return null;
  285. }
  286. /**
  287. * Renders a form tag suitable for the related Propel object.
  288. *
  289. * The method is automatically guessed based on the Propel object:
  290. *
  291. * * if the object is new, the method is POST
  292. * * if the object already exists, the method is PUT
  293. *
  294. * @param string $url The URL for the action
  295. * @param array $attributes An array of HTML attributes
  296. *
  297. * @return string An HTML representation of the opening form tag
  298. *
  299. * @see sfForm
  300. */
  301. public function renderFormTag($url, array $attributes = array())
  302. {
  303. if (!isset($attributes['method']))
  304. {
  305. $attributes['method'] = $this->getObject()->isNew() ? 'post' : 'put';
  306. }
  307. return parent::renderFormTag($url, $attributes);
  308. }
  309. /**
  310. * Updates and saves the current object.
  311. *
  312. * If you want to add some logic before saving or save other associated objects,
  313. * this is the method to override.
  314. *
  315. * @param PropelPDO $con An optional PropelPDO object
  316. */
  317. protected function doSave($con = null)
  318. {
  319. if (is_null($con))
  320. {
  321. $con = $this->getConnection();
  322. }
  323. $this->updateObject();
  324. $this->object->save($con);
  325. // embedded forms
  326. $this->saveEmbeddedForms($con);
  327. }
  328. /**
  329. * Saves embedded form objects.
  330. *
  331. * @param PropelPDO $con An optional PropelPDO object
  332. * @param array $forms An array of forms
  333. */
  334. public function saveEmbeddedForms($con = null, $forms = null)
  335. {
  336. if (is_null($con))
  337. {
  338. $con = $this->getConnection();
  339. }
  340. if (is_null($forms))
  341. {
  342. $forms = $this->embeddedForms;
  343. }
  344. foreach ($forms as $form)
  345. {
  346. if ($form instanceof sfFormPropel)
  347. {
  348. $form->saveEmbeddedForms($con);
  349. $form->getObject()->save($con);
  350. }
  351. else
  352. {
  353. $this->saveEmbeddedForms($con, $form->getEmbeddedForms());
  354. }
  355. }
  356. }
  357. /**
  358. * Updates the default values of the form with the current values of the current object.
  359. */
  360. protected function updateDefaultsFromObject()
  361. {
  362. // update defaults for the main object
  363. if ($this->isNew)
  364. {
  365. $this->setDefaults(array_merge($this->object->toArray(BasePeer::TYPE_FIELDNAME), $this->getDefaults()));
  366. }
  367. else
  368. {
  369. $this->setDefaults(array_merge($this->getDefaults(), $this->object->toArray(BasePeer::TYPE_FIELDNAME)));
  370. }
  371. }
  372. /**
  373. * Saves the uploaded file for the given field.
  374. *
  375. * @param string $field The field name
  376. * @param string $filename The file name of the file to save
  377. * @param array $values An array of values
  378. *
  379. * @return string The filename used to save the file
  380. */
  381. protected function processUploadedFile($field, $filename = null, $values = null)
  382. {
  383. if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
  384. {
  385. throw new LogicException(sprintf('You cannot save the current file for field "%s" as the field is not a file.', $field));
  386. }
  387. if (is_null($values))
  388. {
  389. $values = $this->values;
  390. }
  391. if (isset($values[$field.'_delete']) && $values[$field.'_delete'])
  392. {
  393. $this->removeFile($field);
  394. return '';
  395. }
  396. if (!$values[$field])
  397. {
  398. $column = call_user_func(array(constant(get_class($this->object).'::PEER'), 'translateFieldName'), $field, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
  399. $getter = 'get'.$column;
  400. return $this->object->$getter();
  401. }
  402. // we need the base directory
  403. if (!$this->validatorSchema[$field]->getOption('path'))
  404. {
  405. return $values[$field];
  406. }
  407. $this->removeFile($field);
  408. return $this->saveFile($field, $filename, $values[$field]);
  409. }
  410. /**
  411. * Removes the current file for the field.
  412. *
  413. * @param string $field The field name
  414. */
  415. protected function removeFile($field)
  416. {
  417. if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
  418. {
  419. throw new LogicException(sprintf('You cannot remove the current file for field "%s" as the field is not a file.', $field));
  420. }
  421. $column = call_user_func(array(constant(get_class($this->object).'::PEER'), 'translateFieldName'), $field, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
  422. $getter = 'get'.$column;
  423. if (($directory = $this->validatorSchema[$field]->getOption('path')) && is_file($directory.DIRECTORY_SEPARATOR.$this->object->$getter()))
  424. {
  425. unlink($directory.DIRECTORY_SEPARATOR.$this->object->$getter());
  426. }
  427. }
  428. /**
  429. * Saves the current file for the field.
  430. *
  431. * @param string $field The field name
  432. * @param string $filename The file name of the file to save
  433. * @param sfValidatedFile $file The validated file to save
  434. *
  435. * @return string The filename used to save the file
  436. */
  437. protected function saveFile($field, $filename = null, sfValidatedFile $file = null)
  438. {
  439. if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
  440. {
  441. throw new LogicException(sprintf('You cannot save the current file for field "%s" as the field is not a file.', $field));
  442. }
  443. if (is_null($file))
  444. {
  445. $file = $this->getValue($field);
  446. }
  447. $column = call_user_func(array(constant(get_class($this->object).'::PEER'), 'translateFieldName'), $field, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
  448. $method = sprintf('generate%sFilename', $column);
  449. if (!is_null($filename))
  450. {
  451. return $file->save($filename);
  452. }
  453. else if (method_exists($this->object, $method))
  454. {
  455. return $file->save($this->object->$method($file));
  456. }
  457. else
  458. {
  459. return $file->save();
  460. }
  461. }
  462. protected function camelize($text)
  463. {
  464. return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
  465. }
  466. }