| | |
| | | <?php |
| | | namespace JVBase\registry; |
| | | |
| | | use JVBase\forms\TaxonomySelector; |
| | | use JVBase\managers\CRUD; |
| | | use JVBase\utility\Features; |
| | | use WP_Post; |
| | | use JVBase\meta\MetaRegistry; |
| | | use JVBase\managers\CacheManager; |
| | | use JVBase\meta\Registry; |
| | | if (!defined('ABSPATH')) { |
| | | exit; |
| | | } |
| | |
| | | $singular = $this->config['singular'] ?? ucfirst($this->slug); |
| | | $plural = $this->config['plural'] ?? $singular . 's'; |
| | | $loweredPlural = strtolower($plural); |
| | | $capsMap = $this->config['capability_type']??[]; |
| | | if (empty($capsMap)){ |
| | | $capsMap = [ |
| | | $this->slug, |
| | | str_replace('-', '_',sanitize_title($loweredPlural)) |
| | | ]; |
| | | } |
| | | $args = [ |
| | | 'labels' => $this->buildLabels($singular, $plural), |
| | | 'public' => $this->config['public'] ?? true, |
| | | 'publicly_queryable' => $this->config['publicly_queryable'] ?? true, |
| | | 'publicly_queryable' => $this->config['publicly_queryable'] ?? $this->config['public'] ?? true, |
| | | 'show_ui' => $this->config['show_ui'] ?? true, |
| | | // 'show_in_menu' => false, |
| | | 'show_in_menu' => $this->config['show_in_menu'] ?? true, |
| | | 'query_var' => $this->config['query_var'] ?? true, |
| | | 'rewrite' => $this->config['rewrite'] ?? ['slug' => $this->slug, 'with_front' => false], |
| | | 'capability_type' => [$this->slug, $loweredPlural], |
| | | 'capability_type' => $capsMap, |
| | | 'capabilities' => [ |
| | | 'edit_post' => "edit_{$this->slug}", |
| | | 'read_post' => "read_{$this->slug}", |
| | | 'delete_post' => "delete_{$this->slug}", |
| | | 'edit_posts' => "edit_{$loweredPlural}", |
| | | 'edit_others_posts' => "edit_others_{$loweredPlural}", |
| | | 'publish_posts' => "publish_{$loweredPlural}", |
| | | 'read_private_posts' => "read_private_{$loweredPlural}", |
| | | 'create_posts' => "edit_{$loweredPlural}", |
| | | 'edit_posts' => "edit_{$capsMap[1]}", |
| | | 'edit_others_posts' => "edit_others_{$capsMap[1]}", |
| | | 'publish_posts' => "publish_{$capsMap[1]}", |
| | | 'read_private_posts' => "read_private_{$capsMap[1]}", |
| | | 'create_posts' => "edit_{$capsMap[1]}", |
| | | ], |
| | | 'has_archive' => $this->config['has_archive'] ?? true, |
| | | 'hierarchical' => $this->config['hierarchical'] ?? false, |
| | |
| | | 'show_in_rest' => $this->config['show_in_rest'] ?? true, |
| | | ]; |
| | | |
| | | if (jvbCheck('is_calendar', $this->config)) { |
| | | if ($this->config['is_calendar']??false) { |
| | | $args['rewrite']['slug'] = $args['rewrite']['slug']??$this->slug.'/%eyear%/%emonth%/%eday%'; |
| | | } |
| | | if (isset($this->config['icon'])) { |
| | | if ($this->config['rewrite_taxonomy']??false && array_key_exists($this->config['rewrite_taxonomy'], JVB_TAXONOMY)) { |
| | | $args['rewrite']['slug'] = "{$this->slug}/%{$this->config['rewrite_taxonomy']}%"; |
| | | } |
| | | if ($this->config['icon']??false) { |
| | | $args['menu_icon'] = jvbCSSIcon($this->config['icon']); |
| | | } |
| | | if ($this->config['is_timeline']??false) { |
| | | |
| | | } |
| | | register_post_type($this->post_type, $args); |
| | | |
| | | if (!empty($this->fields)) { |
| | | $meta_registry = new MetaRegistry($this->fields, $this->slug, 'post'); |
| | | $meta_registry = new Registry($this->fields, $this->slug, 'post'); |
| | | $meta_registry->registerMetaFields(); |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | $postType = $this->post_type; |
| | | add_action("save_post_{$this->post_type}", function($post_id, $post, $update) use ($postType) { |
| | | if (jvbNoSaveIt($post_id, $post)) { |
| | | return; |
| | | } |
| | | $this->invalidatePostCache($postType, $post, $update ? 'update' : 'create'); |
| | | }, 10, 3); |
| | | add_filter('jvbDashboardPage', [$this, 'renderDashPage'], 10, 3); |
| | | |
| | | add_action("delete_post", function($post_id, $post) use ($postType) { |
| | | $post = get_post($post_id); |
| | | if ($post && $post->post_type === $postType) { |
| | | $this->invalidatePostCache($postType, $post, 'delete'); |
| | | } |
| | | }, 10, 2); |
| | | |
| | | add_action("transition_post_status", function($new_status, $old_status, $post) use ($postType) { |
| | | if ($post->post_type === $postType && $new_status !== $old_status) { |
| | | $this->invalidatePostCache($postType, $post, 'status_change'); |
| | | } |
| | | }, 10, 3); |
| | | } |
| | | |
| | | protected function invalidatePostCache(string $type, $post, string $action) { |
| | | error_log('Clearing Cache for '.print_r($type, true)); |
| | | |
| | | $cache = new CacheManager(jvbNoBase($type)); |
| | | $cache->delete($post->ID); |
| | | |
| | | // Clear specific cache groups |
| | | CacheManager::invalidateGroup($type); |
| | | |
| | | CacheManager::invalidateGroup("user_content_{$post->post_author}"); |
| | | |
| | | // Clear related caches (taxonomies attached to this post) |
| | | $taxonomies = get_object_taxonomies($post->post_type); |
| | | foreach ($taxonomies as $taxonomy) { |
| | | $terms = wp_get_post_terms($post->ID, $taxonomy, ['fields' => 'ids']); |
| | | if (!empty($terms)) { |
| | | CacheManager::invalidateGroup($taxonomy); |
| | | } |
| | | if ($this->config['hide_children'] ?? false) { |
| | | add_action('template_redirect', [$this, 'redirectChildToParent']); |
| | | } |
| | | |
| | | // Trigger custom action for additional handling |
| | | do_action("jvb_cache_invalidated_{$type}", $post, $action); |
| | | if (array_key_exists('rewrite_taxonomy', $this->config) && array_key_exists($this->config['rewrite_taxonomy'], JVB_TAXONOMY)) { |
| | | add_action('init', [$this, 'addRewriteRules'], 20); |
| | | add_action('post_type_link', [$this, 'rewriteTaxonomySingle'], 15, 2); |
| | | add_filter('post_type_archive_link', [$this, 'rewriteTaxonomyArchive'], 15, 2); |
| | | } |
| | | } |
| | | |
| | | public function hideFromPublic(bool $is_viewable): bool |
| | |
| | | |
| | | return get_post_type_archive_link($post->post_type); |
| | | } |
| | | public function addRewriteRules(): void |
| | | { |
| | | $type = $this->config['rewrite_taxonomy']; |
| | | $taxonomy = jvbCheckBase($type); |
| | | |
| | | // Rule 1: Post type archive - /faq/ |
| | | add_rewrite_rule( |
| | | "{$this->slug}/?$", |
| | | "index.php?post_type={$this->post_type}", |
| | | 'top' |
| | | ); |
| | | |
| | | // Rule 2: Single posts with taxonomy - /faq/section/post/ |
| | | add_rewrite_rule( |
| | | "{$this->slug}/([^/]+)/([^/]+)/?$", |
| | | "index.php?post_type={$this->post_type}&name=\$matches[2]&{$taxonomy}=\$matches[1]", |
| | | 'top' |
| | | ); |
| | | |
| | | // Rule 3: Un-sectioned posts - /faq/post/ |
| | | // Use 'bottom' priority so taxonomy rules match first |
| | | add_rewrite_rule( |
| | | "{$this->slug}/([^/]+)/?$", |
| | | "index.php?post_type={$this->post_type}&name=\$matches[1]", |
| | | 'bottom' |
| | | ); |
| | | } |
| | | public function rewriteTaxonomySingle(string $url, \WP_Post $post): string |
| | | { |
| | | if ($post->post_type === $this->post_type) { |
| | | $type = $this->config['rewrite_taxonomy']; |
| | | $taxonomy = jvbCheckBase($type); |
| | | $terms = wp_get_post_terms($post->ID, $taxonomy); |
| | | if (!empty($terms) && !is_wp_error($terms)) { |
| | | $path = TaxonomySelector::getTermPath($terms[0], true); |
| | | $path = implode('/', array_map(function($term) { |
| | | return sanitize_title($term); |
| | | }, $path)); |
| | | return str_replace("%{$type}%", $path, $url); |
| | | } |
| | | return str_replace("/%{$type}%", '', $url); |
| | | } |
| | | return $url; |
| | | } |
| | | |
| | | public function rewriteTaxonomyArchive(string $url, string $post_type):string |
| | | { |
| | | if ($post_type === $this->post_type) { |
| | | $url = get_home_url(null, "/{$this->slug}/"); |
| | | } |
| | | return $url; |
| | | } |
| | | |
| | | /** |
| | | * Redirect child timeline posts to their parent post |
| | | */ |
| | | public function redirectChildToParent(): void |
| | | { |
| | | if (!is_singular($this->post_type)) { |
| | | return; |
| | | } |
| | | |
| | | global $post; |
| | | |
| | | // If this post has a parent, redirect to parent |
| | | if ($post->post_parent) { |
| | | $parent_url = get_permalink($post->post_parent); |
| | | |
| | | // Add anchor or query param to indicate which child was accessed |
| | | $redirect_url = add_query_arg('update', $post->ID, $parent_url); |
| | | |
| | | wp_redirect($redirect_url, 301); |
| | | exit; |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | } |