Page 1 of 1

Reducing Template Code

Posted: Wed May 11, 2011 6:15 pm
by Jonah Bron

Code: Select all

<aside id="docTree">
<?php

$tree = array();

global $documents, $template, $parents, $slug;

$documents = $doc_tree->fetchAll()->toArray();
$template = <<<EOS
%1\$s	<li%5\$s>
%1\$s		<span><button></button><a href="{$BASE}support/docs/browse/%2\$s">%3\$s</a></span>
%4\$s
%1\$s	</li>

EOS;
$slug = $doc_slug;
$parents = array();
$currentParent = $doc_slug;
while ($currentParent != 'root' && $currentParent != 'error') {
	foreach ($documents as $document) {
		if ($document->slug == $currentParent) {
			$parents[] = $document->slug;
			$currentParent = $document->parent;
		}
	}
}

function scanForChildren($parent, $stackDepth=0) {
	global $documents, $template, $parents, $slug;
	// indent two tabs at a time
	$indent = str_repeat('		', $stackDepth);
	$html = "$indent<ul>\n";
	foreach ($documents as $doc) {
		if ($doc->parent == $parent) {
			$html .= sprintf(
				$template,
				$indent,
				$doc->slug,
				$doc->title,
				scanForChildren($doc->slug, $stackDepth + 1),
				in_array($doc->slug, $parents) ? ($doc->slug == $slug ? ' class="current"' : '') : ' class="closed"'
			);
		}
	}
	$html .= "$indent</ul>\n";
	return $html;
}

echo scanForChildren('root', 1);

?>
</aside>
This mess of code is in a template file in the context of a Skeleton Framework application. It's purpose probably isn't immediately apparent, so I'll explain: this code takes a linear array of document names and in one-to-many relationships, and displays it in tree form. Each document's children can be hidden and shown (with Javascript) like any normal tree (think Eclipse file explorer).

The code is in "working" state. This is clearly view code (as in model view controller), but it seems like there shouldn't be so much (procedural) code in the template file. Plus it ranks of an absence of SRP. To top it off, the main recursive function holds multiple levels of abstraction in itself (conversion, HTML output, etc.).

What I do about this?

P.S. the $stackDepth and $indent variables are strictly to make the markup look pretty :)

Edit: here's an example output:

Code: Select all

<aside id="docTree">
	<ul>
		<li class="closed">
			<span><button></button><a href="http://localhost/batchzip/support/docs/browse/home">Home</a></span>
			<ul>
			</ul>

		</li>
		<li class="closed">
			<span><button></button><a href="http://localhost/batchzip/support/docs/browse/sub">Sub Page</a></span>
			<ul>
			</ul>

		</li>
		<li class="closed">
			<span><button></button><a href="http://localhost/batchzip/support/docs/browse/subsub">Sub Sub page</a></span>
			<ul>
				<li class="closed">
					<span><button></button><a href="http://localhost/batchzip/support/docs/browse/foo">Foo</a></span>
					<ul>
						<li class="closed">
							<span><button></button><a href="http://localhost/batchzip/support/docs/browse/bar">Bar</a></span>
							<ul>
							</ul>

						</li>
					</ul>

				</li>
			</ul>

		</li>
		<li class="closed">
			<span><button></button><a href="http://localhost/batchzip/support/docs/browse/top">Top Level</a></span>
			<ul>
			</ul>

		</li>
	</ul>

</aside>

Re: Reducing Template Code

Posted: Thu May 12, 2011 2:07 pm
by Jonah Bron
John Cartwright wrote:two words:
view helper

Re: Reducing Template Code

Posted: Thu May 12, 2011 5:32 pm
by Jonah Bron
Hm, I've run into a problem. How can I create a recursive helper, while keeping the HTML in the template file, and the logic in the helper? Maybe the helper should execute a callback created by the template to output each nested item?