<?php
|
namespace JVBase\registrar;
|
|
|
use JVBase\base\Site;
|
use JVBase\inc\registrar\helpers\HideSingle;
|
use JVBase\managers\Cache;
|
use JVBase\managers\CRUD;
|
use JVBase\managers\IconsManager;
|
use JVBase\managers\KarmaManager;
|
use JVBase\meta\Meta;
|
use JVBase\registrar\config\Breadcrumbs;
|
use JVBase\registrar\config\Dashboard;
|
use JVBase\registrar\config\Directory;
|
use JVBase\registrar\config\Feed;
|
use JVBase\registrar\config\Integration;
|
use JVBase\registrar\config\Section;
|
use JVBase\registrar\config\SEO;
|
use JVBase\registrar\helpers\AddIntegrationFields;
|
use JVBase\registrar\helpers\MakeCalendarType;
|
use JVBase\registrar\helpers\MakeTimelineType;
|
use JVBase\registrar\helpers\MakeTrackChanges;
|
use JVBase\registrar\helpers\MakeVerification;
|
use WP_Query;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
class Registrar {
|
protected string $slug;
|
protected string $type;
|
protected string $singular;
|
protected string $plural;
|
protected string $profile;
|
protected string $description ='';
|
protected Fields $fields;
|
protected array $sections = [];
|
//For the Terms/Post Registrar
|
protected array $args= [];
|
protected array $sectionOrder = [];
|
public Posts|Terms|false $registrar = false;
|
protected ?string $icon = null;
|
|
protected ?string $upload_title = null;
|
|
protected int|false $page = false;
|
|
public ?string $rewrite_taxonomy = null;
|
|
public bool $add_image_column = false;
|
|
protected static array $allFlags = [
|
//Shared Flags
|
'favouritable', 'karma', 'show_feed', 'show_directory', 'approve_new', 'has_responses', 'invitable',
|
//Post Flags
|
'hide_single', 'redirect_to_author', 'is_calendar', 'single_image', 'is_timeline', 'is_gallery', 'is_faq', 'is_glossary', 'rewrite_taxonomy', 'add_image_column',
|
//Taxonomy Flags
|
'is_content', 'is_ownable', 'verify_entry', 'track_changes', 'associate_user_content',
|
//User Flags
|
'has_dashboard', 'can_register', 'can_create', 'keep_stats', 'can_favourite', 'member_verified', 'profile_link', 'manage_others'
|
];
|
/**********************************************************************************************
|
SHARED FLAGS
|
**********************************************************************************************/
|
/**
|
* @var bool Whether this can be favourited
|
*/
|
protected bool $favouritable = false;
|
/**
|
* @var bool Whether to setup karma for this content
|
*/
|
protected bool $karma = false;
|
protected ?KarmaManager $karmaManager = null;
|
/**
|
* @var bool Whether this should be available in the feed block
|
*/
|
protected bool $show_feed = true;
|
/**
|
* @var bool Whether this should get a directory page
|
*/
|
protected bool $show_directory = false;
|
/**
|
* @var bool Whether these should be approved by admin/verified users before being public
|
*/
|
protected bool $approve_new;
|
/**
|
* @var bool Whether this item can have responses
|
*/
|
protected bool $has_responses;
|
/**
|
* @var bool For Terms: Whether members in this taxonomy can invite other members to join
|
* For User Roles: Whether verified members can invite people to join the site
|
*/
|
protected bool $invitable;
|
/**********************************************************************************************
|
POST FLAGS
|
**********************************************************************************************/
|
/**
|
* @var bool Whether single items of this content should be hidden
|
*/
|
protected bool $hide_single = false;
|
protected ?HideSingle $hideSingleHandler = null;
|
|
/**
|
* @var bool Whether single items should just go to the author's page
|
*/
|
protected bool $redirect_to_author;
|
/**
|
* @var bool Whether to make this a calendar type (example: events)
|
*/
|
protected bool $is_calendar = false;
|
protected ?MakeCalendarType $isCalendarHandler = null;
|
/**
|
* @var bool Whether this is a before/after post type
|
*/
|
protected bool $is_timeline = false;
|
protected ?MakeTimelineType $isTimelineHandler = null;
|
/**
|
* @var bool Whether this is a defined term post type
|
*/
|
protected bool $is_glossary = false;
|
/**
|
* @var bool Whether this is a faq post type
|
*/
|
protected bool $is_faq = false;
|
/**
|
* @var bool Whether the uploader can group images prior to upload
|
*/
|
protected bool $single_image;
|
/**********************************************************************************************
|
TAXONOMY FLAGS
|
********************************************************************************************/
|
/**
|
* @var bool For taxonomy types only. Treats the taxonomy as a content (ie: tattoo shops))
|
*/
|
protected bool $is_content = false;
|
/**
|
* @var bool Whether this taxonomy can be owned/managed by specific people only
|
*/
|
protected bool $is_ownable;
|
/**
|
* @var bool Whether users/content need to request the owner for admission
|
*/
|
protected bool $verify_entry = false;
|
protected ?MakeVerification $verifyEntryHandler = null;
|
/**
|
* @var bool Whether we should track post movements from term to term (ie. artists in tattoo shops)
|
*/
|
protected bool $track_changes = false;
|
protected ?MakeTrackChanges $trackChangesHandler = null;
|
|
/**
|
* @var bool Whether any content by members in this taxonomy should show up in this taxonomy
|
*/
|
protected bool $associate_user_content;
|
|
/*************************************************************************************
|
USER FLAGS
|
*************************************************************************************/
|
/**
|
* @var bool Whether this user role has access to the dashboard
|
*/
|
protected bool $has_dashboard;
|
/**
|
* @var bool Whether this user role can register
|
*/
|
protected bool $can_register;
|
/**
|
* @var bool Whether to track basic statistics for this role
|
*/
|
protected bool $keep_stats;
|
/**
|
* @var bool Whether this role can favourite
|
*/
|
protected bool $can_favourite;
|
/**
|
* @var bool Whether this role should be verified before they can publish anything
|
*/
|
protected bool $member_verified;
|
/**
|
* @var bool Whether to generate a profile for this user role
|
*/
|
public bool $profile_link;
|
/**
|
* @var array|string
|
*/
|
protected array|string $can_create = [];
|
/**
|
* @var array slugs of other user roles this role can manage
|
*/
|
protected array $manage_others = [];
|
/**
|
* @var string The slug of the taxonomy that defines different access points
|
* Example, for edmonton.ink, we have artist_type, and $this->>can_create would be:
|
* [
|
* 'piercer' => ['piercings', 'artwork', 'events'],
|
* 'tattoo_artist'=> ['tattoos', 'artwork', 'events'],
|
* 'artist' => ['artwork']
|
* ]
|
*/
|
protected string $user_subtype;
|
|
/** Configs **/
|
protected Breadcrumbs $breadcrumbs;
|
protected Dashboard $dashboard;
|
protected Directory|false $directory;
|
protected Feed|false $feed;
|
// protected Management $management;
|
// protected Responses $responses;
|
protected ?SEO $seo = null;
|
|
/** Helpers **/
|
protected MakeCalendarType|false $calendar = false;
|
protected array $integrationConfigs = [];
|
protected array $integrationFields = [];
|
protected MakeTrackChanges $trackChanges;
|
protected MakeVerification $verification;
|
|
private static array $instances = [];
|
|
protected string $based;
|
private function __construct(string $slug, string $singular, string $plural, string $type) {
|
$this->slug = $slug;
|
$this->based = jvbCheckBase($slug);
|
$this->type = $type;
|
$this->singular = $singular;
|
$this->plural = $plural;
|
|
// $this->init();
|
|
// $this->initClasses();
|
$this->setFields();
|
|
add_action('init', [$this, 'register'], 2);
|
add_filter('jvbDashboardPage', [$this, 'renderDashPage'], 10, 3);
|
}
|
|
protected function initRegistrar():void {
|
$this->registrar = match ($this->type) {
|
'post' => new Posts($this->slug, $this->singular, $this->plural),
|
'term' => new Terms($this->slug, $this->singular, $this->plural),
|
default => false,
|
};
|
}
|
|
protected function initClasses():void {
|
$this->breadcrumbs = new Breadcrumbs($this->slug);
|
$this->dashboard = new Dashboard($this->slug);
|
$this->directory = new Directory($this->singular);
|
$this->feed = new Feed($this->slug);
|
// $this->management = new Management($this->slug);
|
// $this->responses = new Responses($this->slug);
|
$this->seo = new SEO($this->slug);
|
// $this->trackChanges = new TrackChanges($this->slug);
|
// $this->Verification = new Verification($this->slug);
|
}
|
|
/**
|
* Instantiates for post types
|
* @param string $slug
|
* @return self
|
*/
|
public static function forPost(string $slug, string $singular, string $plural):self
|
{
|
if (!isset(self::$instances[$slug])) {
|
self::$instances[$slug] = new self($slug, $singular, $plural,'post');
|
}
|
return self::$instances[$slug];
|
}
|
|
/**
|
* Instantiates for term types
|
* @param string $slug
|
* @return self
|
*/
|
public static function forTerm(string $slug, string $singular, string $plural):self
|
{
|
if (!isset(self::$instances[$slug])) {
|
self::$instances[$slug] = new self($slug, $singular, $plural,'term');
|
}
|
return self::$instances[$slug];
|
}
|
|
/**
|
* Instantiates for user types
|
* @param string $slug
|
* @return self
|
*/
|
public static function forUser(string $slug, string $singular, string $plural):self
|
{
|
if (!isset(self::$instances[$slug])) {
|
self::$instances[$slug] = new self($slug, $singular, $plural, 'user');
|
}
|
return self::$instances[$slug];
|
}
|
|
/**
|
* Adds the properties for register_post_type or register_taxonomy
|
* @param array $args
|
* @return $this
|
*/
|
public function make(array $args):self
|
{
|
$this->initRegistrar();
|
if (!$this->registrar) {
|
return $this;
|
}
|
$this->args = $args;
|
|
foreach ($args as $property => $value) {
|
if (property_exists($this->registrar, $property)) {
|
$this->registrar->$property = $value;
|
}
|
|
if (property_exists($this, $property)) {
|
$this->$property = $value;
|
}
|
|
}
|
if (isset($this->icon) && !str_contains($this->icon, 'dashicons')){
|
$this->registrar->menu_icon = IconsManager::for()->getCSSIcon($this->icon);
|
}
|
return $this;
|
}
|
|
public function fields():Fields
|
{
|
return $this->fields;
|
}
|
|
public function args():array
|
{
|
return $this->args;
|
}
|
|
public function setFields():void
|
{
|
$this->fields = new Fields($this->type, $this);
|
}
|
public function getFields():array
|
{
|
return array_map(function ($field) {
|
return $field->getConfig();
|
},
|
$this->fields->getFields()
|
);
|
}
|
public function setIcon(string $icon):self
|
{
|
$this->icon = $icon;
|
return $this;
|
}
|
public function getIcon(?string $default = null):string
|
{
|
if (!$default) {
|
$default = jvbDefaultIcon();
|
}
|
|
return $this->icon ?: $default;
|
}
|
public function getSingular():string
|
{
|
return $this->singular;
|
}
|
public function getPlural():string
|
{
|
return $this->plural;
|
}
|
public function getDescription():string
|
{
|
return $this->description;
|
}
|
public function setDescription(string $description):self
|
{
|
$this->description = $description;
|
return $this;
|
}
|
|
public function getType():string
|
{
|
return $this->type;
|
}
|
public function setIntegration(string $integration):self
|
{
|
|
if (!Site::hasIntegration($integration)){
|
error_log('Integration not available for '.$this->slug.': '.$integration);
|
return $this;
|
}
|
$this->integrationConfigs[$integration] = new Integration($integration, $this);
|
$this->integrationFields[$integration] = new AddIntegrationFields($integration, $this);
|
return $this;
|
}
|
public function getIntegrationFields(string $integration):AddIntegrationFields|false
|
{
|
|
if (!Site::has($integration)){
|
error_log('Integration not available for '.$this->slug.': '.$integration);
|
return false;
|
}
|
if (!in_array($integration, $this->integrationFields)) {
|
error_log('No integration fields intitialized for '.$integration);
|
return false;
|
}
|
return $this->integrationFields[$integration];
|
}
|
public function getIntegrations():array
|
{
|
return $this->integrationConfigs;
|
}
|
public function hasIntegration(string $integration) {
|
return in_array($integration, $this->integrationConfigs);
|
}
|
public function hasAnyIntegrations(array $integrations = []):bool
|
{
|
if (empty($integrations)) {
|
$integrations = array_keys($this->integrationConfigs);
|
return !empty($integrations);
|
}
|
return !empty(array_intersect($integrations, array_keys($this->integrationConfigs)));
|
}
|
public function setUploadTitle(string $title):self
|
{
|
$this->upload_title = $title;
|
return $this;
|
}
|
|
public function getUploadTitle():string {
|
return ($this->upload_title) ?: 'Upload '.$this->plural;
|
}
|
|
public function getSlug():string
|
{
|
return $this->slug;
|
}
|
|
public function getBased():string
|
{
|
return $this->based;
|
}
|
|
public function setGlossary(bool $set):self
|
{
|
$this->is_glossary = $set;
|
// if ($set) {
|
// $this->timeline = new MakeTimelineType($this->slug, $this);
|
// }
|
return $this;
|
}
|
public function isGlossary():bool
|
{
|
return $this->is_glossary;
|
}
|
public function setFaq(bool $set):self
|
{
|
$this->is_faq = $set;
|
// if ($set) {
|
// $this->timeline = new MakeTimelineType($this->slug, $this);
|
// }
|
return $this;
|
}
|
public function isFaq():bool
|
{
|
return $this->is_faq;
|
}
|
public function setTimeline(bool $set):self
|
{
|
$this->is_timeline = $set;
|
// if ($set) {
|
// $this->timeline = new MakeTimelineType($this->slug, $this);
|
// }
|
return $this;
|
}
|
public function isTimeline():bool
|
{
|
return $this->is_timeline;
|
}
|
public function setCalendar(bool $set):self
|
{
|
$this->is_calendar = $set;
|
if ($set) {
|
$this->calendar = new MakeCalendarType($this->slug, $this);
|
}
|
return $this;
|
}
|
|
public function setAll(array $flags):self
|
{
|
$flags = array_filter($flags, function($flag) {
|
return in_array($flag, static::$allFlags);
|
});
|
foreach ($flags as $flag) {
|
$this->$flag = true;
|
switch ($flag) {
|
case 'is_content':
|
add_action('init', [$this, 'setupContent'], 20);
|
break;
|
case 'is_glossary':
|
$this->hide_single = true;
|
break;
|
}
|
}
|
return $this;
|
}
|
public function removeAll(array $flags):self
|
{
|
$flags = array_filter($flags, function($flag) {
|
return in_array($flag, static::$allFlags);
|
});
|
foreach ($flags as $flag) {
|
$this->$flag = false;
|
}
|
return $this;
|
}
|
|
|
public function hasFeature(string $feature):bool
|
{
|
if (!in_array($feature, static::$allFlags)) {
|
return false;
|
}
|
return isset($this->$feature) && $this->$feature === true;
|
}
|
public static function getFeatured(string $feature, ?string $type = null):array
|
{
|
self::ensureInstanced();
|
|
if (!in_array($feature, static::$allFlags)) {
|
error_log('Feature requested not found: '.$feature);
|
return [];
|
}
|
|
return array_map(function($inst) { return $inst->slug; },array_filter(self::$instances, function ($inst) use ($feature, $type){
|
if (!is_null($type) && $inst->type !== $type) {
|
return false;
|
}
|
return property_exists($inst, $feature) && isset($inst->$feature) && $inst->$feature === true;
|
}));
|
}
|
|
public function config(string $config):mixed
|
{
|
$allowed = ['breadcrumbs','calendar','dashboard','directory','feed','management','has_responses','seo','trackchanges','verification'];
|
if (!in_array(strtolower($config), $allowed)) {
|
error_log('Invalid config requested from Registrar: '.$config);
|
return [];
|
}
|
return match(strtolower($config)) {
|
'breadcrumbs' => $this->getBreadcrumbs(),
|
'dashboard' => $this->getDashboard(),
|
'directory' => $this->getDirectory(),
|
'feed' => $this->getFeed(),
|
'management' => $this->getManagement(),
|
'has_responses' => $this->getResponses(),
|
'seo' => $this->getSEO(),
|
'trackchanges' => $this->getTrackChanges(),
|
'verification' => $this->getVerification()
|
};
|
}
|
protected function getBreadcrumbs():Breadcrumbs
|
{
|
if (!isset($this->breadcrumbs)) {
|
$this->breadcrumbs = new Breadcrumbs($this->slug, $this);
|
}
|
|
return $this->breadcrumbs;
|
}
|
protected function getCalendar():MakeCalendarType|false
|
{
|
if ($this->is_calendar && !isset($this->calendar)){
|
$this->calendar = new MakeCalendarType($this->slug, $this);
|
} else {
|
$this->calendar = false;
|
}
|
return $this->calendar;
|
}
|
|
protected function getDashboard():Dashboard
|
{
|
if (!isset($this->dashboard)) {
|
$this->dashboard = new Dashboard($this->plural, $this);
|
}
|
|
return $this->dashboard;
|
}
|
|
protected function getDirectory():Directory|false
|
{
|
if (!isset($this->directory)) {
|
$this->directory = new Directory($this->singular);
|
}
|
return $this->directory;
|
}
|
|
protected function getFeed():Feed|false
|
{
|
if (!isset($this->feed)) {
|
$this->feed = new Feed($this->slug);
|
}
|
return $this->feed;
|
}
|
|
public function getSEO():SEO
|
{
|
if (!isset($this->seo)){
|
$this->seo = new SEO($this->slug);
|
}
|
return $this->seo;
|
}
|
|
public function getSections():array
|
{
|
$allSections = array_map(function($section) {
|
return $section->getConfig;
|
}, $this->sections);
|
|
if (!empty($this->sectionOrder)) {
|
$allSections['order'] = $this->sectionOrder;
|
}
|
return $allSections;
|
}
|
public function addSection(string $title):Section
|
{
|
$section = new Section($title, $this);
|
$this->sections[] = $section;
|
return $section;
|
}
|
|
public function setSectionOrder(array $sections):self
|
{
|
$allSections = array_map(function($section) {
|
return $section->getSlug;
|
}, $this->sections);
|
$this->sectionOrder = array_intersect($allSections, $sections);
|
return $this;
|
}
|
public function getSectionOrder():array
|
{
|
return $this->sectionOrder;
|
}
|
|
public function getConfig(string $config):array
|
{
|
$allowed = ['breadcrumbs','calendar','dashboard','directory','feed','management','has_responses','seo','trackchanges','verification'];
|
if (!in_array(strtolower($config), $allowed)) {
|
error_log('Invalid config requested from Registrar: '.$config);
|
return [];
|
}
|
$config = $this->config($config);
|
return ($config) ? $config->getConfig() : [];
|
}
|
|
public function getIntegration(string $service_name):Integration|false
|
{
|
if (array_key_exists($service_name, $this->integrationConfigs)) {
|
return $this->integrationConfigs[$service_name];
|
}
|
return false;
|
}
|
public function getIntegrationConfig(string $service_name):array|false
|
{
|
$integration = $this->getIntegration($service_name);
|
if ($integration){
|
return $integration->getConfig();
|
}
|
return false;
|
}
|
|
public function register():void
|
{
|
if ($this->type === 'post') {
|
if ($this->hide_single) {
|
$this->hideSingleHandler = new HideSingle($this->slug, $this);
|
}
|
if ($this->is_timeline) {
|
$this->isTimelineHandler = new MakeTimelineType($this->slug, $this);
|
$this->registrar->hierarchical = true;
|
}
|
if ($this->is_calendar) {
|
$this->isCalendarHandler = new MakeCalendarType($this->slug, $this);
|
}
|
|
if (!is_null($this->rewrite_taxonomy)) {
|
$this->registrar->addTaxonomyRewrite($this->rewrite_taxonomy);
|
}
|
|
if ($this->registrar) {
|
$this->registrar->register();
|
}
|
if ($this->add_image_column) {
|
add_filter("manage_{$this->based}_posts_columns", [$this, 'addImageColumn']);
|
add_action("manage_{$this->based}_posts_custom_column", [$this, 'showImageColumn'], 10, 2);
|
}
|
} elseif ($this->type === 'term') {
|
if ($this->is_content) {
|
if ($this->verify_entry) {
|
$this->verifyEntryHandler = new MakeVerification();
|
}
|
if ($this->track_changes) {
|
$this->trackChangesHandler = new MakeTrackChanges($this->slug);
|
}
|
}
|
|
if ($this->registrar) {
|
$this->registrar->register();
|
}
|
}
|
|
if ($this->karma) {
|
$this->karmaManager = KarmaManager::for($this->slug, $this->type);
|
}
|
}
|
public static function getInstance(string $slug):Registrar|false
|
{
|
self::ensureInstanced();
|
|
$slug = jvbNoBase($slug);
|
if (array_key_exists($slug, static::$instances)) {
|
return static::$instances[$slug];
|
}
|
return false;
|
}
|
|
public static function getFieldsFor(string $slug):array
|
{
|
self::ensureInstanced();
|
if (!array_key_exists($slug, static::$instances)) {
|
return [];
|
}
|
$instance = static::$instances[$slug];
|
return $instance->getFields();
|
}
|
|
public static function getRegistered(?string $type = null):array
|
{
|
self::ensureInstanced();
|
$instances = ($type) ? array_filter(static::$instances, function($instance) use ($type) {
|
return $instance->type === $type;
|
}) : static::$instances;
|
return array_keys($instances);
|
}
|
|
public static function getLabels():array
|
{
|
self::ensureInstanced();
|
return array_map(function ($instance) {
|
return ['singular' => $instance->getSingular(),
|
'plural' => $instance->getPlural()];
|
}, static::$instances);
|
}
|
|
public function getCreatable():array
|
{
|
if ($this->type !== 'user') {
|
return [];
|
}
|
return $this->can_create;
|
}
|
public function setCreatable(string|array $creatable):self
|
{
|
$this->can_create = $creatable;
|
return $this;
|
}
|
|
public function getManageOthers():array
|
{
|
if ($this->type !== 'user'){
|
return [];
|
}
|
return $this->manage_others;
|
}
|
public function setManageOthers(array $manageable):self
|
{
|
$this->manage_others = $manageable;
|
return $this;
|
}
|
|
public function renderDashPage(string $content, string $page, string $slug):string
|
{
|
if ($slug === $this->slug) {
|
ob_start();
|
$crud = new CRUD($slug);
|
$crud->render();
|
return ob_get_clean();
|
}
|
|
return $content;
|
}
|
|
public function setupContent():void
|
{
|
if (!$this->is_content) return;
|
//We need a pseudo-archive page for this content taxonomy. We create a post with the plural name
|
$this->page = get_option(BASE.$this->slug.'_archive', false);
|
if (!$this->page || !(bool)get_post((int)$this->page)) {
|
$exists = new WP_Query([
|
'post_type' => 'page',
|
'title'=> $this->plural,
|
'posts_per_page' => 1,
|
'post_status' => 'publish',
|
'fields' => 'ids',
|
]);
|
if ($exists->have_posts()) {
|
$page = $exists->posts[0];
|
} else {
|
$page = wp_insert_post([
|
'post_type' => 'page',
|
'post_title' => $this->plural,
|
'post_content' => '',
|
'post_status' => 'publish',
|
]);
|
}
|
|
if ($page && !is_wp_error($page)) {
|
update_post_meta($page, BASE.'for_type', $this->slug);
|
update_option(BASE.$this->slug.'_archive', $page);
|
$this->page = $page;
|
}
|
wp_reset_postdata();
|
}
|
add_filter('jvb_post_content_output', [$this, 'renderContent'], 20, 2);
|
|
|
//Add a date published and date modified fields, and auto-update them on term creation/modification
|
$this->fields()->addField('date_published', [
|
'type' => 'datetime',
|
'label' => 'Published',
|
'hidden' => true,
|
]);
|
$this->fields()->addField('date_modified', [
|
'type' => 'datetime',
|
'label' => 'Modified',
|
'hidden' => true,
|
]);
|
add_action('created_'.$this->based, [$this, 'addTermCreatedMeta']);
|
add_action('edited_'.$this->based, [$this, 'addTermUpdatedMeta']);
|
}
|
public function addTermCreatedMeta(int $termId):void
|
{
|
$meta = Meta::forTerm($termId);
|
$meta->set('date_published', date('Y-m-d H:i:s'));
|
}
|
public function handleContentTermMetaChange(int $meta_id, int $term_id, string $meta_key, $meta_value):void
|
{
|
$term = get_term($term_id);
|
$taxonomy = $term->taxonomy;
|
if ($taxonomy === $this->based && $meta_key !== BASE . 'date_modified') {
|
$meta = Meta::forTerm($term_id);
|
$meta->set('date_modified', date('Y-m-d H:i:s'));
|
}
|
|
}
|
public function addTermUpdatedMeta(int $termId):void
|
{
|
$meta = Meta::forTerm($termId);
|
$meta->set('date_modified', date('Y-m-d H:i:s'));
|
}
|
public function renderContent(string $content, array $block):string
|
{
|
if (!is_page($this->page)) {
|
return $content;
|
}
|
if ($block['blockName'] !== 'core/post-content') {
|
return $content;
|
}
|
if (JVB_TESTING) {
|
Cache::for($this->slug)->flush();
|
}
|
|
$out = Cache::for($this->slug)->remember(
|
get_the_ID(),
|
function() {
|
|
$items = get_terms([
|
'taxonomy' => jvbCheckBase($this->slug),
|
// 'hide_empty' => true,
|
'fields' => 'ids',
|
]);
|
$out = [];
|
if ($items && !is_wp_error($items)) {
|
foreach ($items as $item) {
|
$meta = Meta::forTerm($item);
|
$slug = sanitize_title($meta->get('name'));
|
$item = sprintf(
|
'<li id="%s"><h2><a href="%s">%s</a></h2><p>%s</p><ul class="item-grid">',
|
$slug,
|
get_term_link($item, jvbCheckBase($this->slug))??'',
|
$meta->get('name'),
|
$meta->get('description')
|
);
|
$postTypes = array_map(function($type) { return jvbCheckBase($type);}, $this->registrar->for);
|
$posts = new WP_Query([
|
'post_type' => $postTypes,
|
'post_status' => 'publish',
|
'posts_per_page' => 3,
|
'fields' => 'ids',
|
]);
|
if ($posts->have_posts()) {
|
while($posts->have_posts()) {
|
$posts->the_post();
|
$ID = get_the_id();
|
$postMeta = Meta::forPost($ID);
|
$img = $postMeta->get('post_thumbnail');
|
$img = !empty($img) ? jvbFormatImage((int)$img, 'tiny', 'medium') : '';
|
$item .= sprintf(
|
'<li id="%s" class="item"><h3><a href="%s">%s</a></h3>%s</li>',
|
$slug.'-'.sanitize_title(get_the_title($ID)),
|
get_the_permalink($ID),
|
$postMeta->get('post_title'),
|
$img
|
);
|
}
|
}
|
wp_reset_postdata();
|
$item .= '</ul></li>';
|
$out[] = $item;
|
}
|
}
|
return empty($out) ? '' : '<ul class="content-term-list">'.implode('',$out).'</ul>';
|
}
|
);
|
error_log('Built the '.$this->slug.' page content.');
|
return $content . $out;
|
}
|
|
public static function ensureInstanced():void
|
{
|
if (empty(self::$instances)) {
|
do_action('jvbDefineRegistrar');
|
do_action('jvbDefineRegistrarFields');
|
}
|
}
|
|
/*****************************************************************
|
* FLAGGED FEATURES
|
*****************************************************************/
|
|
public function profile(?string $slug = null, ?string $singular = null, ?string $plural = null):self
|
{
|
if (!$slug) {
|
$slug = $this->slug.'_profile';
|
}
|
if (!$singular) {
|
$singular = $this->singular;
|
}
|
if (!$plural) {
|
$plural = $this->plural;
|
}
|
$this->profile_link = true;
|
|
$this->profile = $slug;
|
|
return Registrar::forPost($slug, $singular, $plural);
|
}
|
public function getProfile():self|false
|
{
|
if (!$this->profile_link) {
|
return false;
|
}
|
return self::getInstance($this->profile);
|
}
|
|
public function setUserSubtype(string $type):self
|
{
|
$this->user_subtype = sanitize_text_field($type);
|
return $this;
|
}
|
public function getUserSubtype():string|false
|
{
|
return $this->user_subtype??false;
|
}
|
|
public function addImageColumn(array $columns):array
|
{
|
$keys = array_keys($columns);
|
$index = array_search('cb', $keys);
|
if ($index !== false) {
|
$pos = $index+1;
|
$columns = array_slice($columns, 0, $pos, true) + ['jvb_featured_image' => 'Image'] + array_slice($columns, $pos, null, true);
|
}
|
return $columns;
|
}
|
public function showImageColumn(string $column, int $postID):void
|
{
|
if ($column === 'jvb_featured_image') {
|
echo get_the_post_thumbnail($postID, 'tiny');
|
}
|
}
|
}
|