<commit_before><?php
/*
 * Xibo - Digital Signage - http://www.xibo.org.uk
 * Copyright (C) 2015 Spring Signage Ltd
 *
 * This file (State.php) is part of Xibo.
 *
 * Xibo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * Xibo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace Xibo\Middleware;

use Slim\Helper\Set;
use Slim\Middleware;
use Slim\Slim;
use Stash\Driver\Composite;
use Stash\Driver\Ephemeral;
use Stash\Driver\FileSystem;
use Stash\Pool;
use Xibo\Exception\InstanceSuspendedException;
use Xibo\Exception\UpgradePendingException;
use Xibo\Helper\ApplicationState;
use Xibo\Helper\NullSession;
use Xibo\Helper\Session;
use Xibo\Helper\Translate;
use Xibo\Service\ConfigServiceInterface;
use Xibo\Service\HelpService;
use Xibo\Service\ModuleService;
use Xibo\Service\SanitizeService;

/**
 * Class State
 * @package Xibo\Middleware
 */
class State extends Middleware
{
    public function call()
    {
        $app = $this->app;

        // Handle additional Middleware
        if (isset($app->configService->middleware) && is_array($app->configService->middleware)) {
            foreach ($app->configService->middleware as $object) {
                $app->add($object);
            }
        }

        // Set state
        State::setState($app);

        // Define versions, etc.
        $app->configService->Version();

        // Attach a hook to log the route
        $this->app->hook('slim.before.dispatch', function() use ($app) {

            // Do we need SSL/STS?
            if ($app->request()->getScheme() == 'https') {
                if ($app->configService->GetSetting('ISSUE_STS', 0) == 1)
                    $app->response()->header('strict-transport-security', 'max-age=' . $app->configService->GetSetting('STS_TTL', 600));
            }
            else {
                if ($app->configService->GetSetting('FORCE_HTTPS', 0) == 1) {
                    $redirect = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
                    header("Location: $redirect");
                    $app->halt(302);
                }
            }

            // Check to see if the instance has been suspended, if so call the special route
            if ($app->configService->GetSetting('INSTANCE_SUSPENDED') == 1)
                throw new InstanceSuspendedException();

            // Get to see if upgrade is pending
            if ($app->configService->isUpgradePending() && $app->getName() != 'web')
                throw new UpgradePendingException();

            // Reset the ETAGs for GZIP
            if ($requestEtag = $app->request->headers->get('IF_NONE_MATCH')) {
                $app->request->headers->set('IF_NONE_MATCH', str_replace('-gzip', '', $requestEtag));
            }
        });

        // Attach a hook to be called after the route has been dispatched
        $this->app->hook('slim.after.dispatch', function() use ($app) {
            // On our way back out the onion, we want to render the controller.
            if ($app->controller != null)
                $app->controller->render();
        });

        // Next middleware
        $this->next->call();
    }

