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 16 /** 17 * Transform the set search parameters into a statement 18 * 19 * @return array ($sql, $opts) The SQL and parameters to execute 20 */ 21 public function getSQL() { 22 if(!$this->columns) throw new StructException('nocolname'); 23 24 $QB = new QueryBuilder(); 25 reset($this->schemas); 26 $schema = current($this->schemas); 27 $datatable = 'data_' . $schema->getTable(); 28 if(!$schema->isLookup()) { 29 $QB->addTable('schema_assignments'); 30 $QB->filters()->whereAnd("$datatable.pid = schema_assignments.pid"); 31 $QB->filters()->whereAnd("schema_assignments.tbl = '{$schema->getTable()}'"); 32 $QB->filters()->whereAnd("schema_assignments.assigned = 1"); 33 $QB->filters()->whereAnd("GETACCESSLEVEL($datatable.pid) > 0"); 34 $QB->filters()->whereAnd("PAGEEXISTS($datatable.pid) = 1"); 35 } 36 $QB->addTable($datatable); 37 $QB->filters()->whereAnd("$datatable.latest = 1"); 38 39 $col = $this->columns[0]; 40 if($col->isMulti()) { 41 $multitable = "multi_{$col->getTable()}"; 42 $MN = 'M' . $col->getColref(); 43 44 $QB->addLeftJoin( 45 $datatable, 46 $multitable, 47 $MN, 48 "$datatable.pid = $MN.pid AND 49 $datatable.rev = $MN.rev AND 50 $MN.colref = {$col->getColref()}" 51 ); 52 53 $col->getType()->select($QB, $MN, 'value', 'tag'); 54 $colname = $MN . 'value'; 55 } else { 56 $col->getType()->select($QB, $datatable, $col->getColName(), 'tag'); 57 $colname = $datatable . '.' . $col->getColName(); 58 } 59 $QB->addSelectStatement("COUNT($colname)", 'count'); 60 $QB->addGroupByStatement('tag'); 61 $QB->addOrderBy('count DESC'); 62 63 return $QB->getSQL(); 64 } 65 66 /** 67 * Execute this search and return the result 68 * 69 * The result is a two dimensional array of Value()s. 70 * 71 * This will always query for the full result (not using offset and limit) and then 72 * return the wanted range, setting the count (@see getCount) to the whole result number 73 * 74 * @return Value[][] 75 */ 76 public function execute() { 77 list($sql, $opts) = $this->getSQL(); 78 79 /** @var \PDOStatement $res */ 80 $res = $this->sqlite->query($sql, $opts); 81 if($res === false) throw new StructException("SQL execution failed for\n\n$sql"); 82 83 $this->result_pids = array(); 84 $result = array(); 85 $cursor = -1; 86 87 while($row = $res->fetch(\PDO::FETCH_ASSOC)) { 88 if (!empty($this->config['min']) && $this->config['min'] > $row['count']) { 89 break; 90 } 91 $cursor++; 92 if($cursor < $this->range_begin) continue; 93 if($this->range_end && $cursor >= $this->range_end) continue; 94 95 $row['tag'] = new Value($this->columns[0], $row['tag']); 96 $result[] = $row; 97 } 98 99 $this->sqlite->res_close($res); 100 $this->count = $cursor + 1; 101 return $result; 102 } 103} 104