MDL-15249 sample cli scripts - sample implementation only, no localization - ideally we should now decide what parameters we need - let the heated discussion begin ;-)

This commit is contained in:
skodak 2009-05-27 09:52:25 +00:00
parent e121db763a
commit 3b596dbf0b
5 changed files with 835 additions and 1756 deletions

539
admin/cli/install.php Normal file
View File

@ -0,0 +1,539 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script creates config.php file and prepares database.
*
* This script is not intended for beginners!
* Potential problems:
* - environment check is not present yet
* - su to apache account or sudo before execution
* - not compatible with Windows platform
*
* @package moodlecore
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (isset($_SERVER['REMOTE_ADDR'])) {
error_log("admin/cli/install.php can not be called from web server!");
exit;
}
$olddir = getcwd();
// change directory so that includes bellow work properly
chdir(dirname($_SERVER['argv'][0]));
// Nothing to do if config.php exists
$configfile = dirname(dirname(dirname(__FILE__))).'/config.php';
if (file_exists($configfile)) {
die("Moodle already installed, please use admin/cli/upgrade.php if you want to upgrade your site.\n");
}
// make sure PHP errors are displayed - helps with diagnosing of problems
@error_reporting(E_ALL);
@ini_set('display_errors', '1');
// we need a lot of memory
@ini_set('memory_limit', '128M');
// Check that PHP is of a sufficient version
if (version_compare(phpversion(), "5.2.8") < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
echo "Sorry, Moodle 2.0 requires PHP 5.2.8 or later (currently using version $phpversion).\n";
echo "Please upgrade your server software or install latest Moodle 1.9.x instead.";
die;
}
// set up configuration
$CFG = new stdClass();
$CFG->lang = 'en_utf8';
$CFG->dirroot = str_replace('\\', '/', dirname(dirname(dirname(__FILE__)))); // Fix for win32
$CFG->libdir = "$CFG->dirroot/lib";
$CFG->wwwroot = "http://localhost";
$CFG->httpswwwroot = $CFG->wwwroot;
$CFG->httpsthemewww = $CFG->wwwroot;
$CFG->dataroot = str_replace('\\', '/', dirname(dirname(dirname(__FILE__))).'/moodledata');
$CFG->docroot = 'http://docs.moodle.org';
$CFG->directorypermissions = 00777;
$CFG->running_installer = true;
$parts = explode('/', str_replace('\\', '/', dirname(dirname(__FILE__))));
$CFG->admin = array_pop($parts);
require($CFG->dirroot.'/version.php');
$CFG->target_release = $release;
//point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else
//the problem is that we need specific version of quickforms and hacked excel files :-(
ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
require_once($CFG->libdir.'/installlib.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->libdir.'/setuplib.php');
require_once($CFG->libdir.'/textlib.class.php');
require_once($CFG->libdir.'/weblib.php');
require_once($CFG->libdir.'/dmllib.php');
require_once($CFG->libdir.'/moodlelib.php');
require_once($CFG->libdir.'/deprecatedlib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/environmentlib.php');
require_once($CFG->libdir.'/xmlize.php');
require_once($CFG->libdir.'/componentlib.class.php');
require_once($CFG->libdir.'/upgradelib.php');
//Database types
$databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
'oci' => moodle_database::get_driver_instance('oci', 'native'),
//'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // new MS sql driver - win32 only
//'mssql' => moodle_database::get_driver_instance('mssql', 'native'), // FreeTDS driver
);
foreach ($databases as $type=>$database) {
if ($database->driver_installed() !== true) {
unset($databases[$type]);
}
}
if (empty($databases)) {
cli_error('No db drivers available!'); // TODO: localize
}
reset($databases);
$defaultdb = key($databases);
// now get cli options
list($options, $unrecognized) = cli_get_params(array('lang'=>$CFG->lang, 'wwwroot'=>'', 'dataroot'=>$CFG->dataroot, 'dbtype'=>$defaultdb, 'dbhost'=>'localhost',
'dbname'=>'moodle', 'dbuser'=>'root', 'dbpass'=>'', 'dbsocket'=>false, 'prefix'=>'mdl_', 'admin-password'=>'',
'non-interactive'=>false, 'agreelicense'=>false, 'help'=>false),
array('h'=>'help'));
$interactive = empty($options['non-interactive']);
// set up language
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
if (file_exists($CFG->dirroot.'/install/lang/'.$lang)) {
$CFG->lang = $lang;
} else {
if (file_exists($CFG->dirroot.'/install/lang/'.$lang.'_utf8')) {
$CFG->lang = $lang.'_utf8';
}
}
if ($unrecognized) {
$error = implode("\n ", $unrecognized);
cli_error("Unrecognized options:\n $error \n. Please use --help option."); // TODO: localize, mark as needed in install
}
if ($options['help']) {
$help =
"Command line Moodle installer, creates config.php and initializes database.
Please note you must execute this script with the same uid as apache
or use chmod/chown after installation.
Site defaults may be changed via local/defaults.php.
Options:
--lang=CODE Installation and default site language.
--wwwroot=URL Web address for the Moodle site,
required in non-interactive mode.
--dataroot=DIR Location of the moodle data folder,
must not be web accessible. Default is moodleroot
in parent directory.
--dbtype=TYPE Database type. Default is mysqli
--dbhost=HOST Database host. Default is localhost
--dbname=NAME Database name. Default is moodle
--dbuser=USERNAME Database user. Default is root
--dbpass=PASSWORD Database password. Default is blank
--dbsocket Use database sockets. Available for some databases only.
--prefix=STRING Table prefix for above database tables. Default is mdl_
--admin-password=PASS Password for the moodle admin account,
required in non-interactive mode.
--non-interactive No interactive questions, installation fails if any
problem encountered.
--agreelicense Indicates agreement with software license,
required in non-interactive mode.
-h, --help Print out this help
Example: \$sudo -u wwwrun /usr/bin/php admin/cli/install.php --lang=cs
"; //TODO: localize, mark as needed in install
echo $help;
die;
}
$separator = str_repeat('=', 79)."\n";
//Print header
echo "Moodle $CFG->target_release command line installation program.\n"; // TODO: localize, mark as needed in install
//Fist select language
if ($interactive) {
echo $separator;
$languages = install_get_list_of_languages();
// fomrat the langs nicely - 4 per line
$c = 0;
$langlist = '';
foreach ($languages as $key=>$lang) {
$c++;
$length = iconv_strlen($lang, 'UTF-8');
$padded = $lang.str_repeat(' ', 28-$length);
$langlist .= $padded;
if ($c % 3 == 0) {
$langlist .= "\n";
}
}
$default = str_replace('_utf8', '', $CFG->lang);
$prompt = "Available languages:\n$langlist\nType language code or press Enter to use default value ($default)"; // TODO: localize, mark as needed in install
$error = '';
do {
echo $error;
$input = cli_input($prompt, $default);
$input = clean_param($input, PARAM_SAFEDIR);
if (!file_exists($CFG->dirroot.'/install/lang/'.$input.'_utf8')) {
$error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install
} else {
$error = '';
}
} while ($error !== '');
$CFG->lang = $input.'_utf8';
} else {
// already verified
}
//We need wwwroot before we test dataroot
$wwwroot = clean_param($options['wwwroot'], PARAM_URL);
$wwwroot = trim($wwwroot, '/');
if ($interactive) {
echo $separator;
if (strpos($wwwroot, 'http') === 0) {
$prompt = "Type URL of your site \nor press Enter to use default value ($wwwroot)"; // TODO: localize, mark as needed in install
} else {
$prompt = "Type URL of your site"; // TODO: localize, mark as needed in install
}
$error = '';
do {
echo $error;
$input = cli_input($prompt, $wwwroot);
$input = clean_param($input, PARAM_URL);
$input = trim($input, '/');
if (strpos($input, 'http') !== 0) {
$error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install
} else {
$error = '';
}
} while ($error !== '');
$wwwroot = $input;
} else {
if (strpos($wwwroot, 'http') !== 0) {
cli_error("Error:\n wwwroot parametr value \"$wwwroot\" in not correct. Please use different value."); // TODO: localize, mark as needed in install
}
}
$CFG->wwwroot = $wwwroot;
$CFG->httpswwwroot = $CFG->wwwroot;
$CFG->httpsthemewww = $CFG->wwwroot;
//We need dataroot before lang download
if ($interactive) {
echo $separator;
$i=0;
while(is_dataroot_insecure()) {
$parrent = dirname($CFG->dataroot);
$i++;
if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
$CFG->dataroot = ''; //can not find secure location for dataroot
break;
}
$CFG->dataroot = dirname($parrent).'/moodledata';
}
$error = '';
do {
if ($CFG->dataroot !== '') {
$prompt = "Type Moodle data directory \nor press Enter to use default value ($CFG->dataroot)"; // TODO: localize, mark as needed in install
} else {
$prompt = "Type Moodle data directory"; // TODO: localize, mark as needed in install
}
echo $error;
$CFG->dataroot = cli_input($prompt, $CFG->dataroot);
if ($CFG->dataroot === '') {
$error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install
} else if (is_dataroot_insecure()) {
$CFG->dataroot = '';
$error = "Directory may not be secure, please retry.\n"; // TODO: localize, mark as needed in install
} else {
if (make_upload_directory('lang', false)) {
$error = '';
} else {
$error = "Can not create dataroot directory, verify permissions or create directory manually.\n"; // TODO: localize, mark as needed in install
}
}
} while ($error !== '');
} else {
if (is_dataroot_insecure()) {
cli_error("Error:\n directory $CFG->dataroot may be directly accessible via web. Please use different directory."); // TODO: localize, mark as needed in install
}
}
//download lang pack with optional notification
if ($CFG->lang != 'en_utf8') {
if ($interactive) {
echo $separator;
echo "Downloading latest language package from moodle.org...\n"; // TODO: localize, mark as needed in install
}
if ($cd = new component_installer('http://download.moodle.org', 'lang16', $CFG->lang.'.zip', 'languages.md5', 'lang')) {
if ($cd->install() == COMPONENT_ERROR) {
if ($cd->get_error() == 'remotedownloaderror') {
$a = new stdClass();
$a->url = 'http://download.moodle.org/lang16/'.$CFG->lang.'.zip';
$a->dest = $CFG->dataroot.'/lang';
cli_problem(get_string($cd->get_error(), 'error', $a));
} else {
cli_problem(get_string($cd->get_error(), 'error'));
}
} else {
// install parent lang if defined
if ($parentlang = get_parent_language()) {
if ($cd = new component_installer('http://download.moodle.org', 'lang16', $parentlang.'.zip', 'languages.md5', 'lang')) {
$cd->install();
}
}
}
}
if ($interactive) {
echo "...finished lang download.\n"; // TODO: localize
}
}
unset($CFG->running_installer); // we use full lang packs from now on
// ask for db type - show only drivers available
if ($interactive) {
$options['dbtype'] = strtolower($options['dbtype']);
echo $separator;
echo "Available database drivers\n";
foreach ($databases as $type=>$database) {
echo " $type:".$database->get_name()."\n";
}
echo "\n";
if (!empty($databases[$options['dbtype']])) {
$prompt = "Type driver short name\nor press Enter to use default value (".$options['dbtype'].")"; // TODO: localize
} else {
$prompt = "Type driver short name"; // TODO: localize
}
$CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases));
} else {
if (empty($databases[$options['dbtype']])) {
cli_error("Error:\n dbtype parametr value \"".$options['dbtype']."\" in not correct. Please use different value."); // TODO: localize
}
$CFG->dbtype = $options['dbtype'];
}
$database = $databases[$CFG->dbtype];
// ask for db host
if ($interactive) {
echo $separator;
if ($options['dbhost'] !== '') {
$prompt = "Type database host\nor press Enter to use default value (".$options['dbhost'].")"; // TODO: localize
} else {
$prompt = "Type database host"; // TODO: localize
}
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
} else {
$CFG->dbhost = $options['dbhost'];
}
// ask for db name
if ($interactive) {
echo $separator;
if ($options['dbname'] !== '') {
$prompt = "Type database name\nor press Enter to use default value (".$options['dbname'].")"; // TODO: localize
} else {
$prompt = "Type database name"; // TODO: localize
}
$CFG->dbname = cli_input($prompt, $options['dbname']);
} else {
$CFG->dbname = $options['dbname'];
}
// ask for db prefix
if ($interactive) {
echo $separator;
//TODO: solve somehow the prefix trouble for oci
if ($options['prefix'] !== '') {
$prompt = "Type table prefix\nor press Enter to use default value (".$options['prefix'].")"; // TODO: localize
} else {
$prompt = "Type table prefix"; // TODO: localize
}
$CFG->prefix = cli_input($prompt, $options['prefix']);
} else {
$CFG->prefix = $options['prefix'];
}
// ask for db user
if ($interactive) {
echo $separator;
if ($options['dbuser'] !== '') {
$prompt = "Type database user name\nor press Enter to use default value (".$options['dbuser'].")"; // TODO: localize
} else {
$prompt = "Type database user name"; // TODO: localize
}
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
} else {
$CFG->dbuser = $options['dbuser'];
}
// ask for db password
if ($interactive) {
echo $separator;
do {
if ($options['dbpass'] !== '') {
$prompt = "Type database user password\nor press Enter to use default value (".$options['dbpass'].")"; // TODO: localize
} else {
$prompt = "Type database user password"; // TODO: localize
}
$CFG->dbpass = cli_input($prompt, $options['dbpass']);
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersit'=>0, 'dbsocket'=>$options['dbsocket']));
} while ($hint_database !== '');
} else {
$CFG->dbpass = $options['dbpass'];
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersit'=>0, 'dbsocket'=>$options['dbsocket']));
if ($hint_database !== '') {
cli_error('Can not open connection to database!');
}
}
// ask for admin user password
if ($interactive) {
echo $separator;
$prompt = "Type requested password for user 'admin'"; // TODO: localize
do {
$options['admin-password'] = cli_input($prompt);
} while (empty($options['admin-password']) or $options['admin-password'] === 'admin');
} else {
if (empty($options['admin-password']) or $options['admin-password'] === 'admin') {
cli_error('Requested administrator password must not be empty or easy to guess..'); //TODO: localize
}
}
if ($interactive) {
echo $separator;
if (!$options['agreelicense']) {
echo "Do you agree to Moodle license blah blah blah?\n"; //TODO: localize and use real license
$input = cli_input('Type yes or y if you agree, ctrl+c if not', '', array('yes', 'y')); // TODO: localize including yes/y
}
} else {
if (!$options['agreelicense']) {
cli_error('You must aggree to license by specifying --agreelicense'); //TODO: localize
}
}
// Finally we have all info needed for config.php
$configphp = install_generate_configphp($database, $CFG);
umask(0137);
if (($fh = fopen($configfile, 'w')) !== false) {
fwrite($fh, $configphp);
fclose($fh);
}
if (!file_exists($configfile)) {
cli_error('Can not create config file.');
} else if ($interactive) {
echo $separator;
echo "config.php created\n";
}
// return back to original dir before executing setup.php chich changes the dir again
chdir($olddir);
// We have config.php, it is a real php script from now on :-)
require($configfile);
// show as much debug as possible
@error_reporting(1023);
@ini_set('display_errors', '1');
$CFG->debug = 38911;
$CFG->debugdisplay = true;
$CFG->version = "";
$CFG->release = "";
// read $version adn $release
require($CFG->dirroot.'/version.php');
if ($DB->get_tables() ) {
cli_error('Database tables already present, cli installation can not continue.');
}
if (!$DB->setup_is_unicodedb()) {
if (!$DB->change_db_encoding()) {
// If could not convert successfully, throw error, and prevent installation
cli_error(get_string('unicoderequired', 'admin'));
}
}
if ($interactive) {
echo $separator;
echo get_string('databasesetup')."\n";
}
// install core
install_core($version, true);
set_config('release', $release);
// install all plugins types, local, etc.
upgrade_noncore(true);
// set up admin user password
$DB->set_field('user', 'password', hash_internal_user_password($options['admin-password'], array('username'=>'admin')));
// indicate that this site is fully configured
set_config('rolesactive', 1);
upgrade_finished();
// log in as admin - we need do anything when applying defaults
$admins = get_admins();
$admin = reset($admins);
session_set_user($admin);
message_set_default_message_preferences($admin);
// apply all default settings, do it twice to fill all defaults - some settings depend on other setting
admin_apply_default_settings(NULL, true);
admin_apply_default_settings(NULL, true);
set_config('registerauth', '');
echo "yay!!!\n";
exit(0); // 0 means success

View File

@ -0,0 +1,85 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script allows you to reset any local user password.
*
* @package moodlecore
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (isset($_SERVER['REMOTE_ADDR'])) {
error_log("admin/cli/upgrade.php can not be called from web server!");
exit;
}
require_once dirname(dirname(dirname(__FILE__))).'/config.php';
require_once($CFG->libdir.'/clilib.php'); // cli only functions
// now get cli options
list($options, $unrecognized) = cli_get_params(array('help'=>false),
array('h'=>'help'));
$interactive = empty($options['non-interactive']);
if ($unrecognized) {
$error = implode("\n ", $unrecognized);
cli_error("Unrecognized options:\n $error \n. Please use --help option."); // TODO: localize
}
if ($options['help']) {
$help =
"Reset local user passwords, useful especially for admin acounts.
There are no security checks here because anybody who is able to
execute this file may execute any PHP too.
Options:
-h, --help Print out this help
Example: \$sudo -u wwwrun /usr/bin/php admin/cli/reset_password.php
"; //TODO: localize
echo $help;
die;
}
$prompt = "Password reset - enter username (manual authentication only)"; // TODO: localize
$username = cli_input($prompt);
if (!$user = $DB->get_record('user', array('auth'=>'manual', 'username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id))) {
cli_error("Can not find user '$username'");
}
$prompt = "Enter new password"; // TODO: localize
$password = cli_input($prompt);
$errmsg = '';//prevent eclipse warning
if (!check_password_policy($password, $errmsg)) {
cli_error($errmsg);
}
$hashedpassword = hash_internal_user_password($password);
$DB->set_field('user', 'password', $hashedpassword, array('id'=>$user->id));
echo "yay!\n";
exit(0); // 0 means success

109
admin/cli/upgrade.php Normal file
View File

@ -0,0 +1,109 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script creates config.php file and prepares database.
*
* This script is not intended for beginners!
* Potential problems:
* - environment check is not present yet
* - su to apache account or sudo before execution
* - not compatible with Windows platform
*
* @package moodlecore
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (isset($_SERVER['REMOTE_ADDR'])) {
error_log("admin/cli/upgrade.php can not be called from web server!");
exit;
}
require_once dirname(dirname(dirname(__FILE__))).'/config.php';
require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions
require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions
require_once($CFG->libdir.'/clilib.php'); // cli only functions
// now get cli options
list($options, $unrecognized) = cli_get_params(array('non-interactive'=>false, 'help'=>false),
array('h'=>'help'));
$interactive = empty($options['non-interactive']);
if ($unrecognized) {
$error = implode("\n ", $unrecognized);
cli_error("Unrecognized options:\n $error \n. Please use --help option."); // TODO: localize
}
if ($options['help']) {
$help =
"Command line Moodle upgrade.
Please note you must execute this script with the same uid as apache!
Site defaults may be changed via local/defaults.php.
Options:
--non-interactive No interactive questions or confirmations
-h, --help Print out this help
Example: \$sudo -u wwwrun /usr/bin/php admin/cli/upgrade.php
"; //TODO: localize
echo $help;
die;
}
if (empty($CFG->version)) {
cli_error('missingconfigversion', 'debug');
}
require("$CFG->dirroot/version.php"); // defines $version and $release
$CFG->target_release = $release; // used during installation and upgrades
if ($version < $CFG->version) {
cli_error('The code you are using is OLDER than the version that made these databases!'); // TODO: localize
}
if ($interactive) {
$prompt = "Do you really want to upgrade Moodle at '$CFG->wwwroot' from '$CFG->release' to '$release'?\nPress ctrl+c to cancel."; // TODO: localize
cli_input($prompt);
}
if ($version > $CFG->version) {
upgrade_core($version, true);
}
set_config('release', $release);
// uncoditionally upgrade
upgrade_noncore(true);
// log in as admin - we need doanything permission when applying defaults
$admins = get_admins();
$admin = reset($admins);
session_set_user($admin);
// apply all default settings, just in case do it twice to fill all defaults
admin_apply_default_settings(NULL, true);
admin_apply_default_settings(NULL, true);
echo "yay!\n";
exit(0); // 0 means success

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
@ -10,570 +11,136 @@
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI support functions
* Command line utility functions and classes
*
* @package moodlecore
* @copyright Dilan
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package moodlecore
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* include PEAR Console libraries
* Get input from user
* @param string $prompt text prompt, should include possible obptions
* @param string $default default value when enter pressed
* @param array $options list of allowed options, empty means any text
* @param bool $casesensitive true if options are case sensitive
* @return string entered text
*/
set_include_path($CFG->libdir . PATH_SEPARATOR . $CFG->libdir . '/pear/');
require_once('Console/Getopt.php');
/**
* Check the validity of the language
* return true or false
*
* @global array
* @param string $lang (short code for language)
* @return bool true/false
*/
function valid_language($lang) {
global $DEFAULT;
$langdir = dir($DEFAULT['dirroot'].'/install/lang');
$i=0;
$validllangs = array();
while (false !== ($file=$langdir->read())) {
if ($file[0] != '.' ) {
$validllangs[$i++]=$file;
function cli_input($prompt, $default='', array $options=null, $casesensitiveoptions=false) {
echo $prompt;
echo "\n: ";
$input = fread(STDIN, 2048);
$input = trim($input);
if ($input === '') {
$input = $default;
}
if ($options) {
if (!$casesensitiveoptions) {
$input = strtolower($input);
}
if (!in_array($input, $options)) {
echo "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install
return cli_input($prompt, $default, $options, $casesensitiveoptions);
}
}
if (in_array($lang,$validllangs)) {
return true;
} else {
return false;
}
}
//========================================================================================//
/**
* Read from array of language strings and return a array of string elements in which
* both values and keys are set to input array's key
*
* @param array $lang string elements
* @return array of string element
*/
function get_short_codes ($lang = array()) {
$short_codes = array();
foreach ($lang as $key => $value) {
$short_codes[$key] = $key;
}
return $short_codes;
}
//========================================================================================//
/**
* Check value for valid yes/no argument
* Return true or false
*
* @param string $value
* @return bool true/false
*/
function valid_yes_no($value){
$valid=array('yes','y','n','no');
$value=strtolower($value);
if (in_array($value,$valid)) {
if ($value[0]=='y') {
return true;
} else if ($value[0]=='n') {
return true;
}
} else {
return false;
}
}
//========================================================================================//
/**
* Can value have a valid integer in the given range
* Return true or false
* @link valid_param()
*
* @uses PARAM_INT
* @param mixed $value
* @param int $start
* @param int $end
* @return bool true/false
*/
function valid_int_range($value,$start,$end) {
if (valid_param($value,PARAM_INT)) {
if ($value < $end && $value > $start) {
return true;
} else {
return false;
}
}
}
/**
* Take a value and and check it with the given set of values
* If value if found in the set return true. False otherwise
*
* @param mixed $value
* @param array $set of valid elements
* @return boolean
*/
function valid_element($value,$set) {
if(!empty($set)) {
//convert all the elements from set to lower case
foreach ($set as $key=>$opt) {
$set[$key]=strtolower($opt);
}
$value=strtolower($value);
if (in_array($value,$set)) {
return true;
} else {
return false;
}
}
}
/**
* Take a value and Type of the value
* If value match the type return true, false otherwise
* uses {@link clean_param()} in moodlelib.php
*
* @param mixed $value
* @param int $type
* @return boolean
*/
function valid_param($value,$type){
$clean_val = clean_param($value,$type);
if ($clean_val == $value) {
return true;
}else {
return false;
}
}
//========================================================================================//
/**
* Creat long arument list for PEAR method invocation using LONGOPTOIN array
*
* @uses CLI_VAL_REQ
* @uses CLI_VAL_OPT
* @param array $long_opt long option array $long_opt
* @return PEAR method compatible long option array
*/
function create_long_options($long_opt) {
$opt=array();
$i=0;
if (is_array($long_opt)) {
foreach ($long_opt as $key=>$value) {
if ($value == CLI_VAL_REQ) {
$opt[$i++]=$key.'=';
} else if ($value == CLI_VAL_OPT) {
$opt[$i++]=$key.'==';
}
}
}
return $opt;
}
//========================================================================================//
/**
* This funtion return an array of options with option as key containing the value of
* respective option
*
* @global array
* @param array of option arguments as defined by PEAR GetOpt calss $opt
* @return return a options arguments with options as keys and values as respective value for key
*/
function get_options($opt=array()) {
global $LONG_OPTIONS;
$ret_arr=array();
//get the options from the defined list of arguments
if (!empty($opt[0]) && is_array($opt[0])) {
foreach ($opt[0] as $key=>$value) {
if (substr($value[0],0,2)=='--') { //if the argument is a long option
$input_option=substr($value[0],2);
} else if (substr($value[0],0,1)=='-'){ //if the argument is a short option
$input_option=substr($value[0],1);
}
//check with valid set of options
if (in_array($input_option,$LONG_OPTIONS)) {
$ret_arr[$input_option]=$value[1];
}
}
}
//return array
return $ret_arr;
}
//========================================================================================//
//=========================================================================//
/**
* Validate options values
*
* @uses CLI_FULL
* @uses CLI_NO
* @param array $options
*/
function validate_option_values($options){
$values=array();
$i=0;
foreach ($options as $val) {
$values[$i++]=$val;
}
if (isset($values['lang'])) {
if (!valid_language($values['lang'])) {
console_write_error('invalidvalueforlanguage');
console_write( "\n", '', false);
}
}
if (isset($values['webdir'])) {
/**
* @todo check valid directory path
*/
}
if (isset($values['webaddr'])) {
/**
* @todo check valid http url
*/
}
if (isset($values['moodledir'])) {
/**
* @todo check valid directory path
*/
}
if (isset($values['datadir'])) {
/**
* @todo check valid directory path
*/
}
if (isset($values['dbtype'])) {
$dbtypes=array('mysql','oci8po','postgres7','mssql','mssql_n','odbc_mssql');
if (!in_array($values['dbtype'],$dbtypes)) {
console_write_error('invaliddbtype');
}
}
if (isset($values['dbhost'])) {
/**
* @todo check host?
*/
}
if (isset($values['dbname'])) {
/**
* @todo check name for valid ones if required
*/
}
if (isset($values['dbuser'])) {
/**
* @todo check validity of db user if required
*/
}
if (isset($values['dbpass'])) {
/**
* @todo check validity of database password if required
*/
}
if (isset($values['prefix'])) {
/**
* @todo check for valid prefix
*/
}
if (isset($values['sitefullname'])) {
/**
* @todo check for valid fullname for site
*/
}
if (isset($values['siteshortname'])) {
/**
* @todo check for valid short name for site
*/
}
if (isset($values['sitesummary'])) {
/**
* @todo check for valid summary
*/
}
if (isset($values['sitenewsitems'])) {
/**
* @todo check for valid news items
*/
}
if (isset($values['adminfirstname'])) {
/**
* @todo check for valid admin first name
*/
}
if (isset($values['adminlastname'])) {
/**
* @todo check for valid last name
*/
}
if (isset($values['adminusername'])) {
/**
* @todo check for valid username
*/
}
if (isset($values['adminpassword'])) {
/**
* @todo check for valid password
*/
}
if (isset($values['adminemail'])) {
/**
* @todo check for valid email
*/
}
if (isset($values['verbose'])) {
if(!valid_int_range($values['verbose'],CLI_NO,CLI_FULL)){
console_write_error('invalidverbosevalue');
}
}
if (isset($values['interactivelevel'])) {
if(!valid_int_range($values['verbose'],CLI_NO,CLI_FULL)){
console_write_error('invalidinteractivevalue');
}
}
if (isset($values['help'])) {
/**
* @todo nothing really
*/
}
}
//=========================================================================//
/**
* Read a mixed type
*
* @param stream $from
* @param int $size
* @return mixed type
*/
function read($from=STDIN,$size=1024) {
$input= trim(fread($from,$size));
return $input;
}
/**
* Read an integer
*
* @uses PARAM_INT
* @return integer
* Returns cli script parameters.
* @param array $longoptions array of --style options ex:('verbose'=>false)
* @param array $shortmapping array describing mapping of short to long style options ex:('h'=>'help', 'v'=>'verbose')
* @return array array of arrays, options, unrecognised as optionlongname=>value
*/
function read_int() {
$input=read();
if (valid_param($input,PARAM_INT)) {
return $input;
} else {
console_write_error('invalidint');
console_write( "\n", '', false);
function cli_get_params(array $longoptions, array $shortmapping=null) {
$shortmapping = (array)$shortmapping;
$options = array();
$unrecognized = array();
if (empty($_SERVER['argv'])) {
// bad luck, we can continue in interactive mode ;-)
return array($options, $unrecognized);
}
}
//=========================================================================//
/**
* Read and integer value within range
*
* @param int $start
* @param int $end
* @return int
*/
function read_int_range($start,$end) {
$input=read_int();
if (valid_int_range($input,$start,$end)) {
return $input;
} else {
console_write_error('invalidintrange');
console_write( "\n", '', false);
$rawoptions = $_SERVER['argv'];
//remove anything after '--', options can not be there
if (($key = array_search('--', $rawoptions)) !== false) {
$rawoptions = array_slice($rawoptions, 0, $key);
}
}
//=========================================================================//
/**
* Read yes/no argument
*
* @return string|void yes/no or void
*/
function read_yes_no() {
$input=strtolower(read());
if (valid_yes_no($input)) {
if ($input[0]=='y') {
return 'yes';
} else if($input[0]=='n') {
return 'no';
}
} else {
console_write_error('invalidyesno');
console_write( "\n", '', false);
}
}
//remove script
unset($rawoptions[0]);
foreach ($rawoptions as $raw) {
if (substr($raw, 0, 2) === '--') {
$value = substr($raw, 2);
$parts = explode('=', $value);
if (count($parts) == 1) {
$key = reset($parts);
$value = true;
} else {
$key = array_shift($parts);
$value = implode('=', $parts);
}
if (array_key_exists($key, $longoptions)) {
$options[$key] = $value;
} else {
$unrecognized[] = $raw;
}
//=========================================================================//
/**
* Read a boolean parameter from the input
*
* @uses PARAM_BOOL
* @return boolean
*/
function read_boolean(){
$input=read_yes_no();
return clean_param($input,PARAM_BOOL);
}
//=========================================================================//
/**
* Reading an element from a given set
*
* @param mixed array $set
* @return mixed
*/
function read_element($set=array()) {
$input=read();
if (valid_element($input,$set)) {
return $input;
} else {
console_write_error('invalidsetelement');
console_write( "\n", '', false);
}
}
//=========================================================================//
/**
* Read URL
*
* @uses PARAM_URL
* @return mixed
*/
function read_url() {
$input = read();
$localhost = false;
if ( strpos($input,'localhost') !== false) {
$input = str_replace('localhost','127.0.0.1',$input);
$localhost=true;
}
if (valid_param($input,PARAM_URL)) {
if ($localhost) {
return str_replace('127.0.0.1','localhost',$input);
} else {
return $input;
}
} else {
console_write_error('invalidurl');
}
}
//=========================================================================//
/**
* Enter description here...
* @todo Document this function
* @return string
*/
function read_dir() {
$input = read();
return $input;
}
//===========================================================================//
/**
* Print compatibility message to standard out, and errors to standard error
*
* @param boolean $success
* @param string $testtext
* @param string $errormessage
* @param boolean $caution
* @param boolean $silent
* @return boolean
*/
function check_compatibility($success, $testtext,$errormessage,$caution=false,$silent=false) {
if ($success) {
if (!$silent) {
console_write(get_string('pass', 'install'),'',false);
}
} else {
if ($caution) {
if (!$silent) {
console_write(get_string('caution', 'install'),'',false);
} else if (substr($raw, 0, 1) === '-') {
$value = substr($raw, 1);
$parts = explode('=', $value);
if (count($parts) == 1) {
$key = reset($parts);
$value = true;
} else {
$key = array_shift($parts);
$value = implode('=', $parts);
}
if (array_key_exists($key, $shortmapping)) {
$options[$shortmapping[$key]] = $value;
} else {
$unrecognized[] = $raw;
}
} else {
console_write(get_string('fail', 'install'),'',false);
console_write_error($errormessage,'',false);
$unrecognized[] = $raw;
continue;
}
}
if (!$silent) {
console_write("\t\t",'',false);
console_write($testtext,'',false);
console_write("\n",'',false);
}
return $success;
}
//==========================================================================//
/**
* Print environment status to standard out
*
* @param array $env of type object
*/
function print_environment_status($env = array()) {
console_write( get_string('name') . "\t\t\t" . get_string('info') . "\t" . get_string('status') . "\n\r", '', false);
//console_write("Status\t\tInfo\t\tPart\n\r",'',false);
foreach ( $env as $object) {
console_write($object->part,'',false);
console_write("\t\t",'',false);
if (!empty($object->info)) {
console_write( $object->info, '', false);
} else {
console_write( "\t", '', false);
//apply defaults
foreach ($longoptions as $key=>$default) {
if (!array_key_exists($key, $options)) {
$options[$key] = $default;
}
console_write( "\t\t", '', false);
if ($object->status == 1 ) {
console_write('ok','',false);
} else {
console_write('fail','',false);
}
console_write("\n\r",'',false);
}
// finished
return array($options, $unrecognized);
}
/**
* Print environment status to standard out
*
* @param array $env of type object
* Write error notification
* @param $text
* @return void
*/
function print_environment_status_detailed($env = array()) {
console_write("Status\t\tLevel\t\tCurrent ver\tRequired ver\t\tPart\t\tInfo\n\r",'',false);
foreach ( $env as $object) {
if ($object->status == 1 ) {
console_write('ok ','',false);
} else if ($object->errorcode != 0) {
console_write('fail ','',false);
} else {
console_write('----','',false);
}
console_write("\t\t",'',false);
console_write($object->level,'',false);
console_write("\t\t",'',false);
console_write($object->current_version,'',false);
console_write("\t",'',false);
console_write($object->needed_version,'',false);
console_write("\t\t",'',false);
console_write($object->part,'',false);
console_write("\t\t",'',false);
console_write($object->info,'',false);
console_write("\n\r",'',false);
}
function cli_problem($text) {
fwrite(STDERR, $text, "\n");
}
/**
* Print a new line in the standard output
* Write to standard out and error with exit in error.
*
* @param string $text
* @param int $errorcode
* @return void (does not return)
*/
function print_newline() {
console_write( "\n", '', false);
function cli_error($text, $errorcode=1) {
fwrite(STDERR, $text);
fwrite(STDERR, "\n");
die($errorcode);
}
?>