/home/kueuepay/public_html/vendor/symfony/error-handler/DebugClassLoader.php
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ErrorHandler;

use Composer\InstalledVersions;
use Doctrine\Common\Persistence\Proxy as LegacyProxy;
use Doctrine\Persistence\Proxy;
use Mockery\MockInterface;
use Phake\IMock;
use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
use PHPUnit\Framework\MockObject\MockObject;
use Prophecy\Prophecy\ProphecySubjectInterface;
use ProxyManager\Proxy\ProxyInterface;
use Symfony\Component\ErrorHandler\Internal\TentativeTypes;

/**
 * Autoloader checking if the class is really defined in the file found.
 *
 * The ClassLoader will wrap all registered autoloaders
 * and will throw an exception if a file is found but does
 * not declare the class.
 *
 * It can also patch classes to turn docblocks into actual return types.
 * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var,
 * which is a url-encoded array with the follow parameters:
 *  - "force": any value enables deprecation notices - can be any of:
 *      - "phpdoc" to patch only docblock annotations
 *      - "2" to add all possible return types
 *      - "1" to add return types but only to tests/final/internal/private methods
 *  - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types
 *  - "deprecations": "1" to trigger a deprecation notice when a child class misses a
 *                    return type while the parent declares an "@return" annotation
 *
 * Note that patching doesn't care about any coding style so you'd better to run
 * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation"
 * and "no_superfluous_phpdoc_tags" enabled typically.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Guilhem Niot <guilhem.niot@gmail.com>
 */
class DebugClassLoader
{
    private const SPECIAL_RETURN_TYPES = [
        'void' => 'void',
        'null' => 'null',
        'resource' => 'resource',
        'boolean' => 'bool',
        'true' => 'true',
        'false' => 'false',
        'integer' => 'int',
        'array' => 'array',
        'bool' => 'bool',
        'callable' => 'callable',
        'float' => 'float',
        'int' => 'int',
        'iterable' => 'iterable',
        'object' => 'object',
        'string' => 'string',
        'self' => 'self',
        'parent' => 'parent',
        'mixed' => 'mixed',
        'static' => 'static',
        '$this' => 'static',
        'list' => 'array',
        'class-string' => 'string',
        'never' => 'never',
    ];

    private const BUILTIN_RETURN_TYPES = [
        'void' => true,
        'array' => true,
        'false' => true,
        'bool' => true,
        'callable' => true,
        'float' => true,
        'int' => true,
        'iterable' => true,
        'object' => true,
        'string' => true,
        'self' => true,
        'parent' => true,
        'mixed' => true,
        'static' => true,
        'null' => true,
        'true' => true,
        'never' => true,
    ];

    private const MAGIC_METHODS = [
        '__isset' => 'bool',
        '__sleep' => 'array',
        '__toString' => 'string',
        '__debugInfo' => 'array',
        '__serialize' => 'array',
    ];

    /**
     * @var callable
     */
    private $classLoader;
    private bool $isFinder;
    private array $loaded = [];
    private array $patchTypes = [];

    private static int $caseCheck;
    private static array $checkedClasses = [];
    private static array $final = [];
    private static array $finalMethods = [];
    private static array $deprecated = [];
    private static array $internal = [];
    private static array $internalMethods = [];
    private static array $annotatedParameters = [];
    private static array $darwinCache = ['/' => ['/', []]];
    private static array $method = [];
    private static array $returnTypes = [];
    private static array $methodTraits = [];
    private static array $fileOffsets = [];

    public function __construct(callable $classLoader)
    {
        $this->classLoader = $classLoader;
        $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
        parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes);
        $this->patchTypes += [
            'force' => null,
            'php' => \PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION,
            'deprecations' => true,
        ];

        if ('phpdoc' === $this->patchTypes['force']) {
            $this->patchTypes['force'] = 'docblock';
        }

        if (!isset(self::$caseCheck)) {
            $file = is_file(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
            $i = strrpos($file, \DIRECTORY_SEPARATOR);
            $dir = substr($file, 0, 1 + $i);
            $file = substr($file, 1 + $i);
            $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
            $test = realpath($dir.$test);

            if (false === $test || false === $i) {
                // filesystem is case sensitive
                self::$caseCheck = 0;
            } elseif (str_ends_with($test, $file)) {
                // filesystem is case insensitive and realpath() normalizes the case of characters
                self::$caseCheck = 1;
            } elseif ('Darwin' === \PHP_OS_FAMILY) {
                // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
                self::$caseCheck = 2;
            } else {
                // filesystem case checks failed, fallback to disabling them
                self::$caseCheck = 0;
            }
        }
    }

    public function getClassLoader(): callable
    {
        return $this->classLoader;
    }

