xref: /plugin/struct/meta/CSVPageImporter.php (revision 17a3a5782666ca8742a2c64cc11565d4f9fe1076)
11fc2361fSSzymon Olewniczak<?php
21fc2361fSSzymon Olewniczak
31fc2361fSSzymon Olewniczaknamespace dokuwiki\plugin\struct\meta;
4d6d97f60SAnna Dabrowska
5d6d97f60SAnna Dabrowskaclass CSVPageImporter extends CSVImporter
6d6d97f60SAnna Dabrowska{
7e53295c5SSzymon Olewniczak    protected $importedPids = array();
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();
18*17a3a578SAndreas Gohr        if (!in_array('pid', $this->header))
19*17a3a578SAndreas 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]);
3117dbef8aSMichael Große        if ($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
73d6d97f60SAnna Dabrowska        $keysAt = array_map(function ($key) {
74d6d97f60SAnna Dabrowska            return "@@$key@@";
75d6d97f60SAnna Dabrowska        }, $keys);
76d6d97f60SAnna Dabrowska        $keysHash = array_map(function ($key) {
77d6d97f60SAnna Dabrowska            return "##$key##";
78d6d97f60SAnna Dabrowska        }, $keys);
7917dbef8aSMichael Große        $flatValues = array_map(
8017dbef8aSMichael Große            function ($value) {
8117dbef8aSMichael Große                if (is_array($value)) {
8217dbef8aSMichael Große                    return implode(', ', $value);
8317dbef8aSMichael Große                }
8417dbef8aSMichael Große                return $value;
85d6d97f60SAnna Dabrowska            },
86d6d97f60SAnna Dabrowska            $line
87d6d97f60SAnna Dabrowska        );
8800043bffSMichael Große        $text = $this->evaluateIfNotEmptyTags($text, $keys, $flatValues);
8917dbef8aSMichael Große        $text = str_replace($keysAt, $flatValues, $text);
9017dbef8aSMichael Große        /** @noinspection CascadeStringReplacementInspection */
9117dbef8aSMichael Große        $text = str_replace($keysHash, $flatValues, $text);
9217dbef8aSMichael Große        saveWikiText($pid, $text, 'Created by struct csv import');
9317dbef8aSMichael Große    }
9417dbef8aSMichael Große
9517dbef8aSMichael Große    /**
9600043bffSMichael Große     * Replace conditional <ifnotempty fieldname></ifnotempty> tags
9700043bffSMichael Große     *
9800043bffSMichael Große     * @param string $text The template
9900043bffSMichael Große     * @param string[] $keys The array of qualified headers
10000043bffSMichael Große     * @param string[] $values The flat array of corresponding values
10100043bffSMichael Große     *
10200043bffSMichael Große     * @return string The template with the tags replaced
10300043bffSMichael Große     */
10400043bffSMichael Große    protected function evaluateIfNotEmptyTags($text, $keys, $values)
10500043bffSMichael Große    {
10600043bffSMichael Große        return preg_replace_callback(
10700043bffSMichael Große            '/<ifnotempty (.+?)>([^<]*?)<\/ifnotempty>/',
108d6d97f60SAnna Dabrowska            function ($matches) use ($keys, $values) {
10900043bffSMichael Große                list (, $blockKey, $textIfNotEmpty) = $matches;
11000043bffSMichael Große                $index = array_search($blockKey, $keys, true);
11100043bffSMichael Große                if ($index === false) {
11200043bffSMichael Große                    msg('Import error: Key "' . hsc($blockKey) . '" not found!', -1);
11300043bffSMichael Große                    return '';
11400043bffSMichael Große                }
11500043bffSMichael Große                if (trim($values[$index]) === '') {
11600043bffSMichael Große                    return '';
11700043bffSMichael Große                }
11800043bffSMichael Große                return $textIfNotEmpty;
11900043bffSMichael Große            },
12000043bffSMichael Große            $text
12100043bffSMichael Große        );
12200043bffSMichael Große    }
12300043bffSMichael Große
12400043bffSMichael Große    /**
1251fc2361fSSzymon Olewniczak     * Check if page id realy exists
1261fc2361fSSzymon Olewniczak     *
1271fc2361fSSzymon Olewniczak     * @param Column $col
1281fc2361fSSzymon Olewniczak     * @param mixed $rawvalue
1291fc2361fSSzymon Olewniczak     * @return bool
1301fc2361fSSzymon Olewniczak     */
131d6d97f60SAnna Dabrowska    protected function validateValue(Column $col, &$rawvalue)
132d6d97f60SAnna Dabrowska    {
13328d21c10SAnna Dabrowska        //check if page id exists and schema is bound to the page
1341fc2361fSSzymon Olewniczak        if ($col->getLabel() == 'pid') {
135e53295c5SSzymon Olewniczak            $pid = cleanID($rawvalue);
136e53295c5SSzymon Olewniczak            if (isset($this->importedPids[$pid])) {
137e53295c5SSzymon Olewniczak                $this->errors[] = 'Page "' . $pid . '" already imported. Skipping the row.';
138e53295c5SSzymon Olewniczak                return false;
139e53295c5SSzymon Olewniczak            }
140e53295c5SSzymon Olewniczak            if (page_exists($pid)) {
141e53295c5SSzymon Olewniczak                $this->importedPids[$pid] = true;
1421fc2361fSSzymon Olewniczak                return true;
1431fc2361fSSzymon Olewniczak            }
14417dbef8aSMichael Große            global $INPUT;
14517dbef8aSMichael Große            if ($INPUT->bool('createPage')) {
14617dbef8aSMichael Große                $this->createPage[$pid] = true;
14717dbef8aSMichael Große                return true;
14817dbef8aSMichael Große            }
149e53295c5SSzymon Olewniczak            $this->errors[] = 'Page "' . $pid . '" does not exists. Skipping the row.';
1501fc2361fSSzymon Olewniczak            return false;
1511fc2361fSSzymon Olewniczak        }
1521fc2361fSSzymon Olewniczak
1531fc2361fSSzymon Olewniczak        return parent::validateValue($col, $rawvalue);
1541fc2361fSSzymon Olewniczak    }
1551fc2361fSSzymon Olewniczak}
156