<?php
|
namespace JVBase\blocks;
|
|
use JVBase\base\Options;
|
use JVBase\base\Site;
|
use JVBase\managers\Cache;
|
use JVBase\forms\TaxonomySelector;
|
use JVBase\meta\Form;
|
use JVBase\meta\Meta;
|
use JVBase\meta\Render;
|
use WP_Block;
|
use WP_Query;
|
|
if (!defined('ABSPATH')) {
|
exit; // Exit if accessed directly
|
}
|
|
class MenuBlock
|
{
|
protected Cache $cache;
|
protected string $config;
|
protected string $type;
|
protected string $path = JVB_DIR . '/build/menu';
|
protected string $image;
|
protected string $header;
|
protected array $params = ['all'];
|
protected string $headerExtra;
|
protected string $detailsTitle;
|
protected array $details;
|
protected array|false $sections = false;
|
protected string $base;
|
|
public function __construct()
|
{
|
$this->cache = Cache::for('menu', WEEK_IN_SECONDS)->connect('post');
|
if (Site::hasIntegration('square')) {
|
$this->base = '_square_';
|
} else if (Site::hasIntegration('helcim')) {
|
$this->base = '_helcim_';
|
}
|
add_action('init', [ $this, 'registerBlock' ]);
|
}
|
|
public function registerBlock():void
|
{
|
register_block_type($this->path, [
|
'render_callback' => [ $this, 'render' ]
|
]);
|
}
|
|
protected function buildParams():void
|
{
|
if (is_post_type_archive(BASE.'menu_item')) {
|
$this->params = ['all'];
|
} elseif (is_tax(BASE.'section')) {
|
$this->params = [];
|
} else {
|
$this->params = [];
|
}
|
}
|
|
public function render(array $attributes, string $content, WP_Block $block)
|
{
|
$this->buildParams();
|
if (empty($this->params)) {
|
return '';
|
}
|
jvbInlineStyles('forms');
|
$key = $this->cache->generateKey($this->params);
|
$this->cache->flush();
|
return $this->cache->remember(
|
$key,
|
function() {
|
ob_start();
|
$this->renderBlock();
|
return ob_get_clean();
|
}
|
);
|
}
|
|
protected function renderBlock():void
|
{
|
$this->renderHeader();
|
$this->renderMenu();
|
$this->renderOnThisPage();
|
}
|
|
protected function renderHeader():void
|
{
|
$title = 'Our Menu';
|
if(!in_array('all', $this->params)) {
|
$title = '<small>'.$title.'</small>';
|
}
|
|
?>
|
<header id="top">
|
<h1><?=$title?></h1>
|
<nav class="menu"><ul>
|
<?php
|
$sections = $this->getSections();
|
foreach ($sections as $section) {
|
if (!jvbTermHasPosts($section['id'], BASE.'section')) {
|
continue;
|
}
|
?>
|
<li><a href="#<?=sanitize_title($section['name'])?>" title="Jump to <?=$section['name']?>"><?=$section['name']?></a></li>
|
<?php
|
}
|
?>
|
</ul></nav>
|
</header>
|
<?php
|
}
|
|
protected function getSections():array
|
{
|
if (!$this->sections) {
|
$sections = Options::get('menu_section_order');
|
if (!is_array($sections)) {
|
$sections = [];
|
}
|
$this->sections = $sections;
|
}
|
|
return $this->sections;
|
}
|
|
protected function renderMenu():void
|
{
|
$sections = $this->getSections();
|
foreach ($sections as $section) {
|
$items = new WP_Query([
|
'post_type' => BASE.'menu_item',
|
'order' => 'ASC',
|
'posts_per_page' => -1,
|
'tax_query' => [
|
[
|
'taxonomy' => BASE.'section',
|
'terms' => (int) $section['id'],
|
]
|
],
|
'fields' => 'ids'
|
]);
|
if ($items->have_posts()) {
|
$slug = sanitize_title($section['name']);
|
?>
|
<section id="<?= $slug?>" class="menu-section">
|
<h2><?=$section['name']?></h2>
|
<hr>
|
<?= (array_key_exists('description', $section) && $section['description'] !== '') ? $section['description'] : ''?>
|
<div class="menu-items">
|
<?php
|
foreach ($items->posts as $ID) {
|
$this->renderMenuItem($ID, $slug);
|
}
|
?>
|
</div>
|
</section>
|
<?php
|
}
|
wp_reset_postdata();
|
}
|
}
|
|
protected function renderMenuItem(int $ID, string $slug, string $postType = 'menu_item') {
|
$meta = Meta::forPost($ID);
|
$fields = $meta->getAll();
|
$values = $meta->getAll([
|
'post_title',
|
$this->base.'item_id',
|
$this->base.'price',
|
$this->base.'product_variations',
|
'max_order',
|
'min_order',
|
'step'
|
]);
|
$priceRange = jvbCurrency($values[$this->base.'price']);
|
$variations = $values[$this->base.'product_variations'];
|
|
if(!empty($variations) && $variations[0][$this->base.'name'] === '') {
|
$variations = [];
|
}
|
|
if (!empty($variations)) {
|
$prices = [];
|
foreach ($variations as $row) {
|
if (isset($row[$this->base.'price']) && is_numeric($row[$this->base.'price'])) {
|
$prices[] = (float) $row[$this->base.'price'];
|
}
|
}
|
if (!empty($prices) && (min($prices) !== max($prices))) {
|
$priceRange = jvbCurrency(min($prices)).' - '.jvbCurrency(max($prices));
|
} elseif (!empty($prices)) {
|
$priceRange = jvbCurrency(max($prices));
|
}
|
}
|
|
$max = $values['max_order']??'';
|
$min = $values['min_order']??'';
|
$step = $values['step']??'';
|
$max = ($max === '') ? 50 : $max;
|
$min = ($min === '') ? 0 : $min;
|
$step = ($step === '') ? 1 : $step;
|
|
|
?>
|
<div class="menu-item<?= !empty($variations) ? ' variable' : '' ?>" data-section="<?=$slug?>" data-label="<?=$values['post_title']?>" data-id="<?=$ID?>">
|
<div class="header row x-btw">
|
<h3><?= $values['post_title']?></h3>
|
<p class="price"><?= $priceRange ?></p>
|
</div>
|
<div class="description">
|
<?= Render::renderFrom($meta, 'post_excerpt')?>
|
</div>
|
<div class="info col right">
|
<?php
|
if (empty($variations)) {
|
echo Form::render(
|
$ID.'|cart_quantity',
|
'',
|
[
|
'type' => 'quantity',
|
'label' => 'Add to Order',
|
'min' => $min,
|
'max' => $max,
|
'step' => $step,
|
'data' => [
|
'price' => $values[$this->base.'price'],
|
'id' => $ID,
|
'catalog-id' => $values[$this->base.'item_id'],
|
'name' => $values['post_title'],
|
'step' => $step,
|
'add-to-cart' => ''
|
],
|
'add' => 'Add 1 '.$values['post_title'].' to cart',
|
'remove' => 'Remove 1 '.$values['post_title'].' from cart',
|
]);
|
} else {
|
foreach ($variations as $index =>$row) {
|
echo sprintf(
|
'<div class="row right nowrap">
|
<div>
|
<h4>%s — %s</h4>
|
%s%s%s
|
</div>',
|
$row[$this->base.'name'],
|
jvbCurrency($row[$this->base.'price']),
|
empty($row[$this->base.'description']) ? '' : wpautop($row[$this->base.'description']),
|
empty($row[$this->base.'ingredients']) ? '' : wpautop('<b>Ingredients:</b>'.$row[$this->base.'ingredients']),
|
empty($row[$this->base.'preparation_time_duration']) ? '' : wpautop('Ready in <b>'.$row[$this->base.'preparation_time_duration'].'</b>'),
|
);
|
echo Form::render(
|
'quantity-'.$index,
|
'',
|
[
|
'type' => 'quantity',
|
'label' => $row[$this->base.'name'],
|
'min' => $min,
|
'max' => $max,
|
'step' => $step,
|
'data' => [
|
'price' => $row[$this->base.'price'],
|
'id' => $ID.'-'.$row[$this->base.'sku'],
|
'catalog-id' => $row[$this->base.'item_id'],
|
'name' => $row[$this->base.'name'],
|
'add-to-cart' => ''
|
],
|
'add' => 'Add 1 '.$row[$this->base.'name'].' to cart.',
|
'remove' => 'Remove 1 '.$row[$this->base.'name'].' from cart.',
|
]
|
);
|
echo '</div>';
|
}
|
}
|
?>
|
</div>
|
|
|
</div>
|
<?php
|
}
|
|
|
protected function renderOnThisPage():void
|
{
|
if (empty($this->details)) {
|
return;
|
}
|
echo jvbOnThisPage(array_keys($this->details));
|
}
|
}
|