<?php
|
namespace JVBase\blocks;
|
|
use DateTime;
|
use JVBase\managers\Cache;
|
use JVBase\meta\Meta;
|
use JVBase\registrar\Registrar;
|
use WP_Block;
|
use WP_Query;
|
|
if (!defined('ABSPATH')) {
|
exit; // Exit if accessed directly
|
}
|
|
class SimpleCalendarBlock
|
{
|
protected Cache $cache;
|
protected string $config;
|
protected string $type;
|
protected string $path = JVB_DIR . '/build/simple-calendar';
|
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;
|
protected array $content;
|
protected array $taxonomies;
|
|
public function __construct()
|
{
|
$this->cache = Cache::for('calendar', 'post', DAY_IN_SECONDS);
|
$this->cache->flush();
|
add_action('init', [ $this, 'registerBlock' ]);
|
}
|
|
public function registerBlock():void
|
{
|
register_block_type($this->path, [
|
'render_callback' => [ $this, 'render' ]
|
]);
|
}
|
|
protected function buildParams():void
|
{
|
$registered = Registrar::withFeature('is_calendar', 'post');
|
$registered = array_map('jvbCheckBase', $registered);
|
$types = [];
|
foreach ($registered as $type) {
|
$registrar = Registrar::getInstance($type);
|
$types[$type] = $registrar->getPlural();
|
}
|
$this->content = $types;
|
|
$taxonomies = [];
|
foreach ($registered as $type) {
|
$registrar = Registrar::getInstance($type);
|
$taxonomies = array_merge($taxonomies, $registrar->registrar->taxonomies);
|
}
|
$taxonomies = array_map('jvbCheckBase', $taxonomies);
|
$types = [];
|
foreach ($taxonomies as $type) {
|
$registrar = Registrar::getInstance($type);
|
$types[$type] = $registrar->getPlural();
|
}
|
$this->taxonomies = $types;
|
|
|
if (is_post_type_archive($registered)) {
|
$this->params = ['all'];
|
} elseif (is_tax($taxonomies)) {
|
$this->params = [];
|
} else {
|
$this->params = [];
|
}
|
|
foreach (['eyear', 'emonth', 'eday'] as $key) {
|
$val = get_query_var($key);
|
if (!empty($val)) {
|
$this->params[$key] = $val;
|
}
|
}
|
|
}
|
|
public function render(array $attributes, string $content, WP_Block $block)
|
{
|
$this->buildParams();
|
if (empty($this->params)) {
|
return '';
|
}
|
|
$this->cache->flush();
|
return $this->cache->remember(
|
$this->params,
|
function() {
|
ob_start();
|
$this->renderBlock();
|
return ob_get_clean();
|
}
|
);
|
}
|
|
protected function renderBlock():void
|
{
|
echo '<section class="simple-calendar">';
|
$this->renderHeader();
|
$this->renderCalendar();
|
$this->renderOnThisPage();
|
echo '</section>';
|
}
|
|
protected function renderHeader():void
|
{
|
$title = $this->determineTitle();
|
|
|
?>
|
|
<header id="top">
|
<h1><?=$title?></h1>
|
<?php $this->buildNav(); ?>
|
</header>
|
<section id="intro">
|
<p>We bring southern-style barbeque eats with Northern flair to any event throughout Alberta.</p>
|
<p><b>Want to bring us to your event?</b> <a href="<?=get_home_url(null,'/book-your-event')?>">Let us know</a>, we'd love to come!</p>
|
</section>
|
<?php
|
}
|
protected function determineTitle():string
|
{
|
if (is_tax(BASE.'event_category')) {
|
$title = sprintf(
|
'%s Events',
|
get_queried_object()->name,
|
);
|
} else {
|
$title = 'Events';
|
}
|
|
|
if(!in_array('all', $this->params)) {
|
$title = '<small>'.$title.'</small>';
|
}
|
if (is_tax(BASE.'city')) {
|
$title .= sprintf(
|
' in %s',
|
get_queried_object()->name,
|
);
|
}
|
if ($this->has('emonth')) {
|
$title .= sprintf(
|
' %s %s',
|
is_tax() ? 'happening on' : 'in',
|
$this->getMonthName((int)$this->has('emonth')),
|
);
|
}
|
if ($this->has('eday')) {
|
$title .= sprintf(
|
' %s,',
|
(int)$this->has('eday')
|
);
|
}
|
if ($this->has('eyear')) {
|
$title.= sprintf(
|
' %s%s',
|
!$this->has('emonth') ? 'in ' : '',
|
$this->has('eyear')
|
);
|
}
|
|
return $title;
|
}
|
protected function buildNav():void
|
{
|
$content = $taxonomies = '';
|
if (count($this->content) > 1) {
|
$out = [];
|
foreach ($this->content as $slug => $title) {
|
$out[] = sprintf(
|
'<li><a href="%s" title="See %s">%s</a></li>',
|
get_post_type_archive_link($slug),
|
$title,
|
$title
|
);
|
}
|
if (!empty($out)) {
|
$content = sprintf(
|
'<ul class="term-list content"><li class="label">Content:</li>%s</ul>',
|
implode('', $out)
|
);
|
}
|
}
|
|
if (!empty($this->taxonomies)) {
|
foreach ($this->taxonomies as $slug => $title) {
|
$check = get_terms([
|
'taxonomy' => $slug,
|
'hide_empty' => true,
|
'orderby' => 'name',
|
]);
|
$out = [];
|
if ($check && !is_wp_error($check)) {
|
foreach ($check as $term) {
|
$out[] = sprintf(
|
'<li><a href="%s" title="See %s">%s</a></li>',
|
get_term_link($term->term_id, $slug),
|
$term->name,
|
$term->name
|
);
|
}
|
}
|
if (!empty($out)) {
|
$taxonomies .= sprintf(
|
'<ul class="term-list row start %s"><li class="label">%s</li>%s</ul>',
|
$slug,
|
$title,
|
implode('', $out)
|
);
|
}
|
}
|
}
|
|
$dates = $this->getDateNavigation();
|
|
if (!is_post_type_archive($this->content[0]) || $this->isDatedArchive()) {
|
echo sprintf(
|
'<a href="%s" class="btn chip">All Events</a>',
|
get_post_type_archive_link($this->content[0])
|
);
|
}
|
if (!empty($content) || !empty($taxonomies) || !empty($dates)) {
|
echo sprintf(
|
'<nav class="calendar types">%s%s%s</nav>',
|
$content,
|
$taxonomies,
|
$dates
|
);
|
}
|
}
|
protected function isDatedArchive():bool
|
{
|
foreach (['eyear', 'emonth', 'eday'] as $key) {
|
if (array_key_exists($key, $this->params)) {
|
return true;
|
}
|
}
|
return false;
|
}
|
protected function getDateNavigation():string
|
{
|
$type = get_post_type();
|
if (empty($type)) {
|
return '';
|
}
|
|
return $this->cache->remember(
|
$type.'dateNav',
|
function() use ($type) {
|
$tmp = new WP_Query([
|
'post_type' => $type,
|
'post_status' => 'publish',
|
'posts_per_page' => -1,
|
'fields' => 'ids',
|
]);
|
$dates = [];
|
foreach ($tmp->posts as $id) {
|
$meta = Meta::forPost($id);
|
$start = $meta->get('date_start');
|
if (!empty($start)) {
|
$date = new DateTime($start);
|
$year = $date->format('Y');
|
$month = $date->format('m');
|
$day = $date->format('d');
|
|
if (!array_key_exists($year, $dates)) {
|
$dates[$year] = [];
|
}
|
if (!array_key_exists($month, $dates[$year])) {
|
$dates[$year][$month] = [];
|
}
|
if (!in_array($day, $dates[$year][$month])) {
|
$dates[$year][$month][] = $day;
|
}
|
}
|
}
|
if (empty($dates)) {
|
return '';
|
}
|
|
$base = get_post_type_archive_link($type);
|
$out = sprintf(
|
'<details class="dates row start"><summary>%sBy Date</summary>',
|
jvbIcon('calendar')
|
);
|
foreach ($dates as $year => $months) {
|
$out .= sprintf(
|
'<details><summary><a href="%s/%d" title="See all in %d">%d</a></summary><ul>',
|
$base,
|
$year,
|
$year,
|
$year
|
);
|
|
foreach ($months as $month => $days) {
|
$m = intval($month);
|
$monthName = $this->getMonthName($m);
|
|
$out .= sprintf(
|
'<li><a href="%s/%d/%s" title="View all posts in %s, %d">%s</a></li>',
|
$base,
|
$year,
|
$month,
|
$monthName,
|
$year,
|
$monthName
|
);
|
}
|
$out .= '</ul></details>';
|
}
|
$out .= '</details>';
|
|
return $out;
|
}
|
);
|
}
|
|
protected function renderCalendar():void
|
{
|
?>
|
<details id="calendar" open>
|
<summary><h2>Upcoming Events <?= jvbIcon('calendar-blank')?></h2></summary>
|
<?= $this->getEvents() ?>
|
</details>
|
<details class="past">
|
<summary><h2>Past Events <?= jvbIcon('calendar-check')?></h2></summary>
|
<?= $this->getEvents(true) ?>
|
</details>
|
<?php
|
}
|
|
protected function getCurrentPostTypes():array
|
{
|
if (is_post_type_archive()) {
|
return [get_queried_object()->name];
|
}
|
if (is_singular()) {
|
return [get_queried_object()->post_type];
|
}
|
if (is_tax()) {
|
$tax = get_queried_object();
|
jvbDump($tax, 'taxonomy');
|
}
|
return [];
|
}
|
protected function getEvents(bool $past = false):string
|
{
|
|
$events = '';
|
if (is_singular()) {
|
return $this->formatSingular();
|
}
|
|
$items = new WP_Query($this->buildArgs($past));
|
|
$events = implode('', array_map([$this, 'formatItem'], $items->posts));
|
|
$events = empty($events) ? '<p class="empty">Nothing here yet</p>' : sprintf(
|
'<ul class="item-list">%s</ul>',
|
$events
|
);
|
$total = $items->max_num_pages;
|
if ($total > 1) {
|
$big = 999999999; // need an unlikely integer
|
$format = $past ? 'jpast' : 'jpage';
|
$events .= paginate_links([
|
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
|
'format' => '?'.$format.'=%#%',
|
'current' => $items->query_vars['paged'],
|
'total' => $total
|
]);
|
}
|
|
wp_reset_postdata();
|
|
return $events;
|
}
|
|
protected function buildArgs(bool $past):array
|
{
|
$page = $past
|
? min($_GET['jpast']??1, 1)
|
: min($_GET['jpage']??1, 1);
|
$postTypes = $this->getCurrentPostTypes();
|
|
$args = [
|
'post_type' => $postTypes,
|
'post_status' => 'publish',
|
'orderby' => 'meta_value',
|
'meta_key' => BASE.'date_start',
|
'meta_type' => 'DATETIME',
|
'posts_per_page'=> 30,
|
'fields' => 'ids',
|
'paged' => $page,
|
'meta_query' => [
|
[
|
'key' => BASE.'past',
|
'value' => '1',
|
'compare' => $past ? 'EXISTS' : 'NOT EXISTS'
|
]
|
]
|
];
|
|
|
if ($this->has('eyear')) {
|
$args['meta_query'][] = [
|
'key' => BASE.'year',
|
'value' => intval($this->has('eyear')),
|
];
|
}
|
if ($this->has('emonth')) {
|
$args['meta_query'][] = [
|
'key' => BASE.'month',
|
'value' => str_pad($this->has('emonth'), 2, "0", STR_PAD_LEFT),
|
];
|
}
|
if ($this->has('eday')) {
|
$args['meta_query'][] = [
|
'key' => BASE.'day',
|
'value' => str_pad($this->has('eday'), 2, "0", STR_PAD_LEFT),
|
];
|
}
|
if (is_tax()) {
|
$obj = get_queried_object();
|
$args['tax_query']= [
|
[
|
'taxonomy' => $obj->taxonomy,
|
'terms' => $obj->term_id,
|
]
|
];
|
}
|
return $args;
|
}
|
|
|
protected function formatItem(int $ID):string
|
{
|
$meta = Meta::forPost($ID);
|
$type = jvbNoBase(get_post_type($ID));
|
$date = strtotime($meta->get('date_start'));
|
return sprintf(
|
'<li class="item %s">
|
%s
|
<h3>
|
<a href="%s" title="Learn More">%s</a>
|
<small><time datetime="%s">%s</time></small>
|
</h3>
|
%s
|
</li>',
|
$type,
|
empty($meta->get('post_thumbnail')) ? '' : jvbFormatImage($meta->get('post_thumbnail'), 'tiny', 'medium'),
|
get_the_permalink($ID),
|
$meta->get('post_title'),
|
date('c', $date),
|
date('F j, Y', $date),
|
empty($meta->get('post_excerpt')) ? '' : wpautop($meta->get('post_excerpt'))
|
);
|
}
|
|
protected function formatSingular():string
|
{
|
return '';
|
}
|
|
|
protected function renderOnThisPage():void
|
{
|
if (empty($this->details)) {
|
return;
|
}
|
echo jvbOnThisPage(array_keys($this->details));
|
}
|
|
protected function has(string $key):false|string
|
{
|
return array_key_exists($key, $this->params) && absint($this->params[$key]) > 0 ?
|
$this->params[$key] :
|
false;
|
}
|
|
protected function getMonthName(int $num):string
|
{
|
return match($num) {
|
1 => 'January',
|
2 => 'February',
|
3 => 'March',
|
4 => 'April',
|
5 => 'May',
|
6 => 'June',
|
7 => 'July',
|
8 => 'August',
|
9 => 'September',
|
10 => 'October',
|
11 => 'November',
|
12 => 'December',
|
};
|
}
|
}
|