jarednova/timber — pull request #138 by mgmartel (2014-01-02 20:30:30+00:00)
Title: Use main WP Loop with Iterators

Hi Jared!

Happy new year :)

I have been playing with the idea of getting the ordinary WP loop to work more nicely with Timber. When I used an iterator for something else the other day and I figured out an elegant way: if we made a `Traversable` WP_Query, it would work in a Twig for loop.

So, I created two iterators: `TimberQueryIterator` and `TimberPostsIterator`, that replace the whole `Timber::get_posts` functionality. Everything still works (almost) exactly the same, but now while using the 'normal' WP Query, with all WP goodness that comes with it. (Stuff like `get_the_ID` can now be used in functions/plugins called in templates)

* * *

TimberQueryIterator
----

This one takes a query, sets up a WP_Query object, and turns it into an Iterator that can be used in a Twig for loop. It simply maps `WP_Query::have_posts()` and `WP_Query::the_post()` to `::valid()` and `::current()` respectively, looping the loop the WP way.

TimberPostsIterator
----

Takes an array of post objects (of any kind) and converts them into an array of `TimberPosts` (or whatever `$post_class` you give it). Whenever you loop over it, this one simply sets the current post as the global `$post` - all to the same effect.

* * *

`Timber::get_posts` automatically decides which iterator to use.

With this change, all 'Post Retrieval' methods in Timber, except `get_posts` and `get_post`, are now unused. I left them in there (and let them partly implement `TimberPostsIterator`), but perhaps these should be deprecated with the iterators in place.

Only caveat is that `TimberQueryIterator` can't be used as an array entirely. So if somebody did array-foo on the return of `Timber::get_posts`, they could run into trouble. Ironically, one of the unit tests uses an array offset. This could be fixed by letting `TimberQueryIterator` implement `ArrayAccess` (so it also gets offset methods), but I think this is pushing a lot of extra complexity into the object for an edge use-case. (In the end, the goal of `Timber::get_posts` is to be used in a Twig template..)

Curious to hear your thoughts!

Mike