Tovrba vlastního routeru – nedokáže tytvořit URL pro jakýkoliv presenter krom defaultu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Tirus91
Člen | 199
+
0
-

Ahoj,
narazil jsem na situaci, kdy si musím sepsat vlastní router, ovšem nestále se mi nedaří.

V tuto chvíli mi přistoupí na http://xxx.cc/ a dostanu chybu
Invalid link: No route for Front:Sign:up(locale=cs)

V případě, že přistoupím na http://xxx.cc/prihlasit tak mi to nematchne správě, jelikož není údajně vyplněn $locale (persistentní) a to i když mám výchozí hodnotu dle nastavení v administraci (cs|en|…), ale když dám http://xxx.cc/cs/prihlasit, tak to najede, ale opět nesestaví URL pro Front:Sign:*

<?php

namespace Tirus\Routers;

use Nette\Application\Request;
use Nette\Application\Routers\Route;
use Nette\Http\IRequest;
use Nette\Http\Url;
use \Tracy\Debugger;

class FrontRoute extends Route {

    const CACHE = 'Tirus.routing';
    const DEFAULT_MODULE = 'Front';
    const DEFAULT_PRESENTER = 'Homepage';
    const DEFAULT_ACTION = 'default';

    /** @var \Tirus\Models\LanguageModel */
    private $languageModel;

    /** @var \Nette\Database\Table\ActiveRow */
    private $defaultLanguage;

    /** @var \Tirus\Models\RouteModel */
    private $routeModel;

    /**
     * @param \Tirus\Models\RouteModel $routeModel
     */
    public function __construct(\Tirus\Models\RouteModel $routeModel, \Nette\Database\Table\ActiveRow $defaultLang, \Tirus\Models\LanguageModel $langModel) {
        $this->routeModel = $routeModel;
        $this->defaultLanguage = $defaultLang;
        $this->languageModel = $langModel;
        parent::__construct('<locale=' . $defaultLang->code . ' [a-z]{2}>/<slug .+>', array(
            'presenter' => self::DEFAULT_PRESENTER,
            'module' => self::DEFAULT_MODULE,
            'action' => self::DEFAULT_ACTION,
            'locale' => $defaultLang->code,
            'slug' => array(
                self::VALUE => '',
                self::FILTER_IN => null,
                self::FILTER_OUT => null,
            ),
        ));
    }

    /**
     * @param  \Nette\Http\IRequest
     * @return \Nette\Application\Request|NULL
     */
    public function match(IRequest $httpRequest) {
        if (($appRequest = parent::match($httpRequest)) === null) {
            return null;
        }
        $parameters = $appRequest->getParameters();

        if (!array_key_exists('slug', $parameters) || ($page = $this->findPageMatch($parameters)) === null) {
            return null;
        }
		if ($page['module'] != self::DEFAULT_MODULE) {
            return null;
        }
        unset($parameters['action'], $parameters['locale']);
        $request = new \Nette\Application\Request(
                $page['module'] . ':' . $page['presenter'], $httpRequest->getMethod(), $parameters + array(
            'slug' => $page['param_id'],
            'action' => $page['action'],
            'locale' => $page['language']
                ), $httpRequest->getPost(), $httpRequest->getFiles(), array(\Nette\Application\Request::SECURED => $httpRequest->isSecured())
        );
        return $request;
    }

    /**
     * @param  \Nette\Application\Request
     * @param  \Nette\Http\Url
     * @return string|NULL
     */
    public function constructUrl(Request $appRequest, Url $refUrl) {
        $parameters = $appRequest->getParameters();
        $pageId = null;
        Debugger::barDump($parameters, '$parameters');
        if (isset($parameters['slug'])) {
            $pageId = $parameters['slug'];
            unset($parameters['slug']);
        }
        Debugger::barDump($pageId, 'pageId');
        $lang = $this->defaultLanguage->code;
        if (isset($parameters['locale'])) {
            $lang = $parameters['locale'] !== null ? $parameters['locale'] : $this->defaultLanguage->code;
            unset($parameters['locale']);
        }
        Debugger::barDump($lang, 'lang');

        $route = clone($this->routeModel);
        $tmp = explode(':', $appRequest->getPresenterName());
        Debugger::barDump($appRequest->presenterName,'PP');
        Debugger::barDump($tmp);
        $presenter = $tmp[1];
        $languageModel = clone($this->languageModel);
        $lan = $languageModel->getByCode($lang);
        $page = $route->findAll()
                ->where('param_id', $pageId)
                ->where('module', self::DEFAULT_MODULE)
                ->where('presenter', $presenter)
                ->where('action', $parameters['action'])
                ->where('language_id IS NULL OR language_id ', $lan->id)
                ->order('id DESC')
                ->fetch();

        if (!$page) {
            Debugger::barDump($parameters, '!$parameters');
            $page = $route->findAll()
                    ->where('param_id', null)
                    ->where('module', self::DEFAULT_MODULE)
                    ->where('presenter', self::DEFAULT_PRESENTER)
                    ->where('action', self::DEFAULT_ACTION)
                    ->where('language_id IS NULL OR language_id ', $lan->id)
                    ->order('id DESC')
                    ->fetch();
        }
        unset($parameters['action']);


        $par = array(
            'module' => self::DEFAULT_MODULE,
            'presenter' => $page->presenter,
            'action' => $page->action,
            'slug' => $page->slug,
            'locale' => $lan->code
                ) + $parameters;
        Debugger::barDump($par, 'PAR');
        $appRequest->setPresenterName(self::DEFAULT_MODULE . ':' . $page->presenter);
        $appRequest->setParameters($par);

        Debugger::barDump(parent::constructUrl($appRequest, $refUrl), 'URL');
        return parent::constructUrl($appRequest, $refUrl);
    }

