-
Notifications
You must be signed in to change notification settings - Fork 1
Data fetching and returning
Context and task are two key aspects of Willow, they are equivalent to Class and Method in PHP and all Willows retrieve data from a single public php method within a class
Willow comes with the following "contexts", which can be extended via plugins, themes or external libraries
- action
- extension
- group
- media
- meta
- module
- navigation
- partial
- post
- taxonomy
- ui
- user
- widget
- wordpress
There use in most cases is totally liberal, as such you can extend the ui context to return data related to taxonomies or wordpress - the available contexts are provided as a broad group of labels by which to group similar functions, rather than as rigid constraints.
The exceptions to the above rule are the action, group and partial contexts which are designed for specific use-cases:
WordPress actions are perhaps what make it such a popular and flexible tool, as they provide developers with a simple and powerful way to change many aspects of how data stored in the database is retrieved and displayed.
Actions are also required to load in assets or to hook callbacks, as such they are a required part of templating - here is a simple example of how Willow can be used to call the wp_head action
{~ action~wp_head ~}
WordPress actions might return data, such as loading assets, Willow facilitates this behaviour by wrapping the action callback in output buffering, capturing the returned data and adding it to the template in the defined spot where the action is called.
The group context was designed to work with ACF groups, returning data in the correct format for rendering single fields and repeater fields, but this functionality is only available if the Q Plugin is also installed and active:
Group fields used along-side JSON formatted ACF configuration settings make for an extremely powerful and portable toolset for development - the ACF classes in Q mean that little to zero additional data controllers are required between adding fields and rendering data in templates.
<div class='col-12 card-columns'>
{~ group~frontpage_feature {+ [a]
config = debug: false &
markup = template: "
{@ {: frontpage_feature :}
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>{{ title }}</h5>
<p class='card-text'>{{ content }}</p>
<a href='{{ url }}' class='btn btn-primary'>More</a>
</div>
</div>
@}"
+} ~}
</div>
The Group context can still be extended like any other context.
Partials are simply re-usable collections of html, JS or text, such as a button or a call to action, they cannot contain other Willow tags and are not parsed by Willow before being rendered.
Partials are stored as text files with a .willow extension - here is an example from one of our Q Themes:
{> search_trigger <}
library/view/context/parent/partial/partial~search_trigger.willow
<div class="row ml-0">
<div class="col-12 list-group list-group-flush border-top">
<div class="list-group-item">
You can also
<a
class="ml-1 btn btn-primary text-white p-2 q-scroll-top"
data-toggle="collapse"
data-target="#search_content"
aria-controls="search_content"
aria-expanded="false"
aria-label="Search navigation"
href="#">
Search our Work
</a>
</div>
</div>
</div>When you call a Partial, Willow simply looks for a matching stored configuration file and returns the data, as shown below:
file: q-willow/library/context/partial.php
public static function get( $args = null ) {
return core\config::get([ 'context' => $args['context'], 'task' => $args['task'] ]);
}
If no matching context/task pair is found, no data will be returned and the partial will render nothing, being removed from the template by the parser cleanup process.
The location of the partial file is important due to how the configuration lookups work - read more
When data returned from a context/task includes arrays of arrays, variables can be accessed directly using dot notation - take the following example which returns both all the commits and also the latest commit version from an ACF group called work_commit
This Willow is stored in it's own configuration file, located at library/view/context/parent/group/group~work_commit.willow
<span class="ml-1">
<a
class="p-1 p-sm-2 btn btn-primary"
href="#commits"
data-modal-toggle='modal'
data-modal-size="modal-lg"
data-modal-title='Commit History'
data-modal-body="<table class='table'><thead><tr><th scope='col'>Release</th><th scope='col'>Details</th></tr></thead><tbody>{@ {: work_commit :} <tr><td>{{ work_commit_version }}</td><td>{{ [e] work_commit_message }}</td></tr> @}</tbody></table>" data-modal-target='#q_modal'>
Version: {{ work_commit.0.work_commit_version }}
</a>
</span>
The Willow is called simply from the template using the following tag:
{~ group~work_commit ~}
Note that the latest version is available via Version: {{ work_commit.0.work_commit_version }}
Another example, again pulling data from ACF - this time from a field group called frontpage_work
configuration sits in its own file at library/view/context/parent/group/group~frontpage_work.willow
<h5 class="row"><div class="col-12 my-3 ml-3">{{ frontpage_work_title }}</div></h5>
<div class="card mb-3">
<a href="{{ frontpage_work_top.post_permalink }}">
<img class="fit card-img-top lazy" style="max-height: 200px" src=""
data-src="{{ frontpage_work_top.src {+ [a] config->handle = square-sm +} }}" />
</a>
<div class="card-body">
<h5 class="card-title">
<a href="{{ frontpage_work_top.post_permalink }}">
{{ frontpage_work_top.post_title }}
</a>
</h5>
<p class="card-text">frontpage_work_top.post_excerpt</p>
<span class="badge badge-pill badge-primary ml-1">
{{ frontpage_work_top.category_name }}
</span>
</div>
</div>
The Willow is called from the template using:
`{~ group~frontpage_work ~}
One of the fields defined in the field group is called frontpage_work_top and is defined as a Post Object - the data formatter in Q has converted the
returned Object into a dot notated array, with each field value available at frontpage_work_top.post_excerpt or frontpage_work_top.post_title - these can then be used directly as Willow variables - such as {{ frontpage_work_top.post_excerpt }}
Most Willow contexts include only one task, a getter which looks for a matching context/task ( class::method ) in the Q plugin - take the following example:
{~ post~title ~}
This Willow will hit the post context and look for a task title, the process for that look up works in the following order:
- Check for a registered extension, with a class
postand a public methodtitle - Check for a public method within the base
postclass with a methodtitle - Check for a matching getter method in the Q plugin i.e.
method_exists( '\q\get\post', $method )
The following example shows how to extend the ui context ( it would work for any other context )
<?php
namespace q\theme\context;
// willow ##
use q\willow; // to extend ##
// register class to render ##
\q\theme\context\ui::run();
class ui {
public static function run( $args = null ) {
// check for willow ##
if( ! class_exists( 'q_willow' ) ){ return false; }
$class = new \ReflectionClass( __CLASS__ );
$methods = $class->getMethods( \ReflectionMethod::IS_PUBLIC );
foreach( $methods as $key ){ $public_methods[] = $key->name; } // match format returned by get_class_methods() ##
// register new class methods ##
\add_action( 'after_setup_theme', function() use ( $public_methods ) {
willow\context\extend::register([
'context' => str_replace( __NAMESPACE__.'\\', '', __CLASS__ ),
'class' => __CLASS__,
'methods' => $public_methods // public only
]);
}, 2 );
}
/**
* Example extension method
*
* @param Array $args
* @since 4.1.0
* @return Array
*/
public static function hello( $args = null ) {
// define key + values ##
return
[
'data' => [ //
'0' => [
'who' => 'You',
'time' => rand(),
],
'1' => [
'who' => 'Me',
'time' => rand(),
]
]
]
;
}
}