diff options
author | Jakob Sack <mail@jakobsack.de> | 2011-03-01 23:20:16 +0100 |
---|---|---|
committer | Jakob Sack <mail@jakobsack.de> | 2011-03-01 23:20:16 +0100 |
commit | 132695ceb1d7ab0e4bfbb141e9e9639111dd25b5 (patch) | |
tree | f53fabcefd89a1e5bbeda9a2c2d2fff6683139d4 /3dparty/MDB2/Schema/Writer.php | |
parent | 1fd39a52fa750878e7d70fba63c099f252095762 (diff) | |
download | nextcloud-server-132695ceb1d7ab0e4bfbb141e9e9639111dd25b5.tar.gz nextcloud-server-132695ceb1d7ab0e4bfbb141e9e9639111dd25b5.zip |
Start of the refactoring. Commit is quite big because I forgot to use git right from the beginning. Sorry.
Diffstat (limited to '3dparty/MDB2/Schema/Writer.php')
-rw-r--r-- | 3dparty/MDB2/Schema/Writer.php | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/3dparty/MDB2/Schema/Writer.php b/3dparty/MDB2/Schema/Writer.php new file mode 100644 index 00000000000..5ae4918dc1d --- /dev/null +++ b/3dparty/MDB2/Schema/Writer.php @@ -0,0 +1,581 @@ +<?php +/** + * PHP versions 4 and 5 + * + * Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, + * Stig. S. Bakken, Lukas Smith, Igor Feghali + * All rights reserved. + * + * MDB2_Schema enables users to maintain RDBMS independant schema files + * in XML that can be used to manipulate both data and database schemas + * This LICENSE is in the BSD license style. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, + * Lukas Smith, Igor Feghali nor the names of his contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Smith <smith@pooteeweet.org> + * Author: Igor Feghali <ifeghali@php.net> + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith <smith@pooteeweet.org> + * @author Igor Feghali <ifeghali@php.net> + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Writer.php,v 1.40 2008/11/30 03:34:00 clockwerx Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + +/** + * Writes an XML schema file + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith <smith@pooteeweet.org> + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Writer +{ + // {{{ properties + + var $valid_types = array(); + + // }}} + // {{{ constructor + + function __construct($valid_types = array()) + { + $this->valid_types = $valid_types; + } + + function MDB2_Schema_Writer($valid_types = array()) + { + $this->__construct($valid_types); + } + + // }}} + // {{{ raiseError() + + /** + * This method is used to communicate an error and invoke error + * callbacks etc. Basically a wrapper for PEAR::raiseError + * without the message string. + * + * @param int|PEAR_Error $code integer error code or and PEAR_Error instance + * @param int $mode error mode, see PEAR_Error docs + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param string $options Extra debug information. Defaults to the last + * query and native error code. + * + * @return object a PEAR error object + * @access public + * @see PEAR_Error + */ + function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) + { + $error =& MDB2_Schema::raiseError($code, $mode, $options, $userinfo); + return $error; + } + + // }}} + // {{{ _escapeSpecialChars() + + /** + * add escapecharacters to all special characters in a string + * + * @param string $string string that should be escaped + * + * @return string escaped string + * @access protected + */ + function _escapeSpecialChars($string) + { + if (!is_string($string)) { + $string = strval($string); + } + + $escaped = ''; + for ($char = 0, $count = strlen($string); $char < $count; $char++) { + switch ($string[$char]) { + case '&': + $escaped .= '&'; + break; + case '>': + $escaped .= '>'; + break; + case '<': + $escaped .= '<'; + break; + case '"': + $escaped .= '"'; + break; + case '\'': + $escaped .= '''; + break; + default: + $code = ord($string[$char]); + if ($code < 32 || $code > 127) { + $escaped .= "&#$code;"; + } else { + $escaped .= $string[$char]; + } + break; + } + } + return $escaped; + } + + // }}} + // {{{ _dumpBoolean() + + /** + * dump the structure of a sequence + * + * @param string $boolean boolean value or variable definition + * + * @return string with xml boolea definition + * @access private + */ + function _dumpBoolean($boolean) + { + if (is_string($boolean)) { + if ($boolean !== 'true' || $boolean !== 'false' + || preg_match('/<variable>.*</variable>/', $boolean) + ) { + return $boolean; + } + } + return $boolean ? 'true' : 'false'; + } + + // }}} + // {{{ dumpSequence() + + /** + * dump the structure of a sequence + * + * @param string $sequence_definition sequence definition + * @param string $sequence_name sequence name + * @param string $eol end of line characters + * @param integer $dump determines what data to dump + * MDB2_SCHEMA_DUMP_ALL : the entire db + * MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db + * MDB2_SCHEMA_DUMP_CONTENT : only the content of the db + * + * @return mixed string xml sequence definition on success, or a error object + * @access public + */ + function dumpSequence($sequence_definition, $sequence_name, $eol, $dump = MDB2_SCHEMA_DUMP_ALL) + { + $buffer = "$eol <sequence>$eol <name>$sequence_name</name>$eol"; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) { + if (!empty($sequence_definition['start'])) { + $start = $sequence_definition['start']; + $buffer .= " <start>$start</start>$eol"; + } + } + + if (!empty($sequence_definition['on'])) { + $buffer .= " <on>$eol"; + $buffer .= " <table>".$sequence_definition['on']['table']; + $buffer .= "</table>$eol <field>".$sequence_definition['on']['field']; + $buffer .= "</field>$eol </on>$eol"; + } + $buffer .= " </sequence>$eol"; + + return $buffer; + } + + // }}} + // {{{ dumpDatabase() + + /** + * Dump a previously parsed database structure in the Metabase schema + * XML based format suitable for the Metabase parser. This function + * may optionally dump the database definition with initialization + * commands that specify the data that is currently present in the tables. + * + * @param array $database_definition unknown + * @param array $arguments associative array that takes pairs of tag + * names and values that define dump options. + * array ( + * 'output_mode' => String + * 'file' : dump into a file + * default: dump using a function + * 'output' => String + * depending on the 'Output_Mode' + * name of the file + * name of the function + * 'end_of_line' => String + * end of line delimiter that should be used + * default: "\n" + * ); + * @param integer $dump determines what data to dump + * MDB2_SCHEMA_DUMP_ALL : the entire db + * MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db + * MDB2_SCHEMA_DUMP_CONTENT : only the content of the db + * + * @return mixed MDB2_OK on success, or a error object + * @access public + */ + function dumpDatabase($database_definition, $arguments, $dump = MDB2_SCHEMA_DUMP_ALL) + { + if (!empty($arguments['output'])) { + if (!empty($arguments['output_mode']) && $arguments['output_mode'] == 'file') { + $fp = fopen($arguments['output'], 'w'); + if ($fp === false) { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'it was not possible to open output file'); + } + + $output = false; + } elseif (is_callable($arguments['output'])) { + $output = $arguments['output']; + } else { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'no valid output function specified'); + } + } else { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'no output method specified'); + } + + $eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n"; + + $sequences = array(); + if (!empty($database_definition['sequences']) + && is_array($database_definition['sequences']) + ) { + foreach ($database_definition['sequences'] as $sequence_name => $sequence) { + $table = !empty($sequence['on']) ? $sequence['on']['table'] :''; + + $sequences[$table][] = $sequence_name; + } + } + + $buffer = '<?xml version="1.0" encoding="ISO-8859-1" ?>'.$eol; + $buffer .= "<database>$eol$eol <name>".$database_definition['name']."</name>"; + $buffer .= "$eol <create>".$this->_dumpBoolean($database_definition['create'])."</create>"; + $buffer .= "$eol <overwrite>".$this->_dumpBoolean($database_definition['overwrite'])."</overwrite>$eol"; + $buffer .= "$eol <charset>".$database_definition['charset']."</charset>$eol"; + + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + if (!empty($database_definition['tables']) && is_array($database_definition['tables'])) { + foreach ($database_definition['tables'] as $table_name => $table) { + $buffer = "$eol <table>$eol$eol <name>$table_name</name>$eol"; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_STRUCTURE) { + $buffer .= "$eol <declaration>$eol"; + if (!empty($table['fields']) && is_array($table['fields'])) { + foreach ($table['fields'] as $field_name => $field) { + if (empty($field['type'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified the type of the field "'. + $field_name.'" of the table "'.$table_name.'"'); + } + if (!empty($this->valid_types) && !array_key_exists($field['type'], $this->valid_types)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'type "'.$field['type'].'" is not yet supported'); + } + $buffer .= "$eol <field>$eol <name>$field_name</name>$eol <type>"; + $buffer .= $field['type']."</type>$eol"; + if (!empty($field['fixed']) && $field['type'] === 'text') { + $buffer .= " <fixed>".$this->_dumpBoolean($field['fixed'])."</fixed>$eol"; + } + if (array_key_exists('default', $field) + && $field['type'] !== 'clob' && $field['type'] !== 'blob' + ) { + $buffer .= ' <default>'.$this->_escapeSpecialChars($field['default'])."</default>$eol"; + } + if (!empty($field['notnull'])) { + $buffer .= " <notnull>".$this->_dumpBoolean($field['notnull'])."</notnull>$eol"; + } else { + $buffer .= " <notnull>false</notnull>$eol"; + } + if (!empty($field['autoincrement'])) { + $buffer .= " <autoincrement>" . $field['autoincrement'] ."</autoincrement>$eol"; + } + if (!empty($field['unsigned'])) { + $buffer .= " <unsigned>".$this->_dumpBoolean($field['unsigned'])."</unsigned>$eol"; + } + if (!empty($field['length'])) { + $buffer .= ' <length>'.$field['length']."</length>$eol"; + } + $buffer .= " </field>$eol"; + } + } + + if (!empty($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $index_name => $index) { + if (strtolower($index_name) === 'primary') { + $index_name = $table_name . '_pKey'; + } + $buffer .= "$eol <index>$eol <name>$index_name</name>$eol"; + if (!empty($index['unique'])) { + $buffer .= " <unique>".$this->_dumpBoolean($index['unique'])."</unique>$eol"; + } + + if (!empty($index['primary'])) { + $buffer .= " <primary>".$this->_dumpBoolean($index['primary'])."</primary>$eol"; + } + + foreach ($index['fields'] as $field_name => $field) { + $buffer .= " <field>$eol <name>$field_name</name>$eol"; + if (!empty($field) && is_array($field)) { + $buffer .= ' <sorting>'.$field['sorting']."</sorting>$eol"; + } + $buffer .= " </field>$eol"; + } + $buffer .= " </index>$eol"; + } + } + + if (!empty($table['constraints']) && is_array($table['constraints'])) { + foreach ($table['constraints'] as $constraint_name => $constraint) { + $buffer .= "$eol <foreign>$eol <name>$constraint_name</name>$eol"; + if (empty($constraint['fields']) || !is_array($constraint['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified a field for the foreign key "'. + $constraint_name.'" of the table "'.$table_name.'"'); + } + if (!is_array($constraint['references']) || empty($constraint['references']['table'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified the referenced table of the foreign key "'. + $constraint_name.'" of the table "'.$table_name.'"'); + } + if (!empty($constraint['match'])) { + $buffer .= " <match>".$constraint['match']."</match>$eol"; + } + if (!empty($constraint['ondelete'])) { + $buffer .= " <ondelete>".$constraint['ondelete']."</ondelete>$eol"; + } + if (!empty($constraint['onupdate'])) { + $buffer .= " <onupdate>".$constraint['onupdate']."</onupdate>$eol"; + } + if (!empty($constraint['deferrable'])) { + $buffer .= " <deferrable>".$constraint['deferrable']."</deferrable>$eol"; + } + if (!empty($constraint['initiallydeferred'])) { + $buffer .= " <initiallydeferred>".$constraint['initiallydeferred']."</initiallydeferred>$eol"; + } + foreach ($constraint['fields'] as $field_name => $field) { + $buffer .= " <field>$field_name</field>$eol"; + } + $buffer .= " <references>$eol <table>".$constraint['references']['table']."</table>$eol"; + foreach ($constraint['references']['fields'] as $field_name => $field) { + $buffer .= " <field>$field_name</field>$eol"; + } + $buffer .= " </references>$eol"; + + $buffer .= " </foreign>$eol"; + } + } + + $buffer .= "$eol </declaration>$eol"; + } + + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + $buffer = ''; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) { + if (!empty($table['initialization']) && is_array($table['initialization'])) { + $buffer = "$eol <initialization>$eol"; + foreach ($table['initialization'] as $instruction) { + switch ($instruction['type']) { + case 'insert': + $buffer .= "$eol <insert>$eol"; + foreach ($instruction['data']['field'] as $field) { + $field_name = $field['name']; + + $buffer .= "$eol <field>$eol <name>$field_name</name>$eol"; + $buffer .= $this->writeExpression($field['group'], 5, $arguments); + $buffer .= " </field>$eol"; + } + $buffer .= "$eol </insert>$eol"; + break; + case 'update': + $buffer .= "$eol <update>$eol"; + foreach ($instruction['data']['field'] as $field) { + $field_name = $field['name']; + + $buffer .= "$eol <field>$eol <name>$field_name</name>$eol"; + $buffer .= $this->writeExpression($field['group'], 5, $arguments); + $buffer .= " </field>$eol"; + } + + if (!empty($instruction['data']['where']) + && is_array($instruction['data']['where']) + ) { + $buffer .= " <where>$eol"; + $buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments); + $buffer .= " </where>$eol"; + } + + $buffer .= "$eol </update>$eol"; + break; + case 'delete': + $buffer .= "$eol <delete>$eol$eol"; + if (!empty($instruction['data']['where']) + && is_array($instruction['data']['where']) + ) { + $buffer .= " <where>$eol"; + $buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments); + $buffer .= " </where>$eol"; + } + $buffer .= "$eol </delete>$eol"; + break; + } + } + $buffer .= "$eol </initialization>$eol"; + } + } + $buffer .= "$eol </table>$eol"; + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + if (isset($sequences[$table_name])) { + foreach ($sequences[$table_name] as $sequence) { + $result = $this->dumpSequence($database_definition['sequences'][$sequence], + $sequence, $eol, $dump); + if (PEAR::isError($result)) { + return $result; + } + + if ($output) { + call_user_func($output, $result); + } else { + fwrite($fp, $result); + } + } + } + } + } + + if (isset($sequences[''])) { + foreach ($sequences[''] as $sequence) { + $result = $this->dumpSequence($database_definition['sequences'][$sequence], + $sequence, $eol, $dump); + if (PEAR::isError($result)) { + return $result; + } + + if ($output) { + call_user_func($output, $result); + } else { + fwrite($fp, $result); + } + } + } + + $buffer = "$eol</database>$eol"; + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + fclose($fp); + } + + return MDB2_OK; + } + + // }}} + // {{{ writeExpression() + + /** + * Dumps the structure of an element. Elements can be value, column, + * function or expression. + * + * @param array $element multi dimensional array that represents the parsed element + * of a DML instruction. + * @param integer $offset base indentation width + * @param array $arguments associative array that takes pairs of tag + * names and values that define dump options. + * + * @return string + * + * @access public + * @see MDB2_Schema_Writer::dumpDatabase() + */ + function writeExpression($element, $offset = 0, $arguments = null) + { + $eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n"; + $str = ''; + + $indent = str_repeat(' ', $offset); + $noffset = $offset + 1; + + switch ($element['type']) { + case 'value': + $str .= "$indent<value>".$this->_escapeSpecialChars($element['data'])."</value>$eol"; + break; + case 'column': + $str .= "$indent<column>".$this->_escapeSpecialChars($element['data'])."</column>$eol"; + break; + case 'function': + $str .= "$indent<function>$eol$indent <name>".$this->_escapeSpecialChars($element['data']['name'])."</name>$eol"; + + if (!empty($element['data']['arguments']) + && is_array($element['data']['arguments']) + ) { + foreach ($element['data']['arguments'] as $v) { + $str .= $this->writeExpression($v, $noffset, $arguments); + } + } + + $str .= "$indent</function>$eol"; + break; + case 'expression': + $str .= "$indent<expression>$eol"; + $str .= $this->writeExpression($element['data']['operants'][0], $noffset, $arguments); + $str .= "$indent <operator>".$element['data']['operator']."</operator>$eol"; + $str .= $this->writeExpression($element['data']['operants'][1], $noffset, $arguments); + $str .= "$indent</expression>$eol"; + break; + } + return $str; + } + + // }}} +} +?> |