-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added sections inheritance of fetched templates #306
base: v3
Are you sure you want to change the base?
Changes from all commits
121cfcf
6ecd911
c8facf3
01af12a
262acb1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ | |
|
||
namespace League\Plates\Template; | ||
|
||
use Exception; | ||
use League\Plates\Engine; | ||
use League\Plates\Exception\TemplateNotFound; | ||
use LogicException; | ||
|
@@ -43,9 +42,10 @@ class Template | |
|
||
/** | ||
* An array of section content. | ||
* @var array | ||
* | ||
* @var TemplateSectionCollection | ||
*/ | ||
protected $sections = array(); | ||
protected $sections; | ||
|
||
/** | ||
* The name of the section currently being rendered. | ||
|
@@ -81,6 +81,7 @@ public function __construct(Engine $engine, $name) | |
{ | ||
$this->engine = $engine; | ||
$this->name = new Name($engine, $name); | ||
$this->sections = new TemplateSectionCollection(); | ||
|
||
$this->data($this->engine->getData($name)); | ||
} | ||
|
@@ -173,7 +174,9 @@ public function render(array $data = array()) | |
|
||
if (isset($this->layoutName)) { | ||
$layout = $this->engine->make($this->layoutName); | ||
$layout->sections = array_merge($this->sections, array('content' => $content)); | ||
$layout->sections->merge($this->sections); | ||
$contentSectionName = 'content'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to use a attribute to declare it. In case someone want to change it. |
||
$layout->sections[$contentSectionName] = $content; | ||
$content = $layout->render($this->layoutData); | ||
} | ||
|
||
|
@@ -251,31 +254,31 @@ public function unshift($name) | |
*/ | ||
public function stop() | ||
{ | ||
if (is_null($this->sectionName)) { | ||
$sectionName = $this->sectionName; | ||
|
||
if (is_null($sectionName)) { | ||
throw new LogicException( | ||
'You must start a section before you can stop it.' | ||
); | ||
} | ||
|
||
if (!isset($this->sections[$this->sectionName])) { | ||
$this->sections[$this->sectionName] = ''; | ||
if (!$this->sections->has($sectionName)) { | ||
$this->sections[$sectionName] = ''; | ||
} | ||
|
||
switch ($this->sectionMode) { | ||
$sectionContent = ob_get_clean(); | ||
|
||
case self::SECTION_MODE_REWRITE: | ||
$this->sections[$this->sectionName] = ob_get_clean(); | ||
break; | ||
|
||
case self::SECTION_MODE_APPEND: | ||
$this->sections[$this->sectionName] .= ob_get_clean(); | ||
break; | ||
// if ob_clean failed for some reason let's just ignore the result | ||
if ($sectionContent === false) { | ||
return; | ||
} | ||
|
||
case self::SECTION_MODE_PREPEND: | ||
$this->sections[$this->sectionName] = ob_get_clean().$this->sections[$this->sectionName]; | ||
break; | ||
$this->sections->add( | ||
$sectionName, | ||
$sectionContent, | ||
$this->sectionMode | ||
); | ||
|
||
} | ||
$this->sectionName = null; | ||
$this->sectionMode = self::SECTION_MODE_REWRITE; | ||
$this->appendSection = false; /* for backward compatibility */ | ||
|
@@ -307,13 +310,22 @@ public function section($name, $default = null) | |
|
||
/** | ||
* Fetch a rendered template. | ||
* | ||
* @param string $name | ||
* @param array $data | ||
* @return string | ||
*/ | ||
public function fetch($name, array $data = array()) | ||
{ | ||
return $this->engine->render($name, $data); | ||
$template = $this->engine->make($name); | ||
$content = $template->render($data); | ||
|
||
// some info like 'sections' are only filled during | ||
// the render processing, so here we have a window to | ||
// fetch them and join to this template. | ||
$this->sections->merge($template->sections); | ||
|
||
return $content; | ||
} | ||
|
||
/** | ||
|
@@ -324,7 +336,7 @@ public function fetch($name, array $data = array()) | |
*/ | ||
public function insert($name, array $data = array()) | ||
{ | ||
echo $this->engine->render($name, $data); | ||
echo $this->fetch($name, $data); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
|
||
namespace League\Plates\Template; | ||
|
||
/** | ||
* Defines the object format of the data target | ||
* to be rendered in a Template's Section. | ||
*/ | ||
class TemplateSection | ||
{ | ||
/** | ||
* Section mode. | ||
* | ||
* @var int | ||
*/ | ||
protected $mode; | ||
|
||
/** | ||
* Section content. | ||
* | ||
* @var string | ||
*/ | ||
protected $content; | ||
|
||
/** | ||
* Section name. | ||
* | ||
* @var string | ||
*/ | ||
protected $name; | ||
|
||
/** | ||
* @param string $name | ||
* @param ?string $content | ||
* @param ?int $mode | ||
*/ | ||
public function __construct(string $name, $content = '', $mode = Template::SECTION_MODE_REWRITE) | ||
{ | ||
$this->name = $name; | ||
$this->content = $content; | ||
$this->mode = $mode; | ||
} | ||
|
||
/** | ||
* @param string $content | ||
* @param int $mode | ||
* @return void | ||
*/ | ||
public function add(string $content, int $mode) | ||
{ | ||
$this->mode = $mode; | ||
|
||
// if this template doesn't have that section, so we just add it. | ||
if (empty($this->content)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like !isset instead of empty. Some time ago I read that this would be faster. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's because empty also checks if the value represents an empty value like |
||
$this->content = $content; | ||
return; | ||
} | ||
|
||
// otherwise we need to consider the incoming section mode | ||
if ($mode === Template::SECTION_MODE_REWRITE) { | ||
$this->content = $content; | ||
return; | ||
} | ||
|
||
if ($mode === Template::SECTION_MODE_APPEND) { | ||
$this->content = $this->content . $content; | ||
return; | ||
} | ||
|
||
if ($mode === Template::SECTION_MODE_PREPEND) { | ||
$this->content = $content . $this->content; | ||
} | ||
} | ||
|
||
/** | ||
* @return string|null | ||
*/ | ||
public function getContent(): string | ||
{ | ||
return $this->content; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function getMode(): int | ||
{ | ||
return $this->mode; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
<?php | ||
|
||
namespace League\Plates\Template; | ||
|
||
use ArrayAccess; | ||
use InvalidArgumentException; | ||
|
||
/** | ||
* Collection of TemplateSections that can be used to fill Template's Sections. | ||
* Here is defined a common API for merging Template Section data. | ||
* NOTE: currently this is not iterable, so do not try this in a foreach. | ||
*/ | ||
class TemplateSectionCollection implements ArrayAccess | ||
{ | ||
/** | ||
* @var array<string, TemplateSection> | ||
*/ | ||
private $sections = array(); | ||
|
||
/** | ||
* @param string $offset | ||
* | ||
* @return bool | ||
*/ | ||
public function has(string $offset): bool | ||
{ | ||
return array_key_exists($offset, $this->sections); | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* | ||
* @return TemplateSection | ||
*/ | ||
public function get(string $offset) | ||
{ | ||
return $this->sections[$offset]; | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* @param TemplateSection|null $value | ||
* | ||
* @return void | ||
*/ | ||
public function set(string $offset, $value) | ||
{ | ||
if (!is_string($offset)) { | ||
throw new InvalidArgumentException('The desired section offset must be a string.'); | ||
} | ||
if (!($value instanceof TemplateSection) && $value != null) { | ||
throw new InvalidArgumentException('The section set must be of type TemplateSection.'); | ||
} | ||
$this->sections[$offset] = $value; | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* | ||
* @return bool | ||
*/ | ||
public function offsetExists($offset): bool | ||
{ | ||
if (!is_string($offset)) { | ||
throw new InvalidArgumentException('The desired section offset must be a string.'); | ||
} | ||
return $this->has($offset); | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* | ||
* @return string | ||
*/ | ||
public function offsetGet($offset) | ||
{ | ||
if (!is_string($offset)) { | ||
throw new InvalidArgumentException('The desired section offset must be a string.'); | ||
} | ||
return $this->get($offset)->getContent(); | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* @param string $value | ||
* | ||
* @return void | ||
*/ | ||
public function offsetSet($offset, $value): void | ||
{ | ||
if (!is_string($offset)) { | ||
throw new InvalidArgumentException('The desired section offset must be a string.'); | ||
} | ||
$this->add($offset, $value, Template::SECTION_MODE_REWRITE); | ||
} | ||
|
||
/** | ||
* @param string $offset | ||
* | ||
* @return void | ||
*/ | ||
public function offsetUnset($offset) | ||
{ | ||
if (!is_string($offset)) { | ||
throw new InvalidArgumentException('The desired section offset must be a string.'); | ||
} | ||
$this->sections[$offset] = null; | ||
unset($this->sections[$offset]); | ||
} | ||
|
||
/** | ||
* Pushes the given section content to the sections array. | ||
* You can use the $mode to merge the content to an existing | ||
* content if that section content already exists. | ||
* | ||
* @param string $name | ||
* @param string $content | ||
* @param ?int $mode | ||
* | ||
* @return void | ||
*/ | ||
public function add(string $name, string $content, $mode = Template::SECTION_MODE_APPEND) | ||
{ | ||
if ($this->has($name)) { | ||
$this->sections[$name]->add($content, $mode); | ||
return; | ||
} | ||
$this->sections[$name] = new TemplateSection($name, $content, $mode); | ||
} | ||
|
||
/** | ||
* Merges another Template Sections collection into | ||
* this one taking in consideration the template | ||
* section's modes. | ||
* | ||
* @return void | ||
*/ | ||
public function merge(TemplateSectionCollection $templateSections) | ||
{ | ||
foreach ($templateSections->sections as $section) { | ||
$this->add( | ||
$section->getName(), | ||
$section->getContent(), | ||
$section->getMode() | ||
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest limit it to .idea