    /**
     * Wraps all autoloaders.
     */
    public static function enable(): void
    {
        // Ensures we don't hit https://bugs.php.net/42098
        class_exists(\Symfony\Component\ErrorHandler\ErrorHandler::class);
        class_exists(\Psr\Log\LogLevel::class);

        if (!\is_array($functions = spl_autoload_functions())) {
            return;
        }

        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }

        foreach ($functions as $function) {
            if (!\is_array($function) || !$function[0] instanceof self) {
                $function = [new static($function), 'loadClass'];
            }

            spl_autoload_register($function);
        }
    }

    /**
     * Disables the wrapping.
     */
    public static function disable(): void
    {
        if (!\is_array($functions = spl_autoload_functions())) {
            return;
        }

        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }

        foreach ($functions as $function) {
            if (\is_array($function) && $function[0] instanceof self) {
                $function = $function[0]->getClassLoader();
            }

            spl_autoload_register($function);
        }
    }

    public static function checkClasses(): bool
    {
        if (!\is_array($functions = spl_autoload_functions())) {
            return false;
        }

        $loader = null;

        foreach ($functions as $function) {
            if (\is_array($function) && $function[0] instanceof self) {
                $loader = $function[0];
                break;
            }
        }

        if (null === $loader) {
            return false;
        }

        static $offsets = [
            'get_declared_interfaces' => 0,
            'get_declared_traits' => 0,
            'get_declared_classes' => 0,
        ];

        foreach ($offsets as $getSymbols => $i) {
            $symbols = $getSymbols();

            for (; $i < \count($symbols); ++$i) {
                if (!is_subclass_of($symbols[$i], MockObject::class)
                    && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class)
                    && !is_subclass_of($symbols[$i], Proxy::class)
                    && !is_subclass_of($symbols[$i], ProxyInterface::class)
                    && !is_subclass_of($symbols[$i], LegacyProxy::class)
                    && !is_subclass_of($symbols[$i], MockInterface::class)
                    && !is_subclass_of($symbols[$i], IMock::class)
                ) {
                    $loader->checkClass($symbols[$i]);
                }
            }

            $offsets[$getSymbols] = $i;
        }

        return true;
    }

    public function findFile(string $class): ?string
    {
        return $this->isFinder ? ($this->classLoader[0]->findFile($class) ?: null) : null;
    }

    /**
     * Loads the given class or interface.
     *
     * @throws \RuntimeException
     */
    public function loadClass(string $class): void
    {
        $e = error_reporting(error_reporting() | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR);

        try {
            if ($this->isFinder && !isset($this->loaded[$class])) {
                $this->loaded[$class] = true;
                if (!$file = $this->classLoader[0]->findFile($class) ?: '') {
                    // no-op
                } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
                    include $file;

                    return;
                } elseif (false === include $file) {
                    return;
                }
            } else {
                ($this->classLoader)($class);
                $file = '';
            }
        } finally {
            error_reporting($e);
        }

        $this->checkClass($class, $file);
    }

    private function checkClass(string $class, string $file = null): void
    {
        $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);

        if (null !== $file && $class && '\\' === $class[0]) {
            $class = substr($class, 1);
        }

        if ($exists) {
            if (isset(self::$checkedClasses[$class])) {
                return;
            }
            self::$checkedClasses[$class] = true;

            $refl = new \ReflectionClass($class);
            if (null === $file && $refl->isInternal()) {
                return;
            }
            $name = $refl->getName();

            if ($name !== $class && 0 === strcasecmp($name, $class)) {
                throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
            }

            $deprecations = $this->checkAnnotations($refl, $name);

            foreach ($deprecations as $message) {
                @trigger_error($message, \E_USER_DEPRECATED);
            }
        }

        if (!$file) {
            return;
        }

        if (!$exists) {
            if (str_contains($class, '/')) {
                throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
            }

            throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
        }

        if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) {
            throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2]));
        }
    }

    public function checkAnnotations(\ReflectionClass $refl, string $class): array
    {
        if (
            'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class
            || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class
        ) {
            return [];
        }
        $deprecations = [];

        $className = str_contains($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;

        // Don't trigger deprecations for classes in the same vendor
        if ($class !== $className) {
            $vendor = preg_match('/^namespace ([^;\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1].'\\' : '';
            $vendorLen = \strlen($vendor);
        } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) {
            $vendorLen = 0;
            $vendor = '';
        } else {
            $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen));
        }

        $parent = get_parent_class($class) ?: null;
        self::$returnTypes[$class] = [];
        $classIsTemplate = false;

        // Detect annotations on the class
        if ($doc = $this->parsePhpDoc($refl)) {
            $classIsTemplate = isset($doc['template']);

            foreach (['final', 'deprecated', 'internal'] as $annotation) {
                if (null !== $description = $doc[$annotation][0] ?? null) {
                    self::${$annotation}[$class] = '' !== $description ? ' '.$description.(preg_match('/[.!]$/', $description) ? '' : '.') : '.';
                }
            }

            if ($refl->isInterface() && isset($doc['method'])) {
                foreach ($doc['method'] as $name => [$static, $returnType, $signature, $description]) {
                    self::$method[$class][] = [$class, $static, $returnType, $name.$signature, $description];

                    if ('' !== $returnType) {
                        $this->setReturnType($returnType, $refl->name, $name, $refl->getFileName(), $parent);
                    }
                }
            }
        }

        $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
        if ($parent) {
            $parentAndOwnInterfaces[$parent] = $parent;

            if (!isset(self::$checkedClasses[$parent])) {
                $this->checkClass($parent);
            }

            if (isset(self::$final[$parent])) {
                $deprecations[] = sprintf('The "%s" class is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className);
            }
        }

        // Detect if the parent is annotated
        foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) {
            if (!isset(self::$checkedClasses[$use])) {
                $this->checkClass($use);
            }
            if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) {
                $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
                $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');

                $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s', $className, $type, $verb, $use, self::$deprecated[$use]);
            }
            if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) {
                $deprecations[] = sprintf('The "%s" %s is considered internal%s It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className);
            }
            if (isset(self::$method[$use])) {
                if ($refl->isAbstract()) {
                    if (isset(self::$method[$class])) {
                        self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
                    } else {
                        self::$method[$class] = self::$method[$use];
                    }
                } elseif (!$refl->isInterface()) {
                    if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)
                        && str_starts_with($className, 'Symfony\\')
                        && (!class_exists(InstalledVersions::class)
                            || 'symfony/symfony' !== InstalledVersions::getRootPackage()['name'])
                    ) {
                        // skip "same vendor" @method deprecations for Symfony\* classes unless symfony/symfony is being tested
                        continue;
                    }
                    $hasCall = $refl->hasMethod('__call');
                    $hasStaticCall = $refl->hasMethod('__callStatic');
                    foreach (self::$method[$use] as [$interface, $static, $returnType, $name, $description]) {
                        if ($static ? $hasStaticCall : $hasCall) {
                            continue;
                        }
                        $realName = substr($name, 0, strpos($name, '('));
                        if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) {
                            $deprecations[] = sprintf('Class "%s" should implement method "%s::%s%s"%s', $className, ($static ? 'static ' : '').$interface, $name, $returnType ? ': '.$returnType : '', null === $description ? '.' : ': '.$description);
                        }
                    }
                }
            }
        }

        if (trait_exists($class)) {
            $file = $refl->getFileName();

            foreach ($refl->getMethods() as $method) {
                if ($method->getFileName() === $file) {
                    self::$methodTraits[$file][$method->getStartLine()] = $class;
                }
            }

            return $deprecations;
        }

        // Inherit @final, @internal, @param and @return annotations for methods
        self::$finalMethods[$class] = [];
        self::$internalMethods[$class] = [];
        self::$annotatedParameters[$class] = [];
        foreach ($parentAndOwnInterfaces as $use) {
            foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) {
                if (isset(self::${$property}[$use])) {
                    self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
                }
            }

            if (null !== (TentativeTypes::RETURN_TYPES[$use] ?? null)) {
                foreach (TentativeTypes::RETURN_TYPES[$use] as $method => $returnType) {
                    $returnType = explode('|', $returnType);
                    foreach ($returnType as $i => $t) {
                        if ('?' !== $t && !isset(self::BUILTIN_RETURN_TYPES[$t])) {
                            $returnType[$i] = '\\'.$t;
                        }
                    }
                    $returnType = implode('|', $returnType);

                    self::$returnTypes[$class] += [$method => [$returnType, 0 === strpos($returnType, '?') ? substr($returnType, 1).'|null' : $returnType, $use, '']];
                }
            }
        }

        foreach ($refl->getMethods() as $method) {
            if ($method->class !== $class) {
                continue;
            }

            if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) {
                $ns = $vendor;
                $len = $vendorLen;
            } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) {
                $len = 0;
                $ns = '';
            } else {
                $ns = str_replace('_', '\\', substr($ns, 0, $len));
            }

            if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
                [$declaringClass, $message] = self::$finalMethods[$parent][$method->name];
                $deprecations[] = sprintf('The "%s::%s()" method is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
            }

            if (isset(self::$internalMethods[$class][$method->name])) {
                [$declaringClass, $message] = self::$internalMethods[$class][$method->name];
                if (strncmp($ns, $declaringClass, $len)) {
                    $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
                }
            }

            // To read method annotations
            $doc = $this->parsePhpDoc($method);

            if (($classIsTemplate || isset($doc['template'])) && $method->hasReturnType()) {
                unset($doc['return']);
            }

            if (isset(self::$annotatedParameters[$class][$method->name])) {
                $definedParameters = [];
                foreach ($method->getParameters() as $parameter) {
                    $definedParameters[$parameter->name] = true;
                }

                foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
                    if (!isset($definedParameters[$parameterName]) && !isset($doc['param'][$parameterName])) {
                        $deprecations[] = sprintf($deprecation, $className);
                    }
                }
            }

            $forcePatchTypes = $this->patchTypes['force'];

            if ($canAddReturnType = null !== $forcePatchTypes && !str_contains($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
                if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
                    $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock';
                }

                $canAddReturnType = 2 === (int) $forcePatchTypes
                    || false !== stripos($method->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR)
                    || $refl->isFinal()
                    || $method->isFinal()
                    || $method->isPrivate()
                    || ('.' === (self::$internal[$class] ?? null) && !$refl->isAbstract())
                    || '.' === (self::$final[$class] ?? null)
                    || '' === ($doc['final'][0] ?? null)
                    || '' === ($doc['internal'][0] ?? null)
                ;
            }

            if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? null) && 'docblock' === $this->patchTypes['force'] && !$method->hasReturnType() && isset(TentativeTypes::RETURN_TYPES[$returnType[2]][$method->name])) {
                $this->patchReturnTypeWillChange($method);
            }

            if (null !== ($returnType ?? $returnType = self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) {
                [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;

                if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) {
                    $this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
                }
                if (!isset($doc['deprecated']) && strncmp($ns, $declaringClass, $len)) {
                    if ('docblock' === $this->patchTypes['force']) {
                        $this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
                    } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) {
                        $deprecations[] = sprintf('Method "%s::%s()" might add "%s" as a native return type declaration in the future. Do the same in %s "%s" now to avoid errors or add an explicit @return annotation to suppress this message.', $declaringClass, $method->name, $normalizedType, interface_exists($declaringClass) ? 'implementation' : 'child class', $className);
                    }
                }
            }

            if (!$doc) {
                $this->patchTypes['force'] = $forcePatchTypes;

                continue;
            }

            if (isset($doc['return']) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
                $this->setReturnType($doc['return'] ?? self::MAGIC_METHODS[$method->name], $method->class, $method->name, $method->getFileName(), $parent, $method->getReturnType());

                if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) {
                    $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]);
                }

                if ($method->isPrivate()) {
                    unset(self::$returnTypes[$class][$method->name]);
                }
            }

            $this->patchTypes['force'] = $forcePatchTypes;

            if ($method->isPrivate()) {
                continue;
            }

            $finalOrInternal = false;

            foreach (['final', 'internal'] as $annotation) {
                if (null !== $description = $doc[$annotation][0] ?? null) {
                    self::${$annotation.'Methods'}[$class][$method->name] = [$class, '' !== $description ? ' '.$description.(preg_match('/[[:punct:]]$/', $description) ? '' : '.') : '.'];
                    $finalOrInternal = true;
                }
            }

            if ($finalOrInternal || $method->isConstructor() || !isset($doc['param']) || StatelessInvocation::class === $class) {
                continue;
            }
            if (!isset(self::$annotatedParameters[$class][$method->name])) {
                $definedParameters = [];
                foreach ($method->getParameters() as $parameter) {
                    $definedParameters[$parameter->name] = true;
                }
            }
            foreach ($doc['param'] as $parameterName => $parameterType) {
                if (!isset($definedParameters[$parameterName])) {
                    self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className);
                }
            }
        }

        return $deprecations;
    }

    public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array
    {
        $real = explode('\\', $class.strrchr($file, '.'));
        $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));

        $i = \count($tail) - 1;
        $j = \count($real) - 1;

        while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
            --$i;
            --$j;
        }

        array_splice($tail, 0, $i + 1);

        if (!$tail) {
            return null;
        }

        $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
        $tailLen = \strlen($tail);
        $real = $refl->getFileName();

        if (2 === self::$caseCheck) {
            $real = $this->darwinRealpath($real);
        }

        if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
            && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
        ) {
            return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
        }

        return null;
    }

    /**
     * `realpath` on MacOSX doesn't normalize the case of characters.
     */
    private function darwinRealpath(string $real): string
    {
        $i = 1 + strrpos($real, '/');
        $file = substr($real, $i);
        $real = substr($real, 0, $i);

        if (isset(self::$darwinCache[$real])) {
            $kDir = $real;
        } else {
            $kDir = strtolower($real);

            if (isset(self::$darwinCache[$kDir])) {
                $real = self::$darwinCache[$kDir][0];
            } else {
                $dir = getcwd();

                if (!@chdir($real)) {
                    return $real.$file;
                }

                $real = getcwd().'/';
                chdir($dir);

                $dir = $real;
                $k = $kDir;
                $i = \strlen($dir) - 1;
                while (!isset(self::$darwinCache[$k])) {
                    self::$darwinCache[$k] = [$dir, []];
                    self::$darwinCache[$dir] = &self::$darwinCache[$k];

                    while ('/' !== $dir[--$i]) {
                    }
                    $k = substr($k, 0, ++$i);
                    $dir = substr($dir, 0, $i--);
                }
            }
        }

        $dirFiles = self::$darwinCache[$kDir][1];

        if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) {
            // Get the file name from "file_name.php(123) : eval()'d code"
            $file = substr($file, 0, strrpos($file, '(', -17));
        }

        if (isset($dirFiles[$file])) {
            return $real.$dirFiles[$file];
        }

        $kFile = strtolower($file);

        if (!isset($dirFiles[$kFile])) {
            foreach (scandir($real, 2) as $f) {
                if ('.' !== $f[0]) {
                    $dirFiles[$f] = $f;
                    if ($f === $file) {
                        $kFile = $k = $file;
                    } elseif ($f !== $k = strtolower($f)) {
                        $dirFiles[$k] = $f;
                    }
                }
            }
            self::$darwinCache[$kDir][1] = $dirFiles;
        }

        return $real.$dirFiles[$kFile];
    }

    /**
     * `class_implements` includes interfaces from the parents so we have to manually exclude them.
     *
     * @return string[]
     */
    private function getOwnInterfaces(string $class, ?string $parent): array
    {
        $ownInterfaces = class_implements($class, false);

        if ($parent) {
            foreach (class_implements($parent, false) as $interface) {
                unset($ownInterfaces[$interface]);
            }
        }

        foreach ($ownInterfaces as $interface) {
            foreach (class_implements($interface) as $interface) {
                unset($ownInterfaces[$interface]);
            }
        }

        return $ownInterfaces;
    }

    private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, \ReflectionType $returnType = null): void
    {
        if ('__construct' === $method) {
            return;
        }

        if ('null' === $types) {
            self::$returnTypes[$class][$method] = ['null', 'null', $class, $filename];

            return;
        }

        if ($nullable = 0 === strpos($types, 'null|')) {
            $types = substr($types, 5);
        } elseif ($nullable = '|null' === substr($types, -5)) {
            $types = substr($types, 0, -5);
        }
        $arrayType = ['array' => 'array'];
        $typesMap = [];
        $glue = false !== strpos($types, '&') ? '&' : '|';
        foreach (explode($glue, $types) as $t) {
            $t = self::SPECIAL_RETURN_TYPES[strtolower($t)] ?? $t;
            $typesMap[$this->normalizeType($t, $class, $parent, $returnType)][$t] = $t;
        }

        if (isset($typesMap['array'])) {
            if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) {
                $typesMap['iterable'] = $arrayType !== $typesMap['array'] ? $typesMap['array'] : ['iterable'];
                unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']);
            } elseif ($arrayType !== $typesMap['array'] && isset(self::$returnTypes[$class][$method]) && !$returnType) {
                return;
            }
        }

        if (isset($typesMap['array']) && isset($typesMap['iterable'])) {
            if ($arrayType !== $typesMap['array']) {
                $typesMap['iterable'] = $typesMap['array'];
            }
            unset($typesMap['array']);
        }

        $iterable = $object = true;
        foreach ($typesMap as $n => $t) {
            if ('null' !== $n) {
                $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || str_contains($n, 'Iterator'));
                $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n]));
            }
        }

        $phpTypes = [];
        $docTypes = [];

        foreach ($typesMap as $n => $t) {
            if ('null' === $n) {
                $nullable = true;
                continue;
            }

            $docTypes[] = $t;

            if ('mixed' === $n || 'void' === $n) {
                $nullable = false;
                $phpTypes = ['' => $n];
                continue;
            }

            if ('resource' === $n) {
                // there is no native type for "resource"
                return;
            }

            if (!isset($phpTypes[''])) {
                $phpTypes[] = $n;
            }
        }
        $docTypes = array_merge([], ...$docTypes);

        if (!$phpTypes) {
            return;
        }

        if (1 < \count($phpTypes)) {
            if ($iterable && '8.0' > $this->patchTypes['php']) {
                $phpTypes = $docTypes = ['iterable'];
            } elseif ($object && 'object' === $this->patchTypes['force']) {
                $phpTypes = $docTypes = ['object'];
            } elseif ('8.0' > $this->patchTypes['php']) {
                // ignore multi-types return declarations
                return;
            }
        }

        $phpType = sprintf($nullable ? (1 < \count($phpTypes) ? '%s|null' : '?%s') : '%s', implode($glue, $phpTypes));
        $docType = sprintf($nullable ? '%s|null' : '%s', implode($glue, $docTypes));

        self::$returnTypes[$class][$method] = [$phpType, $docType, $class, $filename];
    }

    private function normalizeType(string $type, string $class, ?string $parent, ?\ReflectionType $returnType): string
    {
        if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) {
            if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) {
                $lcType = null !== $parent ? '\\'.$parent : 'parent';
            } elseif ('self' === $lcType) {
                $lcType = '\\'.$class;
            }

            return $lcType;
        }

        // We could resolve "use" statements to return the FQDN
        // but this would be too expensive for a runtime checker

        if ('[]' !== substr($type, -2)) {
            return $type;
        }

        if ($returnType instanceof \ReflectionNamedType) {
            $type = $returnType->getName();

            if ('mixed' !== $type) {
                return isset(self::SPECIAL_RETURN_TYPES[$type]) ? $type : '\\'.$type;
            }
        }

        return 'array';
    }

    /**
     * Utility method to add #[ReturnTypeWillChange] where php triggers deprecations.
     */
    private function patchReturnTypeWillChange(\ReflectionMethod $method)
    {
        if (\count($method->getAttributes(\ReturnTypeWillChange::class))) {
            return;
        }

        if (!is_file($file = $method->getFileName())) {
            return;
        }

        $fileOffset = self::$fileOffsets[$file] ?? 0;

        $code = file($file);

        $startLine = $method->getStartLine() + $fileOffset - 2;

        if (false !== stripos($code[$startLine], 'ReturnTypeWillChange')) {
            return;
        }

        $code[$startLine] .= "    #[\\ReturnTypeWillChange]\n";
        self::$fileOffsets[$file] = 1 + $fileOffset;
        file_put_contents($file, $code);
    }

    /**
     * Utility method to add @return annotations to the Symfony code-base where it triggers self-deprecations.
     */
    private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType)
    {
        static $patchedMethods = [];
        static $useStatements = [];

        if (!is_file($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) {
            return;
        }

        $patchedMethods[$file][$startLine] = true;
        $fileOffset = self::$fileOffsets[$file] ?? 0;
        $startLine += $fileOffset - 2;
        if ($nullable = '|null' === substr($returnType, -5)) {
            $returnType = substr($returnType, 0, -5);
        }
        $glue = false !== strpos($returnType, '&') ? '&' : '|';
        $returnType = explode($glue, $returnType);
        $code = file($file);

        foreach ($returnType as $i => $type) {
            if (preg_match('/((?:\[\])+)$/', $type, $m)) {
                $type = substr($type, 0, -\strlen($m[1]));
                $format = '%s'.$m[1];
            } else {
                $format = null;
            }

            if (isset(self::SPECIAL_RETURN_TYPES[$type]) || ('\\' === $type[0] && !$p = strrpos($type, '\\', 1))) {
                continue;
            }

            [$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file);

            if ('\\' !== $type[0]) {
                [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile);

                $p = strpos($type, '\\', 1);
                $alias = $p ? substr($type, 0, $p) : $type;

                if (isset($declaringUseMap[$alias])) {
                    $type = '\\'.$declaringUseMap[$alias].($p ? substr($type, $p) : '');
                } else {
                    $type = '\\'.$declaringNamespace.$type;
                }

                $p = strrpos($type, '\\', 1);
            }

            $alias = substr($type, 1 + $p);
            $type = substr($type, 1);

            if (!isset($useMap[$alias]) && (class_exists($c = $namespace.$alias) || interface_exists($c) || trait_exists($c))) {
                $useMap[$alias] = $c;
            }

            if (!isset($useMap[$alias])) {
                $useStatements[$file][2][$alias] = $type;
                $code[$useOffset] = "use $type;\n".$code[$useOffset];
                ++$fileOffset;
            } elseif ($useMap[$alias] !== $type) {
                $alias .= 'FIXME';
                $useStatements[$file][2][$alias] = $type;
                $code[$useOffset] = "use $type as $alias;\n".$code[$useOffset];
                ++$fileOffset;
            }

            $returnType[$i] = null !== $format ? sprintf($format, $alias) : $alias;
        }

        if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) {
            $returnType = implode($glue, $returnType).($nullable ? '|null' : '');

            if (false !== strpos($code[$startLine], '#[')) {
                --$startLine;
            }

            if ($method->getDocComment()) {
                $code[$startLine] = "     * @return $returnType\n".$code[$startLine];
            } else {
                $code[$startLine] .= <<<EOTXT
    /**
     * @return $returnType
     */

EOTXT;
            }

            $fileOffset += substr_count($code[$startLine], "\n") - 1;
        }

        self::$fileOffsets[$file] = $fileOffset;
        file_put_contents($file, $code);

        $this->fixReturnStatements($method, $normalizedType);
    }

    private static function getUseStatements(string $file): array
    {
        $namespace = '';
        $useMap = [];
        $useOffset = 0;

        if (!is_file($file)) {
            return [$namespace, $useOffset, $useMap];
        }

        $file = file($file);

        for ($i = 0; $i < \count($file); ++$i) {
            if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) {
                break;
            }

            if (str_starts_with($file[$i], 'namespace ')) {
                $namespace = substr($file[$i], \strlen('namespace '), -2).'\\';
                $useOffset = $i + 2;
            }

            if (str_starts_with($file[$i], 'use ')) {
                $useOffset = $i;

                for (; str_starts_with($file[$i], 'use '); ++$i) {
                    $u = explode(' as ', substr($file[$i], 4, -2), 2);

                    if (1 === \count($u)) {
                        $p = strrpos($u[0], '\\');
                        $useMap[substr($u[0], false !== $p ? 1 + $p : 0)] = $u[0];
                    } else {
                        $useMap[$u[1]] = $u[0];
                    }
                }

                break;
            }
        }

        return [$namespace, $useOffset, $useMap];
    }

    private function fixReturnStatements(\ReflectionMethod $method, string $returnType)
    {
        if ('docblock' !== $this->patchTypes['force']) {
            if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?')) {
                return;
            }

            if ('7.4' > $this->patchTypes['php'] && $method->hasReturnType()) {
                return;
            }

            if ('8.0' > $this->patchTypes['php'] && (false !== strpos($returnType, '|') || \in_array($returnType, ['mixed', 'static'], true))) {
                return;
            }

            if ('8.1' > $this->patchTypes['php'] && false !== strpos($returnType, '&')) {
                return;
            }
        }

        if (!is_file($file = $method->getFileName())) {
            return;
        }

        $fixedCode = $code = file($file);
        $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine();

        if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) {
            $fixedCode[$i - 1] = preg_replace('/\)(?::[^;\n]++)?(;?\n)/', "): $returnType\\1", $code[$i - 1]);
        }

        $end = $method->isGenerator() ? $i : $method->getEndLine();
        for (; $i < $end; ++$i) {
            if ('void' === $returnType) {
                $fixedCode[$i] = str_replace('    return null;', '    return;', $code[$i]);
            } elseif ('mixed' === $returnType || '?' === $returnType[0]) {
                $fixedCode[$i] = str_replace('    return;', '    return null;', $code[$i]);
            } else {
                $fixedCode[$i] = str_replace('    return;', "    return $returnType!?;", $code[$i]);
            }
        }

        if ($fixedCode !== $code) {
            file_put_contents($file, $fixedCode);
        }
    }

    /**
     * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector
     */
    private function parsePhpDoc(\Reflector $reflector): array
    {
        if (!$doc = $reflector->getDocComment()) {
            return [];
        }

        $tagName = '';
        $tagContent = '';

        $tags = [];

        foreach (explode("\n", substr($doc, 3, -2)) as $line) {
            $line = ltrim($line);
            $line = ltrim($line, '*');

            if ('' === $line = trim($line)) {
                if ('' !== $tagName) {
                    $tags[$tagName][] = $tagContent;
                }
                $tagName = $tagContent = '';
                continue;
            }

            if ('@' === $line[0]) {
                if ('' !== $tagName) {
                    $tags[$tagName][] = $tagContent;
                    $tagContent = '';
                }

                if (preg_match('{^@([-a-zA-Z0-9_:]++)(\s|$)}', $line, $m)) {
                    $tagName = $m[1];
                    $tagContent = str_replace("\t", ' ', ltrim(substr($line, 2 + \strlen($tagName))));
                } else {
                    $tagName = '';
                }
            } elseif ('' !== $tagName) {
                $tagContent .= ' '.str_replace("\t", ' ', $line);
            }
        }

        if ('' !== $tagName) {
            $tags[$tagName][] = $tagContent;
        }

        foreach ($tags['method'] ?? [] as $i => $method) {
            unset($tags['method'][$i]);

            $parts = preg_split('{(\s++|\((?:[^()]*+|(?R))*\)(?: *: *[^ ]++)?|<(?:[^<>]*+|(?R))*>|\{(?:[^{}]*+|(?R))*\})}', $method, -1, \PREG_SPLIT_DELIM_CAPTURE);
            $returnType = '';
            $static = 'static' === $parts[0];

            for ($i = $static ? 2 : 0; null !== $p = $parts[$i] ?? null; $i += 2) {
                if (\in_array($p, ['', '|', '&', 'callable'], true) || \in_array(substr($returnType, -1), ['|', '&'], true)) {
                    $returnType .= trim($parts[$i - 1] ?? '').$p;
                    continue;
                }

                $signature = '(' === ($parts[$i + 1][0] ?? '(') ? $parts[$i + 1] ?? '()' : null;

                if (null === $signature && '' === $returnType) {
                    $returnType = $p;
                    continue;
                }

                if ($static && 2 === $i) {
                    $static = false;
                    $returnType = 'static';
                }

                if (\in_array($description = trim(implode('', \array_slice($parts, 2 + $i))), ['', '.'], true)) {
                    $description = null;
                } elseif (!preg_match('/[.!]$/', $description)) {
                    $description .= '.';
                }

                $tags['method'][$p] = [$static, $returnType, $signature ?? '()', $description];
                break;
            }
        }

        foreach ($tags['param'] ?? [] as $i => $param) {
            unset($tags['param'][$i]);

            if (\strlen($param) !== strcspn($param, '<{(')) {
                $param = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $param);
            }

            if (false === $i = strpos($param, '$')) {
                continue;
            }

            $type = 0 === $i ? '' : rtrim(substr($param, 0, $i), ' &');
            $param = substr($param, 1 + $i, (strpos($param, ' ', $i) ?: (1 + $i + \strlen($param))) - $i - 1);

            $tags['param'][$param] = $type;
        }

        foreach (['var', 'return'] as $k) {
            if (null === $v = $tags[$k][0] ?? null) {
                continue;
            }
            if (\strlen($v) !== strcspn($v, '<{(')) {
                $v = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $v);
            }

            $tags[$k] = substr($v, 0, strpos($v, ' ') ?: \strlen($v)) ?: null;
        }

        return $tags;
    }
}
Kueue Pay | Contactless Payment System
top

