1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5class CSVPageImporter extends CSVImporter 6{ 7 protected $importedPids = []; 8 9 /** @var bool[] */ 10 protected $createPage = []; 11 12 /** 13 * Import page schema only when the pid header is present. 14 */ 15 protected function readHeaders() 16 { 17 parent::readHeaders(); 18 if (!in_array('pid', $this->header)) 19 throw new StructException('There is no "pid" header in the CSV. Schema not imported.'); 20 } 21 22 /** 23 * Add the revision. 24 * 25 * @param string[] $values 26 */ 27 protected function saveLine($values) 28 { 29 //create new page revision 30 $pid = cleanID($values[0]); 31 if (isset($this->createPage[$pid])) { 32 $this->createPage($pid, $values); 33 } 34 // make sure this schema is assigned 35 /** @noinspection PhpUndefinedVariableInspection */ 36 Assignments::getInstance()->assignPageSchema( 37 $pid, 38 $this->schema->getTable() 39 ); 40 parent::saveLine($values); 41 } 42 43 /** 44 * Create a page from a namespace template and replace column-label-placeholders 45 * 46 * This is intended to use the same placeholders as bureaucracy in their most basic version 47 * (i.e. without default values, formatting, etc. ) 48 * 49 * @param string $pid 50 * @param array $line 51 */ 52 protected function createPage($pid, $line) 53 { 54 $text = pageTemplate($pid); 55 if (trim($text) === '') { 56 $pageParts = explode(':', $pid); 57 $pagename = end($pageParts); 58 $text = "====== $pagename ======\n"; 59 } 60 $keys = array_reduce( 61 $this->columns, 62 function ($keys, Column $col) { 63 if (!in_array($col->getLabel(), $keys, true)) { 64 return $keys; 65 } 66 $index = array_search($col->getLabel(), $keys, true); 67 $keys[$index] = $col->getFullQualifiedLabel(); 68 return $keys; 69 }, 70 $this->header 71 ); 72 73 $keysAt = array_map(function ($key) { 74 return "@@$key@@"; 75 }, $keys); 76 $keysHash = array_map(function ($key) { 77 return "##$key##"; 78 }, $keys); 79 $flatValues = array_map( 80 function ($value) { 81 if (is_array($value)) { 82 return implode(', ', $value); 83 } 84 return $value; 85 }, 86 $line 87 ); 88 $text = $this->evaluateIfNotEmptyTags($text, $keys, $flatValues); 89 $text = str_replace($keysAt, $flatValues, $text); 90 /** @noinspection CascadeStringReplacementInspection */ 91 $text = str_replace($keysHash, $flatValues, $text); 92 saveWikiText($pid, $text, 'Created by struct csv import'); 93 } 94 95 /** 96 * Replace conditional <ifnotempty fieldname></ifnotempty> tags 97 * 98 * @param string $text The template 99 * @param string[] $keys The array of qualified headers 100 * @param string[] $values The flat array of corresponding values 101 * 102 * @return string The template with the tags replaced 103 */ 104 protected function evaluateIfNotEmptyTags($text, $keys, $values) 105 { 106 return preg_replace_callback( 107 '/<ifnotempty (.+?)>([^<]*?)<\/ifnotempty>/', 108 function ($matches) use ($keys, $values) { 109 [, $blockKey, $textIfNotEmpty] = $matches; 110 $index = array_search($blockKey, $keys, true); 111 if ($index === false) { 112 msg('Import error: Key "' . hsc($blockKey) . '" not found!', -1); 113 return ''; 114 } 115 if (trim($values[$index]) === '') { 116 return ''; 117 } 118 return $textIfNotEmpty; 119 }, 120 $text 121 ); 122 } 123 124 /** 125 * Check if page id realy exists 126 * 127 * @param Column $col 128 * @param mixed $rawvalue 129 * @return bool 130 */ 131 protected function validateValue(Column $col, &$rawvalue) 132 { 133 //check if page id exists and schema is bound to the page 134 if ($col->getLabel() == 'pid') { 135 $pid = cleanID($rawvalue); 136 if (isset($this->importedPids[$pid])) { 137 $this->errors[] = 'Page "' . $pid . '" already imported. Skipping the row.'; 138 return false; 139 } 140 if (page_exists($pid)) { 141 $this->importedPids[$pid] = true; 142 return true; 143 } 144 global $INPUT; 145 if ($INPUT->bool('createPage')) { 146 $this->createPage[$pid] = true; 147 return true; 148 } 149 $this->errors[] = 'Page "' . $pid . '" does not exists. Skipping the row.'; 150 return false; 151 } 152 153 return parent::validateValue($col, $rawvalue); 154 } 155} 156