Content Providers

 

Introduction

Sometimes you need to use external data within your Phrozn pages. For the most obvious example, let's assume you have an RSS feed and want to display it's contents on some Phrozn page. Content providers are exactly for this kind of tasks.

Content providers are classes that inject content within your otherwise static pages. Roughly, they represent Data Access Layer between your entity templates and whatever data you need to feature on those templates.

Content providers may be as simple as some array of elements you want to traverse within your templates. They can be more quite complex as well, involving fetching data from some external service, process it and then inject into templates.

Content Provider Class

All extension classes MUST reside in .phrozn/plugins folder.
Base namespace used for plugin code is PhroznPlugin.

In order for your class to be used as Content Provider it MUST implement Phrozn\Provider interface.

namespace Phrozn;
use Phrozn\Has;

interface Provider
    extends Has\Config,
            Has\ProjectPath
{
    /**
     * Get generated content
     *
     * @return mixed
     */
    public function get();
}

As you see, interface is pretty simple with only one relevant method - that's get() method. Other methods are inherited from Has\Config and Has\ProjectPath interfaces and are used to inject extra configuration and project path respectively.

In order to simplify the creation of new content providers, Phrozn comes with base class that implements all this auxiliary functionality, and the only method you generally need to implement is \Phrozn\Provider::get().

Any data returned from get() method can be injected into templates. While you can return scalars, it is more common to return arrays, and if you need scalar it is more convinient to expose it via Front Matter's custom variables.

Injecting Content Into Entries

To use inside entries Content Providers must be included into Front Matter using special variable providers:

providers:
    key:
        provider: ProviderClass
        param: paramValue
        another_param: paramValue

Where,

Entity Description
key Anything you like to use when referring to provider within your entry.
provider Class name of the Content Provider class.
This class must implement \Phrozn\Provider interface.
param(s) You can pass any named parameters to provider class, thus allowing parametrization. Parameters are optional, and if passed can be accessed within provider class by using \Phrozn\Provider::getConfig() method.

As you can see, providers variable is a list, implying that you may have several different providers within the single entry. You can even expose the very same provider under different keys (and using different parameters). See example below, which does exactly that.

Simple Example (List of Primarchs)

Let's start simple and create very basic Content Provider, the one that will only inject bunch of strings into our template.

Here is our simple provider that injects the names of Primarchs into an entry. Standard location for processor classes is plugins/Provider, so we save this as plugins/Provider/Primarchs.php:

namespace PhroznPlugin\Provider;

class Primarchs
    extends \Phrozn\Provider\Base
    implements \Phrozn\Provider
{
    private $primarchs = array(
        array("Lion El'Jonson",           "Dark Angels",                  "Loyal"),
        array("Fulgrim",                  "Emperor's Children",           "Traitor"),
        array("Perturabo",                "Iron Warriors",                "Traitor"),
        array("Jaghatai Khan",            "White Scars",                  "Loyal"),
        array("Leman Russ",               "Space Wolves",                 "Loyal"),
        array("Rogal Dorn",               "Imperial Fists",               "Loyal"),
        array("Night Haunter",            "Night Lords",                  "Traitor"),
        array("Sanguinius",               "Blood Angels",                 "Loyal"),
        array("Ferrus Manus",             "Iron Hands",                   "Loyal"),
        array("Angron",                   "World Eaters",                 "Traitor"),
        array("Roboute Guilliman",        "Ultramarines",                 "Loyal"),
        array("Mortarion",                "Death Guard",                  "Traitor"),
        array("Magnus the Red",           "Thousand Sons",                "Traitor"),
        array("Horus",                    "Luna Wolves/Sons of Horus",    "Traitor"),
        array("Lorgar",                   "Word Bearers",                 "Traitor"),
        array("Vulkan",                   "Salamanders",                  "Loyal"),
        array("Corax",                    "Raven Guard",                  "Loyal"),
        array("Alpharius1   Omegeon2",    "Alpha Legion",                 "Complicated"),
    );

    public function get()
    {
        // get reference to configuration object (it holds passed vars, if any)
        $config = $this->getConfig();

        // form list, replacing numeric keys with associative
        // you can get rid of this by updating original array
        $primarchs = array_map(function ($item) {
            return array(
                'name'          => $item[0],
                'legion'        => $item[1],
                'allegiance'    => $item[2],
            );
        }, $this->primarchs);

        // find who is loyal and who is not!
        if (isset($config['allegiance']) && $allegiance = $config['allegiance']) {
            $primarchs = array_filter($primarchs, function ($primarch) use ($allegiance) {
                return $allegiance === $primarch['allegiance'];
            });
        }

        return $primarchs;
    }
}

If it doesn't make sense just yet, don't worry it will in a minute. Here is corresponding entry file provider.primarchs.twig:

providers:
    all_primarchs:
        provider: Primarchs
    traitor_primarchs:
        provider: Primarchs
        allegiance: Traitor # pass parameter
    loyal_primarchs:
        provider: Primarchs
        allegiance: Loyal
--- 
<h1 id="all-primarchs">All Primarchs:</h1>
<ul>
{% for primarch in this.providers.all_primarchs %}
    <li><b>{{ primarch.name }}</b> of {{ primarch.legion }} ({{ primarch.allegiance}})</li>
{% endfor %}
</ul>

<h1 id="loyal-primarchs">Loyal Primarchs:</h1>
<ol>
{% for primarch in this.providers.loyal_primarchs %}
    <li><b>{{ primarch.name }}</b> of {{ primarch.legion }} ({{ primarch.allegiance}})</li>
{% endfor %}
</ol>

<h1 id="traitor-primarchs">Traitor Primarchs:</h1>
<ol>
{% for primarch in this.providers.traitor_primarchs %}
    <li><b>{{ primarch.name }}</b> of {{ primarch.legion }} ({{ primarch.allegiance}})</li>
{% endfor %}
</ol>

As you see I exposed the same provider class Primarchs under different keys/names. The only difference is parameter (or its absence) passed.

Now, it is a good time to scroll up and review the implemetation of Primarchs::get() method. Pretty simple stuff, right? Check the result page and see for yourself :)

Conclusion

As you see, Phrozn has quite a good support for dynamic content (if you are ok with putting that data into static form).

So, whenever you need to get access to some external data within your entries, the answer is almost always will be Content Providers.

Finally, you can check the code in context on GitHub:

Generated on 14 Jan, 2014 using Phrozn 0.5.6.

Fork me on GitHub