xref: /dokuwiki/inc/Search/Index/AbstractIndex.php (revision 1db169408cb6f6c0deb6231d57207dd563f36013)
1<?php
2
3namespace dokuwiki\Search\Index;
4
5/**
6 * Basic Building block to access individual index files
7 */
8abstract class AbstractIndex
9{
10    /** @var string name of the index */
11    protected $idx;
12
13    /** @var string $suffix of the index */
14    protected $suffix;
15
16    /** @var string full filename to the index */
17    protected $filename;
18
19    /** @var bool is this index opened for writing? */
20    protected $isWritable = false;
21
22    /**
23     * Initialize the index
24     *
25     * The $suffix argument is for an index that is split into multiple parts.
26     * Different index files should use different base names.
27     *
28     * @param string $idx name of the index
29     * @param string $suffix subpart identifier
30     * @param bool $isWritable has a sufficient lock been acquired to write to this index?
31     */
32    public function __construct($idx, $suffix = '', $isWritable = false)
33    {
34        global $conf;
35        $this->filename = $conf['indexdir'] . '/' . $idx . $suffix . '.idx';
36        $this->idx = $idx;
37        $this->suffix = $suffix;
38        $this->isWritable = $isWritable;
39    }
40
41    /**
42     * @return string the full path to the underlying file
43     */
44    public function getFilename()
45    {
46        return $this->filename;
47    }
48
49    /**
50     * Does this index exist, yet?
51     *
52     * @return bool
53     */
54    public function exists()
55    {
56        return file_exists($this->getFilename());
57    }
58
59    /**
60     * Return the largest numeric suffix for the current index
61     *
62     * This is only useful for indexes that use integer based suffixes (like the wordlength indexes)
63     *
64     * @return int 0 if no numeric suffix indexes are found
65     */
66    public function max()
67    {
68        global $conf;
69        $result = 0;
70        $files = glob($conf['indexdir'] . '/' . $this->idx . '*.idx');
71        foreach ($files as $file) {
72            if (preg_match('/(\d)+\.idx$/', $file, $match)) {
73                $num = (int)$match[1];
74                if ($num > $result) $result = $num;
75            }
76        }
77
78        return $result;
79    }
80
81    /**
82     * Change a line in the index
83     *
84     * If the line doesn't exist, it will be added, creating empty
85     * lines inbetween as necessary
86     *
87     * @param int $rid the line number, count starting at 0
88     * @param string $value line content to write
89     */
90    abstract public function changeRow($rid, $value);
91
92    /**
93     * Retrieve a line from the index
94     *
95     * Returns an empty string for non-existing lines
96     *
97     * @param int $rid the line number
98     * @return string a line with trailing whitespace removed
99     */
100    abstract public function retrieveRow($rid);
101
102    /**
103     * Retrieve multiple lines from the index
104     *
105     * Ignores non-existing lines, eg the result array may be smaller than the input $rids
106     *
107     * @param int[] $rids
108     * @return array [rid => value]
109     */
110    abstract public function retrieveRows($rids);
111
112    /**
113     * Searches the Index for a given value
114     *
115     * If the index is writable and the value is not found it will be added. Otherwise null is returned.
116     *
117     * Entries previously marked as deleted will be restored.  FIXME is that true?
118     *
119     * Note the existence of an entry in the index does not say anything about the existence
120     * of the real world object (eg. a page)
121     *
122     * You should preferable use accessCachedValue() instead.
123     *
124     * @param string $value
125     *
126     * @return int|null the RID of the entry, null if not found and not added
127     */
128    public function getRowID($value)
129    {
130        $result = $this->getRowIDs([$value]);
131        return $result[$value] ?? null;
132    }
133
134    /**
135     * Searches the Index for all given values
136     *
137     * If the index is writable, not found values are added
138     *
139     * @param string[] $values
140     * @return array the RIDs of the entries (value => rid)
141     */
142    abstract public function getRowIDs($values);
143
144    /**
145     * Find all RIDs matching a regular expression
146     *
147     * A full regular expression including delimiters and modifiers is expected
148     *
149     * @param string $re the regular expression to match against
150     * @return array (rid => value)
151     */
152    abstract public function search($re);
153
154    /**
155     * Clears the index by deleting its file
156     * @return void
157     */
158    public function clear()
159    {
160        @unlink($this->filename);
161    }
162
163    /**
164     * Saves the index if needed
165     *
166     * The default implementation does nothing and is only for streamlining the API of
167     * the different index classes
168     * @return void
169     */
170    public function save()
171    {
172    }
173}
174