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