1<?php 2 3namespace plugin\struct\meta; 4 5/** 6 * Class Assignments 7 * 8 * Manages the assignment of schemas (table names) to pages and namespaces 9 * 10 * @package plugin\struct\meta 11 */ 12class Assignments { 13 14 /** @var \helper_plugin_sqlite|null */ 15 protected $sqlite; 16 17 /** @var array All the assignments */ 18 protected $patterns; 19 20 /** 21 * Assignments constructor. 22 */ 23 public function __construct() { 24 /** @var \helper_plugin_struct_db $helper */ 25 $helper = plugin_load('helper', 'struct_db'); 26 $this->sqlite = $helper->getDB(); 27 28 if($this->sqlite) $this->load(); 29 } 30 31 /** 32 * Load existing assignment patterns 33 */ 34 protected function load() { 35 $sql = 'SELECT * FROM schema_assignments_patterns ORDER BY pattern'; 36 $res = $this->sqlite->query($sql); 37 $this->patterns = $this->sqlite->res2arr($res); 38 $this->sqlite->res_close($res); 39 } 40 41 /** 42 * Add a new assignment pattern to the pattern table 43 * 44 * @param string $pattern 45 * @param string $table 46 * @return bool 47 */ 48 public function add($pattern, $table) { 49 $sql = 'REPLACE INTO schema_assignments_patterns (pattern, tbl) VALUES (?,?)'; 50 return (bool) $this->sqlite->query($sql, array($pattern, $table)); 51 } 52 53 /** 54 * Remove an existing assignment pattern from the pattern table 55 * 56 * @param string $pattern 57 * @param string $table 58 * @return bool 59 */ 60 public function remove($pattern, $table) { 61 $sql = 'DELETE FROM schema_assignments_patterns WHERE pattern = ? AND tbl = ?'; 62 return (bool) $this->sqlite->query($sql, array($pattern, $table)); 63 } 64 65 /** 66 * Get the whole pattern table 67 * 68 * @return array 69 */ 70 public function getAll() { 71 return $this->patterns; 72 } 73 74 /** 75 * Returns a list of table names assigned to the given page 76 * 77 * @param string $page 78 * @return string[] tables assigned 79 */ 80 public function getPageAssignments($page) { 81 $tables = array(); 82 83 $page = cleanID($page); 84 $pns = ':' . getNS($page) . ':'; 85 86 foreach($this->patterns as $row) { 87 $pat = $row['pattern']; 88 $tbl = $row['tbl']; 89 90 $ans = ':' . cleanID($pat) . ':'; 91 92 if(substr($pat, -2) == '**') { 93 // upper namespaces match 94 if(strpos($pns, $ans) === 0) { 95 $tables[] = $tbl; 96 } 97 } else if(substr($pat, -1) == '*') { 98 // namespaces match exact 99 if($ans == $pns) { 100 $tables[] = $tbl; 101 } 102 } else { 103 // exact match 104 if(cleanID($pat) == $page) { 105 $tables[] = $tbl; 106 } 107 } 108 } 109 110 return array_unique($tables); 111 } 112 113 /** 114 * Returns all tables of schemas that existed and stored data for the page back then 115 * 116 * @todo this is not used currently and can probably be removed again, because we're 117 * always only interested in the current state of affairs, even when restoring. 118 * 119 * @param string $page 120 * @param string $ts 121 * @return array 122 */ 123 public function getHistoricAssignments($page, $ts) { 124 $sql = "SELECT DISTINCT tbl FROM schemas WHERE ts <= ? ORDER BY ts DESC"; 125 $res = $this->sqlite->query($sql, $ts); 126 $tables = $this->sqlite->res2arr($res); 127 $this->sqlite->res_close($res); 128 129 $assigned = array(); 130 foreach ($tables as $row) { 131 $table = $row['tbl']; 132 $sql = "SELECT pid FROM data_$table WHERE pid = ? AND rev <= ? LIMIT 1"; 133 $res = $this->sqlite->query($sql, $page, $ts); 134 $found = $this->sqlite->res2arr($res); 135 $this->sqlite->res_close($res); 136 137 if($found) $assigned[] = $table; 138 } 139 140 return $assigned; 141 } 142} 143