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

Source for file Cli.php

Documentation is available at Cli.php

  1. <?php
  2. /**
  3.  * Application_Cli
  4.  * 
  5.  * Copyright (C) 2009  Mai (Me Artificial Intelligence)
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation, either version 3 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  * 
  20.  * @author Wouter Bulten (wouterbulten@mai-ai.org)
  21.  * @copyright Copyright (C) 2009  Mai (Me Artificial Intelligence)
  22.  * @license http://opensource.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
  23.  * @link http://www.launchpad.net/mai
  24.  * 
  25.  * @package Application
  26.  * @subpackage Cli
  27.  * 
  28.  */
  29.  
  30. /**
  31.  * Command line interface for Mai. (Mai Manager)
  32.  * 
  33.  * @author Wouter Bulten (wouterbulten@mai-ai.org)
  34.  * @copyright Copyright (C) 2009  Mai (Me Artificial Intelligence)
  35.  * @license http://opensource.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
  36.  * @link http://www.launchpad.net/mai
  37.  * 
  38.  * @package Application
  39.  * @subpackage Cli
  40.  * 
  41.  *  
  42.  */
  43. {
  44.     /**
  45.      * Private constructor to prevent creation of this object.
  46.      * @return void 
  47.      */
  48.     private function __construct(){}
  49.     
  50.     /**
  51.      * Starts up the bootstrap.
  52.      * @param $arguments 
  53.      * @return void 
  54.      */
  55.     static public function run()
  56.     {
  57.         self::output("\n---\n Mai Command Line Interface \n\n");
  58.         self::output(" Copyright (C) 2009  Mai (Me Artificial Intelligence) \n");
  59.         self::output(" Licensed under the GNU General Public License version 3 (GPLv3) \n");
  60.         self::output("---\n\n");
  61.  
  62.         do
  63.         {
  64.             $exit false;
  65.             self::output("This CLI can install, update or change your Mai installation. \n");
  66.             self::output("Please proceed with caution! \n");
  67.             do
  68.             {
  69.                 self::output("\nWhat do you want to do?\n\n");
  70.                 self::output("   [1] Install \n");
  71.                 self::output("   [2] Backup database \n");
  72.                 self::output("   [q] Exit  \n\n");
  73.                 self::output("Option: ");
  74.  
  75.                 $option trim(fgets(STDIN));
  76.             }
  77.             while(!in_array($optionarray(1,2'q''[1]''[2]''[q]')));
  78.  
  79.             switch($option)
  80.             {
  81.                 case 1//Install
  82.                 case '[1]':
  83.                     self::runInstall();
  84.                     break;
  85.                 case 2:
  86.                 case '[2]':
  87.                     self::runBackupDb();
  88.                     self::output("\n\nCLI finished.\n\n");
  89.                     break;
  90.                 case 'q':
  91.                 case '[q]':
  92.                 default:
  93.                     self::output("\n\nCLI closed.");
  94.                     $exit true;
  95.                     break;
  96.             }
  97.  
  98.             //Ask to exit the manager
  99.             self::output("\n\nDo you want to exit the manager? (y/n) ");
  100.             $option trim(fgets(STDIN));
  101.             if($option == 'y')
  102.             {
  103.                 $exit true;
  104.             }
  105.         }
  106.         while(!$exit);
  107.     }
  108.     
  109.     /**
  110.      * Ask the user to confirm.
  111.      * @param $message 
  112.      * @return void 
  113.      */
  114.     static private function askToConfirm($message "\n\nDo you wish to continue? (y\n) ")
  115.     {
  116.         //Loop until the answer is 'y' or 'n'
  117.         do
  118.         {
  119.             fwrite(STDOUT$message);
  120.             $continue trim(fgets(STDIN));
  121.             if($continue == 'n')
  122.             {
  123.                 return false;
  124.             }
  125.         }
  126.         while($continue != 'n' && $continue != 'y');
  127.  
  128.         return true;
  129.     }
  130.  
  131.     /**
  132.      * Ask the user to continue
  133.      * @return void 
  134.      */
  135.     static private function askToContinue()
  136.     {
  137.         //Loop until the answer is 'y' or 'n'
  138.         do
  139.         {
  140.             fwrite(STDOUT"\n\nDo you wish to continue? (y/n) ");
  141.  
  142.             $continue trim(fgets(STDIN));
  143.             if($continue == 'n')
  144.             {
  145.                 fwrite(STDOUT"\n" "Exiting manager..." "\n");
  146.                 exit;
  147.             }
  148.  
  149.             fwrite(STDOUT"\n");
  150.         }
  151.         while($continue != 'n' && $continue != 'y');
  152.     }
  153.     
  154.     /**
  155.      * Output a message.
  156.      * @param $message 
  157.      * @return void 
  158.      */
  159.     static private function output($message)
  160.     {
  161.         fwrite(STDOUT$message);
  162.     }
  163.     
  164.     /**
  165.      * Test the PHP version.
  166.      * @return Boolean 
  167.      */
  168.     static private function testPhpVersion()
  169.     {
  170.         return version_compare(PHP_VERSION'5.2.4''>');
  171.     }
  172.  
  173.     /**
  174.      * Look for a loaded database extension.
  175.      * @return Boolean 
  176.      */
  177.     static private function testDatabaseDrivers()
  178.     {
  179.         $loaded false;
  180.  
  181.         if(extension_loaded('fbsql'))
  182.         {
  183.             self::output("FrontBase: OK\n");
  184.             $loaded true;
  185.         }
  186.         else
  187.         {
  188.             self::output("FrontBase: Not found!\n");
  189.         }
  190.  
  191.         if(extension_loaded('ibase'))
  192.         {
  193.             self::output("InterBase / Firebird: OK\n");
  194.             $loaded true;
  195.         }
  196.         else 
  197.         {
  198.             self::output("InterBase / Firebird: Not found!\n");
  199.         }
  200.  
  201.         if(extension_loaded('mssql'))
  202.         {
  203.             self::output("Microsoft SQL Server: OK\n");
  204.             $loaded true;
  205.         }
  206.         else
  207.         {
  208.             self::output("Microsoft SQL Server: Not found!\n");
  209.         }
  210.  
  211.         if(extension_loaded('mysql'))
  212.         {
  213.             self::output("MySQL: OK\n");
  214.             $loaded true;
  215.         }
  216.         else
  217.         {
  218.             self::output("MySQL: Not found!\n");
  219.         }
  220.  
  221.         if(extension_loaded('mysqli'))
  222.         {
  223.             self::output("MySQLi: OK\n");
  224.             $loaded true;
  225.         }
  226.         else
  227.         {
  228.             self::output("MySQLi: Not found!\n");
  229.         }
  230.  
  231.         if(extension_loaded('oci'))
  232.         {
  233.             self::output("Oracle: OK\n");
  234.             $loaded true;
  235.         }
  236.         else
  237.         {
  238.             self::output("Oracle: Not found!\n");
  239.         }
  240.  
  241.         if(extension_loaded('pqsql'))
  242.         {
  243.             self::output("PostgreSQL: OK\n");
  244.             $loaded true;
  245.         }
  246.         else
  247.         {
  248.             self::output("PostgreSQL: Not found!\n");
  249.         }
  250.  
  251.         if(extension_loaded('querysim'))
  252.         {
  253.             self::output("QuerySim: OK\n");
  254.             $loaded true;
  255.         }
  256.         else
  257.         {
  258.             self::output("QuerySim: Not found!\n");
  259.         }
  260.  
  261.         if(extension_loaded('sqlite'))
  262.         {
  263.             self::output("SQLite 2: OK\n");
  264.             $loaded true;
  265.         }
  266.         else
  267.         {
  268.             self::output("SQLite 2: Not found!\n");
  269.         }
  270.  
  271.         return $loaded;
  272.     }
  273.  
  274.     /**
  275.      * Create a config file for Mai
  276.      * @return void 
  277.      */
  278.     static private function createConfig()
  279.     {
  280.         $config array();
  281.  
  282.         //Ask wich db extension to use
  283.         self::output("\nMai creates 2 databases. Wich extension should be used? (e.g. mysql or psql) ");
  284.         do
  285.         {
  286.             $extension trim(fgets(STDIN));
  287.             $config['db']['db_user']['dbtype'$extension;
  288.             $config['db']['db_user']['connection_name''mai_userdb_connection';
  289.             $config['db']['db_base']['dbtype'$extension;
  290.             $config['db']['db_base']['connection_name''mai_basedb_connection';
  291.         }
  292.         while(!in_array($extensionarray('mysql''fbsql''ibase''mssql''mysqli''oci''pgsql''querysim''sqlite')));
  293.  
  294.         //Ask wich host to use
  295.         self::output("\nWhat host should be used? (default is localhost) ");
  296.         $host trim(fgets(STDIN));
  297.         $config['db']['db_user']['host'$host;
  298.         $config['db']['db_base']['host'$host;
  299.  
  300.         //Ask for dbnames
  301.         self::output("\nWhat databse name should be used for the base database? (default is mai_base) ");
  302.         $config['db']['db_base']['dbname'trim(fgets(STDIN));
  303.         self::output("\nWhat databse name should be used for the user database? (default is mai_user) ");
  304.         $config['db']['db_user']['dbname'trim(fgets(STDIN));
  305.  
  306.         //Ask for user and password (base)
  307.         self::output("\nA database user is needed with rights to create the base database.");
  308.         self::output("\nPlease create a database named ".$config['db']['db_base']['dbname']."and a user with rights on it.");
  309.         self::output("\nAlternatively you can create a user wich has the right to create a database.");
  310.         self::output("\nWhat is the username of the user for the BASE db? ");
  311.         $config['db']['db_base']['username'$host trim(fgets(STDIN));
  312.  
  313.         self::output("\nWhat is the password of the user for the BASE db? ");
  314.         $config['db']['db_base']['password'$host trim(fgets(STDIN));
  315.  
  316.         //Ask for user and password (user)
  317.         self::output("\nA database user is needed with rights to create the user database.");
  318.         self::output("\nPlease create a database named ".$config['db']['db_user']['dbname']."and a user with rights on it.");
  319.         self::output("\nAlternatively you can create a user wich has the right to create a database.");
  320.         self::output("\nWhat is the username of the user for the USER db? ");        
  321.         $config['db']['db_user']['username'$host trim(fgets(STDIN));;
  322.  
  323.         self::output("\nWhat is the password of the user for the USER db? ");
  324.         $config['db']['db_user']['password'$host trim(fgets(STDIN));
  325.  
  326.         //End config
  327.         self::output("\nThe config file will now be created. These values can be changed by editing the config file:");
  328.         self::output("\n" APPLICATION_PATH "\config\config.ini");
  329.  
  330.         //Set development to on
  331.         $config['global']['application']['development'1;
  332.  
  333.         //Open the ini file to write
  334.         $iniFile fopen(APPLICATION_PATH "/config/config.ini""w");
  335.         do
  336.         {
  337.             $success true;
  338.             //Try to write to the file
  339.             try
  340.             {
  341.                 fwrite($iniFile";Config file created by Mai Manager at .".date("d-m-Y H:i")."\n\n");
  342.             }
  343.             catch(Exception $e)
  344.             {
  345.                 $success false;
  346.                 self::output("\n\nWARNING: " APPLICATION_PATH "/config/config.ini is not writable!");
  347.                 self::output("\nPlease make this file writable.");
  348.                 self::askToContinue();
  349.             }
  350.         }
  351.         while($success == false);
  352.  
  353.         //Write config to file
  354.         foreach($config as $section => $sectionContent)
  355.         {
  356.             //Create section
  357.             fwrite($iniFile"[$section]\n");
  358.  
  359.             foreach($sectionContent as $head => $sub)
  360.             {
  361.                 //Create name of the variable (head.sub = value)
  362.                 foreach($sub as $name => $value)
  363.                 {
  364.                     fwrite($iniFile"$head.$name = $value\n");
  365.                 }
  366.             }
  367.         }
  368.     }
  369.  
  370.     /**
  371.      * Test the connection with the base db.
  372.      * @return Boolean 
  373.      */
  374.     static private function testBaseDb()
  375.     {
  376.         $config parent::returnDbConfig();
  377.         //Data Source Name
  378.         $dsn =  sprintf('%s://%s:%s@%s/%s',
  379.                     $config->db_base->dbtype,
  380.                     $config->db_base->username,
  381.                     $config->db_base->password,
  382.                     $config->db_base->host,
  383.                     $config->db_base->dbname);
  384.         
  385.         $conn Doctrine_Manager::connection($dsn$config->db_base->connection_name);
  386.         try
  387.         {
  388.             //Test the connection
  389.             $conn->beginTransaction();
  390.             //Save
  391.             Zend_Registry::set('conn_dbbase'$conn);
  392.         }
  393.         catch(Doctrine_Connection_Exception $e)
  394.         {
  395.             return false;
  396.         }
  397.  
  398.         return true;
  399.     }
  400.  
  401.     /**
  402.      * Test the connection with the user db.
  403.      * @return Boolean 
  404.      */
  405.     static private function testUserDb()
  406.     {
  407.         $config parent::returnDbConfig();
  408.         //Data Source Name
  409.         $dsn =  sprintf('%s://%s:%s@%s/%s',
  410.                     $config->db_user->dbtype,
  411.                     $config->db_user->username,
  412.                     $config->db_user->password,
  413.                     $config->db_user->host,
  414.                     $config->db_user->dbname);
  415.  
  416.         $conn Doctrine_Manager::connection($dsn$config->db_user->connection_name);
  417.         
  418.         try
  419.         {
  420.             //Test the connection
  421.             $conn->beginTransaction();
  422.             //Save
  423.             Zend_Registry::set('conn_dbuser'$conn);
  424.         }
  425.         catch(Doctrine_Connection_Exception $e)
  426.         {
  427.             return false;
  428.         }
  429.  
  430.         return true;
  431.     }
  432.  
  433.     /**
  434.      * Install Mai
  435.      * @return void 
  436.      */
  437.     static private function runInstall()
  438.     {
  439.         self::output("\nChecking requirements.. ");
  440.  
  441.         //Test php version
  442.         if(!self::testPhpVersion())
  443.         {
  444.             self::output("\n\nPHP 5.2.4 or higher is recommended! Your version is ".PHP_VERSION.
  445.             "\nMai could run but this is not tested. No support is given!");
  446.  
  447.             self::askToContinue();
  448.         }
  449.         else
  450.         {
  451.             self::output("\nPHP: OK (".PHP_VERSION.") \n");
  452.         }
  453.  
  454.         //Test database
  455.         if(!self::testDatabaseDrivers())
  456.         {
  457.             self::output("\n\nNo database extension is found. Please enable or install an extension.");
  458.             self::output("\nMai cannot run without an database! Installation aborted.");
  459.             exit;
  460.         }
  461.         else
  462.         {
  463.             self::output("\nValid database extension found.");
  464.         }
  465.  
  466.         self::output("\nCreating new config..");
  467.  
  468.         //Ask to create a custom config file
  469.         if(self::askToConfirm("\n\nDo you want to configure Mai? (recommended) (y/n) "))
  470.         {
  471.             self::createConfig();
  472.         }
  473.  
  474.         self::output("\nBootstrapping started..");
  475.  
  476.         //Set include paths
  477.         parent::initIncludePaths();
  478.         //Start auto loader
  479.         parent::initAutoLoader();
  480.         //Load global config
  481.         parent::initGlobalConfig();
  482.  
  483.         self::output("\nBootstrapping completed.");
  484.         self::output("\nTesting database connection: base");
  485.  
  486.         //Start base db connection
  487.         if(!self::testBaseDb())
  488.         {
  489.             self::output("\n\nWARNING: Failed to connect to the base db.");
  490.             self::output("\nYou can configure Mai yourself and update the database using this installer.");
  491.             self::output("\nAlternatively you can reconfigure Mai.");
  492.             if(self::askToConfirm("\n\nDo you want to reconfigure Mai? (recommended) (y/n) "))
  493.             {
  494.                 self::createConfig();
  495.             }
  496.             else
  497.             {
  498.                 if(!self::askToConfirm("\n\nDo you want to continue with the installation? (y/n) "))
  499.                 {
  500.                     //Exit installation
  501.                     self::output("Installation cancelled.");
  502.                     exit;
  503.                 }
  504.  
  505.             }
  506.         }
  507.         else
  508.         {
  509.             self::output("\nBase Database connection: OK");
  510.             //Doctrine Command Line interface
  511.             $cli new Doctrine_Cli(parent::returnDoctrineCliConfigBase());
  512.  
  513.             if(!self::askToConfirm("\nDoes the base database already excist? (y/n) "))
  514.             {
  515.                 //Create base db
  516.  
  517.                 $cli->run(array('mai-manager''create-db basedb'));
  518.             }
  519.  
  520.             //Create tables and data
  521.             $cli->run(array('mai-manager''generate-sql basedb'));
  522.             $cli->run(array('mai-manager''create-tables basedb'));
  523.             //Free from memory
  524.             unset($cli);
  525.         }
  526.  
  527.         self::output("\nTesting database connection: user");
  528.         //Start user db connection
  529.         if(!self::testUserDb())
  530.         {
  531.             self::output("\n\nWARNING: Failed to connect to the user db.");
  532.             self::output("\nYou can configure Mai yourself and update the database using this installer.");
  533.             self::output("\nAlternatively you can reconfigure Mai.");
  534.             if(self::askToConfirm("\n\nDo you want to reconfigure Mai? (recommended) (y/n) "))
  535.             {
  536.                 self::createConfig();
  537.             }
  538.             else
  539.             {
  540.                 if(!self::askToConfirm("\n\nDo you want to continue with the installation? (y/n) "))
  541.                 {
  542.                     //Exit installation
  543.                     self::output("Installation cancelled.");
  544.                     exit;
  545.                 }
  546.  
  547.             }
  548.         }
  549.         else
  550.         {
  551.             self::output("\nUser Database connection: OK");
  552.             //Doctrine Command Line interface
  553.             $cli new Doctrine_Cli(parent::returnDoctrineCliConfigUser());
  554.  
  555.             if(!self::askToConfirm("\nDoes the user databse already excist? (y/n) "))
  556.             {
  557.                 //Create base db
  558.  
  559.                 $cli->run(array('mai-manager''create-db'));
  560.             }
  561.  
  562.             //Create tables and data
  563.             $cli->run(array('mai-manager''generate-sql'));
  564.             $cli->run(array('mai-manager''create-tables'));
  565.             //Free from memory
  566.             unset($cli);
  567.         }
  568.  
  569.         if(self::askToConfirm("\nDo you want to test your Mai installation? (cURL extension required) (y/n) "))
  570.         {
  571.             if(extension_loaded('curl'))
  572.             {
  573.                 //Use the URL to test Mai
  574.                 self::output("\nWhat is the url of your Mai installation? (default is http://localhost) ");
  575.                 $url =  trim(fgets(STDIN));
  576.                 $test curl_init($url '/talk/');
  577.                 //Set to return
  578.                 curl_setopt($testCURLOPT_RETURNTRANSFERtrue);
  579.                 //Get the result
  580.                 $result curl_exec($test);
  581.                 curl_close($test);
  582.  
  583.                 //The TalkController should output invalid-session
  584.                 if($result == 'invalid-session')
  585.                 {
  586.                     self::output("\nTest: OK");
  587.                 }
  588.                 else
  589.                 {
  590.                     self::output("\nTest failed. Response:\n\n".$result);
  591.                 }
  592.             }
  593.             else
  594.             {
  595.                 self::output("\nTest failed, cURL is not activated.");
  596.             }
  597.         }
  598.  
  599.         self::output("\n\n\nMai installation finished! Enjoy!");
  600.     }
  601.  
  602.     /**
  603.      * Backup the Mai database
  604.      * @return void 
  605.      */
  606.     static private function runBackupDb()
  607.     {
  608.         //@Mai Todo: Backup function not yet finished.
  609.         self::output("\n\nMai Manager is not yet able to backup your database.");
  610.     }
  611.  
  612. }

Documentation generated on Mon, 27 Jul 2009 19:51:55 +0200 by phpDocumentor 1.4.1