    /**
     * @param Slim $app
     */
    public static function setState($app)
    {
        //$app->logService->debug('Set State');

        // Set the root Uri
        State::setRootUri($app);

        // Set the config dependencies
        $app->configService->setDependencies($app->store, $app->rootUri);

        // Register the date service
        $app->container->singleton('dateService', function() use ($app) {
            if ($app->configService->GetSetting('CALENDAR_TYPE') == 'Jalali')
                $date = new \Xibo\Service\DateServiceJalali();
            else
                $date = new \Xibo\Service\DateServiceGregorian();

            $date->setLocale(Translate::GetLocale(2));

            return $date;
        });

        // Register the sanitizer
        $app->container->singleton('sanitizerService', function($container) {
            $sanitizer = new SanitizeService($container->dateService);
            $sanitizer->setRequest($container->request);
            return $sanitizer;
        });

        // Register Controllers with DI
        self::registerControllersWithDi($app);

        // Register Factories with DI
        self::registerFactoriesWithDi($app->container);

        $app->container->singleton('moduleService', function () use($app) {
            return new ModuleService(
                $app,
                $app->store,
                $app->pool,
                $app->logService,
                $app->configService,
                $app->dateService,
                $app->sanitizerService
            );
        });

        // Set some public routes
        $app->publicRoutes = array('/login', '/logout', '/clock', '/about', '/login/ping');

        // The state of the application response
        $app->container->singleton('state', function() { return new ApplicationState(); });

        // Setup the translations for gettext
        Translate::InitLocale($app->configService);

        // Config Version
        $app->configService->Version();

        // Default timezone
        date_default_timezone_set($app->configService->GetSetting("defaultTimezone"));

        // Configure the cache
        self::configureCache($app->container, $app->configService, $app->logWriter->getWriter());

        // Register the help service
        $app->container->singleton('helpService', function($container) {
            return new HelpService($container->store, $container->configService, $container->pool);
        });

        // Create a session
        $app->container->singleton('session', function() use ($app) {
            if ($app->getName() == 'web' || $app->getName() == 'auth')
                return new Session($app->logService);
            else
                return new NullSession();
        });

        // We use Slim::flash() so we must immediately start a session (boo)
        $app->container->session->set('init', '1');

        // App Mode
        $mode = $app->configService->GetSetting('SERVER_MODE');
        $app->logService->setMode($mode);

        // Configure logging
        if (strtolower($mode) == 'test') {
            $app->config('log.level', \Slim\Log::DEBUG);
        }
        else {
            $app->config('log.level', \Xibo\Service\LogService::resolveLogLevel($app->configService->GetSetting('audit', 'error')));
        }

        // Configure any extra log handlers
        if ($app->configService->logHandlers != null && is_array($app->configService->logHandlers)) {
            $app->logService->debug('Configuring %d additional log handlers from Config', count($app->configService->logHandlers));
            foreach ($app->configService->logHandlers as $handler) {
                $app->logWriter->addHandler($handler);
            }
        }

        // Configure any extra log processors
        if ($app->configService->logProcessors != null && is_array($app->configService->logProcessors)) {
            $app->logService->debug('Configuring %d additional log processors from Config', count($app->configService->logProcessors));
            foreach ($app->configService->logProcessors as $processor) {
                $app->logWriter->addProcessor($processor);
            }
        }
    }

    /**
     * Set the Root URI
     * @param Slim $app<commit_msg>Fix setting of log level.<commit_after><?php
/*
 * Xibo - Digital Signage - http://www.xibo.org.uk
 * Copyright (C) 2015 Spring Signage Ltd
 *
 * This file (State.php) is part of Xibo.
 *
 * Xibo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * Xibo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace Xibo\Middleware;

use Slim\Helper\Set;
use Slim\Middleware;
use Slim\Slim;
use Stash\Driver\Composite;
use Stash\Driver\Ephemeral;
use Stash\Driver\FileSystem;
use Stash\Pool;
use Xibo\Exception\InstanceSuspendedException;
use Xibo\Exception\UpgradePendingException;
use Xibo\Helper\ApplicationState;
use Xibo\Helper\NullSession;
use Xibo\Helper\Session;
use Xibo\Helper\Translate;
use Xibo\Service\ConfigServiceInterface;
use Xibo\Service\HelpService;
use Xibo\Service\ModuleService;
use Xibo\Service\SanitizeService;

/**
 * Class State
 * @package Xibo\Middleware
 */
class State extends Middleware
{
    public function call()
    {
        $app = $this->app;

        // Handle additional Middleware
        if (isset($app->configService->middleware) && is_array($app->configService->middleware)) {
            foreach ($app->configService->middleware as $object) {
                $app->add($object);
            }
        }

        // Set state
        State::setState($app);

        // Define versions, etc.
        $app->configService->Version();

        // Attach a hook to log the route
        $this->app->hook('slim.before.dispatch', function() use ($app) {

            // Do we need SSL/STS?
            if ($app->request()->getScheme() == 'https') {
                if ($app->configService->GetSetting('ISSUE_STS', 0) == 1)
                    $app->response()->header('strict-transport-security', 'max-age=' . $app->configService->GetSetting('STS_TTL', 600));
            }
            else {
                if ($app->configService->GetSetting('FORCE_HTTPS', 0) == 1) {
                    $redirect = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
                    header("Location: $redirect");
                    $app->halt(302);
                }
            }

            // Check to see if the instance has been suspended, if so call the special route
            if ($app->configService->GetSetting('INSTANCE_SUSPENDED') == 1)
                throw new InstanceSuspendedException();

            // Get to see if upgrade is pending
            if ($app->configService->isUpgradePending() && $app->getName() != 'web')
                throw new UpgradePendingException();

            // Reset the ETAGs for GZIP
            if ($requestEtag = $app->request->headers->get('IF_NONE_MATCH')) {
                $app->request->headers->set('IF_NONE_MATCH', str_replace('-gzip', '', $requestEtag));
            }
        });

        // Attach a hook to be called after the route has been dispatched
        $this->app->hook('slim.after.dispatch', function() use ($app) {
            // On our way back out the onion, we want to render the controller.
            if ($app->controller != null)
                $app->controller->render();
        });

        // Next middleware
        $this->next->call();
    }

    /**
     * @param Slim $app
     */
    public static function setState($app)
    {
        //$app->logService->debug('Set State');

        // Set the root Uri
        State::setRootUri($app);

        // Set the config dependencies
        $app->configService->setDependencies($app->store, $app->rootUri);

        // Register the date service
        $app->container->singleton('dateService', function() use ($app) {
            if ($app->configService->GetSetting('CALENDAR_TYPE') == 'Jalali')
                $date = new \Xibo\Service\DateServiceJalali();
            else
                $date = new \Xibo\Service\DateServiceGregorian();

            $date->setLocale(Translate::GetLocale(2));

            return $date;
        });

        // Register the sanitizer
        $app->container->singleton('sanitizerService', function($container) {
            $sanitizer = new SanitizeService($container->dateService);
            $sanitizer->setRequest($container->request);
            return $sanitizer;
        });

        // Register Controllers with DI
        self::registerControllersWithDi($app);

        // Register Factories with DI
        self::registerFactoriesWithDi($app->container);

        $app->container->singleton('moduleService', function () use($app) {
            return new ModuleService(
                $app,
                $app->store,
                $app->pool,
                $app->logService,
                $app->configService,
                $app->dateService,
                $app->sanitizerService
            );
        });

        // Set some public routes
        $app->publicRoutes = array('/login', '/logout', '/clock', '/about', '/login/ping');

        // The state of the application response
        $app->container->singleton('state', function() { return new ApplicationState(); });

        // Setup the translations for gettext
        Translate::InitLocale($app->configService);

        // Config Version
        $app->configService->Version();

        // Default timezone
        date_default_timezone_set($app->configService->GetSetting("defaultTimezone"));

        // Configure the cache
        self::configureCache($app->container, $app->configService, $app->logWriter->getWriter());

        // Register the help service
        $app->container->singleton('helpService', function($container) {
            return new HelpService($container->store, $container->configService, $container->pool);
        });

        // Create a session
        $app->container->singleton('session', function() use ($app) {
            if ($app->getName() == 'web' || $app->getName() == 'auth')
                return new Session($app->logService);
            else
                return new NullSession();
        });

        // We use Slim::flash() so we must immediately start a session (boo)
        $app->container->session->set('init', '1');

        // App Mode
        $mode = $app->configService->GetSetting('SERVER_MODE');
        $app->logService->setMode($mode);

        // Configure logging
        if (strtolower($mode) == 'test') {
            $app->getLog()->setLevel(\Slim\Log::DEBUG);
        }
        else {
            $app->getLog()->setLevel(\Xibo\Service\LogService::resolveLogLevel($app->configService->GetSetting('audit')));
        }

        // Configure any extra log handlers
        if ($app->configService->logHandlers != null && is_array($app->configService->logHandlers)) {
            $app->logService->debug('Configuring %d additional log handlers from Config', count($app->configService->logHandlers));
            foreach ($app->configService->logHandlers as $handler) {
                $app->logWriter->addHandler($handler);
            }
        }

        // Configure any extra log processors
        if ($app->configService->logProcessors != null && is_array($app->configService->logProcessors)) {
            $app->logService->debug('Configuring %d additional log processors from Config', count($app->configService->logProcessors));
            foreach ($app->configService->logProcessors as $processor) {
                $app->logWriter->addProcessor($processor);
            }
        }
    }

    /**
     * Set the Root URI
     * @param Slim $app
{'fraction_non_alphanumeric': 0.13822213822213822, 'fraction_numerical': 0.002268002268002268, 'mean_word_length': 2.2535355605656897, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 253, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7452954', 'n_tokens_mistral': 4376, 'n_tokens_neox': 4163, 'n_words': 1050}