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

/vendor/anahkiasen/former/src/Former/Former.php

https://gitlab.com/hatemdigify/digifyblog
PHP | 489 lines | 265 code | 53 blank | 171 comment | 14 complexity | 0c65e36191013d00d403c982b375f854 MD5 | raw file
  1. <?php
  2. namespace Former;
  3. use Closure;
  4. use Former\Exceptions\InvalidFrameworkException;
  5. use Former\Traits\Field;
  6. use Illuminate\Container\Container;
  7. use Illuminate\Support\MessageBag;
  8. use Illuminate\Contracts\Validation\Validator;
  9. /**
  10. * Helps the user interact with the various Former components
  11. */
  12. class Former
  13. {
  14. // Instances
  15. ////////////////////////////////////////////////////////////////////
  16. /**
  17. * The current environment
  18. *
  19. * @var \Illuminate\Container\Container
  20. */
  21. protected $app;
  22. /**
  23. * The Method Dispatcher
  24. *
  25. * @var MethodDispatcher
  26. */
  27. protected $dispatch;
  28. // Informations
  29. ////////////////////////////////////////////////////////////////////
  30. /**
  31. * The form's errors
  32. *
  33. * @var Message
  34. */
  35. protected $errors;
  36. /**
  37. * An array of rules to use
  38. *
  39. * @var array
  40. */
  41. protected $rules = array();
  42. /**
  43. * An array of field macros
  44. *
  45. * @var array
  46. */
  47. protected $macros = array();
  48. /**
  49. * The labels created so far
  50. *
  51. * @var array
  52. */
  53. public $labels = array();
  54. /**
  55. * The IDs created so far
  56. *
  57. * @var array
  58. */
  59. public $ids = array();
  60. /**
  61. * A lookup table where the key is the input name,
  62. * and the value is number of times seen. This is
  63. * used to calculate unique ids.
  64. *
  65. * @var array
  66. */
  67. public $names = array();
  68. // Namespaces
  69. ////////////////////////////////////////////////////////////////////
  70. /**
  71. * The namespace of Form elements
  72. */
  73. const FORMSPACE = 'Former\Form\\';
  74. /**
  75. * The namespace of fields
  76. */
  77. const FIELDSPACE = 'Former\Form\Fields\\';
  78. /**
  79. * Build a new Former instance
  80. *
  81. * @param Container $app
  82. * @param MethodDispatcher $dispatcher
  83. */
  84. public function __construct(Container $app, MethodDispatcher $dispatcher)
  85. {
  86. $this->app = $app;
  87. $this->dispatch = $dispatcher;
  88. }
  89. ////////////////////////////////////////////////////////////////////
  90. //////////////////////////// INTERFACE /////////////////////////////
  91. ////////////////////////////////////////////////////////////////////
  92. /**
  93. * Acts as a router that redirects methods to all of Former classes
  94. *
  95. * @param string $method The method called
  96. * @param array $parameters An array of parameters
  97. *
  98. * @return mixed
  99. */
  100. public function __call($method, $parameters)
  101. {
  102. // Dispatch to Form\Elements
  103. // Explicitly check false since closeGroup() may return an empty string
  104. if (($element = $this->dispatch->toElements($method, $parameters)) !== false) {
  105. return $element;
  106. }
  107. // Dispatch to Form\Form
  108. if ($form = $this->dispatch->toForm($method, $parameters)) {
  109. $this->app->instance('former.form', $form);
  110. return $this->app['former.form'];
  111. }
  112. // Dispatch to Form\Group
  113. if ($group = $this->dispatch->toGroup($method, $parameters)) {
  114. return $group;
  115. }
  116. // Dispatch to Form\Actions
  117. if ($actions = $this->dispatch->toActions($method, $parameters)) {
  118. return $actions;
  119. }
  120. // Dispatch to macros
  121. if ($macro = $this->dispatch->toMacros($method, $parameters)) {
  122. return $macro;
  123. }
  124. // Checking for any supplementary classes
  125. $classes = explode('_', $method);
  126. $method = array_pop($classes);
  127. // Dispatch to the different Form\Fields
  128. $framework = isset($this->app['former.form.framework']) ? $this->app['former.form.framework'] : $this->app['former.framework'];
  129. $field = $this->dispatch->toFields($method, $parameters);
  130. if ($field instanceof Field) {
  131. $field = $framework->getFieldClasses($field, $classes);
  132. }
  133. // Else bind field
  134. $this->app->instance('former.field', $field);
  135. return $this->app['former.field'];
  136. }
  137. ////////////////////////////////////////////////////////////////////
  138. //////////////////////////////// MACROS ////////////////////////////
  139. ////////////////////////////////////////////////////////////////////
  140. /**
  141. * Register a macro with Former
  142. *
  143. * @param string $name The name of the macro
  144. * @param Callable $macro The macro itself
  145. *
  146. * @return mixed
  147. */
  148. public function macro($name, $macro)
  149. {
  150. $this->macros[$name] = $macro;
  151. }
  152. /**
  153. * Check if a macro exists
  154. *
  155. * @param string $name
  156. *
  157. * @return boolean
  158. */
  159. public function hasMacro($name)
  160. {
  161. return isset($this->macros[$name]);
  162. }
  163. /**
  164. * Get a registered macro
  165. *
  166. * @param string $name
  167. *
  168. * @return Closure
  169. */
  170. public function getMacro($name)
  171. {
  172. return $this->macros[$name];
  173. }
  174. ////////////////////////////////////////////////////////////////////
  175. ///////////////////////////// POPULATOR ////////////////////////////
  176. ////////////////////////////////////////////////////////////////////
  177. /**
  178. * Add values to populate the array
  179. *
  180. * @param mixed $values Can be an Eloquent object or an array
  181. */
  182. public function populate($values)
  183. {
  184. $this->app['former.populator']->replace($values);
  185. }
  186. /**
  187. * Set the value of a particular field
  188. *
  189. * @param string $field The field's name
  190. * @param mixed $value Its new value
  191. */
  192. public function populateField($field, $value)
  193. {
  194. $this->app['former.populator']->put($field, $value);
  195. }
  196. /**
  197. * Get the value of a field
  198. *
  199. * @param string $field The field's name
  200. * @param null $fallback
  201. *
  202. * @return mixed
  203. */
  204. public function getValue($field, $fallback = null)
  205. {
  206. return $this->app['former.populator']->get($field, $fallback);
  207. }
  208. /**
  209. * Fetch a field value from both the new and old POST array
  210. *
  211. * @param string $name A field name
  212. * @param string $fallback A fallback if nothing was found
  213. *
  214. * @return string The results
  215. */
  216. public function getPost($name, $fallback = null)
  217. {
  218. $name = str_replace(array('[', ']'), array('.', ''), $name);
  219. $name = trim($name, '.');
  220. $oldValue = $this->app['request']->old($name, $fallback);
  221. return $this->app['request']->input($name, $oldValue, true);
  222. }
  223. ////////////////////////////////////////////////////////////////////
  224. ////////////////////////////// TOOLKIT /////////////////////////////
  225. ////////////////////////////////////////////////////////////////////
  226. /**
  227. * Set the errors to use for validations
  228. *
  229. * @param Message $validator The result from a validation
  230. *
  231. * @return void
  232. */
  233. public function withErrors($validator = null)
  234. {
  235. // Try to get the errors form the session
  236. if ($this->app['session']->has('errors')) {
  237. $this->errors = $this->app['session']->get('errors');
  238. }
  239. // If we're given a raw Validator, go fetch the errors in it
  240. if ($validator instanceof Validator) {
  241. $this->errors = $validator->getMessageBag();
  242. } else {
  243. if ($validator instanceof MessageBag) {
  244. $this->errors = $validator;
  245. }
  246. }
  247. return $this->errors;
  248. }
  249. /**
  250. * Add live validation rules
  251. *
  252. * @param array *$rules An array of Laravel rules
  253. *
  254. * @return void
  255. */
  256. public function withRules()
  257. {
  258. $rules = call_user_func_array('array_merge', func_get_args());
  259. // Parse the rules according to Laravel conventions
  260. foreach ($rules as $name => $fieldRules) {
  261. $expFieldRules = $fieldRules;
  262. if (!is_array($expFieldRules)) {
  263. $expFieldRules = explode('|', $expFieldRules);
  264. $expFieldRules = array_map('trim', $expFieldRules);
  265. }
  266. foreach ($expFieldRules as $rule) {
  267. $parameters = null;
  268. // If we have a rule with a value
  269. if (($colon = strpos($rule, ':')) !== false) {
  270. $parameters = str_getcsv(substr($rule, $colon + 1));
  271. }
  272. // Exclude unsupported rules
  273. $rule = is_numeric($colon) ? substr($rule, 0, $colon) : $rule;
  274. // Store processed rule in Former's array
  275. if (!isset($parameters)) {
  276. $parameters = array();
  277. }
  278. $this->rules[$name][$rule] = $parameters;
  279. }
  280. }
  281. }
  282. /**
  283. * Switch the framework used by Former
  284. *
  285. * @param string $framework The name of the framework to use
  286. */
  287. public function framework($framework = null)
  288. {
  289. if (!$framework) {
  290. return $this->app['former.framework']->current();
  291. }
  292. $this->setOption('framework', $framework);
  293. $framework = $this->getFrameworkInstance($framework);
  294. $this->app->bind('former.framework', function ($app) use ($framework) {
  295. return $framework;
  296. });
  297. }
  298. /**
  299. * Get a new framework instance
  300. *
  301. * @param string $framework
  302. *
  303. * @throws Exceptions\InvalidFrameworkException
  304. * @return \Former\Interfaces\FrameworkInterface
  305. */
  306. public function getFrameworkInstance($framework)
  307. {
  308. $formerClass = __NAMESPACE__.'\Framework\\'.$framework;
  309. //get interfaces of the given framework
  310. $interfaces = class_exists($framework) ? class_implements($framework) : array();
  311. if(class_exists($formerClass)) {
  312. $returnClass = $formerClass;
  313. } elseif(class_exists($framework) && isset($interfaces['Former\Interfaces\FrameworkInterface'])) {
  314. // We have some outside class, lets return it.
  315. $returnClass = $framework;
  316. } else {
  317. throw (new InvalidFrameworkException())->setFramework($framework);
  318. }
  319. return new $returnClass($this->app);
  320. }
  321. /**
  322. * Get an option from the config
  323. *
  324. * @param string $option The option
  325. * @param mixed $default Optional fallback
  326. *
  327. * @return mixed
  328. */
  329. public function getOption($option, $default = null)
  330. {
  331. return $this->app['config']->get('former.'.$option, $default);
  332. }
  333. /**
  334. * Set an option on the config
  335. *
  336. * @param string $option
  337. * @param string $value
  338. */
  339. public function setOption($option, $value)
  340. {
  341. return $this->app['config']->set('former.'.$option, $value);
  342. }
  343. ////////////////////////////////////////////////////////////////////
  344. ////////////////////////////// BUILDERS ////////////////////////////
  345. ////////////////////////////////////////////////////////////////////
  346. /**
  347. * Closes a form
  348. *
  349. * @return string A form closing tag
  350. */
  351. public function close()
  352. {
  353. if ($this->app->bound('former.form')) {
  354. $closing = $this->app['former.form']->close();
  355. }
  356. // Destroy instances
  357. $instances = array('former.form', 'former.form.framework');
  358. foreach ($instances as $instance) {
  359. $this->app[$instance] = null;
  360. unset($this->app[$instance]);
  361. }
  362. // Reset populator
  363. $this->app['former.populator']->reset();
  364. // Reset all values
  365. $this->errors = null;
  366. $this->rules = array();
  367. return isset($closing) ? $closing : null;
  368. }
  369. ////////////////////////////////////////////////////////////////////
  370. ////////////////////////////// HELPERS /////////////////////////////
  371. ////////////////////////////////////////////////////////////////////
  372. /**
  373. * Get the errors for the current field
  374. *
  375. * @param string $name A field name
  376. *
  377. * @return string An error message
  378. */
  379. public function getErrors($name = null)
  380. {
  381. // Get name and translate array notation
  382. if (!$name and $this->app['former.field']) {
  383. $name = $this->app['former.field']->getName();
  384. // Always return empty string for anonymous fields (i.e. fields with no name/id)
  385. if (!$name) {
  386. return '';
  387. }
  388. }
  389. if ($this->errors and $name) {
  390. $name = str_replace(array('[', ']'), array('.', ''), $name);
  391. $name = trim($name, '.');
  392. return $this->errors->first($name);
  393. }
  394. return $this->errors;
  395. }
  396. /**
  397. * Get a rule from the Rules array
  398. *
  399. * @param string $name The field to fetch
  400. *
  401. * @return array An array of rules
  402. */
  403. public function getRules($name)
  404. {
  405. // Check the rules for the name as given
  406. $ruleset = array_get($this->rules, $name);
  407. // If no rules found, convert to dot notation and try again
  408. if (is_null($ruleset)) {
  409. $name = str_replace(array('[', ']'), array('.', ''), $name);
  410. $name = trim($name, '.');
  411. $ruleset = array_get($this->rules, $name);
  412. }
  413. return $ruleset;
  414. }
  415. }