Lines 93.18% 41 / 44
Methods 85.71% 6 / 7
Classes 0.00% 0 / 1
Covered by tests of size
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 reviewResultSet 90.32% 28 / 31 0.00% 0 / 1 14.18
 setResultSet 100.00% 1 / 1 100.00% 1 / 1 1
 getScore 100.00% 8 / 8 100.00% 1 / 1 7
 getResultSet 100.00% 1 / 1 100.00% 1 / 1 1
 getNumberOfResults 100.00% 1 / 1 100.00% 1 / 1 1
 setNumberOfResults 100.00% 1 / 1 100.00% 1 / 1 1
32class SearchResultSet
33{
34    /**
35     * "Raw" search result set without permission checks and with possible
36     * duplicates.
37     *
38     * @var stdClass[]
39     */
40    protected array $rawResultSet = [];
41
42    /**
43     * "Reviewed" search result set with checked permissions and without
44     * duplicates.
45     *
46     * @var stdClass[]
47     */
48    protected array $reviewedResultSet = [];
49
50    /**
51     * Ordering of result set.
52     */
53    protected string $ordering;
54
55    /**
56     * Number of search results.
57     */
58    protected int $numberOfResults = 0;
59
60    /**
61     * Constructor.
62     *
63     * @param CurrentUser $currentUser User object
64     * @param Configuration $configuration Configuration object
65     */
66    public function __construct(
67        protected CurrentUser $currentUser,
68        private readonly Permission $faqPermission,
69        protected Configuration $configuration,
70    ) {
71    }
72
73    /**
74     * Check on user and group permissions and on duplicate FAQs.
75     *
76     * @param stdClass[] $resultSet Array with search results
77     */
78    public function reviewResultSet(array $resultSet): void
79    {
80        $this->setResultSet($resultSet);
81
82        $duplicateResults = [];
83        $currentGroupIds = [-1];
84
85        if (
86            'basic' !== $this->configuration->get(item: 'security.permLevel')
87            && isset($this->currentUser->perm) // @mago-expect lint:no-isset - typed property may be uninitialized
88        ) {
89            $permission = $this->currentUser->perm;
90            if (method_exists($permission, 'getUserGroups')) {
91                $currentGroupIds = $permission->getUserGroups($this->currentUser->getUserId());
92            }
93        }
94
95        foreach ($this->rawResultSet as $result) {
96            $permission = false;
97
98            // check permissions for groups
99            if ('medium' === $this->configuration->get(item: 'security.permLevel')) {
100                $groupPermissions = $this->faqPermission->get(Permission::GROUP, (int) $result->id);
101                $groupIds = $currentGroupIds;
102                foreach ($groupPermissions as $groupPermission) {
103                    if (!in_array($groupPermission, $groupIds, strict: true)) {
104                        continue;
105                    }
106
107                    $permission = true;
108                }
109            }
110
111            // check permission for a user
112            if ('basic' === $this->configuration->get(item: 'security.permLevel')) {
113                $userPermission = $this->faqPermission->get(Permission::USER, (int) $result->id);
114                $permission =
115                    in_array(-1, $userPermission, strict: true)
116                    || in_array($this->currentUser->getUserId(), $userPermission, strict: true);
117            }
118
119            // check on duplicates
120            $resultId = (int) $result->id;
121            if (array_key_exists($resultId, $duplicateResults)) {
122                continue;
123            }
124
125            $duplicateResults[$resultId] = true;
126
127            if (!property_exists($result, 'score') || $result->score === null) {
128                $result->score = $this->getScore($result);
129            }
130
131            if ($permission) {
132                $this->reviewedResultSet[] = $result;
133            }
134        }
135
136        $this->setNumberOfResults($this->reviewedResultSet);
137    }
138
139    /**
140     * Sets the "raw" search results.
141     *
142     * @param stdClass[] $resultSet Array with search results
143     */
144    public function setResultSet(array $resultSet): void
145    {
146        $this->rawResultSet = $resultSet;
147    }
148
149    public function getScore(stdClass $object): float
150    {
151        $score = 0.0;
152
153        if (property_exists($object, 'relevance_thema') && is_numeric($object->relevance_thema)) {
154            $score += (float) $object->relevance_thema;
155        }
156
157        if (property_exists($object, 'relevance_content') && is_numeric($object->relevance_content)) {
158            $score += (float) $object->relevance_content;
159        }
160
161        if (property_exists($object, 'relevance_keywords') && is_numeric($object->relevance_keywords)) {
162            $score += (float) $object->relevance_keywords;
163        }
164
165        return round(($score / 3) * 100);
166    }
167
168    /**
169     * Returns the "reviewed" search results.
170     *
171     * @return stdClass[]
172     */
173    public function getResultSet(): array
174    {
175        return $this->reviewedResultSet;
176    }
177
178    /**
179     * Returns the number search results.
180     */
181    public function getNumberOfResults(): int
182    {
183        return $this->numberOfResults;
184    }
185
186    /**
187     * Sets the number of search results.
188     *
189     * @param stdClass[] $resultSet
190     */
191    public function setNumberOfResults(array $resultSet): void
192    {
193        $this->numberOfResults = count($resultSet);
194    }
195}