This commit is contained in:
2026-05-01 23:40:14 +08:00
commit b8f599a617
3867 changed files with 478663 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace Illuminate\Http\Concerns;
use Illuminate\Support\Collection;
trait CanBePrecognitive
{
/**
* Filter the given array of rules into an array of rules that are included in precognitive headers.
*
* @param array $rules
* @return array
*/
public function filterPrecognitiveRules($rules)
{
if (! $this->headers->has('Precognition-Validate-Only')) {
return $rules;
}
$validateOnly = explode(',', $this->header('Precognition-Validate-Only'));
return (new Collection($rules))
->filter(fn ($rule, $attribute) => $this->shouldValidatePrecognitiveAttribute($attribute, $validateOnly))
->all();
}
/**
* Determine if the given attribute should be validated.
*
* @param string $attribute
* @param array $validateOnly
* @return bool
*/
protected function shouldValidatePrecognitiveAttribute($attribute, $validateOnly)
{
foreach ($validateOnly as $pattern) {
$regex = '/^'.str_replace('\*', '[^.]+', preg_quote($pattern, '/')).'$/';
if (preg_match($regex, $attribute)) {
return true;
}
}
return false;
}
/**
* Determine if the request is attempting to be precognitive.
*
* @return bool
*/
public function isAttemptingPrecognition()
{
return $this->header('Precognition') === 'true';
}
/**
* Determine if the request is precognitive.
*
* @return bool
*/
public function isPrecognitive()
{
return $this->attributes->get('precognitive', false);
}
}
@@ -0,0 +1,209 @@
<?php
namespace Illuminate\Http\Concerns;
use Illuminate\Support\Str;
trait InteractsWithContentTypes
{
/**
* Determine if the request is sending JSON.
*
* @return bool
*/
public function isJson()
{
return Str::contains($this->header('CONTENT_TYPE') ?? '', ['/json', '+json']);
}
/**
* Determine if the current request probably expects a JSON response.
*
* @return bool
*/
public function expectsJson()
{
return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
}
/**
* Determine if the current request is asking for JSON.
*
* @return bool
*/
public function wantsJson()
{
$acceptable = $this->getAcceptableContentTypes();
return isset($acceptable[0]) && Str::contains(strtolower($acceptable[0]), ['/json', '+json']);
}
/**
* Determine if the current request is asking for Markdown.
*
* @return bool
*/
public function wantsMarkdown()
{
$acceptable = $this->getAcceptableContentTypes();
return isset($acceptable[0]) && str_starts_with(strtolower($acceptable[0]), 'text/markdown');
}
/**
* Determines whether the current requests accepts a given content type.
*
* @param string|array $contentTypes
* @return bool
*/
public function accepts($contentTypes)
{
$accepts = $this->getAcceptableContentTypes();
if (count($accepts) === 0) {
return true;
}
$types = (array) $contentTypes;
foreach ($accepts as $accept) {
if ($accept && $pos = strpos($accept, ';')) {
$accept = trim(substr($accept, 0, $pos));
}
if ($accept === '*/*' || $accept === '*') {
return true;
}
foreach ($types as $type) {
$accept = strtolower($accept);
$type = strtolower($type);
if (self::matchesType($accept, $type) || $accept === strtok($type, '/').'/*') {
return true;
}
}
}
return false;
}
/**
* Return the most suitable content type from the given array based on content negotiation.
*
* @param string|array $contentTypes
* @return string|null
*/
public function prefers($contentTypes)
{
$accepts = $this->getAcceptableContentTypes();
$contentTypes = (array) $contentTypes;
foreach ($accepts as $accept) {
if ($accept && $pos = strpos($accept, ';')) {
$accept = trim(substr($accept, 0, $pos));
}
if (in_array($accept, ['*/*', '*'])) {
return $contentTypes[0];
}
foreach ($contentTypes as $contentType) {
$type = $contentType;
if (! is_null($mimeType = $this->getMimeType($contentType))) {
$type = $mimeType;
}
$accept = strtolower($accept);
$type = strtolower($type);
if (self::matchesType($type, $accept) || $accept === strtok($type, '/').'/*') {
return $contentType;
}
}
}
}
/**
* Determine if the current request accepts any content type.
*
* @return bool
*/
public function acceptsAnyContentType()
{
$acceptable = $this->getAcceptableContentTypes();
return count($acceptable) === 0 || (
isset($acceptable[0]) && ($acceptable[0] === '*/*' || $acceptable[0] === '*')
);
}
/**
* Determines whether a request accepts JSON.
*
* @return bool
*/
public function acceptsJson()
{
return $this->accepts('application/json');
}
/**
* Determines whether a request accepts Markdown.
*
* @return bool
*/
public function acceptsMarkdown()
{
return $this->accepts('text/markdown');
}
/**
* Determines whether a request accepts HTML.
*
* @return bool
*/
public function acceptsHtml()
{
return $this->accepts('text/html');
}
/**
* Determine if the given content types match.
*
* @param string $actual
* @param string $type
* @return bool
*/
public static function matchesType($actual, $type)
{
if ($actual === $type) {
return true;
}
$split = explode('/', $actual);
return isset($split[1]) && preg_match('#'.preg_quote($split[0], '#').'/.+\+'.preg_quote($split[1], '#').'#', $type);
}
/**
* Get the data format expected in the response.
*
* @param string $default
* @return string
*/
public function format($default = 'html')
{
foreach ($this->getAcceptableContentTypes() as $type) {
if ($format = $this->getFormat($type)) {
return $format;
}
}
return $default;
}
}
@@ -0,0 +1,68 @@
<?php
namespace Illuminate\Http\Concerns;
use Illuminate\Database\Eloquent\Model;
trait InteractsWithFlashData
{
/**
* Retrieve an old input item.
*
* @param string|null $key
* @param \Illuminate\Database\Eloquent\Model|string|array|null $default
* @return string|array|null
*/
public function old($key = null, $default = null)
{
$default = $default instanceof Model ? $default->getAttribute($key) : $default;
return $this->hasSession() ? $this->session()->getOldInput($key, $default) : $default;
}
/**
* Flash the input for the current request to the session.
*
* @return void
*/
public function flash()
{
$this->session()->flashInput($this->input());
}
/**
* Flash only some of the input to the session.
*
* @param mixed $keys
* @return void
*/
public function flashOnly($keys)
{
$this->session()->flashInput(
$this->only(is_array($keys) ? $keys : func_get_args())
);
}
/**
* Flash only some of the input to the session.
*
* @param mixed $keys
* @return void
*/
public function flashExcept($keys)
{
$this->session()->flashInput(
$this->except(is_array($keys) ? $keys : func_get_args())
);
}
/**
* Flush all of the old input from the session.
*
* @return void
*/
public function flush()
{
$this->session()->flashInput([]);
}
}
+300
View File
@@ -0,0 +1,300 @@
<?php
namespace Illuminate\Http\Concerns;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Fluent;
use Illuminate\Support\Traits\Dumpable;
use Illuminate\Support\Traits\InteractsWithData;
use SplFileInfo;
use Symfony\Component\HttpFoundation\InputBag;
trait InteractsWithInput
{
use Dumpable, InteractsWithData;
/**
* Retrieve a server variable from the request.
*
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
public function server($key = null, $default = null)
{
return $this->retrieveItem('server', $key, $default);
}
/**
* Determine if a header is set on the request.
*
* @param string $key
* @return bool
*/
public function hasHeader($key)
{
return ! is_null($this->header($key));
}
/**
* Retrieve a header from the request.
*
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
public function header($key = null, $default = null)
{
return $this->retrieveItem('headers', $key, $default);
}
/**
* Get the bearer token from the request headers.
*
* @return string|null
*/
public function bearerToken()
{
$header = $this->header('Authorization', '');
$position = strripos($header, 'Bearer ');
if ($position !== false) {
$header = substr($header, $position + 7);
return str_contains($header, ',') ? strstr($header, ',', true) : $header;
}
}
/**
* Get the keys for all of the input and files.
*
* @return array
*/
public function keys()
{
return array_merge(array_keys($this->input()), $this->files->keys());
}
/**
* Get all of the input and files for the request.
*
* @param mixed $keys
* @return array
*/
public function all($keys = null)
{
$input = array_replace_recursive($this->input(), $this->allFiles());
if (! $keys) {
return $input;
}
$results = [];
foreach (is_array($keys) ? $keys : func_get_args() as $key) {
Arr::set($results, $key, Arr::get($input, $key));
}
return $results;
}
/**
* Retrieve an input item from the request.
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public function input($key = null, $default = null)
{
return data_get(
$this->getInputSource()->all() + $this->query->all(), $key, $default
);
}
/**
* Retrieve input from the request as a Fluent object instance.
*
* @param array|string|null $key
* @param array $default
* @return \Illuminate\Support\Fluent
*/
public function fluent($key = null, array $default = [])
{
$value = is_array($key) ? $this->only($key) : $this->input($key);
return new Fluent($value ?? $default);
}
/**
* Retrieve a query string item from the request.
*
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
public function query($key = null, $default = null)
{
return $this->retrieveItem('query', $key, $default);
}
/**
* Retrieve a request payload item from the request.
*
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
public function post($key = null, $default = null)
{
return $this->retrieveItem('request', $key, $default);
}
/**
* Determine if a cookie is set on the request.
*
* @param string $key
* @return bool
*/
public function hasCookie($key)
{
return ! is_null($this->cookie($key));
}
/**
* Retrieve a cookie from the request.
*
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
public function cookie($key = null, $default = null)
{
return $this->retrieveItem('cookies', $key, $default);
}
/**
* Get an array of all of the files on the request.
*
* @return array<string, \Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]>
*/
public function allFiles()
{
$files = $this->files->all();
return $this->convertedFiles ??= $this->convertUploadedFiles($files);
}
/**
* Convert the given array of Symfony UploadedFiles to custom Laravel UploadedFiles.
*
* @param array<string, \Symfony\Component\HttpFoundation\File\UploadedFile|\Symfony\Component\HttpFoundation\File\UploadedFile[]> $files
* @return array<string, \Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]>
*/
protected function convertUploadedFiles(array $files)
{
return array_map(function ($file) {
if (is_null($file) || (is_array($file) && empty(array_filter($file)))) {
return $file;
}
return is_array($file)
? $this->convertUploadedFiles($file)
: UploadedFile::createFromBase($file);
}, $files);
}
/**
* Determine if the uploaded data contains a file.
*
* @param string $key
* @return bool
*/
public function hasFile($key)
{
if (! is_array($files = $this->file($key))) {
$files = [$files];
}
foreach ($files as $file) {
if ($this->isValidFile($file)) {
return true;
}
}
return false;
}
/**
* Check that the given file is a valid file instance.
*
* @param mixed $file
* @return bool
*/
protected function isValidFile($file)
{
return $file instanceof SplFileInfo && $file->getPath() !== '';
}
/**
* Retrieve a file from the request.
*
* @param string|null $key
* @param mixed $default
* @return ($key is null ? array<string, \Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]> : \Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]|null)
*/
public function file($key = null, $default = null)
{
return data_get($this->allFiles(), $key, $default);
}
/**
* Retrieve data from the instance.
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
protected function data($key = null, $default = null)
{
return $this->input($key, $default);
}
/**
* Retrieve a parameter item from a given source.
*
* @param string $source
* @param string|null $key
* @param string|array|null $default
* @return string|array|null
*/
protected function retrieveItem($source, $key, $default)
{
if (is_null($key)) {
return $this->$source->all();
}
if ($this->$source instanceof InputBag) {
return $this->$source->all()[$key] ?? $default;
}
return $this->$source->get($key, $default);
}
/**
* Dump the items.
*
* @param mixed $keys
* @return $this
*/
public function dump($keys = [])
{
$keys = is_array($keys) ? $keys : func_get_args();
dump($keys !== [] ? $this->only($keys) : $this->all());
return $this;
}
}