-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Simply create a class with a configure
function that accepts a FieldsBuilder and configure the fields and return the builder.
namespace MyProject\Fields;
use Timber\Image;
use Understory\ACF\FieldsBuilder;
use Understory\ACF\FieldGroup;
class Banner extends FieldGroup
{
private $title;
private $backgroundImage;
public function configure(FieldsBuilder $builder)
{
$builder
->addText('title')
->addWysiwyg('content')
->addImage('background_image');
return $builder;
}
public function getBackgroundImage()
{
// Cache \Timber\Image object
return $this->backgroundImage ?: $this->backgroundImage = new Image($this->getMetaValue('background_image'));
}
// Perform all style attribute logic in the class
public function getBackgroundStyle()
{
$css = [
'min-height' => $this->getBackgroundImage()->height(),
'background-image' => "url({$this->getBackgroundImage()->src()})"
];
return array_reduce(array_keys($css), function($style, $key) use ($css) {
return $style . "{$key}:{$css[$key]};";
}, '');
}
public function getTitle()
{
return $this->title ?: $this->title = $this->getMetaValue('title');
}
public function setTitle($title)
{
$this->title = $title;
}
public function getContent()
{
// Apply the content filter to our wysiwyg content field
return apply_filters('the_content', $this->getMetaValue('content');
}
}
Then you can associate it with a post type, view, etc.
namespace MyProject\Models;
use MyProject\Fields\Banner;
use Understory\CustomPostType;
use Understory\ACF\PostTypeBuilder;
class NewsItem extends CustomPostType
{
private function configure(PostTypeBuilder $postTypeBuilder)
{
$postTypeBuilder->setConfig([
'supports' => 'title, thumbnail, content, excerpt',
]);
// Register post type with the banner custom field group
$this->has('banner', new Banner);
return $postTypeBuilder;
}
}
In the Views\single-news-item.php
view, you can have the logic to display the banner's title if one exists, otherwise default to the News post type's title.
namespace MyProject\Views;
use Understory\View;
use MyProject\Fields\Banner;
class SingleNewsItem extends View
{
private $banner;
/**
* Use the banner associated with the News Item, customize to use the News Item title
* if the title field of the banner was left blank
*/
public function getBanner()
{
if(!$this->banner) {
$this->banner = $this->getPost()->getBanner();
// Use News Item title if a custom banner title wasn't entered
if (!$this->banner->getTitle()) {
$this->banner->setTitle($this->getPost()->getTitle());
}
}
return $this->banner;
}
}
Then in your twig template single-news-item.twig
simply embed the banner template and pass in the banner
{# single-news-item.twig #}
{% extends "base.twig" %}
{% block content %}
{% embed 'section/banner.twig' with { banner: page.banner } %}
{% endembed %}
{# ... Rest of template ... #}
{% endblock %}
Then in the banner twig template section/banner.twig
write once, use everywhere
{# section/banner.twig #}
<section class="section__banner" style="{{ banner.backgroundStyle }}">
<div class="banner__container">
<h1 class="banner__title">{{ banner.title }}</h1>
<div class="banner__content">{{ banner.content }}</div>
</div>
</section>
We can then reuse this banner field and twig template (along with any CSS or javascript written for it) anywhere else, like a View.
/**
* Template Name: Home
*/
namespace MyProject\Views;
use MyProjectFields\Banner;
use Understory\View;
class HomeTemplate extends View
{
public function configure()
{
$this->has('banner', new Banner);
}
/**
* Use the banner associated with the page, customize to use the page title
* if the title field of the banner was left blank
*/
public function getBanner()
{
// Use Page title if a custom banner title wasn't entered
if (!$this->banner->getTitle()) {
$this->banner->setTitle($this->getPost()->getTitle());
}
return $this->banner;
}
}
Then just like the single-news-item template, simply embed the banner template and pass in the banner
{# HomeTemplate.twig #}
{% extends "base.twig" %}
{% block content %}
{% embed 'section/banner.twig' with { banner: page.banner } %}
{% endembed %}
{# ... Rest of template ... #}
{% endblock %}
Since we're doing the same thing in both instances, defaulting to the post title if the banner title field was left blank, perhaps we should move this logic to the field itself.
namespace MyProject\Fields;
use Understory\ACF\FieldGroup;
class Banner extends FieldGroup
{
...
public function getTitle()
{
return $this->getMetaValue('title') ?: $this->getMetaDataBinding()->getTitle();
}
...
}
The scope (MetaDataBinding of a field group is the object (custom post type, options page, etc) that the field group is acting upon.
This will significantly DRY up our view object
namespace MyProject\Views;
use Understory\View;
class SingleNewsItem extends View;
{
private $banner;
public function getBanner()
{
return $this->getPost()->getBanner();
}
}
namespace MyProject\Views;
use Understory\View;
class HomeTemplate extends View
{
private $banner;
public function configure()
{
$this->has('banner', new Fields\Banner);
}
}