/classes/formo/driver/core.php

https://github.com/justus/kohana-formo · PHP · 453 lines · 176 code · 63 blank · 214 comment · 12 complexity · c1bd7a28eaa9623439a10f649e6f4159 MD5 · raw file

  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Abstract Formo_Driver_Core class.
  4. *
  5. * @package Formo
  6. */
  7. abstract class Formo_Driver_Core {
  8. /**
  9. * Decorator object
  10. *
  11. * @var object
  12. * @access protected
  13. */
  14. protected $decorator;
  15. /**
  16. * Field or form object
  17. *
  18. * @var object
  19. * @access protected
  20. */
  21. protected $field;
  22. /**
  23. * The name of the variable passed into the view file
  24. *
  25. * (default value: 'field')
  26. *
  27. * @var string
  28. * @access public
  29. */
  30. public $alias = 'field';
  31. /**
  32. * Indicates whether this kind of field potentially does not have a post value
  33. *
  34. * (default value: FALSE)
  35. *
  36. * @var bool
  37. * @access public
  38. */
  39. public $empty_input = FALSE;
  40. /**
  41. * Indicates whether this kind of field must use the $_FILES array
  42. *
  43. * (default value: FALSE)
  44. *
  45. * @var bool
  46. * @access public
  47. */
  48. public $file = FALSE;
  49. /**
  50. * General factory method
  51. *
  52. * @access public
  53. * @static
  54. * @param mixed Formo_Container $field
  55. * @return void
  56. */
  57. public static function factory(Formo_Container $field)
  58. {
  59. return new Formo_Driver($field);
  60. }
  61. /**
  62. * Populate the field and decorator objects
  63. *
  64. * @access public
  65. * @param mixed Formo_Container $field
  66. * @return void
  67. */
  68. public function __construct(Formo_Container $field)
  69. {
  70. // Load the field instance
  71. $this->field = $field;
  72. // Determine the original decorator type
  73. $type = ($type = $this->field->get('type'))
  74. ? $type
  75. // Fall back on the default form type
  76. : Kohana::config('formo')->type;
  77. $this->decorator($type);
  78. }
  79. /**
  80. * Run methods on the decorator object
  81. *
  82. * @access public
  83. * @param mixed $method
  84. * @param mixed $args
  85. * @return void
  86. */
  87. public function __call($func, $args)
  88. {
  89. // At this point we need to run the method through the decorator
  90. $method = new ReflectionMethod($this->decorator, $func);
  91. return $method->invokeArgs($this->decorator, $args);
  92. }
  93. /**
  94. * Create the decorator instance
  95. *
  96. * @access public
  97. * @param mixed $type
  98. * @return void
  99. */
  100. public function decorator($type)
  101. {
  102. // Make the class name
  103. $class = 'Formo_Decorator_'.ucfirst($type);
  104. // Create the actual decorator object
  105. $this->decorator = new $class($this->field, $this);
  106. }
  107. /**
  108. * Append event takes place after field has been appended
  109. * to its parent
  110. *
  111. * @access public
  112. * @return void
  113. */
  114. public function append()
  115. {
  116. $this->decorator->append();
  117. }
  118. public function set($variable, $value)
  119. {
  120. // If the variable is inside the decorator, set that
  121. if (isset($this->decorator->$variable))
  122. $this->decorator->set($variable, $value);
  123. // Otherwise just set the field value
  124. $this->field->$variable = $value;
  125. return $this->field;
  126. }
  127. public function get($variable, $default)
  128. {
  129. if (isset($this->decorator->$variable))
  130. // If the variable is inside the decorator, return that
  131. return $this->decorator->get($variable);
  132. // Otherwise return the field value if it's set, or the default value if it's not
  133. return (isset($this->field->$variable))
  134. ? $this->field->$variable
  135. : $default;
  136. }
  137. /**
  138. * Called at field's construct. Gives driver chance to do stuff
  139. *
  140. * @access public
  141. * @return void
  142. */
  143. public function post_construct(){}
  144. /**
  145. * Called just before running validate()
  146. *
  147. * @access public
  148. * @return void
  149. */
  150. public function pre_validate(){}
  151. /**
  152. * Called just after running validate()
  153. *
  154. * @access public
  155. * @return void
  156. */
  157. public function post_validate(){}
  158. /**
  159. * Run when loading input data
  160. *
  161. * @access public
  162. * @param mixed $value
  163. * @return void
  164. */
  165. public function load($value)
  166. {
  167. // Just set the value to what was passed
  168. $this->val($value);
  169. }
  170. /**
  171. * Retrive a field's value
  172. *
  173. * @access protected
  174. * @return void
  175. */
  176. protected function get_val()
  177. {
  178. $new_value = $this->field->get('new_value');
  179. return (Formo::is_set($new_value) === TRUE)
  180. ? $new_value
  181. : $this->field->get('value');
  182. }
  183. /**
  184. * Set the field's value
  185. *
  186. * @access protected
  187. * @param mixed $value
  188. * @return void
  189. */
  190. protected function set_val($value)
  191. {
  192. $this->field->set('new_value', $value);
  193. }
  194. /**
  195. * Interface for setting, retrieving field's value
  196. *
  197. * @access public
  198. * @param mixed $value. (default: NULL)
  199. * @return void
  200. */
  201. public function val($value = NULL)
  202. {
  203. if (func_num_args() === 0)
  204. return $this->get_val();
  205. // Run pre_filters on the value
  206. $this->run_pre_filters($value);
  207. // Set the value
  208. $this->set_val($value);
  209. // Run ORM methods
  210. $this->set_orm_fields($value);
  211. return $this;
  212. }
  213. /**
  214. * Return the namespaced name
  215. *
  216. * @access public
  217. * @return void
  218. */
  219. public function name()
  220. {
  221. if ( ! $parent = $this->field->parent())
  222. // If there isn't a parent, don't namespace the name
  223. return $this->field->alias();
  224. return $parent->alias().'['.$this->field->alias().']';
  225. }
  226. /**
  227. * Pre-filter field value
  228. *
  229. * @access protected
  230. * @param mixed & $value
  231. * @return void
  232. */
  233. protected function run_pre_filters( & $value)
  234. {
  235. foreach ($this->field->get_filter('pre') as $filter)
  236. {
  237. // Resolve pseudo args
  238. $this->field->pseudo_args($filter->args, array(':value' => $value));
  239. // Run the filters
  240. $value = $filter->execute();
  241. }
  242. }
  243. /**
  244. * Make ORM field values match Formo field values
  245. *
  246. * @access protected
  247. * @param mixed $value
  248. * @return void
  249. */
  250. protected function set_orm_fields($value)
  251. {
  252. if ($orm = $this->field->model(TRUE))
  253. {
  254. $orm->set_field($this->field, $value);
  255. }
  256. }
  257. /**
  258. * Make every option an array of options
  259. *
  260. * @access public
  261. * @param mixed $options
  262. * @return void
  263. */
  264. public function set_options($options)
  265. {
  266. // Create the new array
  267. $array = array();
  268. foreach ($options as $alias => $value)
  269. {
  270. $array[$alias] = ( ! is_array($value))
  271. // Make the value part of an array
  272. ? array('value' => $value)
  273. : $value;
  274. }
  275. return $array;
  276. }
  277. /**
  278. * Run a method through the orm driver
  279. *
  280. * @access public
  281. * @param mixed $method
  282. * @return void
  283. */
  284. public function orm($method)
  285. {
  286. $args = array_slice(func_get_args(), 1);
  287. return call_user_func_array(array($this->field->orm_driver(), $method), $args);
  288. }
  289. /**
  290. * Runs just prior to rendering a form/field
  291. *
  292. * @access public
  293. * @return void
  294. */
  295. public function pre_render()
  296. {
  297. if (isset($this->field->orm))
  298. {
  299. $this->field->orm_driver()->pre_render();
  300. }
  301. $this->decorator->pre_render();
  302. return $this->field;
  303. }
  304. /**
  305. * Render the field
  306. *
  307. * @access public
  308. * @return void
  309. */
  310. public function render()
  311. {
  312. // First run and do any pre_render stuff
  313. $this->pre_render();
  314. return $this->decorator->render();
  315. }
  316. /**
  317. * Run when open is called on the decorator
  318. *
  319. * @access public
  320. * @return void
  321. */
  322. public function open()
  323. {
  324. // First run and do any pre_render stuff
  325. $this->pre_render();
  326. return $this->decorator->open();
  327. }
  328. /**
  329. * Generate a view from a field or form object
  330. *
  331. * @access public
  332. * @return void
  333. */
  334. public function generate($view_file = FALSE, $view_prefix = NULL)
  335. {
  336. if ($this->field->get('render', NULL) === FALSE)
  337. return;
  338. // First run and do any pre_render stuff
  339. $this->pre_render();
  340. // Prefix acts as a templating system for views
  341. $prefix = $this->get_view_prefix($view_prefix);
  342. // Determine the view file
  343. $view = $this->get_view($view_file);
  344. // Skip the prefix if view prefix is FALSE
  345. $skip_prefix = $view_prefix === FALSE;
  346. return $this->decorator->generate($view, $prefix);
  347. }
  348. protected function get_view($view = FALSE)
  349. {
  350. // The defined view file takes precendence over the default one
  351. // and the parameter passed into generate() takes first precedence
  352. return ($view !== FALSE)
  353. // Always choose the passed view if it exists
  354. ? $view
  355. // Next look for the field-level view
  356. : ($view = $this->field->get('view'))
  357. ? $view
  358. : $this->view;
  359. }
  360. protected function get_view_prefix($prefix = NULL)
  361. {
  362. // If the specified prefix is FALSE, no prefix
  363. if ($prefix === FALSE)
  364. return FALSE;
  365. // If the prefix was specified, use it
  366. if ($prefix !== NULL)
  367. return rtrim($prefix, '/');
  368. // Find the appropriate view_prefix
  369. $prefix = $this->field->get('view_prefix', NULL);
  370. if ($prefix === NULL)
  371. {
  372. $prefix = ($parent = $this->field->parent())
  373. ? $parent->get('view_prefix', NULL)
  374. : NULL;
  375. }
  376. // If prefix is still set to NULL and config file has one defined, use the config prefix
  377. if ($prefix === NULL AND $_prefix = Kohana::config('formo')->view_prefix)
  378. {
  379. $prefix = $_prefix;
  380. }
  381. return $prefix;
  382. }
  383. public function not_empty()
  384. {
  385. $new_value = $this->field->get('new_value');
  386. if (Formo::is_set($new_value) === FALSE AND ! $this->field->get('value'))
  387. return FALSE;
  388. return (bool) $new_value;
  389. }
  390. }