Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/PreventsCircularRecursion.php
Строк: 87
<?php

namespace IlluminateDatabaseEloquentConcerns;

use 
IlluminateSupportArr;
use 
IlluminateSupportOnceable;
use 
WeakMap;

trait 
PreventsCircularRecursion
{
    
/**
     * The cache of objects processed to prevent infinite recursion.
     *
     * @var WeakMap<static, array<string, mixed>>
     */
    
protected static $recursionCache;

    
/**
     * Prevent a method from being called multiple times on the same object within the same call stack.
     *
     * @param  callable  $callback
     * @param  mixed  $default
     * @return mixed
     */
    
protected function withoutRecursion($callback$default null)
    {
        
$trace debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT2);

        
$onceable Onceable::tryFromTrace($trace$callback);

        if (
is_null($onceable)) {
            return 
call_user_func($callback);
        }

        
$stack = static::getRecursiveCallStack($this);

        if (
array_key_exists($onceable->hash$stack)) {
            return 
is_callable($stack[$onceable->hash])
                ? static::
setRecursiveCallValue($this$onceable->hashcall_user_func($stack[$onceable->hash]))
                : 
$stack[$onceable->hash];
        }

        try {
            static::
setRecursiveCallValue($this$onceable->hash$default);

            return 
call_user_func($onceable->callable);
        } finally {
            static::
clearRecursiveCallValue($this$onceable->hash);
        }
    }

    
/**
     * Remove an entry from the recursion cache for an object.
     *
     * @param  object  $object
     * @param  string  $hash
     */
    
protected static function clearRecursiveCallValue($objectstring $hash)
    {
        if (
$stack Arr::except(static::getRecursiveCallStack($object), $hash)) {
            static::
getRecursionCache()->offsetSet($object$stack);
        } elseif (static::
getRecursionCache()->offsetExists($object)) {
            static::
getRecursionCache()->offsetUnset($object);
        }
    }

    
/**
     * Get the stack of methods being called recursively for the current object.
     *
     * @param  object  $object
     * @return array
     */
    
protected static function getRecursiveCallStack($object): array
    {
        return static::
getRecursionCache()->offsetExists($object)
            ? static::
getRecursionCache()->offsetGet($object)
            : [];
    }

    
/**
     * Get the current recursion cache being used by the model.
     *
     * @return WeakMap
     */
    
protected static function getRecursionCache()
    {
        return static::
$recursionCache ??= new WeakMap();
    }

    
/**
     * Set a value in the recursion cache for the given object and method.
     *
     * @param  object  $object
     * @param  string  $hash
     * @param  mixed  $value
     * @return mixed
     */
    
protected static function setRecursiveCallValue($objectstring $hash$value)
    {
        static::
getRecursionCache()->offsetSet(
            
$object,
            
tap(static::getRecursiveCallStack($object), fn (&$stack) => $stack[$hash] = $value),
        );

        return static::
getRecursiveCallStack($object)[$hash];
    }
}
Онлайн: 2
Реклама