Taxonomy.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. /**
  3. * @package Grav\Common
  4. *
  5. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common;
  9. use Grav\Common\Config\Config;
  10. use Grav\Common\Page\Collection;
  11. use Grav\Common\Page\Interfaces\PageInterface;
  12. /**
  13. * The Taxonomy object is a singleton that holds a reference to a 'taxonomy map'. This map is
  14. * constructed as a multidimensional array.
  15. *
  16. * uses the taxonomy defined in the site.yaml file and is built when the page objects are recursed.
  17. * Basically every time a page is found that has taxonomy references, an entry to the page is stored in
  18. * the taxonomy map. The map has the following format:
  19. *
  20. * [taxonomy_type][taxonomy_value][page_path]
  21. *
  22. * For example:
  23. *
  24. * [category][blog][path/to/item1]
  25. * [tag][grav][path/to/item1]
  26. * [tag][grav][path/to/item2]
  27. * [tag][dog][path/to/item3]
  28. */
  29. class Taxonomy
  30. {
  31. protected $taxonomy_map;
  32. protected $grav;
  33. /**
  34. * Constructor that resets the map
  35. *
  36. * @param Grav $grav
  37. */
  38. public function __construct(Grav $grav)
  39. {
  40. $this->taxonomy_map = [];
  41. $this->grav = $grav;
  42. }
  43. /**
  44. * Takes an individual page and processes the taxonomies configured in its header. It
  45. * then adds those taxonomies to the map
  46. *
  47. * @param PageInterface $page the page to process
  48. * @param array $page_taxonomy
  49. */
  50. public function addTaxonomy(PageInterface $page, $page_taxonomy = null)
  51. {
  52. if (!$page_taxonomy) {
  53. $page_taxonomy = $page->taxonomy();
  54. }
  55. if (empty($page_taxonomy) || !$page->published()) {
  56. return;
  57. }
  58. /** @var Config $config */
  59. $config = $this->grav['config'];
  60. if ($config->get('site.taxonomies')) {
  61. foreach ((array)$config->get('site.taxonomies') as $taxonomy) {
  62. if (isset($page_taxonomy[$taxonomy])) {
  63. foreach ((array)$page_taxonomy[$taxonomy] as $item) {
  64. $this->taxonomy_map[$taxonomy][(string)$item][$page->path()] = ['slug' => $page->slug()];
  65. }
  66. }
  67. }
  68. }
  69. }
  70. /**
  71. * Returns a new Page object with the sub-pages containing all the values set for a
  72. * particular taxonomy.
  73. *
  74. * @param array $taxonomies taxonomies to search, eg ['tag'=>['animal','cat']]
  75. * @param string $operator can be 'or' or 'and' (defaults to 'and')
  76. *
  77. * @return Collection Collection object set to contain matches found in the taxonomy map
  78. */
  79. public function findTaxonomy($taxonomies, $operator = 'and')
  80. {
  81. $matches = [];
  82. $results = [];
  83. foreach ((array)$taxonomies as $taxonomy => $items) {
  84. foreach ((array)$items as $item) {
  85. if (isset($this->taxonomy_map[$taxonomy][$item])) {
  86. $matches[] = $this->taxonomy_map[$taxonomy][$item];
  87. } else {
  88. $matches[] = [];
  89. }
  90. }
  91. }
  92. if (strtolower($operator) === 'or') {
  93. foreach ($matches as $match) {
  94. $results = array_merge($results, $match);
  95. }
  96. } else {
  97. $results = $matches ? array_pop($matches) : [];
  98. foreach ($matches as $match) {
  99. $results = array_intersect_key($results, $match);
  100. }
  101. }
  102. return new Collection($results, ['taxonomies' => $taxonomies]);
  103. }
  104. /**
  105. * Gets and Sets the taxonomy map
  106. *
  107. * @param array $var the taxonomy map
  108. *
  109. * @return array the taxonomy map
  110. */
  111. public function taxonomy($var = null)
  112. {
  113. if ($var) {
  114. $this->taxonomy_map = $var;
  115. }
  116. return $this->taxonomy_map;
  117. }
  118. /**
  119. * Gets item keys per taxonomy
  120. *
  121. * @param string $taxonomy taxonomy name
  122. *
  123. * @return array keys of this taxonomy
  124. */
  125. public function getTaxonomyItemKeys($taxonomy)
  126. {
  127. return isset($this->taxonomy_map[$taxonomy]) ? array_keys($this->taxonomy_map[$taxonomy]) : [];
  128. }
  129. }