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:
