Jump to content

Wikipedia-style template parsing


Grayda

Recommended Posts

My latest big project is a website engine that lets people manage their entire website through their browser. It's aimed at website developers (myself) and people who don't know too much about HTML and PHP and stuff (the client). One idea I'm implementing is "templates". For example, if a user wanted to show the page called "hello", they would simply type {{hello}} and it would be included, very much like Wikipedia's {{stub}} templates and so forth.

 

I would also like to pass arguments to the "template", so a user could type {{weather|New York}} and have the weather page generate some HTML that shows the weather in New York.

 

I got this working after much fiddling, by:

$t = preg_match("/\{\{(I.*)\}\}/", $thePage, $args);

-ing the page pulled from the database then splitting the results from $args by the pipe delimiter. This worked great for several different templates on the one page, but if I wanted to re-use one template several times, for example to automate complex tasks, then it would silently fail, showing the first template, but blank spaces for the remaining templates. So for example, if I have 3 templates defined: header (the navigation for the website), fact (a [Citation Needed] template) and footer (for copyright info) and my code looks like this:

 

{{header}}
This statement is a lie{{fact}}
While this statement is correct{{fact}}
{{footer}}

 

One would expect to see:

 

Home | About | Contact

 

This statement is a lie[Citation Needed]

While this statement is correct[Citation Needed]

 

©2008 MyCompany

 

But instead we get:

 

Home | About | Contact

 

This statement is a lie[Citation Needed]

While this statement is correct

 

 

©2008 MyCompany

 

Note the missing [Citation Needed] after the second statement, plus the extra whitespace?

 

I've tried lots of ways to get this working, from preg_match_all (Just returns the whole page, minus the first {{ and last }}), preg_replace (But doesn't let me pass the page name to a custom function) and even preg_replace_callback which did gave me the error

preg_replace_callback() [function.preg-replace-callback]: Requires argument 2, 'doFix', to be a valid callback in <script filename> on line 71
despite the function doFix existing, being a valid function, returning the right values etc.

 

Am I missing something? Can I pass what's between the {{ and }} to my custom function, $this->getPage($thePage); ? I'm slowly starting to get the hang of regular expressions, but it's just so difficult to read sometimes..

 

Any help is much appreciated :)

Link to comment
Share on other sites

I found a solution. Turns out I needed to use preg_match_all to grab all of the results, because preg_match only matches the first one and stops looking. This, however, throws in ALL the results:

 

 

Array

        (

            [0] => {{header}}

            [1] => {{fact}}

            [2] => {{fact}}

            [3] => {{footer}}

            [4] => header

            [5] => fact

            [6] => fact

            [7] => footer

        )

 

So I simply loop through the array and unset the first half of the array

 

My code now looks like this (and is rather messy. I hope there's a quicker, cleaner way to do this):

 

// First, we extract the text between the {{ and }} and return it as $a
preg_match_all("|{{(.*)}}|", $retPage, $a);
// Then we loop through the array, divided by two, and unset the first half of the array
for ($i = 0; $i < count($a) / 2; $i++) {
unset($a[$i]);
}

// Then we loop through again, this time exploding the arguments given to the temmplate, ignoring any errors
for ($i = 0; $i < count($a[1]); $i++) {
@$args = explode("|", $a[1][$i]); 
// Next, we set up a sessions variable called "pagename_args" which contains our arguments for the template to parse 
$_SESSION[$args[0] . "_args"] = $args;
// Now we grab the page from the database and store it in $n
$n = $this->getPage($args[0]);
// Remove the template tag from the page, and replace it with our page name
$retPage = preg_replace("|{{(.*)}}|", $n, $retPage);
// And finally, we remove the $_SESSION variable we made, since the page no longer needs it
$_SESSION[$args[0] . "_args"] = array();
}

 

I highly doubt this is the right way, or the fast way, to do this, but for now it works. I guess my regexes need a little work, too ;)

 

I hope this helps someone out, because it's being doing my head in for a while  :P

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.