Bearsampp 2026.9.23
Loading...
Searching...
No Matches
CLI.php
Go to the documentation of this file.
1<?php
19require_once 'PEAR/Frontend.php';
20
34{
40 var $type = 'CLI';
41 var $lp = ''; // line prefix
42
43 var $params = array();
44 var $term = array(
45 'bold' => '',
46 'normal' => '',
47 );
48
49 function __construct()
50 {
51 parent::__construct();
52 $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
53 if (function_exists('posix_isatty') && !posix_isatty(1)) {
54 // output is being redirected to a file or through a pipe
55 } elseif ($term) {
56 if (preg_match('/^(xterm|vt220|linux)/', $term)) {
57 $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109);
58 $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
59 } elseif (preg_match('/^vt100/', $term)) {
60 $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
61 $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
62 }
63 } elseif (OS_WINDOWS) {
64 // XXX add ANSI codes here
65 }
66 }
67
71 function displayError($e)
72 {
73 return $this->_displayLine($e->getMessage());
74 }
75
79 function displayFatalError($eobj)
80 {
81 $this->displayError($eobj);
82 if (class_exists('PEAR_Config')) {
83 $config = &PEAR_Config::singleton();
84 if ($config->get('verbose') > 5) {
85 if (function_exists('debug_print_backtrace')) {
86 debug_print_backtrace();
87 exit(1);
88 }
89
90 $raised = false;
91 foreach (debug_backtrace() as $i => $frame) {
92 if (!$raised) {
93 if (isset($frame['class'])
94 && strtolower($frame['class']) == 'pear'
95 && strtolower($frame['function']) == 'raiseerror'
96 ) {
97 $raised = true;
98 } else {
99 continue;
100 }
101 }
102
103 $frame['class'] = !isset($frame['class']) ? '' : $frame['class'];
104 $frame['type'] = !isset($frame['type']) ? '' : $frame['type'];
105 $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
106 $frame['line'] = !isset($frame['line']) ? '' : $frame['line'];
107 $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
108 }
109 }
110 }
111
112 exit(1);
113 }
114
124 function skipParamgroup($id)
125 {
126 $this->_skipSections[$id] = true;
127 }
128
129 function runPostinstallScripts(&$scripts)
130 {
131 foreach ($scripts as $i => $script) {
132 $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
133 }
134 }
135
141 function runInstallScript($xml, &$script)
142 {
143 $this->_skipSections = array();
144 if (!is_array($xml) || !isset($xml['paramgroup'])) {
145 $script->run(array(), '_default');
146 return;
147 }
148
149 $completedPhases = array();
150 if (!isset($xml['paramgroup'][0])) {
151 $xml['paramgroup'] = array($xml['paramgroup']);
152 }
153
154 foreach ($xml['paramgroup'] as $group) {
155 if (isset($this->_skipSections[$group['id']])) {
156 // the post-install script chose to skip this section dynamically
157 continue;
158 }
159
160 if (isset($group['name'])) {
161 $paramname = explode('::', $group['name']);
162 if ($lastgroup['id'] != $paramname[0]) {
163 continue;
164 }
165
166 $group['name'] = $paramname[1];
167 if (!isset($answers)) {
168 return;
169 }
170
171 if (isset($answers[$group['name']])) {
172 switch ($group['conditiontype']) {
173 case '=' :
174 if ($answers[$group['name']] != $group['value']) {
175 continue 2;
176 }
177 break;
178 case '!=' :
179 if ($answers[$group['name']] == $group['value']) {
180 continue 2;
181 }
182 break;
183 case 'preg_match' :
184 if (!@preg_match('/' . $group['value'] . '/',
185 $answers[$group['name']])) {
186 continue 2;
187 }
188 break;
189 default :
190 return;
191 }
192 }
193 }
194
195 $lastgroup = $group;
196 if (isset($group['instructions'])) {
197 $this->_display($group['instructions']);
198 }
199
200 if (!isset($group['param'][0])) {
201 $group['param'] = array($group['param']);
202 }
203
204 if (isset($group['param'])) {
205 if (method_exists($script, 'postProcessPrompts')) {
206 $prompts = $script->postProcessPrompts($group['param'], $group['id']);
207 if (!is_array($prompts) || count($prompts) != count($group['param'])) {
208 $this->outputData('postinstall', 'Error: post-install script did not ' .
209 'return proper post-processed prompts');
210 $prompts = $group['param'];
211 } else {
212 foreach ($prompts as $i => $var) {
213 if (!is_array($var) || !isset($var['prompt']) ||
214 !isset($var['name']) ||
215 ($var['name'] != $group['param'][$i]['name']) ||
216 ($var['type'] != $group['param'][$i]['type'])
217 ) {
218 $this->outputData('postinstall', 'Error: post-install script ' .
219 'modified the variables or prompts, severe security risk. ' .
220 'Will instead use the defaults from the package.xml');
221 $prompts = $group['param'];
222 }
223 }
224 }
225
226 $answers = $this->confirmDialog($prompts);
227 } else {
228 $answers = $this->confirmDialog($group['param']);
229 }
230 }
231
232 if ((isset($answers) && $answers) || !isset($group['param'])) {
233 if (!isset($answers)) {
234 $answers = array();
235 }
236
237 array_unshift($completedPhases, $group['id']);
238 if (!$script->run($answers, $group['id'])) {
239 $script->run($completedPhases, '_undoOnError');
240 return;
241 }
242 } else {
243 $script->run($completedPhases, '_undoOnError');
244 return;
245 }
246 }
247 }
248
256 {
257 $answers = $prompts = $types = array();
258 foreach ($params as $param) {
259 $prompts[$param['name']] = $param['prompt'];
260 $types[$param['name']] = $param['type'];
261 $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
262 }
263
264 $tried = false;
265 do {
266 if ($tried) {
267 $i = 1;
268 foreach ($answers as $var => $value) {
269 if (!strlen($value)) {
270 echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
271 }
272 $i++;
273 }
274 }
275
276 $answers = $this->userDialog('', $prompts, $types, $answers);
277 $tried = true;
278 } while (is_array($answers) && count(array_filter($answers)) != count($prompts));
279
280 return $answers;
281 }
282
283 function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
284 {
285 if (!is_array($prompts)) {
286 return array();
287 }
288
289 $testprompts = array_keys($prompts);
290 $result = $defaults;
291
292 reset($prompts);
293 if (count($prompts) === 1) {
294 foreach ($prompts as $key => $prompt) {
295 $type = $types[$key];
296 $default = @$defaults[$key];
297 print "$prompt ";
298 if ($default) {
299 print "[$default] ";
300 }
301 print ": ";
302
303 $line = fgets(STDIN, 2048);
304 $result[$key] = ($default && trim($line) == '') ? $default : trim($line);
305 }
306
307 return $result;
308 }
309
310 $first_run = true;
311 while (true) {
312 $descLength = max(array_map('strlen', $prompts));
313 $descFormat = "%-{$descLength}s";
314 $last = count($prompts);
315
316 $i = 0;
317 foreach ($prompts as $n => $var) {
318 $res = isset($result[$n]) ? $result[$n] : null;
319 printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
320 }
321 print "\n1-$last, 'all', 'abort', or Enter to continue: ";
322
323 $tmp = trim(fgets(STDIN, 1024));
324 if (empty($tmp)) {
325 break;
326 }
327
328 if ($tmp == 'abort') {
329 return false;
330 }
331
332 if (isset($testprompts[(int)$tmp - 1])) {
333 $var = $testprompts[(int)$tmp - 1];
334 $desc = $prompts[$var];
335 $current = @$result[$var];
336 print "$desc [$current] : ";
337 $tmp = trim(fgets(STDIN, 1024));
338 if ($tmp !== '') {
339 $result[$var] = $tmp;
340 }
341 } elseif ($tmp == 'all') {
342 foreach ($prompts as $var => $desc) {
343 $current = $result[$var];
344 print "$desc [$current] : ";
345 $tmp = trim(fgets(STDIN, 1024));
346 if (trim($tmp) !== '') {
347 $result[$var] = trim($tmp);
348 }
349 }
350 }
351
352 $first_run = false;
353 }
354
355 return $result;
356 }
357
358 function userConfirm($prompt, $default = 'yes')
359 {
360 if (PHP_VERSION_ID < 70000) {
361 trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
362 } else {
363 throw new Error('PEAR_Frontend_CLI::userConfirm not yet converted');
364 }
365 static $positives = array('y', 'yes', 'on', '1');
366 static $negatives = array('n', 'no', 'off', '0');
367 print "$this->lp$prompt [$default] : ";
368 $fp = fopen("php://stdin", "r");
369 $line = fgets($fp, 2048);
370 fclose($fp);
371 $answer = strtolower(trim($line));
372 if (empty($answer)) {
373 $answer = $default;
374 }
375 if (in_array($answer, $positives)) {
376 return true;
377 }
378 if (in_array($answer, $negatives)) {
379 return false;
380 }
381 if (in_array($default, $positives)) {
382 return true;
383 }
384 return false;
385 }
386
387 function outputData($data, $command = '_default')
388 {
389 switch ($command) {
390 case 'channel-info':
391 foreach ($data as $type => $section) {
392 if ($type == 'main') {
393 $section['data'] = array_values($section['data']);
394 }
395
396 $this->outputData($section);
397 }
398 break;
399 case 'install':
400 case 'upgrade':
401 case 'upgrade-all':
402 if (is_array($data) && isset($data['release_warnings'])) {
403 $this->_displayLine('');
404 $this->_startTable(array(
405 'border' => false,
406 'caption' => 'Release Warnings'
407 ));
408 $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
409 $this->_endTable();
410 $this->_displayLine('');
411 }
412
413 $this->_displayLine(is_array($data) ? $data['data'] : $data);
414 break;
415 case 'search':
416 $this->_startTable($data);
417 if (isset($data['headline']) && is_array($data['headline'])) {
418 $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
419 }
420
421 $packages = array();
422 foreach($data['data'] as $category) {
423 foreach($category as $name => $pkg) {
424 $packages[$pkg[0]] = $pkg;
425 }
426 }
427
428 $p = array_keys($packages);
429 natcasesort($p);
430 foreach ($p as $name) {
431 $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
432 }
433
434 $this->_endTable();
435 break;
436 case 'list-all':
437 if (!isset($data['data'])) {
438 $this->_displayLine('No packages in channel');
439 break;
440 }
441
442 $this->_startTable($data);
443 if (isset($data['headline']) && is_array($data['headline'])) {
444 $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
445 }
446
447 $packages = array();
448 foreach($data['data'] as $category) {
449 foreach($category as $name => $pkg) {
450 $packages[$pkg[0]] = $pkg;
451 }
452 }
453
454 $p = array_keys($packages);
455 natcasesort($p);
456 foreach ($p as $name) {
457 $pkg = $packages[$name];
458 unset($pkg[4], $pkg[5]);
459 $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
460 }
461
462 $this->_endTable();
463 break;
464 case 'config-show':
465 $data['border'] = false;
466 $opts = array(
467 0 => array('wrap' => 30),
468 1 => array('wrap' => 20),
469 2 => array('wrap' => 35)
470 );
471
472 $this->_startTable($data);
473 if (isset($data['headline']) && is_array($data['headline'])) {
474 $this->_tableRow($data['headline'], array('bold' => true), $opts);
475 }
476
477 foreach ($data['data'] as $group) {
478 foreach ($group as $value) {
479 if ($value[2] == '') {
480 $value[2] = "<not set>";
481 }
482
483 $this->_tableRow($value, null, $opts);
484 }
485 }
486
487 $this->_endTable();
488 break;
489 case 'remote-info':
490 $d = $data;
491 $data = array(
492 'caption' => 'Package details:',
493 'border' => false,
494 'data' => array(
495 array("Latest", $data['stable']),
496 array("Installed", $data['installed']),
497 array("Package", $data['name']),
498 array("License", $data['license']),
499 array("Category", $data['category']),
500 array("Summary", $data['summary']),
501 array("Description", $data['description']),
502 ),
503 );
504
505 if (isset($d['deprecated']) && $d['deprecated']) {
506 $conf = &PEAR_Config::singleton();
507 $reg = $conf->getRegistry();
508 $name = $reg->parsedPackageNameToString($d['deprecated'], true);
509 $data['data'][] = array('Deprecated! use', $name);
510 }
511 default: {
512 if (is_array($data)) {
513 $this->_startTable($data);
514 $count = count($data['data'][0]);
515 if ($count == 2) {
516 $opts = array(0 => array('wrap' => 25),
517 1 => array('wrap' => 48)
518 );
519 } elseif ($count == 3) {
520 $opts = array(0 => array('wrap' => 30),
521 1 => array('wrap' => 20),
522 2 => array('wrap' => 35)
523 );
524 } else {
525 $opts = null;
526 }
527 if (isset($data['headline']) && is_array($data['headline'])) {
528 $this->_tableRow($data['headline'],
529 array('bold' => true),
530 $opts);
531 }
532
533 if (is_array($data['data'])) {
534 foreach($data['data'] as $row) {
535 $this->_tableRow($row, null, $opts);
536 }
537 } else {
538 $this->_tableRow(array($data['data']), null, $opts);
539 }
540 $this->_endTable();
541 } else {
542 $this->_displayLine($data);
543 }
544 }
545 }
546 }
547
548 function log($text, $append_crlf = true)
549 {
550 if ($append_crlf) {
551 return $this->_displayLine($text);
552 }
553
554 return $this->_display($text);
555 }
556
557 function bold($text)
558 {
559 if (empty($this->term['bold'])) {
560 return strtoupper($text);
561 }
562
563 return $this->term['bold'] . $text . $this->term['normal'];
564 }
565
566 function _displayHeading($title)
567 {
568 print $this->lp.$this->bold($title)."\n";
569 print $this->lp.str_repeat("=", strlen($title))."\n";
570 }
571
572 function _startTable($params = array())
573 {
574 $params['table_data'] = array();
575 $params['widest'] = array(); // indexed by column
576 $params['highest'] = array(); // indexed by row
577 $params['ncols'] = 0;
578 $this->params = $params;
579 }
580
581 function _tableRow($columns, $rowparams = array(), $colparams = array())
582 {
583 $highest = 1;
584 for ($i = 0; $i < count($columns); $i++) {
585 $col = &$columns[$i];
586 if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
587 $col = wordwrap($col, $colparams[$i]['wrap']);
588 }
589
590 if (strpos($col, "\n") !== false) {
591 $multiline = explode("\n", $col);
592 $w = 0;
593 foreach ($multiline as $n => $line) {
594 $len = strlen($line);
595 if ($len > $w) {
596 $w = $len;
597 }
598 }
599 $lines = count($multiline);
600 } else {
601 $w = strlen($col);
602 }
603
604 if (isset($this->params['widest'][$i])) {
605 if ($w > $this->params['widest'][$i]) {
606 $this->params['widest'][$i] = $w;
607 }
608 } else {
609 $this->params['widest'][$i] = $w;
610 }
611
612 $tmp = count_chars($columns[$i], 1);
613 // handle unix, mac and windows formats
614 $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
615 if ($lines > $highest) {
616 $highest = $lines;
617 }
618 }
619
620 if (count($columns) > $this->params['ncols']) {
621 $this->params['ncols'] = count($columns);
622 }
623
624 $new_row = array(
625 'data' => $columns,
626 'height' => $highest,
627 'rowparams' => $rowparams,
628 'colparams' => $colparams,
629 );
630 $this->params['table_data'][] = $new_row;
631 }
632
633 function _endTable()
634 {
635 extract($this->params);
636 if (!empty($caption)) {
637 $this->_displayHeading($caption);
638 }
639
640 if (count($table_data) === 0) {
641 return;
642 }
643
644 if (!isset($width)) {
645 $width = $widest;
646 } else {
647 for ($i = 0; $i < $ncols; $i++) {
648 if (!isset($width[$i])) {
649 $width[$i] = $widest[$i];
650 }
651 }
652 }
653
654 $border = false;
655 if (empty($border)) {
656 $cellstart = '';
657 $cellend = ' ';
658 $rowend = '';
659 $padrowend = false;
660 $borderline = '';
661 } else {
662 $cellstart = '| ';
663 $cellend = ' ';
664 $rowend = '|';
665 $padrowend = true;
666 $borderline = '+';
667 foreach ($width as $w) {
668 $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
669 $borderline .= '+';
670 }
671 }
672
673 if ($borderline) {
674 $this->_displayLine($borderline);
675 }
676
677 for ($i = 0; $i < count($table_data); $i++) {
678 extract($table_data[$i]);
679 if (!is_array($rowparams)) {
680 $rowparams = array();
681 }
682
683 if (!is_array($colparams)) {
684 $colparams = array();
685 }
686
687 $rowlines = array();
688 if ($height > 1) {
689 for ($c = 0; $c < count($data); $c++) {
690 $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
691 if (count($rowlines[$c]) < $height) {
692 $rowlines[$c] = array_pad($rowlines[$c], $height, '');
693 }
694 }
695 } else {
696 for ($c = 0; $c < count($data); $c++) {
697 $rowlines[$c] = array($data[$c]);
698 }
699 }
700
701 for ($r = 0; $r < $height; $r++) {
702 $rowtext = '';
703 for ($c = 0; $c < count($data); $c++) {
704 if (isset($colparams[$c])) {
705 $attribs = array_merge($rowparams, $colparams);
706 } else {
707 $attribs = $rowparams;
708 }
709
710 $w = isset($width[$c]) ? $width[$c] : 0;
711 //$cell = $data[$c];
712 $cell = $rowlines[$c][$r];
713 $l = strlen($cell);
714 if ($l > $w) {
715 $cell = substr($cell, 0, $w);
716 }
717
718 if (isset($attribs['bold'])) {
719 $cell = $this->bold($cell);
720 }
721
722 if ($l < $w) {
723 // not using str_pad here because we may
724 // add bold escape characters to $cell
725 $cell .= str_repeat(' ', $w - $l);
726 }
727
728 $rowtext .= $cellstart . $cell . $cellend;
729 }
730
731 if (!$border) {
732 $rowtext = rtrim($rowtext);
733 }
734
735 $rowtext .= $rowend;
736 $this->_displayLine($rowtext);
737 }
738 }
739
740 if ($borderline) {
741 $this->_displayLine($borderline);
742 }
743 }
744
745 function _displayLine($text)
746 {
747 print "$this->lp$text\n";
748 }
749
750 function _display($text)
751 {
752 print $text;
753 }
754}
$result
runPostinstallScripts(&$scripts)
Definition CLI.php:129
_tableRow($columns, $rowparams=array(), $colparams=array())
Definition CLI.php:581
log($text, $append_crlf=true)
Definition CLI.php:548
userDialog($command, $prompts, $types=array(), $defaults=array(), $screensize=20)
Definition CLI.php:283
_displayLine($text)
Definition CLI.php:745
_display($text)
Definition CLI.php:750
skipParamgroup($id)
Definition CLI.php:124
userConfirm($prompt, $default='yes')
Definition CLI.php:358
displayError($e)
Definition CLI.php:71
runInstallScript($xml, &$script)
Definition CLI.php:141
_displayHeading($title)
Definition CLI.php:566
bold($text)
Definition CLI.php:557
confirmDialog($params)
Definition CLI.php:255
_startTable($params=array())
Definition CLI.php:572
displayFatalError($eobj)
Definition CLI.php:79
outputData($data, $command='_default')
Definition CLI.php:387
$config
Definition pearcmd.php:182
if( $raw) foreach($opts as $opt) if( $store_system_config) if($store_user_config) $command
Definition pearcmd.php:322
if(PEAR::isError($options)) $opts
Definition pearcmd.php:150
if(!extension_loaded('winbinder')) if(!dl('php_winbinder.dll')) trigger_error("WinBinder extension could not be loaded.\n" E_USER_ERROR
Definition winbinder.php:14