<?php

/**
 * Stubs for {@see https://github.com/laravel/framework/blob/master/src/Illuminate/Support/helpers.php}
 */

/**
* @see https://github.com/vimeo/psalm/issues/4816 for why this hack exists
*/
class NullObject {
    /**
     * @return null
     */
 	public function __call(string $_name, array $args) {
        return null;
    }

    /**
     * @return null
     */
    public function __get(string $s) {
        return null;
    }

    public function __set(string $_name, string $_value) : void {
    }
}

// append_config: nothing to stub

/**
 * Determine if the given value is "blank".
 *
 * @param  mixed  $value
 * @psalm-return ($value is (bool|numeric|non-empty-array)
 *  ? false
 *  : ($value is (null|''|array<never, never>) ? true : bool)
 * )
 */
function blank($value) {}

/**
 * Get the class "basename" of the given object / class.
 *
 * @param  class-string|object  $class
 * @return non-empty-string
 */
function class_basename($class) {}

/**
 * Returns all traits used by a class, its parent classes and trait of their traits.
 *
 * @param class-string|object $trait
 * @return array<trait-string, trait-string>
 */
function class_uses_recursive($class) {}

// e: nothing to stub (taint analysis only)
// env: nothing to stub

/**
 * Determine if a value is "filled".
 *
 * @param  mixed  $value
 * @psalm-return ($value is (bool|numeric|non-empty-array)
 *  ? true
 *  : ($value is (null|''|array<never, never>) ? false : bool)
 * )
 */
function filled($value) {}

/**
 * Get an item from an object using "dot" notation.
 *
 * @template TObject
 *
 * @param  TObject  $object
 * @param  string|null  $key
 * @param  mixed  $default
 * @return ($key is (null|'') ? TObject : mixed)
 */
function object_get($object, $key, $default = null) {}

/**
 * Provide access to optional objects.
 *
 * @template TValue
 * @template TResult
 * @template TCallback of null|callable(TValue): TResult
 * @psalm-param TValue $value
 * @psalm-return (
 *  TValue is null
 *      ? NullObject
 *      : (TCallback is null ? TValue : TResult)
 * )
 */
function optional($value = null, callable $callback = null) {}

// preg_replace_array: nothing to stub

/**
 * Retry an operation a given number of times.
 *
 * @template TValue
 * @param positive-int|list<int> $times
 * @param callable(int): TValue $callback
 * @param int<0, max> $sleep
 * @param null|callable(\Exception): bool $when
 * @psalm-return TValue
 *
 * @throws \Exception
 */
function retry($times, callable $callback, $sleep = 0, $when = null) {}

/**
 * Get a new stringable object from the given string.
 *
 * @param  string|null  $string
 * @return (func_num_args() is 0
 *  ? (stringable-object&\Illuminate\Support\Str)
 *  : \Illuminate\Support\Stringable
 * )
 */
function str($string = null) {}

/**
 * Call the given Closure with the given value then return the value.
 *
 * @template TValue
 *
 * @param TValue $value
 * @param null|callable(TValue): void $callback
 * @return TValue
 */
function tap($value, $callback = null) {}

/**
 * Throw the given exception if the given condition is true.
 *
 * @template TCondition
 * @template TException of \Throwable
 *
 * @param  TCondition  $condition
 * @param  TException|class-string<TException>|string  $exception
 * @param  mixed  ...$parameters
 * @return (TCondition is empty ? TCondition : never)
 * @psalm-assert empty $condition
 * @psalm-mutation-free
 */
function throw_if($condition, $exception = 'RuntimeException', ...$parameters) {}

/**
 * Throw the given exception unless the given condition is true.
 *
 * @template TCondition
 * @template TException of \Throwable
 *
 * @param  TCondition  $condition
 * @param  TException|class-string<TException>|string  $exception
 * @param  mixed  ...$parameters
 * @return (TCondition is empty ? never : TCondition)
 * @psalm-assert !empty $condition
 * @psalm-mutation-free
 */
function throw_unless($condition, $exception = 'RuntimeException', ...$parameters) {}

/**
 * Returns all traits used by a trait and its traits.
 *
 * @param class-string $trait
 * @return array<trait-string, trait-string>
 */
function trait_uses_recursive($trait) {}

/**
 * Transform the given value if it is present.
 *
 * @template TValue
 * @template TCallbackReturn
 * @template TDefault
 * @template TDefaultReturn
 *
 * @param  TValue  $value
 * @param  callable(TValue): TCallbackReturn  $callback
 * @param  TDefault|callable(TValue): TDefaultReturn  $default
 * @return mixed|null
 * @psalm-return ($value is (bool|numeric|non-empty-array)
 *  ? TCallbackReturn
 *  : ($value is (''|array<never, never>|null)
 *      ? (TDefault is callable ? TDefaultReturn : TDefault)
 *      : (TCallbackReturn|TDefaultReturn|TDefault)
 *    )
 *  )
 */
function transform($value, callable $callback, $default = null) {}

// windows_os: nothing to stub
// with: nothing to stub
