clilib.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <?php
  2. /**
  3. * Opens and parses/checks a VChamilo instance definition file
  4. * @param string $location
  5. *
  6. */
  7. function vchamilo_parse_csv_nodelist($nodelistlocation = '', $plugin = null){
  8. global $_configuration;
  9. $vnodes = array();
  10. if (empty($nodelistlocation)){
  11. $nodelistlocation = $_configuratioh['root_sys'].'/plugin/vchamilo/nodelist.csv';
  12. }
  13. // decode file
  14. $csv_delimiter = "\;";
  15. $csv_delimiter2 = ";";
  16. // make arrays of valid fields for error checking
  17. $required = array('root_web' => 1,
  18. 'sitename' => 1,
  19. 'institution' => 1,
  20. 'main_database' => 1,
  21. 'statistics_database' => 1,
  22. 'user_personal_database' => 1,
  23. 'db_user' => 1,
  24. 'db_password' => 1,
  25. 'course_folder' => 1,
  26. );
  27. $optional = array(
  28. 'db_host' => 1,
  29. 'template' => 1,
  30. 'table_prefix' => 1,
  31. 'single_database' => 1,
  32. 'tracking_enabled' => 1,
  33. 'visible' => 1,
  34. );
  35. $optionalDefaults = array(
  36. 'db_host' => $_configuration['db_host'],
  37. 'db_prefix' => 'chm_',
  38. 'table_prefix' => '',
  39. 'tracking_enabled' => 0,
  40. 'single_database' => 1,
  41. 'template' => '',
  42. 'visible' => 1,
  43. );
  44. $patterns = array();
  45. // Metas are accepted patterns (optional)
  46. $metas = array(
  47. 'plugin_.*',
  48. 'config_.*'
  49. );
  50. // Get header (field names)
  51. $textlib = new textlib();
  52. if (!$fp = fopen($nodelistlocation, 'rb')) {
  53. cli_error($plugin->get_lang('badnodefile', 'vchamilo', $nodelistlocation));
  54. }
  55. // Jump any empty or comment line
  56. $text = fgets($fp, 1024);
  57. $i = 0;
  58. while(vchamilo_is_empty_line_or_format($text, $i == 0)){
  59. $text = fgets($fp, 1024);
  60. $i++;
  61. }
  62. $headers = explode($csv_delimiter2, $text);
  63. // Check for valid field names
  64. foreach ($headers as $h) {
  65. $header[] = trim($h);
  66. $patternized = implode('|', $patterns) . "\\d+";
  67. $metapattern = implode('|', $metas);
  68. if (!(isset($required[$h]) ||
  69. isset($optionalDefaults[$h]) ||
  70. isset($optional[$h]) ||
  71. preg_match("/$patternized/", $h) ||
  72. preg_match("/$metapattern/", $h))) {
  73. cli_error("Node parse : invalidfieldname $h ");
  74. return;
  75. }
  76. if (isset($required[trim($h)])) {
  77. $required[trim($h)] = 0;
  78. }
  79. }
  80. $expectedcols = count($headers);
  81. $i++;
  82. // Check for required fields.
  83. foreach ($required as $key => $value) {
  84. if ($value) { // Required field missing.
  85. cli_error("fieldrequired $key");
  86. return;
  87. }
  88. }
  89. $linenum = 2; // Since header is line 1.
  90. // Take some from admin profile, other fixed by hardcoded defaults.
  91. while (!feof ($fp)) {
  92. // Make a new base record.
  93. $vnode = new StdClass();
  94. foreach ($optionalDefaults as $key => $value) {
  95. $vnode->$key = $value;
  96. }
  97. //Note: commas within a field should be encoded as &#44 (for comma separated csv files)
  98. //Note: semicolon within a field should be encoded as &#59 (for semicolon separated csv files)
  99. $text = fgets($fp, 1024);
  100. if (vchamilo_is_empty_line_or_format($text, false)) {
  101. $i++;
  102. continue;
  103. }
  104. $valueset = explode($csv_delimiter2, $text);
  105. if (count($valueset) != $expectedcols) {
  106. cli_error('wrong line count at line '.$i);
  107. }
  108. $f = 0;
  109. foreach ($valueset as $value) {
  110. // Decode encoded commas.
  111. $key = $headers[$f];
  112. if (preg_match('/\|/', $key)) {
  113. list($plugin, $variable) = explode('|', str_replace('plugin_', '', $key));
  114. if (empty($variable)) die("Key error in CSV : $key ");
  115. if (!isset($vnode->$plugin)) {
  116. $vnode->$plugin = new StdClass();
  117. }
  118. $vnode->$plugin->$variable = trim($value);
  119. } else {
  120. if (preg_match('/^config_/', $key)) {
  121. $smartkey = str_replace('config_', '', $key);
  122. $keyparts = implode('|', $smartkey);
  123. $keyvar = $keyparts[0];
  124. $subkey = @$keyparts[1];
  125. $vnode->config->$smartkey = new StdClass;
  126. $vnode->config->$smartkey->subkey = $subkey;
  127. $vnode->config->$smartkey->value = trim($value);
  128. } else {
  129. $vnode->$key = trim($value);
  130. }
  131. }
  132. $f++;
  133. }
  134. $vnodes[] = $vnode;
  135. }
  136. return $vnodes;
  137. }
  138. /**
  139. * Check a CSV input line format for empty or commented lines
  140. * Ensures compatbility to UTF-8 BOM or unBOM formats
  141. */
  142. function vchamilo_is_empty_line_or_format(&$text, $resetfirst = false) {
  143. global $CFG;
  144. static $textlib;
  145. static $first = true;
  146. // We may have a risk the BOM is present on first line
  147. if ($resetfirst) $first = true;
  148. if (!isset($textlib)) $textlib = new textlib(); // Singleton
  149. $text = $textlib->trim_utf8_bom($text);
  150. $first = false;
  151. $text = preg_replace("/\n?\r?/", '', $text);
  152. // last chance
  153. if ('ASCII' == mb_detect_encoding($text)) {
  154. $text = utf8_encode($text);
  155. }
  156. // Check the text is empty or comment line and answer true if it is.
  157. return preg_match('/^$/', $text) || preg_match('/^(\(|\[|-|#|\/| )/', $text);
  158. }
  159. /**
  160. * Get input from user
  161. * @param string $prompt text prompt, should include possible options
  162. * @param string $default default value when enter pressed
  163. * @param array $options list of allowed options, empty means any text
  164. * @param bool $casesensitive true if options are case sensitive
  165. * @return string entered text
  166. */
  167. function cli_input($prompt, $default='', array $options=null, $casesensitiveoptions=false) {
  168. echo $prompt;
  169. echo "\n: ";
  170. $input = fread(STDIN, 2048);
  171. $input = trim($input);
  172. if ($input === '') {
  173. $input = $default;
  174. }
  175. if ($options) {
  176. if (!$casesensitiveoptions) {
  177. $input = strtolower($input);
  178. }
  179. if (!in_array($input, $options)) {
  180. echo "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install
  181. return cli_input($prompt, $default, $options, $casesensitiveoptions);
  182. }
  183. }
  184. return $input;
  185. }
  186. /**
  187. * Returns cli script parameters.
  188. * @param array $longoptions array of --style options ex:('verbose'=>false)
  189. * @param array $shortmapping array describing mapping of short to long style options ex:('h'=>'help', 'v'=>'verbose')
  190. * @return array array of arrays, options, unrecognised as optionlongname=>value
  191. */
  192. function cli_get_params(array $longoptions, array $shortmapping=null) {
  193. $shortmapping = (array)$shortmapping;
  194. $options = array();
  195. $unrecognized = array();
  196. if (empty($_SERVER['argv'])) {
  197. // Bad luck, we can continue in interactive mode ;-)
  198. return array($options, $unrecognized);
  199. }
  200. $rawoptions = $_SERVER['argv'];
  201. // Remove anything after '--', options can not be there.
  202. if (($key = array_search('--', $rawoptions)) !== false) {
  203. $rawoptions = array_slice($rawoptions, 0, $key);
  204. }
  205. // Remove script.
  206. unset($rawoptions[0]);
  207. foreach ($rawoptions as $raw) {
  208. if (substr($raw, 0, 2) === '--') {
  209. $value = substr($raw, 2);
  210. $parts = explode('=', $value);
  211. if (count($parts) == 1) {
  212. $key = reset($parts);
  213. $value = true;
  214. } else {
  215. $key = array_shift($parts);
  216. $value = implode('=', $parts);
  217. }
  218. if (array_key_exists($key, $longoptions)) {
  219. $options[$key] = $value;
  220. } else {
  221. $unrecognized[] = $raw;
  222. }
  223. } else if (substr($raw, 0, 1) === '-') {
  224. $value = substr($raw, 1);
  225. $parts = explode('=', $value);
  226. if (count($parts) == 1) {
  227. $key = reset($parts);
  228. $value = true;
  229. } else {
  230. $key = array_shift($parts);
  231. $value = implode('=', $parts);
  232. }
  233. if (array_key_exists($key, $shortmapping)) {
  234. $options[$shortmapping[$key]] = $value;
  235. } else {
  236. $unrecognized[] = $raw;
  237. }
  238. } else {
  239. $unrecognized[] = $raw;
  240. continue;
  241. }
  242. }
  243. // Apply defaults.
  244. foreach ($longoptions as $key=>$default) {
  245. if (!array_key_exists($key, $options)) {
  246. $options[$key] = $default;
  247. }
  248. }
  249. // Finished.
  250. return array($options, $unrecognized);
  251. }
  252. /**
  253. * Print or return section separator string
  254. * @param bool $return false means print, true return as string
  255. * @return mixed void or string
  256. */
  257. function cli_separator($return=false) {
  258. $separator = str_repeat('-', 79)."\n";
  259. if ($return) {
  260. return $separator;
  261. } else {
  262. echo $separator;
  263. }
  264. }
  265. /**
  266. * Print or return section heading string
  267. * @param string $string text
  268. * @param bool $return false means print, true return as string
  269. * @return mixed void or string
  270. */
  271. function cli_heading($string, $return=false) {
  272. $string = "== $string ==\n";
  273. if ($return) {
  274. return $string;
  275. } else {
  276. echo $string;
  277. }
  278. }
  279. /**
  280. * Write error notification
  281. * @param $text
  282. * @return void
  283. */
  284. function cli_problem($text) {
  285. fwrite(STDERR, $text."\n");
  286. }
  287. /**
  288. * Write to standard out and error with exit in error.
  289. *
  290. * @param string $text
  291. * @param int $errorcode
  292. * @return void (does not return)
  293. */
  294. function cli_error($text, $errorcode = 1) {
  295. fwrite(STDERR, $text);
  296. fwrite(STDERR, "\n");
  297. die($errorcode);
  298. }