11fc2361fSSzymon Olewniczak<?php 21fc2361fSSzymon Olewniczak 31fc2361fSSzymon Olewniczaknamespace dokuwiki\plugin\struct\meta; 41fc2361fSSzymon Olewniczakuse dokuwiki\plugin\struct\types\Page; 51fc2361fSSzymon Olewniczak 61fc2361fSSzymon Olewniczakclass CSVPageImporter extends CSVImporter { 7e53295c5SSzymon Olewniczak 8e53295c5SSzymon Olewniczak protected $importedPids = array(); 9e53295c5SSzymon Olewniczak 10ee52a3aaSMichael Große /** @var bool[] */ 1117dbef8aSMichael Große protected $createPage = []; 1217dbef8aSMichael Große 131fc2361fSSzymon Olewniczak /** 141fc2361fSSzymon Olewniczak * Chceck if schema is page schema 151fc2361fSSzymon Olewniczak * 161fc2361fSSzymon Olewniczak * @throws StructException 171fc2361fSSzymon Olewniczak * @param string $table 181fc2361fSSzymon Olewniczak * @param string $file 191fc2361fSSzymon Olewniczak */ 201fc2361fSSzymon Olewniczak public function __construct($table, $file) { 211fc2361fSSzymon Olewniczak parent::__construct($table, $file); 221fc2361fSSzymon Olewniczak 231fc2361fSSzymon Olewniczak if($this->schema->isLookup()) throw new StructException($table.' is not a page schema'); 241fc2361fSSzymon Olewniczak } 251fc2361fSSzymon Olewniczak 261fc2361fSSzymon Olewniczak /** 271fc2361fSSzymon Olewniczak * Import page schema only when the pid header is present. 281fc2361fSSzymon Olewniczak */ 291fc2361fSSzymon Olewniczak protected function readHeaders() { 301fc2361fSSzymon Olewniczak 311fc2361fSSzymon Olewniczak //add pid to struct 321fc2361fSSzymon Olewniczak $pageType = new Page(null, 'pid'); 3317dbef8aSMichael Große $this->columns[] = new Column(0, $pageType, 0, true, $this->schema->getTable()); 341fc2361fSSzymon Olewniczak 351fc2361fSSzymon Olewniczak parent::readHeaders(); 361fc2361fSSzymon Olewniczak 371fc2361fSSzymon Olewniczak if(!in_array('pid', $this->header)) throw new StructException('There is no "pid" header in the CSV. Schema not imported.'); 381fc2361fSSzymon Olewniczak } 391fc2361fSSzymon Olewniczak 401fc2361fSSzymon Olewniczak /** 411fc2361fSSzymon Olewniczak * Creates the insert string for the single value table 421fc2361fSSzymon Olewniczak * 431fc2361fSSzymon Olewniczak * @return string 441fc2361fSSzymon Olewniczak */ 451fc2361fSSzymon Olewniczak protected function getSQLforAllValues() { 461fc2361fSSzymon Olewniczak $colnames = array(); 471fc2361fSSzymon Olewniczak foreach($this->columns as $i => $col) { 481fc2361fSSzymon Olewniczak $colnames[] = 'col' . $col->getColref(); 491fc2361fSSzymon Olewniczak } 501fc2361fSSzymon Olewniczak //replace first column with pid 511fc2361fSSzymon Olewniczak $colnames[0] = 'pid'; 521fc2361fSSzymon Olewniczak //insert rev at the end 531fc2361fSSzymon Olewniczak $colnames[] = 'rev'; 541fc2361fSSzymon Olewniczak 551fc2361fSSzymon Olewniczak $placeholds = join(', ', array_fill(0, count($colnames), '?')); 561fc2361fSSzymon Olewniczak $colnames = join(', ', $colnames); 571fc2361fSSzymon Olewniczak $table = $this->schema->getTable(); 581fc2361fSSzymon Olewniczak 59e53295c5SSzymon Olewniczak return "INSERT INTO data_$table ($colnames, latest) VALUES ($placeholds, 1)"; 601fc2361fSSzymon Olewniczak } 611fc2361fSSzymon Olewniczak 621fc2361fSSzymon Olewniczak /** 631fc2361fSSzymon Olewniczak * Add the revision. 641fc2361fSSzymon Olewniczak * 651fc2361fSSzymon Olewniczak * @param string[] $values 661fc2361fSSzymon Olewniczak * @param $line 671fc2361fSSzymon Olewniczak * @param string $single 681fc2361fSSzymon Olewniczak * @param string $multi 691fc2361fSSzymon Olewniczak */ 701fc2361fSSzymon Olewniczak protected function saveLine($values, $line, $single, $multi) { 71e53295c5SSzymon Olewniczak //create new page revision 7295ea798eSMichael Große $pid = cleanID($values[0]); 7317dbef8aSMichael Große if ($this->createPage[$pid]) { 7417dbef8aSMichael Große $this->createPage($pid, $line); 7517dbef8aSMichael Große } 76e53295c5SSzymon Olewniczak $helper = plugin_load('helper', 'struct'); 77e53295c5SSzymon Olewniczak $revision = $helper->createPageRevision($pid, 'CSV data imported'); 78e53295c5SSzymon Olewniczak p_get_metadata($pid); // reparse the metadata of the page top update the titles/rev/lasteditor table 79e53295c5SSzymon Olewniczak 80e53295c5SSzymon Olewniczak // make sure this schema is assigned 81e53295c5SSzymon Olewniczak /** @noinspection PhpUndefinedVariableInspection */ 82e53295c5SSzymon Olewniczak Assignments::getInstance()->assignPageSchema( 83e53295c5SSzymon Olewniczak $pid, 84e53295c5SSzymon Olewniczak $this->schema->getTable() 85e53295c5SSzymon Olewniczak ); 86e53295c5SSzymon Olewniczak 87e53295c5SSzymon Olewniczak //add page revision to values 88e53295c5SSzymon Olewniczak $values[] = $revision; 89e53295c5SSzymon Olewniczak 901fc2361fSSzymon Olewniczak parent::saveLine($values, $line, $single, $multi); 911fc2361fSSzymon Olewniczak } 921fc2361fSSzymon Olewniczak 931fc2361fSSzymon Olewniczak /** 9417dbef8aSMichael Große * Create a page from a namespace template and replace column-label-placeholders 9517dbef8aSMichael Große * 9617dbef8aSMichael Große * This is intended to use the same placeholders as bureaucracy in their most basic version 9717dbef8aSMichael Große * (i.e. without default values, formatting, etc. ) 9817dbef8aSMichael Große * 9917dbef8aSMichael Große * @param string $pid 10017dbef8aSMichael Große * @param array $line 10117dbef8aSMichael Große */ 10217dbef8aSMichael Große protected function createPage($pid, $line) 10317dbef8aSMichael Große { 10417dbef8aSMichael Große $text = pageTemplate($pid); 10517dbef8aSMichael Große if (trim($text) === '') { 10617dbef8aSMichael Große $pageParts = explode(':', $pid); 10717dbef8aSMichael Große $pagename = end($pageParts); 10817dbef8aSMichael Große $text = "====== $pagename ======\n"; 10917dbef8aSMichael Große } 110*c09fb9e3SMichael Große $keys = array_reduce($this->columns, 111*c09fb9e3SMichael Große function ($keys, Column $col) { 112*c09fb9e3SMichael Große if (!in_array($col->getLabel(), $keys, true)) { 113*c09fb9e3SMichael Große return $keys; 114*c09fb9e3SMichael Große } 115*c09fb9e3SMichael Große $index = array_search($col->getLabel(), $keys, true); 116*c09fb9e3SMichael Große $keys[$index] = $col->getFullQualifiedLabel(); 117*c09fb9e3SMichael Große return $keys; 118*c09fb9e3SMichael Große }, 119*c09fb9e3SMichael Große $this->header 120*c09fb9e3SMichael Große ); 121*c09fb9e3SMichael Große 12217dbef8aSMichael Große $keysAt = array_map(function ($key) { return "@@$key@@";}, $keys); 12317dbef8aSMichael Große $keysHash = array_map(function ($key) { return "##$key##";}, $keys); 12417dbef8aSMichael Große $flatValues = array_map( 12517dbef8aSMichael Große function($value) { 12617dbef8aSMichael Große if (is_array($value)) { 12717dbef8aSMichael Große return implode(', ', $value); 12817dbef8aSMichael Große } 12917dbef8aSMichael Große return $value; 13017dbef8aSMichael Große }, $line); 13117dbef8aSMichael Große $text = str_replace($keysAt, $flatValues, $text); 13217dbef8aSMichael Große /** @noinspection CascadeStringReplacementInspection */ 13317dbef8aSMichael Große $text = str_replace($keysHash, $flatValues, $text); 13417dbef8aSMichael Große saveWikiText($pid, $text, 'Created by struct csv import'); 13517dbef8aSMichael Große } 13617dbef8aSMichael Große 13717dbef8aSMichael Große /** 1381fc2361fSSzymon Olewniczak * In the paga schemas primary key is a touple of (pid, rev) 1391fc2361fSSzymon Olewniczak * 1401fc2361fSSzymon Olewniczak * @param string[] $values 1411fc2361fSSzymon Olewniczak * @param string $single 1421fc2361fSSzymon Olewniczak * @return array(pid, rev) 1431fc2361fSSzymon Olewniczak */ 1441fc2361fSSzymon Olewniczak protected function insertIntoSingle($values, $single) { 1451fc2361fSSzymon Olewniczak $pid = $values[0]; 1461fc2361fSSzymon Olewniczak $rev = $values[count($values) - 1]; 147e53295c5SSzymon Olewniczak 148e53295c5SSzymon Olewniczak //update latest 149e53295c5SSzymon Olewniczak $table = $this->schema->getTable(); 150e53295c5SSzymon Olewniczak $this->sqlite->query("UPDATE data_$table SET latest = 0 WHERE latest = 1 AND pid = ?", array($pid)); 151e53295c5SSzymon Olewniczak 152e53295c5SSzymon Olewniczak //insert into table 153e53295c5SSzymon Olewniczak parent::insertIntoSingle($values, $single); 154e53295c5SSzymon Olewniczak 1551fc2361fSSzymon Olewniczak //primary key is touple of (pid, rev) 1561fc2361fSSzymon Olewniczak return array($pid, $rev); 1571fc2361fSSzymon Olewniczak } 1581fc2361fSSzymon Olewniczak 1591fc2361fSSzymon Olewniczak /** 1601fc2361fSSzymon Olewniczak * Add pid and rev to insert query parameters 1611fc2361fSSzymon Olewniczak * 1621fc2361fSSzymon Olewniczak * @param string $multi 1631fc2361fSSzymon Olewniczak * @param string $pk 1641fc2361fSSzymon Olewniczak * @param string $column 1651fc2361fSSzymon Olewniczak * @param string $row 1661fc2361fSSzymon Olewniczak * @param string $value 1671fc2361fSSzymon Olewniczak */ 1681fc2361fSSzymon Olewniczak protected function insertIntoMulti($multi, $pk, $column, $row, $value) { 1691fc2361fSSzymon Olewniczak list($pid, $rev) = $pk; 170e53295c5SSzymon Olewniczak 171e53295c5SSzymon Olewniczak //update latest 172e53295c5SSzymon Olewniczak $table = $this->schema->getTable(); 173e53295c5SSzymon Olewniczak $this->sqlite->query("UPDATE multi_$table SET latest = 0 WHERE latest = 1 AND pid = ?", array($pid)); 174e53295c5SSzymon Olewniczak 1751fc2361fSSzymon Olewniczak $this->sqlite->query($multi, array($pid, $rev, $column->getColref(), $row + 1, $value)); 1761fc2361fSSzymon Olewniczak } 1771fc2361fSSzymon Olewniczak 1781fc2361fSSzymon Olewniczak /** 1791fc2361fSSzymon Olewniczak * In page schemas we use REPLACE instead of INSERT to prevent ambiguity 1801fc2361fSSzymon Olewniczak * 1811fc2361fSSzymon Olewniczak * @return string 1821fc2361fSSzymon Olewniczak */ 1831fc2361fSSzymon Olewniczak protected function getSQLforMultiValue() { 1841fc2361fSSzymon Olewniczak $table = $this->schema->getTable(); 1851fc2361fSSzymon Olewniczak /** @noinspection SqlResolve */ 186e53295c5SSzymon Olewniczak return "INSERT INTO multi_$table (pid, rev, colref, row, value, latest) VALUES (?,?,?,?,?,1)"; 1871fc2361fSSzymon Olewniczak } 1881fc2361fSSzymon Olewniczak 1891fc2361fSSzymon Olewniczak /** 1901fc2361fSSzymon Olewniczak * Check if page id realy exists 1911fc2361fSSzymon Olewniczak * 1921fc2361fSSzymon Olewniczak * @param Column $col 1931fc2361fSSzymon Olewniczak * @param mixed $rawvalue 1941fc2361fSSzymon Olewniczak * @return bool 1951fc2361fSSzymon Olewniczak */ 1961fc2361fSSzymon Olewniczak protected function validateValue(Column $col, &$rawvalue) { 197e53295c5SSzymon Olewniczak //check if page id exists and schema is bounded to the page 1981fc2361fSSzymon Olewniczak if($col->getLabel() == 'pid') { 199e53295c5SSzymon Olewniczak $pid = cleanID($rawvalue); 200e53295c5SSzymon Olewniczak if (isset($this->importedPids[$pid])) { 201e53295c5SSzymon Olewniczak $this->errors[] = 'Page "'.$pid.'" already imported. Skipping the row.'; 202e53295c5SSzymon Olewniczak return false; 203e53295c5SSzymon Olewniczak } 204e53295c5SSzymon Olewniczak if(page_exists($pid)) { 205e53295c5SSzymon Olewniczak $this->importedPids[$pid] = true; 2061fc2361fSSzymon Olewniczak return true; 2071fc2361fSSzymon Olewniczak } 20817dbef8aSMichael Große global $INPUT; 20917dbef8aSMichael Große if ($INPUT->bool('createPage')) { 21017dbef8aSMichael Große $this->createPage[$pid] = true; 21117dbef8aSMichael Große return true; 21217dbef8aSMichael Große } 213e53295c5SSzymon Olewniczak $this->errors[] = 'Page "'.$pid.'" does not exists. Skipping the row.'; 2141fc2361fSSzymon Olewniczak return false; 2151fc2361fSSzymon Olewniczak } 2161fc2361fSSzymon Olewniczak 2171fc2361fSSzymon Olewniczak return parent::validateValue($col, $rawvalue); 2181fc2361fSSzymon Olewniczak } 2191fc2361fSSzymon Olewniczak} 220