11fc2361fSSzymon Olewniczak<?php 21fc2361fSSzymon Olewniczak 31fc2361fSSzymon Olewniczaknamespace dokuwiki\plugin\struct\meta; 4d6d97f60SAnna Dabrowska 5d6d97f60SAnna Dabrowskaclass CSVPageImporter extends CSVImporter 6d6d97f60SAnna Dabrowska{ 77234bfb1Ssplitbrain protected $importedPids = []; 8e53295c5SSzymon Olewniczak 9ee52a3aaSMichael Große /** @var bool[] */ 1017dbef8aSMichael Große protected $createPage = []; 1117dbef8aSMichael Große 121fc2361fSSzymon Olewniczak /** 131fc2361fSSzymon Olewniczak * Import page schema only when the pid header is present. 141fc2361fSSzymon Olewniczak */ 15d6d97f60SAnna Dabrowska protected function readHeaders() 16d6d97f60SAnna Dabrowska { 171fc2361fSSzymon Olewniczak parent::readHeaders(); 1817a3a578SAndreas Gohr if (!in_array('pid', $this->header)) 1917a3a578SAndreas Gohr throw new StructException('There is no "pid" header in the CSV. Schema not imported.'); 201fc2361fSSzymon Olewniczak } 211fc2361fSSzymon Olewniczak 221fc2361fSSzymon Olewniczak /** 231fc2361fSSzymon Olewniczak * Add the revision. 241fc2361fSSzymon Olewniczak * 251fc2361fSSzymon Olewniczak * @param string[] $values 261fc2361fSSzymon Olewniczak */ 275e8c6cf6SAnna Dabrowska protected function saveLine($values) 28d6d97f60SAnna Dabrowska { 29e53295c5SSzymon Olewniczak //create new page revision 3095ea798eSMichael Große $pid = cleanID($values[0]); 311ca21e17SAnna Dabrowska if (isset($this->createPage[$pid])) { 325e8c6cf6SAnna Dabrowska $this->createPage($pid, $values); 3317dbef8aSMichael Große } 34e53295c5SSzymon Olewniczak // make sure this schema is assigned 35e53295c5SSzymon Olewniczak /** @noinspection PhpUndefinedVariableInspection */ 36e53295c5SSzymon Olewniczak Assignments::getInstance()->assignPageSchema( 37e53295c5SSzymon Olewniczak $pid, 38e53295c5SSzymon Olewniczak $this->schema->getTable() 39e53295c5SSzymon Olewniczak ); 405e8c6cf6SAnna Dabrowska parent::saveLine($values); 411fc2361fSSzymon Olewniczak } 421fc2361fSSzymon Olewniczak 431fc2361fSSzymon Olewniczak /** 4417dbef8aSMichael Große * Create a page from a namespace template and replace column-label-placeholders 4517dbef8aSMichael Große * 4617dbef8aSMichael Große * This is intended to use the same placeholders as bureaucracy in their most basic version 4717dbef8aSMichael Große * (i.e. without default values, formatting, etc. ) 4817dbef8aSMichael Große * 4917dbef8aSMichael Große * @param string $pid 5017dbef8aSMichael Große * @param array $line 5117dbef8aSMichael Große */ 5217dbef8aSMichael Große protected function createPage($pid, $line) 5317dbef8aSMichael Große { 5417dbef8aSMichael Große $text = pageTemplate($pid); 5517dbef8aSMichael Große if (trim($text) === '') { 5617dbef8aSMichael Große $pageParts = explode(':', $pid); 5717dbef8aSMichael Große $pagename = end($pageParts); 5817dbef8aSMichael Große $text = "====== $pagename ======\n"; 5917dbef8aSMichael Große } 60d6d97f60SAnna Dabrowska $keys = array_reduce( 61d6d97f60SAnna Dabrowska $this->columns, 62c09fb9e3SMichael Große function ($keys, Column $col) { 63c09fb9e3SMichael Große if (!in_array($col->getLabel(), $keys, true)) { 64c09fb9e3SMichael Große return $keys; 65c09fb9e3SMichael Große } 66c09fb9e3SMichael Große $index = array_search($col->getLabel(), $keys, true); 67c09fb9e3SMichael Große $keys[$index] = $col->getFullQualifiedLabel(); 68c09fb9e3SMichael Große return $keys; 69c09fb9e3SMichael Große }, 70c09fb9e3SMichael Große $this->header 71c09fb9e3SMichael Große ); 72c09fb9e3SMichael Große 73*5e29103aSannda $keysAt = array_map(static fn($key) => "@@$key@@", $keys); 74*5e29103aSannda $keysHash = array_map(static fn($key) => "##$key##", $keys); 7517dbef8aSMichael Große $flatValues = array_map( 7617dbef8aSMichael Große function ($value) { 7717dbef8aSMichael Große if (is_array($value)) { 7817dbef8aSMichael Große return implode(', ', $value); 7917dbef8aSMichael Große } 8017dbef8aSMichael Große return $value; 81d6d97f60SAnna Dabrowska }, 82d6d97f60SAnna Dabrowska $line 83d6d97f60SAnna Dabrowska ); 8400043bffSMichael Große $text = $this->evaluateIfNotEmptyTags($text, $keys, $flatValues); 8517dbef8aSMichael Große $text = str_replace($keysAt, $flatValues, $text); 8617dbef8aSMichael Große /** @noinspection CascadeStringReplacementInspection */ 8717dbef8aSMichael Große $text = str_replace($keysHash, $flatValues, $text); 8817dbef8aSMichael Große saveWikiText($pid, $text, 'Created by struct csv import'); 8917dbef8aSMichael Große } 9017dbef8aSMichael Große 9117dbef8aSMichael Große /** 9200043bffSMichael Große * Replace conditional <ifnotempty fieldname></ifnotempty> tags 9300043bffSMichael Große * 9400043bffSMichael Große * @param string $text The template 9500043bffSMichael Große * @param string[] $keys The array of qualified headers 9600043bffSMichael Große * @param string[] $values The flat array of corresponding values 9700043bffSMichael Große * 9800043bffSMichael Große * @return string The template with the tags replaced 9900043bffSMichael Große */ 10000043bffSMichael Große protected function evaluateIfNotEmptyTags($text, $keys, $values) 10100043bffSMichael Große { 10200043bffSMichael Große return preg_replace_callback( 10300043bffSMichael Große '/<ifnotempty (.+?)>([^<]*?)<\/ifnotempty>/', 104d6d97f60SAnna Dabrowska function ($matches) use ($keys, $values) { 1057234bfb1Ssplitbrain [, $blockKey, $textIfNotEmpty] = $matches; 10600043bffSMichael Große $index = array_search($blockKey, $keys, true); 10700043bffSMichael Große if ($index === false) { 10800043bffSMichael Große msg('Import error: Key "' . hsc($blockKey) . '" not found!', -1); 10900043bffSMichael Große return ''; 11000043bffSMichael Große } 11100043bffSMichael Große if (trim($values[$index]) === '') { 11200043bffSMichael Große return ''; 11300043bffSMichael Große } 11400043bffSMichael Große return $textIfNotEmpty; 11500043bffSMichael Große }, 11600043bffSMichael Große $text 11700043bffSMichael Große ); 11800043bffSMichael Große } 11900043bffSMichael Große 12000043bffSMichael Große /** 1211fc2361fSSzymon Olewniczak * Check if page id realy exists 1221fc2361fSSzymon Olewniczak * 1231fc2361fSSzymon Olewniczak * @param Column $col 1241fc2361fSSzymon Olewniczak * @param mixed $rawvalue 1251fc2361fSSzymon Olewniczak * @return bool 1261fc2361fSSzymon Olewniczak */ 127d6d97f60SAnna Dabrowska protected function validateValue(Column $col, &$rawvalue) 128d6d97f60SAnna Dabrowska { 12928d21c10SAnna Dabrowska //check if page id exists and schema is bound to the page 1301fc2361fSSzymon Olewniczak if ($col->getLabel() == 'pid') { 131e53295c5SSzymon Olewniczak $pid = cleanID($rawvalue); 132e53295c5SSzymon Olewniczak if (isset($this->importedPids[$pid])) { 133e53295c5SSzymon Olewniczak $this->errors[] = 'Page "' . $pid . '" already imported. Skipping the row.'; 134e53295c5SSzymon Olewniczak return false; 135e53295c5SSzymon Olewniczak } 136e53295c5SSzymon Olewniczak if (page_exists($pid)) { 137e53295c5SSzymon Olewniczak $this->importedPids[$pid] = true; 1381fc2361fSSzymon Olewniczak return true; 1391fc2361fSSzymon Olewniczak } 14017dbef8aSMichael Große global $INPUT; 14117dbef8aSMichael Große if ($INPUT->bool('createPage')) { 14217dbef8aSMichael Große $this->createPage[$pid] = true; 14317dbef8aSMichael Große return true; 14417dbef8aSMichael Große } 145e53295c5SSzymon Olewniczak $this->errors[] = 'Page "' . $pid . '" does not exists. Skipping the row.'; 1461fc2361fSSzymon Olewniczak return false; 1471fc2361fSSzymon Olewniczak } 1481fc2361fSSzymon Olewniczak 1491fc2361fSSzymon Olewniczak return parent::validateValue($col, $rawvalue); 1501fc2361fSSzymon Olewniczak } 1511fc2361fSSzymon Olewniczak} 152