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