Stack partials, store components, unstack partials - Fixes #1373
Fixes instances where nested repeating partials are destroying the partial component stack and causing breaking errors. Nesting example: Partial (with components) ^-> Calls component default markup ^-> Refers to partial override (with repeating partial calls) ^-> Calls another partial (with components) ^-> Components not found (destroyed by repeating calls above)
This commit is contained in:
parent
6f414fe611
commit
85933facbc
|
|
@ -111,7 +111,7 @@ class Controller
|
|||
/**
|
||||
* @var array Component partial stack, used internally.
|
||||
*/
|
||||
protected $partialComponentStack = [];
|
||||
protected $partialStack = [];
|
||||
|
||||
/**
|
||||
* Creates the controller.
|
||||
|
|
@ -127,6 +127,7 @@ class Controller
|
|||
|
||||
$this->assetPath = Config::get('cms.themesPath', '/themes').'/'.$this->theme->getDirName();
|
||||
$this->router = new Router($this->theme);
|
||||
$this->partialStack = new PartialStack;
|
||||
$this->initTwigEnvironment();
|
||||
|
||||
self::$instance = $this;
|
||||
|
|
@ -847,6 +848,8 @@ class Controller
|
|||
*/
|
||||
|
||||
if ($partial instanceof Partial) {
|
||||
$this->partialStack->stackPartial();
|
||||
|
||||
$manager = ComponentManager::instance();
|
||||
|
||||
foreach ($partial->settings['components'] as $component => $properties) {
|
||||
|
|
@ -868,10 +871,7 @@ class Controller
|
|||
$componentObj->alias = $alias;
|
||||
$parameters[$alias] = $partial->components[$alias] = $componentObj;
|
||||
|
||||
array_push($this->partialComponentStack, [
|
||||
'name' => $alias,
|
||||
'obj' => $componentObj
|
||||
]);
|
||||
$this->partialStack->addComponent($alias, $componentObj);
|
||||
|
||||
$this->setComponentPropertiesFromParams($componentObj, $parameters);
|
||||
$componentObj->init();
|
||||
|
|
@ -890,7 +890,7 @@ class Controller
|
|||
}
|
||||
|
||||
/*
|
||||
* Render the parital
|
||||
* Render the partial
|
||||
*/
|
||||
CmsException::mask($partial, 400);
|
||||
$this->loader->setObject($partial);
|
||||
|
|
@ -899,9 +899,7 @@ class Controller
|
|||
CmsException::unmask();
|
||||
|
||||
if ($partial instanceof Partial) {
|
||||
if ($this->partialComponentStack) {
|
||||
array_pop($this->partialComponentStack);
|
||||
}
|
||||
$this->partialStack->unstackPartial();
|
||||
}
|
||||
|
||||
$this->vars = $vars;
|
||||
|
|
@ -1224,10 +1222,9 @@ class Controller
|
|||
return $this->layout->components[$name];
|
||||
}
|
||||
|
||||
foreach ($this->partialComponentStack as $componentInfo) {
|
||||
if ($componentInfo['name'] == $name) {
|
||||
return $componentInfo['obj'];
|
||||
}
|
||||
$partialComponent = $this->partialStack->getComponent($name);
|
||||
if ($partialComponent !== null) {
|
||||
return $partialComponent;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
<?php namespace Cms\Classes;
|
||||
|
||||
/**
|
||||
* Manager class for stacking nested partials and keeping track
|
||||
* of their components. Partial "objects" store the components
|
||||
* used by that partial for deferred retrieval.
|
||||
*
|
||||
* @package october\cms
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
class PartialStack
|
||||
{
|
||||
/**
|
||||
* @var array The current partial "object" being rendered.
|
||||
*/
|
||||
public $activePartial = null;
|
||||
|
||||
/**
|
||||
* @var array Collection of previously rendered partial "objects".
|
||||
*/
|
||||
protected $partialStack = [];
|
||||
|
||||
/**
|
||||
* Partial entry point, appends a new partial to the stack.
|
||||
*/
|
||||
public function stackPartial()
|
||||
{
|
||||
if ($this->activePartial !== null) {
|
||||
array_unshift($this->partialStack, $this->activePartial);
|
||||
}
|
||||
|
||||
$this->activePartial = [
|
||||
'components' => []
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial exit point, removes the active partial from the stack.
|
||||
*/
|
||||
public function unstackPartial()
|
||||
{
|
||||
$this->activePartial = array_shift($this->partialStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a component to the active partial stack.
|
||||
*/
|
||||
public function addComponent($alias, $componentObj)
|
||||
{
|
||||
array_push($this->activePartial['components'], [
|
||||
'name' => $alias,
|
||||
'obj' => $componentObj
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a component by its alias from the partial stack.
|
||||
*/
|
||||
public function getComponent($name)
|
||||
{
|
||||
$component = $this->findComponentFromStack($name, $this->activePartial);
|
||||
if ($component !== null) {
|
||||
return $component;
|
||||
}
|
||||
|
||||
foreach ($this->partialStack as $stack) {
|
||||
$component = $this->findComponentFromStack($name, $stack);
|
||||
if ($component !== null) {
|
||||
return $component;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates a component by its alias from the supplied stack.
|
||||
*/
|
||||
protected function findComponentFromStack($name, $stack)
|
||||
{
|
||||
foreach ($stack['components'] as $componentInfo) {
|
||||
if ($componentInfo['name'] == $name) {
|
||||
return $componentInfo['obj'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue