MDB2_Schema
[ class tree: MDB2_Schema ] [ index: MDB2_Schema ] [ all elements ]

Source for file Parser2.php

Documentation is available at Parser2.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP versions 4 and 5                                                 |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Igor Feghali <ifeghali@php.net>                              |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: Parser2.php,v 1.8 2007/08/20 05:26:19 ifeghali Exp $
  46. //
  47.  
  48. require_once 'XML/Unserializer.php';
  49. require_once 'MDB2/Schema/Validate.php';
  50.  
  51. /**
  52.  * Parses an XML schema file
  53.  *
  54.  * @package MDB2_Schema
  55.  * @category Database
  56.  * @access protected
  57.  * @author Igor Feghali <ifeghali@php.net>
  58.  */
  59. class MDB2_Schema_Parser2 extends XML_Unserializer
  60. {
  61.     var $database_definition = array();
  62.     var $database_loaded = array();
  63.     var $variables = array();
  64.     var $error;
  65.     var $structure = false;
  66.     var $val;
  67.     var $options = array();
  68.     var $table = array();
  69.     var $table_name = '';
  70.     var $field = array();
  71.     var $field_name = '';
  72.     var $index = array();
  73.     var $index_name = '';
  74.     var $constraint = array();
  75.     var $constraint_name = '';
  76.     var $sequence = array();
  77.     var $sequence_name = '';
  78.     var $init = array();
  79.  
  80.     function __construct($variables$fail_on_invalid_names = true$structure = false$valid_types = array()$force_defaults = true)
  81.     {
  82.         // force ISO-8859-1 due to different defaults for PHP4 and PHP5
  83.         // todo: this probably needs to be investigated some more and cleaned up
  84.         $this->options['encoding''ISO-8859-1';
  85.         $this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE'= true;
  86.         $this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY'= false;
  87.         $this->options['forceEnum'= array('table''field''index''foreign''insert''update''delete''sequence');
  88.         /*
  89.          * todo: find a way to force the following items not to be parsed as arrays
  90.          * as it cause problems in functions with multiple arguments
  91.          */
  92.         //$this->options['forceNEnum'] = array('value', 'column');
  93.         $this->variables = $variables;
  94.         $this->structure = $structure;
  95.         $this->val =new MDB2_Schema_Validate($fail_on_invalid_names$valid_types$force_defaults);
  96.         parent::XML_Unserializer($this->options);
  97.     }
  98.  
  99.     function MDB2_Schema_Parser2($variables$fail_on_invalid_names = true$structure = false$valid_types = array()$force_defaults = true)
  100.     {
  101.         $this->__construct($variables$fail_on_invalid_names$structure$valid_types$force_defaults);
  102.     }
  103.  
  104.     function parse()
  105.     {
  106.         $result $this->unserialize($this->filenametrue);
  107.  
  108.         if (PEAR::isError($result)) {
  109.             return $result;
  110.         else {
  111.             $this->database_loaded = $this->getUnserializedData();
  112.             return $this->fixDatabaseKeys($this->database_loaded);
  113.         }
  114.     }
  115.  
  116.     function setInputFile($filename)
  117.     {
  118.         $this->filename $filename;
  119.         return MDB2_OK;
  120.     }
  121.  
  122.     function renameKey(&$arr$oKey$nKey)
  123.     {
  124.         $arr[$nKey&$arr[$oKey];
  125.         unset($arr[$oKey]);
  126.     }
  127.  
  128.     function fixDatabaseKeys($database)
  129.     {
  130.         $this->database_definition = array(
  131.             'name' => '',
  132.             'create' => '',
  133.             'overwrite' => '',
  134.             'description' => '',
  135.             'comments' => '',
  136.             'tables' => array(),
  137.             'sequences' => array()
  138.         );
  139.  
  140.         if (!empty($database['name'])) {
  141.             $this->database_definition['name'$database['name'];
  142.         }
  143.         if (!empty($database['create'])) {
  144.             $this->database_definition['create'$database['create'];
  145.         }
  146.         if (!empty($database['overwrite'])) {
  147.             $this->database_definition['overwrite'$database['overwrite'];
  148.         }
  149.         if (!empty($database['description'])) {
  150.             $this->database_definition['description'$database['description'];
  151.         }
  152.         if (!empty($database['comments'])) {
  153.             $this->database_definition['comments'$database['comments'];
  154.         }
  155.  
  156.         if (!empty($database['table']&& is_array($database['table'])) {
  157.             foreach ($database['table'as $table{
  158.                 $this->fixTableKeys($table);
  159.             }
  160.         }
  161.  
  162.         if (!empty($database['sequence']&& is_array($database['sequence'])) {
  163.             foreach ($database['sequence'as $sequence{
  164.                 $this->fixSequenceKeys($sequence);
  165.             }
  166.         }
  167.  
  168.         $result $this->val->validateDatabase($this->database_definition);
  169.         if (PEAR::isError($result)) {
  170.             return $this->raiseError($result->getUserinfo());
  171.         }
  172.  
  173.         return MDB2_OK;
  174.     }
  175.  
  176.     function fixTableKeys($table)
  177.     {
  178.         $this->table = array(
  179.             'was' => '',
  180.             'description' => '',
  181.             'comments' => '',
  182.             'fields' => array(),
  183.             'indexes' => array(),
  184.             'constraints' => array(),
  185.             'initialization' => array()
  186.         );
  187.  
  188.         if (!empty($table['name'])) {
  189.             $this->table_name = $table['name'];
  190.         else {
  191.             $this->table_name = '';
  192.         }
  193.         if (!empty($table['was'])) {
  194.             $this->table['was'$table['was'];
  195.         }
  196.         if (!empty($table['description'])) {
  197.             $this->table['description'$table['description'];
  198.         }
  199.         if (!empty($table['comments'])) {
  200.             $this->table['comments'$table['comments'];
  201.         }
  202.  
  203.         if (!empty($table['declaration']&& is_array($table['declaration'])) {
  204.             if (!empty($table['declaration']['field']&& is_array($table['declaration']['field'])) {
  205.                 foreach ($table['declaration']['field'as $field{
  206.                     $this->fixTableFieldKeys($field);
  207.                 }
  208.             }
  209.  
  210.             if (!empty($table['declaration']['index']&& is_array($table['declaration']['index'])) {
  211.                 foreach ($table['declaration']['index'as $index{
  212.                     $this->fixTableIndexKeys($index);
  213.                 }
  214.             }
  215.  
  216.             if (!empty($table['declaration']['foreign']&& is_array($table['declaration']['foreign'])) {
  217.                 foreach ($table['declaration']['foreign'as $constraint{
  218.                     $this->fixTableConstraintKeys($constraint);
  219.                 }
  220.             }
  221.         }
  222.  
  223.         if (!empty($table['initialization']&& is_array($table['initialization'])) {
  224.             if (!empty($table['initialization']['insert']&& is_array($table['initialization']['insert'])) {
  225.                 foreach ($table['initialization']['insert'as $init{
  226.                     $this->fixTableInitializationKeys($init'insert');
  227.                 }
  228.             }
  229.             if (!empty($table['initialization']['update']&& is_array($table['initialization']['update'])) {
  230.                 foreach ($table['initialization']['update'as $init{
  231.                     $this->fixTableInitializationKeys($init'update');
  232.                 }
  233.             }
  234.             if (!empty($table['initialization']['delete']&& is_array($table['initialization']['delete'])) {
  235.                 foreach ($table['initialization']['delete'as $init{
  236.                     $this->fixTableInitializationKeys($init'delete');
  237.                 }
  238.             }
  239.         }
  240.  
  241.         $result $this->val->validateTable($this->database_definition['tables']$this->table$this->table_name);
  242.         if (PEAR::isError($result)) {
  243.             return $this->raiseError($result->getUserinfo());
  244.         else {
  245.             $this->database_definition['tables'][$this->table_name$this->table;
  246.         }
  247.  
  248.         return MDB2_OK;
  249.     }
  250.  
  251.     function fixTableFieldKeys($field)
  252.     {
  253.         $this->field = array();
  254.         if (!empty($field['name'])) {
  255.             $this->field_name = $field['name'];
  256.         else {
  257.             $this->field_name = '';
  258.         }
  259.         if (!empty($field['was'])) {
  260.             $this->field['was'$field['was'];
  261.         }
  262.         if (!empty($field['type'])) {
  263.             $this->field['type'$field['type'];
  264.         }
  265.         if (!empty($field['fixed'])) {
  266.             $this->field['fixed'$field['fixed'];
  267.         }
  268.         if (isset($field['default'])) {
  269.             $this->field['default'$field['default'];
  270.         }
  271.         if (!empty($field['notnull'])) {
  272.             $this->field['notnull'$field['notnull'];
  273.         }
  274.         if (!empty($field['autoincrement'])) {
  275.             $this->field['autoincrement'$field['autoincrement'];
  276.         }
  277.         if (!empty($field['unsigned'])) {
  278.             $this->field['unsigned'$field['unsigned'];
  279.         }
  280.         if (!empty($field['length'])) {
  281.             $this->field['length'$field['length'];
  282.         }
  283.         if (!empty($field['description'])) {
  284.             $this->field['description'$field['description'];
  285.         }
  286.         if (!empty($field['comments'])) {
  287.             $this->field['comments'$field['comments'];
  288.         }
  289.  
  290.         $result $this->val->validateField($this->table['fields']$this->field$this->field_name);
  291.         if (PEAR::isError($result)) {
  292.             return $this->raiseError($result->getUserinfo());
  293.         else {
  294.             $this->table['fields'][$this->field_name$this->field;
  295.         }
  296.  
  297.         return MDB2_OK;
  298.     }
  299.  
  300.     function fixTableIndexKeys($index)
  301.     {
  302.         $this->index = array(
  303.             'was' => '',
  304.             'unique' =>'',
  305.             'primary' => '',
  306.             'fields' => array()
  307.         );
  308.  
  309.         if (!empty($index['name'])) {
  310.             $this->index_name = $index['name'];
  311.         else {
  312.             $this->index_name = '';
  313.         }
  314.         if (!empty($index['was'])) {
  315.             $this->index['was'$index['was'];
  316.         }
  317.         if (!empty($index['unique'])) {
  318.             $this->index['unique'$index['unique'];
  319.         }
  320.         if (!empty($index['primary'])) {
  321.             $this->index['primary'$index['primary'];
  322.         }
  323.         if (!empty($index['field'])) {
  324.             foreach($index['field'as $field{
  325.                 if (!empty($field['name'])) {
  326.                     $this->field_name = $field['name'];
  327.                 else {
  328.                     $this->field_name = '';
  329.                 }
  330.                 $this->field = array(
  331.                     'sorting' => ''
  332.                 );
  333.  
  334.                 if (!empty($field['sorting'])) {
  335.                     $this->field['sorting'$field['sorting'];
  336.                 }
  337.  
  338.                 $result $this->val->validateIndexField($this->index['fields']$this->field$this->field_name);
  339.                 if (PEAR::isError($result)) {
  340.                     return $this->raiseError($result->getUserinfo());
  341.                 }
  342.  
  343.                 $this->index['fields'][$this->field_name$this->field;
  344.             }
  345.         }
  346.  
  347.         $result $this->val->validateIndex($this->table['indexes']$this->index$this->index_name);
  348.         if (PEAR::isError($result)) {
  349.             return $this->raiseError($result->getUserinfo());
  350.         else {
  351.             $this->table['indexes'][$this->index_name$this->index;
  352.         }
  353.  
  354.         return MDB2_OK;
  355.     }
  356.  
  357.     function fixTableConstraintKeys($constraint{
  358.         $this->constraint = array(
  359.             'was' => '',
  360.             'match' => '',
  361.             'ondelete' => '',
  362.             'onupdate' => '',
  363.             'deferrable' => '',
  364.             'initiallydeferred' => '',
  365.             'foreign' => true,
  366.             'fields' => array(),
  367.             'references' => array('table' => '''fields' => array())
  368.         );
  369.  
  370.         if (!empty($constraint['name'])) {
  371.             $this->constraint_name = $constraint['name'];
  372.         else {
  373.             $this->constraint_name = '';
  374.         }
  375.         if (!empty($constraint['was'])) {
  376.             $this->constraint['was'$constraint['was'];
  377.         }
  378.         if (!empty($constraint['match'])) {
  379.             $this->constraint['match'$constraint['match'];
  380.         }
  381.         if (!empty($constraint['ondelete'])) {
  382.             $this->constraint['ondelete'$constraint['ondelete'];
  383.         }
  384.         if (!empty($constraint['onupdate'])) {
  385.             $this->constraint['onupdate'$constraint['onupdate'];
  386.         }
  387.         if (!empty($constraint['deferrable'])) {
  388.             $this->constraint['deferrable'$constraint['deferrable'];
  389.         }
  390.         if (!empty($constraint['initiallydeferred'])) {
  391.             $this->constraint['initiallydeferred'$constraint['initiallydeferred'];
  392.         }
  393.         if (!empty($constraint['field']&& is_array($constraint['field'])) {
  394.             foreach($constraint['field'as $field{
  395.                 $result $this->val->validateConstraintField($this->constraint['fields']$field);
  396.                 if (PEAR::isError($result)) {
  397.                     return $this->raiseError($result->getUserinfo());
  398.                 }
  399.  
  400.                 $this->constraint['fields'][$field'';
  401.             }
  402.         }
  403.  
  404.         if (!empty($constraint['references']&& is_array($constraint['references'])) {
  405.             /**
  406.              * As we forced 'table' to be enumerated
  407.              * we have to fix it on the foreign-references-table context
  408.              */
  409.             if (!empty($constraint['references']['table']&& is_array($constraint['references']['table'])) {
  410.                 $this->constraint['references']['table'$constraint['references']['table'][0];
  411.             }
  412.  
  413.             if (!empty($constraint['references']['field']&& is_array($constraint['references']['field'])) {
  414.                 foreach($constraint['references']['field'as $field{
  415.                     $result $this->val->validateConstraintReferencedField($this->constraint['references']['fields']$field);
  416.                     if (PEAR::isError($result)) {
  417.                         return $this->raiseError($result->getUserinfo());
  418.                     }
  419.  
  420.                     $this->constraint['references']['fields'][$field'';
  421.                 }
  422.             }
  423.         }
  424.  
  425.         $result $this->val->validateConstraint($this->table['constraints']$this->constraint$this->constraint_name);
  426.         if (PEAR::isError($result)) {
  427.             return $this->raiseError($result->getUserinfo());
  428.         else {
  429.             $this->table['constraints'][$this->constraint_name$this->constraint;
  430.         }
  431.  
  432.         return MDB2_OK;
  433.     }
  434.  
  435.     function fixTableInitializationKeys($element$type '')
  436.     {
  437.         if (!empty($element['select']&& is_array($element['select'])) {
  438.             $this->fixTableInitializationDataKeys($element['select']);
  439.             $this->init = array'select' => $this->init );
  440.         else {
  441.             $this->fixTableInitializationDataKeys($element);
  442.         }
  443.  
  444.         $this->table['initialization'][= array'type' => $type'data' => $this->init );
  445.     }
  446.  
  447.     function fixTableInitializationDataKeys($element)
  448.     {
  449.         $this->init = array();
  450.         if (!empty($element['field']&& is_array($element['field'])) {
  451.             foreach ($element['field'as $field{
  452.                 $name $field['name'];
  453.                 unset($field['name']);
  454.  
  455.                 $this->setExpression($field);
  456.                 $this->init['field'][= array'name' => $name'group' => $field );
  457.             }
  458.         }
  459.         /**
  460.          * As we forced 'table' to be enumerated
  461.          * we have to fix it on the insert-select context
  462.          */
  463.         if (!empty($element['table']&& is_array($element['table'])) {
  464.             $this->init['table'$element['table'][0];
  465.         }
  466.         if (!empty($element['where']&& is_array($element['where'])) {
  467.             $this->init['where'$element['where'];
  468.             $this->setExpression($this->init['where']);
  469.         }
  470.     }
  471.  
  472.     function setExpression(&$arr)
  473.     {
  474.         $element each($arr);
  475.         $arr = array'type' => $element['key');
  476.         $element $element['value'];
  477.  
  478.         switch ($arr['type']{
  479.             case 'null':
  480.             break;
  481.             case 'value':
  482.             case 'column':
  483.                 $arr['data'$element;
  484.             break;
  485.             case 'function':
  486.                 if (!empty($element)
  487.                     && is_array($element)
  488.                 {
  489.                     $arr['data'= array'name' => $element['name');
  490.                     unset($element['name']);
  491.  
  492.                     foreach ($element as $type => $value{
  493.                         if (!empty($value)) {
  494.                             if (is_array($value)) {
  495.                                 foreach ($value as $argument{
  496.                                     $argument = array$type => $argument );
  497.                                     $this->setExpression($argument);
  498.                                     $arr['data']['arguments'][$argument;
  499.                                 }
  500.                             else {
  501.                                 $arr['data']['arguments'][= array'type' => $type'data' => $value );
  502.                             }
  503.                         }
  504.                     }
  505.                 }
  506.             break;
  507.             case 'expression':
  508.                 $arr['data'= array'operants' => array()'operator' => $element['operator');
  509.                 unset($element['operator']);
  510.  
  511.                 foreach ($element as $k => $v{
  512.                     $argument = array$k => $v );
  513.                     $this->setExpression($argument);
  514.                     $arr['data']['operants'][$argument;
  515.                 }
  516.             break;
  517.         }
  518.     }
  519.  
  520.     function fixSequenceKeys($sequence)
  521.     {
  522.         $this->sequence = array(
  523.             'was' => '',
  524.             'start' => '',
  525.             'description' => '',
  526.             'comments' => '',
  527.             'on' => array('table' => '''field' => '')
  528.         );
  529.  
  530.         if (!empty($sequence['name'])) {
  531.             $this->sequence_name = $sequence['name'];
  532.         else {
  533.             $this->sequence_name = '';
  534.         }
  535.         if (!empty($sequence['was'])) {
  536.             $this->sequence['was'$sequence['was'];
  537.         }
  538.         if (!empty($sequence['start'])) {
  539.             $this->sequence['start'$sequence['start'];
  540.         }
  541.         if (!empty($sequence['description'])) {
  542.             $this->sequence['description'$sequence['description'];
  543.         }
  544.         if (!empty($sequence['comments'])) {
  545.             $this->sequence['comments'$sequence['comments'];
  546.         }
  547.         if (!empty($sequence['on']&& is_array($sequence['on'])) {
  548.             /**
  549.              * As we forced 'table' to be enumerated
  550.              * we have to fix it on the sequence-on-table context
  551.              */
  552.             if (!empty($sequence['on']['table']&& is_array($sequence['on']['table'])) {
  553.                 $this->sequence['on']['table'$sequence['on']['table'][0];
  554.             }
  555.  
  556.             /**
  557.              * As we forced 'field' to be enumerated
  558.              * we have to fix it on the sequence-on-field context
  559.              */
  560.             if (!empty($sequence['on']['field']&& is_array($sequence['on']['field'])) {
  561.                 $this->sequence['on']['field'$sequence['on']['field'][0];
  562.             }
  563.         }
  564.  
  565.         $result $this->val->validateSequence($this->database_definition['sequences']$this->sequence$this->sequence_name);
  566.         if (PEAR::isError($result)) {
  567.             return $this->raiseError($result->getUserinfo());
  568.         else {
  569.             $this->database_definition['sequences'][$this->sequence_name$this->sequence;
  570.         }
  571.  
  572.         return MDB2_OK;
  573.     }
  574.  
  575.     function &raiseError($msg = null$ecode = MDB2_SCHEMA_ERROR_PARSE)
  576.     {
  577.         if (is_null($this->error)) {
  578.             $error 'Parser error: '.$msg."\n";
  579.             $this->error =MDB2_Schema::raiseError($ecodenullnull$error);
  580.         }
  581.         return $this->error;
  582.     }
  583. }
  584.  
  585. ?>

Documentation generated on Mon, 11 Mar 2019 14:44:34 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.