34.9% *
Extensive use of:
add_action(
'after_setup_theme', // action / filter name
[$this, 'removeZoomFromGallery'], // callback
99, // priority
2 // accepted argument count
);
add_filter('wp_print_styles', [$this, 'dequeueUnusedAssets'], 99);
add_filter('wp_enqueue_scripts', [$this, 'dequeueUnusedAssets'], 99);
add_filter('after_setup_theme', [$this, 'removeZoomFromGallery'], 99);
add_filter('init', [$this, 'addProductBrandPostType']);
add_filter('add_meta_boxes_product_brand', [$this, 'addProductBrandMetaBoxes']);
add_filter('save_post', [$this, 'saveProductBrandMetaBoxData']);
add_filter('init', [$this, 'addProductFunctionPostType']);
add_filter('add_meta_boxes_product_function', [$this, 'addProductFunctionMetaBoxes']);
add_filter('save_post', [$this, 'saveProductFunctionMetaBoxData']);
add_filter('woocommerce_template_single_price', [$this, 'showPriceNotice'], 10);
add_filter('woocommerce_after_add_to_cart_quantity', [$this, 'showShippingMethod'], 35);
add_filter('woocommerce_single_product_summary', [$this, 'showDivider'], 31);
add_filter('woocommerce_single_product_summary', [$this, 'showReturnAndShippingInfo'], 40);
add_filter('woocommerce_single_product_summary', [$this, 'showDivider'], 41);
add_filter('woocommerce_single_product_summary', [$this, 'showPaymentGateways'], 45);
add_filter('woocommerce_single_product_summary', [$this, 'showDivider'], 49);
add_filter('woocommerce_single_product_summary', [$this, 'showInteractionButtons'], 50);
add_filter('woocommerce_after_single_product_summary', [$this, 'showDivider'], 10);
add_filter('woocommerce_after_single_product_summary', [$this, 'showDescription'], 11);
add_filter('woocommerce_after_single_product_summary', [$this, 'showProductDetails'], 15);
add_filter('woocommerce_after_single_product_summary', [$this, 'showOtherProductsFromSameBrand'], 53);
add_filter('woocommerce_after_single_product_summary', [$this, 'showDivider'], 54);
add_filter('woocommerce_after_single_product_summary', [$this, 'showFaqArea'], 55);
add_filter('woocommerce_after_single_product_summary', [$this, 'showDivider'], 56);
add_filter('woocommerce_after_single_product_summary', [$this, 'showNewsletterForm'], 60);
add_filter('woocommerce_single_product_image_thumbnail_html', [$this, 'showBrandLogoAndFunctionSymbol'], 10, 2);
add_filter('init', function() {
remove_filter('woocommerce_single_product_summary', 'woocommerce_output_product_data_tabs', 35);
remove_filter('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
remove_filter('woocommerce_single_product_summary', 'sf_product_share', 45);
remove_filter('woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40);
add_filter('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 50);
}, 99);
... and that's only one feature.
Downsides of
No templating engine
<main id="main" class="site-main">
<?php
if ( have_posts() ) {
// Load posts loop.
while ( have_posts() ) {
the_post();
get_template_part( 'template-parts/content/content' );
}
// Previous/next page navigation.
twentynineteen_the_posts_navigation();
} else {
// If no content, include the "No posts found" template.
get_template_part( 'template-parts/content/content', 'none' );
}
?>
</main>
hardcoded file names
(more or less)
Getting blade on board
Add required composer packages ...
{
// ...
"require": {
"illuminate/support": "^5",
"illuminate/view": "^5"
}
// ...
}
... and assemble.
Register services
$this->container = new \Illuminate\Container\Container;
$this->container->singleton('files', function() {
return new \Illuminate\Filesystem\Filesystem;
});
$this->container->singleton('events', function() {
return new \Illuminate\Events\Dispatcher;
});
$this->container->singleton('blade.compiler', function() {
return new \Illuminate\View\Compilers\BladeCompiler(
$this->container['files'], // Filesystem
$this->cachePath // Configured value
);
});
$this->container->singleton('view.engine.resolver', function() {
$resolver = new \Illuminate\View\Engines\EngineResolver;
$resolver->register('php', function() {
return new \Illuminate\View\Engines\PhpEngine;
});
$resolver->register('blade', function() {
return new \Illuminate\View\Engines\CompilerEngine(
$this->container['blade.compiler'],
$this->container['files'] // Filesystem
);
});
return $resolver;
});
$this->container->singleton('view.finder', function() {
return new FileViewFinder(
$this->container['files'], // Filesystem
$this->viewPaths // Configured value
);
});
$this->factory = new Factory(
$this->container['view.engine.resolver'],
$this->container['view.finder'],
$this->container['events']
);
$this->factory->setContainer($this->container);
At least we can do this now:
echo $this->factory
->make('my.view')
->render()
Okay, we have pretty views.
What now?
Problems:
Simplified WordPress life cycle
Check URL
Determine kind of data
Determine template to load
apply_filter(
"{$type}_template",
string $template,
string $type,
array $templates
)
... to the rescue
// Default supported types by WordPress:
$templateTypes = [
'index', '404', 'archive', 'author', 'category',
'taxonomy', 'date', 'embed', 'home', 'frontpage',
'privacypolicy', 'page', 'paged', 'search',
'singular', 'attachment', 'single', 'tag',
];
foreach($templateTypes as $templateType) {
add_filter(
"{$templateType}_template",
fn($template, $type, $templates) =>
$this->handleTemplateRequest($template),
99,
3
);
}
public function handleTemplateRequest($template) {
$this->desiredTemplate = $template;
// Here we can decide if we want to intercept or not.
// Now we have full flexibility with naming, etc. Yay!
if (
get_option('maintenance_mode', false) &&
!is_user_logged_in()
) {
$this->desiredTemplate = 'pages.maintenance';
}
return dirname(__DIR__) . '/index.php';
}
the full index.php
<?php
// Make sure we have no direct contact
!defined('ABSPATH') && die('Safety first!');
// Render page
echo \IlluminatedWordPressTheme\TemplatePage::render();
namespace IlluminatedWordPressTheme;
class TemplatePage {
private $template;
private function __construct($template) {
$this->template = $template;
}
public static function render() {
// The class that registered all the filters
$template = ViewController::getInstance()->getTemplate();
return (new static($template))->renderPage();
}
}
public function renderPage() {
$data = $this->getData();
if (!View::make()->exists("templates.{$this->template}")) {
$this->template = 'index';
}
return View::view("templates.{$this->template}")
->with($data)
->render();
}
We solved our problems and made our lives easier.
/sebwas
WordPress share: [https://w3techs.com/technologies/details/cm-wordpress/all/all](https://w3techs.com/technologies/details/cm-wordpress/all/all)
Table lamp by Creative Stall from [the Noun Project](https://thenounproject.com/search/?q=desk%20lamp&i=981470). The original work has been modified.