xref: /plugin/struct/meta/SearchCloud.php (revision 7234bfb14e712ff548d9266ef32fdcc8eaf2d04e)
10699ff47SMichael Grosse<?php
20699ff47SMichael Grosse
30699ff47SMichael Grossenamespace dokuwiki\plugin\struct\meta;
40699ff47SMichael Grosse
50699ff47SMichael Grosse/**
60699ff47SMichael Grosse * Class SearchCloud
70699ff47SMichael Grosse *
80699ff47SMichael Grosse * The same as @see SearchConfig, but executed a search that is not pid-focused
90699ff47SMichael Grosse *
100699ff47SMichael Grosse * @package dokuwiki\plugin\struct\meta
110699ff47SMichael Grosse */
12d6d97f60SAnna Dabrowskaclass SearchCloud extends SearchConfig
13d6d97f60SAnna Dabrowska{
143ec19891SMichael Grosse    protected $limit = '';
153ec19891SMichael Grosse
160699ff47SMichael Grosse    /**
170699ff47SMichael Grosse     * Transform the set search parameters into a statement
180699ff47SMichael Grosse     *
190699ff47SMichael Grosse     * @return array ($sql, $opts) The SQL and parameters to execute
200699ff47SMichael Grosse     */
21dea51657SAnna Dabrowska    public function getSQL()
22d6d97f60SAnna Dabrowska    {
230699ff47SMichael Grosse        if (!$this->columns) throw new StructException('nocolname');
240699ff47SMichael Grosse
250699ff47SMichael Grosse        $QB = new QueryBuilder();
260699ff47SMichael Grosse        reset($this->schemas);
270699ff47SMichael Grosse        $schema = current($this->schemas);
280699ff47SMichael Grosse        $datatable = 'data_' . $schema->getTable();
29dea51657SAnna Dabrowska
300699ff47SMichael Grosse        $QB->addTable($datatable);
31dea51657SAnna Dabrowska
32dea51657SAnna Dabrowska        // add conditional page clauses if pid has a value
33dea51657SAnna Dabrowska        $subAnd = $QB->filters()->whereSubAnd();
34dea51657SAnna Dabrowska        $subAnd->whereAnd("$datatable.pid = ''");
35*7234bfb1Ssplitbrain
36dea51657SAnna Dabrowska        $subOr = $subAnd->whereSubOr();
37dea51657SAnna Dabrowska        $subOr->whereAnd("GETACCESSLEVEL($datatable.pid) > 0");
38dea51657SAnna Dabrowska        $subOr->whereAnd("PAGEEXISTS($datatable.pid) = 1");
39b871825aSAndreas Gohr        $subOr->whereSubOr()
40b871825aSAndreas Gohr            ->whereAnd('ASSIGNED == 1')
41b871825aSAndreas Gohr            ->whereSubOr()
42b871825aSAndreas Gohr                ->whereAnd("$datatable.rid > 0")
43b871825aSAndreas Gohr                ->whereAnd("ASSIGNED IS NULL");
44dea51657SAnna Dabrowska
45dea51657SAnna Dabrowska        // add conditional schema assignment check
46dea51657SAnna Dabrowska        $QB->addLeftJoin(
47dea51657SAnna Dabrowska            $datatable,
48dea51657SAnna Dabrowska            'schema_assignments',
49dea51657SAnna Dabrowska            '',
50dea51657SAnna Dabrowska            "$datatable.pid != ''
51dea51657SAnna Dabrowska                    AND $datatable.pid = schema_assignments.pid
5215df5922SAnna Dabrowska                    AND schema_assignments.tbl = '{$schema->getTable()}'"
53dea51657SAnna Dabrowska        );
54dea51657SAnna Dabrowska
550699ff47SMichael Grosse        $QB->filters()->whereAnd("$datatable.latest = 1");
565b133c8dSMichael Große        $QB->filters()->where('AND', 'tag IS NOT \'\'');
570699ff47SMichael Grosse
580699ff47SMichael Grosse        $col = $this->columns[0];
590699ff47SMichael Grosse        if ($col->isMulti()) {
600699ff47SMichael Grosse            $multitable = "multi_{$col->getTable()}";
6187feee46SMichael Grosse            $MN = $QB->generateTableAlias('M');
620699ff47SMichael Grosse
630699ff47SMichael Grosse            $QB->addLeftJoin(
640699ff47SMichael Grosse                $datatable,
650699ff47SMichael Grosse                $multitable,
660699ff47SMichael Grosse                $MN,
6715df5922SAnna Dabrowska                "$datatable.pid = $MN.pid AND
6815df5922SAnna Dabrowska                     $datatable.rid = $MN.rid AND
690699ff47SMichael Grosse                     $datatable.rev = $MN.rev AND
700699ff47SMichael Grosse                     $MN.colref = {$col->getColref()}"
710699ff47SMichael Grosse            );
720699ff47SMichael Grosse
730699ff47SMichael Grosse            $col->getType()->select($QB, $MN, 'value', 'tag');
745f11f83eSMichael Grosse            $colname = $MN . '.value';
750699ff47SMichael Grosse        } else {
760699ff47SMichael Grosse            $col->getType()->select($QB, $datatable, $col->getColName(), 'tag');
770699ff47SMichael Grosse            $colname = $datatable . '.' . $col->getColName();
780699ff47SMichael Grosse        }
790699ff47SMichael Grosse        $QB->addSelectStatement("COUNT($colname)", 'count');
8015df5922SAnna Dabrowska        $QB->addSelectColumn('schema_assignments', 'assigned', 'ASSIGNED');
810699ff47SMichael Grosse        $QB->addGroupByStatement('tag');
82aafac1c1SMichael Grosse        $QB->addOrderBy('count DESC');
830699ff47SMichael Grosse
84*7234bfb1Ssplitbrain        [$sql, $opts] = $QB->getSQL();
853ec19891SMichael Grosse        return [$sql . $this->limit, $opts];
860699ff47SMichael Grosse    }
870699ff47SMichael Grosse
880699ff47SMichael Grosse    /**
893ec19891SMichael Grosse     * We do not have pagination in clouds, so we can work with a limit within SQL
903ec19891SMichael Grosse     *
913ec19891SMichael Grosse     * @param int $limit
923ec19891SMichael Grosse     */
93d6d97f60SAnna Dabrowska    public function setLimit($limit)
94d6d97f60SAnna Dabrowska    {
953ec19891SMichael Grosse        $this->limit = " LIMIT $limit";
963ec19891SMichael Grosse    }
973ec19891SMichael Grosse
983ec19891SMichael Grosse    /**
990699ff47SMichael Grosse     * Execute this search and return the result
1000699ff47SMichael Grosse     *
1010699ff47SMichael Grosse     * The result is a two dimensional array of Value()s.
1020699ff47SMichael Grosse     *
1030699ff47SMichael Grosse     * @return Value[][]
1040699ff47SMichael Grosse     */
105dea51657SAnna Dabrowska    public function execute()
106d6d97f60SAnna Dabrowska    {
107*7234bfb1Ssplitbrain        [$sql, $opts] = $this->getSQL();
1080699ff47SMichael Grosse
1090699ff47SMichael Grosse        /** @var \PDOStatement $res */
1100699ff47SMichael Grosse        $res = $this->sqlite->query($sql, $opts);
1110699ff47SMichael Grosse        if ($res === false) throw new StructException("SQL execution failed for\n\n$sql");
1120699ff47SMichael Grosse
1133ec19891SMichael Grosse        $result = [];
11479b29326SAnna Dabrowska        $rows = $res->fetchAll(\PDO::FETCH_ASSOC);
115ae457e47SMichael Grosse
1163ec19891SMichael Grosse        foreach ($rows as $row) {
117ae457e47SMichael Grosse            if (!empty($this->config['min']) && $this->config['min'] > $row['count']) {
118ae457e47SMichael Grosse                break;
119ae457e47SMichael Grosse            }
1200699ff47SMichael Grosse
1210699ff47SMichael Grosse            $row['tag'] = new Value($this->columns[0], $row['tag']);
1220699ff47SMichael Grosse            $result[] = $row;
1230699ff47SMichael Grosse        }
1240699ff47SMichael Grosse
12579b29326SAnna Dabrowska        $res->closeCursor();
1263ec19891SMichael Grosse        $this->count = count($result);
1270699ff47SMichael Grosse        return $result;
1280699ff47SMichael Grosse    }
1290699ff47SMichael Grosse}
130