Skip to content

Commit

Permalink
[Form] Improved FormRenderer API to reduce the size of the function c…
Browse files Browse the repository at this point in the history
…all stack during rendering
  • Loading branch information
webmozart committed Jul 22, 2012
1 parent ec4250a commit 0628f2f
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 262 deletions.
86 changes: 43 additions & 43 deletions AbstractRendererEngine.php
Expand Up @@ -74,132 +74,132 @@ public function setTheme(FormView $view, $themes)
/**
* {@inheritdoc}
*/
public function getResourceForBlock(FormView $view, $block)
public function getResourceForBlockName(FormView $view, $blockName)
{
$cacheKey = $view->vars[self::CACHE_KEY_VAR];

if (!isset($this->resources[$cacheKey][$block])) {
$this->loadResourceForBlock($cacheKey, $view, $block);
if (!isset($this->resources[$cacheKey][$blockName])) {
$this->loadResourceForBlockName($cacheKey, $view, $blockName);
}

return $this->resources[$cacheKey][$block];
return $this->resources[$cacheKey][$blockName];
}

/**
* {@inheritdoc}
*/
public function getResourceForBlockHierarchy(FormView $view, array $blockHierarchy, $hierarchyLevel)
public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel)
{
$cacheKey = $view->vars[self::CACHE_KEY_VAR];
$block = $blockHierarchy[$hierarchyLevel];
$blockName = $blockNameHierarchy[$hierarchyLevel];

if (!isset($this->resources[$cacheKey][$block])) {
$this->loadResourceForBlockHierarchy($cacheKey, $view, $blockHierarchy, $hierarchyLevel);
if (!isset($this->resources[$cacheKey][$blockName])) {
$this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel);
}

return $this->resources[$cacheKey][$block];
return $this->resources[$cacheKey][$blockName];
}

/**
* {@inheritdoc}
*/
public function getResourceHierarchyLevel(FormView $view, array $blockHierarchy, $hierarchyLevel)
public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel)
{
$cacheKey = $view->vars[self::CACHE_KEY_VAR];
$block = $blockHierarchy[$hierarchyLevel];
$blockName = $blockNameHierarchy[$hierarchyLevel];

if (!isset($this->resources[$cacheKey][$block])) {
$this->loadResourceForBlockHierarchy($cacheKey, $view, $blockHierarchy, $hierarchyLevel);
if (!isset($this->resources[$cacheKey][$blockName])) {
$this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel);
}

// If $block was previously rendered loaded with loadTemplateForBlock(), the template
// is cached but the hierarchy level is not. In this case, we know that the block
// exists at this very hierarchy level, so we can just set it.
if (!isset($this->resourceHierarchyLevels[$cacheKey][$block])) {
$this->resourceHierarchyLevels[$cacheKey][$block] = $hierarchyLevel;
if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) {
$this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;
}

return $this->resourceHierarchyLevels[$cacheKey][$block];
return $this->resourceHierarchyLevels[$cacheKey][$blockName];
}

/**
* Loads the cache with the resource for a given block name.
*
* @see getResourceForBlock()
*
* @param string $cacheKey The cache key of the form view.
* @param FormView $view The form view for finding the applying themes.
* @param string $block The name of the block to load.
* @param string $cacheKey The cache key of the form view.
* @param FormView $view The form view for finding the applying themes.
* @param string $blockName The name of the block to load.
*
* @return Boolean True if the resource could be loaded, false otherwise.
*/
abstract protected function loadResourceForBlock($cacheKey, FormView $view, $block);
abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName);

/**
* Loads the cache with the resource for a specific level of a block hierarchy.
*
* @see getResourceForBlockHierarchy()
*
* @param string $cacheKey The cache key used for storing the
* resource.
* @param FormView $view The form view for finding the applying
* themes.
* @param array $blockHierarchy The block hierarchy, with the most
* specific block name at the end.
* @param integer $hierarchyLevel The level in the block hierarchy that
* should be loaded.
* @param string $cacheKey The cache key used for storing the
* resource.
* @param FormView $view The form view for finding the applying
* themes.
* @param array $blockNameHierarchy The block hierarchy, with the most
* specific block name at the end.
* @param integer $hierarchyLevel The level in the block hierarchy that
* should be loaded.
*
* @return Boolean True if the resource could be loaded, false otherwise.
*/
private function loadResourceForBlockHierarchy($cacheKey, FormView $view, array $blockHierarchy, $hierarchyLevel)
private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel)
{
$block = $blockHierarchy[$hierarchyLevel];
$blockName = $blockNameHierarchy[$hierarchyLevel];

// Try to find a template for that block
if ($this->loadResourceForBlock($cacheKey, $view, $block)) {
if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) {
// If loadTemplateForBlock() returns true, it was able to populate the
// cache. The only missing thing is to set the hierarchy level at which
// the template was found.
$this->resourceHierarchyLevels[$cacheKey][$block] = $hierarchyLevel;
$this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;

return true;
}

if ($hierarchyLevel > 0) {
$parentLevel = $hierarchyLevel - 1;
$parentBlock = $blockHierarchy[$parentLevel];
$parentBlockName = $blockNameHierarchy[$parentLevel];

// The next two if statements contain slightly duplicated code. This is by intention
// and tries to avoid execution of unnecessary checks in order to increase performance.

if (isset($this->resources[$cacheKey][$parentBlock])) {
if (isset($this->resources[$cacheKey][$parentBlockName])) {
// It may happen that the parent block is already loaded, but its level is not.
// In this case, the parent block must have been loaded by loadResourceForBlock(),
// which does not check the hierarchy of the block. Subsequently the block must have
// been found directly on the parent level.
if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlock])) {
$this->resourceHierarchyLevels[$cacheKey][$parentBlock] = $parentLevel;
if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) {
$this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel;
}

// Cache the shortcuts for further accesses
$this->resources[$cacheKey][$block] = $this->resources[$cacheKey][$parentBlock];
$this->resourceHierarchyLevels[$cacheKey][$block] = $this->resourceHierarchyLevels[$cacheKey][$parentBlock];
$this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
$this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];

