<commit_before><?php

namespace x2ts\route;

use x2ts\Component;
use x2ts\ComponentFactory as X;
use x2ts\route\event\PostRouteEvent;
use x2ts\route\event\PreRouteEvent;
use x2ts\route\http\Request;
use x2ts\route\http\Response;
use x2ts\route\rule\IRule;
use x2ts\Toolkit;

/**
 * Class Router
 *
 * @property IRule[]     $rules
 * @property-read Action $action
 * @package x2ts\route
 */
class Router extends Component {
    protected static $_conf = [
        'baseUri' => '',
        'rules'   => [],
    ];

    protected $action;

    public function init() {
        /** @var array $rules */
        $rules = $this->conf['rules'];
        foreach ($rules as $ruleClass => $ruleConf) {
            /** @var IRule $rule */
            $rule = new $ruleClass();
            $rule->setConf($ruleConf);
            $this->addRule($rule);
        }
    }

    /**
     * @var IRule[]
     */
    private $rules = [];

    public function addRule(IRule $rule) {
        $this->rules[] = $rule;
        return $this;
    }

    /**
     * @param Request  $req
     * @param Response $res
     *
     * @return bool
     */
    public function route($req, $res) {
        $uri = $req->server('REQUEST_URI');
        $preRouteEvent = new PreRouteEvent([
            'dispatcher' => $this,
            'uri'        => $uri,
        ]);
        X::bus()->dispatch($preRouteEvent);

        $subUri = ltrim(substr($uri, strlen($this->conf['baseUri'])), '/');
        foreach ($this->rules as $rule) {
            if ($rule->isMatch($subUri)) {
                $action = $rule->fetchAction();
                $args = $rule->fetchArguments();
                $action->request = $req;
                $action->response = $res;
                $this->action = $action;
                $postRoute = new PostRouteEvent([
                    'dispatcher' => $this,
                    'uri'        => $uri,
                    'action'     => $action,
                    'args'       => $args,
                ]);
                X::bus()->dispatch($postRoute);
                $action->run($args);
                return true;
            }
        }

        $res->setHeader('Status', 404, true, 404);
        $res->setBody('Not Found');
        $res->response();
        Toolkit::trace("Action not found: $uri");
        return false;
    }

    public function onPreRoute(callable $callback, $state = null) {
        X::bus()->on('x2ts.route.PreRoute', $callback, $state);
        return $this;
    }

    public function onPostRoute(callable $callback, $state = null) {
        X::bus()->on('x2ts.route.PostRoute', $callback, $state);
        return $this;<commit_msg>call $action->init() before calling run<commit_after><?php

namespace x2ts\route;

use x2ts\Component;
use x2ts\ComponentFactory as X;
use x2ts\route\event\PostRouteEvent;
use x2ts\route\event\PreRouteEvent;
use x2ts\route\http\Request;
use x2ts\route\http\Response;
use x2ts\route\rule\IRule;
use x2ts\Toolkit;

/**
 * Class Router
 *
 * @property IRule[]     $rules
 * @property-read Action $action
 * @package x2ts\route
 */
class Router extends Component {
    protected static $_conf = [
        'baseUri' => '',
        'rules'   => [],
    ];

    protected $action;

    public function init() {
        /** @var array $rules */
        $rules = $this->conf['rules'];
        foreach ($rules as $ruleClass => $ruleConf) {
            /** @var IRule $rule */
            $rule = new $ruleClass();
            $rule->setConf($ruleConf);
            $this->addRule($rule);
        }
    }

    /**
     * @var IRule[]
     */
    private $rules = [];

    public function addRule(IRule $rule) {
        $this->rules[] = $rule;
        return $this;
    }

    /**
     * @param Request  $req
     * @param Response $res
     *
     * @return bool
     */
    public function route($req, $res) {
        $uri = $req->server('REQUEST_URI');
        $preRouteEvent = new PreRouteEvent([
            'dispatcher' => $this,
            'uri'        => $uri,
        ]);
        X::bus()->dispatch($preRouteEvent);

        $subUri = ltrim(substr($uri, strlen($this->conf['baseUri'])), '/');
        foreach ($this->rules as $rule) {
            if ($rule->isMatch($subUri)) {
                $action = $rule->fetchAction();
                $args = $rule->fetchArguments();
                $action->request = $req;
                $action->response = $res;
                $this->action = $action;
                $postRoute = new PostRouteEvent([
                    'dispatcher' => $this,
                    'uri'        => $uri,
                    'action'     => $action,
                    'args'       => $args,
                ]);
                X::bus()->dispatch($postRoute);
                $action->init();
                $action->run($args);
                return true;
            }
        }

        $res->setHeader('Status', 404, true, 404);
        $res->setBody('Not Found');
        $res->response();
        Toolkit::trace("Action not found: $uri");
        return false;
    }

    public function onPreRoute(callable $callback, $state = null) {
        X::bus()->on('x2ts.route.PreRoute', $callback, $state);
        return $this;
    }

    public function onPostRoute(callable $callback, $state = null) {
        X::bus()->on('x2ts.route.PostRoute', $callback, $state);
        return $this;
{'fraction_non_alphanumeric': 0.16223750232298828, 'fraction_numerical': 0.006690206281360342, 'mean_word_length': 1.76, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '194814', 'n_tokens_mistral': 1639, 'n_tokens_neox': 1582, 'n_words': 336}