xref: /plugin/struct/meta/SearchCloud.php (revision b193f1ee28c5fa11f136bc19373095ca8f6d073d)
1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5
6/**
7 * Class SearchCloud
8 *
9 * The same as @see SearchConfig, but executed a search that is not pid-focused
10 *
11 * @package dokuwiki\plugin\struct\meta
12 */
13class SearchCloud extends SearchConfig {
14
15    protected $limit = '';
16
17
18    /**
19     * Transform the set search parameters into a statement
20     *
21     * @return array ($sql, $opts) The SQL and parameters to execute
22     */
23    public function getSQL() {
24        if(!$this->columns) throw new StructException('nocolname');
25
26        $QB = new QueryBuilder();
27        reset($this->schemas);
28        $schema = current($this->schemas);
29        $datatable = 'data_' . $schema->getTable();
30        if(!$schema->isLookup()) {
31            $QB->addTable('schema_assignments');
32            $QB->filters()->whereAnd("$datatable.pid = schema_assignments.pid");
33            $QB->filters()->whereAnd("schema_assignments.tbl = '{$schema->getTable()}'");
34            $QB->filters()->whereAnd("schema_assignments.assigned = 1");
35            $QB->filters()->whereAnd("GETACCESSLEVEL($datatable.pid) > 0");
36            $QB->filters()->whereAnd("PAGEEXISTS($datatable.pid) = 1");
37        }
38        $QB->addTable($datatable);
39        $QB->filters()->whereAnd("$datatable.latest = 1");
40        $QB->filters()->where('AND', 'tag IS NOT \'\'');
41
42        $col = $this->columns[0];
43        if($col->isMulti()) {
44            $multitable = "multi_{$col->getTable()}";
45            $MN = $QB->generateTableAlias('M');
46
47            $QB->addLeftJoin(
48                $datatable,
49                $multitable,
50                $MN,
51                "$datatable.pid = $MN.pid AND
52                     $datatable.rev = $MN.rev AND
53                     $MN.colref = {$col->getColref()}"
54            );
55
56            $col->getType()->select($QB, $MN, 'value', 'tag');
57            $colname = $MN . '.value';
58        } else {
59            $col->getType()->select($QB, $datatable, $col->getColName(), 'tag');
60            $colname = $datatable . '.' . $col->getColName();
61        }
62        $QB->addSelectStatement("COUNT($colname)", 'count');
63        $QB->addGroupByStatement('tag');
64        $QB->addOrderBy('count DESC');
65
66        list($sql, $opts) = $QB->getSQL();
67        return [$sql . $this->limit, $opts];
68    }
69
70    /**
71     * We do not have pagination in clouds, so we can work with a limit within SQL
72     *
73     * @param int $limit
74     */
75    public function setLimit($limit) {
76        $this->limit = " LIMIT $limit";
77    }
78
79    /**
80     * Execute this search and return the result
81     *
82     * The result is a two dimensional array of Value()s.
83     *
84     * @return Value[][]
85     */
86    public function execute() {
87        list($sql, $opts) = $this->getSQL();
88
89        /** @var \PDOStatement $res */
90        $res = $this->sqlite->query($sql, $opts);
91        if($res === false) throw new StructException("SQL execution failed for\n\n$sql");
92
93        $result = [];
94        $rows = $this->sqlite->res2arr($res);
95
96        foreach ($rows as $row) {
97            if (!empty($this->config['min']) && $this->config['min'] > $row['count']) {
98                break;
99            }
100
101            $row['tag'] = new Value($this->columns[0], $row['tag']);
102            $result[] = $row;
103        }
104
105        $this->sqlite->res_close($res);
106        $this->count = count($result);
107        return $result;
108    }
109}
110