Rozparsování linku na modul, presenter, akci a parametry

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

Dobrý den, mám dotaz, zda existuje nějáký chytrý způsob, jak rozparsovat nette link (něco ve stylu :Modul:Product:show $productId, lang ⇒ cs) na jednotlivé části (modul, presenter, akci, parametry). Chtěl bych to použít v BasePresenteru jako metodu:
parseLink($link);

a to aby to fungovalo i pokud bude link např, this, nebo !signal, nebo kdyby obsahoval jen akci popř. presenter + akci atd.
Zn. ideál, kdyby vracel asociativní pole, kde klíče by byly: module, presenter, action, params a příslušné hodnoty.
Děkuji za radu.

Editoval maw (5. 10. 2012 13:44)

enumag
Člen | 2118
+
0
-

Přesně tohle jsem kdysi dávno úspěšně nevyřešil. Můj závěr tehdy byl takový, že by bylo nutné metodu Presenter::createRequest rozdělit na více metod – z nichž jedna by řešila tohle.

maw
Člen | 6
+
0
-

Mno, nakonec jsem to vyřešil takto (viz. níže). Pro mé účely to zatím dostačuje (i když to teda asi není úplně ideální řešení). Pozn.: metody jsou v BasePresenteru.

    /**
     * Returns Module name
     * @return string
     */
    public function getModuleName()
    {
        $pos = strrpos($this->name, ':');
        if (is_int($pos)) {
            return substr($this->name, 0, $pos);
        }
        return NULL;
    }

    /**
     * Return presenter pure name
     * @return string
     */
    public function getPresenterName()
    {
        $pos = strrpos($this->name, ':');
        if (is_int($pos)) {
            return substr($this->name, $pos + 1);
        }
        return $this->name;
    }

    /**
     * Rozparsuje link na modul, presenter, akci - př. :Administration:Default:default
     * @param string $link
     * @return array associativní pole s klíči module, presenter, action
     */
    public function parseLink($link){
        $matches = array();
        preg_match_all("/\,\s?.+/i", $link, $parameters);
        $replace = $parameters[0];
        $linkwithoutparams = str_replace($replace, "", $link);
        preg_match_all("/\:?([a-zA-Z]+)/i", $linkwithoutparams, $matches);
        $match = $matches[1];
        switch(count($match)){
            case 1:
                $out = array('module' => $this->getModuleName(), 'presenter' =>$this->getPresenterName(), 'action' => $match[0]);
            break;
            case 2:
                $out = array('module' => $this->getModuleName(), 'presenter' => $match[0], 'action' => $match[1]);
            break;
            case 3:
                $out = array('module' => $match[0], 'presenter' => $match[1], 'action' => $match[2]);
            break;
            default:
                $out = false;
            break;
        }
        return $out;
    }

maw
Člen | 6
+
0
-

Ještě upravená verze metody parseLink…

<?php
/**
     * Rozparsuje link na modul, presenter, akci - př. :Administration:Default:default
     * @param string $link
     * @return array associativní pole s klíči module, presenter, action
     */
    public function parseLink($link) {
        $matches = array();
        preg_match_all("/\,\s?.+/i", $link, $parameters);
        $replace = $parameters[0];
        $linkwithoutparams = str_replace($replace, "", $link);
        preg_match_all("/\:?([a-zA-Z]+!?)/i", $linkwithoutparams, $matches);
        $match = $matches[1];

        if(substr($linkwithoutparams, -1) == '!') { array_pop($match); } // Vyhodíme z "parametrů" signály (na ty se práva nevztahují)

        switch (count($match)) {
            case 0:
                $out = array('module' => $this->getModuleName(), 'presenter' => $this->getPresenterName(), 'action' => $this->getAction());
                break;
            case 1:
                $out = array('module' => $this->getModuleName(), 'presenter' => $this->getPresenterName(), 'action' => $match[0]);
                break;
            case 2:
                $out = array('module' => $this->getModuleName(), 'presenter' => $match[0], 'action' => $match[1]);
                break;
            case 3:
                $out = array('module' => $match[0], 'presenter' => $match[1], 'action' => $match[2]);
                break;
            default:
                $out = false;
                break;
        }
        return $out;
    }
?>
Filip Procházka
Moderator | 4668
+
0
-

Tak se teda zeptám já – na co to potřebuješ? Nešlo by to udělat bez toho, lépe?

llook
Člen | 407
+
0
-

Dá se to udělat tak, že si z toho nejdřív vytvoříš URL pomocí $presenter->link() a tu potom proženeš zpětně přes $router->match(). Tím získáš Application\Request, tzn. název presenteru a hodnoty parametrů.

Něco podobného jsem dělal u seleniových testů, abych mohl psát aserce na URL otevřené stránky (něco jako $this->assertPresenter(':Module:Presenter', 'action => default, id => 5')).

maw
Člen | 6
+
0
-

No potřeboval jsem to kvůli tomu, že jsem si psal vlastní Authorizator. Potřeboval jsem si nějak parsovat url, kvůli zjišťování oprávnění rolí na resources (sekce).

enumag
Člen | 2118
+
0
-

@maw: Zkus normálně zavolat Presenter::createRequest() s tím linkem jako argument a pak se mrkni na Presenter::getLastCreatedRequest(), mělo by tam být ± to co potřebuješ.