<?php
namespace Catcher;

use Throwable;

/**
 * Вызов обработчика ошибок с защитой от повторных исключений.
 *
 * @param callable $restorer Функция восстановления, принимающая исключения.
 * @param Throwable ...$errors Исключения, переданные для обработки.
 * @return mixed
 * @throws Throwable
 */
function start_restorer(callable $restorer, Throwable ...$errors) {
    try {
        return $restorer(...$errors);
    } catch (Throwable $e) {
        error_log("Restorer error: " . $e->getMessage());
        throw $e;
    }
}

/**
 * Оборачивает функцию и добавляет обработку ошибок.
 *
 * @param callable $func Основная функция.
 * @param callable|null $restorer Обработчик ошибок (по умолчанию — пробрасывает исключение).
 * @return callable
 */
function recovery(callable $func, callable $restorer = null): callable {
    if ($restorer === null) {
        $restorer = function (Throwable ...$errors) {
            throw $errors[0]; // Пробрасываем первое исключение
        };
    }

    return function (...$args) use ($func, $restorer) {
        try {
            return $func(...$args);
        } catch (Throwable $e) {
            return start_restorer($restorer, $e);
        }
    };
}

?>