xref: /plugin/struct/meta/CSVExporter.php (revision ad86a8246773ce555271b9f3e75eb4f5fbf66227)
1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5/**
6 * Class CSVExporter
7 *
8 * exports raw schema data to CSV. For lookup schemas this data can be reimported again through
9 * CSVImporter
10 *
11 * Note this is different from syntax/csv.php
12 *
13 * @package dokuwiki\plugin\struct\meta
14 */
15class CSVExporter
16{
17    const DATATYPE_PAGE = 'page';
18    const DATATYPE_LOOKUP = 'lookup';
19    const DATATYPE_SERIAL = 'serial';
20
21    protected $type = '';
22
23    /**
24     * CSVExporter constructor.
25     *
26     * @param string $table
27     * @param string $type
28     */
29    public function __construct($table, $type)
30    {
31        // TODO make it nicer
32        $this->type = $type;
33
34        $search = new Search();
35        $search->addSchema($table);
36        $search->addColumn('*');
37        $result = $search->execute();
38
39        if ($this->type !== self::DATATYPE_LOOKUP) {
40            $pids = $search->getPids();
41        }
42
43        echo $this->header($search->getColumns());
44        foreach ($result as $i => $row) {
45            if ($this->type !== self::DATATYPE_LOOKUP) {
46                $pid = $pids[$i];
47            } else {
48                $pid = '';
49            }
50            echo $this->row($row, $pid);
51        }
52    }
53
54    /**
55     * Create the header
56     *
57     * @param Column[] $columns
58     * @return string
59     */
60    protected function header($columns)
61    {
62        $row = '';
63
64        if ($this->type !== self::DATATYPE_LOOKUP) {
65            $row .= $this->escape('pid');
66            $row .= ',';
67        }
68
69        foreach ($columns as $i => $col) {
70            $row .= $this->escape($col->getLabel());
71            $row .= ',';
72        }
73        return rtrim($row, ',') . "\r\n";
74    }
75
76    /**
77     * Create one row of data
78     *
79     * @param Value[] $values
80     * @param string $pid pid of this row
81     * @return string
82     */
83    protected function row($values, $pid)
84    {
85        $row = '';
86        if ($this->type !== self::DATATYPE_LOOKUP) {
87            $row .= $this->escape($pid);
88            $row .= ',';
89        }
90
91        foreach ($values as $value) {
92            /** @var Value $value */
93            $val = $value->getRawValue();
94            if (is_array($val)) $val = join(',', $val);
95
96            // FIXME check escaping of composite ids (JSON with """")
97            $row .= $this->escape($val);
98            $row .= ',';
99        }
100
101        return rtrim($row, ',') . "\r\n";
102    }
103
104    /**
105     * Escapes and wraps the given string
106     *
107     * Uses doubled quotes for escaping which seems to be the standard escaping method for CSV
108     *
109     * @param string $str
110     * @return string
111     */
112    protected function escape($str)
113    {
114        return '"' . str_replace('"', '""', $str) . '"';
115    }
116}
117