Quick Steps to NFC Pay

Getting started with NFC Pay is simple and quick. Register your account, add your cards, and you're ready to make payments in no time. Whether you're paying at a store, sending money to a friend, or managing your merchant transactions, NFC Pay makes it easy and secure.

1

Register Your Account

Download the NFC Pay app and sign up with your email or phone number. Complete the registration process by verifying your identity, and set up your secure PIN to protect your account.

2

Add Your Cards

Link your debit or credit cards to your NFC Pay wallet. Simply scan your card or enter the details manually, and you’re set to load funds, shop, and pay with ease.

3

Make Payment

To pay, simply tap your phone or scan the QR code at checkout. You can also transfer money to other users with a few taps. Enjoy fast, contactless payments with top-notch security.

Advanced Security Features Designed to Protect Your Information Effectively

NFC Pay prioritizes your security with advanced features that safeguard every transaction. From SMS or email verification to end-to-end encryption, we've implemented robust measures to ensure your data is always protected. Our security systems are designed to prevent unauthorized access and provide you with a safe and reliable payment experience.

img

SMS or Email Verification

Receive instant alerts for every transaction to keep track of your account activities.

img

KYC Solution

Verify your identity through our Know Your Customer process to prevent fraud and enhance security.

img

Two Factor Authentication

