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

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