1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5/** 6 * Class SearchCloud 7 * 8 * The same as @see SearchConfig, but executed a search that is not pid-focused 9 * 10 * @package dokuwiki\plugin\struct\meta 11 */ 12class SearchCloud extends SearchConfig 13{ 14 protected $limit = ''; 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 { 23 if (!$this->columns) throw new StructException('nocolname'); 24 25 $QB = new QueryBuilder(); 26 reset($this->schemas); 27 $schema = current($this->schemas); 28 $datatable = 'data_' . $schema->getTable(); 29 30 $QB->addTable($datatable); 31 32 // add conditional page clauses if pid has a value 33 $subAnd = $QB->filters()->whereSubAnd(); 34 $subAnd->whereAnd("$datatable.pid = ''"); 35 36 $subOr = $subAnd->whereSubOr(); 37 $subOr->whereAnd("GETACCESSLEVEL($datatable.pid) > 0"); 38 $subOr->whereAnd("PAGEEXISTS($datatable.pid) = 1"); 39 $subOr->whereSubOr() 40 ->whereAnd('ASSIGNED == 1') 41 ->whereSubOr() 42 ->whereAnd("$datatable.rid > 0") 43 ->whereAnd("ASSIGNED IS NULL"); 44 45 // add conditional schema assignment check 46 $QB->addLeftJoin( 47 $datatable, 48 'schema_assignments', 49 '', 50 "$datatable.pid != '' 51 AND $datatable.pid = schema_assignments.pid 52 AND schema_assignments.tbl = '{$schema->getTable()}'" 53 ); 54 55 $QB->filters()->whereAnd("$datatable.latest = 1"); 56 $QB->filters()->where('AND', 'tag IS NOT \'\''); 57 58 $col = $this->columns[0]; 59 if ($col->isMulti()) { 60 $multitable = "multi_{$col->getTable()}"; 61 $MN = $QB->generateTableAlias('M'); 62 63 $QB->addLeftJoin( 64 $datatable, 65 $multitable, 66 $MN, 67 "$datatable.pid = $MN.pid AND 68 $datatable.rid = $MN.rid AND 69 $datatable.rev = $MN.rev AND 70 $MN.colref = {$col->getColref()}" 71 ); 72 73 $col->getType()->select($QB, $MN, 'value', 'tag'); 74 $colname = $MN . '.value'; 75 } else { 76 $col->getType()->select($QB, $datatable, $col->getColName(), 'tag'); 77 $colname = $datatable . '.' . $col->getColName(); 78 } 79 $QB->addSelectStatement("COUNT($colname)", 'count'); 80 $QB->addSelectColumn('schema_assignments', 'assigned', 'ASSIGNED'); 81 $QB->addGroupByStatement('tag'); 82 $QB->addOrderBy('count DESC'); 83 84 [$sql, $opts] = $QB->getSQL(); 85 return [$sql . $this->limit, $opts]; 86 } 87 88 /** 89 * We do not have pagination in clouds, so we can work with a limit within SQL 90 * 91 * @param int $limit 92 */ 93 public function setLimit($limit) 94 { 95 $this->limit = " LIMIT $limit"; 96 } 97 98 /** 99 * Execute this search and return the result 100 * 101 * Because the cloud uses a different search, we omit calling 102 * getResult() und run() methods of the parent class, and return the result array directly. 103 * 104 * @return Value[][] 105 */ 106 public function getRows() 107 { 108 [$sql, $opts] = $this->getSQL(); 109 110 /** @var \PDOStatement $res */ 111 $res = $this->sqlite->query($sql, $opts); 112 if ($res === false) throw new StructException("SQL execution failed for\n\n$sql"); 113 114 $result = []; 115 $rows = $res->fetchAll(\PDO::FETCH_ASSOC); 116 117 foreach ($rows as $row) { 118 if (!empty($this->config['min']) && $this->config['min'] > $row['count']) { 119 break; 120 } 121 122 $row['tag'] = new Value($this->columns[0], $row['tag']); 123 $result[] = $row; 124 } 125 126 $res->closeCursor(); 127 return $result; 128 } 129} 130