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