    /**
     * @param $parameters
     * @return mixed[]|null
     */
    private function findPageMatch($parameters) {
        $lang = isset($parameters['locale']) && $parameters['locale'] !== null ? $parameters['locale'] : $this->defaultLanguage->code;

        $route = clone($this->routeModel);
        $page = $route
                ->findBySlug((string) $parameters['slug']);

        if (count($page->count()) == 1) {
            $page = $page->fetch();
            if ($page) {
                return $this->getPageArray($page);
            }
            return null;
        }
        $route = clone($this->routeModel);
        $languageModel = clone($this->languageModel);
        $page = $route->
                findAll()
                ->where('slug', (string) $parameters['slug'])
                ->where('module', self::DEFAULT_MODULE)
                ->where('language_id', $languageModel->getByCode($this->defaultLanguage->code)->id)
                ->order('id DESC')
                ->fetchAll();

        $page = $page->fetch();
        if ($page) {
            return $this->getPageArray($page);
        }
        return null;
    }

    private function getPageArray(\Nette\Database\Table\ActiveRow $page) {
        $pageArray = $page->toArray();
        if ($page->language_id == null) {
            $pageArray['language'] = $this->defaultLanguage->code;
        } else {
            $lang = clone($this->languageModel);
            $pageArray['language'] = $lang->findById($page->language_id)->code;
        }
        return $pageArray;
    }

}

Jinak, při sestavování té URL se nic nedostane do metody constructUrl

Samotnýt RouteFactory je

<?php

namespace App;

use \Nette\Application\Routers\Route,
    \Nette\Application\Routers\RouteList,
    \Tirus\Routers;

/**
 * Router factory.
 */
class RouterFactory {

    private $routeModel;
    private $defaultLang;
    private $languageModel;

    public function __construct(\Tirus\Models\RouteModel $routeModel, \Tirus\Models\LanguageModel $langModel, \Tirus\Models\SystemModel $systemModel) {
        $this->routeModel = $routeModel;
        $this->defaultLang = $systemModel->getCurrent()->language;
        $this->languageModel = $langModel;
    }

    /**
     * @return \Nette\Application\IRouter
     */
    public function createRouter() {
        $router = new RouteList();
        $router[] = new Routers\FrontRoute($this->routeModel, $this->defaultLang, $this->languageModel);
        $router[] = new Route('index.php', 'Front:Default:default', Route::ONE_WAY);
        return $router;
    }

Nette je 2.3.0

Editoval Tirus91 (8. 3. 2015 18:27)

Tirus91
Člen | 199
+
0
-

Trochu jsem do teď pátral a zjistil jsem, že v případě v presenter.php když se volá

$url = $this->router->constructUrl($this->lastCreatedRequest, $refUrl);

tak se nezavolá metoda mého routeru. Čím to může být?

Tirus91
Člen | 199
+
0
-

Takže stačilo upravit volání

parent::__construct('[<locale=' . $defaultLang->code . ' [a-z]{2}>/]<slug>[/<presenter>[/<action>]]', array(
            'presenter' => self::DEFAULT_PRESENTER,
            'module' => self::DEFAULT_MODULE,
            'action' => self::DEFAULT_ACTION,
            'locale' => $defaultLang->code,
            'slug' => array(
                self::VALUE => null,
                self::FILTER_IN => null,
                self::FILTER_OUT => null,
            ),
        ));

v tuto chvíli to již generuje odkazy, ovšem problém nastává, že to tam dává i presenter a action. Vyřešil jsem to str_replace(), ale to mi nepříjde nejlepší řešení