Routa pro presentery v libovolné namespace
- nanuqcz
- Člen | 822
Zkouším si vytvořit další z řady CMF a narazil jsem na problém.
Chtěl bych vytvořit routu, která by spouštěla presentery z namespace
CMF
. Tzn použití by bylo takto:
$router[] = new CMFRoute('<presenter>/<action>[/<id>]', 'Front:Homepage:default'); //spustí se presenter \CMF\FrontModule\HomepagePresenter a jeho akce default
Zkoušel jsem to takto:
class CMFRoute extends Route
{
public function match(IRequest $httpRequest)
{
$request = parent::match($httpRequest);
$request->setPresenterName('CMF\\' . $request->getPresenterName());
return $request;
}
}
Ale evidentně na to jdu špatně.
Prosím o rady, odkazy apod. Z API na to nejsem schopný přijít. Díky
EDIT: Tak částečně vyřešeno (pohrabal jsem se uvnitř
Nette). Budu muset přepsat službu presenterFactory
(její metodu
formatPresenterClass
). Bohužel nevím, jak to mám udělat
(čistě), aby byl výsledný namespace presenteru závislý na
použité routě.
Editoval xxxObiWan (24. 7. 2011 20:59)
- nanuqcz
- Člen | 822
Tak nakonec jsem to vyřešil takhle (pokud to někomu pomůže):
config.neon
services:
presenterFactory: #přepisuji defaultní PresenterFactory z Nette
class: MyPresenterFactory
arguments: [%appDir%, @container]
MyPresenterFactory.php
class MyPresenterFactory extends Nette\Application\PresenterFactory
{
/**
* Podpora pro vlastní namespace presenterů
* @param string $name
* @return string
*/
public function getPresenterClass(& $name)
{
if (strrpos($name, '\\')) {
return $this->formatPresenterClass($name); //obejdeme všechny kontroly Nette :-(
} else {
return parent::getPresenterClass($name);
}
}
}
bootstrap.php
$router[] = new NamespaceRoute('<presenter>/<action>[/<id>]', 'CMF\\Homepage:default');
NamespaceRoute.php
class NamespaceRoute extends Route
{
/** @var string */
protected $namespace;
/**
* @param string URL mask, e.g. '<presenter>/<action>/<id \d{1,3}>'
* @param array|string default values or metadata
* @param int flags
*/
public function __construct($mask, $metadata = array(), $flags = 0)
{
if (is_string($metadata) && strrpos($metadata, '\\')) {
$this->namespace = substr_replace($metadata, '', strrpos($metadata, '\\'));
$metadata = substr_replace($metadata, '', 0, strrpos($metadata, '\\') + 1);
} else {
$this->namespace = '';
}
parent::__construct($mask, $metadata, $flags);
}
/**
* Maps HTTP request to a Request object.
* @param IRequest
* @return Request|NULL
*/
public function match(IRequest $httpRequest)
{
$request = parent::match($httpRequest);
if ($request !== NULL && $this->namespace) {
$request->setPresenterName($this->namespace . '\\' . $request->getPresenterName());
}
return $request;
}
/**
* Constructs absolute URL from Request object.
* @param Request
* @param Url
* @return string|NULL
*/
public function constructUrl(Request $appRequest, Url $refUrl)
{
if ($this->namespace) {
$nameWithoutNamespace = substr_replace($appRequest->getPresenterName(), '', 0, strlen($this->namespace) + 1);
$appRequest->setPresenterName($nameWithoutNamespace);
}
return parent::constructUrl($appRequest, $refUrl);
}
}
Nevím, nakolik je to čisté řešení (ale zatím vypadá že funguje). Za případné návrhy na lepší řešení předem děkuji :-)
Editoval xxxObiWan (26. 7. 2011 2:26)