Dramatically supply transparent backward deliverables before caward comp internal or "organic" sources.

img

End-to-End Encryption

All your data and transactions are encrypted, ensuring that your sensitive information remains private.

img

Behavior Tracking

Monitor unusual activity patterns to detect and prevent suspicious behavior in real-time.

Top Reasons to Choose Us for Reliable and Expert Solutions

With NFC Pay, you get a trusted platform backed by proven expertise and a commitment to quality. We put our customers first, offering innovative solutions tailored to your needs, ensuring every transaction is secure, swift, and seamless.

1

Proven Expertise

Our team brings years of experience in the digital payments industry to provide reliable services.

2

Commitment to Quality

We prioritize excellence, ensuring that every aspect of our platform meets the highest standards.

3

Customer-Centric Approach

Your needs drive our solutions, and we are dedicated to delivering a superior user experience.

4

Innovative Solutions

We continuously evolve, integrating the latest technologies to enhance your payment experience.

Customer Feedback: Real Experiences from Satisfied Clients and Partners

Hear from our users who trust NFC Pay for their everyday transactions. Our commitment to security, ease of use, and exceptional service shines through in their experiences. See why our clients choose NFC Pay for their payment needs and how it has transformed the way they manage their finances.

"NFC Pay has made my transactions incredibly simple and secure. The intuitive interface and quick payment options are game-changers for my business"

"I love how NFC Pay prioritizes security without compromising on convenience. The two-factor authentication and instant alerts give me peace of mind every time I use it."

"Setting up my merchant account was a breeze, and now I can accept payments effortlessly. NFC Pay has truly streamlined my operations, saving me time and hassle."

Get the NFC Pay App for Seamless Transactions Anytime, Anywhere

Unlock the full potential of NFC Pay by downloading our app, designed to bring secure, swift, and smart transactions to your fingertips. Whether you're paying at a store, transferring money to friends, or managing your business payments, the NFC Pay app makes it effortless. Available on both iOS and Android, it's your all-in-one solution for convenient and reliable digital payments. Download now and experience the future of payments!

img