Error
Call to undefined method Skeleton\I18n\Translator\Extractor\Twig::add_template_path() Error thrown with message "Call to undefined method Skeleton\I18n\Translator\Extractor\Twig::add_template_path()" Stacktrace: #12 Error in /var/www/admin.tickoweb.be/app/delivery/event/I18n.php:26 #11 App\Delivery\Event\I18n:get_translator_extractor in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:185 #10 call_user_func_array in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:185 #9 Skeleton\Core\Application:call_event in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web/Event/I18n.php:58 #8 Skeleton\Application\Web\Event\I18n:get_translator in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:185 #7 call_user_func_array in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:185 #6 Skeleton\Core\Application:call_event in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web.php:274 #5 Skeleton\Application\Web:get_details in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:104 #4 Skeleton\Core\Application:__construct in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:402 #3 Skeleton\Core\Application:get_by_name in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:387 #2 Skeleton\Core\Application:get_all in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php:277 #1 Skeleton\Core\Application:detect in /var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Http/Handler.php:66 #0 Skeleton\Core\Http\Handler:run in /var/www/admin.tickoweb.be/webroot/handler.php:18
Stack frames (13)
12
Error
/var/www/admin.tickoweb.be/app/delivery/event/I18n.php26
11
App\Delivery\Event\I18n get_translator_extractor
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php185
10
call_user_func_array
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php185
9
Skeleton\Core\Application call_event
/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web/Event/I18n.php58
8
Skeleton\Application\Web\Event\I18n get_translator
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php185
7
call_user_func_array
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php185
6
Skeleton\Core\Application call_event
/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web.php274
5
Skeleton\Application\Web get_details
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php104
4
Skeleton\Core\Application __construct
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php402
3
Skeleton\Core\Application get_by_name
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php387
2
Skeleton\Core\Application get_all
/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php277
1
Skeleton\Core\Application detect
/packages/tigron/skeleton-core/lib/Skeleton/Core/Http/Handler.php66
0
Skeleton\Core\Http\Handler run
/var/www/admin.tickoweb.be/webroot/handler.php18
/var/www/admin.tickoweb.be/app/delivery/event/I18n.php
 * @author David Vandemaele <david@tigron.be>
 */
 
namespace App\Delivery\Event;
 
class I18n extends \Skeleton\Application\Web\Event\I18n {
 
    /**
     * Get the translator extractor for this app
     *
     * @access public
     * @return \Skeleton\I18n\Translator\Extractor $extractor
     */
    public function get_translator_extractor(): \Skeleton\I18n\Translator\Extractor {
        // Twig templates are the default for a skeleton app
        if (!file_exists($this->application->path . '/skin')) {
            throw new \Exception('Cannot get translator_extractor, template path does not exist');
        }
        $translator_extractor_twig = new \Skeleton\I18n\Translator\Extractor\Twig();
        $translator_extractor_twig->add_template_path($this->application->path . '/skin');
        $config = \Skeleton\Core\Config::get();
        $translator_extractor_twig->add_template_path($config->external_tickoweb_path . '/skinv2/template/');
        return $translator_extractor_twig;
    }
 
 
    /**
     * Get the translator storage for this app
     *
     * @access public
     * @return \Skeleton\I18n\Translator\Storage $storage
     */
    public function get_translator_storage(): \Skeleton\I18n\Translator\Storage {
        $storage = new \Dictionary_Storage();
 
        /**
         * If no channel is set we fallback to root dictionary
         * Note: Translator_Storage is requested on Application::get_all()
         * however, channel is only set on event Module::bootstrap.
         * Because of this, you will find a refresh of the request to
Arguments
  1. "Call to undefined method Skeleton\I18n\Translator\Extractor\Twig::add_template_path()"
    
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
                return $this->events[strtolower($context)];
            }
 
            $event = new $default($this);
            $this->events[strtolower($context)] = $event;
            return $this->events[strtolower($context)];
        }
 
        throw new \Exception('There is no event found for context ' . $requested_context);
    }
 
    /**
     * Call event
     *
     * @access public
     * @param $arguments mixed[]
     */
    public function call_event(string $context, string $action, array $arguments = []): mixed {
        $event = $this->load_event($context);
        return call_user_func_array([$event, $action], $arguments);
    }
 
    /**
     * Event exists
     *
     * @access public
     */
    public function event_exists(string $context, string $action): bool {
        try {
            $event = $this->load_event($context);
        } catch (\Exception $e) {
            return false;
        }
 
        if (is_callable([$event, $action])) {
            return true;
        }
 
        return false;
    }
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
                return $this->events[strtolower($context)];
            }
 
            $event = new $default($this);
            $this->events[strtolower($context)] = $event;
            return $this->events[strtolower($context)];
        }
 
        throw new \Exception('There is no event found for context ' . $requested_context);
    }
 
    /**
     * Call event
     *
     * @access public
     * @param $arguments mixed[]
     */
    public function call_event(string $context, string $action, array $arguments = []): mixed {
        $event = $this->load_event($context);
        return call_user_func_array([$event, $action], $arguments);
    }
 
    /**
     * Event exists
     *
     * @access public
     */
    public function event_exists(string $context, string $action): bool {
        try {
            $event = $this->load_event($context);
        } catch (\Exception $e) {
            return false;
        }
 
        if (is_callable([$event, $action])) {
            return true;
        }
 
        return false;
    }
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web/Event/I18n.php
    public function get_translator_storage(): \Skeleton\I18n\Translator\Storage {
        $default_configuration = \Skeleton\I18n\Translator\Storage\Po::get_default_configuration();
 
        if (!isset($default_configuration['storage_path'])) {
            throw new \Exception('No po storage path defined, cannot setup translation');
        }
 
        return new \Skeleton\I18n\Translator\Storage\Po();
    }
 
    /**
     * Get translator
     *
     * @access public
     * @return \Skeleton\I18n\Translator $translator
     */
    public function get_translator(): ?\Skeleton\I18n\Translator {
        try {
            $translator_storage = $this->application->call_event('i18n', 'get_translator_storage');
            $translator_extractor = $this->application->call_event('i18n', 'get_translator_extractor');
        } catch (\Exception $e) {
            return null;
        }
 
        $translator = new \Skeleton\I18n\Translator($this->application->name);
        $translator->set_translator_storage($translator_storage);
        $translator->set_translator_extractor($translator_extractor);
        return $translator;
    }
 
    /**
     * Detect the language
     *
     * @access public
     * @return \Skeleton\I18n\LanguageInterface $language
     */
    public function detect_language(): \Skeleton\I18n\LanguageInterface {
        $language_interface = \Skeleton\I18n\Config::$language_interface;
 
        // Check for requested language in $_GET
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
                return $this->events[strtolower($context)];
            }
 
            $event = new $default($this);
            $this->events[strtolower($context)] = $event;
            return $this->events[strtolower($context)];
        }
 
        throw new \Exception('There is no event found for context ' . $requested_context);
    }
 
    /**
     * Call event
     *
     * @access public
     * @param $arguments mixed[]
     */
    public function call_event(string $context, string $action, array $arguments = []): mixed {
        $event = $this->load_event($context);
        return call_user_func_array([$event, $action], $arguments);
    }
 
    /**
     * Event exists
     *
     * @access public
     */
    public function event_exists(string $context, string $action): bool {
        try {
            $event = $this->load_event($context);
        } catch (\Exception $e) {
            return false;
        }
 
        if (is_callable([$event, $action])) {
            return true;
        }
 
        return false;
    }
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
                return $this->events[strtolower($context)];
            }
 
            $event = new $default($this);
            $this->events[strtolower($context)] = $event;
            return $this->events[strtolower($context)];
        }
 
        throw new \Exception('There is no event found for context ' . $requested_context);
    }
 
    /**
     * Call event
     *
     * @access public
     * @param $arguments mixed[]
     */
    public function call_event(string $context, string $action, array $arguments = []): mixed {
        $event = $this->load_event($context);
        return call_user_func_array([$event, $action], $arguments);
    }
 
    /**
     * Event exists
     *
     * @access public
     */
    public function event_exists(string $context, string $action): bool {
        try {
            $event = $this->load_event($context);
        } catch (\Exception $e) {
            return false;
        }
 
        if (is_callable([$event, $action])) {
            return true;
        }
 
        return false;
    }
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-application-web/lib/Skeleton/Application/Web.php
     *
     * @access protected
     */
    protected function get_details(): void {
        parent::get_details();
 
        $this->media_path = $this->path . '/media/';
        $this->template_path = $this->path . '/template/';
        $this->module_path = $this->path . '/module/';
        $this->module_namespace = '\\App\\' . ucfirst($this->name) . "\Module\\";
 
        $autoloader = new \Skeleton\Core\Autoloader();
        $autoloader->add_namespace($this->module_namespace, $this->module_path);
        $autoloader->register();
 
        /**
         * Configure translation: default = po storage
         */
        if (class_exists('\Skeleton\I18n\Translator')) {
            $translator = $this->call_event('i18n', 'get_translator');
            if ($translator !== null) {
                $translator->save();
            }
        }
    }
 
    /**
     * Load the config
     *
     * @access private
     */
    protected function load_config(): void {
        /**
         * Set some defaults
         */
        $this->config->session_name = 'APP';
        $this->config->sticky_session_name = 'sys_sticky_session';
        $this->config->csrf_enabled = false;
        $this->config->replay_enabled = false;
        $this->config->hostnames = [];
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
     * @var array<string> $events
     * @access public
     */
    public array $events = [];
 
    /**
     * Application
     *
     * @access private
     */
    private static ?Application $application = null;
 
    /**
     * Constructor
     *
     * @access public
     */
    public function __construct(string $name) {
        $this->name = $name;
        $this->get_details();
    }
 
    /**
     * Accept the HTTP request
     *
     * @access public
     */
    public function accept(): void {
        /**
         * If this application is launched while another application has been
         * set, we need to take over the request_relative_uri
         * This happens when whitin an application, another application is
         * started.
         */
        $application = self::get();
        $this->request_relative_uri = $application->request_relative_uri;
        $this->hostname = $application->hostname;
 
        \Skeleton\Core\Application::set($this);
 
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
            if ($application_path[0] === '.') {
                continue;
            }
 
            $application = self::get_by_name($application_path);
            $applications[] = $application;
        }
 
        return $applications;
    }
 
    /**
     * Get application by name
     *
     * @access public
     * @return Application $application
     */
    public static function get_by_name(string $name): Application {
        $application_type = self::get_application_type($name);
        return new $application_type($name);
    }
 
    /**
     * Get application_type
     *
     * @access public
     * @return string $classname
     */
    public static function get_application_type(string $application_name): string {
        $config = clone Config::get();
        $application_path = realpath($config->application_path . '/' . $application_name);
 
        if (!file_exists($application_path . '/config')) {
            throw new \Exception('No config directory created in app ' . $application_name);
        }
 
        /**
         * Set some defaults
         */
        $config->application_type = '\Skeleton\Application\Web';
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
     *
     * @access public
     * @return array<self> $applications
     */
    public static function get_all(): array {
        $config = Config::get();
 
        if (!isset($config->application_path)) {
            throw new \Exception('No application_path set. Please set "application_path" in project configuration');
        }
 
        $application_paths = scandir($config->application_path);
        $applications = [];
 
        foreach ($application_paths as $application_path) {
            if ($application_path[0] === '.') {
                continue;
            }
 
            $application = self::get_by_name($application_path);
            $applications[] = $application;
        }
 
        return $applications;
    }
 
    /**
     * Get application by name
     *
     * @access public
     * @return Application $application
     */
    public static function get_by_name(string $name): Application {
        $application_type = self::get_application_type($name);
        return new $application_type($name);
    }
 
    /**
     * Get application_type
     *
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Application.php
     * Detect
     *
     * @access public
     * @return Application $application
     */
    public static function detect(string $hostname, string $request_uri): Application {
        // If we already have a cached application, return that one
        if (self::$application !== null) {
            return Application::get();
        }
 
        // If multiple host headers have been set, use the last one
        if (strpos($hostname, ', ') !== false) {
            [$hostname, $discard] = array_reverse(explode(', ', $hostname));
        }
 
        unset($discard);
 
        // Find matching applications
        $applications = self::get_all();
        $matched_applications = [];
 
        // Match via event
        foreach ($applications as $application) {
            if ($application->call_event('application', 'detect', [ $hostname, $request_uri ])) {
                $matched_applications[] = $application;
            }
        }
 
        // If we don't have any matched applications, try to match wildcards
        if (count($matched_applications) === 0) {
            foreach ($applications as $application) {
                $wildcard_hostnames = $application->config->hostnames;
                foreach ($wildcard_hostnames as $key => $wildcard_hostname) {
                    if (strpos($wildcard_hostname, '*') === false) {
                        unset($wildcard_hostnames[$key]);
                    }
                }
 
                if (count($wildcard_hostnames) === 0) {
/var/www/admin.tickoweb.be/lib/external/packages/tigron/skeleton-core/lib/Skeleton/Core/Http/Handler.php
            $elements = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
            $hostname = trim(end($elements));
        } elseif (isset($_SERVER['HTTP_HOST'])) {
            $hostname = $_SERVER['HTTP_HOST'];
        } elseif (isset($_SERVER['SERVER_NAME'])) {
            $hostname = $_SERVER['SERVER_NAME'];
        } elseif (isset($_SERVER['SERVER_ADDR'])) {
            $hostname = $_SERVER['SERVER_ADDR'];
        } else {
            throw new \Exception('Not a web request');
        }
 
        // Remove port number from host
        $hostname = preg_replace('/:\d+$/', '', $hostname);
 
        /**
         * Define the application
         */
        try {
            $application = Application::detect($hostname, $request_uri);
        } catch (\Skeleton\Core\Exception_Unknown_Application $e) {
            Status::code_404('application');
        }
        $application->accept();
    }
}
 
/var/www/admin.tickoweb.be/webroot/handler.php
<?php
/**
 * Initialize the application
 *
 * @author Christophe Gosiau <christophe@tigron.be>
 * @author Gerry Demaret <gerry@tigron.be>
 * @author David Vandemaele <david@tigron.be>
 */
 
declare(strict_types=1);
 
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
 
require_once '../lib/base/Bootstrap.php';
Bootstrap::boot();
\Skeleton\Core\Http\Handler::Run();
 

Environment & details:

empty
empty
empty
empty
empty
Key Value
USER
"tickoweb"
HOME
"/home/tickoweb"
HTTP_ACCEPT_ENCODING
"gzip, br, zstd, deflate"
HTTP_USER_AGENT
"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)"
HTTP_ACCEPT
"*/*"
HTTP_CONNECTION
"close"
HTTP_X_BALANCED_BY
"proxy2.tickoweb.net"
HTTP_X_FORWARDED_FOR
"216.73.216.57"
HTTP_HOST
"api.test11.tickoweb.be"
HTTP_X_FORWARDED_PROTO
"https"
SCRIPT_FILENAME
"/var/www/admin.tickoweb.be/webroot/handler.php"
REDIRECT_STATUS
"200"
SERVER_NAME
"admin.tickoweb.be"
SERVER_PORT
"80"
SERVER_ADDR
"10.21.0.41"
REMOTE_USER
""
REMOTE_PORT
""
REMOTE_ADDR
"216.73.216.57"
SERVER_SOFTWARE
"nginx/1.22.1"
GATEWAY_INTERFACE
"CGI/1.1"
REQUEST_SCHEME
"http"
SERVER_PROTOCOL
"HTTP/1.0"
DOCUMENT_ROOT
"/usr/share/nginx/html"
DOCUMENT_URI
"/"
REQUEST_URI
"/"
SCRIPT_NAME
"/"
CONTENT_LENGTH
""
CONTENT_TYPE
""
REQUEST_METHOD
"GET"
QUERY_STRING
""
FCGI_ROLE
"RESPONDER"
PHP_SELF
"/"
REQUEST_TIME_FLOAT
1785293293.6972
REQUEST_TIME
1785293293
empty
0. Whoops\Handler\PlainTextHandler
1. Whoops\Handler\PrettyPageHandler