xref: /plugin/struct/meta/CSVPageImporter.php (revision ee52a3aa7c715f708738cb793de0f26043d1e5d2)
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
10*ee52a3aaSMichael 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
72e53295c5SSzymon Olewniczak        $pid = $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        }
11017dbef8aSMichael Große        $keys = array_map(function (Column $col) {return $col->getFullQualifiedLabel();} , $this->columns);
11117dbef8aSMichael Große        $keysAt = array_map(function ($key) { return "@@$key@@";}, $keys);
11217dbef8aSMichael Große        $keysHash = array_map(function ($key) { return "##$key##";}, $keys);
11317dbef8aSMichael Große        $flatValues = array_map(
11417dbef8aSMichael Große            function($value) {
11517dbef8aSMichael Große                if (is_array($value)) {
11617dbef8aSMichael Große                    return implode(', ', $value);
11717dbef8aSMichael Große                }
11817dbef8aSMichael Große                return $value;
11917dbef8aSMichael Große            }, $line);
12017dbef8aSMichael Große        $text = str_replace($keysAt, $flatValues, $text);
12117dbef8aSMichael Große        /** @noinspection CascadeStringReplacementInspection */
12217dbef8aSMichael Große        $text = str_replace($keysHash, $flatValues, $text);
12317dbef8aSMichael Große        saveWikiText($pid, $text, 'Created by struct csv import');
12417dbef8aSMichael Große    }
12517dbef8aSMichael Große
12617dbef8aSMichael Große    /**
1271fc2361fSSzymon Olewniczak     * In the paga schemas primary key is a touple of (pid, rev)
1281fc2361fSSzymon Olewniczak     *
1291fc2361fSSzymon Olewniczak     * @param string[] $values
1301fc2361fSSzymon Olewniczak     * @param string   $single
1311fc2361fSSzymon Olewniczak     * @return array(pid, rev)
1321fc2361fSSzymon Olewniczak     */
1331fc2361fSSzymon Olewniczak    protected function insertIntoSingle($values, $single) {
1341fc2361fSSzymon Olewniczak        $pid = $values[0];
1351fc2361fSSzymon Olewniczak        $rev = $values[count($values) - 1];
136e53295c5SSzymon Olewniczak
137e53295c5SSzymon Olewniczak        //update latest
138e53295c5SSzymon Olewniczak        $table = $this->schema->getTable();
139e53295c5SSzymon Olewniczak        $this->sqlite->query("UPDATE data_$table SET latest = 0 WHERE latest = 1 AND pid = ?", array($pid));
140e53295c5SSzymon Olewniczak
141e53295c5SSzymon Olewniczak        //insert into table
142e53295c5SSzymon Olewniczak        parent::insertIntoSingle($values, $single);
143e53295c5SSzymon Olewniczak
1441fc2361fSSzymon Olewniczak        //primary key is touple of (pid, rev)
1451fc2361fSSzymon Olewniczak        return array($pid, $rev);
1461fc2361fSSzymon Olewniczak    }
1471fc2361fSSzymon Olewniczak
1481fc2361fSSzymon Olewniczak    /**
1491fc2361fSSzymon Olewniczak     * Add pid and rev to insert query parameters
1501fc2361fSSzymon Olewniczak     *
1511fc2361fSSzymon Olewniczak     * @param string $multi
1521fc2361fSSzymon Olewniczak     * @param string $pk
1531fc2361fSSzymon Olewniczak     * @param string $column
1541fc2361fSSzymon Olewniczak     * @param string $row
1551fc2361fSSzymon Olewniczak     * @param string $value
1561fc2361fSSzymon Olewniczak     */
1571fc2361fSSzymon Olewniczak    protected function insertIntoMulti($multi, $pk, $column, $row, $value) {
1581fc2361fSSzymon Olewniczak        list($pid, $rev) = $pk;
159e53295c5SSzymon Olewniczak
160e53295c5SSzymon Olewniczak        //update latest
161e53295c5SSzymon Olewniczak        $table = $this->schema->getTable();
162e53295c5SSzymon Olewniczak        $this->sqlite->query("UPDATE multi_$table SET latest = 0 WHERE latest = 1 AND pid = ?", array($pid));
163e53295c5SSzymon Olewniczak
1641fc2361fSSzymon Olewniczak        $this->sqlite->query($multi, array($pid, $rev, $column->getColref(), $row + 1, $value));
1651fc2361fSSzymon Olewniczak    }
1661fc2361fSSzymon Olewniczak
1671fc2361fSSzymon Olewniczak    /**
1681fc2361fSSzymon Olewniczak     * In page schemas we use REPLACE instead of INSERT to prevent ambiguity
1691fc2361fSSzymon Olewniczak     *
1701fc2361fSSzymon Olewniczak     * @return string
1711fc2361fSSzymon Olewniczak     */
1721fc2361fSSzymon Olewniczak    protected function getSQLforMultiValue() {
1731fc2361fSSzymon Olewniczak        $table = $this->schema->getTable();
1741fc2361fSSzymon Olewniczak        /** @noinspection SqlResolve */
175e53295c5SSzymon Olewniczak        return "INSERT INTO multi_$table (pid, rev, colref, row, value, latest) VALUES (?,?,?,?,?,1)";
1761fc2361fSSzymon Olewniczak    }
1771fc2361fSSzymon Olewniczak
1781fc2361fSSzymon Olewniczak    /**
1791fc2361fSSzymon Olewniczak     * Check if page id realy exists
1801fc2361fSSzymon Olewniczak     *
1811fc2361fSSzymon Olewniczak     * @param Column $col
1821fc2361fSSzymon Olewniczak     * @param mixed  $rawvalue
1831fc2361fSSzymon Olewniczak     * @return bool
1841fc2361fSSzymon Olewniczak     */
1851fc2361fSSzymon Olewniczak    protected function validateValue(Column $col, &$rawvalue) {
186e53295c5SSzymon Olewniczak        //check if page id exists and schema is bounded to the page
1871fc2361fSSzymon Olewniczak        if($col->getLabel() == 'pid') {
188e53295c5SSzymon Olewniczak            $pid = cleanID($rawvalue);
189e53295c5SSzymon Olewniczak            if (isset($this->importedPids[$pid])) {
190e53295c5SSzymon Olewniczak                $this->errors[] = 'Page "'.$pid.'" already imported. Skipping the row.';
191e53295c5SSzymon Olewniczak                return false;
192e53295c5SSzymon Olewniczak            }
193e53295c5SSzymon Olewniczak            if(page_exists($pid)) {
194e53295c5SSzymon Olewniczak                $this->importedPids[$pid] = true;
1951fc2361fSSzymon Olewniczak                return true;
1961fc2361fSSzymon Olewniczak            }
19717dbef8aSMichael Große            global $INPUT;
19817dbef8aSMichael Große            if ($INPUT->bool('createPage')) {
19917dbef8aSMichael Große                $this->createPage[$pid] = true;
20017dbef8aSMichael Große                return true;
20117dbef8aSMichael Große            }
202e53295c5SSzymon Olewniczak            $this->errors[] = 'Page "'.$pid.'" does not exists. Skipping the row.';
2031fc2361fSSzymon Olewniczak            return false;
2041fc2361fSSzymon Olewniczak        }
2051fc2361fSSzymon Olewniczak
2061fc2361fSSzymon Olewniczak        return parent::validateValue($col, $rawvalue);
2071fc2361fSSzymon Olewniczak    }
2081fc2361fSSzymon Olewniczak}
209