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 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: Christian Weiske <cweiske@php.net>                           |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: Tool.php,v 1.4 2008/03/24 19:15:02 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.         default:
  144.             throw new MDB2_Schema_Tool_ParameterException("Unknown mode \"$arg\"");
  145.         }
  146.     }//protected function getAction(&$args)
  147.  
  148.  
  149.  
  150.     /**
  151.     * Writes the message to stderr
  152.     *
  153.     * @param string $msg Message to print
  154.     *
  155.     * @return void 
  156.     */
  157.     protected static function toStdErr($msg)
  158.     {
  159.         file_put_contents('php://stderr'$msg);
  160.     }//protected static function toStdErr($msg)
  161.  
  162.  
  163.  
  164.     /**
  165.     * Displays generic help to stdout
  166.     *
  167.     * @return void 
  168.     */
  169.     protected function doHelp()
  170.     {
  171.         self::toStdErr(<<<EOH
  172. Usage: mdb2_schematool mode parameters
  173.  
  174. Works with database schemas
  175.  
  176. mode: (- and -- are optional)
  177.  h,  help     Show this help screen
  178.  d,  dump     Dump a schema to stdout
  179.  l,  load     Load a schema into database
  180.  i,  diff     Create a diff between two schemas and dump it to stdout
  181.  a,  apply    Apply a diff to a database
  182.  
  183. EOH
  184.         );
  185.     }//protected function doHelp()
  186.  
  187.  
  188.  
  189.     /**
  190.     * Displays the help screen for "dump" command
  191.     *
  192.     * @return void 
  193.     */
  194.     protected function doHelpDump()
  195.     {
  196.         self::toStdErr<<<EOH
  197. Usage: mdb2_schematool dump [-p] DSN
  198.  
  199. Dumps a database schema to stdout
  200.  
  201. DSN: Data source name in the form of
  202.  driver://user:password@host/database
  203.  
  204. User and password may be omitted.
  205. Using -p reads password from stdin which is more secure than passing it in the parameter.
  206.  
  207. EOH
  208.         );
  209.     }//protected function doHelpDump()
  210.  
  211.  
  212.  
  213.     /**
  214.     * Displays the help screen for "load" command
  215.     *
  216.     * @return void 
  217.     */
  218.     protected function doHelpLoad()
  219.     {
  220.         self::toStdErr<<<EOH
  221. Usage: mdb2_schematool load [-p] source [-p] destination
  222.  
  223. Loads a database schema from source to destination
  224.  (Creates the database schema at destination)
  225.  
  226. source can be a DSN or a schema file,
  227. destination should be a DSN
  228.  
  229. DSN: Data source name in the form of
  230.  driver://user:password@host/database
  231.  
  232. User and password may be omitted.
  233. Using -p reads password from stdin which is more secure than passing it in the parameter.
  234.  
  235. EOH
  236.         );
  237.     }//protected function doHelpLoad()
  238.  
  239.  
  240.  
  241.     /**
  242.     * Returns an array of options for MDB2_Schema constructor
  243.     *
  244.     * @return array Options for MDB2_Schema constructor
  245.     */
  246.     protected function getSchemaOptions()
  247.     {
  248.         $options = array(
  249.             'log_line_break' => '<br>',
  250.             'idxname_format' => '%s',
  251.             'debug' => true,
  252.             'quote_identifier' => true,
  253.             'force_defaults' => false,
  254.             'portability' => true,
  255.             'use_transactions' => false,
  256.         );
  257.         return $options;
  258.     }//protected function getSchemaOptions()
  259.  
  260.  
  261.  
  262.     /**
  263.     * Checks if the passed parameter is a PEAR_Error object
  264.     * and throws an exception in that case.
  265.     *
  266.     * @param mixed  $object   Some variable to check
  267.     * @param string $location Where the error occured
  268.     *
  269.     * @return void 
  270.     */
  271.     protected function throwExceptionOnError($object$location '')
  272.     {
  273.         if (PEAR::isError($object)) {
  274.             //FIXME: exception class
  275.             //debug_print_backtrace();
  276.             throw new Exception('Error ' $location
  277.                 . "\n" $object->getMessage()
  278.                 . "\n" $object->getUserInfo()
  279.             );
  280.         }
  281.     }//protected function throwExceptionOnError($object, $location = '')
  282.  
  283.  
  284.  
  285.     /**
  286.     * Loads a file or a dsn from the arguments
  287.     *
  288.     * @param array &$args Array of arguments to the program
  289.     *
  290.     * @return array Array of ('file'|'dsn', $value)
  291.     */
  292.     protected function getFileOrDsn(&$args)
  293.     {
  294.         if (count($args== 0{
  295.             throw new MDB2_Schema_Tool_ParameterException('File or DSN expected');
  296.         }
  297.  
  298.         $arg array_shift($args);
  299.         if ($arg == '-p'{
  300.             $bAskPassword = true;
  301.             $arg          array_shift($args);
  302.         else {
  303.             $bAskPassword = false;
  304.         }
  305.  
  306.         if (strpos($arg'://'=== false{
  307.             if (file_exists($arg)) {
  308.                 //File
  309.                 return array('file'$arg);
  310.             else {
  311.                 throw new Exception('Schema file does not exist');
  312.             }
  313.         }
  314.  
  315.         //read password if necessary
  316.         if ($bAskPassword{
  317.             $password $this->readPasswordFromStdin($arg);
  318.             $arg      = self::setPasswordIntoDsn($arg$password);
  319.             self::toStdErr($arg);
  320.         }
  321.         return array('dsn'$arg);
  322.     }//protected function getFileOrDsn(&$args)
  323.  
  324.  
  325.  
  326.     /**
  327.     * Takes a DSN data source name and integrates the given
  328.     * password into it.
  329.     *
  330.     * @param string $dsn      Data source name
  331.     * @param string $password Password
  332.     *
  333.     * @return string DSN with password
  334.     */
  335.     protected function setPasswordIntoDsn($dsn$password)
  336.     {
  337.         //simple try to integrate password
  338.         if (strpos($dsn'@'=== false{
  339.             //no @ -> no user and no password
  340.             return str_replace('://''://:' $password '@'$dsn);
  341.         else if (preg_match('|://[^:]+@|'$dsn)) {
  342.             //user only, no password
  343.             return str_replace('@'':' $password '@'$dsn);
  344.         else if (strpos($dsn':@'!== false{
  345.             //abstract version
  346.             return str_replace(':@'':' $password '@'$dsn);
  347.         }
  348.  
  349.         return $dsn;
  350.     }//protected function setPasswordIntoDsn($dsn, $password)
  351.  
  352.  
  353.  
  354.     /**
  355.     * Reads a password from stdin
  356.     *
  357.     * @param string $dsn DSN name to put into the message
  358.     *
  359.     * @return string Password
  360.     */
  361.     protected function readPasswordFromStdin($dsn)
  362.     {
  363.         $stdin fopen('php://stdin''r');
  364.         self::toStdErr('Please insert password for ' $dsn "\n");
  365.         $password '';
  366.         $breakme  = false;
  367.         while (false !== ($char fgetc($stdin))) {
  368.             if (ord($char== 10 || $char == "\n" || $char == "\r"{
  369.                 break;
  370.             }
  371.             $password .= $char;
  372.         }
  373.         fclose($stdin);
  374.  
  375.         return trim($password);
  376.     }//protected function readPasswordFromStdin()
  377.  
  378.  
  379.  
  380.     /**
  381.     * Creates a database schema dump and sends it to stdout
  382.     *
  383.     * @param array $args Command line arguments
  384.     *
  385.     * @return void 
  386.     */
  387.     protected function doDump($args)
  388.     {
  389.         list($type$dsn$this->getFileOrDsn($args);
  390.  
  391.         if ($type == 'file'{
  392.             throw new MDB2_Schema_Tool_ParameterException(
  393.                 'Dumping a schema file as a schema file does not make much sense'
  394.             );
  395.         }
  396.  
  397.         $schema MDB2_Schema::factory($dsn$this->getSchemaOptions());
  398.         $this->throwExceptionOnError($schema);
  399.  
  400.         $definition $schema->getDefinitionFromDatabase();
  401.         $this->throwExceptionOnError($definition);
  402.  
  403.  
  404.         $dump_options = array(
  405.             'output_mode' => 'file',
  406.             'output' => 'php://stdout',
  407.             'end_of_line' => "\r\n"
  408.         );
  409.         $op $schema->dumpDatabase(
  410.             $definition$dump_optionsMDB2_SCHEMA_DUMP_STRUCTURE
  411.         );
  412.         $this->throwExceptionOnError($op);
  413.  
  414.         $schema->disconnect();
  415.     }//protected function doDump($args)
  416.  
  417.  
  418.  
  419.     /**
  420.     * Loads a database schema
  421.     *
  422.     * @param array $args Command line arguments
  423.     *
  424.     * @return void 
  425.     */
  426.     protected function doLoad($args)
  427.     {
  428.         list($typeSource$dsnSource$this->getFileOrDsn($args);
  429.         list($typeDest,   $dsnDest)   $this->getFileOrDsn($args);
  430.  
  431.         if ($typeDest == 'file'{
  432.             throw new MDB2_Schema_Tool_ParameterException(
  433.                 'A schema can only be loaded into a database, not a file'
  434.             );
  435.         }
  436.  
  437.  
  438.         $schemaDest MDB2_Schema::factory($dsnDest$this->getSchemaOptions());
  439.         $this->throwExceptionOnError($schemaDest);
  440.  
  441.         //load definition
  442.         if ($typeSource == 'file'{
  443.             $definition $schemaDest->parseDatabaseDefinitionFile($dsnSource);
  444.             $where      'loading schema file';
  445.         else {
  446.             $schemaSource MDB2_Schema::factory($dsnSource$this->getSchemaOptions());
  447.             $this->throwExceptionOnError($schemaSource'connecting to source database');
  448.  
  449.             $definition $schemaSource->getDefinitionFromDatabase();
  450.             $where      'loading definition from database';
  451.         }
  452.         $this->throwExceptionOnError($definition$where);
  453.  
  454.  
  455.         //create destination database from definition
  456.         $simulate = false;
  457.         $op       $schemaDest->createDatabase($definitionarray()$simulate);
  458.         $this->throwExceptionOnError($op'creating the database');
  459.     }//protected function doLoad($args)
  460.  
  461.  
  462. }//class MDB2_Schema_Tool
  463.  
  464. ?>

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