PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/sbweb/sbweb_logica/lib/symfony/plugins/sfDoctrinePlugin/lib/form/sfFormDoctrine.class.php

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