Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
3.28% covered (danger)
3.28%
2 / 61
11.11% covered (danger)
11.11%
1 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
HierarchyAwareTrait
3.28% covered (danger)
3.28%
2 / 61
11.11% covered (danger)
11.11%
1 / 9
1079.98
0.00% covered (danger)
0.00%
0 / 1
 getHierarchyDriver
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 setHierarchyDriverManager
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getHierarchyTopID
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHierarchyTopTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCollectionSearchId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainingCollections
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
210
 isCollection
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 getHierarchyTrees
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getHierarchyType
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * Hierarchy support for record drivers.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2017.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  RecordDrivers
25 * @author   Demian Katz <demian.katz@villanova.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
28 */
29
30namespace VuFind\RecordDriver\Feature;
31
32use function count;
33use function in_array;
34
35/**
36 * Hierarchy support for record drivers.
37 *
38 * Assumption: Hierarchy fields found in $this->fields.
39 * Assumption: Config object found in $this->mainConfig.
40 *
41 * @category VuFind
42 * @package  RecordDrivers
43 * @author   Demian Katz <demian.katz@villanova.edu>
44 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
45 * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
46 */
47trait HierarchyAwareTrait
48{
49    /**
50     * Hierarchy driver plugin manager
51     *
52     * @var \VuFind\Hierarchy\Driver\PluginManager
53     */
54    protected $hierarchyDriverManager = null;
55
56    /**
57     * Hierarchy driver for current object
58     *
59     * @var \VuFind\Hierarchy\Driver\AbstractBase
60     */
61    protected $hierarchyDriver = null;
62
63    /**
64     * Get a hierarchy driver appropriate to the current object. (May be false if
65     * disabled/unavailable).
66     *
67     * @return \VuFind\Hierarchy\Driver\AbstractBase|bool
68     */
69    public function getHierarchyDriver()
70    {
71        if (
72            null === $this->hierarchyDriver
73            && null !== $this->hierarchyDriverManager
74        ) {
75            $type = $this->getHierarchyType();
76            $this->hierarchyDriver = $type
77                ? $this->hierarchyDriverManager->get($type) : false;
78        }
79        return $this->hierarchyDriver;
80    }
81
82    /**
83     * Inject a hierarchy driver plugin manager.
84     *
85     * @param \VuFind\Hierarchy\Driver\PluginManager $pm Hierarchy driver manager
86     *
87     * @return object
88     */
89    public function setHierarchyDriverManager(
90        \VuFind\Hierarchy\Driver\PluginManager $pm
91    ) {
92        $this->hierarchyDriverManager = $pm;
93        return $this;
94    }
95
96    /**
97     * Get the hierarchy_top_id(s) associated with this item (empty if none).
98     *
99     * @return array
100     */
101    public function getHierarchyTopID()
102    {
103        return (array)($this->fields['hierarchy_top_id'] ?? []);
104    }
105
106    /**
107     * Get the absolute parent title(s) associated with this item (empty if none).
108     *
109     * @return array
110     */
111    public function getHierarchyTopTitle()
112    {
113        return (array)($this->fields['hierarchy_top_title'] ?? []);
114    }
115
116    /**
117     * Return the collection search ID for this record.
118     *
119     * @return string
120     */
121    public function getCollectionSearchId(): string
122    {
123        return $this->getUniqueID();
124    }
125
126    /**
127     * Get an associative array (id => title) of collections containing this record.
128     *
129     * @return array
130     */
131    public function getContainingCollections()
132    {
133        // If collections are disabled or this record is not part of a hierarchy, go
134        // no further....
135        if (
136            !isset($this->mainConfig->Collections->collections)
137            || !$this->mainConfig->Collections->collections
138            || !($hierarchyDriver = $this->getHierarchyDriver())
139        ) {
140            return false;
141        }
142
143        // Initialize some variables needed within the switch below:
144        $isCollection = $this->isCollection();
145        $titles = $ids = [];
146
147        // Check config setting for what constitutes a collection, act accordingly:
148        switch ($hierarchyDriver->getCollectionLinkType()) {
149            case 'All':
150                if (
151                    isset($this->fields['hierarchy_parent_title'])
152                    && isset($this->fields['hierarchy_parent_id'])
153                ) {
154                    $titles = $this->fields['hierarchy_parent_title'];
155                    $ids = $this->fields['hierarchy_parent_id'];
156                }
157                break;
158            case 'Top':
159                $topTitles = $this->getHierarchyTopTitle();
160                $topIDs = $this->getHierarchyTopID();
161                if ($topTitles && $topIDs) {
162                    foreach ($topIDs as $i => $topId) {
163                        // Don't mark an item as its own parent -- filter out parent
164                        // collections whose IDs match the current collection's ID.
165                        if (
166                            !$isCollection
167                            || $topId !== $this->fields['is_hierarchy_id']
168                        ) {
169                            $ids[] = $topId;
170                            $titles[] = $topTitles[$i];
171                        }
172                    }
173                }
174                break;
175        }
176
177        // Map the titles and IDs to a useful format:
178        $c = count($ids);
179        $retVal = [];
180        for ($i = 0; $i < $c; $i++) {
181            $retVal[$ids[$i]] = $titles[$i];
182        }
183        return $retVal;
184    }
185
186    /**
187     * Get the value of whether or not this is a collection level record
188     *
189     * NOTE: \VuFind\Hierarchy\TreeDataFormatter\AbstractBase::isCollection()
190     * duplicates some of this logic.
191     *
192     * @return bool
193     */
194    public function isCollection()
195    {
196        if (!($hierarchyDriver = $this->getHierarchyDriver())) {
197            // Not a hierarchy type record
198            return false;
199        }
200
201        // Check config setting for what constitutes a collection
202        switch ($hierarchyDriver->getCollectionLinkType()) {
203            case 'All':
204                return isset($this->fields['is_hierarchy_id']);
205            case 'Top':
206                return isset($this->fields['is_hierarchy_id'])
207                    && in_array(
208                        $this->fields['is_hierarchy_id'],
209                        $this->getHierarchyTopID()
210                    );
211            default:
212                // Default to not be a collection level record
213                return false;
214        }
215    }
216
217    /**
218     * Get a list of hierarchy trees containing this record.
219     *
220     * @param string $hierarchyID The hierarchy to get the tree for
221     *
222     * @return mixed An associative array of hierarchy trees on success
223     * (id => title), false if no hierarchies found
224     */
225    public function getHierarchyTrees($hierarchyID = false)
226    {
227        $hierarchyDriver = $this->getHierarchyDriver();
228        if ($hierarchyDriver && $hierarchyDriver->showTree()) {
229            return $hierarchyDriver->getTreeRenderer($this)
230                ->getTreeList($hierarchyID);
231        }
232        return false;
233    }
234
235    /**
236     * Get the Hierarchy Type (false if none)
237     *
238     * @return string|bool
239     */
240    public function getHierarchyType()
241    {
242        if (isset($this->fields['hierarchy_top_id'])) {
243            $hierarchyType = $this->fields['hierarchytype'] ?? false;
244            if (!$hierarchyType) {
245                $hierarchyType = $this->mainConfig->Hierarchy->driver ?? false;
246            }
247            return $hierarchyType;
248        }
249        return false;
250    }
251}