TAX = $args['TAX']; $this->PT = $args['PT']; $this->metabox = $args['metabox'] ?? TaxonomyMetabox::DEFAULT; $this->form = $args['form']; } public function init(): void { add_action('init', [$this, 'register']); add_action('add_meta_boxes', [$this, 'metaboxes'], 5); add_action($this->TAX.'_add_form_fields', [$this, 'add']); add_action($this->TAX.'_edit_form_fields', [$this, 'edit']); add_action('created_'.$this->TAX, [$this, 'save']); add_action('edited_'.$this->TAX, [$this, 'save']); add_filter('manage_edit-'.$this->TAX.'_columns', [$this, 'columns']); add_filter('manage_'.$this->TAX.'_custom_column', [$this, 'content'], 10, 3); add_filter('manage_edit-'.$this->TAX.'_sortable_columns', [$this, 'sortable']); // Register Taxonomy in DayTidy add_filter('DayTidy/F__DayTidy/Data/Entity__taxonomies/taxonomies', [$this, 'introduce']); } /** * Register Taxonomy * * @return void */ public function register(): void { // Filter Args $args = apply_filters('DayTidy/F__DayTidy/Taxonomy__register/args', $this->args(), $this); if (!isset($args['capabilities'])) { $args['capabilities'] = Capabilities::taxonomyCapabilities(Capabilities::MANAGE_OFFERINGS); } register_taxonomy( $this->TAX, $this->PT, $args ); register_taxonomy_for_object_type($this->TAX, $this->PT); } /** * Register Metaboxes * * @return void */ public function metaboxes(): void { } /** * Display Taxonomy Add Fields * * @return void */ public function add(): void { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- DayTidy Kses sanitizes the generated form markup. echo Kses::form( wp_nonce_field($this->nonceAction(), 'daytidy_taxonomy_nonce', false, false) . $this->form()->generator(new TaxAdd())->display() ); } /** * Display Taxonomy Edit Fields * * @param WP_Term $term * @return void */ public function edit(WP_Term $term): void { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- DayTidy Kses sanitizes the generated form markup. echo Kses::form( wp_nonce_field($this->nonceAction(), 'daytidy_taxonomy_nonce', false, false) . $this->form()->generator(new TaxEdit())->display(new Term($term->term_id)) ); } /** * Save the Taxonomy Fields * * @param int $term_id * @return void */ public function save(int $term_id): void { $taxonomy = get_taxonomy($this->TAX); if (!$taxonomy || !current_user_can($taxonomy->cap->edit_terms)) return; $nonce = isset($_POST['daytidy_taxonomy_nonce']) && is_scalar($_POST['daytidy_taxonomy_nonce']) ? sanitize_text_field(wp_unslash((string) $_POST['daytidy_taxonomy_nonce'])) : ''; if (!$nonce || !wp_verify_nonce($nonce, $this->nonceAction())) return; // It's quick edit if ($this->form()->isQuickEdit($_POST)) return; // Save $this->form()->save(new Term($term_id), wp_unslash($_POST)); // Trigger Action do_action('DayTidy/A__'.get_called_class().'__save/saved', $term_id); } private function nonceAction(): string { return 'daytidy-taxonomy-' . $this->TAX; } /** * Get form handler of taxonomy * * @return FormInterface */ public function form(): FormInterface { return $this->form->fields($this->fields()); } /** * @param mixed[] $args * @return int[]|string|string[]|WP_Error|WP_Term[] */ public function fetch(array $args = []) { if (Arr::empty($args)) $args = [ 'taxonomy' => $this->TAX, 'hide_empty' => false, ]; return get_terms($args); } /** * @param mixed[] $default * @return mixed[] */ public function columns(array $default): array { // Columns $cols = $this->cols(); // Default Columns if (Arr::empty($cols)) return $default; // Customized Columns $columns = []; foreach ($cols as $key => $config) { if (Arr::empty($config) and Arr::isset($default, $key)) $columns[$key] = $default[$key]; else if (Arr::filled($config) and Arr::isset($config, 'label')) $columns[$key] = $config['label']; } return $columns; } /** * @param string $content * @param string $key * @param int $term_id * @return string */ public function content(string $content, string $key, int $term_id): string { // Columns $cols = $this->cols(); // Default Columns if (Arr::empty($cols)) return $content; // Content of Custom Columns if (Arr::isset($cols, $key) and Arr::isset($cols[$key], 'content')) { if (is_callable($cols[$key]['content'])) $content = call_user_func($cols[$key]['content'], $term_id); else if (is_string($cols[$key]['content'])) $content = $cols[$key]['content']; } return $content; } /** * @param mixed[] $default * @return mixed[] */ public function sortable(array $default): array { // Columns $cols = $this->cols(); // Default Columns if (Arr::empty($cols)) return $default; // Add Sortable Columns foreach ($cols as $key => $config) { if (Arr::empty($config)) continue; if (Arr::falsy($config, 'sortable')) continue; $default[$key] = $config['sortable']; } return $default; } /** * Taxonomy Labels * * @param string $singular * @param string $plural * @return array */ public function labels(string $singular, string $plural): array { $singular_readable = Str::humanify($singular); $singular_lower = Str::lowercase($singular); $plural_readable = Str::humanify($plural); $plural_lower = Str::lowercase($plural); return [ 'name' => $plural_readable, 'singular_name' => $singular_readable, // translators: Placeholder values. 'all_items' => sprintf(esc_html__('All %s', 'daytidy'), $plural_readable), // translators: Placeholder values. 'edit_item' => sprintf(esc_html__('Edit %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'view_item' => sprintf(esc_html__('View %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'update_item' => sprintf(esc_html__('Update %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'add_new_item' => sprintf(esc_html__('Add New %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'new_item_name' => sprintf(esc_html__('New %s Name', 'daytidy'), $singular_readable), // translators: Placeholder values. 'popular_items' => sprintf(esc_html__('Popular %s', 'daytidy'), $plural_readable), // translators: Placeholder values. 'search_items' => sprintf(esc_html__('Search %s', 'daytidy'), $plural_readable), // translators: Placeholder values. 'separate_items_with_commas' => sprintf(esc_html__('Separate %s with commas', 'daytidy'), $plural_lower), // translators: Placeholder values. 'add_or_remove_items' => sprintf(esc_html__('Add or remove %s', 'daytidy'), $plural_lower), // translators: Placeholder values. 'choose_from_most_used' => sprintf(esc_html__('Choose from the most used %s', 'daytidy'), $plural_lower), // translators: Placeholder values. 'not_found' => sprintf(esc_html__('No %s found.', 'daytidy'), $plural_lower), // translators: Placeholder values. 'back_to_items' => sprintf(esc_html__('Back to %s', 'daytidy'), $plural_readable), // translators: Placeholder values. 'parent_item' => sprintf(esc_html__('Parent %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'parent_item_colon' => sprintf(esc_html__('Parent %s:', 'daytidy'), $singular_readable), // translators: Placeholder values. 'filter_by_item' => sprintf(esc_html__('Filter by %s', 'daytidy'), $singular_readable), // translators: Placeholder values. 'item_link' => sprintf(esc_html__('%s link', 'daytidy'), $singular_readable), // translators: Placeholder values. 'item_link_description' => sprintf(esc_html__('A link to a %s', 'daytidy'), $singular_lower), // translators: Placeholder values. 'no_terms' => sprintf(esc_html__('No %s', 'daytidy'), $plural_readable), ]; } public function plural(): string { return $this->args()['labels']['name']; } public function singular(): string { return $this->args()['labels']['singular_name']; } /** * Used to register the taxonomy in DayTidy system * * @see \DayTidy\Data\Entity::taxonomies() * @param mixed[] $taxonomies * @return mixed[] */ public function introduce(array $taxonomies): array { $taxonomies[] = $this->TAX; return $taxonomies; } /** * @param string $taxonomy * @return Taxonomy */ public static function instance(string $taxonomy) { if ($taxonomy === Host::TAX) return new Host(); else if ($taxonomy === Location::TAX) return new Location(); else if ($taxonomy === Label::TAX) return new Label(); else if ($taxonomy === Tag::TAX) return new Tag(); else if ($taxonomy === OfferingCategory::TAX) return new OfferingCategory(); // Get Taxonomy Object of Add-ons and Third Parties return apply_filters('DayTidy/F__DayTidy/Taxonomy__instance/instance', null, $taxonomy); } public function create(array $data): int { $name = Arr::ternary($data, 'name', ''); if (Str::trim($name) === '') return 0; // Term Args $args = Arr::ternary($data, 'args', $data); // Insert Term $term = wp_insert_term($name, $this->TAX, $args); // An error happened if ($term instanceof WP_Error) return 0; // Created Term ID $term_id = $term['term_id']; // Save $this->form()->save(new Term($term_id), $data); // Return ID return $term_id; } abstract public function args(): array; abstract public function fields(): array; abstract public function cols(): array; }