xref: /plugin/struct/meta/SchemaBuilder.php (revision 127d6bacbaa5831b9606d5ae91b03cfbe9108473)
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
148*127d6bacSMichael Große        $config = $this->data['config'] ?: '{}';
149*127d6bacSMichael Große
15076f0676dSAndreas Gohr        /** @noinspection SqlResolve */
151*127d6bacSMichael Große        $sql = "INSERT INTO schemas (tbl, ts, islookup, user, config) VALUES (?, ?, ?, ?, ?)";
152*127d6bacSMichael Große        $this->sqlite->query($sql, $this->table, $this->time, (int) $this->oldschema->isLookup(), $this->user, $config);
1531c502704SAndreas Gohr        $res = $this->sqlite->query('SELECT last_insert_rowid()');
1541c502704SAndreas Gohr        $this->newschemaid = $this->sqlite->res2single($res);
1551c502704SAndreas Gohr        $this->sqlite->res_close($res);
1561c502704SAndreas Gohr        if(!$this->newschemaid) return false;
1571c502704SAndreas Gohr        return true;
1581c502704SAndreas Gohr    }
1591c502704SAndreas Gohr
1601c502704SAndreas Gohr    /**
1611c502704SAndreas Gohr     * Updates all the existing column infos and adds them to the new schema
1621c502704SAndreas Gohr     */
1631c502704SAndreas Gohr    protected function updateColumns() {
1641c502704SAndreas Gohr        foreach($this->oldschema->getColumns() as $column) {
1651c502704SAndreas Gohr            $oldEntry = $column->getType()->getAsEntry();
1661c502704SAndreas Gohr            $oldTid   = $column->getTid();
1671c502704SAndreas Gohr            $newEntry = $oldEntry;
1681c502704SAndreas Gohr            $newTid   = $oldTid;
1691c502704SAndreas Gohr            $sort = $column->getSort();
1701c502704SAndreas Gohr            if(isset($this->data['cols'][$column->getColref()])){
1711c502704SAndreas Gohr                // todo I'm not too happy with this hardcoded here - we should probably have a list of fields at one place
1721c502704SAndreas Gohr                $newEntry['config'] = $this->data['cols'][$column->getColref()]['config'];
1731c502704SAndreas Gohr                $newEntry['label'] = $this->data['cols'][$column->getColref()]['label'];
174b7a5ee93SMichael Große                $newEntry['ismulti'] = $this->data['cols'][$column->getColref()]['ismulti'];
1751c502704SAndreas Gohr                $newEntry['class'] = $this->data['cols'][$column->getColref()]['class'];
1761c502704SAndreas Gohr                $sort = $this->data['cols'][$column->getColref()]['sort'];
17726147f8cSAndreas Gohr                $enabled = (bool) $this->data['cols'][$column->getColref()]['isenabled'];
1781c502704SAndreas Gohr
1791c502704SAndreas Gohr                // when the type definition has changed, we create a new one
1801c502704SAndreas Gohr                if(array_diff_assoc($oldEntry, $newEntry)) {
1811c502704SAndreas Gohr                    $ok = $this->sqlite->storeEntry('types', $newEntry);
1821c502704SAndreas Gohr                    if(!$ok) return false;
1831c502704SAndreas Gohr                    $res = $this->sqlite->query('SELECT last_insert_rowid()');
1841c502704SAndreas Gohr                    if(!$res) return false;
1851c502704SAndreas Gohr                    $newTid = $this->sqlite->res2single($res);
1861c502704SAndreas Gohr                    $this->sqlite->res_close($res);
187b3e0ad6dSMichael Grosse                    if ($oldEntry['ismulti'] == false && $newEntry['ismulti'] == '1') {
188b3e0ad6dSMichael Grosse                        $this->migrateSingleToMulti($this->oldschema->getTable(), $column->getColref());
189b3e0ad6dSMichael Grosse                    }
1901c502704SAndreas Gohr                }
1911c502704SAndreas Gohr            } else {
19226147f8cSAndreas Gohr                $enabled = false; // no longer there for some reason
1931c502704SAndreas Gohr            }
1941c502704SAndreas Gohr
1951c502704SAndreas Gohr            // add this type to the schema columns
1961c502704SAndreas Gohr            $schemaEntry = array(
1971c502704SAndreas Gohr                'sid' => $this->newschemaid,
1981c502704SAndreas Gohr                'colref' => $column->getColref(),
1991c502704SAndreas Gohr                'enabled' => $enabled,
2001c502704SAndreas Gohr                'tid' => $newTid,
2011c502704SAndreas Gohr                'sort' => $sort
2021c502704SAndreas Gohr            );
2031c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('schema_cols', $schemaEntry);
2041c502704SAndreas Gohr            if(!$ok) return false;
2051c502704SAndreas Gohr        }
2061c502704SAndreas Gohr        return true;
2071c502704SAndreas Gohr    }
2081c502704SAndreas Gohr
2094050be94SMichael Grosse    /**
2104050be94SMichael Grosse     * Write the latest value from an entry in a data_ table to the corresponding multi_table
2114050be94SMichael Grosse     *
2124050be94SMichael Grosse     * @param string $table
2134050be94SMichael Grosse     * @param int    $colref
2144050be94SMichael Grosse     */
2154050be94SMichael Grosse    protected function migrateSingleToMulti($table, $colref) {
21676f0676dSAndreas Gohr        /** @noinspection SqlResolve */
217b3e0ad6dSMichael Grosse        $sqlSelect = "SELECT pid, rev, col$colref AS value FROM data_$table WHERE latest = 1";
218b3e0ad6dSMichael Grosse        $res = $this->sqlite->query($sqlSelect);
219b3e0ad6dSMichael Grosse        $valueSet = $this->sqlite->res2arr($res);
220b3e0ad6dSMichael Grosse        $this->sqlite->res_close($res);
221b3e0ad6dSMichael Grosse        $valueString = array();
2224050be94SMichael Grosse        $arguments = array();
223b3e0ad6dSMichael Grosse        foreach ($valueSet as $values) {
224b3e0ad6dSMichael Grosse            if (blank($values['value']) || trim($values['value']) == '') {
225b3e0ad6dSMichael Grosse                continue;
226b3e0ad6dSMichael Grosse            }
2274050be94SMichael Grosse            $valueString[] = "(?, ?, ?, ?, ?)";
2284050be94SMichael Grosse            $arguments = array_merge($arguments, array($colref, $values['pid'], $values['rev'], 1, $values['value']));
229b3e0ad6dSMichael Grosse        }
230b3e0ad6dSMichael Grosse        if (empty($valueString)) {
231b3e0ad6dSMichael Grosse            return;
232b3e0ad6dSMichael Grosse        }
233b3e0ad6dSMichael Grosse        $valueString = join(',', $valueString);
23476f0676dSAndreas Gohr        /** @noinspection SqlResolve */
235b3e0ad6dSMichael Grosse        $sqlInsert = "INSERT OR REPLACE INTO multi_$table (colref, pid, rev, row, value) VALUES $valueString";
2364050be94SMichael Grosse        $this->sqlite->query($sqlInsert, $arguments);
237b3e0ad6dSMichael Grosse    }
238b3e0ad6dSMichael Grosse
2391c502704SAndreas Gohr    /**
2401c502704SAndreas Gohr     * Adds new columns to the new schema
2411c502704SAndreas Gohr     *
2421c502704SAndreas Gohr     * @return bool
2431c502704SAndreas Gohr     */
2441c502704SAndreas Gohr    protected function addColumns() {
2451c502704SAndreas Gohr        if(!isset($this->data['new'])) return true;
2461c502704SAndreas Gohr
2471c502704SAndreas Gohr        $colref = count($this->oldschema->getColumns())+1;
2481c502704SAndreas Gohr
2491c502704SAndreas Gohr        foreach($this->data['new'] as $column) {
25026147f8cSAndreas Gohr            if(!$column['isenabled']) continue; // we do not add a disabled column
25126147f8cSAndreas Gohr
2521c502704SAndreas Gohr            // todo this duplicates the hardcoding as in  the function above
2531c502704SAndreas Gohr            $newEntry = array();
2541c502704SAndreas Gohr            $newEntry['config'] = $column['config'];
2551c502704SAndreas Gohr            $newEntry['label'] = $column['label'];
256b7a5ee93SMichael Große            $newEntry['ismulti'] = $column['ismulti'];
2571c502704SAndreas Gohr            $newEntry['class'] = $column['class'];
2581c502704SAndreas Gohr            $sort = $column['sort'];
25926147f8cSAndreas Gohr
2601c502704SAndreas Gohr
2616684d78dSAndreas Gohr            // only save if the column got a name
2626684d78dSAndreas Gohr            if(!$newEntry['label']) continue;
2636684d78dSAndreas Gohr
2646684d78dSAndreas Gohr            // add new column to the data table
2656684d78dSAndreas Gohr            if(!$this->addDataTableColumn($colref)) {
2666684d78dSAndreas Gohr                return false;
2676684d78dSAndreas Gohr            }
2686684d78dSAndreas Gohr
2691c502704SAndreas Gohr            // save the type
2701c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('types', $newEntry);
2711c502704SAndreas Gohr            if(!$ok) return false;
2721c502704SAndreas Gohr            $res = $this->sqlite->query('SELECT last_insert_rowid()');
2731c502704SAndreas Gohr            if(!$res) return false;
2741c502704SAndreas Gohr            $newTid = $this->sqlite->res2single($res);
2751c502704SAndreas Gohr            $this->sqlite->res_close($res);
2761c502704SAndreas Gohr
2771c502704SAndreas Gohr
2781c502704SAndreas Gohr            // add this type to the schema columns
2791c502704SAndreas Gohr            $schemaEntry = array(
2801c502704SAndreas Gohr                'sid' => $this->newschemaid,
2811c502704SAndreas Gohr                'colref' => $colref,
28226147f8cSAndreas Gohr                'enabled' => true,
2831c502704SAndreas Gohr                'tid' => $newTid,
2841c502704SAndreas Gohr                'sort' => $sort
2851c502704SAndreas Gohr            );
2861c502704SAndreas Gohr            $ok = $this->sqlite->storeEntry('schema_cols', $schemaEntry);
2871c502704SAndreas Gohr            if(!$ok) return false;
2881c502704SAndreas Gohr            $colref++;
2891c502704SAndreas Gohr        }
2901c502704SAndreas Gohr
2911c502704SAndreas Gohr        return true;
2921c502704SAndreas Gohr    }
2931c502704SAndreas Gohr
2941c502704SAndreas Gohr    /**
2950fe33e72SAndreas Gohr     * Create a completely new data table with no columns yet also create the appropriate
2960fe33e72SAndreas Gohr     * multi value table for the schema
2971c502704SAndreas Gohr     *
2981c502704SAndreas Gohr     * @todo how do we want to handle indexes?
2991c502704SAndreas Gohr     * @return bool
3001c502704SAndreas Gohr     */
3011c502704SAndreas Gohr    protected function newDataTable() {
3020fe33e72SAndreas Gohr        $ok = true;
3031c502704SAndreas Gohr
3040fe33e72SAndreas Gohr        $tbl = 'data_' . $this->table;
3051c502704SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3061c502704SAndreas Gohr                    pid NOT NULL,
3076684d78dSAndreas Gohr                    rev INTEGER NOT NULL,
3087059e7e1SAndreas Gohr                    latest BOOLEAN NOT NULL DEFAULT 0,
3096684d78dSAndreas Gohr                    PRIMARY KEY(pid, rev)
3106684d78dSAndreas Gohr                )";
3110fe33e72SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3121c502704SAndreas Gohr
3130fe33e72SAndreas Gohr        $tbl = 'multi_' . $this->table;
3140fe33e72SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3150fe33e72SAndreas Gohr                    colref INTEGER NOT NULL,
3160fe33e72SAndreas Gohr                    pid NOT NULL,
3170fe33e72SAndreas Gohr                    rev INTEGER NOT NULL,
3188f259467SAndreas Gohr                    latest INTEGER NOT NULL DEFAULT 0,
3190fe33e72SAndreas Gohr                    row INTEGER NOT NULL,
3200fe33e72SAndreas Gohr                    value,
3210fe33e72SAndreas Gohr                    PRIMARY KEY(colref, pid, rev, row)
3220fe33e72SAndreas Gohr                );";
3230fe33e72SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3240fe33e72SAndreas Gohr
3250fe33e72SAndreas Gohr        return $ok;
3261c502704SAndreas Gohr    }
3271c502704SAndreas Gohr
3281c502704SAndreas Gohr    /**
3297c080d69SAndreas Gohr     * Creates a new lookup table with no columns
3307c080d69SAndreas Gohr     *
3317c080d69SAndreas Gohr     * This is basically the same as @see newDataTable() but sets
3327c080d69SAndreas Gohr     * different primary keys and types
3337c080d69SAndreas Gohr     *
3347c080d69SAndreas Gohr     * @return bool
3357c080d69SAndreas Gohr     */
3367c080d69SAndreas Gohr    protected function newLookupTable() {
3377c080d69SAndreas Gohr        $ok = true;
3387c080d69SAndreas Gohr
3397c080d69SAndreas Gohr        $tbl = 'data_' . $this->table;
3407c080d69SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3417c080d69SAndreas Gohr                    pid INTEGER PRIMARY KEY,
3427c080d69SAndreas Gohr                    rev INTEGER NOT NULL DEFAULT 0,
3437c080d69SAndreas Gohr                    latest BOOLEAN NOT NULL DEFAULT 1
3447c080d69SAndreas Gohr                )";
3457c080d69SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3467c080d69SAndreas Gohr
3477c080d69SAndreas Gohr        $tbl = 'multi_' . $this->table;
3487c080d69SAndreas Gohr        $sql = "CREATE TABLE $tbl (
3497c080d69SAndreas Gohr                    colref INTEGER NOT NULL,
3507c080d69SAndreas Gohr                    pid INTEGER NOT NULL,
3517c080d69SAndreas Gohr                    rev INTEGER NOT NULL DEFAULT 0,
3528f259467SAndreas Gohr                    latest INTEGER NOT NULL DEFAULT 0,
3537c080d69SAndreas Gohr                    row INTEGER NOT NULL,
3547c080d69SAndreas Gohr                    value,
3557c080d69SAndreas Gohr                    PRIMARY KEY(colref, pid, row)
3567c080d69SAndreas Gohr                );";
3577c080d69SAndreas Gohr        $ok = $ok && (bool) $this->sqlite->query($sql);
3587c080d69SAndreas Gohr
3597c080d69SAndreas Gohr        return $ok;
3607c080d69SAndreas Gohr    }
3617c080d69SAndreas Gohr
3627c080d69SAndreas Gohr    /**
3636684d78dSAndreas Gohr     * Add an additional column to the existing data table
3641c502704SAndreas Gohr     *
3656684d78dSAndreas Gohr     * @param int $index the new column index to add
3661c502704SAndreas Gohr     * @return bool
3671c502704SAndreas Gohr     */
3686684d78dSAndreas Gohr    protected function addDataTableColumn($index) {
3691c502704SAndreas Gohr        $tbl = 'data_' . $this->table;
3706684d78dSAndreas Gohr        $sql = " ALTER TABLE $tbl ADD COLUMN col$index DEFAULT ''";
3711c502704SAndreas Gohr        if(! $this->sqlite->query($sql)) {
3721c502704SAndreas Gohr            return false;
3731c502704SAndreas Gohr        }
3741c502704SAndreas Gohr        return true;
3751c502704SAndreas Gohr    }
3761c502704SAndreas Gohr
37778bff02fSMichael Grosse    /**
37878bff02fSMichael Grosse     * @param string $user
37978bff02fSMichael Grosse     * @return SchemaBuilder
38078bff02fSMichael Grosse     */
38178bff02fSMichael Grosse    public function setUser($user) {
38278bff02fSMichael Grosse        $this->user = $user;
38378bff02fSMichael Grosse        return $this;
38478bff02fSMichael Grosse    }
38578bff02fSMichael Grosse
38678bff02fSMichael Grosse
3871c502704SAndreas Gohr}
388