From b15461d1d0c8ca616150e44d72c295a07cebbdcb Mon Sep 17 00:00:00 2001 From: jmontoyaa Date: Thu, 7 Apr 2016 16:14:39 +0200 Subject: [PATCH] Some fixes in the vchamilo plugin --- plugin/vchamilo/install.php | 24 +- plugin/vchamilo/lib.php | 560 ++++++++++++++++-- plugin/vchamilo/plugin.php | 13 +- .../views/editinstance.controller.php | 50 +- plugin/vchamilo/views/editinstance.php | 31 +- plugin/vchamilo/views/editinstance_form.php | 344 ++++++++++- plugin/vchamilo/views/manage.php | 24 +- 7 files changed, 903 insertions(+), 143 deletions(-) diff --git a/plugin/vchamilo/install.php b/plugin/vchamilo/install.php index 28c3907eff..27e95fe7cc 100644 --- a/plugin/vchamilo/install.php +++ b/plugin/vchamilo/install.php @@ -1,18 +1,18 @@ execute_sql($sql)){ + Database::query($sql); + /*if(!$DB->execute_sql($sql)){ print_error('noexecutionfor','block_vmoodle', $sql); return false; - } + }*/ } return true; @@ -257,7 +258,7 @@ function vchamilo_create_databases($vchamilo, $cnx = null) { /** * get a proper SQLdump command * @param object $vmoodledata the complete new host information -* @return string the shell command +* @return string the shell command */ function vchamilo_get_database_dump_cmd($vchamilodata){ global $CFG; @@ -309,7 +310,7 @@ function vchamilo_load_db_template($vchamilo, $dbtemplate, $template){ $absolute_templatesdir = $_configuration['root_sys'].$templatefoldername; $relative_datadir = $templatefoldername.$separator.$template.'_sql'; $absolute_datadir = $_configuration['root_sys'].$relative_datadir; - + $filerad = preg_replace('/_database$/', '', $dbtemplate); $sqlfile = 'chamilo_master_'.$filerad.'.sql'; @@ -326,7 +327,7 @@ function vchamilo_load_db_template($vchamilo, $dbtemplate, $template){ ctrace("load_database_from_dump : executing feeding sql as \n $import "); if (!defined('CLI_SCRIPT')){ - putenv('LANG=en_US.utf-8'); + putenv('LANG=en_US.utf-8'); } // ensure utf8 is correctly handled by php exec() // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input @@ -353,7 +354,7 @@ function vchamilo_execute_db_sql(&$vchamilo, $bulkfile, $cnx = null, $vars=null, $erroritems[] = $erroritem; return $erroritem; } - + $local_cnx = 0; if (is_null($cnx)){ $cnx = vchamilo_make_connection($vchamilo, true); @@ -412,7 +413,7 @@ function vchamilo_execute_db_sql(&$vchamilo, $bulkfile, $cnx = null, $vars=null, if ($local_cnx){ vchamilo_close_connection($vchamilo, $cnx); } - + if (!empty($erroritems)){ return $erroritems; } @@ -439,7 +440,7 @@ function vchamilo_dump_databases($vchamilo, $outputfilerad){ // By default, empty password. $pass = ''; $pgm = null; - + if (empty($port)){ $port = 3306; } @@ -479,7 +480,7 @@ function vchamilo_dump_databases($vchamilo, $outputfilerad){ $cmds[] = $cmd_user . ' > ' . escapeshellarg($outputfilerad.'_user_personal.sql'); } } - + $mysqldumpcmd = vchamilo_get_config('vchamilo', 'cmd_mysqldump', true); $pgm = (!empty($mysqldumpcmd)) ? stripslashes($mysqldumpcmd) : false ; @@ -510,7 +511,7 @@ function vchamilo_dump_databases($vchamilo, $outputfilerad){ if ($LOG = fopen(dirname($outputfilerad).'/cmd.log', 'a')){ fwrite($LOG, $cmd."\n"); } - + // Executes the SQL command. exec($cmd, $execoutput, $returnvalue); if ($LOG){ @@ -551,12 +552,9 @@ function vchamilo_make_this(){ $thischamilo->db_user = $_configuration['db_user']; $thischamilo->db_password = $_configuration['db_password']; $thischamilo->db_prefix = $_configuration['db_prefix']; - $thischamilo->main_database = $_configuration['main_databse']; - $thischamilo->statistics_database = $_configuration['statistics_databse']; - $thischamilo->user_personal_database = $_configuration['user_personal_databse']; + $thischamilo->main_database = $_configuration['main_database']; ; $thischamilo->table_prefix = $_configuration['table_prefix']; - $thischamilo->single_database = $_configuration['single_database']; - $thischamilo->tracking_enabled = $_configuration['tracking_enabled']; + return $thischamilo; } @@ -606,30 +604,33 @@ function vchamilo_print_error($errortrace, $return = false){ $str .= ''; $str .= ''; } - + if ($return) return $str; echo $str; } /** * this function set will map standard moodle API calls to chamilo -* internal primitives. This avoids too many changes to do in imported +* internal primitives. This avoids too many changes to do in imported * code * */ -function vchamilo_get_config($module, $key, $isplugin = true){ - global $_configuration, $DB; - - if ($isplugin){ +function vchamilo_get_config($module, $key, $isplugin = true) +{ + if ($isplugin) { $key = $module.'_'.$key; } - if($configrec = $DB->get_record(TABLE_MAIN_SETTINGS_CURRENT, array('variable' => $key, 'subkey' => $module))){ - return $configrec->selected_value; + + $params = array('variable = ? AND subkey = ?' => [$key, $module]); + $result = api_get_settings_params_simple($params); + if ($result) { + return $result['selected_value']; } return false; } -function vchamilo_load_files_from_template($vchamilo, $template){ +function vchamilo_load_files_from_template($vchamilo, $template) +{ global $_configuration; // Make template directory (files and SQL). @@ -646,12 +647,12 @@ function vchamilo_load_files_from_template($vchamilo, $template){ $vcoursepath = api_get_path(TO_SYS, SYS_COURSE_PATH, (array)$vchamilo); $vhomepath = api_get_path(TO_SYS, SYS_HOME_PATH, (array)$vchamilo); $varchivepath = api_get_path(TO_SYS, SYS_ARCHIVE_PATH, (array)$vchamilo); - + echo "archiveapth : $varchivepath"; // Rename some dirs top match instance requirements $manifest = vchamilo_get_vmanifest($template); - + // get the protocol free hostname $originarchivedir = preg_replace('/https?:\/\//', '', $manifest->templatewwwroot); $originhomedir = preg_replace('/https?:\/\//', '', $manifest->templatewwwroot); @@ -663,10 +664,10 @@ function vchamilo_load_files_from_template($vchamilo, $template){ copyDirContentTo(chop_last_slash($absolute_template_datadir.'/'.$manifest->coursefolder), chop_last_slash($vcoursepath), false); copyDirContentTo(chop_last_slash($absolute_template_datadir.'/archive/'.$originarchivedir), chop_last_slash($varchivepath), false); copyDirContentTo(chop_last_slash($absolute_template_datadir.'/home/'.$originhomedir), chop_last_slash($vhomepath), false); - } -function chop_last_slash($path){ +function chop_last_slash($path) +{ return preg_replace('/\/$/', '', $path); } @@ -718,3 +719,496 @@ function copyDirContentTo($source, $destination, $move = true) { } } + + +// from moot + + +define('PARAM_BOOL', 1); +define('PARAM_INT', 2); +define('PARAM_TEXT', 3); +define('PARAM_RAW', 4); + +/** + * this function set will map standard moodle API calls to chamilo + * internal primitives. This avoids too many changes to do in imported + * code + * + */ +function get_config($module, $key = false, $isplugin = true) { + global $_configuration, $DB; + static $static_settings; + + if (!isset($static_settings)) { + include_once $_configuration['root_sys'].'local/ent_installer/static_settings.php'; + } + + if ($isplugin){ + $configkey = $module.'_'.$key; + } else { + $configkey = $key; + } + + if ($module == 'ent_installer') { + $dyna_setting = $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('subkey' => 'ent_installer', 'variable' => $configkey)); + if (!is_null($dyna_setting)) { + return $dyna_setting; + } + + if(empty($config)){ + ctrace("Wrap to static setting $module,$configkey "); + if (array_key_exists($key, $static_settings)){ + return $static_settings[$key]; + } + } + } else { + if (!$module) { + return $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('variable' => $configkey)); + } + if ($key) { + return $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('variable' => $configkey, 'subkey' => $module)); + } else { + // Get all config from a subkey as an object + $configs = $DB->get_records(TABLE_MAIN_SETTINGS_CURRENT, array('subkey' => $module)); + if (!empty($configs)) { + $config = new StdClass; + foreach ($configs as $cf) { + $key = str_replace($module.'_', '', $cf->variable); + $config->$key = $cf->selected_value; + } + return $config; + } + return null; + } + } +} + +function set_config($key, $value, $module, $isplugin = false) { + + if ($isplugin) { + $key = $module.'_'.$key; + } + + if ($isplugin) { + // ensure setting is actually in database + api_update_setting($value, $key, $module); + } else { + api_update_setting($value, $module, $key); + } +} + +/** + * gets a string from a component + * + */ +function get_string($key, $component = 'local_ent_installer', $a = ''){ + global $_configuration; + static $strings; + static $fallbackstrings; + + if ($component == 'local_ent_installer') { + $fallbackpath = $_configuration['root_sys'].'local/ent_installer/lang/english/local_ent_installer.php'; + + if (!isset($strings)) { + $lang = api_get_language_from_type('platform_lang'); + if (empty($lang)) $lang = 'english'; + $path = $_configuration['root_sys'].'local/ent_installer/lang/'.$lang.'/local_ent_installer.php'; + + if (!file_exists($path)) { + if (!file_exists($path)) { + print_error('missinglang', null); + die; + } + + if (!isset($fallbackstrings)) { + include $fallbackpath; + $fallbackstrings = $string; + } + } + + include $path; + $strings = $string; + } + + if (!array_key_exists($key, $strings)) { + if (!isset($fallbackstrings)) { + include $fallbackpath; + $fallbackstrings = $string; + } + if (!array_key_exists($key, $fallbackstrings)) { + return "[[$key]]"; + } + if (is_scalar($a)) { + return str_replace('{$a}', $a, $fallbackstrings[$key]); + } + if (is_array($a)) { + $a = (object)$a; + } + if (is_object($a)) { + return replace_string_vars($a, $fallbackstrings[$key]); + } + debugging('String insertion not supported', 1); + die; + } + + if (is_scalar($a)) { + return str_replace('{$a}', $a, $strings[$key]); + } + if (is_array($a)){ + $a = (object)$a; + } + if (is_object($a)){ + return replace_string_vars($a, $strings[$key]); + } + debugging('String insertion not supported', 1); + die; + } else { + return get_lang($key); + } +} + +function replace_string_vars($a, $str){ + preg_match_all('/{\$a-\>(.+?)}/', $str, $matches); + if (!empty($matches[1])){ + foreach($matches[1] as $replacekey){ + $str = str_replace('{$a->'.$replacekey.'}', $a->$replacekey, $str); + } + } + return $str; +} + +function print_error($key, $component = '', $passthru = false, $extrainfo = ''){ + global $debuglevel; + global $debugdisplay; + + if ($component === null){ + $str = $key; + } else { + $str = get_string($string, $component); + } + ctrace('ERROR: '. $str); + if (!empty($extrainfo)){ + ctrace('Extra: '. $extrainfo); + } + if ($debugdisplay >= 3){ + debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + } + if (!$passthru) die; +} + +function debugging($message, $level) { + global $debuglevel; + global $debugdisplay; + + if ($level <= $debuglevel) { + ctrace('DEBUG: '.$message); + if ($debugdisplay >= 3){ + debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + } + } +} + +/** + * Wrap moodle to chamilo side + * + */ +function mtrace($message){ + ctrace($message); +} + +function ctrace($str) { + if (!defined('CLI_SCRIPT')) echo "
";
+    echo $str;
+    if (!defined('CLI_SCRIPT')) echo "
"; +} + +/** + * Sets a platform configuration setting to a given value, creating it if necessary + * @param string The value we want to record + * @param string The variable name we want to insert + * @param string The subkey for the variable we want to insert + * @param string The type for the variable we want to insert + * @param string The category for the variable we want to insert + * @param string The title + * @param string The comment + * @param string The scope + * @param string The subkey text + * @param int The access_url for which this parameter is valid + * @param int The changeability of this setting for non-master urls + * @return boolean true on success, false on failure + */ +function api_update_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) { + global $_setting; + + if (empty($var) || !isset($val)) { + return false; + } + + $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); + $var = Database::escape_string($var); + $val = Database::escape_string($val); + $a = (int) $a; + + if (empty($a)) { $a = 1; } + + // Check if this variable doesn't exist already + $select = "SELECT id FROM $t_settings WHERE variable = '$var' "; + + if (!empty($sk)) { + $sk = Database::escape_string($sk); + $select .= " AND subkey = '$sk'"; + } + + if ($a > 1) { + $select .= " AND access_url = $a"; + } else { + $select .= " AND access_url = 1 "; + } + + $res = Database::query($select); + if (Database::num_rows($res) > 0) { // Found item for this access_url. + $row = Database::fetch_array($res); + // update value + $update['selected_value'] = $val; + Database::update($t_settings, $update, array('id = ?' => $row['id'])); + return $row['id']; + + // update in memory setting value + $_setting[$var][$sk] = $val; + } + + // Item not found for this access_url, we have to check if the whole thing is missing + // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1 + $insert = "INSERT INTO $t_settings " . + "(variable,selected_value," . + "type,category," . + "subkey,title," . + "comment,scope," . + "subkeytext,access_url,access_url_changeable)" . + " VALUES ('$var','$val',"; + if (isset($type)) { + $type = Database::escape_string($type); + $insert .= "'$type',"; + } else { + $insert .= "NULL,"; + } + if (isset($c)) { // Category + $c = Database::escape_string($c); + $insert .= "'$c',"; + } else { + $insert .= "NULL,"; + } + if (isset($sk)) { // Subkey + $sk = Database::escape_string($sk); + $insert .= "'$sk',"; + } else { + $insert .= "NULL,"; + } + if (isset($title)) { // Title + $title = Database::escape_string($title); + $insert .= "'$title',"; + } else { + $insert .= "NULL,"; + } + if (isset($com)) { // Comment + $com = Database::escape_string($com); + $insert .= "'$com',"; + } else { + $insert .= "NULL,"; + } + if (isset($sc)) { // Scope + $sc = Database::escape_string($sc); + $insert .= "'$sc',"; + } else { + $insert .= "NULL,"; + } + if (isset($skt)) { // Subkey text + $skt = Database::escape_string($skt); + $insert .= "'$skt',"; + } else { + $insert .= "NULL,"; + } + $insert .= "$a,$v)"; + $res = Database::query($insert); + + // update in memory setting value + $_setting[$var][$sk] = $value; + + return $res; +} + +/** + * converts a timestamp to sql tms + * @param lint $time a unix timestamp + */ +function make_tms($time) { + $tms = date('Y-m-d H:i:s', $time); + return $tms; +} + +/** + * Makes sure the data is using valid utf8, invalid characters are discarded. + * + * Note: this function is not intended for full objects with methods and private properties. + * + * @param mixed $value + * @return mixed with proper utf-8 encoding + */ +function fix_utf8($value) { + if (is_null($value) or $value === '') { + return $value; + + } else if (is_string($value)) { + if ((string)(int)$value === $value) { + // shortcut + return $value; + } + + // Lower error reporting because glibc throws bogus notices. + $olderror = error_reporting(); + if ($olderror & E_NOTICE) { + error_reporting($olderror ^ E_NOTICE); + } + + // Note: this duplicates min_fix_utf8() intentionally. + static $buggyiconv = null; + if ($buggyiconv === null) { + $buggyiconv = (!function_exists('iconv') or iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'\80') !== '100\80'); + } + + if ($buggyiconv) { + if (function_exists('mb_convert_encoding')) { + $subst = mb_substitute_character(); + mb_substitute_character(''); + $result = mb_convert_encoding($value, 'utf-8', 'utf-8'); + mb_substitute_character($subst); + + } else { + // Warn admins on admin/index.php page. + $result = $value; + } + + } else { + $result = iconv('UTF-8', 'UTF-8//IGNORE', $value); + } + + if ($olderror & E_NOTICE) { + error_reporting($olderror); + } + + return $result; + + } else if (is_array($value)) { + foreach ($value as $k=>$v) { + $value[$k] = fix_utf8($v); + } + return $value; + + } else if (is_object($value)) { + $value = clone($value); // do not modify original + foreach ($value as $k=>$v) { + $value->$k = fix_utf8($v); + } + return $value; + + } else { + // this is some other type, no utf-8 here + return $value; + } +} + +function print_object($obj) { + echo '
';
+    print_r($obj);
+    echo '
'; +} + +function require_js($file, $component, $return = false) { + global $_configuration, $htmlHeadXtra; + + if (preg_match('/^local_/', $component)) { + $component = str_replace('local_', '', $component); + $path = 'local/'; + } else { + $path = 'plugin/'; + } + + // Secure the postslashing of the roots. + $root_web = $_configuration['root_web'].'/'; + $root_web = preg_replace('#//$#', '/', $root_web); + + $str = ''."\n"; + if ($return === 'head') { + $htmlHeadXtra[] = $str; + } + if ($return) { + return $str; + } + echo $str; +} + +function require_css($file, $component, $return = false) { + global $_configuration, $htmlHeadXtra; + + if (preg_match('/^local_/', $component)) { + $component = str_replace('local_', '', $component); + $path = 'local/'; + } else { + $path = 'plugin/'; + } + + // Secure the postslashing of the roots. + $root_web = $_configuration['root_web'].'/'; + $root_web = preg_replace('#//$#', '/', $root_web); + + $str = ''."\n"; + if ($return === 'head') { + $htmlHeadXtra[] = $str; + } + if ($return) { + return $str; + } + echo $str; +} + +/** + * + */ +function required_param($key, $type = 0) { + if (array_key_exists($key, $_REQUEST)) { + $value = $_REQUEST[$key]; + $value = param_filter_type($value, $type); + return $value; + } + die("Missing expected param $key in request input"); +} + +function optional_param($key, $default, $type = 0) { + if (array_key_exists($key, $_REQUEST)) { + $value = $_REQUEST[$key]; + $value = param_filter_type($value, $type); + return $value; + } + return $default; +} + +function param_filter_type($value, $type) { + switch($type) { + case 0: + return $value; // no filtering + case PARAM_BOOL: + return $value == 0; // forces outputing boolean + case PARAM_INT: + if (preg_match('/^([1-90]+)/', $value, $matches)) { + return $matches[1]; + } + return 0; + case PARAM_TEXT: + // TODO more filtering here + return $value; + } +} + +function redirect($url) { + header("Location: $url\n\n"); +} \ No newline at end of file diff --git a/plugin/vchamilo/plugin.php b/plugin/vchamilo/plugin.php index 22aeacd5e5..3960a1e4e3 100644 --- a/plugin/vchamilo/plugin.php +++ b/plugin/vchamilo/plugin.php @@ -11,11 +11,6 @@ require_once(api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib/vchamilo_plugin.class.p require_once(api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib.php'); global $_configuration; -require_once($_configuration['root_sys'].'/local/classes/database.class.php'); - -// replace chamilo Database API with stronger DB api -global $DB; -$DB = new DatabaseManager(); /** * Plugin details (must be present) @@ -33,10 +28,10 @@ $plugin_info['version'] = '1.0'; $plugin_info['author'] = 'Valery Fremaux'; -/* Plugin optional settings */ +/* Plugin optional settings */ -/* - * This form will be showed in the plugin settings once the plugin was installed +/* + * This form will be showed in the plugin settings once the plugin was installed * in the plugin/hello_world/index.php you can have access to the value: $plugin_info['settings']['hello_world_show_type'] */ @@ -83,7 +78,7 @@ $form->addElement('header', $plugininstance->get_lang('mysqlcmds')); $form->addElement('text', 'cmd_mysql', $plugininstance->get_lang('mysqlcmd')); $form->addElement('text', 'cmd_mysqldump', $plugininstance->get_lang('mysqldumpcmd')); -$form->addElement('style_submit_button', 'submit_button', $plugininstance->get_lang('Save')); +$form->addButtonSave($plugininstance->get_lang('Save')); $plugin_info['settings_form'] = $form; diff --git a/plugin/vchamilo/views/editinstance.controller.php b/plugin/vchamilo/views/editinstance.controller.php index f16e881790..17f86c2fc4 100644 --- a/plugin/vchamilo/views/editinstance.controller.php +++ b/plugin/vchamilo/views/editinstance.controller.php @@ -9,6 +9,10 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { unset($data->what); unset($data->submitbutton); unset($data->id); + unset($data->vid); + unset($data->testconnection); + unset($data->testdatapath); + $registeronly = $data->registeronly; unset($data->registeronly); $data->lastcron = 0; @@ -19,13 +23,18 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { $template = $data->template; unset($data->template); } - + ctrace("Registering VChamilo "); $tablename = Database::get_main_table('vchamilo'); - if ($DB->record_exists('vchamilo', array('root_web' => $data->root_web))) { - $DB->update_record('vchamilo', $data, 'root_web'); + $sql = "SELECT * FROM $tablename WHERE root_web = '".Database::escape_string($data->root_web)."'"; + $result = Database::query($sql); + + if (Database::num_rows($result)) { + $sql = "SELECT * FROM $tablename WHERE root_web = '".Database::escape_string($data->root_web)."'"; + Database::update($tablename, $data, ['root_web = ?' => $data->root_web]); + //$DB->update_record('vchamilo', $data, 'root_web'); } else { - $DB->insert_record('vchamilo', $data); + Database::insert($tablename, (array) $data); } if ($registeronly){ @@ -33,9 +42,9 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { ctrace("Registering only. out."); vchamilo_redirect(api_get_path(WEB_PLUGIN_PATH).'vchamilo/views/manage.php'); } - + // or we continue with physical creation - + // Create course directory for operations. // this is very important here (DO NOT USE api_get_path() !!) because storage may be remotely located $absalternatecourse = vchamilo_get_config('vchamilo', 'course_real_root'); @@ -54,7 +63,7 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { $INDEX = fopen($coursedir.'/index.html', 'w'); fputs($INDEX, vchamilo_get_default_course_index_fragment()); fclose($INDEX); - + $HTACCESS = fopen($coursedir.'/.htaccess', 'w'); fputs($HTACCESS, vchamilo_get_htaccess_fragment($data->course_folder)); fclose($HTACCESS); @@ -79,9 +88,9 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { } // create homedir - + // Structure of virtualized home folders : - + /* * {LegacyHomeContainer} => {VChamiloSubcontainer} => {BrandedAccessUrlHome} * @@ -92,12 +101,12 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { $archive_folder = $matches[1]; // prepare it now but use it later if ($absalternatehome = vchamilo_get_config('vchamilo', 'home_real_root')){ // absalternatehome is a vchamilo config setting that tells where the - // real physical storage for home pages are. + // real physical storage for home pages are. $homedir = str_replace('//', '/', $absalternatehome.'/'.$home_folder); } else { // homedir is the home container at install level. This may contains // in reality home subdirs from branding suburls. - // In straight installs, this should be located as a hostname subrouted + // In straight installs, this should be located as a hostname subrouted // dir in home dir of the chamilo install. // In delocated installs (clustered installations), the root 'home' directory // may be a symbolic link to a delocated path. @@ -165,40 +174,29 @@ if ($data->what == 'addinstance' || $data->what == 'registerinstance') { // deploy template database ctrace("Creating databases from template $template "); - vchamilo_create_databases($data); - ctrace("Loading data template $template "); - vchamilo_load_db_template($data, 'main_database', $template); - if (!empty($data->statistics_database) && $data->main_database != $data->statistics_database) { - vchamilo_load_db_template($data, 'statistics_database', $template); - } - if (!empty($data->user_personal_database) && ($data->main_database != $data->user_personal_database) && ($data->user_personal_database != $data->statistics_database)) { - vchamilo_load_db_template($data, 'user_personal_database', $template); - } - ctrace("Coying files from template $template "); - vchamilo_load_files_from_template($data, $template); } ctrace("Fixing records"); // Builds a new database manager on new instance to operate records - $NDB = new DatabaseManager($data); +// $NDB = new DatabaseManager($data); // pluging in site name institution - $settingstable = $NDB->format_table_name(TABLE_MAIN_SETTINGS_CURRENT); + $settingstable = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); $sitename = str_replace("'", "''", $data->sitename); $institution = str_replace("'", "''", $data->institution); $sqls[] = " UPDATE {$settingstable} SET selected_value = '{$sitename}' WHERE variable = 'siteName' AND category = 'Platform' "; $sqls[] = " UPDATE {$settingstable} SET selected_value = '{$institution}' WHERE variable = 'institution' AND category = 'Platform' "; - $accessurltable = $NDB->format_table_name('access_url'); + $accessurltable = Database::get_main_table(TABLE_MAIN_ACCESS_URL); $sqls[] = " UPDATE {$accessurltable} SET url = '{$data->root_web}' WHERE id = '1' "; foreach ($sqls as $sql) { - $NDB->execute_sql($sql); + Database::query($sql); } ctrace("Finished. "); diff --git a/plugin/vchamilo/views/editinstance.php b/plugin/vchamilo/views/editinstance.php index 4c66de07f5..ed8b95c1a2 100644 --- a/plugin/vchamilo/views/editinstance.php +++ b/plugin/vchamilo/views/editinstance.php @@ -4,16 +4,10 @@ define('CHAMILO_INTERNAL', true); global $plugininstance; -require_once('../../../main/inc/global.inc.php'); -require_once($_configuration['root_sys'].'/local/classes/mootochamlib.php'); -require_once($_configuration['root_sys'].'/local/classes/database.class.php'); - -global $DB; -$DB = new DatabaseManager(); - -require_once(api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib/vchamilo_plugin.class.php'); -require_once(api_get_path(SYS_PLUGIN_PATH).'vchamilo/views/editinstance_form.php'); -HTML_QuickForm::registerElementType('cancel', api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib/QuickForm/cancel.php', 'HTML_QuickForm_cancel'); +require_once '../../../main/inc/global.inc.php'; +require_once api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib.php'; +require_once api_get_path(SYS_PLUGIN_PATH).'vchamilo/lib/vchamilo_plugin.class.php'; +require_once api_get_path(SYS_PLUGIN_PATH).'vchamilo/views/editinstance_form.php'; $htmlHeadXtra[] = ''; @@ -27,7 +21,6 @@ $thisurl = api_get_path(WEB_PLUGIN_PATH).'vchamilo/views/manage.php'; // security api_protect_admin_script(); - if ($id) { $mode = 'update'; } else { @@ -39,18 +32,18 @@ $form->definition(); $actions = ''; $message = ''; - -// call controller -// $data = $form->get_data(); -if ($data = $form->get_data()){ +if ($data = $form->get_data()) { include(api_get_path(SYS_PLUGIN_PATH).'vchamilo/views/editinstance.controller.php'); } if ($id){ - $vhost = $DB->get_record('vchamilo', array('id' => $id)); - $vhost->vid = $vhost->id; - unset($vhost->id); - $form->set_data((array)$vhost); +// $vhost = $DB->get_record('vchamilo', array('id' => $id)); + $sql = "SELECT * FROM vchamilo WHERE id = $id"; + $result = Database::query($sql); + $vhost = Database::fetch_array($result); + $vhost['vid'] = $vhost['id']; + unset($vhost['id']); + $form->set_data($vhost); } else { $data = array(); $data['db_host'] = 'localhost'; diff --git a/plugin/vchamilo/views/editinstance_form.php b/plugin/vchamilo/views/editinstance_form.php index 1d4479d923..54966995ab 100644 --- a/plugin/vchamilo/views/editinstance_form.php +++ b/plugin/vchamilo/views/editinstance_form.php @@ -1,14 +1,325 @@ _mode = $mode; + $this->_cancelurl = $cancelurl; + $this->_customdata = $customdata; + + $attributes = array('style' => 'width: 60%; float: '.($text_dir == 'rtl' ? 'right;' : 'left;')); + // $this->_form = new FormValidator($mode.'_instance', 'post', $returnurl, '', $attributes, true); + $this->_form = new FormValidator($mode.'_instance', 'post', $returnurl, '', $attributes); + } + + abstract function definition(); + abstract function validation($data, $files = null); + + function validate() { + return $this->_form->validate(); + } + + function display() { + return $this->_form->display(); + } + + function definition_after_data(){ + } + + function return_form(){ + return $this->_form->toHtml(); + } + + function is_in_add_mode(){ + return $this->_mode == 'add'; + } + + /** + * Use this method to a cancel and submit button to the end of your form. Pass a param of false + * if you don't want a cancel button in your form. If you have a cancel button make sure you + * check for it being pressed using is_cancelled() and redirecting if it is true before trying to + * get data with get_data(). + * + * @param boolean $cancel whether to show cancel button, default true + * @param string $submitlabel label for submit button, defaults to get_string('savechanges') + */ + public function add_action_buttons($cancel = true, $submitlabel = null, $cancellabel = null) + { + // TODO : refine lang fetch to effective global strings. + if (is_null($submitlabel)){ + $submitlabel = get_lang('save'); + } + + if (is_null($cancellabel)){ + $submitlabel = get_lang('cancel'); + } + + $cform =& $this->_form; + if ($cancel){ + //when two elements we need a group + $buttonarray = array(); + $buttonarray[] = &$cform->createElement('submit', 'submitbutton', $submitlabel); + //$buttonarray[] = &$cform->createElement('cancel', $cancellabel, $this->_cancelurl); + $cform->addGroup($buttonarray, 'buttonar', '', array(' '), false); + } else { + //no group needed + $cform->addElement('submit', 'submitbutton', $submitlabel); + } + } + + /** + * Return submitted data if properly submitted or returns NULL if validation fails or + * if there is no submitted data. + * + * @param bool $slashed true means return data with addslashes applied + * @return object submitted data; NULL if not valid or not submitted + */ + public function get_data($slashed=true) + { + $cform =& $this->_form; + + if ($this->is_submitted() and $this->is_validated()) { + $data = $cform->exportValues(null, $slashed); + unset($data['sesskey']); // we do not need to return sesskey + unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too + if (empty($data)) { + return NULL; + } else { + return (object)$data; + } + } else { + return NULL; + } + } + + /** + * Return submitted data without validation or NULL if there is no submitted data. + * + * @param bool $slashed true means return data with addslashes applied + * @return object submitted data; NULL if not submitted + */ + public function get_submitted_data($slashed=true) + { + $cform =& $this->_form; + + if ($this->is_submitted()) { + $data = $cform->exportValues(null, $slashed); + unset($data['sesskey']); // we do not need to return sesskey + unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too + if (empty($data)) { + return NULL; + } else { + return (object)$data; + } + } else { + return NULL; + } + } + + /** + * Check that form was submitted. Does not check validity of submitted data. + * + * @return bool true if form properly submitted + */ + public function is_submitted() + { + return $this->_form->isSubmitted(); + } + + /** + * Return true if a cancel button has been pressed resulting in the form being submitted. + * + * @return bool true if a cancel button has been pressed + */ + public function is_cancelled() + { + $cform =& $this->_form; + if ($cform->isSubmitted()){ + foreach ($cform->_cancelButtons as $cancelbutton){ + if (optional_param($cancelbutton, 0, PARAM_RAW)){ + return true; + } + } + } + return false; + } -class InstanceForm extends ChamiloForm{ + /** + * Check that form data is valid. + * You should almost always use this, rather than {@see validate_defined_fields} + * + * @return bool true if form data valid + */ + public function is_validated() + { + //finalize the form definition before any processing + if (!$this->_definition_finalized) { + $this->_definition_finalized = true; + $this->definition_after_data(); + } + return $this->validate_defined_fields(); + } + + /** + * Validate the form. + * + * You almost always want to call {@see is_validated} instead of this + * because it calls {@see definition_after_data} first, before validating the form, + * which is what you want in 99% of cases. + * + * This is provided as a separate function for those special cases where + * you want the form validated before definition_after_data is called + * for example, to selectively add new elements depending on a no_submit_button press, + * but only when the form is valid when the no_submit_button is pressed, + * + * @param boolean $validateonnosubmit optional, defaults to false. The default behaviour + * is NOT to validate the form when a no submit button has been pressed. + * pass true here to override this behaviour + * + * @return bool true if form data valid + */ + public function validate_defined_fields($validateonnosubmit=false) + { + static $validated = null; // one validation is enough + $cform =& $this->_form; + + if ($this->no_submit_button_pressed() && empty($validateonnosubmit)){ + return false; + } elseif ($validated === null) { + $internal_val = $cform->validate(); + + $files = array(); + $file_val = $this->_validate_files($files); + if ($file_val !== true) { + if (!empty($file_val)) { + foreach ($file_val as $element => $msg) { + $cform->setElementError($element, $msg); + } + } + $file_val = false; + } + + $data = $cform->exportValues(null, true); + $chamilo_val = $this->validation($data, $files); + if ((is_array($chamilo_val) && count($chamilo_val)!==0)) { + // non-empty array means errors + foreach ($chamilo_val as $element => $msg) { + $cform->setElementError($element, $msg); + } + $chamilo_val = false; + + } else { + // anything else means validation ok + $chamilo_val = true; + } + + $validated = ($internal_val and $chamilo_val and $file_val); + } + return $validated; + } + + public function no_submit_button_pressed() + { + static $nosubmit = null; // one check is enough + + if (!is_null($nosubmit)){ + return $nosubmit; + } + + $cform =& $this->_form; + $nosubmit = false; + if (!$this->is_submitted()){ + return false; + } + /* + foreach ($cform->_noSubmitButtons as $nosubmitbutton){ + if (optional_param($nosubmitbutton, 0, PARAM_RAW)){ + $nosubmit = true; + break; + } + } + return $nosubmit; + */ + return false; + } + + /** + * Load in existing data as form defaults. Usually new entry defaults are stored directly in + * form definition (new entry form); this function is used to load in data where values + * already exist and data is being edited (edit entry form). + * + * @param mixed $default_values object or array of default values + * @param bool $slashed true if magic quotes applied to data values + */ + public function set_data($default_values, $slashed=false) + { + if (is_object($default_values)) { + $default_values = (array)$default_values; + } + $filter = $slashed ? 'stripslashes' : NULL; + $this->_form->setDefaults($default_values, $filter); + } + + /** + * Internal method. Validates all uploaded files. + */ + public function _validate_files(&$files) + { + $files = array(); + + if (empty($_FILES)) { + // we do not need to do any checks because no files were submitted + // note: server side rules do not work for files - use custom verification in validate() instead + return true; + } + $errors = array(); + $mform =& $this->_form; + + // check the files + $status = $this->_upload_manager->preprocess_files(); + + // now check that we really want each file + foreach ($_FILES as $elname=>$file) { + if ($mform->elementExists($elname) and $mform->getElementType($elname)=='file') { + $required = $mform->isElementRequired($elname); + if (!empty($this->_upload_manager->files[$elname]['uploadlog']) and empty($this->_upload_manager->files[$elname]['clear'])) { + if (!$required and $file['error'] == UPLOAD_ERR_NO_FILE) { + // file not uploaded and not required - ignore it + continue; + } + $errors[$elname] = $this->_upload_manager->files[$elname]['uploadlog']; + + } else if (!empty($this->_upload_manager->files[$elname]['clear'])) { + $files[$elname] = $this->_upload_manager->files[$elname]['tmp_name']; + } + } else { + error('Incorrect upload attempt!'); + } + } - var $_plugin; + // return errors if found + if ($status and 0 == count($errors)){ + return true; - function __construct($plugin, $mode = 'add', $returnurl = null, $cancelurl = null){ + } else { + $files = array(); + return $errors; + } + } +} + +class InstanceForm extends ChamiloForm +{ + public $_plugin; + + public function __construct($plugin, $mode = 'add', $returnurl = null, $cancelurl = null) + { global $_configuration; $this->_plugin = $plugin; @@ -18,7 +329,8 @@ class InstanceForm extends ChamiloForm{ parent::__construct($mode, $returnurl, $cancelurl); } - function definition(){ + function definition() + { global $_configuration; $cform = $this->_form; @@ -40,12 +352,10 @@ class InstanceForm extends ChamiloForm{ $cform->addElement('header', $this->_plugin->get_lang('hostdefinition')); // Name. $cform->addElement('text', 'sitename', $this->_plugin->get_lang('sitename'), $size_input_text); - $cform->applyFilter('sitename', 'html_filter'); $cform->applyFilter('sitename', 'trim'); // Shortname. $cform->addElement('text', 'institution', $this->_plugin->get_lang('institution'), ($this->mode == 'edit' ? 'disabled="disabled" ' : '')); - $cform->applyFilter('institution', 'html_filter'); $cform->applyFilter('institution', 'trim'); // Host's name. @@ -74,18 +384,6 @@ class InstanceForm extends ChamiloForm{ // Database name. $cform->addElement('text', 'main_database', $this->_plugin->get_lang('maindatabase')); - // Database name. - $cform->addElement('text', 'statistics_database', $this->_plugin->get_lang('statisticsdatabase')); - - // Database name. - $cform->addElement('text', 'user_personal_database', $this->_plugin->get_lang('userpersonaldatabase')); - - // tracking_enabled - $yesnooptions = array('0' => $this->_plugin->get_lang('no'), '1' => $this->_plugin->get_lang('yes')); - $cform->addElement('select', 'tracking_enabled', $this->_plugin->get_lang('trackingenabled'), $yesnooptions); - - // Single database - $cform->addElement('select', 'single_database', $this->_plugin->get_lang('singledatabase'), $yesnooptions); // Table's prefix. $cform->addElement('text', 'table_prefix', $this->_plugin->get_lang('tableprefix')); @@ -130,11 +428,11 @@ class InstanceForm extends ChamiloForm{ } } - function validation($data, $files = null){ + function validation($data, $files = null) + { global $plugininstance; $errors = array(); - var_dump($data); if (!preg_match('/^courses[_-]/', $data['course_folder'])){ $errors['course_folder'] = $plugininstance->get_lang('errormuststartwithcourses'); } diff --git a/plugin/vchamilo/views/manage.php b/plugin/vchamilo/views/manage.php index d8996147eb..f367efa3e7 100644 --- a/plugin/vchamilo/views/manage.php +++ b/plugin/vchamilo/views/manage.php @@ -1,12 +1,8 @@ assign('actions', $actions); $tpl->assign('message', $message); $tpl->assign('content', $content); $tpl->display_one_col_template(); - \ No newline at end of file