PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Form/Form.class.php

http://github.com/onPHP/onphp-framework
PHP | 485 lines | 303 code | 79 blank | 103 comment | 27 complexity | 9039e05bc7e8002c2db6b4e84c93d59c MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /****************************************************************************
  3. * Copyright (C) 2004-2009 by Konstantin V. Arkhipov, Anton E. Lebedevich *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU Lesser General Public License as *
  7. * published by the Free Software Foundation; either version 3 of the *
  8. * License, or (at your option) any later version. *
  9. * *
  10. ****************************************************************************/
  11. /**
  12. * Complete Form class.
  13. *
  14. * @ingroup Form
  15. * @ingroup Module
  16. *
  17. * @see http://onphp.org/examples.Form.en.html
  18. **/
  19. final class Form extends RegulatedForm
  20. {
  21. const WRONG = 0x0001;
  22. const MISSING = 0x0002;
  23. private $errors = array();
  24. private $labels = array();
  25. private $describedLabels = array();
  26. private $proto = null;
  27. private $importFiltering = true;
  28. /**
  29. * @return Form
  30. **/
  31. public static function create()
  32. {
  33. return new self;
  34. }
  35. public function getErrors()
  36. {
  37. return array_merge($this->errors, $this->violated);
  38. }
  39. public function hasError($name)
  40. {
  41. return array_key_exists($name, $this->errors)
  42. || array_key_exists($name, $this->violated);
  43. }
  44. public function getError($name)
  45. {
  46. if (array_key_exists($name, $this->errors)) {
  47. return $this->errors[$name];
  48. } elseif (array_key_exists($name, $this->violated)) {
  49. return $this->violated[$name];
  50. }
  51. return null;
  52. }
  53. public function getInnerErrors()
  54. {
  55. $result = $this->getErrors();
  56. foreach ($this->primitives as $name => $prm) {
  57. if (
  58. (
  59. ($prm instanceof PrimitiveFormsList)
  60. || ($prm instanceof PrimitiveForm)
  61. )
  62. && $prm->getValue()
  63. ) {
  64. if ($errors = $prm->getInnerErrors()) {
  65. $result[$name] = $errors;
  66. } else {
  67. unset($result[$name]);
  68. }
  69. }
  70. }
  71. return $result;
  72. }
  73. /**
  74. * @return Form
  75. **/
  76. public function dropAllErrors()
  77. {
  78. $this->errors = array();
  79. $this->violated = array();
  80. return $this;
  81. }
  82. /**
  83. * @return Form
  84. **/
  85. public function enableImportFiltering()
  86. {
  87. $this->importFiltering = true;
  88. return $this;
  89. }
  90. /**
  91. * @return Form
  92. **/
  93. public function disableImportFiltering()
  94. {
  95. $this->importFiltering = false;
  96. return $this;
  97. }
  98. /**
  99. * primitive marking
  100. **/
  101. //@{
  102. /**
  103. * @return Form
  104. **/
  105. public function markMissing($primitiveName)
  106. {
  107. return $this->markCustom($primitiveName, Form::MISSING);
  108. }
  109. /**
  110. * rule or primitive
  111. *
  112. * @return Form
  113. **/
  114. public function markWrong($name)
  115. {
  116. if (isset($this->primitives[$name]))
  117. $this->errors[$name] = self::WRONG;
  118. elseif (isset($this->rules[$name]))
  119. $this->violated[$name] = self::WRONG;
  120. else
  121. throw new MissingElementException(
  122. $name.' does not match known primitives or rules'
  123. );
  124. return $this;
  125. }
  126. /**
  127. * @return Form
  128. **/
  129. public function markGood($primitiveName)
  130. {
  131. if (isset($this->primitives[$primitiveName]))
  132. unset($this->errors[$primitiveName]);
  133. elseif (isset($this->rules[$primitiveName]))
  134. unset($this->violated[$primitiveName]);
  135. else
  136. throw new MissingElementException(
  137. $primitiveName.' does not match known primitives or rules'
  138. );
  139. return $this;
  140. }
  141. /**
  142. * Set's custom error mark for primitive.
  143. *
  144. * @return Form
  145. **/
  146. public function markCustom($primitiveName, $customMark)
  147. {
  148. Assert::isInteger($customMark);
  149. $this->errors[$this->get($primitiveName)->getName()] = $customMark;
  150. return $this;
  151. }
  152. //@}
  153. /**
  154. * Returns plain list of error's labels
  155. **/
  156. public function getTextualErrors()
  157. {
  158. $list = array();
  159. foreach (array_keys($this->labels) as $name) {
  160. if ($label = $this->getTextualErrorFor($name))
  161. $list[] = $label;
  162. }
  163. return $list;
  164. }
  165. public function getTextualErrorFor($name)
  166. {
  167. if (
  168. isset(
  169. $this->violated[$name],
  170. $this->labels[$name][$this->violated[$name]]
  171. )
  172. )
  173. return $this->labels[$name][$this->violated[$name]];
  174. elseif (
  175. isset(
  176. $this->errors[$name],
  177. $this->labels[$name][$this->errors[$name]]
  178. )
  179. )
  180. return $this->labels[$name][$this->errors[$name]];
  181. else
  182. return null;
  183. }
  184. public function getErrorDescriptionFor($name)
  185. {
  186. if (
  187. isset(
  188. $this->violated[$name],
  189. $this->describedLabels[$name][$this->violated[$name]]
  190. )
  191. )
  192. return $this->describedLabels[$name][$this->violated[$name]];
  193. elseif (
  194. isset(
  195. $this->errors[$name],
  196. $this->describedLabels[$name][$this->errors[$name]]
  197. )
  198. )
  199. return $this->describedLabels[$name][$this->errors[$name]];
  200. else
  201. return null;
  202. }
  203. /**
  204. * @return Form
  205. **/
  206. public function addErrorDescription($name, $errorType, $description)
  207. {
  208. if (
  209. !isset($this->rules[$name])
  210. && !$this->get($name)->getName()
  211. )
  212. throw new MissingElementException(
  213. "knows nothing about '{$name}'"
  214. );
  215. $this->describedLabels[$name][$errorType] = $description;
  216. return $this;
  217. }
  218. /**
  219. * @return Form
  220. **/
  221. public function addWrongLabel($primitiveName, $label)
  222. {
  223. return $this->addErrorLabel($primitiveName, Form::WRONG, $label);
  224. }
  225. /**
  226. * @return Form
  227. **/
  228. public function addMissingLabel($primitiveName, $label)
  229. {
  230. return $this->addErrorLabel($primitiveName, Form::MISSING, $label);
  231. }
  232. /**
  233. * @return Form
  234. **/
  235. public function addCustomLabel($primitiveName, $customMark, $label)
  236. {
  237. return $this->addErrorLabel($primitiveName, $customMark, $label);
  238. }
  239. public function getWrongLabel($primitiveName)
  240. {
  241. return $this->getErrorLabel($primitiveName, Form::WRONG);
  242. }
  243. public function getMissingLabel($primitiveName)
  244. {
  245. return $this->getErrorLabel($primitiveName, Form::MISSING);
  246. }
  247. /**
  248. * @return Form
  249. **/
  250. public function import($scope)
  251. {
  252. foreach ($this->primitives as $prm)
  253. $this->importPrimitive($scope, $prm);
  254. return $this;
  255. }
  256. /**
  257. * @return Form
  258. **/
  259. public function importMore($scope)
  260. {
  261. foreach ($this->primitives as $prm) {
  262. if (!$prm->isImported())
  263. $this->importPrimitive($scope, $prm);
  264. }
  265. return $this;
  266. }
  267. /**
  268. * @return Form
  269. **/
  270. public function importOne($primitiveName, $scope)
  271. {
  272. return $this->importPrimitive($scope, $this->get($primitiveName));
  273. }
  274. /**
  275. * @return Form
  276. **/
  277. public function importValue($primitiveName, $value)
  278. {
  279. $prm = $this->get($primitiveName);
  280. return $this->checkImportResult($prm, $prm->importValue($value));
  281. }
  282. /**
  283. * @return Form
  284. **/
  285. public function importOneMore($primitiveName, $scope)
  286. {
  287. $prm = $this->get($primitiveName);
  288. if (!$prm->isImported())
  289. return $this->importPrimitive($scope, $prm);
  290. return $this;
  291. }
  292. public function exportValue($primitiveName)
  293. {
  294. return $this->get($primitiveName)->exportValue();
  295. }
  296. public function export()
  297. {
  298. $result = array();
  299. foreach ($this->primitives as $name => $prm) {
  300. if ($prm->isImported())
  301. $result[$name] = $prm->exportValue();
  302. }
  303. return $result;
  304. }
  305. public function toFormValue($value)
  306. {
  307. if ($value instanceof FormField)
  308. return $this->getValue($value->getName());
  309. elseif ($value instanceof LogicalObject)
  310. return $value->toBoolean($this);
  311. else
  312. return $value;
  313. }
  314. /**
  315. * @return Form
  316. **/
  317. public function setProto(EntityProto $proto)
  318. {
  319. $this->proto = $proto;
  320. return $this;
  321. }
  322. /**
  323. * @return EntityProto
  324. **/
  325. public function getProto()
  326. {
  327. return $this->proto;
  328. }
  329. /**
  330. * @return Form
  331. **/
  332. private function importPrimitive($scope, BasePrimitive $prm)
  333. {
  334. if (!$this->importFiltering) {
  335. if ($prm instanceof FiltrablePrimitive) {
  336. $chain = $prm->getImportFilter();
  337. $prm->dropImportFilters();
  338. $result = $this->checkImportResult(
  339. $prm,
  340. $prm->import($scope)
  341. );
  342. $prm->setImportFilter($chain);
  343. return $result;
  344. } elseif ($prm instanceof PrimitiveForm) {
  345. return $this->checkImportResult(
  346. $prm,
  347. $prm->unfilteredImport($scope)
  348. );
  349. }
  350. }
  351. return $this->checkImportResult($prm, $prm->import($scope));
  352. }
  353. /**
  354. * @return Form
  355. **/
  356. private function checkImportResult(BasePrimitive $prm, $result)
  357. {
  358. if (
  359. $prm instanceof PrimitiveAlias
  360. && $result !== null
  361. )
  362. $this->markGood($prm->getInner()->getName());
  363. $name = $prm->getName();
  364. if (null === $result) {
  365. if ($prm->isRequired())
  366. $this->errors[$name] = self::MISSING;
  367. } elseif (true === $result) {
  368. unset($this->errors[$name]);
  369. } elseif ($error = $prm->getCustomError()) {
  370. $this->errors[$name] = $error;
  371. } else
  372. $this->errors[$name] = self::WRONG;
  373. return $this;
  374. }
  375. /**
  376. * Assigns specific label for given primitive and error type.
  377. * One more example of horrible documentation style.
  378. *
  379. * @param $name string primitive or rule name
  380. * @param $errorType enum Form::(WRONG|MISSING)
  381. * @param $label string YDFB WTF is this :-) (c) /.
  382. * @throws MissingElementException
  383. * @return Form
  384. **/
  385. private function addErrorLabel($name, $errorType, $label)
  386. {
  387. if (
  388. !isset($this->rules[$name])
  389. && !$this->get($name)->getName()
  390. )
  391. throw new MissingElementException(
  392. "knows nothing about '{$name}'"
  393. );
  394. $this->labels[$name][$errorType] = $label;
  395. return $this;
  396. }
  397. private function getErrorLabel($name, $errorType)
  398. {
  399. // checks for primitive's existence
  400. $this->get($name);
  401. if (isset($this->labels[$name][$errorType]))
  402. return $this->labels[$name][$errorType];
  403. return null;
  404. }
  405. }
  406. ?>