LogicException
Redis PHP extension has not been installed LogicException thrown with message "Redis PHP extension has not been installed" Stacktrace: #12 LogicException in /var/www/vespa-t5.org/system/src/Grav/Common/Cache.php:324 #11 Grav\Common\Cache:getCacheDriver in /var/www/vespa-t5.org/system/src/Grav/Common/Cache.php:147 #10 Grav\Common\Cache:init in /var/www/vespa-t5.org/system/src/Grav/Common/Cache.php:119 #9 Grav\Common\Cache:__construct in /var/www/vespa-t5.org/system/src/Grav/Common/Grav.php:738 #8 Grav\Common\Grav:Grav\Common\{closure} in /var/www/vespa-t5.org/vendor/pimple/pimple/src/Pimple/Container.php:122 #7 Pimple\Container:offsetGet in /var/www/vespa-t5.org/user/plugins/problems/classes/Problems/Base/ProblemChecker.php:26 #6 Grav\Plugin\Problems\Base\ProblemChecker:__construct in /var/www/vespa-t5.org/user/plugins/problems/problems.php:165 #5 Grav\Plugin\ProblemsPlugin:problemsFound in /var/www/vespa-t5.org/user/plugins/problems/problems.php:60 #4 Grav\Plugin\ProblemsPlugin:onFatalException in /var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php:264 #3 Symfony\Component\EventDispatcher\EventDispatcher:doDispatch in /var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php:239 #2 Symfony\Component\EventDispatcher\EventDispatcher:callListeners in /var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php:73 #1 Symfony\Component\EventDispatcher\EventDispatcher:dispatch in /var/www/vespa-t5.org/system/src/Grav/Common/Grav.php:597 #0 Grav\Common\Grav:fireEvent in /var/www/vespa-t5.org/index.php:49
Stack frames (13)
12
LogicException
/system/src/Grav/Common/Cache.php324
11
Grav\Common\Cache getCacheDriver
/system/src/Grav/Common/Cache.php147
10
Grav\Common\Cache init
/system/src/Grav/Common/Cache.php119
9
Grav\Common\Cache __construct
/system/src/Grav/Common/Grav.php738
8
Grav\Common\Grav Grav\Common\{closure}
/vendor/pimple/pimple/src/Pimple/Container.php122
7
Pimple\Container offsetGet
/user/plugins/problems/classes/Problems/Base/ProblemChecker.php26
6
Grav\Plugin\Problems\Base\ProblemChecker __construct
/user/plugins/problems/problems.php165
5
Grav\Plugin\ProblemsPlugin problemsFound
/user/plugins/problems/problems.php60
4
Grav\Plugin\ProblemsPlugin onFatalException
/vendor/symfony/event-dispatcher/EventDispatcher.php264
3
Symfony\Component\EventDispatcher\EventDispatcher doDispatch
/vendor/symfony/event-dispatcher/EventDispatcher.php239
2
Symfony\Component\EventDispatcher\EventDispatcher callListeners
/vendor/symfony/event-dispatcher/EventDispatcher.php73
1
Symfony\Component\EventDispatcher\EventDispatcher dispatch
/system/src/Grav/Common/Grav.php597
0
Grav\Common\Grav fireEvent
/index.php49
/var/www/vespa-t5.org/system/src/Grav/Common/Cache.php
                        $redis->connect(
                            $this->config->get('system.cache.redis.server', 'localhost'),
                            $this->config->get('system.cache.redis.port', 6379)
                        );
                    }
 
                    // Authenticate with password if set
                    if ($password && !$redis->auth($password)) {
                        throw new \RedisException('Redis authentication failed');
                    }
 
                    // Select alternate ( !=0 ) database ID if set
                    if ($databaseId && !$redis->select($databaseId)) {
                        throw new \RedisException('Could not select alternate Redis database ID');
                    }
 
                    $driver = new DoctrineCache\RedisCache();
                    $driver->setRedis($redis);
                } else {
                    throw new LogicException('Redis PHP extension has not been installed');
                }
                break;
 
            default:
                $driver = new DoctrineCache\FilesystemCache($this->cache_dir);
                break;
        }
 
        return $driver;
    }
 
    /**
     * Gets a cached entry if it exists based on an id. If it does not exist, it returns false
     *
     * @param  string $id the id of the cached entry
     * @return mixed|bool     returns the cached entry, can be any type, or false if doesn't exist
     */
    public function fetch($id)
    {
        if ($this->enabled) {
Arguments
  1. "Redis PHP extension has not been installed"
    
/var/www/vespa-t5.org/system/src/Grav/Common/Cache.php
    public function init(Grav $grav)
    {
        $this->config = $grav['config'];
        $this->now = time();
 
        if (null === $this->enabled) {
            $this->enabled = (bool)$this->config->get('system.cache.enabled');
        }
 
        /** @var Uri $uri */
        $uri = $grav['uri'];
 
        $prefix = $this->config->get('system.cache.prefix');
        $uniqueness = substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
 
        // Cache key allows us to invalidate all cache on configuration changes.
        $this->key = ($prefix ?: 'g') . '-' . $uniqueness;
        $this->cache_dir = $grav['locator']->findResource('cache://doctrine/' . $uniqueness, true, true);
        $this->driver_setting = $this->config->get('system.cache.driver');
        $this->driver = $this->getCacheDriver();
        $this->driver->setNamespace($this->key);
 
        /** @var EventDispatcher $dispatcher */
        $dispatcher = Grav::instance()['events'];
        $dispatcher->addListener('onSchedulerInitialized', [$this, 'onSchedulerInitialized']);
    }
 
    /**
     * @return CacheInterface
     */
    public function getSimpleCache()
    {
        if (null === $this->simpleCache) {
            $cache = new \Grav\Framework\Cache\Adapter\DoctrineCache($this->driver, '', $this->getLifetime());
 
            // Disable cache key validation.
            $cache->setValidation(false);
 
            $this->simpleCache = $cache;
        }
/var/www/vespa-t5.org/system/src/Grav/Common/Cache.php
    protected static $images_remove = [
        'cache://images'
    ];
 
    protected static $cache_remove = [
        'cache://'
    ];
 
    protected static $tmp_remove = [
        'tmp://'
    ];
 
    /**
     * Constructor
     *
     * @param Grav $grav
     */
    public function __construct(Grav $grav)
    {
        $this->init($grav);
    }
 
    /**
     * Initialization that sets a base key and the driver based on configuration settings
     *
     * @param  Grav $grav
     * @return void
     */
    public function init(Grav $grav)
    {
        $this->config = $grav['config'];
        $this->now = time();
 
        if (null === $this->enabled) {
            $this->enabled = (bool)$this->config->get('system.cache.enabled');
        }
 
        /** @var Uri $uri */
        $uri = $grav['uri'];
 
/var/www/vespa-t5.org/system/src/Grav/Common/Grav.php
 
        return $container;
    }
 
    /**
     * Register all services
     * Services are defined in the diMap. They can either only the class
     * of a Service Provider or a pair of serviceKey => serviceClass that
     * gets directly mapped into the container.
     *
     * @return void
     */
    protected function registerServices(): void
    {
        foreach (self::$diMap as $serviceKey => $serviceClass) {
            if (is_int($serviceKey)) {
                $this->register(new $serviceClass);
            } else {
                $this[$serviceKey] = function ($c) use ($serviceClass) {
                    return new $serviceClass($c);
                };
            }
        }
    }
 
    /**
     * This attempts to find media, other files, and download them
     *
     * @param string $path
     * @return PageInterface|false
     */
    public function fallbackUrl($path)
    {
        $path_parts = Utils::pathinfo($path);
        if (!is_array($path_parts)) {
            return false;
        }
 
        /** @var Uri $uri */
        $uri = $this['uri'];
/var/www/vespa-t5.org/vendor/pimple/pimple/src/Pimple/Container.php
    {
        if (!isset($this->keys[$id])) {
            throw new UnknownIdentifierException($id);
        }
 
        if (
            isset($this->raw[$id])
            || !\is_object($this->values[$id])
            || isset($this->protected[$this->values[$id]])
            || !\method_exists($this->values[$id], '__invoke')
        ) {
            return $this->values[$id];
        }
 
        if (isset($this->factories[$this->values[$id]])) {
            return $this->values[$id]($this);
        }
 
        $raw = $this->values[$id];
        $val = $this->values[$id] = $raw($this);
        $this->raw[$id] = $raw;
 
        $this->frozen[$id] = true;
 
        return $val;
    }
 
    /**
     * Checks if a parameter or an object is set.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return bool
     */
    #[\ReturnTypeWillChange]
    public function offsetExists($id)
    {
        return isset($this->keys[$id]);
    }
 
/var/www/vespa-t5.org/user/plugins/problems/classes/Problems/Base/ProblemChecker.php
use RocketTheme\Toolbox\Event\Event;
 
/**
 * Class ProblemChecker
 * @package Grav\Plugin\Problems\Base
 */
class ProblemChecker
{
    /** @var string */
    const PROBLEMS_PREFIX = 'problem-check-';
 
    /** @var array */
    protected $problems = [];
    /** @var string */
    protected $status_file;
 
    public function __construct()
    {
        /** @var Cache $cache */
        $cache = Grav::instance()['cache'];
        $this->status_file = CACHE_DIR . $this::PROBLEMS_PREFIX . $cache->getKey() . '.json';
    }
 
    /**
     * @return bool
     */
    public function load(): bool
    {
        if ($this->statusFileExists()) {
            $json = file_get_contents($this->status_file) ?: '';
            $data = json_decode($json, true);
            if (!is_array($data)) {
                return false;
            }
 
            foreach ($data as $problem) {
                $class = $problem['class'];
                $this->problems[] = new $class($problem);
            }
        }
/var/www/vespa-t5.org/user/plugins/problems/problems.php
 
        $data = [
            'problems' => $this->problems,
            'base_url' => $baseUrlRelative = $uri->rootUrl(false),
            'problems_url' => $baseUrlRelative . '/user/plugins/problems',
        ];
 
        $reports['Grav Potential Problems'] = $twig->render('reports/problems-report.html.twig', $data);
 
        $this->grav['assets']->addCss('plugins://problems/css/admin.css');
        $this->grav['assets']->addCss('plugins://problems/css/spectre-icons.css');
    }
 
    /**
     * @return bool
     */
    private function problemsFound(): bool
    {
        if (null === $this->checker) {
            $this->checker = new ProblemChecker();
        }
 
        $status = $this->checker->check(__DIR__ . '/classes/Problems');
        $this->problems = $this->checker->getProblems();
        
        return $status;
    }
 
    /**
     * @return Environment
     */
    private function getTwig(): Environment
    {
        $loader = new FilesystemLoader(__DIR__ . '/templates');
        $twig = new Environment($loader, ['debug' => true]);
        $twig->addExtension(New DebugExtension());
 
        return $twig;
    }
}
/var/www/vespa-t5.org/user/plugins/problems/problems.php
     * [onPluginsInitialized:100000] Composer autoload.
     *
     * @return ClassLoader
     */
    public function autoload(): ClassLoader
    {
        return require __DIR__ . '/vendor/autoload.php';
    }
 
    /**
     * @return void
     */
    public function onFatalException(): void
    {
        if (\defined('GRAV_CLI') || $this->isAdmin()) {
            return;
        }
 
        // Run through potential issues
        if ($this->problemsFound()) {
            $this->renderProblems();
        }
    }
 
    /**
     * Add Flex-Object's preset.scss to the Admin Preset SCSS compile process
     *
     * @param Event $event
     */
    public function onAdminCompilePresetSCSS(Event $event): void
    {
        $event['scss']->add($this->grav['locator']->findResource('plugins://problems/scss/_preset.scss'));
    }
 
    /**
     * @return void
     */
    public function onPluginsInitialized(): void
    {
        if (\defined('GRAV_CLI') || $this->isAdmin()) {
/var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php
 
        foreach ($listeners as $listener) {
            if ($stoppable && $event->isPropagationStopped()) {
                break;
            }
            // @deprecated: the ternary operator is part of a BC layer and should be removed in 5.0
            $listener($listener instanceof WrappedListener ? new LegacyEventProxy($event) : $event, $eventName, $this);
        }
    }
 
    /**
     * @deprecated since Symfony 4.3, use callListeners() instead
     */
    protected function doDispatch($listeners, $eventName, Event $event)
    {
        foreach ($listeners as $listener) {
            if ($event->isPropagationStopped()) {
                break;
            }
            $listener($event, $eventName, $this);
        }
    }
 
    /**
     * Sorts the internal list of listeners for the given event by priority.
     */
    private function sortListeners(string $eventName)
    {
        krsort($this->listeners[$eventName]);
        $this->sorted[$eventName] = [];
 
        foreach ($this->listeners[$eventName] as &$listeners) {
            foreach ($listeners as $k => &$listener) {
                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
                    $listener[0] = $listener[0]();
                    $listener[1] = $listener[1] ?? '__invoke';
                }
                $this->sorted[$eventName][] = $listener;
            }
        }
/var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php
            } else {
                $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]);
            }
        }
    }
 
    /**
     * Triggers the listeners of an event.
     *
     * This method can be overridden to add functionality that is executed
     * for each listener.
     *
     * @param callable[] $listeners The event listeners
     * @param string     $eventName The name of the event to dispatch
     * @param object     $event     The event object to pass to the event handlers/listeners
     */
    protected function callListeners(iterable $listeners, string $eventName, $event)
    {
        if ($event instanceof Event) {
            $this->doDispatch($listeners, $eventName, $event);
 
            return;
        }
 
        $stoppable = $event instanceof ContractsEvent || $event instanceof StoppableEventInterface;
 
        foreach ($listeners as $listener) {
            if ($stoppable && $event->isPropagationStopped()) {
                break;
            }
            // @deprecated: the ternary operator is part of a BC layer and should be removed in 5.0
            $listener($listener instanceof WrappedListener ? new LegacyEventProxy($event) : $event, $eventName, $this);
        }
    }
 
    /**
     * @deprecated since Symfony 4.3, use callListeners() instead
     */
    protected function doDispatch($listeners, $eventName, Event $event)
    {
/var/www/vespa-t5.org/vendor/symfony/event-dispatcher/EventDispatcher.php
 
        if (\is_object($event)) {
            $eventName = $eventName ?? \get_class($event);
        } elseif (\is_string($event) && (null === $eventName || $eventName instanceof ContractsEvent || $eventName instanceof Event)) {
            @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', EventDispatcherInterface::class), \E_USER_DEPRECATED);
            $swap = $event;
            $event = $eventName ?? new Event();
            $eventName = $swap;
        } else {
            throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, "%s" given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
        }
 
        if (null !== $this->optimized && null !== $eventName) {
            $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName));
        } else {
            $listeners = $this->getListeners($eventName);
        }
 
        if ($listeners) {
            $this->callListeners($listeners, $eventName, $event);
        }
 
        return $event;
    }
 
    /**
     * {@inheritdoc}
     */
    public function getListeners($eventName = null)
    {
        if (null !== $eventName) {
            if (empty($this->listeners[$eventName])) {
                return [];
            }
 
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }
 
            return $this->sorted[$eventName];
/var/www/vespa-t5.org/system/src/Grav/Common/Grav.php
        return $event;
    }
 
    /**
     * Fires an event with optional parameters.
     *
     * @param  string $eventName
     * @param  Event|null $event
     * @return Event
     */
    public function fireEvent($eventName, Event $event = null)
    {
        /** @var EventDispatcherInterface $events */
        $events = $this['events'];
        if (null === $event) {
            $event = new Event();
        }
 
        $timestamp = microtime(true);
        $events->dispatch($event, $eventName);
 
        /** @var Debugger $debugger */
        $debugger = $this['debugger'];
        $debugger->addEvent($eventName, $event, $events, $timestamp);
 
        return $event;
    }
 
    /**
     * Set the final content length for the page and flush the buffer
     *
     * @return void
     */
    public function shutdown(): void
    {
        // Prevent user abort allowing onShutdown event to run without interruptions.
        if (function_exists('ignore_user_abort')) {
            @ignore_user_abort(true);
        }
 
/var/www/vespa-t5.org/index.php
$loader = require $autoload;
 
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
 
// Set internal encoding.
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');
 
use Grav\Common\Grav;
use RocketTheme\Toolbox\Event\Event;
 
// Get the Grav instance
$grav = Grav::instance(array('loader' => $loader));
 
// Process the page
try {
    $grav->process();
} catch (\Error|\Exception $e) {
    $grav->fireEvent('onFatalException', new Event(array('exception' => $e)));
    throw $e;
}
 

Environment & details:

empty
empty
empty
empty
empty
Key Value
PATH
"/usr/local/bin:/usr/bin:/bin"
USER
"www-data"
HOME
"/var/www"
HTTP_REFERER
"https://www.vespa-t5.org/meine-roller/die-gelbe-t5/"
HTTP_USER_AGENT
"claudebot"
HTTP_ACCEPT
"*/*"
HTTP_HOST
"www.vespa-t5.org"
PHP_VALUE
"open_basedir="/tmp/:/var/lib/php/:/var/www/vespa-t5.org/""
SCRIPT_FILENAME
"/var/www/vespa-t5.org/index.php"
SSL_CLIENT_VERIFY
"NONE"
SSL_CIPHER
"TLS_AES_256_GCM_SHA384"
SSL_SESSION_ID
"86fb70679407d7653032227ba6c40185d0fe0632a7f789dcb444d200b322db8b"
SSL_PROTOCOL
"TLSv1.3"
REDIRECT_STATUS
"200"
SERVER_NAME
"vespa-t5.org"
SERVER_PORT
"443"
SERVER_ADDR
"152.53.15.160"
REMOTE_USER
""
REMOTE_PORT
"33874"
REMOTE_ADDR
"23.20.220.59"
SERVER_SOFTWARE
"nginx/1.22.1"
GATEWAY_INTERFACE
"CGI/1.1"
HTTPS
"on"
REQUEST_SCHEME
"https"
SERVER_PROTOCOL
"HTTP/2.0"
DOCUMENT_ROOT
"/var/www/vespa-t5.org"
DOCUMENT_URI
"/index.php"
REQUEST_URI
"/meine-roller/die-gelbe-t5"
SCRIPT_NAME
"/index.php"
CONTENT_LENGTH
""
CONTENT_TYPE
""
REQUEST_METHOD
"GET"
QUERY_STRING
""
FCGI_ROLE
"RESPONDER"
PHP_SELF
"/index.php"
REQUEST_TIME_FLOAT
1710830999.7329
REQUEST_TIME
1710830999
empty
0. Whoops\Handler\PrettyPageHandler
1. Whoops\Handler\CallbackHandler