grav = $grav; $this->language = $grav['language']; $this->taxonomy_map[$this->language->getLanguage()] = []; } /** * Takes an individual page and processes the taxonomies configured in its header. It * then adds those taxonomies to the map * * @param PageInterface $page the page to process * @param array|null $page_taxonomy */ public function addTaxonomy(PageInterface $page, $page_taxonomy = null) { if (!$page->published()) { return; } if (!$page_taxonomy) { $page_taxonomy = $page->taxonomy(); } if (empty($page_taxonomy)) { return; } /** @var Config $config */ $config = $this->grav['config']; $taxonomies = (array)$config->get('site.taxonomies'); foreach ($taxonomies as $taxonomy) { // Skip invalid taxonomies. if (!\is_string($taxonomy)) { continue; } $current = $page_taxonomy[$taxonomy] ?? null; foreach ((array)$current as $item) { $this->iterateTaxonomy($page, $taxonomy, '', $item); } } } /** * Iterate through taxonomy fields * * Reduces [taxonomy_type] to dot-notation where necessary * * @param PageInterface $page The Page to process * @param string $taxonomy Taxonomy type to add * @param string $key Taxonomy type to concatenate * @param iterable|string $value Taxonomy value to add or iterate * @return void */ public function iterateTaxonomy(PageInterface $page, string $taxonomy, string $key, $value) { if (is_iterable($value)) { foreach ($value as $identifier => $item) { $identifier = "{$key}.{$identifier}"; $this->iterateTaxonomy($page, $taxonomy, $identifier, $item); } } elseif (is_string($value)) { if (!empty($key)) { $taxonomy .= $key; } $active = $this->language->getLanguage(); $this->taxonomy_map[$active][$taxonomy][(string) $value][$page->path()] = ['slug' => $page->slug()]; } } /** * Returns a new Page object with the sub-pages containing all the values set for a * particular taxonomy. * * @param array $taxonomies taxonomies to search, eg ['tag'=>['animal','cat']] * @param string $operator can be 'or' or 'and' (defaults to 'and') * @return Collection Collection object set to contain matches found in the taxonomy map */ public function findTaxonomy($taxonomies, $operator = 'and') { $matches = []; $results = []; $active = $this->language->getLanguage(); foreach ((array)$taxonomies as $taxonomy => $items) { foreach ((array)$items as $item) { $matches[] = $this->taxonomy_map[$active][$taxonomy][$item] ?? []; } } if (strtolower($operator) === 'or') { foreach ($matches as $match) { $results = array_merge($results, $match); } } else { $results = $matches ? array_pop($matches) : []; foreach ($matches as $match) { $results = array_intersect_key($results, $match); } } return new Collection($results, ['taxonomies' => $taxonomies]); } /** * Gets and Sets the taxonomy map * * @param array|null $var the taxonomy map * @return array the taxonomy map */ public function taxonomy($var = null) { $active = $this->language->getLanguage(); if ($var) { $this->taxonomy_map[$active] = $var; } return $this->taxonomy_map[$active] ?? []; } /** * Gets item keys per taxonomy * * @param string $taxonomy taxonomy name * @return array keys of this taxonomy */ public function getTaxonomyItemKeys($taxonomy) { $active = $this->language->getLanguage(); return isset($this->taxonomy_map[$active][$taxonomy]) ? array_keys($this->taxonomy_map[$active][$taxonomy]) : []; } }