Вход Регистрация
Файл: vendor/nesbot/carbon/src/Carbon/Callback.php
Строк: 142
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use 
Closure;
use 
DateInterval;
use 
DatePeriod;
use 
DateTime;
use 
DateTimeInterface;
use 
DateTimeZone;
use 
ReflectionFunction;
use 
ReflectionNamedType;
use 
ReflectionType;

final class 
Callback
{
    private ?
ReflectionFunction $function;

    private function 
__construct(private readonly Closure $closure)
    {
    }

    public static function 
fromClosure(Closure $closure): self
    
{
        return new 
self($closure);
    }

    public static function 
parameter(mixed $closuremixed $valuestring|int $index 0): mixed
    
{
        if (
$closure instanceof Closure) {
            return 
self::fromClosure($closure)->prepareParameter($value$index);
        }

        return 
$value;
    }

    public function 
getReflectionFunction(): ReflectionFunction
    
{
        return 
$this->function ??= new ReflectionFunction($this->closure);
    }

    public function 
prepareParameter(mixed $valuestring|int $index 0): mixed
    
{
        
$type $this->getParameterType($index);

        if (!(
$type instanceof ReflectionNamedType)) {
            return 
$value;
        }

        
$name $type->getName();

        if (
$name === CarbonInterface::class) {
            
$name $value instanceof DateTime Carbon::class : CarbonImmutable::class;
        }

        if (!
class_exists($name) || is_a($value$name)) {
            return 
$value;
        }

        
$class $this->getPromotedClass($value);

        if (
$class && is_a($name$classtrue)) {
            return 
$name::instance($value);
        }

        return 
$value;
    }

    public function 
call(mixed ...$arguments): mixed
    
{
        foreach (
$arguments as $index => &$value) {
            if (
$this->getPromotedClass($value)) {
                
$value $this->prepareParameter($value$index);
            }
        }

        return (
$this->closure)(...$arguments);
    }

    private function 
getParameterType(string|int $index): ?ReflectionType
    
{
        
$parameters $this->getReflectionFunction()->getParameters();

        if (
is_int($index)) {
            return (
$parameters[$index] ?? null)?->getType();
        }

        foreach (
$parameters as $parameter) {
            if (
$parameter->getName() === $index) {
                return 
$parameter->getType();
            }
        }

        return 
null;
    }

    
/** @return class-string|null */
    
private function getPromotedClass(mixed $value): ?string
    
{
        if (
$value instanceof DateTimeInterface) {
            return 
CarbonInterface::class;
        }

        if (
$value instanceof DateInterval) {
            return 
CarbonInterval::class;
        }

        if (
$value instanceof DatePeriod) {
            return 
CarbonPeriod::class;
        }

        if (
$value instanceof DateTimeZone) {
            return 
CarbonTimeZone::class;
        }

        return 
null;
    }
}
Онлайн: 0
Реклама