ValidatedInput.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. <?php
  2. namespace Illuminate\Support;
  3. use ArrayIterator;
  4. use Illuminate\Contracts\Support\ValidatedData;
  5. use Illuminate\Support\Facades\Date;
  6. use stdClass;
  7. use Symfony\Component\VarDumper\VarDumper;
  8. use Traversable;
  9. class ValidatedInput implements ValidatedData
  10. {
  11. /**
  12. * The underlying input.
  13. *
  14. * @var array
  15. */
  16. protected $input;
  17. /**
  18. * Create a new validated input container.
  19. *
  20. * @param array $input
  21. * @return void
  22. */
  23. public function __construct(array $input)
  24. {
  25. $this->input = $input;
  26. }
  27. /**
  28. * Determine if the validated input has one or more keys.
  29. *
  30. * @param string|array $key
  31. * @return bool
  32. */
  33. public function exists($key)
  34. {
  35. return $this->has($key);
  36. }
  37. /**
  38. * Determine if the validated input has one or more keys.
  39. *
  40. * @param mixed $keys
  41. * @return bool
  42. */
  43. public function has($keys)
  44. {
  45. $keys = is_array($keys) ? $keys : func_get_args();
  46. foreach ($keys as $key) {
  47. if (! Arr::has($this->all(), $key)) {
  48. return false;
  49. }
  50. }
  51. return true;
  52. }
  53. /**
  54. * Determine if the validated input contains any of the given keys.
  55. *
  56. * @param string|array $keys
  57. * @return bool
  58. */
  59. public function hasAny($keys)
  60. {
  61. $keys = is_array($keys) ? $keys : func_get_args();
  62. $input = $this->all();
  63. return Arr::hasAny($input, $keys);
  64. }
  65. /**
  66. * Apply the callback if the validated input contains the given input item key.
  67. *
  68. * @param string $key
  69. * @param callable $callback
  70. * @param callable|null $default
  71. * @return $this|mixed
  72. */
  73. public function whenHas($key, callable $callback, callable $default = null)
  74. {
  75. if ($this->has($key)) {
  76. return $callback(data_get($this->all(), $key)) ?: $this;
  77. }
  78. if ($default) {
  79. return $default();
  80. }
  81. return $this;
  82. }
  83. /**
  84. * Determine if the validated input contains a non-empty value for an input item.
  85. *
  86. * @param string|array $key
  87. * @return bool
  88. */
  89. public function filled($key)
  90. {
  91. $keys = is_array($key) ? $key : func_get_args();
  92. foreach ($keys as $value) {
  93. if ($this->isEmptyString($value)) {
  94. return false;
  95. }
  96. }
  97. return true;
  98. }
  99. /**
  100. * Determine if the validated input contains an empty value for an input item.
  101. *
  102. * @param string|array $key
  103. * @return bool
  104. */
  105. public function isNotFilled($key)
  106. {
  107. $keys = is_array($key) ? $key : func_get_args();
  108. foreach ($keys as $value) {
  109. if (! $this->isEmptyString($value)) {
  110. return false;
  111. }
  112. }
  113. return true;
  114. }
  115. /**
  116. * Determine if the validated input contains a non-empty value for any of the given input items.
  117. *
  118. * @param string|array $keys
  119. * @return bool
  120. */
  121. public function anyFilled($keys)
  122. {
  123. $keys = is_array($keys) ? $keys : func_get_args();
  124. foreach ($keys as $key) {
  125. if ($this->filled($key)) {
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. /**
  132. * Apply the callback if the validated input contains a non-empty value for the given input item key.
  133. *
  134. * @param string $key
  135. * @param callable $callback
  136. * @param callable|null $default
  137. * @return $this|mixed
  138. */
  139. public function whenFilled($key, callable $callback, callable $default = null)
  140. {
  141. if ($this->filled($key)) {
  142. return $callback(data_get($this->all(), $key)) ?: $this;
  143. }
  144. if ($default) {
  145. return $default();
  146. }
  147. return $this;
  148. }
  149. /**
  150. * Determine if the given input item is an empty string.
  151. *
  152. * @param string $key
  153. * @return bool
  154. */
  155. protected function isEmptyString($key)
  156. {
  157. $value = $this->input($key);
  158. return ! is_bool($value) && ! is_array($value) && trim((string) $value) === '';
  159. }
  160. /**
  161. * Determine if the validated input is missing one or more keys.
  162. *
  163. * @param mixed $keys
  164. * @return bool
  165. */
  166. public function missing($keys)
  167. {
  168. return ! $this->has($keys);
  169. }
  170. /**
  171. * Apply the callback if the validated input is missing the given input item key.
  172. *
  173. * @param string $key
  174. * @param callable $callback
  175. * @param callable|null $default
  176. * @return $this|mixed
  177. */
  178. public function whenMissing($key, callable $callback, callable $default = null)
  179. {
  180. if ($this->missing($key)) {
  181. return $callback(data_get($this->all(), $key)) ?: $this;
  182. }
  183. if ($default) {
  184. return $default();
  185. }
  186. return $this;
  187. }
  188. /**
  189. * Get the keys for all of the input.
  190. *
  191. * @return array
  192. */
  193. public function keys()
  194. {
  195. return array_keys($this->input());
  196. }
  197. /**
  198. * Retrieve an input item from the validated input.
  199. *
  200. * @param string|null $key
  201. * @param mixed $default
  202. * @return mixed
  203. */
  204. public function input($key = null, $default = null)
  205. {
  206. return data_get(
  207. $this->all(), $key, $default
  208. );
  209. }
  210. /**
  211. * Retrieve input from the validated input as a Stringable instance.
  212. *
  213. * @param string $key
  214. * @param mixed $default
  215. * @return \Illuminate\Support\Stringable
  216. */
  217. public function str($key, $default = null)
  218. {
  219. return $this->string($key, $default);
  220. }
  221. /**
  222. * Retrieve input from the validated input as a Stringable instance.
  223. *
  224. * @param string $key
  225. * @param mixed $default
  226. * @return \Illuminate\Support\Stringable
  227. */
  228. public function string($key, $default = null)
  229. {
  230. return str($this->input($key, $default));
  231. }
  232. /**
  233. * Retrieve input as a boolean value.
  234. *
  235. * Returns true when value is "1", "true", "on", and "yes". Otherwise, returns false.
  236. *
  237. * @param string|null $key
  238. * @param bool $default
  239. * @return bool
  240. */
  241. public function boolean($key = null, $default = false)
  242. {
  243. return filter_var($this->input($key, $default), FILTER_VALIDATE_BOOLEAN);
  244. }
  245. /**
  246. * Retrieve input as an integer value.
  247. *
  248. * @param string $key
  249. * @param int $default
  250. * @return int
  251. */
  252. public function integer($key, $default = 0)
  253. {
  254. return intval($this->input($key, $default));
  255. }
  256. /**
  257. * Retrieve input as a float value.
  258. *
  259. * @param string $key
  260. * @param float $default
  261. * @return float
  262. */
  263. public function float($key, $default = 0.0)
  264. {
  265. return floatval($this->input($key, $default));
  266. }
  267. /**
  268. * Retrieve input from the validated input as a Carbon instance.
  269. *
  270. * @param string $key
  271. * @param string|null $format
  272. * @param string|null $tz
  273. * @return \Illuminate\Support\Carbon|null
  274. *
  275. * @throws \Carbon\Exceptions\InvalidFormatException
  276. */
  277. public function date($key, $format = null, $tz = null)
  278. {
  279. if ($this->isNotFilled($key)) {
  280. return null;
  281. }
  282. if (is_null($format)) {
  283. return Date::parse($this->input($key), $tz);
  284. }
  285. return Date::createFromFormat($format, $this->input($key), $tz);
  286. }
  287. /**
  288. * Retrieve input from the validated input as an enum.
  289. *
  290. * @template TEnum
  291. *
  292. * @param string $key
  293. * @param class-string<TEnum> $enumClass
  294. * @return TEnum|null
  295. */
  296. public function enum($key, $enumClass)
  297. {
  298. if ($this->isNotFilled($key) ||
  299. ! enum_exists($enumClass) ||
  300. ! method_exists($enumClass, 'tryFrom')) {
  301. return null;
  302. }
  303. return $enumClass::tryFrom($this->input($key));
  304. }
  305. /**
  306. * Get a subset containing the provided keys with values from the input data.
  307. *
  308. * @param mixed $keys
  309. * @return array
  310. */
  311. public function only($keys)
  312. {
  313. $results = [];
  314. $input = $this->all();
  315. $placeholder = new stdClass;
  316. foreach (is_array($keys) ? $keys : func_get_args() as $key) {
  317. $value = data_get($input, $key, $placeholder);
  318. if ($value !== $placeholder) {
  319. Arr::set($results, $key, $value);
  320. }
  321. }
  322. return $results;
  323. }
  324. /**
  325. * Get all of the input except for a specified array of items.
  326. *
  327. * @param mixed $keys
  328. * @return array
  329. */
  330. public function except($keys)
  331. {
  332. $keys = is_array($keys) ? $keys : func_get_args();
  333. $results = $this->all();
  334. Arr::forget($results, $keys);
  335. return $results;
  336. }
  337. /**
  338. * Merge the validated input with the given array of additional data.
  339. *
  340. * @param array $items
  341. * @return static
  342. */
  343. public function merge(array $items)
  344. {
  345. return new static(array_merge($this->all(), $items));
  346. }
  347. /**
  348. * Get the input as a collection.
  349. *
  350. * @param array|string|null $key
  351. * @return \Illuminate\Support\Collection
  352. */
  353. public function collect($key = null)
  354. {
  355. return collect(is_array($key) ? $this->only($key) : $this->input($key));
  356. }
  357. /**
  358. * Get the raw, underlying input array.
  359. *
  360. * @return array
  361. */
  362. public function all()
  363. {
  364. return $this->input;
  365. }
  366. /**
  367. * Dump the validated input items and end the script.
  368. *
  369. * @param mixed ...$keys
  370. * @return never
  371. */
  372. public function dd(...$keys)
  373. {
  374. $this->dump(...$keys);
  375. exit(1);
  376. }
  377. /**
  378. * Dump the items.
  379. *
  380. * @param mixed $keys
  381. * @return $this
  382. */
  383. public function dump($keys = [])
  384. {
  385. $keys = is_array($keys) ? $keys : func_get_args();
  386. VarDumper::dump(count($keys) > 0 ? $this->only($keys) : $this->all());
  387. return $this;
  388. }
  389. /**
  390. * Get the instance as an array.
  391. *
  392. * @return array
  393. */
  394. public function toArray()
  395. {
  396. return $this->all();
  397. }
  398. /**
  399. * Dynamically access input data.
  400. *
  401. * @param string $name
  402. * @return mixed
  403. */
  404. public function __get($name)
  405. {
  406. return $this->input($name);
  407. }
  408. /**
  409. * Dynamically set input data.
  410. *
  411. * @param string $name
  412. * @param mixed $value
  413. * @return mixed
  414. */
  415. public function __set($name, $value)
  416. {
  417. $this->input[$name] = $value;
  418. }
  419. /**
  420. * Determine if an input item is set.
  421. *
  422. * @return bool
  423. */
  424. public function __isset($name)
  425. {
  426. return $this->exists($name);
  427. }
  428. /**
  429. * Remove an input item.
  430. *
  431. * @param string $name
  432. * @return void
  433. */
  434. public function __unset($name)
  435. {
  436. unset($this->input[$name]);
  437. }
  438. /**
  439. * Determine if an item exists at an offset.
  440. *
  441. * @param mixed $key
  442. * @return bool
  443. */
  444. public function offsetExists($key): bool
  445. {
  446. return $this->exists($key);
  447. }
  448. /**
  449. * Get an item at a given offset.
  450. *
  451. * @param mixed $key
  452. * @return mixed
  453. */
  454. public function offsetGet($key): mixed
  455. {
  456. return $this->input($key);
  457. }
  458. /**
  459. * Set the item at a given offset.
  460. *
  461. * @param mixed $key
  462. * @param mixed $value
  463. * @return void
  464. */
  465. public function offsetSet($key, $value): void
  466. {
  467. if (is_null($key)) {
  468. $this->input[] = $value;
  469. } else {
  470. $this->input[$key] = $value;
  471. }
  472. }
  473. /**
  474. * Unset the item at a given offset.
  475. *
  476. * @param string $key
  477. * @return void
  478. */
  479. public function offsetUnset($key): void
  480. {
  481. unset($this->input[$key]);
  482. }
  483. /**
  484. * Get an iterator for the input.
  485. *
  486. * @return \ArrayIterator
  487. */
  488. public function getIterator(): Traversable
  489. {
  490. return new ArrayIterator($this->input);
  491. }
  492. }