Override presenteru, ak existuje v custom folderi
- stewestw
- Člen | 42
riesime si CMS, v ktorom je normalne zachovana struktura nette. z casu na cas potrebujeme overridenut presenter pre konkr. klienta, nechceme ale zasiahnut do core.
- vsetky presenteri dedia basePresenter.
- custom mame vynate a ked sa v nom nachadza nazov presenteru ktory volame, tak sa forwardne (forward ale nechceme)
kod:
<?php
/**
* Created by PhpStorm.
* User: stefan
* Date: 27/01/2017
* Time: 14:08
*/
namespace Core;
use Nette;
use Core\Models\Privileges;
class BasePresenter extends Nette\Application\UI\Presenter{
/** @var */
protected $acl;
/**
*
* set override on startup
*
*/
public function startup(){
// call default functionality
parent::startup();
// set right presenter override
$request = $this->getRequest();
$action = $this->getAction();
$shortName = str_replace('Override', '', explode(':', $this->getName())[count(explode(':', $this->getName())) -1]);
$folder = 'custom/overrides/';
if ( !$request->isMethod('forward')) {
$parts = $this->getParts();
$rewrite_dest = __DIR__ . '/../../'.$folder.implode('/',$parts).'/presenters/'.$shortName.'OverridePresenter.php';
if(file_exists($rewrite_dest)){
$exploder = explode(':', $this->getName());
$exploder[count($exploder) - 1] = $exploder[count($exploder) - 1].'Override';
$override = ':'.implode(':', $exploder).':'.$action;
$override = str_replace('OverrideOverride', "Override", $override);
$args = $this->getParameters();
$this->forward($override, $args);
}
}
// set right template override
$parts = $this->getParts();
$rewrite_dest_original = str_replace( 'Override.latte', '.latte', __DIR__ . '/../'.implode('/', $parts).'/templates/'.$shortName.'/' .$action.'.latte');
$rewrite_dest = str_replace( 'Override.latte', '.latte', __DIR__ . '/../../'.$folder.implode('/', $parts) .'/templates/'.$shortName.'/'.$action.'.latte');
if(file_exists($rewrite_dest)){
$this->template->setFile($rewrite_dest);
}else{
$this->template->setFile($rewrite_dest_original);
}
}
/**
* @return mixed
*/
protected function getParts(){
$class_info = new \ReflectionClass($this);
$class_info = explode('\\Presenters\\', $class_info->name)[0];
return explode('\\', $class_info);
}
/**
* @param Privileges $acl
*/
public function injectDependencies(Privileges $acl){
$this->acl = $acl;
}
}
- David Matějka
- Moderator | 6445
o zjisteni nazvu presenteru se stara sluzba PresenterFactory (respektivfe IPresenterFactory), takze si muzes udelat vlastni implementaci, ktera se koukne, jestli existuje ta override trida
- Martk
- Člen | 661
@stewestw řešil jsem stejnou záležitost, ale pak jsem z ní upustil a koukám, že na gitu jsem to stále nechal. Třeba ti to pomůže
- matopeto
- Člen | 395
Bud pretazit a/alebo prrepisat ten kusok co hlada tu classu na nieco take:
<?php
$classOverride = $this->formatPresenterClass($name . "override");
if (class_exists($classOverride) {
$class = $classOverride;
} else {
$class = $this->formatPresenterClass($name);
}
if (!class_exists($class)) {
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found.");
}
?>
Editoval matopeto (21. 6. 2017 16:58)
- stewestw
- Člen | 42
posunul som sa dalej, dakujem, vyzera to, ze mi uz robi aj override, ale samotny presenter hadze chybu:
Call to a member function isSent() on null
tu:
File: .../nette/application/src/Application/UI/Presenter.php:177
167: * @return Nette\Application\IResponse
168: */
169: public function run(Application\Request $request)
170: {
171: try {
172: // STARTUP
173: $this->request = $request;
174: $this->payload = $this->payload ?: new \stdClass;
175: $this->setParent($this->getParent(), $request->getPresenterName());
176:
177: if (!$this->httpResponse->isSent()) {
178: $this->httpResponse->addHeader('Vary', 'X-Requested-With');
179: }
180:
181: $this->initGlobalParameters();
- stewestw
- Člen | 42
uz som to presiel cez
<?php
/**
* Created by PhpStorm.
* User: stefan
* Date: 21/06/2017
* Time: 16:44
*/
namespace Core;
use Nette\Application\PresenterFactory;
use Nette\Application\IPresenter;
class CorePresenterFactory extends PresenterFactory{
public function getPresenterClass(& $name) {
$class = parent::getPresenterClass($name);
$exploder = explode(':', $name);
$exploder[count($exploder) - 1] = $exploder[count($exploder) - 1].'Override';
$override = implode(':', $exploder);
$override = str_replace('OverrideOverride', 'Override', $override);
$class = $this->formatPresenterClass($override);
if (!class_exists($class)) {
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found.");
}
$reflection = new \ReflectionClass($class);
$class = $reflection->getName();
if (!$reflection->implementsInterface(IPresenter::class)) {
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor.");
} elseif ($reflection->isAbstract()) {
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract.");
}
return $class;
}
}
stale mi t ale vracia:
Argument 1 passed to Front\CoreModule\Presenters\HomepageOverridePresenter::__construct() must be an instance of Core\Models\Db, none given, called in /Applications/MAMP/htdocs/suchacms/vendor/nette/application/src/Application/PresenterFactory.php
je to mozne pls neako vyriesit?
- Martk
- Člen | 661
A registruješ tu třídu presenter factory takhle? Měl jsem tam potíže, že se mi tam nepředávalo factory v konstruktoru presenter factory, takže se použilo výchozí factory callback
Edit:
Pro tebe to bude chtít menší úpravu
$def = $builder->getDefinition($builder->getByType('Nette\Application\IPresenterFactory'));
$original = $def->getFactory();
$def->setFactory('TvojeTrida', $original->arguments);
Editoval Martk (21. 6. 2017 17:46)
- stewestw
- Člen | 42
dakujem, uz to slape :) vytvoril som jednoduchu extension ako si to mal ty. ak to niekto do buducna bude hladat, tak tu je inicializacia:
<?php
namespace Core;
use Nette\DI\CompilerExtension;
use Core\CorePresenterFactory;
class CoreExtension extends CompilerExtension
{
public function beforeCompile()
{
$builder = $this->getContainerBuilder();
$def = $builder->getDefinition($builder->getByType('Nette\Application\IPresenterFactory'));
$original = $def->getFactory();
$def->setFactory('Core\CorePresenterFactory', $original->arguments);
}
}
- David Matějka
- Moderator | 6445
ta trida dedi od base presenteru na urovni php, to nezmenis.. (pokud nepocitam prasarny s autoloadingem :))