xref: /plugin/struct/meta/SchemaBuilder.php (revision 8f2594674dc864a5f8a2455d5836ec024b2a45f2)
11c502704SAndreas Gohr<?php
21c502704SAndreas Gohr
3ba766201SAndreas Gohrnamespace dokuwiki\plugin\struct\meta;
41c502704SAndreas Gohr
57182938bSAndreas Gohr/**
67182938bSAndreas Gohr * Class SchemaBuilder
77182938bSAndreas Gohr *
87182938bSAndreas Gohr * This class builds and updates the schema definitions for our tables. This includes CREATEing and ALTERing
97182938bSAndreas Gohr * the actual data tables as well as updating the meta information in our meta data tables.
107182938bSAndreas Gohr *
117182938bSAndreas Gohr * To use, simply instantiate a new object of the Builder and run the build() method on it.
127182938bSAndreas Gohr *
137182938bSAndreas Gohr * Note: even though data tables use a data_ prefix in the database, this prefix is internal only and should
147182938bSAndreas Gohr *       never be passed as $table anywhere!
157182938bSAndreas Gohr *
16ba766201SAndreas Gohr * @package dokuwiki\plugin\struct\meta
177182938bSAndreas Gohr */
181c502704SAndreas Gohrclass SchemaBuilder {
191c502704SAndreas Gohr
201c502704SAndreas Gohr    /**
211c502704SAndreas Gohr     * @var array The posted new data for the schema
227182938bSAndreas Gohr     * @see Schema::AdminEditor()
231c502704SAndreas Gohr     */
241c502704SAndreas Gohr    protected $data = array();
251c502704SAndreas Gohr
26fa7b96aaSMichael Grosse    protected $user;
27fa7b96aaSMichael Grosse
281c502704SAndreas Gohr    /**
291c502704SAndreas Gohr     * @var string The table name associated with the schema
301c502704SAndreas Gohr     */
311c502704SAndreas Gohr    protected $table = '';
321c502704SAndreas Gohr
331c502704SAndreas Gohr    /**
341c502704SAndreas Gohr     * @var Schema the previously valid schema for this table
351c502704SAndreas Gohr     */
361c502704SAndreas Gohr    protected $oldschema;
371c502704SAndreas Gohr
381c502704SAndreas Gohr    /** @var int the ID of the newly created schema */
391c502704SAndreas Gohr    protected $newschemaid = 0;
401c502704SAndreas Gohr
41a1603abdSAndreas Gohr    /** @var \helper_plugin_struct_db */
42a1603abdSAndreas Gohr    protected $helper;
43a1603abdSAndreas Gohr
441c502704SAndreas Gohr    /** @var \helper_plugin_sqlite|null  */
451c502704SAndreas Gohr    protected $sqlite;
461c502704SAndreas Gohr
479d580426SAndreas Gohr    /** @var int the time for which this schema should be created - default to time() can be overriden for tests */
489d580426SAndreas Gohr    protected $time = 0;
499d580426SAndreas Gohr
501c502704SAndreas Gohr    /**
511c502704SAndreas Gohr     * SchemaBuilder constructor.
527182938bSAndreas Gohr     *
537182938bSAndreas Gohr     * @param string $table The table's name
547182938bSAndreas Gohr     * @param array $data The defining of the table (basically what get's posted in the schema editor form)
557182938bSAndreas Gohr     * @see Schema::AdminEditor()
561c502704SAndreas Gohr     */
571c502704SAndreas Gohr    public function __construct($table, $data) {
581c502704SAndreas Gohr        $this->table = $table;
591c502704SAndreas Gohr        $this->data = $data;
607c080d69SAndreas Gohr        $this->oldschema = new Schema($table, 0, $data['islookup']);
611c502704SAndreas Gohr
62a1603abdSAndreas Gohr        $this->helper = plugin_load('helper', 'struct_db');
63a1603abdSAndreas Gohr        $this->sqlite = $this->helper->getDB();
6412fe9b2cSMichael Grosse        $this->user = $_SERVER['REMOTE_USER'];
651c502704SAndreas Gohr    }
661c502704SAndreas Gohr
671c502704SAndreas Gohr    /**
681c502704SAndreas Gohr     * Create the new schema
691c502704SAndreas Gohr     *
709d580426SAndreas Gohr     * @param int $time when to create this schema 0 for now
711c502704SAndreas Gohr     * @return bool|int the new schema id on success
721c502704SAndreas Gohr     */
739d580426SAndreas Gohr    public function build($time=0) {
749d580426SAndreas Gohr        $this->time = $time;
75a1603abdSAndreas Gohr        $this->fixLabelUniqueness();
76a1603abdSAndreas Gohr
771c502704SAndreas Gohr        $this->sqlite->query('BEGIN TRANSACTION');
786390a534SMichael Große        $ok = true;
796684d78dSAndreas Gohr        // create the data table if new schema
806684d78dSAndreas Gohr        if(!$this->oldschema->getId()) {
817c080d69SAndreas Gohr            if($this->oldschema->isLookup()) {
827c080d69SAndreas Gohr                $ok = $this->newLookupTable();
837c080d69SAndreas Gohr            } else {
841c502704SAndreas Gohr                $ok = $this->newDataTable();
856684d78dSAndreas Gohr            }
867c080d69SAndreas Gohr        }
871c502704SAndreas Gohr
881c502704SAndreas Gohr        // create a new schema
896390a534SMichael Große        $ok = $ok && $this->newSchema();
901c502704SAndreas Gohr
911c502704SAndreas Gohr        // update column info
926390a534SMichael Große        $ok = $ok && $this->updateColumns();
936390a534SMichael Große        $ok = $ok && $this->addColumns();
941c502704SAndreas Gohr
956390a534SMichael Große        if (!$ok) {
966390a534SMichael Große            $this->sqlite->query('ROLLBACK TRANSACTION');
976390a534SMichael Große            return false;
986390a534SMichael Große        }
991c502704SAndreas Gohr        $this->sqlite->query('COMMIT TRANSACTION');
1001c502704SAndreas Gohr
1011c502704SAndreas Gohr        return $this->newschemaid;
1021c502704SAndreas Gohr    }
1031c502704SAndreas Gohr
1041c502704SAndreas Gohr    /**
105a1603abdSAndreas Gohr     * Makes sure all labels in the schema to save are unique
106a1603abdSAndreas Gohr     */
107a1603abdSAndreas Gohr    protected function fixLabelUniqueness() {
108a1603abdSAndreas Gohr        $labels = array();
109a1603abdSAndreas Gohr
110cf25d54bSAndreas Gohr        if(isset($this->data['cols'])) foreach($this->data['cols'] as $idx => $column) {
111a1603abdSAndreas Gohr            $this->data['cols'][$idx]['label'] = $this->fixLabel($column['label'], $labels);
112a1603abdSAndreas Gohr        }
113a1603abdSAndreas Gohr
114cf25d54bSAndreas Gohr        if(isset($this->data['new'])) foreach($this->data['new'] as $idx => $column) {
115a1603abdSAndreas Gohr            $this->data['new'][$idx]['label'] = $this->fixLabel($column['label'], $labels);
116a1603abdSAndreas Gohr        }
117a1603abdSAndreas Gohr    }
118a1603abdSAndreas Gohr
119a1603abdSAndreas Gohr    /**
120a1603abdSAndreas Gohr     * Creates a unique label from the given one
121a1603abdSAndreas Gohr     *
122a1603abdSAndreas Gohr     * @param string $wantedlabel
123a1603abdSAndreas Gohr     * @param array $labels list of already assigned labels (will be filled)
124a1603abdSAndreas Gohr     * @return string
125a1603abdSAndreas Gohr     */
126a1603abdSAndreas Gohr    protected function fixLabel($wantedlabel, &$labels) {
127a1603abdSAndreas Gohr        $wantedlabel = trim($wantedlabel);
128a1603abdSAndreas Gohr        $fixedlabel = $wantedlabel;
129a1603abdSAndreas Gohr        $idx = 1;
1302d8ff844SAndreas Gohr        while(isset($labels[utf8_strtolower($fixedlabel)])) {
131a1603abdSAndreas Gohr            $fixedlabel = $wantedlabel.$idx++;
132a1603abdSAndreas Gohr        }
133a1603abdSAndreas Gohr        // did we actually do a rename? apply it.
134a1603abdSAndreas Gohr        if($fixedlabel != $wantedlabel) {
135a1603abdSAndreas Gohr            msg(sprintf($this->helper->getLang('duplicate_label'), $wantedlabel, $fixedlabel), -1);
136a1603abdSAndreas Gohr            $this->data['cols']['label'] = $fixedlabel;
137a1603abdSAndreas Gohr        }
1382d8ff844SAndreas Gohr        $labels[utf8_strtolower($fixedlabel)] = 1;
139a1603abdSAndreas Gohr        return $fixedlabel;
140a1603abdSAndreas Gohr    }
141a1603abdSAndreas Gohr
142a1603abdSAndreas Gohr    /**
1431c502704SAndreas Gohr     * Creates a new schema
1441c502704SAndreas Gohr     */
1451c502704SAndreas Gohr    protected function newSchema() {
1469d580426SAndreas Gohr        if(!$this->time) $this->time = time();
1479d580426SAndreas Gohr
14876f0676dSAndreas Gohr        /** @noinspection SqlResolve */
149e2c90eebSAndreas Gohr        $sql = "INSERT INTO schemas (tbl, ts, islookup, user, editors) VALUES (?, ?, ?, ?, ?)";
150e2c90eebSAndreas Gohr        $this->sqlite->query($sql, $this->table, $this->time, (int) $this->oldschema->isLookup(), $this->user, $this->data['editors']);
1511c502704SAndreas Gohr        $res = $this->sqlite->query('SELECT last_insert_rowid()');
1521c502704SAndreas Gohr        $this->newschemaid = $this->sqlite->res2single($res);
1531c502704SAndreas Gohr        $this->sqlite->res_close($res);
1541c502704SAndreas Gohr        if(!$this->newschemaid) return false;
1551c502704SAndreas Gohr        return true;
1561c502704SAndreas Gohr    }
1571c502704SAndreas Gohr
1581c502704SAndreas Gohr    /**
1591c502704SAndreas Gohr     * Updates all the existing column infos and adds them to the new schema
1601c502704SAndreas Gohr     */
1611c502704SAndreas Gohr    protected function updateColumns() {
1621c502704SAndreas Gohr        foreach($this->oldschema->getColumns() as $column) {
1631c502704SAndreas Gohr            $oldEntry = $column->getType()->getAsEntry();
1641c502704SAndreas Gohr            $oldTid   = $column->getTid();
1651c502704SAndreas Gohr            $newEntry = $oldEntry;
1661c502704SAndreas Gohr            $newTid   = $oldTid;
1671c502704SAndreas Gohr            $sort = $column->getSort();
1681c502704SAndreas Gohr            if(isset($this->data['cols'][$column->getColref()])){
1691c502704SAndreas Gohr                // todo I'm not too happy with this hardcoded here - we should probably have a list of fields at one place
1701c502704SAndreas Gohr                $newEntry['config'] = $this->data['cols'][$column->getColref()]['config'];
1711c502704SAndreas Gohr                $newEntry['label'] = $this->data['cols'][$column->getColref()]['label'];
172b7a5ee93SMichael Große                $newEntry['ismulti'] = $this->data['cols'][$column->getColref()]['ismulti'];
1731c502704SAndreas Gohr                $newEntry['class'] = $this->data['cols'][$column->getColref()]['class'];
1741c502704SAndreas Gohr                $sort = $this->data['cols'][$column->getColref()]['sort'];
17526147f8cSAndreas Gohr                $enabled = (bool) $this->data['cols'][$column->getColref()]['isenabled'];
1761c502704SAndreas Gohr
1771c502704SAndreas Gohr                // when the type definition has changed, we create a new one
1781c502704SAndreas Gohr                if(array_diff_assoc($oldEntry, $newEntry)) {
1791c502704SAndreas Gohr                    $ok = $this->sqlite->storeEntry('types', $newEntry);
1801c502704SAndreas Gohr                    if(!$ok) return false;
1811c502704SAndreas Gohr                    $res = $this->sqlite->query('SELECT last_insert_rowid()');
1821c502704SAndreas Gohr                    if(!$res) return false;
1831c502704SAndreas Gohr                    $newTid = $this->sqlite->res2single($res);
1841c502704SAndreas Gohr                    $this->sqlite->res_close($res);
185b3e0ad6dSMichael Grosse                    if ($oldEntry['ismulti'] == false && $newEntry['ismulti'] == '1') {
186b3e0ad6dSMichael Grosse                        $this->migrateSingleToMulti($this->oldschema->getTable(), $column->getColref());
187b3e0ad6dSMichael Grosse                    }
1881c502704SAndreas Gohr                }
1891c502704SAndreas Gohr            } else {
19026147f8cSAndreas Gohr                $enabled = false; // no longer there for some reason
1911c502704SAndreas Gohr            }
1921c502704SAndreas Gohr
1931c502704SAndreas Gohr            // add this type to the schema columns
1941c502704SAndreas Gohr            $schemaEntry = array(
1951c502704SAndreas Gohr                'sid' => $this->newschemaid,
1961c502704SAndreas Gohr                'colref' => $column->getColref(),
1971c502704SAndreas Gohr                'enabled' => $enabled,
1981c502704SAndreas Gohr                'tid' => $newTid,
1991c502704SAndreas Gohr                'sort' => $sort
2001c502704SAndreas Gohr            );
2011c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('schema_cols', $schemaEntry);
2021c502704SAndreas Gohr            if(!$ok) return false;
2031c502704SAndreas Gohr        }
2041c502704SAndreas Gohr        return true;
2051c502704SAndreas Gohr    }
2061c502704SAndreas Gohr
2074050be94SMichael Grosse    /**
2084050be94SMichael Grosse     * Write the latest value from an entry in a data_ table to the corresponding multi_table
2094050be94SMichael Grosse     *
2104050be94SMichael Grosse     * @param string $table
2114050be94SMichael Grosse     * @param int    $colref
2124050be94SMichael Grosse     */
2134050be94SMichael Grosse    protected function migrateSingleToMulti($table, $colref) {
21476f0676dSAndreas Gohr        /** @noinspection SqlResolve */
215b3e0ad6dSMichael Grosse        $sqlSelect = "SELECT pid, rev, col$colref AS value FROM data_$table WHERE latest = 1";
216b3e0ad6dSMichael Grosse        $res = $this->sqlite->query($sqlSelect);
217b3e0ad6dSMichael Grosse        $valueSet = $this->sqlite->res2arr($res);
218b3e0ad6dSMichael Grosse        $this->sqlite->res_close($res);
219b3e0ad6dSMichael Grosse        $valueString = array();
2204050be94SMichael Grosse        $arguments = array();
221b3e0ad6dSMichael Grosse        foreach ($valueSet as $values) {
222b3e0ad6dSMichael Grosse            if (blank($values['value']) || trim($values['value']) == '') {
223b3e0ad6dSMichael Grosse                continue;
224b3e0ad6dSMichael Grosse            }
2254050be94SMichael Grosse            $valueString[] = "(?, ?, ?, ?, ?)";
2264050be94SMichael Grosse            $arguments = array_merge($arguments, array($colref, $values['pid'], $values['rev'], 1, $values['value']));
227b3e0ad6dSMichael Grosse        }
228b3e0ad6dSMichael Grosse        if (empty($valueString)) {
229b3e0ad6dSMichael Grosse            return;
230b3e0ad6dSMichael Grosse        }
231b3e0ad6dSMichael Grosse        $valueString = join(',', $valueString);
23276f0676dSAndreas Gohr        /** @noinspection SqlResolve */
233b3e0ad6dSMichael Grosse        $sqlInsert = "INSERT OR REPLACE INTO multi_$table (colref, pid, rev, row, value) VALUES $valueString";
2344050be94SMichael Grosse        $this->sqlite->query($sqlInsert, $arguments);
235b3e0ad6dSMichael Grosse    }
236b3e0ad6dSMichael Grosse
2371c502704SAndreas Gohr    /**
2381c502704SAndreas Gohr     * Adds new columns to the new schema
2391c502704SAndreas Gohr     *
2401c502704SAndreas Gohr     * @return bool
2411c502704SAndreas Gohr     */
2421c502704SAndreas Gohr    protected function addColumns() {
2431c502704SAndreas Gohr        if(!isset($this->data['new'])) return true;
2441c502704SAndreas Gohr
2451c502704SAndreas Gohr        $colref = count($this->oldschema->getColumns())+1;
2461c502704SAndreas Gohr
2471c502704SAndreas Gohr        foreach($this->data['new'] as $column) {
24826147f8cSAndreas Gohr            if(!$column['isenabled']) continue; // we do not add a disabled column
24926147f8cSAndreas Gohr
2501c502704SAndreas Gohr            // todo this duplicates the hardcoding as in  the function above
2511c502704SAndreas Gohr            $newEntry = array();
2521c502704SAndreas Gohr            $newEntry['config'] = $column['config'];
2531c502704SAndreas Gohr            $newEntry['label'] = $column['label'];
254b7a5ee93SMichael Große            $newEntry['ismulti'] = $column['ismulti'];
2551c502704SAndreas Gohr            $newEntry['class'] = $column['class'];
2561c502704SAndreas Gohr            $sort = $column['sort'];
25726147f8cSAndreas Gohr
2581c502704SAndreas Gohr
2596684d78dSAndreas Gohr            // only save if the column got a name
2606684d78dSAndreas Gohr            if(!$newEntry['label']) continue;
2616684d78dSAndreas Gohr
2626684d78dSAndreas Gohr            // add new column to the data table
2636684d78dSAndreas Gohr            if(!$this->addDataTableColumn($colref)) {
2646684d78dSAndreas Gohr                return false;
2656684d78dSAndreas Gohr            }
2666684d78dSAndreas Gohr
2671c502704SAndreas Gohr            // save the type
2681c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('types', $newEntry);
2691c502704SAndreas Gohr            if(!$ok) return false;
2701c502704SAndreas Gohr            $res = $this->sqlite->query('SELECT last_insert_rowid()');
2711c502704SAndreas Gohr            if(!$res) return false;
2721c502704SAndreas Gohr            $newTid = $this->sqlite->res2single($res);
2731c502704SAndreas Gohr            $this->sqlite->res_close($res);
2741c502704SAndreas Gohr
2751c502704SAndreas Gohr
2761c502704SAndreas Gohr            // add this type to the schema columns
2771c502704SAndreas Gohr            $schemaEntry = array(
2781c502704SAndreas Gohr                'sid' => $this->newschemaid,
2791c502704SAndreas Gohr                'colref' => $colref,
28026147f8cSAndreas Gohr                'enabled' => true,
2811c502704SAndreas Gohr                'tid' => $newTid,
2821c502704SAndreas Gohr                'sort' => $sort
2831c502704SAndreas Gohr            );
2841c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('schema_cols', $schemaEntry);
2851c502704SAndreas Gohr            if(!$ok) return false;
2861c502704SAndreas Gohr            $colref++;
2871c502704SAndreas Gohr        }
2881c502704SAndreas Gohr
2891c502704SAndreas Gohr        return true;
2901c502704SAndreas Gohr    }
2911c502704SAndreas Gohr
2921c502704SAndreas Gohr    /**
2930fe33e72SAndreas Gohr     * Create a completely new data table with no columns yet also create the appropriate
2940fe33e72SAndreas Gohr     * multi value table for the schema
2951c502704SAndreas Gohr     *
2961c502704SAndreas Gohr     * @todo how do we want to handle indexes?
2971c502704SAndreas Gohr     * @return bool
2981c502704SAndreas Gohr     */
2991c502704SAndreas Gohr    protected function newDataTable() {
3000fe33e72SAndreas Gohr        $ok = true;
3011c502704SAndreas Gohr
3020fe33e72SAndreas Gohr        $tbl = 'data_' . $this->table;
3031c502704SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3041c502704SAndreas Gohr                    pid NOT NULL,
3056684d78dSAndreas Gohr                    rev INTEGER NOT NULL,
3067059e7e1SAndreas Gohr                    latest BOOLEAN NOT NULL DEFAULT 0,
3076684d78dSAndreas Gohr                    PRIMARY KEY(pid, rev)
3086684d78dSAndreas Gohr                )";
3090fe33e72SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3101c502704SAndreas Gohr
3110fe33e72SAndreas Gohr        $tbl = 'multi_' . $this->table;
3120fe33e72SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3130fe33e72SAndreas Gohr                    colref INTEGER NOT NULL,
3140fe33e72SAndreas Gohr                    pid NOT NULL,
3150fe33e72SAndreas Gohr                    rev INTEGER NOT NULL,
316*8f259467SAndreas Gohr                    latest INTEGER NOT NULL DEFAULT 0,
3170fe33e72SAndreas Gohr                    row INTEGER NOT NULL,
3180fe33e72SAndreas Gohr                    value,
3190fe33e72SAndreas Gohr                    PRIMARY KEY(colref, pid, rev, row)
3200fe33e72SAndreas Gohr                );";
3210fe33e72SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3220fe33e72SAndreas Gohr
3230fe33e72SAndreas Gohr        return $ok;
3241c502704SAndreas Gohr    }
3251c502704SAndreas Gohr
3261c502704SAndreas Gohr    /**
3277c080d69SAndreas Gohr     * Creates a new lookup table with no columns
3287c080d69SAndreas Gohr     *
3297c080d69SAndreas Gohr     * This is basically the same as @see newDataTable() but sets
3307c080d69SAndreas Gohr     * different primary keys and types
3317c080d69SAndreas Gohr     *
3327c080d69SAndreas Gohr     * @return bool
3337c080d69SAndreas Gohr     */
3347c080d69SAndreas Gohr    protected function newLookupTable() {
3357c080d69SAndreas Gohr        $ok = true;
3367c080d69SAndreas Gohr
3377c080d69SAndreas Gohr        $tbl = 'data_' . $this->table;
3387c080d69SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3397c080d69SAndreas Gohr                    pid INTEGER PRIMARY KEY,
3407c080d69SAndreas Gohr                    rev INTEGER NOT NULL DEFAULT 0,
3417c080d69SAndreas Gohr                    latest BOOLEAN NOT NULL DEFAULT 1
3427c080d69SAndreas Gohr                )";
3437c080d69SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3447c080d69SAndreas Gohr
3457c080d69SAndreas Gohr        $tbl = 'multi_' . $this->table;
3467c080d69SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3477c080d69SAndreas Gohr                    colref INTEGER NOT NULL,
3487c080d69SAndreas Gohr                    pid INTEGER NOT NULL,
3497c080d69SAndreas Gohr                    rev INTEGER NOT NULL DEFAULT 0,
350*8f259467SAndreas Gohr                    latest INTEGER NOT NULL DEFAULT 0,
3517c080d69SAndreas Gohr                    row INTEGER NOT NULL,
3527c080d69SAndreas Gohr                    value,
3537c080d69SAndreas Gohr                    PRIMARY KEY(colref, pid, row)
3547c080d69SAndreas Gohr                );";
3557c080d69SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3567c080d69SAndreas Gohr
3577c080d69SAndreas Gohr        return $ok;
3587c080d69SAndreas Gohr    }
3597c080d69SAndreas Gohr
3607c080d69SAndreas Gohr    /**
3616684d78dSAndreas Gohr     * Add an additional column to the existing data table
3621c502704SAndreas Gohr     *
3636684d78dSAndreas Gohr     * @param int $index the new column index to add
3641c502704SAndreas Gohr     * @return bool
3651c502704SAndreas Gohr     */
3666684d78dSAndreas Gohr    protected function addDataTableColumn($index) {
3671c502704SAndreas Gohr        $tbl = 'data_' . $this->table;
3686684d78dSAndreas Gohr        $sql = " ALTER TABLE $tbl ADD COLUMN col$index DEFAULT ''";
3691c502704SAndreas Gohr        if(! $this->sqlite->query($sql)) {
3701c502704SAndreas Gohr            return false;
3711c502704SAndreas Gohr        }
3721c502704SAndreas Gohr        return true;
3731c502704SAndreas Gohr    }
3741c502704SAndreas Gohr
37578bff02fSMichael Grosse    /**
37678bff02fSMichael Grosse     * @param string $user
37778bff02fSMichael Grosse     * @return SchemaBuilder
37878bff02fSMichael Grosse     */
37978bff02fSMichael Grosse    public function setUser($user) {
38078bff02fSMichael Grosse        $this->user = $user;
38178bff02fSMichael Grosse        return $this;
38278bff02fSMichael Grosse    }
38378bff02fSMichael Grosse
38478bff02fSMichael Grosse
3851c502704SAndreas Gohr}
386