xref: /dokuwiki/inc/Search/Query/PageSet.php (revision 0b1bbbbb7d4e3c531cd255dbf878ce27d5967a0c)
1<?php
2
3namespace dokuwiki\Search\Query;
4
5/**
6 * A set of pages with associated scores
7 *
8 * Represents concrete search results where each page has a numeric score
9 * (typically word frequency counts). Provides set operations for combining
10 * results during query evaluation.
11 */
12class PageSet implements StackEntry
13{
14    /** @var array<string, int> page ID => score */
15    protected array $pages;
16
17    /**
18     * @param array<string, int> $pages page ID => score
19     */
20    public function __construct(array $pages = [])
21    {
22        $this->pages = $pages;
23    }
24
25    /**
26     * @return array<string, int> page ID => score
27     */
28    public function getPages(): array
29    {
30        return $this->pages;
31    }
32
33    /**
34     * Intersect with another PageSet, summing scores for pages present in both
35     *
36     * @return self pages present in both sets
37     */
38    public function intersect(PageSet $other): self
39    {
40        $otherPages = $other->getPages();
41        $result = [];
42        foreach ($this->pages as $id => $score) {
43            if (isset($otherPages[$id])) {
44                $result[$id] = $score + $otherPages[$id];
45            }
46        }
47        return new self($result);
48    }
49
50    /**
51     * Unite with another PageSet, summing scores where pages overlap
52     *
53     * @return self pages present in either set
54     */
55    public function unite(PageSet $other): self
56    {
57        $result = $this->pages;
58        foreach ($other->getPages() as $id => $score) {
59            $result[$id] = ($result[$id] ?? 0) + $score;
60        }
61        return new self($result);
62    }
63
64    /**
65     * Remove pages that exist in the other PageSet
66     *
67     * @return self pages in this set but not in $other
68     */
69    public function subtract(PageSet $other): self
70    {
71        return new self(array_diff_key($this->pages, $other->getPages()));
72    }
73
74    /**
75     * @return bool true if this set contains no pages
76     */
77    public function isEmpty(): bool
78    {
79        return empty($this->pages);
80    }
81}
82