Luc Laverdure
Luc Laverdure

Reputation: 1480

Template Engine refactoring

   $global_models =
            array(12) {
              ["page.login"]=>
              string(1) "2"
              ["page.item.id"]=>
              string(3) "new"
              ["page.content.title"]=>
              string(0) ""
              ["page.trigger.date"]=>
              string(0) ""
              ["page.trigger.url"]=>
              string(0) ""
              ["page.trigger.admin_only"]=>
              string(1) "N"
              ["page.content.body"]=>
              string(0) ""
              ["page..ga"]=>
              string(27) "GA1.2.1694644634.1491872034"
              ["prompt.message"]=>
              string(0) ""
              ["prompt.error"]=>
              string(0) ""
              ["page.tags"]=>
              array(1) {
                ["name"]=>
                array(2) {
                  [0]=>
                  string(2) "xx"
                  [1]=>
                  string(2) "yy"
                }
              }
              ["page.custom"]=>
              array(2) {
                ["header"]=>
                array(2) {
                  [0]=>
                  string(0) "1"
                  [1]=>
                  string(1) "a"
                }
                ["value"]=>
                array(2) {
                  [0]=>
                  string(0) "2"
                  [1]=>
                  string(1) "b"
                }
              }
            }

Code:

        foreach ($global_models as $var => $data) {
            // when model data is an array
            if (is_array($data)) {
                // fetch for blocks and render loops
                $forblocks = array();
                preg_match_all('/(?<block>\[for:'.$var.'\](?<content>[\s\S]+)\[end:'.$var.'\])/ix', $view_output, $forblocks, PREG_SET_ORDER);
                if (count($forblocks)) {
                    foreach ($forblocks as $foundForBlock) {
                        $foreach_data = '';
                        foreach ($data as $mykey => $row) {
                            // set model values within the loop, ex: blocks.x value
                            $block_content = $foundForBlock['content'];
                            foreach ($row as $subvar => $value) {
                                if (!is_array($value)) {
                                    $block_content = str_replace('['.$var.'.'.$subvar.']', $value, $block_content);
                                    //$block_content = str_replace('['.$var.'.'.$mykey.']', $value, $block_content);
                                }
                            }
                            // append the parsed new block (of for loop) as processed view to render (ifs and setters for example)
                            $foreach_data .=  $this->process_view($controller, $block_content, $recursion_level + 1);
                        }
                        $view_output = str_replace($foundForBlock['block'], $foreach_data, $view_output);
                    }
                }
            } else {
                // simple model, replace model with value ex: "[stats.x]" by "18"
                $view_output = str_replace('['.$var.']', $data, $view_output);
            }
        }

Issue:

Key to value pair works

my blocks of data don't work...

$viewoutput =
"
    [page.login]
"

should result in

"
2
"

This:

$viewoutput =
"
[for:page.custom]
      [page.custom.header] - [page.custom.value]
[end:page.custom]
"

should result in

"
    1 - 2
    a - b
"

This:

$viewoutput =

"
[for:page.tags]
      [page.tags.name]
[end:page.tags]
"

should result in

"
    xx
    yy
"

I've refactored my code about 20 times and each time I get a headache...!

Someone please help?

Thanks and viva la community! :)

Upvotes: 1

Views: 83

Answers (2)

Luc Laverdure
Luc Laverdure

Reputation: 1480

Fixed myself...

        // process shared models (variables)
        foreach ($global_models as $var => $data) {
            // when model data is an array
            if (is_array($data)) {
                // fetch for blocks and render loops
                $forblocks = array();
                preg_match_all('/(?<block>\[for:'.$var.'\](?<content>[\s\S]+)\[end:'.$var.'\])/ix', $view_output, $forblocks, PREG_SET_ORDER);
                if (count($forblocks)) {
                    foreach ($forblocks as $foundForBlock) {
                        $block_content = array();
                        foreach ($data as $mykey => $row) {
                        //$foreach_data = '';
                            // set model values within the loop, ex: blocks.x value
                            foreach ($row as $subvar => $value) {
                                if (!isset($block_content[$subvar])) $block_content[$subvar] = $foundForBlock['content'];
                                if (!is_array($value)) {
                                    if (is_numeric($subvar)) {
                                        $block_content[$subvar] = str_replace('['.$var.'.'.$mykey.']', $value, $block_content[$subvar]);

                                    } 
                                }
                            }
                            // append the parsed new block (of for loop) as processed view to render (ifs and setters for example)
                        }
                        $block_content = implode("\n", $block_content);
                        $view_output = str_replace($foundForBlock['block'], $block_content, $view_output);
                    }
                }
            } else {
                // simple model, replace model with value ex: "[stats.x]" by "18"
                $view_output = str_replace('['.$var.']', $data, $view_output);
            }
        }

Upvotes: 1

Sahil Gulati
Sahil Gulati

Reputation: 15141

I have tried my self best to get it done. I know this is not a generic solution but it will solve your current problem. You must use different function for using loop([for:page.custom]) and simple([page.login]) attribute. I have already went through this issue. I also solved one of my problem by this, Here you should define seperate function which will first decide which function will handle modification whether it is for loop or for simple. But for now i have fixed your issue with a single php function.

Try this code snippet here

<?php
ini_set('display_errors', 1);
$global_models = array(
    "page.login" => "2",
    "page.item.id" => "new",
    "page.content.title" => "",
    "page.trigger.date" => "",
    "page.trigger.url" => "",
    "page.trigger.admin_only" => "N",
    "page.content.body" => "testing",
    "page..ga" => "GA1.2.1694644634.1491872034",
    "prompt.message" => "",
    "prompt.error" => "",
    "page.tags" =>
    array(
        "name" =>
        array(
            0 => "xx",
            1 => "yy"
        )
    ),
    "page.custom" =>
    array(
        "header" =>
        array(
            0 => "1",
            1 => "a",
        ),
        "value" =>
        array(
            0 => "2",
            1 => "b",
        )
    )
);
$viewoutput =
"
    [page.content.body]
[for:page.custom]
      [page.custom.header] - [page.custom.value]
[end:page.custom]
";

echo modify($viewoutput);

function modify($viewoutput)
{
    $returnString="";
    global $global_models;
    $segments=explode("\n", $viewoutput);
    $counter=0;
    while(count($segments)>0)
    {
        $segment=$segments[$counter];
        if (preg_match("/\[for:\K([\w\.]+)\]/", $segment,$matches))
        {
            unset($segments[$counter]);
            $counter++;
            $segment=$segments[$counter];
            $pointer=0;
            $data=array();

            preg_match_all("/\.([\w]+)\]/", $segment,$segmentMatches);
            for($x=0;$x<count($global_models[$matches[1]][$segmentMatches[1][0]]);$x++)
            {
                $newString=$segment;
                foreach($segmentMatches[1] as $toReplace)
                {
                    $newString=  str_replace("[".$matches[1].".".$toReplace."]", $global_models[$matches[1]][$toReplace][$x], $newString);
                }
                $data[]=$newString;
            }
        }
        elseif(preg_match("/\[end:\K([\w\.]+)\]/", $segment))
        {
            $returnString.=  implode("\n", $data);
        }
        elseif(preg_match("/\[([\w\.]+)\]/", $segment,$matches1) && !preg_match("/\[for:\K([\w\.]+)\]/", $segment,$matches))
        {
            $returnString=$returnString.$global_models[$matches1[1]]."\n";
        }
        else
        {
            $returnString=$returnString.$segment."\n";
        }
        unset($segments[$counter]);
        $counter++;
    }
    return $returnString;
}

Upvotes: 2

Related Questions