'[wc-category]', 'Top category:' => '[wc-category level="top"]', 'Last category:' => '[wc-category level="last" separator=", "]', ); public function getValue($post, $field) { $terms = 'product_variation' === $post->post_type ? get_the_terms($post->post_parent, 'product_cat') : get_the_terms($post, 'product_cat'); $termsHierarchy = array(); while (!empty($terms)) { foreach ($terms as &$term) { if ($this->termHaveParent($terms, $term)) { continue; } else { $this->sortTermsHierarchically($terms, $termsHierarchy, $term->parent); } } } $args = isset($field['args']) ? $field['args'] : array(); return $this->categoryObjectsToString($termsHierarchy, null, $args); } protected function termHaveParent($terms, $term) { foreach ($terms as $theTerm) { if ($term->parent === $theTerm->term_id) { return true; } } return false; } protected function sortTermsHierarchically(&$cats, &$into, $parentId = 0) { foreach ($cats as $i => $cat) { if ($cat->parent == $parentId) { $into[$cat->term_id] = $cat; unset($cats[$i]); } } foreach ($into as $topCat) { $topCat->childrens = array(); $this->sortTermsHierarchically($cats, $topCat->childrens, $topCat->term_id); } } protected function categoryObjectsToString($terms, $termMeta = null, $args = array()) { if ($terms && !is_wp_error($terms)) { $categoryChains = array(); foreach ($terms as $term) { $levels = $this->getLevels(array($term)); if (!empty($levels)) { if (isset($args['level']) && 'top' === $args['level']) { $categoryChains[] = reset($levels); } elseif (isset($args['level']) && 'last' === $args['level']) { $categoryChains[] = end($levels); } else { $categoryChains[] = implode(isset($args['separator']) ? $args['separator'] : "➝", $levels); } } } if (!empty($categoryChains)) { return implode('; ', $categoryChains); } else { return null; } } return null; } protected function getLevels($parents, $result = array()) { $levelItems = array(); $nextLevelParents = array(); foreach ($parents as $currentLevelParent) { $levelItems[] = $currentLevelParent->name; if (!empty($currentLevelParent->childrens)) { $nextLevelParents += $currentLevelParent->childrens; } } $result[] = implode(', ', $levelItems); return !empty($nextLevelParents) ? $this->getLevels($nextLevelParents, $result) : $result; } }