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

Source for file Tool.php

Documentation is available at Tool.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP version 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: Christian Weiske <cweiske@php.net>                           |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: Tool.php,v 1.5 2008/11/17 23:03:51 ifeghali Exp $
  46. //
  47.  
  48. require_once 'MDB2/Schema.php';
  49. require_once 'MDB2/Schema/Tool/ParameterException.php';
  50.  
  51. /**
  52. * Command line tool to work with database schemas
  53. *
  54. * Functionality:
  55. * - dump a database schema to stdout
  56. * - import schema into database
  57. * - create a diff between two schemas
  58. * - apply diff to database
  59. *
  60. @category Database
  61. @package  MDB2_Schema
  62. @author   Christian Weiske <cweiske@php.net>
  63. @license  http://www.opensource.org/licenses/bsd-license.php BSD License
  64. @link     http://pear.php.net/package/MDB2_Schema/
  65. */
  66. {
  67.     /**
  68.     * Run the schema tool
  69.     *
  70.     * @param array $args Array of command line arguments
  71.     */
  72.     public function __construct($args)
  73.     {
  74.         $strAction $this->getAction($args);
  75.         try {
  76.             $this->{'do' ucfirst($strAction)}($args);
  77.         catch (MDB2_Schema_Tool_ParameterException $e{
  78.             $this->{'doHelp' . ucfirst($strAction)}($e->getMessage());
  79.         }
  80.     }//public function __construct($args)
  81.  
  82.  
  83.  
  84.     /**
  85.     * Runs the tool with command line arguments
  86.     *
  87.     * @return void 
  88.     */
  89.     public static function run()
  90.     {
  91.         $args $GLOBALS['argv'];
  92.         array_shift($args);
  93.  
  94.         try {
  95.             $tool = new MDB2_Schema_Tool($args);
  96.         catch (Exception $e{
  97.             self::toStdErr($e->getMessage("\n");
  98.         }
  99.     }//public static function run()
  100.  
  101.  
  102.  
  103.     /**
  104.     * Reads the first parameter from the argument array and
  105.     * returns the action.
  106.     *
  107.     * @param array &$args Command line parameters
  108.     *
  109.     * @return string Action to execute
  110.     */
  111.     protected function getAction(&$args)
  112.     {
  113.         if (count($args== 0{
  114.             return 'help';
  115.         }
  116.         $arg array_shift($args);
  117.         switch ($arg{
  118.         case 'h':
  119.         case 'help':
  120.         case '-h':
  121.         case '--help':
  122.             return 'help';
  123.         case 'd':
  124.         case 'dump':
  125.         case '-d':
  126.         case '--dump':
  127.             return 'dump';
  128.         case 'l':
  129.         case 'load':
  130.         case '-l':
  131.         case '--load':
  132.             return 'load';
  133.         case 'i':
  134.         case 'diff':
  135.         case '-i':
  136.         case '--diff':
  137.             return 'diff';
  138.         case 'a':
  139.         case 'apply':
  140.         case '-a':
  141.         case '--apply':
  142.             return 'apply';
  143.         case 'n':
  144.         case 'init':
  145.         case '-i':
  146.         case '--init':
  147.             return 'init';
  148.         default:
  149.             throw new MDB2_Schema_Tool_ParameterException("Unknown mode \"$arg\"");
  150.         }
  151.     }//protected function getAction(&$args)
  152.  
  153.  
  154.  
  155.     /**
  156.     * Writes the message to stderr
  157.     *
  158.     * @param string $msg Message to print
  159.     *
  160.     * @return void 
  161.     */
  162.     protected static function toStdErr($msg)
  163.     {
  164.         file_put_contents('php://stderr'$msg);
  165.     }//protected static function toStdErr($msg)
  166.  
  167.  
  168.  
  169.     /**
  170.     * Displays generic help to stdout
  171.     *
  172.     * @return void 
  173.     */
  174.     protected function doHelp()
  175.     {
  176.         self::toStdErr(<<<EOH
  177. Usage: mdb2_schematool mode parameters
  178.  
  179. Works with database schemas
  180.  
  181. mode: (- and -- are optional)
  182.  h,  help     Show this help screen
  183.  d,  dump     Dump a schema to stdout
  184.  l,  load     Load a schema into database
  185.  i,  diff     Create a diff between two schemas and dump it to stdout
  186.  a,  apply    Apply a diff to a database
  187.  n,  init     Initialize a database with data
  188.  
  189. EOH
  190.         );
  191.     }//protected function doHelp()
  192.  
  193.  
  194.  
  195.     /**
  196.     * Displays the help screen for "dump" command
  197.     *
  198.     * @return void 
  199.     */
  200.     protected function doHelpDump()
  201.     {
  202.         self::toStdErr<<<EOH
  203. Usage: mdb2_schematool dump [all|data|schema] [-p] DSN
  204.  
  205. Dumps a database schema to stdout
  206.  
  207. If dump type is not specified, defaults to "schema".
  208.  
  209. DSN: Data source name in the form of
  210.  driver://user:password@host/database
  211.  
  212. User and password may be omitted.
  213. Using -p reads password from stdin which is more secure than passing it in the parameter.
  214.  
  215. EOH
  216.         );
  217.     }//protected function doHelpDump()
  218.  
  219.  
  220.  
  221.     /**
  222.     * Displays the help screen for "init" command
  223.     *
  224.     * @return void 
  225.     */
  226.     protected function doHelpInit()
  227.     {
  228.         self::toStdErr<<<EOH
  229. Usage: mdb2_schematool init source [-p] destination
  230.  
  231. Initializes a database with data
  232.  (Inserts data on a previous created database at destination)
  233.  
  234. source should be a schema file containing data,
  235. destination should be a DSN
  236.  
  237. DSN: Data source name in the form of
  238.  driver://user:password@host/database
  239.  
  240. User and password may be omitted.
  241. Using -p reads password from stdin which is more secure than passing it in the parameter.
  242.  
  243. EOH
  244.         );
  245.     }//protected function doHelpInit()
  246.  
  247.  
  248.  
  249.     /**
  250.     * Displays the help screen for "load" command
  251.     *
  252.     * @return void 
  253.     */
  254.     protected function doHelpLoad()
  255.     {
  256.         self::toStdErr<<<EOH
  257. Usage: mdb2_schematool load [-p] source [-p] destination
  258.  
  259. Loads a database schema from source to destination
  260.  (Creates the database schema at destination)
  261.  
  262. source can be a DSN or a schema file,
  263. destination should be a DSN
  264.  
  265. DSN: Data source name in the form of
  266.  driver://user:password@host/database
  267.  
  268. User and password may be omitted.
  269. Using -p reads password from stdin which is more secure than passing it in the parameter.
  270.  
  271. EOH
  272.         );
  273.     }//protected function doHelpLoad()
  274.  
  275.  
  276.  
  277.     /**
  278.     * Returns an array of options for MDB2_Schema constructor
  279.     *
  280.     * @return array Options for MDB2_Schema constructor
  281.     */
  282.     protected function getSchemaOptions()
  283.     {
  284.         $options = array(
  285.             'log_line_break' => '<br>',
  286.             'idxname_format' => '%s',
  287.             'debug' => true,
  288.             'quote_identifier' => true,
  289.             'force_defaults' => false,
  290.             'portability' => true,
  291.             'use_transactions' => false,
  292.         );
  293.         return $options;
  294.     }//protected function getSchemaOptions()
  295.  
  296.  
  297.  
  298.     /**
  299.     * Checks if the passed parameter is a PEAR_Error object
  300.     * and throws an exception in that case.
  301.     *
  302.     * @param mixed  $object   Some variable to check
  303.     * @param string $location Where the error occured
  304.     *
  305.     * @return void 
  306.     */
  307.     protected function throwExceptionOnError($object$location '')
  308.     {
  309.         if (PEAR::isError($object)) {
  310.             //FIXME: exception class
  311.             //debug_print_backtrace();
  312.             throw new Exception('Error ' $location
  313.                 . "\n" $object->getMessage()
  314.                 . "\n" $object->getUserInfo()
  315.             );
  316.         }
  317.     }//protected function throwExceptionOnError($object, $location = '')
  318.  
  319.  
  320.  
  321.     /**
  322.     * Loads a file or a dsn from the arguments
  323.     *
  324.     * @param array &$args Array of arguments to the program
  325.     *
  326.     * @return array Array of ('file'|'dsn', $value)
  327.     */
  328.     protected function getFileOrDsn(&$args)
  329.     {
  330.         if (count($args== 0{
  331.             throw new MDB2_Schema_Tool_ParameterException('File or DSN expected');
  332.         }
  333.  
  334.         $arg array_shift($args);
  335.         if ($arg == '-p'{
  336.             $bAskPassword = true;
  337.             $arg          array_shift($args);
  338.         else {
  339.             $bAskPassword = false;
  340.         }
  341.  
  342.         if (strpos($arg'://'=== false{
  343.             if (file_exists($arg)) {
  344.                 //File
  345.                 return array('file'$arg);
  346.             else {
  347.                 throw new Exception('Schema file does not exist');
  348.             }
  349.         }
  350.  
  351.         //read password if necessary
  352.         if ($bAskPassword{
  353.             $password $this->readPasswordFromStdin($arg);
  354.             $arg      = self::setPasswordIntoDsn($arg$password);
  355.             self::toStdErr($arg);
  356.         }
  357.         return array('dsn'$arg);
  358.     }//protected function getFileOrDsn(&$args)
  359.  
  360.  
  361.  
  362.     /**
  363.     * Takes a DSN data source name and integrates the given
  364.     * password into it.
  365.     *
  366.     * @param string $dsn      Data source name
  367.     * @param string $password Password
  368.     *
  369.     * @return string DSN with password
  370.     */
  371.     protected function setPasswordIntoDsn($dsn$password)
  372.     {
  373.         //simple try to integrate password
  374.         if (strpos($dsn'@'=== false{
  375.             //no @ -> no user and no password
  376.             return str_replace('://''://:' $password '@'$dsn);
  377.         else if (preg_match('|://[^:]+@|'$dsn)) {
  378.             //user only, no password
  379.             return str_replace('@'':' $password '@'$dsn);
  380.         else if (strpos($dsn':@'!== false{
  381.             //abstract version
  382.             return str_replace(':@'':' $password '@'$dsn);
  383.         }
  384.  
  385.         return $dsn;
  386.     }//protected function setPasswordIntoDsn($dsn, $password)
  387.  
  388.  
  389.  
  390.     /**
  391.     * Reads a password from stdin
  392.     *
  393.     * @param string $dsn DSN name to put into the message
  394.     *
  395.     * @return string Password
  396.     */
  397.     protected function readPasswordFromStdin($dsn)
  398.     {
  399.         $stdin fopen('php://stdin''r');
  400.         self::toStdErr('Please insert password for ' $dsn "\n");
  401.         $password '';
  402.         $breakme  = false;
  403.         while (false !== ($char fgetc($stdin))) {
  404.             if (ord($char== 10 || $char == "\n" || $char == "\r"{
  405.                 break;
  406.             }
  407.             $password .= $char;
  408.         }
  409.         fclose($stdin);
  410.  
  411.         return trim($password);
  412.     }//protected function readPasswordFromStdin()
  413.  
  414.  
  415.  
  416.     /**
  417.     * Creates a database schema dump and sends it to stdout
  418.     *
  419.     * @param array $args Command line arguments
  420.     *
  421.     * @return void 
  422.     */
  423.     protected function doDump($args)
  424.     {
  425.         $dump_what MDB2_SCHEMA_DUMP_STRUCTURE;
  426.         $arg '';
  427.         if (count($args)) {
  428.             $arg $args[0];
  429.         }
  430.  
  431.         switch (strtolower($arg)) {
  432.         case 'all':
  433.             $dump_what MDB2_SCHEMA_DUMP_ALL;
  434.             array_shift($args);
  435.             break;
  436.         case 'data':
  437.             $dump_what MDB2_SCHEMA_DUMP_CONTENT;
  438.             array_shift($args);
  439.             break;
  440.         case 'schema':
  441.             array_shift($args);
  442.         }
  443.  
  444.         list($type$dsn$this->getFileOrDsn($args);
  445.         if ($type == 'file'{
  446.             throw new MDB2_Schema_Tool_ParameterException(
  447.                 'Dumping a schema file as a schema file does not make much sense'
  448.             );
  449.         }
  450.  
  451.         $schema MDB2_Schema::factory($dsn$this->getSchemaOptions());
  452.         $this->throwExceptionOnError($schema);
  453.  
  454.         $definition $schema->getDefinitionFromDatabase();
  455.         $this->throwExceptionOnError($definition);
  456.  
  457.  
  458.         $dump_options = array(
  459.             'output_mode' => 'file',
  460.             'output' => 'php://stdout',
  461.             'end_of_line' => "\r\n"
  462.         );
  463.         $op $schema->dumpDatabase(
  464.             $definition$dump_options$dump_what
  465.         );
  466.         $this->throwExceptionOnError($op);
  467.  
  468.         $schema->disconnect();
  469.     }//protected function doDump($args)
  470.  
  471.  
  472.  
  473.     /**
  474.     * Loads a database schema
  475.     *
  476.     * @param array $args Command line arguments
  477.     *
  478.     * @return void 
  479.     */
  480.     protected function doLoad($args)
  481.     {
  482.         list($typeSource$dsnSource$this->getFileOrDsn($args);
  483.         list($typeDest,   $dsnDest)   $this->getFileOrDsn($args);
  484.  
  485.         if ($typeDest == 'file'{
  486.             throw new MDB2_Schema_Tool_ParameterException(
  487.                 'A schema can only be loaded into a database, not a file'
  488.             );
  489.         }
  490.  
  491.  
  492.         $schemaDest MDB2_Schema::factory($dsnDest$this->getSchemaOptions());
  493.         $this->throwExceptionOnError($schemaDest);
  494.  
  495.         //load definition
  496.         if ($typeSource == 'file'{
  497.             $definition $schemaDest->parseDatabaseDefinitionFile($dsnSource);
  498.             $where      'loading schema file';
  499.         else {
  500.             $schemaSource MDB2_Schema::factory($dsnSource$this->getSchemaOptions());
  501.             $this->throwExceptionOnError($schemaSource'connecting to source database');
  502.  
  503.             $definition $schemaSource->getDefinitionFromDatabase();
  504.             $where      'loading definition from database';
  505.         }
  506.         $this->throwExceptionOnError($definition$where);
  507.  
  508.  
  509.         //create destination database from definition
  510.         $simulate = false;
  511.         $op       $schemaDest->createDatabase($definitionarray()$simulate);
  512.         $this->throwExceptionOnError($op'creating the database');
  513.     }//protected function doLoad($args)
  514.  
  515.  
  516.  
  517.     /**
  518.     * Initializes a database with data
  519.     *
  520.     * @param array $args Command line arguments
  521.     *
  522.     * @return void 
  523.     */
  524.     protected function doInit($args)
  525.     {
  526.         list($typeSource$dsnSource$this->getFileOrDsn($args);
  527.         list($typeDest,   $dsnDest)   $this->getFileOrDsn($args);
  528.  
  529.         if ($typeSource != 'file'{
  530.             throw new MDB2_Schema_Tool_ParameterException(
  531.                 'Data must come from a source file'
  532.             );
  533.         }
  534.  
  535.         if ($typeDest != 'dsn'{
  536.             throw new MDB2_Schema_Tool_ParameterException(
  537.                 'A schema can only be loaded into a database, not a file'
  538.             );
  539.         }
  540.  
  541.         $schemaDest MDB2_Schema::factory($dsnDest$this->getSchemaOptions());
  542.         $this->throwExceptionOnError($schemaDest'connecting to destination database');
  543.  
  544.         $definition $schemaDest->getDefinitionFromDatabase();
  545.         $this->throwExceptionOnError($definition'loading definition from database');
  546.  
  547.         $op $schemaDest->writeInitialization($dsnSource$definition);
  548.         $this->throwExceptionOnError($op'initializing database');
  549.     }//protected function doInit($args)
  550.  
  551.  
  552. }//class MDB2_Schema_Tool
  553.  
  554. ?>

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