Skip to content

Commit

Permalink
added custom sections
Browse files Browse the repository at this point in the history
  • Loading branch information
matthes committed Jul 25, 2018
1 parent b3a3024 commit 3b9e848
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 27 deletions.
5 changes: 3 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,23 +260,23 @@ This example will replace the htmlspecialchars() escaper by the strip_tags() fun
Sections are like functions but provide the content they enclose:

```
{section name="someName"}
{sectionxy name="someName"}
Some Content
{/section}
{/sectionxy}
```

```
{section name="someName" > out}
{sectionxy name="someName" > out}
Some Content
{/section}
{/sectionxy}
{= out}
```

To use sections you must just set the callback:

```php
$textTemplate->setSectionCallback(function ($params, $content, $context, $cmdParam) {
$textTemplate->setSectionCallback("sectionxy", function ($content, $params, $command, $context, $cmdParam) {
return "Content to replace section content with";
});
```
Expand Down
38 changes: 19 additions & 19 deletions src/TextTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ class TextTemplate {
private $mFunctions = [];

/**
* @var null|callable
* @var callable[]
*/
private $sectionCallback = null;
private $sections = [];

public function __construct ($text="") {

Expand All @@ -71,10 +71,9 @@ public function __construct ($text="") {
*
* @param $enableSectionMode
*/
public function setSectionCallback($sectionCallback)
public function addSection($name, $sectionCallback)
{

$this->sectionCallback = $sectionCallback;
$this->sections[$name] = $sectionCallback;
}


Expand Down Expand Up @@ -193,11 +192,14 @@ public function _replaceNestingLevels ($input) {
$indexCounter = 0;
$nestingIndex = [];

$blockTags = array_keys($this->sections);
$blockTags[] = "if";
$blockTags[] = "for";

$lines = explode("\n", $input);
for ($li=0; $li < count ($lines); $li++) {
$lines[$li] = preg_replace_callback('/\{(?!=)\s*(\/?)\s*([a-z]+)(.*?)\}/im',
function ($matches) use (&$nestingIndex, &$indexCounter, &$li) {
$blockTags = ["if", "for", "section"];
function ($matches) use (&$nestingIndex, &$indexCounter, &$li, $blockTags) {
$slash = $matches[1];
$tag = $matches[2];
$rest = $matches[3];
Expand Down Expand Up @@ -470,19 +472,21 @@ private function _runIf (&$context, $content, $cmdParam, $softFail, &$ifConditio



private function _runSection(&$context, $content, $cmdParam, $softFail)
private function _runSection($command, &$context, $content, $cmdParam, $softFail)
{
if ($this->sectionCallback === null) {
return $this->_parseBlock($context, $content, $softFail);
if ( ! isset($this->sections[$command])) {
if ($softFail === true)
return "!!ERR:Undefined section '$command'!!";
throw new TemplateParsingException("Undefined section {$command}...{/$command} in block '$cmdParam'");
}

$funcParams = $this->_parseFunctionParameters($cmdParam, $context, $softFail);
$content = $this->_parseBlock($context, $content, $softFail);

try {
$func = $this->sectionCallback;
$func = $this->sections[$command];
$out = $func(
$funcParams["paramArr"], $content, $context, $cmdParam
$content, $funcParams["paramArr"], $command, $context, $cmdParam
);
if ($funcParams["retAs"] !== null) {
$context[$funcParams["retAs"]] = $out;
Expand Down Expand Up @@ -526,8 +530,8 @@ private function _parseFunctionParameters ($cmdParam, &$context, $softFail)

private function _parseBlock (&$context, $block, $softFail) {
// (?!\{): Lookahead Regex: Don't touch double {{

$result = preg_replace_callback('/(\{(?!=)((?<bcommand>if|for|section)(?<bnestingLevel>[0-9]+))(?<bcmdParam>.*?)\}(?<bcontent>.*?)\n?\{\/\2\}|\{(?!=)(?<command>[a-z]+)\s*(?<cmdParam>.*?)\}|\{\=(?<value>.+?)\})/ism',
$bCommands = implode("|", array_keys($this->sections));
$result = preg_replace_callback('/(\{(?!=)((?<bcommand>if|for|' . $bCommands . ')(?<bnestingLevel>[0-9]+))(?<bcmdParam>.*?)\}(?<bcontent>.*?)\n?\{\/\2\}|\{(?!=)(?<command>[a-z]+)\s*(?<cmdParam>.*?)\}|\{\=(?<value>.+?)\})/ism',
function ($matches) use (&$context, $softFail) {
if (isset ($matches["value"]) && $matches["value"] != null) {
return $this->_parseValueOfTags($context, $matches["value"], $softFail);
Expand Down Expand Up @@ -557,13 +561,9 @@ function ($matches) use (&$context, $softFail) {
$this->ifConditionMatch[$nestingLevel]
);

case "section":
return $this->_runSection($context, $content, $cmdParam, $softFail);

default:
if ( ! $softFail)
throw new TemplateParsingException("Invalid block-command '$command' in block '{$matches[0]}'");
return "!! Invalid block-command: '$command' !!";
return $this->_runSection($command, $context, $content, $cmdParam, $softFail);
}
} else {
// Regular Commands
Expand Down
6 changes: 5 additions & 1 deletion test/sections.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace Test;
require __DIR__ . "/../vendor/autoload.php";

use http\Exception\InvalidArgumentException;
use Leuffen\TextTemplate\TextTemplate;
use Tester\Assert;
use Tester\Environment;
Expand Down Expand Up @@ -38,8 +40,10 @@ EOT;

$template = new TextTemplate($tpl);
$sec = [];
$template->setSectionCallback(function ($params, $content, $context, $cmdParam) use (&$sec) {
$template->addSection("section", function ($content, $params, $command, $context, $cmdParam) use (&$sec) {
$sec[$params["name"]] = $content;
if ($command !== "section")
throw new InvalidArgumentException("Command missing");
return "*" . trim ($content) . "*";
});
$textResult = $template->apply([]);
Expand Down

0 comments on commit 3b9e848

Please sign in to comment.