xref: /plugin/struct/types/Page.php (revision ba4522e61dba3c7a23392ee7b5cd4e65a38da6fa)
1<?php
2namespace dokuwiki\plugin\struct\types;
3
4use dokuwiki\plugin\struct\meta\QueryBuilder;
5
6/**
7 * Class Page
8 *
9 * Represents a single page in the wiki. Will be linked in output.
10 *
11 * @package dokuwiki\plugin\struct\types
12 */
13class Page extends AbstractMultiBaseType {
14
15    protected $config = array(
16        'usetitles' => false,
17        'autocomplete' => array(
18            'mininput' => 2,
19            'maxresult' => 5,
20            'namespace' => '',
21            'postfix' => '',
22        ),
23    );
24
25    /**
26     * Output the stored data
27     *
28     * @param string $value the value stored in the database - JSON when titles are used
29     * @param \Doku_Renderer $R the renderer currently used to render the data
30     * @param string $mode The mode the output is rendered in (eg. XHTML)
31     * @return bool true if $mode could be satisfied
32     */
33    public function renderValue($value, \Doku_Renderer $R, $mode) {
34        if($this->config['usetitles']) {
35            list($id, $title) = json_decode($value);
36        } else {
37            $id = $value;
38            $title = null;
39        }
40
41        if(!$id) return true;
42
43        $R->internallink(":$id", $title);
44        return true;
45    }
46
47    /**
48     * Cleans the link
49     *
50     * @param string $value
51     * @return string
52     */
53    public function validate($value) {
54        return cleanID($value);
55    }
56
57    /**
58     * Autocompletion support for pages
59     *
60     * @return array
61     */
62    public function handleAjax() {
63        global $INPUT;
64
65        // check minimum length
66        $lookup = trim($INPUT->str('search'));
67        if(utf8_strlen($lookup) < $this->config['autocomplete']['mininput']) return array();
68
69        // results wanted?
70        $max = $this->config['autocomplete']['maxresult'];
71        if($max <= 0) return array();
72
73        // lookup with namespace and postfix applied
74        $namespace = $this->config['autocomplete']['namespace'];
75        if($namespace) {
76            // namespace may be relative, resolve in current context
77            $namespace .= ':foo'; // resolve expects pageID
78            resolve_pageid($INPUT->str('ns'), $namespace, $exists);
79            $namespace = getNS($namespace);
80        }
81        $postfix = $this->config['postfix'];
82        if($namespace) $lookup .= ' @' . $namespace;
83
84        $data = ft_pageLookup($lookup, true, $this->config['usetitles']);
85        if(!count($data)) return array();
86
87        // this basically duplicates what we do in ajax_qsearch()
88        $result = array();
89        $counter = 0;
90        foreach($data as $id => $title) {
91            if($this->config['usetitles']) {
92                $name = $title . ' (' . $id . ')';
93            } else {
94                $ns = getNS($id);
95                if($ns) {
96                    $name = noNS($id) . ' (' . $ns . ')';
97                } else {
98                    $name = $id;
99                }
100            }
101
102            // check suffix
103            if($postfix && !substr($id, -1 * strlen($postfix)) == $postfix) {
104                continue; // page does not end in postfix, don't suggest it
105            }
106
107            $result[] = array(
108                'label' => $name,
109                'value' => $id
110            );
111
112            $counter++;
113            if($counter > $max) break;
114        }
115
116        return $result;
117    }
118
119    /**
120     * When using titles, we need ot join the titles table
121     *
122     * @param QueryBuilder $QB
123     * @param string $tablealias
124     * @param string $colname
125     * @param string $alias
126     */
127    public function select(QueryBuilder $QB, $tablealias, $colname, $alias) {
128        if(!$this->config['usetitles']) {
129            parent::select($QB, $tablealias, $colname, $alias);
130            return;
131        }
132        $rightalias = $QB->generateTableAlias();
133        $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.$colname = $rightalias.pid");
134        $QB->addSelectStatement("JSON($tablealias.$colname, $rightalias.title)", $alias);
135    }
136
137    /**
138     * When using titles, sort by them first
139     *
140     * @param QueryBuilder $QB
141     * @param string $tablealias
142     * @param string $colname
143     * @param string $order
144     */
145    public function sort(QueryBuilder $QB, $tablealias, $colname, $order) {
146        if(!$this->config['usetitles']) {
147            parent::sort($QB, $tablealias, $colname, $order);
148            return;
149        }
150
151        $rightalias = $QB->generateTableAlias();
152        $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.$colname = $rightalias.pid");
153        $QB->addOrderBy("$rightalias.title $order");
154        $QB->addOrderBy("$tablealias.$colname $order");
155    }
156
157    /**
158     * Return the pageid only
159     *
160     * @param string $value
161     * @return string
162     */
163    public function rawValue($value) {
164        if($this->config['usetitles']) {
165            list($value) = json_decode($value);
166        }
167        return $value;
168    }
169
170    /**
171     * When using titles, we need to compare against the title table, too
172     *
173     * @param QueryBuilder $QB
174     * @param string $tablealias
175     * @param string $colname
176     * @param string $comp
177     * @param string $value
178     * @param string $op
179     */
180    public function filter(QueryBuilder $QB, $tablealias, $colname, $comp, $value, $op) {
181        if(!$this->config['usetitles']) {
182            parent::filter($QB, $tablealias, $colname, $comp, $value, $op);
183            return;
184        }
185
186        $rightalias = $QB->generateTableAlias();
187        $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.$colname = $rightalias.pid");
188
189        // compare against page and title
190        $sub = $QB->filters()->where($op);
191        $pl = $QB->addValue($value);
192        $sub->whereOr("$tablealias.$colname $comp $pl");
193        $pl = $QB->addValue($value);
194        $sub->whereOr("$rightalias.title $comp $pl");
195    }
196
197}
198