PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/forms/forms.php

http://github.com/andyhd/minim
PHP | 434 lines | 390 code | 38 blank | 6 comment | 32 complexity | f21f0f67a13a4dceb317e477f43b835c MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. class Minim_Forms implements Minim_Plugin // {{{
  3. {
  4. function form() // {{{
  5. {
  6. $argc = func_num_args();
  7. $argv = func_get_args();
  8. $model = NULL;
  9. $params = array();
  10. if ($argc > 0)
  11. {
  12. if (is_array($argv[0]))
  13. {
  14. $params = $argv[0];
  15. }
  16. if (is_string($argv[0]))
  17. {
  18. $model = $argv[0];
  19. if ($argc > 1 and is_array($argv[1]))
  20. {
  21. $params = $argv[1];
  22. }
  23. }
  24. }
  25. return new Minim_Form($model, $params);
  26. } // }}}
  27. } // }}}
  28. class Minim_Form // {{{
  29. {
  30. var $_model;
  31. var $_params;
  32. var $_fields;
  33. var $_validated;
  34. var $_errors;
  35. function __construct($model, $params=array()) // {{{
  36. {
  37. $this->_model = $model;
  38. $this->_params = $params;
  39. $this->_fields = array();
  40. $this->_validated = FALSE;
  41. $this->_errors = array();
  42. // build default form from model
  43. if ($this->_model)
  44. {
  45. $manager = minim('orm')->{$model};
  46. $have_data = array_key_exists('instance', $params);
  47. foreach ($manager->_fields as $name => $field)
  48. {
  49. $args = array();
  50. if ($have_data)
  51. {
  52. // get initial value for field
  53. $args['initial'] = $params['instance']->$name;
  54. // is field required? !blank & not_null
  55. if (!$field->attr('blank') and $field->attr('not_null'))
  56. {
  57. $args['required'] = TRUE;
  58. }
  59. // read only?
  60. if ($field->attr('read_only'))
  61. {
  62. $args['read_only'] = TRUE;
  63. }
  64. if ($field->attr('max_length'))
  65. {
  66. $args['max_length'] = $field->attr('max_length');
  67. }
  68. }
  69. if ($field->attr('primary_key'))
  70. {
  71. // don't show primary key field
  72. $this->hiddenField($name, $args);
  73. continue;
  74. }
  75. switch ($field->_type)
  76. {
  77. case 'timestamp':
  78. if (!$field->attr('read_only'))
  79. {
  80. $this->dateField($name, $args);
  81. }
  82. else
  83. {
  84. $this->hiddenField($name, $args);
  85. }
  86. break;
  87. case 'text':
  88. if (!$field->attr('read_only'))
  89. {
  90. if (!$field->attr('max_length'))
  91. {
  92. $this->textArea($name, $args);
  93. }
  94. else
  95. {
  96. $this->textField($name, $args);
  97. }
  98. }
  99. else
  100. {
  101. $this->hiddenField($name, $args);
  102. }
  103. break;
  104. case 'foreign_key':
  105. if ($have_data)
  106. {
  107. $key = $field->attr('field');
  108. $args['initial'] = $params['instance']->$name->$key;
  109. }
  110. if (!$field->attr('read_only'))
  111. {
  112. $model = $field->attr('model');
  113. $choices = array();
  114. foreach (minim('orm')->$model->all() as $obj)
  115. {
  116. $choice = "{$obj->_name}_{$obj->id}";
  117. $choices[$choice] = $obj->id;
  118. }
  119. $args['choices'] = $choices;
  120. $this->selectField($name, $args);
  121. }
  122. else
  123. {
  124. $this->hiddenField($name, $args);
  125. }
  126. break;
  127. default:
  128. if ($field->attr('read_only'))
  129. {
  130. $this->hiddenField($name, $args);
  131. }
  132. else
  133. {
  134. $this->textField($name, $args);
  135. }
  136. }
  137. }
  138. }
  139. } // }}}
  140. function &exclude($fields) // {{{
  141. {
  142. // TODO - find a more efficient way of doing this
  143. if (is_array($fields) and $fields)
  144. {
  145. foreach ($fields as $name)
  146. {
  147. if (array_key_exists($name, $this->_fields))
  148. {
  149. unset($this->_fields[$name]);
  150. }
  151. }
  152. }
  153. return $this;
  154. } // }}}
  155. function hiddenField($name, $params=array()) // {{{
  156. {
  157. $this->_fields[$name] = new Minim_Hidden($name, $params);
  158. return $this;
  159. } // }}}
  160. function textField($name, $params=array()) // {{{
  161. {
  162. $this->_fields[$name] = new Minim_Text($name, $params);
  163. return $this;
  164. } // }}}
  165. function passwordField($name, $params=array()) // {{{
  166. {
  167. $this->_fields[$name] = new Minim_Password($name, $params);
  168. return $this;
  169. } // }}}
  170. function dateField($name, $params=array()) // {{{
  171. {
  172. $this->_fields[$name] = new Minim_Date($name, $params);
  173. return $this;
  174. } // }}}
  175. function textArea($name, $params=array()) // {{{
  176. {
  177. $this->_fields[$name] = new Minim_TextArea($name, $params);
  178. return $this;
  179. } // }}}
  180. function selectField($name, $params=array()) // {{{
  181. {
  182. $this->_fields[$name] = new Minim_Select($name, $params);
  183. return $this;
  184. } // }}}
  185. function __get($name) // {{{
  186. {
  187. if (array_key_exists($name, $this->_fields))
  188. {
  189. $field =& $this->_fields[$name];
  190. return $field;
  191. }
  192. minim()->log("MinimForm {$this->_name} has no field named {$name}");
  193. return NULL;
  194. } // }}}
  195. function __set($name, $value) // {{{
  196. {
  197. if (array_key_exists($name, $this->_fields))
  198. {
  199. return $this->_fields[$name]->_value = $value;
  200. }
  201. } // }}}
  202. function from($data) // {{{
  203. {
  204. foreach ($this->_fields as $name => &$field)
  205. {
  206. if (array_key_exists($name, $data))
  207. {
  208. $field->_value = $data[$name];
  209. }
  210. }
  211. } // }}}
  212. function isValid() // {{{
  213. {
  214. if (!$this->_validated)
  215. {
  216. $this->_validated = TRUE;
  217. $errors = array();
  218. foreach ($this->_fields as $name => $field)
  219. {
  220. $errors[] = $field->isValid() ? NULL : "Field $name invalid";
  221. }
  222. $errors = array_filter($errors);
  223. $this->_errors = $errors;
  224. }
  225. return empty($this->_errors);
  226. } // }}}
  227. function errors() // {{{
  228. {
  229. return $this->_errors();
  230. } // }}}
  231. function getData() // {{{
  232. {
  233. $data = array();
  234. foreach ($this->_fields as $name => &$field)
  235. {
  236. $data[$name] = $field->getValue();
  237. }
  238. return $data;
  239. } // }}}
  240. } // }}}
  241. class Minim_Input // {{{
  242. {
  243. var $_initial;
  244. var $_value;
  245. var $_name;
  246. var $_attrs;
  247. var $_id;
  248. var $_class;
  249. var $label;
  250. function __construct($name, $params) // {{{
  251. {
  252. $this->_name = $name;
  253. $this->_attrs = $params;
  254. $this->_value = NULL;
  255. if (array_key_exists('initial', $this->_attrs))
  256. {
  257. $this->_initial = $params['initial'];
  258. unset($this->_attrs['initial']);
  259. }
  260. if (!array_key_exists('id', $this->_attrs))
  261. {
  262. $this->_id = "{$this->_name}_id";
  263. }
  264. else
  265. {
  266. $this->_id = $this->_attrs['id'];
  267. unset($this->_attrs['id']);
  268. }
  269. if (array_key_exists('classes', $this->_attrs))
  270. {
  271. $this->_class = ' class="'.join(' ', $this->_attrs['classes']).'"';
  272. unset($this->_attrs['classes']);
  273. }
  274. $label = ucfirst($this->_name);
  275. if (array_key_exists('label', $this->_attrs))
  276. {
  277. $label = $this->_attrs['label'];
  278. unset($this->_attrs['label']);
  279. }
  280. $this->label = <<<PHP
  281. <label for="{$this->_id}">{$label}</label>
  282. PHP;
  283. } // }}}
  284. function getValue() // {{{
  285. {
  286. if (!$this->_value)
  287. {
  288. return $this->_initial;
  289. }
  290. return $this->_value;
  291. } // }}}
  292. function render() // {{{
  293. {
  294. die('Minim_Input::render must be overridden');
  295. } // }}}
  296. function isValid() // {{{
  297. {
  298. return TRUE;
  299. } // }}}
  300. } // }}}
  301. class Minim_Hidden extends Minim_Input // {{{
  302. {
  303. function __construct($name, $params)
  304. {
  305. parent::__construct($name, $params);
  306. $this->label = '';
  307. }
  308. function render()
  309. {
  310. return <<<PHP
  311. <input type="hidden" name="{$this->_name}" value="{$this->getValue()}">
  312. PHP;
  313. }
  314. } // }}}
  315. class Minim_Text extends Minim_Input // {{{
  316. {
  317. function __construct($name, $params)
  318. {
  319. parent::__construct($name, $params);
  320. $this->_maxlen = @$params['max_length'];
  321. }
  322. function render()
  323. {
  324. $maxlen = '';
  325. if ($this->_maxlen)
  326. {
  327. $maxlen = ' maxlen="'.$this->_maxlen.'"';
  328. }
  329. return <<<PHP
  330. <input id="{$this->_id}" type="text" name="{$this->_name}" value="{$this->getValue()}"{$this->_class}$maxlen>
  331. PHP;
  332. }
  333. } // }}}
  334. class Minim_Password extends Minim_Input // {{{
  335. {
  336. function render()
  337. {
  338. return <<<PHP
  339. <input id="{$this->_id}" type="password" name="{$this->_name}"{$this->_class}>
  340. PHP;
  341. }
  342. } // }}}
  343. class Minim_Date extends Minim_Input // {{{
  344. {
  345. function render()
  346. {
  347. $date = date('Y-m-d H:i:s', $this->getValue());
  348. return <<<PHP
  349. <input id="{$this->_id}" type="text" name="{$this->_name}" value="{$date}"{$this->_class}>
  350. PHP;
  351. }
  352. } // }}}
  353. class Minim_TextArea extends Minim_Input // {{{
  354. {
  355. function render()
  356. {
  357. $rows = (int) @$this->_attrs['rows'];
  358. $rows = $rows ? ' rows="'.$rows.'"' : '';
  359. return <<<PHP
  360. <textarea id="{$this->_id}" name="{$this->_name}"{$rows}{$this->_class}>{$this->getValue()}</textarea>
  361. PHP;
  362. }
  363. } // }}}
  364. class Minim_Select extends Minim_Input // {{{
  365. {
  366. var $_choices;
  367. function __construct($name, $params) // {{{
  368. {
  369. parent::__construct($name, $params);
  370. $this->_choices = array();
  371. if (is_array(@$params['choices']))
  372. {
  373. $this->_choices = $params['choices'];
  374. }
  375. } // }}}
  376. function render() // {{{
  377. {
  378. $options = '';
  379. foreach ($this->_choices as $name => $value)
  380. {
  381. $selected = '';
  382. if ($value == $this->_initial)
  383. {
  384. $selected = ' selected="selected"';
  385. }
  386. $options .= <<<PHP
  387. <option value="$value"$selected>$name</option>
  388. PHP;
  389. }
  390. return <<<PHP
  391. <select id="{$this->_id}" name="{$this->_name}"{$this->_class}>
  392. $options
  393. </select>
  394. PHP;
  395. } // }}}
  396. } // }}}