<?php
|
namespace JVBase\blocks;
|
|
use JVBase\managers\Cache;
|
use JVBase\forms\TaxonomySelector;
|
use WP_Block;
|
|
if (!defined('ABSPATH')) {
|
exit; // Exit if accessed directly
|
}
|
|
class SummaryBlock
|
{
|
protected Cache $cache;
|
protected string $config;
|
protected string $type;
|
protected string $path = JVB_DIR . '/build/summary';
|
protected string $image;
|
protected string $header;
|
protected string $headerExtra;
|
protected bool $isOpen = false;
|
protected string $beforeSummary;
|
protected string $detailsTitle;
|
protected array $details;
|
|
public function __construct()
|
{
|
$this->cache = Cache::for('summary_block', WEEK_IN_SECONDS);
|
add_action('init', [ $this, 'registerBlock' ]);
|
add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);
|
if (JVB_TESTING) {
|
$this->cache->flush();
|
}
|
}
|
|
public function registerBlock()
|
{
|
register_block_type($this->path, [
|
'render_callback' => [ $this, 'render' ]
|
]);
|
}
|
|
public function enqueueScripts():void
|
{
|
wp_enqueue_script('jvb-page-nav');
|
}
|
|
protected function getConfig():string
|
{
|
return (is_tax()) ? 'tax' : 'content';
|
}
|
|
protected function generateKey():string
|
{
|
$obj = get_queried_object();
|
return match (true) {
|
is_tax() => jvbNoBase($obj->taxonomy) . $obj->term_id,
|
is_a($obj, 'WP_Post_type') => jvbNoBase($obj->name),
|
is_a($obj, 'WP_User') => jvbUserRole($obj->ID),
|
default => jvbNoBase($obj->post_type) . $obj->ID,
|
};
|
}
|
|
public function render(array $attributes, string $content, WP_Block $block)
|
{
|
$this->config = $this->getConfig();
|
$key = $this->generateKey();
|
$cache = $this->cache->get($key);
|
|
if ($cache) {
|
return $cache;
|
}
|
$this->image = apply_filters(
|
'jvbSummaryImage',
|
'',
|
$this->getType()
|
);
|
/**
|
* The h1 title element, excluding the h1 tag.
|
* Can include additional html (like <small> or <b>)
|
*/
|
$this->header = apply_filters(
|
'jvbSummaryHeader',
|
$this->defaultTitle(),
|
$this->getType()
|
);
|
/**
|
* Anything that appears after the h1 tag, but before the details block (optional))
|
*/
|
$headerExtra = apply_filters(
|
'jvbSummaryHeaderExtra',
|
'',
|
$this->getType()
|
);
|
$this->headerExtra = ($headerExtra === '') ? '' : '<div>'.$headerExtra.'</div>';
|
|
$this->beforeSummary = apply_filters(
|
'jvbBeforeSummary',
|
'',
|
$this->getType()
|
);
|
/**
|
* The HTML string that appears within the <summary> block
|
*/
|
$this->detailsTitle = apply_filters(
|
'jvbSummaryDetailsTitle',
|
'More',
|
$this->getType()
|
);
|
|
$this->isOpen = apply_filters(
|
'jvbSummaryIsOpen',
|
false,
|
$this->getType()
|
);
|
|
/**
|
* The content of the <details> block.
|
* This should return either an empty array for no information (so no details block)
|
* Or an array with slug => (string) html content, excluding outer div shell
|
*
|
* If empty, no <details> block is rendered
|
*/
|
$this->details = apply_filters(
|
'jvbSummaryDetails',
|
[],
|
$this->getType()
|
);
|
|
ob_start();
|
$this->renderBlock();
|
$content = ob_get_clean();
|
$this->cache->set($key, $content);
|
return $content;
|
}
|
|
protected function renderBlock():void
|
{
|
$this->renderHeader();
|
$this->renderDetails();
|
$this->renderOnThisPage();
|
}
|
|
protected function renderHeader():void
|
{
|
?>
|
<header id="top">
|
<?php if ($this->image !== ''): ?>
|
<?= $this->image ?>
|
<div>
|
<?php endif; ?>
|
|
<h1><?= $this->header ?></h1>
|
<?= $this->headerExtra ?>
|
|
<?php if ($this->image !==''): ?>
|
</div>
|
<?php endif; ?>
|
</header>
|
<?php
|
if (!empty($this->beforeSummary)) {
|
echo $this->beforeSummary;
|
}
|
}
|
|
protected function renderDetails():void
|
{
|
$details = array_filter($this->details, function ($value) {
|
return $value !== '';
|
});
|
if (empty($details)) {
|
return;
|
}
|
$open = $this->isOpen ? ' open' : '';
|
?>
|
<details class="info"<?=$open?>>
|
<summary class="row x-btw"><?= $this->detailsTitle ?></summary>
|
<?php
|
foreach ($this->details as $key => $details) {
|
if ($details === '') {
|
continue;
|
}
|
?>
|
<div id="<?=$key?>">
|
<?= $details ?>
|
</div>
|
<?php
|
}
|
?>
|
</details>
|
<?php
|
}
|
|
protected function renderOnThisPage():void
|
{
|
if (empty($this->details)) {
|
return;
|
}
|
$IDs = apply_filters('jvbSummaryOnThisPage', array_keys($this->details), $this->getType());
|
echo jvbOnThisPage($IDs);
|
}
|
|
protected function getType():string
|
{
|
if (empty($this->type)) {
|
$this->type = match (true) {
|
is_tax() => jvbNoBase(get_queried_object()->taxonomy),
|
is_post_type_archive() => jvbNoBase(get_queried_object()->name),
|
default => jvbNoBase(get_queried_object()->post_type),
|
};
|
}
|
return $this->type;
|
}
|
protected function defaultTitle():string
|
{
|
return (is_singular()) ? get_the_title() : get_the_archive_title();
|
}
|
}
|