package and depencies
This commit is contained in:
		| @@ -21,6 +21,7 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|         Concerns\CompilesConditionals, | ||||
|         Concerns\CompilesEchos, | ||||
|         Concerns\CompilesErrors, | ||||
|         Concerns\CompilesFragments, | ||||
|         Concerns\CompilesHelpers, | ||||
|         Concerns\CompilesIncludes, | ||||
|         Concerns\CompilesInjections, | ||||
| @@ -122,6 +123,20 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|      */ | ||||
|     protected $rawBlocks = []; | ||||
|  | ||||
|     /** | ||||
|      * The array of anonymous component paths to search for components in. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $anonymousComponentPaths = []; | ||||
|  | ||||
|     /** | ||||
|      * The array of anonymous component namespaces to autoload from. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $anonymousComponentNamespaces = []; | ||||
|  | ||||
|     /** | ||||
|      * The array of class component aliases and their class names. | ||||
|      * | ||||
| @@ -241,7 +256,7 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|         ); | ||||
|  | ||||
|         foreach ($this->precompilers as $precompiler) { | ||||
|             $value = call_user_func($precompiler, $value); | ||||
|             $value = $precompiler($value); | ||||
|         } | ||||
|  | ||||
|         // Here we will loop through all of the tokens returned by the Zend lexer and | ||||
| @@ -340,11 +355,11 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|      */ | ||||
|     protected function storeUncompiledBlocks($value) | ||||
|     { | ||||
|         if (strpos($value, '@verbatim') !== false) { | ||||
|         if (str_contains($value, '@verbatim')) { | ||||
|             $value = $this->storeVerbatimBlocks($value); | ||||
|         } | ||||
|  | ||||
|         if (strpos($value, '@php') !== false) { | ||||
|         if (str_contains($value, '@php')) { | ||||
|             $value = $this->storePhpBlocks($value); | ||||
|         } | ||||
|  | ||||
| @@ -504,12 +519,14 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|      */ | ||||
|     protected function compileStatement($match) | ||||
|     { | ||||
|         if (Str::contains($match[1], '@')) { | ||||
|         if (str_contains($match[1], '@')) { | ||||
|             $match[0] = isset($match[3]) ? $match[1].$match[3] : $match[1]; | ||||
|         } elseif (isset($this->customDirectives[$match[1]])) { | ||||
|             $match[0] = $this->callCustomDirective($match[1], Arr::get($match, 3)); | ||||
|         } elseif (method_exists($this, $method = 'compile'.ucfirst($match[1]))) { | ||||
|             $match[0] = $this->$method(Arr::get($match, 3)); | ||||
|         } else { | ||||
|             return $match[0]; | ||||
|         } | ||||
|  | ||||
|         return isset($match[3]) ? $match[0] : $match[0].$match[2]; | ||||
| @@ -524,9 +541,9 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|      */ | ||||
|     protected function callCustomDirective($name, $value) | ||||
|     { | ||||
|         $value = $value ?? ''; | ||||
|         $value ??= ''; | ||||
|  | ||||
|         if (Str::startsWith($value, '(') && Str::endsWith($value, ')')) { | ||||
|         if (str_starts_with($value, '(') && str_ends_with($value, ')')) { | ||||
|             $value = Str::substr($value, 1, -1); | ||||
|         } | ||||
|  | ||||
| @@ -625,12 +642,12 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|      */ | ||||
|     public function component($class, $alias = null, $prefix = '') | ||||
|     { | ||||
|         if (! is_null($alias) && Str::contains($alias, '\\')) { | ||||
|         if (! is_null($alias) && str_contains($alias, '\\')) { | ||||
|             [$class, $alias] = [$alias, $class]; | ||||
|         } | ||||
|  | ||||
|         if (is_null($alias)) { | ||||
|             $alias = Str::contains($class, '\\View\\Components\\') | ||||
|             $alias = str_contains($class, '\\View\\Components\\') | ||||
|                             ? collect(explode('\\', Str::after($class, '\\View\\Components\\')))->map(function ($segment) { | ||||
|                                 return Str::kebab($segment); | ||||
|                             })->implode(':') | ||||
| @@ -672,6 +689,45 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|         return $this->classComponentAliases; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register a new anonymous component path. | ||||
|      * | ||||
|      * @param  string  $path | ||||
|      * @param  string|null  $prefix | ||||
|      * @return void | ||||
|      */ | ||||
|     public function anonymousComponentPath(string $path, string $prefix = null) | ||||
|     { | ||||
|         $prefixHash = md5($prefix ?: $path); | ||||
|  | ||||
|         $this->anonymousComponentPaths[] = [ | ||||
|             'path' => $path, | ||||
|             'prefix' => $prefix, | ||||
|             'prefixHash' => $prefixHash, | ||||
|         ]; | ||||
|  | ||||
|         Container::getInstance() | ||||
|                 ->make(ViewFactory::class) | ||||
|                 ->addNamespace($prefixHash, $path); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register an anonymous component namespace. | ||||
|      * | ||||
|      * @param  string  $directory | ||||
|      * @param  string|null  $prefix | ||||
|      * @return void | ||||
|      */ | ||||
|     public function anonymousComponentNamespace(string $directory, string $prefix = null) | ||||
|     { | ||||
|         $prefix ??= $directory; | ||||
|  | ||||
|         $this->anonymousComponentNamespaces[$prefix] = Str::of($directory) | ||||
|                 ->replace('/', '.') | ||||
|                 ->trim('. ') | ||||
|                 ->toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register a class-based component namespace. | ||||
|      * | ||||
| @@ -684,6 +740,26 @@ class BladeCompiler extends Compiler implements CompilerInterface | ||||
|         $this->classComponentNamespaces[$prefix] = $namespace; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the registered anonymous component paths. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAnonymousComponentPaths() | ||||
|     { | ||||
|         return $this->anonymousComponentPaths; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the registered anonymous component namespaces. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAnonymousComponentNamespaces() | ||||
|     { | ||||
|         return $this->anonymousComponentNamespaces; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the registered class component namespaces. | ||||
|      * | ||||
|   | ||||
| @@ -3,34 +3,64 @@ | ||||
| namespace Illuminate\View\Compilers; | ||||
|  | ||||
| use Illuminate\Filesystem\Filesystem; | ||||
| use Illuminate\Support\Str; | ||||
| use InvalidArgumentException; | ||||
|  | ||||
| abstract class Compiler | ||||
| { | ||||
|     /** | ||||
|      * The Filesystem instance. | ||||
|      * The filesystem instance. | ||||
|      * | ||||
|      * @var \Illuminate\Filesystem\Filesystem | ||||
|      */ | ||||
|     protected $files; | ||||
|  | ||||
|     /** | ||||
|      * Get the cache path for the compiled views. | ||||
|      * The cache path for the compiled views. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $cachePath; | ||||
|  | ||||
|     /** | ||||
|      * The base path that should be removed from paths before hashing. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $basePath; | ||||
|  | ||||
|     /** | ||||
|      * Determines if compiled views should be cached. | ||||
|      * | ||||
|      * @var bool | ||||
|      */ | ||||
|     protected $shouldCache; | ||||
|  | ||||
|     /** | ||||
|      * The compiled view file extension. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $compiledExtension = 'php'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new compiler instance. | ||||
|      * | ||||
|      * @param  \Illuminate\Filesystem\Filesystem  $files | ||||
|      * @param  string  $cachePath | ||||
|      * @param  string  $basePath | ||||
|      * @param  bool  $shouldCache | ||||
|      * @param  string  $compiledExtension | ||||
|      * @return void | ||||
|      * | ||||
|      * @throws \InvalidArgumentException | ||||
|      */ | ||||
|     public function __construct(Filesystem $files, $cachePath) | ||||
|     public function __construct( | ||||
|         Filesystem $files, | ||||
|         $cachePath, | ||||
|         $basePath = '', | ||||
|         $shouldCache = true, | ||||
|         $compiledExtension = 'php') | ||||
|     { | ||||
|         if (! $cachePath) { | ||||
|             throw new InvalidArgumentException('Please provide a valid cache path.'); | ||||
| @@ -38,6 +68,9 @@ abstract class Compiler | ||||
|  | ||||
|         $this->files = $files; | ||||
|         $this->cachePath = $cachePath; | ||||
|         $this->basePath = $basePath; | ||||
|         $this->shouldCache = $shouldCache; | ||||
|         $this->compiledExtension = $compiledExtension; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -48,7 +81,7 @@ abstract class Compiler | ||||
|      */ | ||||
|     public function getCompiledPath($path) | ||||
|     { | ||||
|         return $this->cachePath.'/'.sha1('v2'.$path).'.php'; | ||||
|         return $this->cachePath.'/'.sha1('v2'.Str::after($path, $this->basePath)).'.'.$this->compiledExtension; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -59,6 +92,10 @@ abstract class Compiler | ||||
|      */ | ||||
|     public function isExpired($path) | ||||
|     { | ||||
|         if (! $this->shouldCache) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         $compiled = $this->getCompiledPath($path); | ||||
|  | ||||
|         // If the compiled file doesn't exist we will indicate that the view is expired | ||||
|   | ||||
| @@ -111,10 +111,18 @@ class ComponentTagCompiler | ||||
|                     (?: | ||||
|                         \s+ | ||||
|                         (?: | ||||
|                             (?: | ||||
|                                 @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 (\:\\\$)(\w+) | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 [\w\-:.@]+ | ||||
|                                 ( | ||||
| @@ -164,10 +172,18 @@ class ComponentTagCompiler | ||||
|                     (?: | ||||
|                         \s+ | ||||
|                         (?: | ||||
|                             (?: | ||||
|                                 @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 (\:\\\$)(\w+) | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 [\w\-:.@]+ | ||||
|                                 ( | ||||
| @@ -216,12 +232,16 @@ class ComponentTagCompiler | ||||
|             return [Str::camel($key) => $value]; | ||||
|         }); | ||||
|  | ||||
|         // If the component doesn't exists as a class we'll assume it's a class-less | ||||
|         // If the component doesn't exist as a class, we'll assume it's a class-less | ||||
|         // component and pass the component as a view parameter to the data so it | ||||
|         // can be accessed within the component and we can render out the view. | ||||
|         if (! class_exists($class)) { | ||||
|             $view = Str::startsWith($component, 'mail::') | ||||
|                 ? "\$__env->getContainer()->make(Illuminate\\View\\Factory::class)->make('{$component}')" | ||||
|                 : "'$class'"; | ||||
|  | ||||
|             $parameters = [ | ||||
|                 'view' => "'$class'", | ||||
|                 'view' => $view, | ||||
|                 'data' => '['.$this->attributesToString($data->all(), $escapeBound = false).']', | ||||
|             ]; | ||||
|  | ||||
| @@ -231,6 +251,9 @@ class ComponentTagCompiler | ||||
|         } | ||||
|  | ||||
|         return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).']) | ||||
| <?php if (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag && $constructor = (new ReflectionClass('.$class.'::class))->getConstructor()): ?> | ||||
| <?php $attributes = $attributes->except(collect($constructor->getParameters())->map->getName()->all()); ?> | ||||
| <?php endif; ?> | ||||
| <?php $component->withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>'; | ||||
|     } | ||||
|  | ||||
| @@ -268,12 +291,13 @@ class ComponentTagCompiler | ||||
|             return $class; | ||||
|         } | ||||
|  | ||||
|         if ($viewFactory->exists($view = $this->guessViewName($component))) { | ||||
|             return $view; | ||||
|         if (! is_null($guess = $this->guessAnonymousComponentUsingNamespaces($viewFactory, $component)) || | ||||
|             ! is_null($guess = $this->guessAnonymousComponentUsingPaths($viewFactory, $component))) { | ||||
|             return $guess; | ||||
|         } | ||||
|  | ||||
|         if ($viewFactory->exists($view = $this->guessViewName($component).'.index')) { | ||||
|             return $view; | ||||
|         if (Str::startsWith($component, 'mail::')) { | ||||
|             return $component; | ||||
|         } | ||||
|  | ||||
|         throw new InvalidArgumentException( | ||||
| @@ -281,6 +305,72 @@ class ComponentTagCompiler | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Attempt to find an anonymous component using the registered anonymous component paths. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\View\Factory  $viewFactory | ||||
|      * @param  string  $component | ||||
|      * @return string|null | ||||
|      */ | ||||
|     protected function guessAnonymousComponentUsingPaths(Factory $viewFactory, string $component) | ||||
|     { | ||||
|         $delimiter = ViewFinderInterface::HINT_PATH_DELIMITER; | ||||
|  | ||||
|         foreach ($this->blade->getAnonymousComponentPaths() as $path) { | ||||
|             try { | ||||
|                 if (str_contains($component, $delimiter) && | ||||
|                     ! str_starts_with($component, $path['prefix'].$delimiter)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 $formattedComponent = str_starts_with($component, $path['prefix'].$delimiter) | ||||
|                         ? Str::after($component, $delimiter) | ||||
|                         : $component; | ||||
|  | ||||
|                 if (! is_null($guess = match (true) { | ||||
|                     $viewFactory->exists($guess = $path['prefixHash'].$delimiter.$formattedComponent) => $guess, | ||||
|                     $viewFactory->exists($guess = $path['prefixHash'].$delimiter.$formattedComponent.'.index') => $guess, | ||||
|                     default => null, | ||||
|                 })) { | ||||
|                     return $guess; | ||||
|                 } | ||||
|             } catch (InvalidArgumentException $e) { | ||||
|                 // | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Attempt to find an anonymous component using the registered anonymous component namespaces. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\View\Factory  $viewFactory | ||||
|      * @param  string  $component | ||||
|      * @return string|null | ||||
|      */ | ||||
|     protected function guessAnonymousComponentUsingNamespaces(Factory $viewFactory, string $component) | ||||
|     { | ||||
|         return collect($this->blade->getAnonymousComponentNamespaces()) | ||||
|             ->filter(function ($directory, $prefix) use ($component) { | ||||
|                 return Str::startsWith($component, $prefix.'::'); | ||||
|             }) | ||||
|             ->prepend('components', $component) | ||||
|             ->reduce(function ($carry, $directory, $prefix) use ($component, $viewFactory) { | ||||
|                 if (! is_null($carry)) { | ||||
|                     return $carry; | ||||
|                 } | ||||
|  | ||||
|                 $componentName = Str::after($component, $prefix.'::'); | ||||
|  | ||||
|                 if ($viewFactory->exists($view = $this->guessViewName($componentName, $directory))) { | ||||
|                     return $view; | ||||
|                 } | ||||
|  | ||||
|                 if ($viewFactory->exists($view = $this->guessViewName($componentName, $directory).'.index')) { | ||||
|                     return $view; | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find the class for the given component using the registered namespaces. | ||||
|      * | ||||
| @@ -293,7 +383,7 @@ class ComponentTagCompiler | ||||
|  | ||||
|         $prefix = $segments[0]; | ||||
|  | ||||
|         if (! isset($this->namespaces[$prefix]) || ! isset($segments[1])) { | ||||
|         if (! isset($this->namespaces[$prefix], $segments[1])) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -338,15 +428,18 @@ class ComponentTagCompiler | ||||
|      * Guess the view name for the given component. | ||||
|      * | ||||
|      * @param  string  $name | ||||
|      * @param  string  $prefix | ||||
|      * @return string | ||||
|      */ | ||||
|     public function guessViewName($name) | ||||
|     public function guessViewName($name, $prefix = 'components.') | ||||
|     { | ||||
|         $prefix = 'components.'; | ||||
|         if (! Str::endsWith($prefix, '.')) { | ||||
|             $prefix .= '.'; | ||||
|         } | ||||
|  | ||||
|         $delimiter = ViewFinderInterface::HINT_PATH_DELIMITER; | ||||
|  | ||||
|         if (Str::contains($name, $delimiter)) { | ||||
|         if (str_contains($name, $delimiter)) { | ||||
|             return Str::replaceFirst($delimiter, $delimiter.$prefix, $name); | ||||
|         } | ||||
|  | ||||
| @@ -362,7 +455,7 @@ class ComponentTagCompiler | ||||
|      */ | ||||
|     public function partitionDataAndAttributes($class, array $attributes) | ||||
|     { | ||||
|         // If the class doesn't exists, we'll assume it's a class-less component and | ||||
|         // If the class doesn't exist, we'll assume it is a class-less component and | ||||
|         // return all of the attributes as both data and attributes since we have | ||||
|         // now way to partition them. The user can exclude attributes manually. | ||||
|         if (! class_exists($class)) { | ||||
| @@ -403,12 +496,16 @@ class ComponentTagCompiler | ||||
|             < | ||||
|                 \s* | ||||
|                 x[\-\:]slot | ||||
|                 \s+ | ||||
|                 (:?)name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)) | ||||
|                 (?:\:(?<inlineName>\w+(?:-\w+)*))? | ||||
|                 (?:\s+(:?)name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))? | ||||
|                 (?<attributes> | ||||
|                     (?: | ||||
|                         \s+ | ||||
|                         (?: | ||||
|                             (?: | ||||
|                                 @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) | ||||
|                             ) | ||||
|                             | | ||||
|                             (?: | ||||
|                                 \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} | ||||
|                             ) | ||||
| @@ -435,9 +532,13 @@ class ComponentTagCompiler | ||||
|         /x"; | ||||
|  | ||||
|         $value = preg_replace_callback($pattern, function ($matches) { | ||||
|             $name = $this->stripQuotes($matches['name']); | ||||
|             $name = $this->stripQuotes($matches['inlineName'] ?: $matches['name']); | ||||
|  | ||||
|             if ($matches[1] !== ':') { | ||||
|             if (Str::contains($name, '-') && ! empty($matches['inlineName'])) { | ||||
|                 $name = Str::camel($name); | ||||
|             } | ||||
|  | ||||
|             if ($matches[2] !== ':') { | ||||
|                 $name = "'{$name}'"; | ||||
|             } | ||||
|  | ||||
| @@ -459,8 +560,9 @@ class ComponentTagCompiler | ||||
|      */ | ||||
|     protected function getAttributesFromAttributeString(string $attributeString) | ||||
|     { | ||||
|         $attributeString = $this->parseShortAttributeSyntax($attributeString); | ||||
|         $attributeString = $this->parseAttributeBag($attributeString); | ||||
|  | ||||
|         $attributeString = $this->parseComponentTagClassStatements($attributeString); | ||||
|         $attributeString = $this->parseBindAttributes($attributeString); | ||||
|  | ||||
|         $pattern = '/ | ||||
| @@ -495,7 +597,7 @@ class ComponentTagCompiler | ||||
|  | ||||
|             $value = $this->stripQuotes($value); | ||||
|  | ||||
|             if (Str::startsWith($attribute, 'bind:')) { | ||||
|             if (str_starts_with($attribute, 'bind:')) { | ||||
|                 $attribute = Str::after($attribute, 'bind:'); | ||||
|  | ||||
|                 $this->boundAttributes[$attribute] = true; | ||||
| @@ -503,7 +605,7 @@ class ComponentTagCompiler | ||||
|                 $value = "'".$this->compileAttributeEchos($value)."'"; | ||||
|             } | ||||
|  | ||||
|             if (Str::startsWith($attribute, '::')) { | ||||
|             if (str_starts_with($attribute, '::')) { | ||||
|                 $attribute = substr($attribute, 1); | ||||
|             } | ||||
|  | ||||
| @@ -511,6 +613,21 @@ class ComponentTagCompiler | ||||
|         })->toArray(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses a short attribute syntax like :$foo into a fully-qualified syntax like :foo="$foo". | ||||
|      * | ||||
|      * @param  string  $value | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function parseShortAttributeSyntax(string $value) | ||||
|     { | ||||
|         $pattern = "/\s\:\\\$(\w+)/x"; | ||||
|  | ||||
|         return preg_replace_callback($pattern, function (array $matches) { | ||||
|             return " :{$matches[1]}=\"\${$matches[1]}\""; | ||||
|         }, $value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse the attribute bag in a given attribute string into its fully-qualified syntax. | ||||
|      * | ||||
| @@ -527,6 +644,27 @@ class ComponentTagCompiler | ||||
|         return preg_replace($pattern, ' :attributes="$1"', $attributeString); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse @class statements in a given attribute string into their fully-qualified syntax. | ||||
|      * | ||||
|      * @param  string  $attributeString | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function parseComponentTagClassStatements(string $attributeString) | ||||
|     { | ||||
|         return preg_replace_callback( | ||||
|              '/@(class)(\( ( (?>[^()]+) | (?2) )* \))/x', function ($match) { | ||||
|                  if ($match[1] === 'class') { | ||||
|                      $match[2] = str_replace('"', "'", $match[2]); | ||||
|  | ||||
|                      return ":class=\"\Illuminate\Support\Arr::toCssClasses{$match[2]}\""; | ||||
|                  } | ||||
|  | ||||
|                  return $match[0]; | ||||
|              }, $attributeString | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse the "bind" attributes in a given attribute string into their fully-qualified syntax. | ||||
|      * | ||||
|   | ||||
| @@ -23,7 +23,7 @@ trait CompilesComponents | ||||
|      */ | ||||
|     protected function compileComponent($expression) | ||||
|     { | ||||
|         [$component, $alias, $data] = strpos($expression, ',') !== false | ||||
|         [$component, $alias, $data] = str_contains($expression, ',') | ||||
|                     ? array_map('trim', explode(',', trim($expression, '()'), 3)) + ['', '', ''] | ||||
|                     : [trim($expression, '()'), '', '']; | ||||
|  | ||||
| @@ -64,7 +64,7 @@ trait CompilesComponents | ||||
|     { | ||||
|         return implode("\n", [ | ||||
|             '<?php if (isset($component)) { $__componentOriginal'.$hash.' = $component; } ?>', | ||||
|             '<?php $component = $__env->getContainer()->make('.Str::finish($component, '::class').', '.($data ?: '[]').'); ?>', | ||||
|             '<?php $component = '.$component.'::resolve('.($data ?: '[]').' + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? (array) $attributes->getIterator() : [])); ?>', | ||||
|             '<?php $component->withName('.$alias.'); ?>', | ||||
|             '<?php if ($component->shouldRender()): ?>', | ||||
|             '<?php $__env->startComponent($component->resolveView(), $component->data()); ?>', | ||||
| @@ -149,7 +149,11 @@ trait CompilesComponents | ||||
|      */ | ||||
|     protected function compileProps($expression) | ||||
|     { | ||||
|         return "<?php \$attributes = \$attributes->exceptProps{$expression}; ?> | ||||
|         return "<?php \$attributes ??= new \\Illuminate\\View\\ComponentAttributeBag; ?> | ||||
| <?php foreach(\$attributes->onlyProps{$expression} as \$__key => \$__value) { | ||||
|     \$\$__key = \$\$__key ?? \$__value; | ||||
| } ?> | ||||
| <?php \$attributes = \$attributes->exceptProps{$expression}; ?> | ||||
| <?php foreach (array_filter({$expression}, 'is_string', ARRAY_FILTER_USE_KEY) as \$__key => \$__value) { | ||||
|     \$\$__key = \$\$__key ?? \$__value; | ||||
| } ?> | ||||
| @@ -182,7 +186,7 @@ trait CompilesComponents | ||||
|      */ | ||||
|     public static function sanitizeComponentAttribute($value) | ||||
|     { | ||||
|         if (is_object($value) && $value instanceof CanBeEscapedWhenCastToString) { | ||||
|         if ($value instanceof CanBeEscapedWhenCastToString) { | ||||
|             return $value->escapeWhenCastingToString(); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -304,4 +304,82 @@ trait CompilesConditionals | ||||
|     { | ||||
|         return '<?php endif; ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile a selected block into valid PHP. | ||||
|      * | ||||
|      * @param  string  $condition | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileSelected($condition) | ||||
|     { | ||||
|         return "<?php if{$condition}: echo 'selected'; endif; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile a checked block into valid PHP. | ||||
|      * | ||||
|      * @param  string  $condition | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileChecked($condition) | ||||
|     { | ||||
|         return "<?php if{$condition}: echo 'checked'; endif; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile a disabled block into valid PHP. | ||||
|      * | ||||
|      * @param  string  $condition | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileDisabled($condition) | ||||
|     { | ||||
|         return "<?php if{$condition}: echo 'disabled'; endif; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile a required block into valid PHP. | ||||
|      * | ||||
|      * @param  string  $condition | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileRequired($condition) | ||||
|     { | ||||
|         return "<?php if{$condition}: echo 'required'; endif; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile a readonly block into valid PHP. | ||||
|      * | ||||
|      * @param  string  $condition | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileReadonly($condition) | ||||
|     { | ||||
|         return "<?php if{$condition}: echo 'readonly'; endif; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the push statements into valid PHP. | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compilePushIf($expression) | ||||
|     { | ||||
|         $parts = explode(',', $this->stripParentheses($expression), 2); | ||||
|  | ||||
|         return "<?php if({$parts[0]}): \$__env->startPush({$parts[1]}); ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-push statements into valid PHP. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileEndPushIf() | ||||
|     { | ||||
|         return '<?php $__env->stopPush(); endif; ?>'; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -143,7 +143,7 @@ trait CompilesEchos | ||||
|     { | ||||
|         $value = Str::of($value) | ||||
|             ->trim() | ||||
|             ->when(Str::endsWith($value, ';'), function ($str) { | ||||
|             ->when(str_ends_with($value, ';'), function ($str) { | ||||
|                 return $str->beforeLast(';'); | ||||
|             }); | ||||
|  | ||||
|   | ||||
							
								
								
									
										36
									
								
								vendor/laravel/framework/src/Illuminate/View/Compilers/Concerns/CompilesFragments.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/laravel/framework/src/Illuminate/View/Compilers/Concerns/CompilesFragments.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Illuminate\View\Compilers\Concerns; | ||||
|  | ||||
| trait CompilesFragments | ||||
| { | ||||
|     /** | ||||
|      * The last compiled fragment. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $lastFragment; | ||||
|  | ||||
|     /** | ||||
|      * Compile the fragment statements into valid PHP. | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileFragment($expression) | ||||
|     { | ||||
|         $this->lastFragment = trim($expression, "()'\" "); | ||||
|  | ||||
|         return "<?php \$__env->startFragment{$expression}; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-fragment statements into valid PHP. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileEndfragment() | ||||
|     { | ||||
|         return '<?php echo $__env->stopFragment(); ?>'; | ||||
|     } | ||||
| } | ||||
| @@ -2,6 +2,8 @@ | ||||
|  | ||||
| namespace Illuminate\View\Compilers\Concerns; | ||||
|  | ||||
| use Illuminate\Foundation\Vite; | ||||
|  | ||||
| trait CompilesHelpers | ||||
| { | ||||
|     /** | ||||
| @@ -46,4 +48,31 @@ trait CompilesHelpers | ||||
|     { | ||||
|         return "<?php echo method_field{$method}; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the "vite" statements into valid PHP. | ||||
|      * | ||||
|      * @param  ?string  $arguments | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileVite($arguments) | ||||
|     { | ||||
|         $arguments ??= '()'; | ||||
|  | ||||
|         $class = Vite::class; | ||||
|  | ||||
|         return "<?php echo app('$class'){$arguments}; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the "viteReactRefresh" statements into valid PHP. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileViteReactRefresh() | ||||
|     { | ||||
|         $class = Vite::class; | ||||
|  | ||||
|         return "<?php echo app('$class')->reactRefresh(); ?>"; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
|  | ||||
| namespace Illuminate\View\Compilers\Concerns; | ||||
|  | ||||
| use Illuminate\Contracts\View\ViewCompilationException; | ||||
|  | ||||
| trait CompilesLoops | ||||
| { | ||||
|     /** | ||||
| @@ -16,12 +18,18 @@ trait CompilesLoops | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      * | ||||
|      * @throws \Illuminate\Contracts\View\ViewCompilationException | ||||
|      */ | ||||
|     protected function compileForelse($expression) | ||||
|     { | ||||
|         $empty = '$__empty_'.++$this->forElseCounter; | ||||
|  | ||||
|         preg_match('/\( *(.*) +as *(.*)\)$/is', $expression, $matches); | ||||
|         preg_match('/\( *(.+) +as +(.+)\)$/is', $expression ?? '', $matches); | ||||
|  | ||||
|         if (count($matches) === 0) { | ||||
|             throw new ViewCompilationException('Malformed @forelse statement.'); | ||||
|         } | ||||
|  | ||||
|         $iteratee = trim($matches[1]); | ||||
|  | ||||
| @@ -87,10 +95,16 @@ trait CompilesLoops | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      * | ||||
|      * @throws \Illuminate\Contracts\View\ViewCompilationException | ||||
|      */ | ||||
|     protected function compileForeach($expression) | ||||
|     { | ||||
|         preg_match('/\( *(.*) +as *(.*)\)$/is', $expression, $matches); | ||||
|         preg_match('/\( *(.+) +as +(.*)\)$/is', $expression ?? '', $matches); | ||||
|  | ||||
|         if (count($matches) === 0) { | ||||
|             throw new ViewCompilationException('Malformed @foreach statement.'); | ||||
|         } | ||||
|  | ||||
|         $iteratee = trim($matches[1]); | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
|  | ||||
| namespace Illuminate\View\Compilers\Concerns; | ||||
|  | ||||
| use Illuminate\Support\Str; | ||||
|  | ||||
| trait CompilesStacks | ||||
| { | ||||
|     /** | ||||
| @@ -26,6 +28,24 @@ trait CompilesStacks | ||||
|         return "<?php \$__env->startPush{$expression}; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the push-once statements into valid PHP. | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compilePushOnce($expression) | ||||
|     { | ||||
|         $parts = explode(',', $this->stripParentheses($expression), 2); | ||||
|  | ||||
|         [$stack, $id] = [$parts[0], $parts[1] ?? '']; | ||||
|  | ||||
|         $id = trim($id) ?: "'".(string) Str::uuid()."'"; | ||||
|  | ||||
|         return '<?php if (! $__env->hasRenderedOnce('.$id.')): $__env->markAsRenderedOnce('.$id.'); | ||||
| $__env->startPush('.$stack.'); ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-push statements into valid PHP. | ||||
|      * | ||||
| @@ -36,6 +56,16 @@ trait CompilesStacks | ||||
|         return '<?php $__env->stopPush(); ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-push-once statements into valid PHP. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileEndpushOnce() | ||||
|     { | ||||
|         return '<?php $__env->stopPush(); endif; ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the prepend statements into valid PHP. | ||||
|      * | ||||
| @@ -47,6 +77,24 @@ trait CompilesStacks | ||||
|         return "<?php \$__env->startPrepend{$expression}; ?>"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the prepend-once statements into valid PHP. | ||||
|      * | ||||
|      * @param  string  $expression | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compilePrependOnce($expression) | ||||
|     { | ||||
|         $parts = explode(',', $this->stripParentheses($expression), 2); | ||||
|  | ||||
|         [$stack, $id] = [$parts[0], $parts[1] ?? '']; | ||||
|  | ||||
|         $id = trim($id) ?: "'".(string) Str::uuid()."'"; | ||||
|  | ||||
|         return '<?php if (! $__env->hasRenderedOnce('.$id.')): $__env->markAsRenderedOnce('.$id.'); | ||||
| $__env->startPrepend('.$stack.'); ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-prepend statements into valid PHP. | ||||
|      * | ||||
| @@ -56,4 +104,14 @@ trait CompilesStacks | ||||
|     { | ||||
|         return '<?php $__env->stopPrepend(); ?>'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compile the end-prepend-once statements into valid PHP. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function compileEndprependOnce() | ||||
|     { | ||||
|         return '<?php $__env->stopPrepend(); endif; ?>'; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 RafficMohammed
					RafficMohammed