Source for file Parser.php
Documentation is available at Parser.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | 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 |
// | 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 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: Christian Dickmann <dickmann@php.net> |
// +----------------------------------------------------------------------+
// $Id: Parser.php,v 1.5 2004/04/09 10:39:08 lsmith Exp $
require_once 'XML/Parser.php';
* Parses an XML schema file
* @author Christian Dickmann <dickmann@php.net>
class MDB2_Tools_Parser extends XML_Parser
var $database_definition = array ();
var $variables = array ();
var $invalid_names = array (
var $fail_on_invalid_names = true;
function MDB2_Tools_Parser ($variables, $fail_on_invalid_names = true )
$this->variables = $variables;
$this->fail_on_invalid_names = $fail_on_invalid_names;
function startHandler ($xp, $element, $attribs)
$this->elements[$this->count++ ] = strtolower($element);
$this->element = implode('-', $this->elements);
switch ($this->element) {
case 'database-table-initialization-insert':
$this->init = array ('type' => 'insert');
case 'database-table-initialization-insert-field':
case 'database-table-declaration-field':
case 'database-table-declaration-field-default':
$this->field['default'] = '';
case 'database-table-declaration-index':
case 'database-sequence':
case 'database-table-declaration-index-field':
function endHandler ($xp, $element)
switch ($this->element) {
case 'database-table-initialization-insert-field':
$this->raiseError ('field-name has to be specified', $xp);
if (isset ($this->init['fields'][$this->init_name])) {
$this->raiseError ('field "'. $this->init_name. '" already filled', $xp);
if (!isset ($this->table['fields'][$this->init_name])) {
$this->raiseError ('unkown field "'. $this->init_name. '"', $xp);
if ($this->init_value !== ''
&& !$this->validateFieldValue ($this->init_name, $this->init_value, $xp))
$this->raiseError ('field "'. $this->init_name. '" has wrong value', $xp);
$this->init['fields'][$this->init_name] = $this->init_value;
case 'database-table-initialization-insert':
$this->table['initialization'][] = $this->init;
if (!isset ($this->table['was'])) {
$this->table['was'] = $this->table_name;
if (!$this->table_name) {
$this->raiseError ('tables need names', $xp);
if (isset ($this->database_definition['tables'][$this->table_name])) {
$this->raiseError ('table "'. $this->table_name. '" already exists', $xp);
if (!isset ($this->table['fields'])) {
$this->raiseError ('tables need one or more fields', $xp);
if (isset ($this->table['indexes'])) {
foreach ($this->table['indexes'] as $index_name => $index) {
foreach ($index['fields'] as $field_name => $field) {
if (!isset ($this->table['fields'][$field_name])) {
$this->raiseError ('index field "'. $field_name. '" does not exist', $xp);
if (!(isset ($this->table['fields'][$field_name]['notnull'])
&& $this->table['fields'][$field_name]['notnull'] == true ))
$this->raiseError ('index field "'. $field_name.
'" has to be "notnull"', $xp);
$this->database_definition['tables'][$this->table_name] = $this->table;
case 'database-table-declaration-field':
if (!$this->field_name || !isset ($this->field['type'])) {
$this->raiseError ('field "'. $this->field_name. '" was not properly specified', $xp);
if (isset ($this->table['fields'][$this->field_name])) {
$this->raiseError ('field "'. $this->field_name. '" already exists', $xp);
if ($this->fail_on_invalid_names && isset ($this->invalid_names[$this->field_name])) {
$this->raiseError ('fieldname "'. $this->field_name. '" not allowed', $xp);
switch ($this->field['type']) {
if (isset ($this->field['unsigned'])
&& $this->field['unsigned'] !== '1' && $this->field['unsigned'] !== '0')
$this->raiseError ('unsigned has to be 1 or 0', $xp);
if (isset ($this->field['length']) && ((int) $this->field['length']) <= 0 ) {
$this->raiseError ('length has to be an integer greater 0', $xp);
$this->raiseError ('no valid field type ("'. $this->field['type']. '") specified', $xp);
if (!isset ($this->field['was'])) {
$this->field['was'] = $this->field_name;
if (isset ($this->field['notnull']) && !$this->is_boolean ($this->field['notnull'])) {
$this->raiseError ('field "notnull" has to be 1 or 0', $xp);
if (isset ($this->field['notnull']) && !isset ($this->field['default'])) {
$this->raiseError ('if field is "notnull", it needs a default value', $xp);
if (isset ($this->field['unsigned']) && !$this->is_boolean ($this->field['unsigned'])) {
$this->raiseError ('field "notnull" has to be 1 or 0', $xp);
$this->table['fields'][$this->field_name] = $this->field;
if (isset ($this->field['default'])) {
if ($this->field['type'] == 'clob' || $this->field['type'] == 'blob') {
$this->raiseError ('"'. $this->field['type'].
'"-fields are not allowed to have a default value', $xp);
if ($this->field['default'] !== ''
&& !$this->validateFieldValue ($this->field_name, $this->field['default'], $xp))
$this->raiseError ('default value of "'. $this->field_name. '" is of wrong type', $xp);
case 'database-table-declaration-index':
if (!$this->index_name) {
$this->raiseError ('an index needs a name', $xp);
if (isset ($this->table['indexes'][$this->index_name])) {
$this->raiseError ('index "'. $this->index_name. '" already exists', $xp);
if (isset ($this->index['unique']) && !$this->is_boolean ($this->index['unique'])) {
$this->raiseError ('field "unique" has to be 1 or 0', $xp);
if (!isset ($this->index['was'])) {
$this->index['was'] = $this->index_name;
$this->table['indexes'][$this->index_name] = $this->index;
case 'database-table-declaration-index-field':
if (!$this->field_name) {
$this->raiseError ('the index-field-name is required', $xp);
if (isset ($this->field['sorting'])
&& $this->field['sorting'] !== 'ascending' && $this->field['sorting'] !== 'descending') {
$this->raiseError ('sorting type unknown', $xp);
$this->index['fields'][$this->field_name] = $this->field;
/* Sequence declaration */
case 'database-sequence':
$this->raiseError ('a sequence has to have a name', $xp);
if (isset ($this->database_definition['sequences'][$this->seq_name])) {
$this->raiseError ('sequence "'. $this->seq_name. '" already exists', $xp);
if (!isset ($this->seq['was'])) {
$this->seq['was'] = $this->seq_name;
if (isset ($this->seq['on'])) {
if ((!isset ($this->seq['on']['table']) || !$this->seq['on']['table'])
|| (!isset ($this->seq['on']['field']) || !$this->seq['on']['field']))
$this->raiseError ('sequence "'. $this->seq_name.
'" was not properly defined', $xp);
$this->database_definition['sequences'][$this->seq_name] = $this->seq;
if (isset ($this->database_definition['create'])
&& !$this->is_boolean ($this->database_definition['create']))
$this->raiseError ('field "create" has to be 1 or 0', $xp);
if (isset ($this->database_definition['overwrite'])
&& !$this->is_boolean ($this->database_definition['overwrite']))
$this->raiseError ('field "overwrite" has to be 1 or 0', $xp);
if (!isset ($this->database_definition['name'])
|| !$this->database_definition['name']
$this->raiseError ('database needs a name', $xp);
if (isset ($this->database_definition['sequences'])) {
foreach ($this->database_definition['sequences'] as $seq_name => $seq) {
&& !isset ($this->database_definition['tables'][$seq['on']['table']]['fields'][$seq['on']['field']]))
$this->raiseError ('sequence "'. $seq_name.
'" was assigned on unexisting field/table', $xp);
$this->database_definition = $this->error;
unset ($this->elements[-- $this->count]);
$this->element = implode('-', $this->elements);
function validateFieldValue ($field_name, &$field_value, &$xp)
if (!isset ($this->table['fields'][$field_name])) {
$field_def = $this->table['fields'][$field_name];
switch ($field_def['type']) {
if (isset ($field_def['length']) && strlen($field_value) > $field_def['length']) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if (!preg_match('/^([0-9a-f]{2})*$/i', $field_value)) {
return $this->raiseError('"'.$field_value.'" is not of type "'.
$field_def['type'].'"', $xp);
$field_value = pack('H*', $field_value);
if (isset ($field_def['length']) && strlen($field_value) > $field_def['length']) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if ($field_value != ((int) $field_value)) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
$field_value = (int) $field_value;
if (isset ($field_def['unsigned']) && $field_def['unsigned'] && $field_value < 0 ) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if (!$this->is_boolean ($field_value)) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $field_value)) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $field_value)) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if (!preg_match("/([0-9]{2}):([0-9]{2}):([0-9]{2})/", $field_value)) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
if ($field_value != (double) $field_value) {
return $this->raiseError ('"'. $field_value. '" is not of type "'.
$field_def['type']. '"', $xp);
$field_value = (double) $field_value;
function raiseError ($msg, $xp = null )
$error = "Parser error: ";
$error = "Parser error: \"". $msg. "\"\n";
$error .= " Byte: $byte; Line: $line; Col: $column\n";
function is_boolean (&$value)
if (is_int($value) && ($value == 0 || $value == 1 )) {
if ($value === '1' || $value === '0') {
function cdataHandler ($xp, $data)
if ($this->var_mode == true ) {
if (!isset ($this->variables[$data])) {
$this->raiseError ('variable "'. $data. '" not found', $xp);
$data = $this->variables[$data];
switch ($this->element) {
case 'database-table-initialization-insert-field-name':
@$this->init_name .= $data;
case 'database-table-initialization-insert-field-value':
@$this->init_value .= $data;
@$this->database_definition['name'] .= $data;
@$this->database_definition['create'] .= $data;
case 'database-overwrite':
@$this->database_definition['overwrite'] .= $data;
case 'database-table-name':
@$this->table_name .= $data;
case 'database-table-was':
@$this->table['was'] .= $data;
case 'database-table-declaration-field-name':
@$this->field_name .= $data;
case 'database-table-declaration-field-type':
@$this->field['type'] .= $data;
case 'database-table-declaration-field-was':
@$this->field['was'] .= $data;
case 'database-table-declaration-field-notnull':
@$this->field['notnull'] .= $data;
case 'database-table-declaration-field-unsigned':
@$this->field['unsigned'] .= $data;
case 'database-table-declaration-field-default':
@$this->field['default'] .= $data;
case 'database-table-declaration-field-length':
@$this->field['length'] .= $data;
case 'database-table-declaration-index-name':
@$this->index_name .= $data;
case 'database-table-declaration-index-unique':
@$this->index['unique'] .= $data;
case 'database-table-declaration-index-was':
@$this->index['was'] .= $data;
case 'database-table-declaration-index-field-name':
@$this->field_name .= $data;
case 'database-table-declaration-index-field-sorting':
@$this->field['sorting'] .= $data;
/* Sequence declaration */
case 'database-sequence-name':
@$this->seq_name .= $data;
case 'database-sequence-was':
@$this->seq['was'] .= $data;
case 'database-sequence-start':
@$this->seq['start'] .= $data;
case 'database-sequence-on-table':
@$this->seq['on']['table'] .= $data;
case 'database-sequence-on-field':
@$this->seq['on']['field'] .= $data;
Documentation generated on Mon, 11 Mar 2019 10:15:53 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|