<?php
|
namespace JVBase\utility;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
/**
|
* @deprecated Use Registrar.php directly
|
* Centralized registry for all content types, taxonomies, and user roles
|
* Provides a single source of truth and caching layer
|
*/
|
class Checker
|
{
|
private static ?Checker $instance = null;
|
private array $cache = [];
|
private array $relationships = [];
|
|
// Cache keys for different registries
|
const CACHE_CONTENT = 'content_types';
|
const CACHE_TAXONOMIES = 'taxonomies';
|
const CACHE_USER_ROLES = 'user_roles';
|
const CACHE_RELATIONSHIPS = 'relationships';
|
|
private function __construct()
|
{
|
$this->initialize();
|
}
|
|
public static function getInstance(): self
|
{
|
if (self::$instance === null) {
|
self::$instance = new self();
|
}
|
return self::$instance;
|
}
|
|
/**
|
* Initialize all registries and build relationships
|
*/
|
private function initialize(): void
|
{
|
// Build initial caches
|
$this->buildRelationships();
|
|
// Set up WordPress hooks for cache invalidation
|
add_action('init', [$this, 'validateRegistrations'], 1);
|
add_action('registered_post_type', [$this, 'invalidateContentCache']);
|
add_action('registered_taxonomy', [$this, 'invalidateTaxonomyCache']);
|
}
|
|
/**
|
* Get all content types with optional filtering
|
*/
|
public function getContentTypes(array $filters = []): array
|
{
|
$content = $this->cache[self::CACHE_CONTENT] ?? [];
|
|
if (empty($filters)) {
|
return $content;
|
}
|
|
return $this->applyFilters($content, $filters);
|
}
|
|
/**
|
* Get all taxonomies with optional filtering
|
*/
|
public function getTaxonomies(array $filters = []): array
|
{
|
$taxonomies = $this->cache[self::CACHE_TAXONOMIES] ?? [];
|
|
if (empty($filters)) {
|
return $taxonomies;
|
}
|
|
return $this->applyFilters($taxonomies, $filters);
|
}
|
|
/**
|
* Get user roles with specific capabilities
|
*/
|
public function getUserRoles(array $filters = []): array
|
{
|
$roles = $this->cache[self::CACHE_USER_ROLES] ?? [];
|
|
if (empty($filters)) {
|
return $roles;
|
}
|
|
return $this->applyFilters($roles, $filters);
|
}
|
|
/**
|
* Get taxonomies for a specific content type
|
*/
|
public function getTaxonomiesForContent(string $contentType): array
|
{
|
$contentType = jvbNoBase($contentType);
|
return $this->relationships['content_taxonomies'][$contentType] ?? [];
|
}
|
|
/**
|
* Get content types for a specific taxonomy
|
*/
|
public function getContentForTaxonomy(string $taxonomy): array
|
{
|
$taxonomy = jvbNoBase($taxonomy);
|
return $this->relationships['taxonomy_content'][$taxonomy] ?? [];
|
}
|
|
/**
|
* Get content types a user role can create
|
*/
|
public function getCreatableContent(string $role): array
|
{
|
$role = jvbNoBase($role);
|
return $this->relationships['role_content'][$role] ?? [];
|
}
|
|
/**
|
* Check if a type has a specific feature
|
*/
|
public function hasFeature(string $type, string $feature, string $registry = 'content'): bool
|
{
|
$type = jvbNoBase($type);
|
|
$data = match ($registry) {
|
'content' => $this->cache[self::CACHE_CONTENT][$type] ?? [],
|
'taxonomy' => $this->cache[self::CACHE_TAXONOMIES][$type] ?? [],
|
'user' => $this->cache[self::CACHE_USER_ROLES][$type] ?? [],
|
default => []
|
};
|
|
return isset($data[$feature]) && $data[$feature] === true;
|
}
|
|
/**
|
* Get all types with a specific feature
|
*/
|
public function getTypesWithFeature(string $feature, string $registry = 'content'): array
|
{
|
$filters = [$feature => true];
|
|
return match ($registry) {
|
'content' => $this->getContentTypes($filters),
|
'taxonomy' => $this->getTaxonomies($filters),
|
'user' => $this->getUserRoles($filters),
|
default => []
|
};
|
}
|
|
|
/**
|
* Build relationships between types
|
*/
|
private function buildRelationships(): void
|
{
|
// Content -> Taxonomies
|
foreach ($this->cache[self::CACHE_CONTENT] as $contentSlug => $content) {
|
$this->relationships['content_taxonomies'][$contentSlug] = [];
|
}
|
|
// Taxonomy -> Content
|
foreach ($this->cache[self::CACHE_TAXONOMIES] as $taxSlug => $taxonomy) {
|
$this->relationships['taxonomy_content'][$taxSlug] = $taxonomy['for_content'] ?? [];
|
|
// Build reverse relationship
|
foreach ($taxonomy['for_content'] ?? [] as $contentType) {
|
$this->relationships['content_taxonomies'][$contentType][] = $taxSlug;
|
}
|
}
|
|
// User Role -> Content
|
foreach ($this->cache[self::CACHE_USER_ROLES] as $roleSlug => $role) {
|
$this->relationships['role_content'][$roleSlug] = $role['_creatable_content'];
|
}
|
|
$this->cache[self::CACHE_RELATIONSHIPS] = $this->relationships;
|
}
|
|
/**
|
* Apply filters to a registry array
|
*/
|
private function applyFilters(array $data, array $filters): array
|
{
|
return array_filter($data, function ($item) use ($filters) {
|
foreach ($filters as $key => $value) {
|
if (!isset($item[$key]) || $item[$key] !== $value) {
|
return false;
|
}
|
}
|
return true;
|
});
|
}
|
|
/**
|
* Extract creatable content from user role config
|
*/
|
private function extractCreatableContent(array $config): array
|
{
|
$content = [];
|
|
foreach ($config['can_create'] ?? [] as $item) {
|
if (is_array($item)) {
|
foreach ($item as $type => $contents) {
|
$content = array_merge($content, $contents);
|
}
|
} else {
|
$content[] = $item;
|
}
|
}
|
|
return array_unique($content);
|
}
|
|
/**
|
* Check if content type supports dashboard
|
*/
|
private function computesDashboardSupport(array $config): bool
|
{
|
return !empty($config['fields']) ||
|
!empty($config['sections']) ||
|
($config['show_dashboard'] ?? false);
|
}
|
|
/**
|
* Check if content type is a user profile type
|
*/
|
private function computesUserType(array $config): bool
|
{
|
foreach ($this->cache[self::CACHE_USER_ROLES] ?? [] as $role) {
|
if (($role['profile'] ?? '') === $config['_slug']) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
/**
|
* Validate all registrations are properly set up
|
*/
|
public function validateRegistrations(): void
|
{
|
$errors = [];
|
|
// Validate taxonomy relationships
|
foreach ($this->getTaxonomies() as $taxSlug => $taxonomy) {
|
foreach ($taxonomy['for_content'] ?? [] as $contentType) {
|
if (!isset($this->cache[self::CACHE_CONTENT][$contentType])) {
|
$errors[] = "Taxonomy '{$taxSlug}' references non-existent content type '{$contentType}'";
|
}
|
}
|
}
|
|
// Validate user role content permissions
|
foreach ($this->getUserRoles() as $roleSlug => $role) {
|
foreach ($role['_creatable_content'] as $contentType) {
|
if (!isset($this->cache[self::CACHE_CONTENT][$contentType]) &&
|
!isset($this->cache[self::CACHE_TAXONOMIES][$contentType])) {
|
$errors[] = "Role '{$roleSlug}' references non-existent type '{$contentType}'";
|
}
|
}
|
}
|
|
if (!empty($errors) && WP_DEBUG) {
|
foreach ($errors as $error) {
|
error_log("[Checker Validation] {$error}");
|
}
|
}
|
}
|
|
/**
|
* Invalidate content cache
|
*/
|
public function invalidateContentCache(): void
|
{
|
unset($this->cache[self::CACHE_CONTENT]);
|
$this->buildContentCache();
|
$this->buildRelationships();
|
}
|
|
/**
|
* Invalidate taxonomy cache
|
*/
|
public function invalidateTaxonomyCache(): void
|
{
|
unset($this->cache[self::CACHE_TAXONOMIES]);
|
$this->buildTaxonomyCache();
|
$this->buildRelationships();
|
}
|
|
/**
|
* Get registry statistics for debugging
|
*/
|
public function getStats(): array
|
{
|
return [
|
'content_types' => count($this->cache[self::CACHE_CONTENT] ?? []),
|
'taxonomies' => count($this->cache[self::CACHE_TAXONOMIES] ?? []),
|
'user_roles' => count($this->cache[self::CACHE_USER_ROLES] ?? []),
|
'relationships' => count($this->relationships),
|
'cache_size' => strlen(serialize($this->cache))
|
];
|
}
|
}
|