return true;
}

if ($this->loadResourceForBlockHierarchy($cacheKey, $view, $blockHierarchy, $parentLevel)) {
if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) {
// Cache the shortcuts for further accesses
$this->resources[$cacheKey][$block] = $this->resources[$cacheKey][$parentBlock];
$this->resourceHierarchyLevels[$cacheKey][$block] = $this->resourceHierarchyLevels[$cacheKey][$parentBlock];
$this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
$this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];

return true;
}
}

// Cache the result for further accesses
$this->resources[$cacheKey][$block] = false;
$this->resourceHierarchyLevels[$cacheKey][$block] = false;
$this->resources[$cacheKey][$blockName] = false;
$this->resourceHierarchyLevels[$cacheKey][$blockName] = false;

return false;
}
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -175,5 +175,5 @@ CHANGELOG
* `toArrayKeys`
* `isChoiceGroup`
* `isChoiceSelected`
* added method `block` to FormHelper and deprecated `renderBlock` instead
* [BC BREAK] renamed method `renderBlock` in FormHelper to `block` and changed its signature
* made FormView properties public and deprecated their accessor methods
36 changes: 18 additions & 18 deletions Extension/Templating/TemplatingRendererEngine.php
Expand Up @@ -35,7 +35,7 @@ public function __construct(EngineInterface $engine, array $defaultThemes = arra
/**
* {@inheritdoc}
*/
public function renderBlock(FormView $view, $resource, $block, array $variables = array())
public function renderBlock(FormView $view, $resource, $blockName, array $variables = array())
{
return trim($this->engine->render($resource, $variables));
}
Expand All @@ -48,13 +48,13 @@ public function renderBlock(FormView $view, $resource, $block, array $variables
*
* @see getResourceForBlock()
*
* @param string $cacheKey The cache key of the form view.
* @param FormView $view The form view for finding the applying themes.
* @param string $block The name of the block to load.
* @param string $cacheKey The cache key of the form view.
* @param FormView $view The form view for finding the applying themes.
* @param string $blockName The name of the block to load.
*
* @return Boolean True if the resource could be loaded, false otherwise.
*/
protected function loadResourceForBlock($cacheKey, FormView $view, $block)
protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName)
{
// Recursively try to find the block in the themes assigned to $view,
// then of its parent form, then of the parent form of the parent and so on.
Expand All @@ -64,7 +64,7 @@ protected function loadResourceForBlock($cacheKey, FormView $view, $block)
// Check each theme whether it contains the searched block
if (isset($this->themes[$cacheKey])) {
for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
if ($this->loadResourceFromTheme($cacheKey, $block, $this->themes[$cacheKey][$i])) {
if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) {
return true;
}
}
Expand All @@ -73,7 +73,7 @@ protected function loadResourceForBlock($cacheKey, FormView $view, $block)
// Check the default themes once we reach the root form without success
if (!$view->parent) {
for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) {
if ($this->loadResourceFromTheme($cacheKey, $block, $this->defaultThemes[$i])) {
if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) {
return true;
}
}
Expand All @@ -84,38 +84,38 @@ protected function loadResourceForBlock($cacheKey, FormView $view, $block)
if ($view->parent) {
$parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR];

if (!isset($this->resources[$parentCacheKey][$block])) {
$this->loadResourceForBlock($parentCacheKey, $view->parent, $block);
if (!isset($this->resources[$parentCacheKey][$blockName])) {
$this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName);
}

// If a template exists in the parent themes, cache that template
// for the current theme as well to speed up further accesses
if ($this->resources[$parentCacheKey][$block]) {
$this->resources[$cacheKey][$block] = $this->resources[$parentCacheKey][$block];
if ($this->resources[$parentCacheKey][$blockName]) {
$this->resources[$cacheKey][$blockName] = $this->resources[$parentCacheKey][$blockName];

return true;
}
}

// Cache that we didn't find anything to speed up further accesses
$this->resources[$cacheKey][$block] = false;
$this->resources[$cacheKey][$blockName] = false;

return false;
}

/**
* Tries to load the resource for a block from a theme.
*
* @param string $cacheKey The cache key for storing the resource.
* @param string $block The name of the block to load a resource for.
* @param mixed $theme The theme to load the block from.
* @param string $cacheKey The cache key for storing the resource.
* @param string $blockName The name of the block to load a resource for.
* @param mixed $theme The theme to load the block from.
*
* @return Boolean True if the resource could be loaded, false otherwise.
*/
protected function loadResourceFromTheme($cacheKey, $block, $theme)
protected function loadResourceFromTheme($cacheKey, $blockName, $theme)
{
if ($this->engine->exists($templateName = $theme . ':' . $block . '.html.php')) {
$this->resources[$cacheKey][$block] = $templateName;
if ($this->engine->exists($templateName = $theme . ':' . $blockName . '.html.php')) {
$this->resources[$cacheKey][$blockName] = $templateName;

return true;
}
Expand Down

0 comments on commit 0628f2f

Please sign in to comment.