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-2008 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith, Igor Feghali                           |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB2_Schema enables users to maintain RDBMS independant schema files |
  10. // | in XML that can be used to manipulate both data and database schemas |
  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, Igor Feghali nor the names of his contributors may be   |
  26. // | used to endorse or promote products derived from this software       |
  27. // | without specific prior 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.11 2008/02/06 23:13:51 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.             'charset' => '',
  135.             'description' => '',
  136.             'comments' => '',
  137.             'tables' => array(),
  138.             'sequences' => array()
  139.         );
  140.  
  141.         if (!empty($database['name'])) {
  142.             $this->database_definition['name'$database['name'];
  143.         }
  144.         if (!empty($database['create'])) {
  145.             $this->database_definition['create'$database['create'];
  146.         }
  147.         if (!empty($database['overwrite'])) {
  148.             $this->database_definition['overwrite'$database['overwrite'];
  149.         }
  150.         if (!empty($database['charset'])) {
  151.             $this->database_definition['charset'$database['charset'];
  152.         }
  153.         if (!empty($database['description'])) {
  154.             $this->database_definition['description'$database['description'];
  155.         }
  156.         if (!empty($database['comments'])) {
  157.             $this->database_definition['comments'$database['comments'];
  158.         }
  159.  
  160.         if (!empty($database['table']&& is_array($database['table'])) {
  161.             foreach ($database['table'as $table{
  162.                 $this->fixTableKeys($table);
  163.             }
  164.         }
  165.  
  166.         if (!empty($database['sequence']&& is_array($database['sequence'])) {
  167.             foreach ($database['sequence'as $sequence{
  168.                 $this->fixSequenceKeys($sequence);
  169.             }
  170.         }
  171.  
  172.         $result $this->val->validateDatabase($this->database_definition);
  173.         if (PEAR::isError($result)) {
  174.             return $this->raiseError($result->getUserinfo());
  175.         }
  176.  
  177.         return MDB2_OK;
  178.     }
  179.  
  180.     function fixTableKeys($table)
  181.     {
  182.         $this->table = array(
  183.             'was' => '',
  184.             'description' => '',
  185.             'comments' => '',
  186.             'fields' => array(),
  187.             'indexes' => array(),
  188.             'constraints' => array(),
  189.             'initialization' => array()
  190.         );
  191.  
  192.         if (!empty($table['name'])) {
  193.             $this->table_name = $table['name'];
  194.         else {
  195.             $this->table_name = '';
  196.         }
  197.         if (!empty($table['was'])) {
  198.             $this->table['was'$table['was'];
  199.         }
  200.         if (!empty($table['description'])) {
  201.             $this->table['description'$table['description'];
  202.         }
  203.         if (!empty($table['comments'])) {
  204.             $this->table['comments'$table['comments'];
  205.         }
  206.  
  207.         if (!empty($table['declaration']&& is_array($table['declaration'])) {
  208.             if (!empty($table['declaration']['field']&& is_array($table['declaration']['field'])) {
  209.                 foreach ($table['declaration']['field'as $field{
  210.                     $this->fixTableFieldKeys($field);
  211.                 }
  212.             }
  213.  
  214.             if (!empty($table['declaration']['index']&& is_array($table['declaration']['index'])) {
  215.                 foreach ($table['declaration']['index'as $index{
  216.                     $this->fixTableIndexKeys($index);
  217.                 }
  218.             }
  219.  
  220.             if (!empty($table['declaration']['foreign']&& is_array($table['declaration']['foreign'])) {
  221.                 foreach ($table['declaration']['foreign'as $constraint{
  222.                     $this->fixTableConstraintKeys($constraint);
  223.                 }
  224.             }
  225.         }
  226.  
  227.         if (!empty($table['initialization']&& is_array($table['initialization'])) {
  228.             if (!empty($table['initialization']['insert']&& is_array($table['initialization']['insert'])) {
  229.                 foreach ($table['initialization']['insert'as $init{
  230.                     $this->fixTableInitializationKeys($init'insert');
  231.                 }
  232.             }
  233.             if (!empty($table['initialization']['update']&& is_array($table['initialization']['update'])) {
  234.                 foreach ($table['initialization']['update'as $init{
  235.                     $this->fixTableInitializationKeys($init'update');
  236.                 }
  237.             }
  238.             if (!empty($table['initialization']['delete']&& is_array($table['initialization']['delete'])) {
  239.                 foreach ($table['initialization']['delete'as $init{
  240.                     $this->fixTableInitializationKeys($init'delete');
  241.                 }
  242.             }
  243.         }
  244.  
  245.         $result $this->val->validateTable($this->database_definition['tables']$this->table$this->table_name);
  246.         if (PEAR::isError($result)) {
  247.             return $this->raiseError($result->getUserinfo());
  248.         else {
  249.             $this->database_definition['tables'][$this->table_name$this->table;
  250.         }
  251.  
  252.         return MDB2_OK;
  253.     }
  254.  
  255.     function fixTableFieldKeys($field)
  256.     {
  257.         $this->field = array();
  258.         if (!empty($field['name'])) {
  259.             $this->field_name = $field['name'];
  260.         else {
  261.             $this->field_name = '';
  262.         }
  263.         if (!empty($field['was'])) {
  264.             $this->field['was'$field['was'];
  265.         }
  266.         if (!empty($field['type'])) {
  267.             $this->field['type'$field['type'];
  268.         }
  269.         if (!empty($field['fixed'])) {
  270.             $this->field['fixed'$field['fixed'];
  271.         }
  272.         if (isset($field['default'])) {
  273.             $this->field['default'$field['default'];
  274.         }
  275.         if (!empty($field['notnull'])) {
  276.             $this->field['notnull'$field['notnull'];
  277.         }
  278.         if (!empty($field['autoincrement'])) {
  279.             $this->field['autoincrement'$field['autoincrement'];
  280.         }
  281.         if (!empty($field['unsigned'])) {
  282.             $this->field['unsigned'$field['unsigned'];
  283.         }
  284.         if (!empty($field['length'])) {
  285.             $this->field['length'$field['length'];
  286.         }
  287.         if (!empty($field['description'])) {
  288.             $this->field['description'$field['description'];
  289.         }
  290.         if (!empty($field['comments'])) {
  291.             $this->field['comments'$field['comments'];
  292.         }
  293.  
  294.         $result $this->val->validateField($this->table['fields']$this->field$this->field_name);
  295.         if (PEAR::isError($result)) {
  296.             return $this->raiseError($result->getUserinfo());
  297.         else {
  298.             $this->table['fields'][$this->field_name$this->field;
  299.         }
  300.  
  301.         return MDB2_OK;
  302.     }
  303.  
  304.     function fixTableIndexKeys($index)
  305.     {
  306.         $this->index = array(
  307.             'was' => '',
  308.             'unique' =>'',
  309.             'primary' => '',
  310.             'fields' => array()
  311.         );
  312.  
  313.         if (!empty($index['name'])) {
  314.             $this->index_name = $index['name'];
  315.         else {
  316.             $this->index_name = '';
  317.         }
  318.         if (!empty($index['was'])) {
  319.             $this->index['was'$index['was'];
  320.         }
  321.         if (!empty($index['unique'])) {
  322.             $this->index['unique'$index['unique'];
  323.         }
  324.         if (!empty($index['primary'])) {
  325.             $this->index['primary'$index['primary'];
  326.         }
  327.         if (!empty($index['field'])) {
  328.             foreach($index['field'as $field{
  329.                 if (!empty($field['name'])) {
  330.                     $this->field_name = $field['name'];
  331.                 else {
  332.                     $this->field_name = '';
  333.                 }
  334.                 $this->field = array(
  335.                     'sorting' => '',
  336.                     'length' => ''
  337.                 );
  338.  
  339.                 if (!empty($field['sorting'])) {
  340.                     $this->field['sorting'$field['sorting'];
  341.                 }
  342.                 if (!empty($field['length'])) {
  343.                     $this->field['length'$field['length'];
  344.                 }
  345.  
  346.                 $result $this->val->validateIndexField($this->index['fields']$this->field$this->field_name);
  347.                 if (PEAR::isError($result)) {
  348.                     return $this->raiseError($result->getUserinfo());
  349.                 }
  350.  
  351.                 $this->index['fields'][$this->field_name$this->field;
  352.             }
  353.         }
  354.  
  355.         $result $this->val->validateIndex($this->table['indexes']$this->index$this->index_name);
  356.         if (PEAR::isError($result)) {
  357.             return $this->raiseError($result->getUserinfo());
  358.         else {
  359.             $this->table['indexes'][$this->index_name$this->index;
  360.         }
  361.  
  362.         return MDB2_OK;
  363.     }
  364.  
  365.     function fixTableConstraintKeys($constraint{
  366.         $this->constraint = array(
  367.             'was' => '',
  368.             'match' => '',
  369.             'ondelete' => '',
  370.             'onupdate' => '',
  371.             'deferrable' => '',
  372.             'initiallydeferred' => '',
  373.             'foreign' => true,
  374.             'fields' => array(),
  375.             'references' => array('table' => '''fields' => array())
  376.         );
  377.  
  378.         if (!empty($constraint['name'])) {
  379.             $this->constraint_name = $constraint['name'];
  380.         else {
  381.             $this->constraint_name = '';
  382.         }
  383.         if (!empty($constraint['was'])) {
  384.             $this->constraint['was'$constraint['was'];
  385.         }
  386.         if (!empty($constraint['match'])) {
  387.             $this->constraint['match'$constraint['match'];
  388.         }
  389.         if (!empty($constraint['ondelete'])) {
  390.             $this->constraint['ondelete'$constraint['ondelete'];
  391.         }
  392.         if (!empty($constraint['onupdate'])) {
  393.             $this->constraint['onupdate'$constraint['onupdate'];
  394.         }
  395.         if (!empty($constraint['deferrable'])) {
  396.             $this->constraint['deferrable'$constraint['deferrable'];
  397.         }
  398.         if (!empty($constraint['initiallydeferred'])) {
  399.             $this->constraint['initiallydeferred'$constraint['initiallydeferred'];
  400.         }
  401.         if (!empty($constraint['field']&& is_array($constraint['field'])) {
  402.             foreach($constraint['field'as $field{
  403.                 $result $this->val->validateConstraintField($this->constraint['fields']$field);
  404.                 if (PEAR::isError($result)) {
  405.                     return $this->raiseError($result->getUserinfo());
  406.                 }
  407.  
  408.                 $this->constraint['fields'][$field'';
  409.             }
  410.         }
  411.  
  412.         if (!empty($constraint['references']&& is_array($constraint['references'])) {
  413.             /**
  414.              * As we forced 'table' to be enumerated
  415.              * we have to fix it on the foreign-references-table context
  416.              */
  417.             if (!empty($constraint['references']['table']&& is_array($constraint['references']['table'])) {
  418.                 $this->constraint['references']['table'$constraint['references']['table'][0];
  419.             }
  420.  
  421.             if (!empty($constraint['references']['field']&& is_array($constraint['references']['field'])) {
  422.                 foreach($constraint['references']['field'as $field{
  423.                     $result $this->val->validateConstraintReferencedField($this->constraint['references']['fields']$field);
  424.                     if (PEAR::isError($result)) {
  425.                         return $this->raiseError($result->getUserinfo());
  426.                     }
  427.  
  428.                     $this->constraint['references']['fields'][$field'';
  429.                 }
  430.             }
  431.         }
  432.  
  433.         $result $this->val->validateConstraint($this->table['constraints']$this->constraint$this->constraint_name);
  434.         if (PEAR::isError($result)) {
  435.             return $this->raiseError($result->getUserinfo());
  436.         else {
  437.             $this->table['constraints'][$this->constraint_name$this->constraint;
  438.         }
  439.  
  440.         return MDB2_OK;
  441.     }
  442.  
  443.     function fixTableInitializationKeys($element$type '')
  444.     {
  445.         if (!empty($element['select']&& is_array($element['select'])) {
  446.             $this->fixTableInitializationDataKeys($element['select']);
  447.             $this->init = array'select' => $this->init );
  448.         else {
  449.             $this->fixTableInitializationDataKeys($element);
  450.         }
  451.  
  452.         $this->table['initialization'][= array'type' => $type'data' => $this->init );
  453.     }
  454.  
  455.     function fixTableInitializationDataKeys($element)
  456.     {
  457.         $this->init = array();
  458.         if (!empty($element['field']&& is_array($element['field'])) {
  459.             foreach ($element['field'as $field{
  460.                 $name $field['name'];
  461.                 unset($field['name']);
  462.  
  463.                 $this->setExpression($field);
  464.                 $this->init['field'][= array'name' => $name'group' => $field );
  465.             }
  466.         }
  467.         /**
  468.          * As we forced 'table' to be enumerated
  469.          * we have to fix it on the insert-select context
  470.          */
  471.         if (!empty($element['table']&& is_array($element['table'])) {
  472.             $this->init['table'$element['table'][0];
  473.         }
  474.         if (!empty($element['where']&& is_array($element['where'])) {
  475.             $this->init['where'$element['where'];
  476.             $this->setExpression($this->init['where']);
  477.         }
  478.     }
  479.  
  480.     function setExpression(&$arr)
  481.     {
  482.         $element each($arr);
  483.         $arr = array'type' => $element['key');
  484.         $element $element['value'];
  485.  
  486.         switch ($arr['type']{
  487.             case 'null':
  488.             break;
  489.             case 'value':
  490.             case 'column':
  491.                 $arr['data'$element;
  492.             break;
  493.             case 'function':
  494.                 if (!empty($element)
  495.                     && is_array($element)
  496.                 {
  497.                     $arr['data'= array'name' => $element['name');
  498.                     unset($element['name']);
  499.  
  500.                     foreach ($element as $type => $value{
  501.                         if (!empty($value)) {
  502.                             if (is_array($value)) {
  503.                                 foreach ($value as $argument{
  504.                                     $argument = array$type => $argument );
  505.                                     $this->setExpression($argument);
  506.                                     $arr['data']['arguments'][$argument;
  507.                                 }
  508.                             else {
  509.                                 $arr['data']['arguments'][= array'type' => $type'data' => $value );
  510.                             }
  511.                         }
  512.                     }
  513.                 }
  514.             break;
  515.             case 'expression':
  516.                 $arr['data'= array'operants' => array()'operator' => $element['operator');
  517.                 unset($element['operator']);
  518.  
  519.                 foreach ($element as $k => $v{
  520.                     $argument = array$k => $v );
  521.                     $this->setExpression($argument);
  522.                     $arr['data']['operants'][$argument;
  523.                 }
  524.             break;
  525.         }
  526.     }
  527.  
  528.     function fixSequenceKeys($sequence)
  529.     {
  530.         $this->sequence = array(
  531.             'was' => '',
  532.             'start' => '',
  533.             'description' => '',
  534.             'comments' => '',
  535.             'on' => array('table' => '''field' => '')
  536.         );
  537.  
  538.         if (!empty($sequence['name'])) {
  539.             $this->sequence_name = $sequence['name'];
  540.         else {
  541.             $this->sequence_name = '';
  542.         }
  543.         if (!empty($sequence['was'])) {
  544.             $this->sequence['was'$sequence['was'];
  545.         }
  546.         if (!empty($sequence['start'])) {
  547.             $this->sequence['start'$sequence['start'];
  548.         }
  549.         if (!empty($sequence['description'])) {
  550.             $this->sequence['description'$sequence['description'];
  551.         }
  552.         if (!empty($sequence['comments'])) {
  553.             $this->sequence['comments'$sequence['comments'];
  554.         }
  555.         if (!empty($sequence['on']&& is_array($sequence['on'])) {
  556.             /**
  557.              * As we forced 'table' to be enumerated
  558.              * we have to fix it on the sequence-on-table context
  559.              */
  560.             if (!empty($sequence['on']['table']&& is_array($sequence['on']['table'])) {
  561.                 $this->sequence['on']['table'$sequence['on']['table'][0];
  562.             }
  563.  
  564.             /**
  565.              * As we forced 'field' to be enumerated
  566.              * we have to fix it on the sequence-on-field context
  567.              */
  568.             if (!empty($sequence['on']['field']&& is_array($sequence['on']['field'])) {
  569.                 $this->sequence['on']['field'$sequence['on']['field'][0];
  570.             }
  571.         }
  572.  
  573.         $result $this->val->validateSequence($this->database_definition['sequences']$this->sequence$this->sequence_name);
  574.         if (PEAR::isError($result)) {
  575.             return $this->raiseError($result->getUserinfo());
  576.         else {
  577.             $this->database_definition['sequences'][$this->sequence_name$this->sequence;
  578.         }
  579.  
  580.         return MDB2_OK;
  581.     }
  582.  
  583.     function &raiseError($msg = null$ecode = MDB2_SCHEMA_ERROR_PARSE)
  584.     {
  585.         if (is_null($this->error)) {
  586.             $error 'Parser error: '.$msg."\n";
  587.             $this->error =MDB2_Schema::raiseError($ecodenullnull$error);
  588.         }
  589.         return $this->error;
  590.     }
  591. }
  592.  
  593. ?>

Documentation generated on Mon, 11 Mar 2019 15:16:43 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.