dependencies-upgrade

This commit is contained in:
RafficMohammed
2023-01-08 02:20:59 +05:30
parent 7870479b18
commit 49021a4497
1711 changed files with 74994 additions and 70803 deletions

View File

@@ -2,13 +2,20 @@
namespace Illuminate\View\Compilers;
use Illuminate\Container\Container;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ReflectsClosures;
use Illuminate\View\Component;
use InvalidArgumentException;
class BladeCompiler extends Compiler implements CompilerInterface
{
use Concerns\CompilesAuthorizations,
Concerns\CompilesClasses,
Concerns\CompilesComments,
Concerns\CompilesComponents,
Concerns\CompilesConditionals,
@@ -18,11 +25,13 @@ class BladeCompiler extends Compiler implements CompilerInterface
Concerns\CompilesIncludes,
Concerns\CompilesInjections,
Concerns\CompilesJson,
Concerns\CompilesJs,
Concerns\CompilesLayouts,
Concerns\CompilesLoops,
Concerns\CompilesRawPhp,
Concerns\CompilesStacks,
Concerns\CompilesTranslations;
Concerns\CompilesTranslations,
ReflectsClosures;
/**
* All of the registered extensions.
@@ -62,7 +71,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
/**
* All of the available compiler functions.
*
* @var array
* @var string[]
*/
protected $compilers = [
// 'Comments',
@@ -74,21 +83,21 @@ class BladeCompiler extends Compiler implements CompilerInterface
/**
* Array of opening and closing tags for raw echos.
*
* @var array
* @var string[]
*/
protected $rawTags = ['{!!', '!!}'];
/**
* Array of opening and closing tags for regular echos.
*
* @var array
* @var string[]
*/
protected $contentTags = ['{{', '}}'];
/**
* Array of opening and closing tags for escaped echos.
*
* @var array
* @var string[]
*/
protected $escapedTags = ['{{{', '}}}'];
@@ -100,14 +109,14 @@ class BladeCompiler extends Compiler implements CompilerInterface
protected $echoFormat = 'e(%s)';
/**
* Array of footer lines to be added to template.
* Array of footer lines to be added to the template.
*
* @var array
*/
protected $footer = [];
/**
* Array to temporary store the raw blocks found in the template.
* Array to temporarily store the raw blocks found in the template.
*
* @var array
*/
@@ -120,6 +129,13 @@ class BladeCompiler extends Compiler implements CompilerInterface
*/
protected $classComponentAliases = [];
/**
* The array of class component namespaces to autoload from.
*
* @var array
*/
protected $classComponentNamespaces = [];
/**
* Indicates if component tags should be compiled.
*
@@ -146,9 +162,11 @@ class BladeCompiler extends Compiler implements CompilerInterface
$contents = $this->appendFilePath($contents);
}
$this->files->put(
$this->getCompiledPath($this->getPath()), $contents
$this->ensureCompiledDirectoryExists(
$compiledPath = $this->getCompiledPath($this->getPath())
);
$this->files->put($compiledPath, $contents);
}
}
@@ -244,7 +262,74 @@ class BladeCompiler extends Compiler implements CompilerInterface
$result = $this->addFooters($result);
}
return $result;
if (! empty($this->echoHandlers)) {
$result = $this->addBladeCompilerVariable($result);
}
return str_replace(
['##BEGIN-COMPONENT-CLASS##', '##END-COMPONENT-CLASS##'],
'',
$result);
}
/**
* Evaluate and render a Blade string to HTML.
*
* @param string $string
* @param array $data
* @param bool $deleteCachedView
* @return string
*/
public static function render($string, $data = [], $deleteCachedView = false)
{
$component = new class($string) extends Component
{
protected $template;
public function __construct($template)
{
$this->template = $template;
}
public function render()
{
return $this->template;
}
};
$view = Container::getInstance()
->make(ViewFactory::class)
->make($component->resolveView(), $data);
return tap($view->render(), function () use ($view, $deleteCachedView) {
if ($deleteCachedView) {
unlink($view->getPath());
}
});
}
/**
* Render a component instance to HTML.
*
* @param \Illuminate\View\Component $component
* @return string
*/
public static function renderComponent(Component $component)
{
$data = $component->data();
$view = value($component->resolveView(), $data);
if ($view instanceof View) {
return $view->with($data)->render();
} elseif ($view instanceof Htmlable) {
return $view->toHtml();
} else {
return Container::getInstance()
->make(ViewFactory::class)
->make($view, $data)
->render();
}
}
/**
@@ -318,7 +403,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
}
return (new ComponentTagCompiler(
$this->classComponentAliases, $this
$this->classComponentAliases, $this->classComponentNamespaces, $this
))->compile($value);
}
@@ -340,7 +425,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
}
/**
* Get a placeholder to temporary mark the position of raw blocks.
* Get a placeholder to temporarily mark the position of raw blocks.
*
* @param int|string $replace
* @return string
@@ -439,6 +524,8 @@ class BladeCompiler extends Compiler implements CompilerInterface
*/
protected function callCustomDirective($name, $value)
{
$value = $value ?? '';
if (Str::startsWith($value, '(') && Str::endsWith($value, ')')) {
$value = Str::substr($value, 1, -1);
}
@@ -568,9 +655,9 @@ class BladeCompiler extends Compiler implements CompilerInterface
{
foreach ($components as $key => $value) {
if (is_numeric($key)) {
static::component($value, null, $prefix);
$this->component($value, null, $prefix);
} else {
static::component($key, $value, $prefix);
$this->component($key, $value, $prefix);
}
}
}
@@ -585,6 +672,28 @@ class BladeCompiler extends Compiler implements CompilerInterface
return $this->classComponentAliases;
}
/**
* Register a class-based component namespace.
*
* @param string $namespace
* @param string $prefix
* @return void
*/
public function componentNamespace($namespace, $prefix)
{
$this->classComponentNamespaces[$prefix] = $namespace;
}
/**
* Get the registered class component namespaces.
*
* @return array
*/
public function getClassComponentNamespaces()
{
return $this->classComponentNamespaces;
}
/**
* Register a component alias directive.
*
@@ -616,7 +725,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
*/
public function include($path, $alias = null)
{
return $this->aliasInclude($path, $alias);
$this->aliasInclude($path, $alias);
}
/**

View File

@@ -71,4 +71,17 @@ abstract class Compiler
return $this->files->lastModified($path) >=
$this->files->lastModified($compiled);
}
/**
* Create the compiled file directory if necessary.
*
* @param string $path
* @return void
*/
protected function ensureCompiledDirectoryExists($path)
{
if (! $this->files->exists(dirname($path))) {
$this->files->makeDirectory(dirname($path), 0777, true, true);
}
}
}

View File

@@ -8,6 +8,7 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use Illuminate\View\AnonymousComponent;
use Illuminate\View\DynamicComponent;
use Illuminate\View\ViewFinderInterface;
use InvalidArgumentException;
use ReflectionClass;
@@ -32,6 +33,13 @@ class ComponentTagCompiler
*/
protected $aliases = [];
/**
* The component class namespaces.
*
* @var array
*/
protected $namespaces = [];
/**
* The "bind:" attributes that have been compiled for the current component.
*
@@ -40,15 +48,17 @@ class ComponentTagCompiler
protected $boundAttributes = [];
/**
* Create new component tag compiler.
* Create a new component tag compiler.
*
* @param array $aliases
* @param \Illuminate\View\Compilers\BladeCompiler|null
* @param array $namespaces
* @param \Illuminate\View\Compilers\BladeCompiler|null $blade
* @return void
*/
public function __construct(array $aliases = [], ?BladeCompiler $blade = null)
public function __construct(array $aliases = [], array $namespaces = [], ?BladeCompiler $blade = null)
{
$this->aliases = $aliases;
$this->namespaces = $namespaces;
$this->blade = $blade ?: new BladeCompiler(new Filesystem, sys_get_temp_dir());
}
@@ -100,18 +110,26 @@ class ComponentTagCompiler
(?<attributes>
(?:
\s+
[\w\-:.@]+
(
=
(?:
(?:
\\\"[^\\\"]*\\\"
|
\'[^\']*\'
|
[^\'\\\"=<>]+
\{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\}
)
|
(?:
[\w\-:.@]+
(
=
(?:
\\\"[^\\\"]*\\\"
|
\'[^\']*\'
|
[^\'\\\"=<>]+
)
)?
)
)
?)*
)*
\s*
)
(?<![\/=\-])
@@ -145,17 +163,25 @@ class ComponentTagCompiler
(?<attributes>
(?:
\s+
[\w\-:.@]+
(
=
(?:
(?:
\\\"[^\\\"]*\\\"
|
\'[^\']*\'
|
[^\'\\\"=<>]+
\{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\}
)
)?
|
(?:
[\w\-:.@]+
(
=
(?:
\\\"[^\\\"]*\\\"
|
\'[^\']*\'
|
[^\'\\\"=<>]+
)
)?
)
)
)*
\s*
)
@@ -167,7 +193,7 @@ class ComponentTagCompiler
$attributes = $this->getAttributesFromAttributeString($matches['attributes']);
return $this->componentString($matches[1], $attributes)."\n@endcomponentClass ";
return $this->componentString($matches[1], $attributes)."\n@endComponentClass##END-COMPONENT-CLASS##";
}, $value);
}
@@ -204,8 +230,8 @@ class ComponentTagCompiler
$parameters = $data->all();
}
return " @component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).'])
<?php $component->withAttributes(['.$this->attributesToString($attributes->all()).']); ?>';
return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).'])
<?php $component->withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>';
}
/**
@@ -216,7 +242,7 @@ class ComponentTagCompiler
*
* @throws \InvalidArgumentException
*/
protected function componentClass(string $component)
public function componentClass(string $component)
{
$viewFactory = Container::getInstance()->make(Factory::class);
@@ -234,6 +260,10 @@ class ComponentTagCompiler
);
}
if ($class = $this->findClassByComponent($component)) {
return $class;
}
if (class_exists($class = $this->guessClassName($component))) {
return $class;
}
@@ -242,11 +272,36 @@ class ComponentTagCompiler
return $view;
}
if ($viewFactory->exists($view = $this->guessViewName($component).'.index')) {
return $view;
}
throw new InvalidArgumentException(
"Unable to locate a class or view for component [{$component}]."
);
}
/**
* Find the class for the given component using the registered namespaces.
*
* @param string $component
* @return string|null
*/
public function findClassByComponent(string $component)
{
$segments = explode('::', $component);
$prefix = $segments[0];
if (! isset($this->namespaces[$prefix]) || ! isset($segments[1])) {
return;
}
if (class_exists($class = $this->namespaces[$prefix].'\\'.$this->formatClassName($segments[1]))) {
return $class;
}
}
/**
* Guess the class name for the given component.
*
@@ -259,11 +314,24 @@ class ComponentTagCompiler
->make(Application::class)
->getNamespace();
$class = $this->formatClassName($component);
return $namespace.'View\\Components\\'.$class;
}
/**
* Format the class name for the given component.
*
* @param string $component
* @return string
*/
public function formatClassName(string $component)
{
$componentPieces = array_map(function ($componentPiece) {
return ucfirst(Str::camel($componentPiece));
}, explode('.', $component));
return $namespace.'View\\Components\\'.implode('\\', $componentPieces);
return implode('\\', $componentPieces);
}
/**
@@ -292,7 +360,7 @@ class ComponentTagCompiler
* @param array $attributes
* @return array
*/
protected function partitionDataAndAttributes($class, array $attributes)
public function partitionDataAndAttributes($class, array $attributes)
{
// If the class doesn't exists, we'll assume it's a class-less component and
// return all of the attributes as both data and attributes since we have
@@ -320,7 +388,7 @@ class ComponentTagCompiler
*/
protected function compileClosingTags(string $value)
{
return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endcomponentClass ', $value);
return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endComponentClass##END-COMPONENT-CLASS##', $value);
}
/**
@@ -331,14 +399,53 @@ class ComponentTagCompiler
*/
public function compileSlots(string $value)
{
$value = preg_replace_callback('/<\s*x[\-\:]slot\s+(:?)name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+))\s*>/', function ($matches) {
$pattern = "/
<
\s*
x[\-\:]slot
\s+
(:?)name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+))
(?<attributes>
(?:
\s+
(?:
(?:
\{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\}
)
|
(?:
[\w\-:.@]+
(
=
(?:
\\\"[^\\\"]*\\\"
|
\'[^\']*\'
|
[^\'\\\"=<>]+
)
)?
)
)
)*
\s*
)
(?<![\/=\-])
>
/x";
$value = preg_replace_callback($pattern, function ($matches) {
$name = $this->stripQuotes($matches['name']);
if ($matches[1] !== ':') {
$name = "'{$name}'";
}
return " @slot({$name}) ";
$this->boundAttributes = [];
$attributes = $this->getAttributesFromAttributeString($matches['attributes']);
return " @slot({$name}, null, [".$this->attributesToString($attributes).']) ';
}, $value);
return preg_replace('/<\/\s*x[\-\:]slot[^>]*>/', ' @endslot', $value);
@@ -352,6 +459,8 @@ class ComponentTagCompiler
*/
protected function getAttributesFromAttributeString(string $attributeString)
{
$attributeString = $this->parseAttributeBag($attributeString);
$attributeString = $this->parseBindAttributes($attributeString);
$pattern = '/
@@ -394,10 +503,30 @@ class ComponentTagCompiler
$value = "'".$this->compileAttributeEchos($value)."'";
}
if (Str::startsWith($attribute, '::')) {
$attribute = substr($attribute, 1);
}
return [$attribute => $value];
})->toArray();
}
/**
* Parse the attribute bag in a given attribute string into its fully-qualified syntax.
*
* @param string $attributeString
* @return string
*/
protected function parseAttributeBag(string $attributeString)
{
$pattern = "/
(?:^|\s+) # start of the string or whitespace between attributes
\{\{\s*(\\\$attributes(?:[^}]+?(?<!\s))?)\s*\}\} # exact match of attributes variable being echoed
/x";
return preg_replace($pattern, ' :attributes="$1"', $attributeString);
}
/**
* Parse the "bind" attributes in a given attribute string into their fully-qualified syntax.
*
@@ -408,7 +537,7 @@ class ComponentTagCompiler
{
$pattern = "/
(?:^|\s+) # start of the string or whitespace between attributes
: # attribute needs to start with a semicolon
:(?!:) # attribute needs to start with a single colon
([\w\-:.@]+) # match the actual attribute name
= # only match attributes that have a value
/xm";

View File

@@ -0,0 +1,19 @@
<?php
namespace Illuminate\View\Compilers\Concerns;
trait CompilesClasses
{
/**
* Compile the conditional class statement into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileClass($expression)
{
$expression = is_null($expression) ? '([])' : $expression;
return "class=\"<?php echo \Illuminate\Support\Arr::toCssClasses{$expression} ?>\"";
}
}

View File

@@ -2,7 +2,9 @@
namespace Illuminate\View\Compilers\Concerns;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Support\Str;
use Illuminate\View\ComponentAttributeBag;
trait CompilesComponents
{
@@ -76,15 +78,7 @@ trait CompilesComponents
*/
protected function compileEndComponent()
{
$hash = array_pop(static::$componentHashStack);
return implode("\n", [
'<?php if (isset($__componentOriginal'.$hash.')): ?>',
'<?php $component = $__componentOriginal'.$hash.'; ?>',
'<?php unset($__componentOriginal'.$hash.'); ?>',
'<?php endif; ?>',
'<?php echo $__env->renderComponent(); ?>',
]);
return '<?php echo $__env->renderComponent(); ?>';
}
/**
@@ -94,7 +88,13 @@ trait CompilesComponents
*/
public function compileEndComponentClass()
{
return static::compileEndComponent()."\n".implode("\n", [
$hash = array_pop(static::$componentHashStack);
return $this->compileEndComponent()."\n".implode("\n", [
'<?php endif; ?>',
'<?php if (isset($__componentOriginal'.$hash.')): ?>',
'<?php $component = $__componentOriginal'.$hash.'; ?>',
'<?php unset($__componentOriginal'.$hash.'); ?>',
'<?php endif; ?>',
]);
}
@@ -160,6 +160,20 @@ trait CompilesComponents
<?php unset(\$__defined_vars); ?>";
}
/**
* Compile the aware statement into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileAware($expression)
{
return "<?php foreach ({$expression} as \$__key => \$__value) {
\$__consumeVariable = is_string(\$__key) ? \$__key : \$__value;
\$\$__consumeVariable = is_string(\$__key) ? \$__env->getConsumableComponentData(\$__key, \$__value) : \$__env->getConsumableComponentData(\$__value);
} ?>";
}
/**
* Sanitize the given component attribute value.
*
@@ -168,8 +182,12 @@ trait CompilesComponents
*/
public static function sanitizeComponentAttribute($value)
{
if (is_object($value) && $value instanceof CanBeEscapedWhenCastToString) {
return $value->escapeWhenCastingToString();
}
return is_string($value) ||
(is_object($value) && method_exists($value, '__toString'))
(is_object($value) && ! $value instanceof ComponentAttributeBag && method_exists($value, '__toString'))
? e($value)
: $value;
}

View File

@@ -7,7 +7,7 @@ use Illuminate\Support\Str;
trait CompilesConditionals
{
/**
* Identifier for the first case in switch statement.
* Identifier for the first case in the switch statement.
*
* @var bool
*/
@@ -283,8 +283,9 @@ trait CompilesConditionals
}
/**
* Compile an once block into valid PHP.
* Compile a once block into valid PHP.
*
* @param string|null $id
* @return string
*/
protected function compileOnce($id = null)

View File

@@ -2,8 +2,34 @@
namespace Illuminate\View\Compilers\Concerns;
use Closure;
use Illuminate\Support\Str;
trait CompilesEchos
{
/**
* Custom rendering callbacks for stringable objects.
*
* @var array
*/
protected $echoHandlers = [];
/**
* Add a handler to be executed before echoing a given class.
*
* @param string|callable $class
* @param callable|null $handler
* @return void
*/
public function stringable($class, $handler = null)
{
if ($class instanceof Closure) {
[$class, $handler] = [$this->firstClosureParameterType($class), $class];
}
$this->echoHandlers[$class] = $handler;
}
/**
* Compile Blade echos into valid PHP.
*
@@ -46,7 +72,9 @@ trait CompilesEchos
$callback = function ($matches) {
$whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];
return $matches[1] ? substr($matches[0], 1) : "<?php echo {$matches[2]}; ?>{$whitespace}";
return $matches[1]
? substr($matches[0], 1)
: "<?php echo {$this->wrapInEchoHandler($matches[2])}; ?>{$whitespace}";
};
return preg_replace_callback($pattern, $callback, $value);
@@ -65,7 +93,7 @@ trait CompilesEchos
$callback = function ($matches) {
$whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];
$wrapped = sprintf($this->echoFormat, $matches[2]);
$wrapped = sprintf($this->echoFormat, $this->wrapInEchoHandler($matches[2]));
return $matches[1] ? substr($matches[0], 1) : "<?php echo {$wrapped}; ?>{$whitespace}";
};
@@ -86,9 +114,54 @@ trait CompilesEchos
$callback = function ($matches) {
$whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];
return $matches[1] ? $matches[0] : "<?php echo e({$matches[2]}); ?>{$whitespace}";
return $matches[1]
? $matches[0]
: "<?php echo e({$this->wrapInEchoHandler($matches[2])}); ?>{$whitespace}";
};
return preg_replace_callback($pattern, $callback, $value);
}
/**
* Add an instance of the blade echo handler to the start of the compiled string.
*
* @param string $result
* @return string
*/
protected function addBladeCompilerVariable($result)
{
return "<?php \$__bladeCompiler = app('blade.compiler'); ?>".$result;
}
/**
* Wrap the echoable value in an echo handler if applicable.
*
* @param string $value
* @return string
*/
protected function wrapInEchoHandler($value)
{
$value = Str::of($value)
->trim()
->when(Str::endsWith($value, ';'), function ($str) {
return $str->beforeLast(';');
});
return empty($this->echoHandlers) ? $value : '$__bladeCompiler->applyEchoHandler('.$value.')';
}
/**
* Apply the echo handler for the value if it exists.
*
* @param string $value
* @return string
*/
public function applyEchoHandler($value)
{
if (is_object($value) && isset($this->echoHandlers[get_class($value)])) {
return call_user_func($this->echoHandlers[get_class($value)], $value);
}
return $value;
}
}

View File

@@ -64,7 +64,7 @@ trait CompilesIncludes
{
$expression = $this->stripParentheses($expression);
return "<?php echo \$__env->renderWhen(! $expression, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?>";
return "<?php echo \$__env->renderUnless($expression, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?>";
}
/**

View File

@@ -12,12 +12,12 @@ trait CompilesInjections
*/
protected function compileInject($expression)
{
$segments = explode(',', preg_replace("/[\(\)\\\"\']/", '', $expression));
$segments = explode(',', preg_replace("/[\(\)]/", '', $expression));
$variable = trim($segments[0]);
$variable = trim($segments[0], " '\"");
$service = trim($segments[1]);
return "<?php \${$variable} = app('{$service}'); ?>";
return "<?php \${$variable} = app({$service}); ?>";
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Illuminate\View\Compilers\Concerns;
use Illuminate\Support\Js;
trait CompilesJs
{
/**
* Compile the "@js" directive into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileJs(string $expression)
{
return sprintf(
"<?php echo \%s::from(%s)->toHtml() ?>",
Js::class, $this->stripParentheses($expression)
);
}
}

View File

@@ -28,6 +28,23 @@ trait CompilesLayouts
return '';
}
/**
* Compile the extends-first statements into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileExtendsFirst($expression)
{
$expression = $this->stripParentheses($expression);
$echo = "<?php echo \$__env->first({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>";
$this->footer[] = $echo;
return '';
}
/**
* Compile the section statements into valid PHP.
*