Helper classes for building WordPress theme in the LIN3S way
After implementing several WordPress themes, we built what we think can be considered as best practices building this kind of projects in a clean, consistent and fast way: thus was born LIN3S's WordPress Standard Edition. We are really happy with it, but there are some tasks that are very repetitive and tedious, furthermore each developer usually implements in a different way so, with this library we try to avoid these kind of troubles. At this moment, WPFoundation only contains a set of interfaces and abstract classes (in the future who knows :)) to force all developers to follow the same way becoming our code more consistent.
The recommended and the most suitable way to install is through Composer. Be sure that the tool is installed in your system and execute the following command:
$ composer require lin3s/wp-foundation
The following code snippets are representative code samples of how can it use this library:
- Ajax
- Configuration
- PostTypes
- Twig
- Widgets
(...)
use LIN3S\WPFoundation\Ajax\Ajax;
final class MyAwesomeAjax extends Ajax
{
/**
* {@inheritdoc}
*/
protected $action = 'my_awesome_ajax';
/**
* {@inheritdoc}
*/
public function ajax()
{
(...)
die('returning data');
}
}
ACF configuration class, this class is responsible for all the logic about this WordPress plugin. A this moment this API only has one method that allows to have seamlessly multiple WYSWYG configuration for this type field used by ACF.
(...)
use LIN3S\WPFoundation\Configuration\Acf\Acf;
final class Acf extends BaseAcf
{
/**
* {@inheritdoc}
*/
public function wyswygToolbars()
{
return [
'basic' => [1 => ['bold', 'italic']],
'lin3s' => [1 => ['bold', 'italic', 'bullist', 'numlist', 'link', 'unlink']],
];
}
}
(...)
use LIN3S\WPFoundation\Configuration\Assets\Assets as BaseAssets;
final class Assets extends BaseAssets
{
/**
* {@inheritdoc}
*/
public function productionAssets()
{
$this
->addScript('app.min', self::BUILD_JS, ['jquery', 'jquery.counterup', 'sidr']);
}
/**
* {@inheritdoc}
*/
public function developmentAssets()
{
$this
->addScript('jquery.sidr.min', self::VENDOR . '/sidr')
->addScript('waypoints', self::VENDOR . '/jquery-waypoints')
->addScript('jquery.counterup', self::VENDOR . '/Counter-Up')
->addScript('counter', self::ASSETS_JS, ['jquery', 'jquery.sidr.min', 'waypoints', 'jquery.counterup'])
->addScript('typekit', self::ASSETS_JS, [], '1.0.0', false)
->addScript('menu')
->addScript('accordion')
->addScript('post-ajax', self::ASSETS_JS, [], '1.0.0', false, 'postsAjax')
}
/**
* {@inheritdoc}
*/
public function adminAssets()
{
$this->addStylesheet('adminCss');
$this->addScript('adminScript');
}
}
Mailer
class configures the way that emails are sent using wp_mail()
. You should configure the mailer parameters
editing the WordPress config file. Default parameters are given for the localhost smtp delivery.
You can define your own custom mailer that implements MailInterface
and uses wp_mail()
configuration selected
creating an instance of one of the two strategies above.
(...)
use LIN3S\WPFoundation\Configuration\Mailer\MailInterface;
use Timber;
final class ContactMail implements MailInterface
{
/**
* {@inheritdoc}
*/
public static function mail($request)
{
wp_mail(
MAILER_TO,
'Contact'
Timber::compile('mail/mail.twig', ['request' => $request]),
['Content-Type: text/html; charset=UTF-8']
);
}
}
MailerInterface
is deprecated and will be removed in v2.0.0. Use wp_mail() directly to send the emails
// src/App/App.php
use LIN3S\WPFoundation\Configuration\Menus\Menus
class App extends Theme {
public function classes() {
(...)
new Menus([
self::MENU_AWESOME => 'Awesome menu'
]
}
}
(...)
use LIN3S\WPFoundation\Configuration\Theme\Theme;
final class AwesomeTheme extends Theme
{
/**
* {@inheritdoc}
*/
public function classes()
{
new Assets();
new Acf();
new Mailer();
new Menus();
new CustomPostType();
}
/**
* {@inheritdoc}
*/
public function templates($templates)
{
return array_merge($templates, [
'index' => 'Index',
'customs' => 'Customs',
]);
}
/**
* {@inheritdoc}
*/
public function context(array $context)
{
$context['mainMenu'] = new TimberMenu('main-menu');
$data['lang'] = ICL_LANGUAGE_CODE;
return $context;
}
}
\LIN3S\WPFoundation\Configuration\Translations\Translations::trans('Your awesome string');
Declaring a post type is as easy as creating a new instance of PostType
.
// src/App/App.php
class App extends Theme {
public function classes() {
(...)
new PostType(
PostTypes::CUSTOM_POST_TYPE,
[
'labels' => [
'name' => Translations::trans('Exhibitions'),
'singular_name' => Translations::trans('Exhibition'),
],
'has_archive' => true,
'public' => true,
'publicly_queryable' => true,
'query_var' => true,
'show_in_rest' => true,
'show_ui' => true,
'supports' => ['title', 'editor', 'thumbnail'],
]
)
}
}
To add custom fields to a custom post type just create a Fields
instance:
// src/App/App.php
class App extends Theme {
public function classes() {
(...)
new Fields(
PostTypes::CUSTOM_POST_TYPE,
[
Fully\Qualified\Namespace\Components\CustomFieldComponent::class,
],
new PostTypeFieldConnector(PostTypes::CUSTOM_POST_TYPE)
['editor'],
['comments']
);
}
}
(...)
use LIN3S\WPFoundation\PostTypes\Field\FieldComponent;
final class CustomFieldComponent extends FieldComponent
{
/**
* {@inheritdoc}
*/
public static function definition($aName)
{
return [
'key' => sprintf('field_%s_component', $aName),
(...)
]);
}
}
(...)
use LIN3S\WPFoundation\PostTypes\Fields\PageFields as BasePageFields;
final class PageFields extends BasePageFields
{
/**
* {@inheritdoc}
*/
private $name = 'my_awesome_template;
/**
* {@inheritdoc}
*/
public function components()
{
return [
'Fully\Qualified\Namespace\Components\CustomFieldComponent',
];
];
}
(...)
use LIN3S\WPFoundation\PostTypes\RewriteRules\RewriteRules;
final class CustomRewriteRules extends RewriteRules
{
/**
* {@inheritdoc}
*/
public function rewriteRules()
{
add_rewrite_rule(
'^custom-base-url/([^/]*)/([^/]*)/([^/]*)/?$',
'index.php?category=$matches[1]&subcategory=$matches[2]&custom=$matches[3]',
'top'
);
add_rewrite_rule(
'^custom-base-url/([^/]*)/([^/]*)/?$',
'index.php?category=$matches[1]&subcategory=$matches[2]',
'top'
);
}
/**
* {@inheritdoc}
*/
public function rewriteTags()
{
add_rewrite_tag('%category%', '([^/]*)');
add_rewrite_tag('%subcategory%', '([^/]*)');
add_rewrite_tag('%custom%', '([^/]*)');
}
/**
* {@inheritdoc}
*/
public function templateInclude($template)
{
$controller = new CustomController();
$method = '';
if (get_query_var('category') !== ''
&& get_query_var('subcategory') !== ''
&& get_query_var('custom') != ''
) {
$method = 'showAction';
} elseif (get_query_var('category') !== ''
&& get_query_var('subcategory') !== ''
) {
$method = 'listAction';
}
return $method === '' ? $template : $controller->$method();
}
}
After instantiate the the TagManagerTwig
in your theme, you can just call as following:
(...)
{% block tagManager %}
{{ tagManager('GTM-XXXXXX') }}
{% endblock %}
After instantiate the the TranslationTwig
in your theme, you can just call as following:
(...)
{{ trans('Your awesome string') }}
(...)
use LIN3S\WPFoundation\Widgets\Widget;
final class SocialNetworksWidget extends Widget
{
/**
* {@inheritdoc}
*/
public function widget($args, $instance)
{
$data = [
'beforeWidget' => $args['before_widget'],
'afterWidget' => $args['after_widget'],
'beforeTitle' => $args['before_title'],
'afterTitle' => $args['after_title'],
'twitterUrl' => (!empty($instance['twitterUrl'])) ? strip_tags($instance['twitterUrl']) : '',
'facebookUrl' => (!empty($instance['facebookUrl'])) ? strip_tags($instance['facebookUrl']) : '',
'pinterestUrl' => (!empty($instance['pinterestUrl'])) ? strip_tags($instance['pinterestUrl']) : '',
'youtubeUrl' => (!empty($instance['youtubeUrl'])) ? strip_tags($instance['youtubeUrl']) : '',
'rssUrl' => (!empty($instance['rssUrl'])) ? strip_tags($instance['rssUrl']) : '',
];
return Timber::render('widgets/front/socialNetworks.twig', $data);
}
/**
* {@inheritdoc}
*/
public function form($instance)
{
$instance['widgetNumber'] = $this->number();
$instance['widgetName'] = $this->name();
return Timber::render('widgets/admin/socialNetworks.twig', $instance);
}
/**
* {@inheritdoc}
*/
public function update($newInstance)
{
$instance = [
'twitterUrl' => (!empty($newInstance['twitterUrl'])) ? strip_tags($newInstance['twitterUrl']) : '',
'facebookUrl' => (!empty($newInstance['facebookUrl'])) ? strip_tags($newInstance['facebookUrl']) : '',
'pinterestUrl' => (!empty($newInstance['pinterestUrl'])) ? strip_tags($newInstance['pinterestUrl']) : '',
'youtubeUrl' => (!empty($newInstance['youtubeUrl'])) ? strip_tags($newInstance['youtubeUrl']) : '',
'rssUrl' => (!empty($newInstance['rssUrl'])) ? strip_tags($newInstance['rssUrl']) : '',
];
return $instance;
}
}
(...)
use LIN3S\WPFoundation\Widgets\Areas\WidgetArea;
final class CustomWidgetArea extends WidgetArea
{
/**
* {@inheritdoc}
*/
public function widgetArea()
{
register_sidebar([
'name' => 'Custom widgets',
'id' => 'custom-widgets',
'before_widget' => '<section class="custom-widget">',
'after_widget' => '</section>',
'before_title' => '<h5>',
'after_title' => '</h5>',
]);
}
}