taxonomy(); add_action($tax . '_edit_form_fields', array($this, 'render_related_panel'), 5, 2); } private function taxonomy() { return (string) apply_filters('aieo_dmm_tag_extras_taxonomy', 'product_tag'); } public function render_related_panel($term, $taxonomy) { if (!is_object($term) || !isset($term->term_id)) { return; } if ((string) $taxonomy !== $this->taxonomy()) { return; } if (!class_exists('AIEO_DMM_Related_Tab')) { return; } ?>

term_id); ?>
get_results( "SELECT source_taxonomy, target_kind, target_subtype, COUNT(*) AS edges, COUNT(DISTINCT source_term_id) AS terms FROM `{$table}` GROUP BY source_taxonomy, target_kind, target_subtype", ARRAY_A ); $out = array(); foreach ($rows as $r) { $src = (string) $r['source_taxonomy']; if (!isset($out[$src])) { $out[$src] = array('edges' => 0, 'terms' => 0, 'targets' => array()); } $out[$src]['edges'] += (int) $r['edges']; $out[$src]['terms'] = max($out[$src]['terms'], (int) $r['terms']); $label = self::target_label((string) $r['target_kind'], (string) $r['target_subtype']); $out[$src]['targets'][$label] = ( isset($out[$src]['targets'][$label]) ? $out[$src]['targets'][$label] : 0 ) + (int) $r['edges']; } return $out; } private static function target_label($kind, $subtype) { if ('term' === $kind) { $tax = get_taxonomy($subtype); return ($tax && isset($tax->labels->name)) ? (string) $tax->labels->name : $subtype; } if ('post' === $kind) { $pt = get_post_type_object($subtype); return ($pt && isset($pt->labels->name)) ? (string) $pt->labels->name : $subtype; } return $subtype !== '' ? $subtype : $kind; } public function render_subtab() { $usage = self::usage(); $taxes = class_exists('AIEO_DMM_Related_Tab') ? (array) AIEO_DMM_Related_Tab::source_taxonomies() : array(); list($open, $close) = AIEO_DMM_UI::card(array( 'anchor' => 'tag-extras-overview', 'icon' => 'circle-question-mark', 'title' => $this->get_label(), 'description' => __( 'Link a brand to a category, a category to a blog post, a tag to a need. The link is stored once and shown from BOTH ends: connect a brand to "Dry skin" and that brand appears on the Dry skin screen, and Dry skin appears on the brand, with nothing to keep in step by hand. The storefront blocks that show related brands, categories and articles read these links.', 'ai-eshop-optimizer' ), 'footnote' => __( 'Open one, click a term, and the Related panel sits under its normal fields.', 'ai-eshop-optimizer' ), 'col' => 1, )); echo $open; $articles = \Rooster\Admin\Guidance::text(__( 'Blog posts count too, in both directions. Tie an article to the brands and categories it is about, and the article can list them while those brands and categories list the article: the Post Related Brands and Post Related Product Categories blocks put them at the foot of the post, and the brand and category pages show the writing about them.', 'ai-eshop-optimizer' ), 'guidance', array( 'question' => __( 'Do blog posts count?', 'ai-eshop-optimizer' ) )); echo $articles; $nolist = \Rooster\Admin\Guidance::text(__( 'There is no list to fill in here. You make a link from whichever term you are already editing, which is why this screen shows where your links are rather than asking you to build them in one place.', 'ai-eshop-optimizer' ), 'guidance', array( 'question' => __( 'Where is the list?', 'ai-eshop-optimizer' ) )); echo $nolist; if (!$taxes) { $off = \Rooster\Admin\States::state('not-set-up', array( 'title' => __('The related-content panel is not loaded on this site.', 'ai-eshop-optimizer'), 'compact' => true, )); echo $off; echo $close; return; } $tax_rows = array(); foreach ($taxes as $tax) { $obj = get_taxonomy($tax); $name = ($obj && isset($obj->labels->name)) ? (string) $obj->labels->name : (string) $tax; $edges = isset($usage[$tax]) ? $usage[$tax]['edges'] : 0; $terms = isset($usage[$tax]) ? $usage[$tax]['terms'] : 0; $tgts = isset($usage[$tax]) ? $usage[$tax]['targets'] : array(); arsort($tgts); $url = add_query_arg( array('taxonomy' => $tax, 'post_type' => 'product'), admin_url('edit-tags.php') ); if ($tgts) { $parts = array(); foreach ($tgts as $label => $n) { $parts[] = esc_html($label) . ' ' . esc_html(number_format_i18n($n)) . ''; } $linked = wp_kses_post(implode(' · ', $parts)); } else { $linked = '' . esc_html__('nothing linked yet', 'ai-eshop-optimizer') . ''; } $tax_rows[] = array( '_name' => $name, 'where' => array('title' => $name, 'sub' => (string) $tax), 'terms' => number_format_i18n($terms), 'edges' => number_format_i18n($edges), 'linked' => array('html' => $linked), 'act' => array(array('label' => __('Open', 'ai-eshop-optimizer'), 'url' => $url)), ); } echo \Rooster\Admin\Ui::table( array( array('key' => 'where', 'label' => __('Where you can link from', 'ai-eshop-optimizer'), 'type' => 'text'), array('key' => 'terms', 'label' => __('Terms linked', 'ai-eshop-optimizer'), 'type' => 'num'), array('key' => 'edges', 'label' => __('Links', 'ai-eshop-optimizer'), 'type' => 'num'), array('key' => 'linked', 'label' => __('Linked to', 'ai-eshop-optimizer'), 'type' => 'html'), array('key' => 'act', 'label' => __('Actions', 'ai-eshop-optimizer'), 'type' => 'actions'), ), $tax_rows, array('id' => 'aieo-tag-extras-usage') ); echo $close; } }