Flourish PHP Unframework
This is an archived copy of the forum for reference purposes

Another fTemplating improvement

posted by ihumanable 9 years ago

In a previous suggestion I talked about a widget system that I'm working with (this thread can be found here, http://flourishlib.com/discussion/2/261)

As this system has gotten some more real world use it has become necessary, for my project, to have a way to place an element at the beginning of an fTemplating array.

Using some of the code from before:


//In the common init.php
 
$template = new fTemplating('/path/to/templates/');

//Get a handle to the special widget, it will be shown at the top of a special page
$template->set('special-widget', 'widgets/special.widget.php');
 
//On most pages we will show the a, b, c, and d widgets
$template->set('a-widget', 'widgets/a.widget.php');
$template->set('b-widget', 'widgets/b.widget.php');
$template->set('c-widget', 'widgets/c.widget.php');
$template->set('d-widget', 'widgets/d.widget.php');

$template->add('widgets', 'a-widget');
$template->add('widgets', 'b-widget');
$template->add('widgets', 'c-widget');
$template->add('widgets', 'd-widget');

Then later on being able to prepend allows me to do something like this

//Put the special widget first
$template->prepend('widgets', 'special-widget');
$template->place('widget-panel');

To acheive this I added a method to the fTemplating class following the same code style as the rest of the class.

	/**
	 * Adds a value to the beginning of an array element
	 *
	 * @param string $element The element to add to
	 * @param mixed $value The value to add
	 * @param fTemplating The template object to allow for method chaining
	 */
	public function prepend($element, $value) {
	  if(!isset($this->elements[$element])) {
	    $this->elements[$element] = array();
	  }
	  if(!is_array($this->elements[$element])) {
	    throw new fProgrammerException(
	      '%1$s was called for an element, %2$s, which is not an array',
	      'prepend()',
	      $element
	    );
	  }
	  array_unshift($this->elements[$element], $value);
	  
	  return $this;
	}

For the sake of symmetry I added an append function that simply calls the add function.

This was useful for my use-case but may not be generally useful. I submit this code for consideration of inclusion.

How about a third optional parameter for fTemplating::add() that would allow adding at the beginning? This would reduce the amount of code and would prevent having to create append for symmetry sake.

posted by wbond 9 years ago

That is an equally acceptable solution. Thanks for taking the time to look at this Will. I wonder then if it makes sense to allow arbitrary insertion, something like the following:

//Referencing the code from above
$template->add('widgets', 'special-widget', 0);
//widgets would look like:
// array ( 'special',
//         'a',
//         'b',
//         'c',
//         'd'        );


$template->add('widgets', 'special-widget', 2);
//widgets would look like:
// array ( 'a',
//         'b',
//         'special',
//         'c',
//         'd'        )

This does lead to some thorny questions like what would -1 do, it could follow some of the other functions in the php language (like substr) and place it at the end of the array. What happens if you give a number greater than the length, in the above example what would the following code do.

$template->add('widgets', 'special-widget', 10);

Flourish is such a wonderful library because of it's straightforward nature, so although arbitrary positioning would be nice, unless you can think of some ways to handle these weird edge cases, it would probably be best to just have a boolean flag as the third parameter.

Thanks again for your attention.

posted by ihumanable 9 years ago

In r904 I added the boolean parameter to add things at the beginning. I decided this was the most straight-forward solution, and anything beyond that was getting complicated.

Just to let you know, I did break backwards compatibility with that release. The method you had requested added, fTemplating::remove() was renamed to fTemplating::filter() since that was a more accurate name. In addition, a new fTemplating::remove() was added that is the opposite of fTemplating::add(). It will remove an element from the end of an array and return it. It accepts an optional boolean parameter to remove the value from the beginning instead of the end.

It is also now possible to use array dereference syntax in element names with fTemplating to access or set those values:

$template->set('user', array(
    'first_name' => 'John',
    'last_name'  => 'Smith'
));
echo $template->get('user[first_name]');
$template->set('user[logged_in]', TRUE);
posted by wbond 9 years ago