annotate vendor/psy/psysh/src/Configuration.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@13 1 <?php
Chris@13 2
Chris@13 3 /*
Chris@13 4 * This file is part of Psy Shell.
Chris@13 5 *
Chris@13 6 * (c) 2012-2018 Justin Hileman
Chris@13 7 *
Chris@13 8 * For the full copyright and license information, please view the LICENSE
Chris@13 9 * file that was distributed with this source code.
Chris@13 10 */
Chris@13 11
Chris@13 12 namespace Psy;
Chris@13 13
Chris@13 14 use Psy\Exception\DeprecatedException;
Chris@13 15 use Psy\Exception\RuntimeException;
Chris@13 16 use Psy\Output\OutputPager;
Chris@13 17 use Psy\Output\ShellOutput;
Chris@13 18 use Psy\Readline\GNUReadline;
Chris@13 19 use Psy\Readline\HoaConsole;
Chris@13 20 use Psy\Readline\Libedit;
Chris@13 21 use Psy\Readline\Readline;
Chris@13 22 use Psy\Readline\Transient;
Chris@13 23 use Psy\TabCompletion\AutoCompleter;
Chris@13 24 use Psy\VarDumper\Presenter;
Chris@13 25 use Psy\VersionUpdater\Checker;
Chris@13 26 use Psy\VersionUpdater\GitHubChecker;
Chris@13 27 use Psy\VersionUpdater\IntervalChecker;
Chris@13 28 use Psy\VersionUpdater\NoopChecker;
Chris@13 29
Chris@13 30 /**
Chris@13 31 * The Psy Shell configuration.
Chris@13 32 */
Chris@13 33 class Configuration
Chris@13 34 {
Chris@13 35 const COLOR_MODE_AUTO = 'auto';
Chris@13 36 const COLOR_MODE_FORCED = 'forced';
Chris@13 37 const COLOR_MODE_DISABLED = 'disabled';
Chris@13 38
Chris@13 39 private static $AVAILABLE_OPTIONS = [
Chris@13 40 'codeCleaner',
Chris@13 41 'colorMode',
Chris@13 42 'configDir',
Chris@13 43 'dataDir',
Chris@13 44 'defaultIncludes',
Chris@13 45 'eraseDuplicates',
Chris@13 46 'errorLoggingLevel',
Chris@13 47 'forceArrayIndexes',
Chris@13 48 'historySize',
Chris@13 49 'manualDbFile',
Chris@13 50 'pager',
Chris@13 51 'prompt',
Chris@13 52 'requireSemicolons',
Chris@13 53 'runtimeDir',
Chris@13 54 'startupMessage',
Chris@13 55 'updateCheck',
Chris@13 56 'useBracketedPaste',
Chris@13 57 'usePcntl',
Chris@13 58 'useReadline',
Chris@13 59 'useTabCompletion',
Chris@13 60 'useUnicode',
Chris@13 61 'warnOnMultipleConfigs',
Chris@13 62 ];
Chris@13 63
Chris@13 64 private $defaultIncludes;
Chris@13 65 private $configDir;
Chris@13 66 private $dataDir;
Chris@13 67 private $runtimeDir;
Chris@13 68 private $configFile;
Chris@13 69 /** @var string|false */
Chris@13 70 private $historyFile;
Chris@13 71 private $historySize;
Chris@13 72 private $eraseDuplicates;
Chris@13 73 private $manualDbFile;
Chris@13 74 private $hasReadline;
Chris@13 75 private $useReadline;
Chris@13 76 private $useBracketedPaste;
Chris@13 77 private $hasPcntl;
Chris@13 78 private $usePcntl;
Chris@13 79 private $newCommands = [];
Chris@13 80 private $requireSemicolons = false;
Chris@13 81 private $useUnicode;
Chris@13 82 private $useTabCompletion;
Chris@13 83 private $newMatchers = [];
Chris@13 84 private $errorLoggingLevel = E_ALL;
Chris@13 85 private $warnOnMultipleConfigs = false;
Chris@13 86 private $colorMode;
Chris@13 87 private $updateCheck;
Chris@13 88 private $startupMessage;
Chris@13 89 private $forceArrayIndexes = false;
Chris@13 90
Chris@13 91 // services
Chris@13 92 private $readline;
Chris@13 93 private $output;
Chris@13 94 private $shell;
Chris@13 95 private $cleaner;
Chris@13 96 private $pager;
Chris@13 97 private $manualDb;
Chris@13 98 private $presenter;
Chris@13 99 private $autoCompleter;
Chris@13 100 private $checker;
Chris@13 101 private $prompt;
Chris@13 102
Chris@13 103 /**
Chris@13 104 * Construct a Configuration instance.
Chris@13 105 *
Chris@13 106 * Optionally, supply an array of configuration values to load.
Chris@13 107 *
Chris@13 108 * @param array $config Optional array of configuration values
Chris@13 109 */
Chris@13 110 public function __construct(array $config = [])
Chris@13 111 {
Chris@13 112 $this->setColorMode(self::COLOR_MODE_AUTO);
Chris@13 113
Chris@13 114 // explicit configFile option
Chris@13 115 if (isset($config['configFile'])) {
Chris@13 116 $this->configFile = $config['configFile'];
Chris@17 117 } elseif ($configFile = \getenv('PSYSH_CONFIG')) {
Chris@13 118 $this->configFile = $configFile;
Chris@13 119 }
Chris@13 120
Chris@13 121 // legacy baseDir option
Chris@13 122 if (isset($config['baseDir'])) {
Chris@13 123 $msg = "The 'baseDir' configuration option is deprecated; " .
Chris@13 124 "please specify 'configDir' and 'dataDir' options instead";
Chris@13 125 throw new DeprecatedException($msg);
Chris@13 126 }
Chris@13 127
Chris@13 128 unset($config['configFile'], $config['baseDir']);
Chris@13 129
Chris@13 130 // go go gadget, config!
Chris@13 131 $this->loadConfig($config);
Chris@13 132 $this->init();
Chris@13 133 }
Chris@13 134
Chris@13 135 /**
Chris@13 136 * Initialize the configuration.
Chris@13 137 *
Chris@13 138 * This checks for the presence of Readline and Pcntl extensions.
Chris@13 139 *
Chris@13 140 * If a config file is available, it will be loaded and merged with the current config.
Chris@13 141 *
Chris@13 142 * If no custom config file was specified and a local project config file
Chris@13 143 * is available, it will be loaded and merged with the current config.
Chris@13 144 */
Chris@13 145 public function init()
Chris@13 146 {
Chris@13 147 // feature detection
Chris@17 148 $this->hasReadline = \function_exists('readline');
Chris@17 149 $this->hasPcntl = \function_exists('pcntl_signal') && \function_exists('posix_getpid');
Chris@13 150
Chris@13 151 if ($configFile = $this->getConfigFile()) {
Chris@13 152 $this->loadConfigFile($configFile);
Chris@13 153 }
Chris@13 154
Chris@13 155 if (!$this->configFile && $localConfig = $this->getLocalConfigFile()) {
Chris@13 156 $this->loadConfigFile($localConfig);
Chris@13 157 }
Chris@13 158 }
Chris@13 159
Chris@13 160 /**
Chris@13 161 * Get the current PsySH config file.
Chris@13 162 *
Chris@13 163 * If a `configFile` option was passed to the Configuration constructor,
Chris@13 164 * this file will be returned. If not, all possible config directories will
Chris@13 165 * be searched, and the first `config.php` or `rc.php` file which exists
Chris@13 166 * will be returned.
Chris@13 167 *
Chris@13 168 * If you're trying to decide where to put your config file, pick
Chris@13 169 *
Chris@13 170 * ~/.config/psysh/config.php
Chris@13 171 *
Chris@13 172 * @return string
Chris@13 173 */
Chris@13 174 public function getConfigFile()
Chris@13 175 {
Chris@13 176 if (isset($this->configFile)) {
Chris@13 177 return $this->configFile;
Chris@13 178 }
Chris@13 179
Chris@13 180 $files = ConfigPaths::getConfigFiles(['config.php', 'rc.php'], $this->configDir);
Chris@13 181
Chris@13 182 if (!empty($files)) {
Chris@17 183 if ($this->warnOnMultipleConfigs && \count($files) > 1) {
Chris@17 184 $msg = \sprintf('Multiple configuration files found: %s. Using %s', \implode($files, ', '), $files[0]);
Chris@17 185 \trigger_error($msg, E_USER_NOTICE);
Chris@13 186 }
Chris@13 187
Chris@13 188 return $files[0];
Chris@13 189 }
Chris@13 190 }
Chris@13 191
Chris@13 192 /**
Chris@13 193 * Get the local PsySH config file.
Chris@13 194 *
Chris@13 195 * Searches for a project specific config file `.psysh.php` in the current
Chris@13 196 * working directory.
Chris@13 197 *
Chris@13 198 * @return string
Chris@13 199 */
Chris@13 200 public function getLocalConfigFile()
Chris@13 201 {
Chris@17 202 $localConfig = \getcwd() . '/.psysh.php';
Chris@13 203
Chris@17 204 if (@\is_file($localConfig)) {
Chris@13 205 return $localConfig;
Chris@13 206 }
Chris@13 207 }
Chris@13 208
Chris@13 209 /**
Chris@13 210 * Load configuration values from an array of options.
Chris@13 211 *
Chris@13 212 * @param array $options
Chris@13 213 */
Chris@13 214 public function loadConfig(array $options)
Chris@13 215 {
Chris@13 216 foreach (self::$AVAILABLE_OPTIONS as $option) {
Chris@13 217 if (isset($options[$option])) {
Chris@17 218 $method = 'set' . \ucfirst($option);
Chris@13 219 $this->$method($options[$option]);
Chris@13 220 }
Chris@13 221 }
Chris@13 222
Chris@13 223 // legacy `tabCompletion` option
Chris@13 224 if (isset($options['tabCompletion'])) {
Chris@13 225 $msg = '`tabCompletion` is deprecated; use `useTabCompletion` instead.';
Chris@17 226 @\trigger_error($msg, E_USER_DEPRECATED);
Chris@13 227
Chris@13 228 $this->setUseTabCompletion($options['tabCompletion']);
Chris@13 229 }
Chris@13 230
Chris@13 231 foreach (['commands', 'matchers', 'casters'] as $option) {
Chris@13 232 if (isset($options[$option])) {
Chris@17 233 $method = 'add' . \ucfirst($option);
Chris@13 234 $this->$method($options[$option]);
Chris@13 235 }
Chris@13 236 }
Chris@13 237
Chris@13 238 // legacy `tabCompletionMatchers` option
Chris@13 239 if (isset($options['tabCompletionMatchers'])) {
Chris@13 240 $msg = '`tabCompletionMatchers` is deprecated; use `matchers` instead.';
Chris@17 241 @\trigger_error($msg, E_USER_DEPRECATED);
Chris@13 242
Chris@13 243 $this->addMatchers($options['tabCompletionMatchers']);
Chris@13 244 }
Chris@13 245 }
Chris@13 246
Chris@13 247 /**
Chris@13 248 * Load a configuration file (default: `$HOME/.config/psysh/config.php`).
Chris@13 249 *
Chris@13 250 * This configuration instance will be available to the config file as $config.
Chris@13 251 * The config file may directly manipulate the configuration, or may return
Chris@13 252 * an array of options which will be merged with the current configuration.
Chris@13 253 *
Chris@13 254 * @throws \InvalidArgumentException if the config file returns a non-array result
Chris@13 255 *
Chris@13 256 * @param string $file
Chris@13 257 */
Chris@13 258 public function loadConfigFile($file)
Chris@13 259 {
Chris@13 260 $__psysh_config_file__ = $file;
Chris@13 261 $load = function ($config) use ($__psysh_config_file__) {
Chris@13 262 $result = require $__psysh_config_file__;
Chris@13 263 if ($result !== 1) {
Chris@13 264 return $result;
Chris@13 265 }
Chris@13 266 };
Chris@13 267 $result = $load($this);
Chris@13 268
Chris@13 269 if (!empty($result)) {
Chris@17 270 if (\is_array($result)) {
Chris@13 271 $this->loadConfig($result);
Chris@13 272 } else {
Chris@13 273 throw new \InvalidArgumentException('Psy Shell configuration must return an array of options');
Chris@13 274 }
Chris@13 275 }
Chris@13 276 }
Chris@13 277
Chris@13 278 /**
Chris@13 279 * Set files to be included by default at the start of each shell session.
Chris@13 280 *
Chris@13 281 * @param array $includes
Chris@13 282 */
Chris@13 283 public function setDefaultIncludes(array $includes = [])
Chris@13 284 {
Chris@13 285 $this->defaultIncludes = $includes;
Chris@13 286 }
Chris@13 287
Chris@13 288 /**
Chris@13 289 * Get files to be included by default at the start of each shell session.
Chris@13 290 *
Chris@13 291 * @return array
Chris@13 292 */
Chris@13 293 public function getDefaultIncludes()
Chris@13 294 {
Chris@13 295 return $this->defaultIncludes ?: [];
Chris@13 296 }
Chris@13 297
Chris@13 298 /**
Chris@13 299 * Set the shell's config directory location.
Chris@13 300 *
Chris@13 301 * @param string $dir
Chris@13 302 */
Chris@13 303 public function setConfigDir($dir)
Chris@13 304 {
Chris@13 305 $this->configDir = (string) $dir;
Chris@13 306 }
Chris@13 307
Chris@13 308 /**
Chris@13 309 * Get the current configuration directory, if any is explicitly set.
Chris@13 310 *
Chris@13 311 * @return string
Chris@13 312 */
Chris@13 313 public function getConfigDir()
Chris@13 314 {
Chris@13 315 return $this->configDir;
Chris@13 316 }
Chris@13 317
Chris@13 318 /**
Chris@13 319 * Set the shell's data directory location.
Chris@13 320 *
Chris@13 321 * @param string $dir
Chris@13 322 */
Chris@13 323 public function setDataDir($dir)
Chris@13 324 {
Chris@13 325 $this->dataDir = (string) $dir;
Chris@13 326 }
Chris@13 327
Chris@13 328 /**
Chris@13 329 * Get the current data directory, if any is explicitly set.
Chris@13 330 *
Chris@13 331 * @return string
Chris@13 332 */
Chris@13 333 public function getDataDir()
Chris@13 334 {
Chris@13 335 return $this->dataDir;
Chris@13 336 }
Chris@13 337
Chris@13 338 /**
Chris@13 339 * Set the shell's temporary directory location.
Chris@13 340 *
Chris@13 341 * @param string $dir
Chris@13 342 */
Chris@13 343 public function setRuntimeDir($dir)
Chris@13 344 {
Chris@13 345 $this->runtimeDir = (string) $dir;
Chris@13 346 }
Chris@13 347
Chris@13 348 /**
Chris@13 349 * Get the shell's temporary directory location.
Chris@13 350 *
Chris@13 351 * Defaults to `/psysh` inside the system's temp dir unless explicitly
Chris@13 352 * overridden.
Chris@13 353 *
Chris@13 354 * @return string
Chris@13 355 */
Chris@13 356 public function getRuntimeDir()
Chris@13 357 {
Chris@13 358 if (!isset($this->runtimeDir)) {
Chris@13 359 $this->runtimeDir = ConfigPaths::getRuntimeDir();
Chris@13 360 }
Chris@13 361
Chris@17 362 if (!\is_dir($this->runtimeDir)) {
Chris@17 363 \mkdir($this->runtimeDir, 0700, true);
Chris@13 364 }
Chris@13 365
Chris@13 366 return $this->runtimeDir;
Chris@13 367 }
Chris@13 368
Chris@13 369 /**
Chris@13 370 * Set the readline history file path.
Chris@13 371 *
Chris@13 372 * @param string $file
Chris@13 373 */
Chris@13 374 public function setHistoryFile($file)
Chris@13 375 {
Chris@13 376 $this->historyFile = ConfigPaths::touchFileWithMkdir($file);
Chris@13 377 }
Chris@13 378
Chris@13 379 /**
Chris@13 380 * Get the readline history file path.
Chris@13 381 *
Chris@13 382 * Defaults to `/history` inside the shell's base config dir unless
Chris@13 383 * explicitly overridden.
Chris@13 384 *
Chris@13 385 * @return string
Chris@13 386 */
Chris@13 387 public function getHistoryFile()
Chris@13 388 {
Chris@13 389 if (isset($this->historyFile)) {
Chris@13 390 return $this->historyFile;
Chris@13 391 }
Chris@13 392
Chris@13 393 $files = ConfigPaths::getConfigFiles(['psysh_history', 'history'], $this->configDir);
Chris@13 394
Chris@13 395 if (!empty($files)) {
Chris@17 396 if ($this->warnOnMultipleConfigs && \count($files) > 1) {
Chris@17 397 $msg = \sprintf('Multiple history files found: %s. Using %s', \implode($files, ', '), $files[0]);
Chris@17 398 \trigger_error($msg, E_USER_NOTICE);
Chris@13 399 }
Chris@13 400
Chris@13 401 $this->setHistoryFile($files[0]);
Chris@13 402 } else {
Chris@13 403 // fallback: create our own history file
Chris@13 404 $dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
Chris@13 405 $this->setHistoryFile($dir . '/psysh_history');
Chris@13 406 }
Chris@13 407
Chris@13 408 return $this->historyFile;
Chris@13 409 }
Chris@13 410
Chris@13 411 /**
Chris@13 412 * Set the readline max history size.
Chris@13 413 *
Chris@13 414 * @param int $value
Chris@13 415 */
Chris@13 416 public function setHistorySize($value)
Chris@13 417 {
Chris@13 418 $this->historySize = (int) $value;
Chris@13 419 }
Chris@13 420
Chris@13 421 /**
Chris@13 422 * Get the readline max history size.
Chris@13 423 *
Chris@13 424 * @return int
Chris@13 425 */
Chris@13 426 public function getHistorySize()
Chris@13 427 {
Chris@13 428 return $this->historySize;
Chris@13 429 }
Chris@13 430
Chris@13 431 /**
Chris@13 432 * Sets whether readline erases old duplicate history entries.
Chris@13 433 *
Chris@13 434 * @param bool $value
Chris@13 435 */
Chris@13 436 public function setEraseDuplicates($value)
Chris@13 437 {
Chris@13 438 $this->eraseDuplicates = (bool) $value;
Chris@13 439 }
Chris@13 440
Chris@13 441 /**
Chris@13 442 * Get whether readline erases old duplicate history entries.
Chris@13 443 *
Chris@13 444 * @return bool
Chris@13 445 */
Chris@13 446 public function getEraseDuplicates()
Chris@13 447 {
Chris@13 448 return $this->eraseDuplicates;
Chris@13 449 }
Chris@13 450
Chris@13 451 /**
Chris@13 452 * Get a temporary file of type $type for process $pid.
Chris@13 453 *
Chris@13 454 * The file will be created inside the current temporary directory.
Chris@13 455 *
Chris@13 456 * @see self::getRuntimeDir
Chris@13 457 *
Chris@13 458 * @param string $type
Chris@13 459 * @param int $pid
Chris@13 460 *
Chris@13 461 * @return string Temporary file name
Chris@13 462 */
Chris@13 463 public function getTempFile($type, $pid)
Chris@13 464 {
Chris@17 465 return \tempnam($this->getRuntimeDir(), $type . '_' . $pid . '_');
Chris@13 466 }
Chris@13 467
Chris@13 468 /**
Chris@13 469 * Get a filename suitable for a FIFO pipe of $type for process $pid.
Chris@13 470 *
Chris@13 471 * The pipe will be created inside the current temporary directory.
Chris@13 472 *
Chris@13 473 * @param string $type
Chris@13 474 * @param int $pid
Chris@13 475 *
Chris@13 476 * @return string Pipe name
Chris@13 477 */
Chris@13 478 public function getPipe($type, $pid)
Chris@13 479 {
Chris@17 480 return \sprintf('%s/%s_%s', $this->getRuntimeDir(), $type, $pid);
Chris@13 481 }
Chris@13 482
Chris@13 483 /**
Chris@13 484 * Check whether this PHP instance has Readline available.
Chris@13 485 *
Chris@13 486 * @return bool True if Readline is available
Chris@13 487 */
Chris@13 488 public function hasReadline()
Chris@13 489 {
Chris@13 490 return $this->hasReadline;
Chris@13 491 }
Chris@13 492
Chris@13 493 /**
Chris@13 494 * Enable or disable Readline usage.
Chris@13 495 *
Chris@13 496 * @param bool $useReadline
Chris@13 497 */
Chris@13 498 public function setUseReadline($useReadline)
Chris@13 499 {
Chris@13 500 $this->useReadline = (bool) $useReadline;
Chris@13 501 }
Chris@13 502
Chris@13 503 /**
Chris@13 504 * Check whether to use Readline.
Chris@13 505 *
Chris@13 506 * If `setUseReadline` as been set to true, but Readline is not actually
Chris@13 507 * available, this will return false.
Chris@13 508 *
Chris@13 509 * @return bool True if the current Shell should use Readline
Chris@13 510 */
Chris@13 511 public function useReadline()
Chris@13 512 {
Chris@13 513 return isset($this->useReadline) ? ($this->hasReadline && $this->useReadline) : $this->hasReadline;
Chris@13 514 }
Chris@13 515
Chris@13 516 /**
Chris@13 517 * Set the Psy Shell readline service.
Chris@13 518 *
Chris@13 519 * @param Readline $readline
Chris@13 520 */
Chris@13 521 public function setReadline(Readline $readline)
Chris@13 522 {
Chris@13 523 $this->readline = $readline;
Chris@13 524 }
Chris@13 525
Chris@13 526 /**
Chris@13 527 * Get the Psy Shell readline service.
Chris@13 528 *
Chris@13 529 * By default, this service uses (in order of preference):
Chris@13 530 *
Chris@13 531 * * GNU Readline
Chris@13 532 * * Libedit
Chris@13 533 * * A transient array-based readline emulation.
Chris@13 534 *
Chris@13 535 * @return Readline
Chris@13 536 */
Chris@13 537 public function getReadline()
Chris@13 538 {
Chris@13 539 if (!isset($this->readline)) {
Chris@13 540 $className = $this->getReadlineClass();
Chris@13 541 $this->readline = new $className(
Chris@13 542 $this->getHistoryFile(),
Chris@13 543 $this->getHistorySize(),
Chris@13 544 $this->getEraseDuplicates()
Chris@13 545 );
Chris@13 546 }
Chris@13 547
Chris@13 548 return $this->readline;
Chris@13 549 }
Chris@13 550
Chris@13 551 /**
Chris@13 552 * Get the appropriate Readline implementation class name.
Chris@13 553 *
Chris@13 554 * @see self::getReadline
Chris@13 555 *
Chris@13 556 * @return string
Chris@13 557 */
Chris@13 558 private function getReadlineClass()
Chris@13 559 {
Chris@13 560 if ($this->useReadline()) {
Chris@13 561 if (GNUReadline::isSupported()) {
Chris@13 562 return 'Psy\Readline\GNUReadline';
Chris@13 563 } elseif (Libedit::isSupported()) {
Chris@13 564 return 'Psy\Readline\Libedit';
Chris@13 565 } elseif (HoaConsole::isSupported()) {
Chris@13 566 return 'Psy\Readline\HoaConsole';
Chris@13 567 }
Chris@13 568 }
Chris@13 569
Chris@13 570 return 'Psy\Readline\Transient';
Chris@13 571 }
Chris@13 572
Chris@13 573 /**
Chris@13 574 * Enable or disable bracketed paste.
Chris@13 575 *
Chris@13 576 * Note that this only works with readline (not libedit) integration for now.
Chris@13 577 *
Chris@13 578 * @param bool $useBracketedPaste
Chris@13 579 */
Chris@13 580 public function setUseBracketedPaste($useBracketedPaste)
Chris@13 581 {
Chris@13 582 $this->useBracketedPaste = (bool) $useBracketedPaste;
Chris@13 583 }
Chris@13 584
Chris@13 585 /**
Chris@13 586 * Check whether to use bracketed paste with readline.
Chris@13 587 *
Chris@13 588 * When this works, it's magical. Tabs in pastes don't try to autcomplete.
Chris@13 589 * Newlines in paste don't execute code until you get to the end. It makes
Chris@13 590 * readline act like you'd expect when pasting.
Chris@13 591 *
Chris@13 592 * But it often (usually?) does not work. And when it doesn't, it just spews
Chris@13 593 * escape codes all over the place and generally makes things ugly :(
Chris@13 594 *
Chris@13 595 * If `useBracketedPaste` has been set to true, but the current readline
Chris@13 596 * implementation is anything besides GNU readline, this will return false.
Chris@13 597 *
Chris@13 598 * @return bool True if the shell should use bracketed paste
Chris@13 599 */
Chris@13 600 public function useBracketedPaste()
Chris@13 601 {
Chris@13 602 // For now, only the GNU readline implementation supports bracketed paste.
Chris@13 603 $supported = ($this->getReadlineClass() === 'Psy\Readline\GNUReadline');
Chris@13 604
Chris@13 605 return $supported && $this->useBracketedPaste;
Chris@13 606
Chris@13 607 // @todo mebbe turn this on by default some day?
Chris@13 608 // return isset($this->useBracketedPaste) ? ($supported && $this->useBracketedPaste) : $supported;
Chris@13 609 }
Chris@13 610
Chris@13 611 /**
Chris@13 612 * Check whether this PHP instance has Pcntl available.
Chris@13 613 *
Chris@13 614 * @return bool True if Pcntl is available
Chris@13 615 */
Chris@13 616 public function hasPcntl()
Chris@13 617 {
Chris@13 618 return $this->hasPcntl;
Chris@13 619 }
Chris@13 620
Chris@13 621 /**
Chris@13 622 * Enable or disable Pcntl usage.
Chris@13 623 *
Chris@13 624 * @param bool $usePcntl
Chris@13 625 */
Chris@13 626 public function setUsePcntl($usePcntl)
Chris@13 627 {
Chris@13 628 $this->usePcntl = (bool) $usePcntl;
Chris@13 629 }
Chris@13 630
Chris@13 631 /**
Chris@13 632 * Check whether to use Pcntl.
Chris@13 633 *
Chris@13 634 * If `setUsePcntl` has been set to true, but Pcntl is not actually
Chris@13 635 * available, this will return false.
Chris@13 636 *
Chris@13 637 * @return bool True if the current Shell should use Pcntl
Chris@13 638 */
Chris@13 639 public function usePcntl()
Chris@13 640 {
Chris@13 641 return isset($this->usePcntl) ? ($this->hasPcntl && $this->usePcntl) : $this->hasPcntl;
Chris@13 642 }
Chris@13 643
Chris@13 644 /**
Chris@13 645 * Enable or disable strict requirement of semicolons.
Chris@13 646 *
Chris@13 647 * @see self::requireSemicolons()
Chris@13 648 *
Chris@13 649 * @param bool $requireSemicolons
Chris@13 650 */
Chris@13 651 public function setRequireSemicolons($requireSemicolons)
Chris@13 652 {
Chris@13 653 $this->requireSemicolons = (bool) $requireSemicolons;
Chris@13 654 }
Chris@13 655
Chris@13 656 /**
Chris@13 657 * Check whether to require semicolons on all statements.
Chris@13 658 *
Chris@13 659 * By default, PsySH will automatically insert semicolons at the end of
Chris@13 660 * statements if they're missing. To strictly require semicolons, set
Chris@13 661 * `requireSemicolons` to true.
Chris@13 662 *
Chris@13 663 * @return bool
Chris@13 664 */
Chris@13 665 public function requireSemicolons()
Chris@13 666 {
Chris@13 667 return $this->requireSemicolons;
Chris@13 668 }
Chris@13 669
Chris@13 670 /**
Chris@13 671 * Enable or disable Unicode in PsySH specific output.
Chris@13 672 *
Chris@13 673 * Note that this does not disable Unicode output in general, it just makes
Chris@13 674 * it so PsySH won't output any itself.
Chris@13 675 *
Chris@13 676 * @param bool $useUnicode
Chris@13 677 */
Chris@13 678 public function setUseUnicode($useUnicode)
Chris@13 679 {
Chris@13 680 $this->useUnicode = (bool) $useUnicode;
Chris@13 681 }
Chris@13 682
Chris@13 683 /**
Chris@13 684 * Check whether to use Unicode in PsySH specific output.
Chris@13 685 *
Chris@13 686 * Note that this does not disable Unicode output in general, it just makes
Chris@13 687 * it so PsySH won't output any itself.
Chris@13 688 *
Chris@13 689 * @return bool
Chris@13 690 */
Chris@13 691 public function useUnicode()
Chris@13 692 {
Chris@13 693 if (isset($this->useUnicode)) {
Chris@13 694 return $this->useUnicode;
Chris@13 695 }
Chris@13 696
Chris@13 697 // @todo detect `chsh` != 65001 on Windows and return false
Chris@13 698 return true;
Chris@13 699 }
Chris@13 700
Chris@13 701 /**
Chris@13 702 * Set the error logging level.
Chris@13 703 *
Chris@13 704 * @see self::errorLoggingLevel
Chris@13 705 *
Chris@13 706 * @param bool $errorLoggingLevel
Chris@13 707 */
Chris@13 708 public function setErrorLoggingLevel($errorLoggingLevel)
Chris@13 709 {
Chris@13 710 $this->errorLoggingLevel = (E_ALL | E_STRICT) & $errorLoggingLevel;
Chris@13 711 }
Chris@13 712
Chris@13 713 /**
Chris@13 714 * Get the current error logging level.
Chris@13 715 *
Chris@13 716 * By default, PsySH will automatically log all errors, regardless of the
Chris@13 717 * current `error_reporting` level. Additionally, if the `error_reporting`
Chris@13 718 * level warrants, an ErrorException will be thrown.
Chris@13 719 *
Chris@13 720 * Set `errorLoggingLevel` to 0 to prevent logging non-thrown errors. Set it
Chris@13 721 * to any valid error_reporting value to log only errors which match that
Chris@13 722 * level.
Chris@13 723 *
Chris@13 724 * http://php.net/manual/en/function.error-reporting.php
Chris@13 725 *
Chris@13 726 * @return int
Chris@13 727 */
Chris@13 728 public function errorLoggingLevel()
Chris@13 729 {
Chris@13 730 return $this->errorLoggingLevel;
Chris@13 731 }
Chris@13 732
Chris@13 733 /**
Chris@13 734 * Set a CodeCleaner service instance.
Chris@13 735 *
Chris@13 736 * @param CodeCleaner $cleaner
Chris@13 737 */
Chris@13 738 public function setCodeCleaner(CodeCleaner $cleaner)
Chris@13 739 {
Chris@13 740 $this->cleaner = $cleaner;
Chris@13 741 }
Chris@13 742
Chris@13 743 /**
Chris@13 744 * Get a CodeCleaner service instance.
Chris@13 745 *
Chris@13 746 * If none has been explicitly defined, this will create a new instance.
Chris@13 747 *
Chris@13 748 * @return CodeCleaner
Chris@13 749 */
Chris@13 750 public function getCodeCleaner()
Chris@13 751 {
Chris@13 752 if (!isset($this->cleaner)) {
Chris@13 753 $this->cleaner = new CodeCleaner();
Chris@13 754 }
Chris@13 755
Chris@13 756 return $this->cleaner;
Chris@13 757 }
Chris@13 758
Chris@13 759 /**
Chris@13 760 * Enable or disable tab completion.
Chris@13 761 *
Chris@13 762 * @param bool $useTabCompletion
Chris@13 763 */
Chris@13 764 public function setUseTabCompletion($useTabCompletion)
Chris@13 765 {
Chris@13 766 $this->useTabCompletion = (bool) $useTabCompletion;
Chris@13 767 }
Chris@13 768
Chris@13 769 /**
Chris@13 770 * @deprecated Call `setUseTabCompletion` instead
Chris@13 771 *
Chris@13 772 * @param bool $useTabCompletion
Chris@13 773 */
Chris@13 774 public function setTabCompletion($useTabCompletion)
Chris@13 775 {
Chris@13 776 $this->setUseTabCompletion($useTabCompletion);
Chris@13 777 }
Chris@13 778
Chris@13 779 /**
Chris@13 780 * Check whether to use tab completion.
Chris@13 781 *
Chris@13 782 * If `setUseTabCompletion` has been set to true, but readline is not
Chris@13 783 * actually available, this will return false.
Chris@13 784 *
Chris@13 785 * @return bool True if the current Shell should use tab completion
Chris@13 786 */
Chris@13 787 public function useTabCompletion()
Chris@13 788 {
Chris@13 789 return isset($this->useTabCompletion) ? ($this->hasReadline && $this->useTabCompletion) : $this->hasReadline;
Chris@13 790 }
Chris@13 791
Chris@13 792 /**
Chris@13 793 * @deprecated Call `useTabCompletion` instead
Chris@13 794 *
Chris@13 795 * @return bool
Chris@13 796 */
Chris@13 797 public function getTabCompletion()
Chris@13 798 {
Chris@13 799 return $this->useTabCompletion();
Chris@13 800 }
Chris@13 801
Chris@13 802 /**
Chris@13 803 * Set the Shell Output service.
Chris@13 804 *
Chris@13 805 * @param ShellOutput $output
Chris@13 806 */
Chris@13 807 public function setOutput(ShellOutput $output)
Chris@13 808 {
Chris@13 809 $this->output = $output;
Chris@13 810 }
Chris@13 811
Chris@13 812 /**
Chris@13 813 * Get a Shell Output service instance.
Chris@13 814 *
Chris@13 815 * If none has been explicitly provided, this will create a new instance
Chris@13 816 * with VERBOSITY_NORMAL and the output page supplied by self::getPager
Chris@13 817 *
Chris@13 818 * @see self::getPager
Chris@13 819 *
Chris@13 820 * @return ShellOutput
Chris@13 821 */
Chris@13 822 public function getOutput()
Chris@13 823 {
Chris@13 824 if (!isset($this->output)) {
Chris@13 825 $this->output = new ShellOutput(
Chris@13 826 ShellOutput::VERBOSITY_NORMAL,
Chris@13 827 $this->getOutputDecorated(),
Chris@13 828 null,
Chris@13 829 $this->getPager()
Chris@13 830 );
Chris@13 831 }
Chris@13 832
Chris@13 833 return $this->output;
Chris@13 834 }
Chris@13 835
Chris@13 836 /**
Chris@13 837 * Get the decoration (i.e. color) setting for the Shell Output service.
Chris@13 838 *
Chris@13 839 * @return null|bool 3-state boolean corresponding to the current color mode
Chris@13 840 */
Chris@13 841 public function getOutputDecorated()
Chris@13 842 {
Chris@13 843 if ($this->colorMode() === self::COLOR_MODE_AUTO) {
Chris@13 844 return;
Chris@13 845 } elseif ($this->colorMode() === self::COLOR_MODE_FORCED) {
Chris@13 846 return true;
Chris@13 847 } elseif ($this->colorMode() === self::COLOR_MODE_DISABLED) {
Chris@13 848 return false;
Chris@13 849 }
Chris@13 850 }
Chris@13 851
Chris@13 852 /**
Chris@13 853 * Set the OutputPager service.
Chris@13 854 *
Chris@13 855 * If a string is supplied, a ProcOutputPager will be used which shells out
Chris@13 856 * to the specified command.
Chris@13 857 *
Chris@13 858 * @throws \InvalidArgumentException if $pager is not a string or OutputPager instance
Chris@13 859 *
Chris@13 860 * @param string|OutputPager $pager
Chris@13 861 */
Chris@13 862 public function setPager($pager)
Chris@13 863 {
Chris@17 864 if ($pager && !\is_string($pager) && !$pager instanceof OutputPager) {
Chris@13 865 throw new \InvalidArgumentException('Unexpected pager instance');
Chris@13 866 }
Chris@13 867
Chris@13 868 $this->pager = $pager;
Chris@13 869 }
Chris@13 870
Chris@13 871 /**
Chris@13 872 * Get an OutputPager instance or a command for an external Proc pager.
Chris@13 873 *
Chris@13 874 * If no Pager has been explicitly provided, and Pcntl is available, this
Chris@13 875 * will default to `cli.pager` ini value, falling back to `which less`.
Chris@13 876 *
Chris@13 877 * @return string|OutputPager
Chris@13 878 */
Chris@13 879 public function getPager()
Chris@13 880 {
Chris@13 881 if (!isset($this->pager) && $this->usePcntl()) {
Chris@17 882 if ($pager = \ini_get('cli.pager')) {
Chris@16 883 // use the default pager
Chris@13 884 $this->pager = $pager;
Chris@17 885 } elseif ($less = \exec('which less 2>/dev/null')) {
Chris@13 886 // check for the presence of less...
Chris@13 887 $this->pager = $less . ' -R -S -F -X';
Chris@13 888 }
Chris@13 889 }
Chris@13 890
Chris@13 891 return $this->pager;
Chris@13 892 }
Chris@13 893
Chris@13 894 /**
Chris@13 895 * Set the Shell AutoCompleter service.
Chris@13 896 *
Chris@13 897 * @param AutoCompleter $autoCompleter
Chris@13 898 */
Chris@13 899 public function setAutoCompleter(AutoCompleter $autoCompleter)
Chris@13 900 {
Chris@13 901 $this->autoCompleter = $autoCompleter;
Chris@13 902 }
Chris@13 903
Chris@13 904 /**
Chris@13 905 * Get an AutoCompleter service instance.
Chris@13 906 *
Chris@13 907 * @return AutoCompleter
Chris@13 908 */
Chris@13 909 public function getAutoCompleter()
Chris@13 910 {
Chris@13 911 if (!isset($this->autoCompleter)) {
Chris@13 912 $this->autoCompleter = new AutoCompleter();
Chris@13 913 }
Chris@13 914
Chris@13 915 return $this->autoCompleter;
Chris@13 916 }
Chris@13 917
Chris@13 918 /**
Chris@13 919 * @deprecated Nothing should be using this anymore
Chris@13 920 *
Chris@13 921 * @return array
Chris@13 922 */
Chris@13 923 public function getTabCompletionMatchers()
Chris@13 924 {
Chris@13 925 return [];
Chris@13 926 }
Chris@13 927
Chris@13 928 /**
Chris@13 929 * Add tab completion matchers to the AutoCompleter.
Chris@13 930 *
Chris@13 931 * This will buffer new matchers in the event that the Shell has not yet
Chris@13 932 * been instantiated. This allows the user to specify matchers in their
Chris@13 933 * config rc file, despite the fact that their file is needed in the Shell
Chris@13 934 * constructor.
Chris@13 935 *
Chris@13 936 * @param array $matchers
Chris@13 937 */
Chris@13 938 public function addMatchers(array $matchers)
Chris@13 939 {
Chris@17 940 $this->newMatchers = \array_merge($this->newMatchers, $matchers);
Chris@13 941 if (isset($this->shell)) {
Chris@13 942 $this->doAddMatchers();
Chris@13 943 }
Chris@13 944 }
Chris@13 945
Chris@13 946 /**
Chris@13 947 * Internal method for adding tab completion matchers. This will set any new
Chris@13 948 * matchers once a Shell is available.
Chris@13 949 */
Chris@13 950 private function doAddMatchers()
Chris@13 951 {
Chris@13 952 if (!empty($this->newMatchers)) {
Chris@13 953 $this->shell->addMatchers($this->newMatchers);
Chris@13 954 $this->newMatchers = [];
Chris@13 955 }
Chris@13 956 }
Chris@13 957
Chris@13 958 /**
Chris@13 959 * @deprecated Use `addMatchers` instead
Chris@13 960 *
Chris@13 961 * @param array $matchers
Chris@13 962 */
Chris@13 963 public function addTabCompletionMatchers(array $matchers)
Chris@13 964 {
Chris@13 965 $this->addMatchers($matchers);
Chris@13 966 }
Chris@13 967
Chris@13 968 /**
Chris@13 969 * Add commands to the Shell.
Chris@13 970 *
Chris@13 971 * This will buffer new commands in the event that the Shell has not yet
Chris@13 972 * been instantiated. This allows the user to specify commands in their
Chris@13 973 * config rc file, despite the fact that their file is needed in the Shell
Chris@13 974 * constructor.
Chris@13 975 *
Chris@13 976 * @param array $commands
Chris@13 977 */
Chris@13 978 public function addCommands(array $commands)
Chris@13 979 {
Chris@17 980 $this->newCommands = \array_merge($this->newCommands, $commands);
Chris@13 981 if (isset($this->shell)) {
Chris@13 982 $this->doAddCommands();
Chris@13 983 }
Chris@13 984 }
Chris@13 985
Chris@13 986 /**
Chris@13 987 * Internal method for adding commands. This will set any new commands once
Chris@13 988 * a Shell is available.
Chris@13 989 */
Chris@13 990 private function doAddCommands()
Chris@13 991 {
Chris@13 992 if (!empty($this->newCommands)) {
Chris@13 993 $this->shell->addCommands($this->newCommands);
Chris@13 994 $this->newCommands = [];
Chris@13 995 }
Chris@13 996 }
Chris@13 997
Chris@13 998 /**
Chris@13 999 * Set the Shell backreference and add any new commands to the Shell.
Chris@13 1000 *
Chris@13 1001 * @param Shell $shell
Chris@13 1002 */
Chris@13 1003 public function setShell(Shell $shell)
Chris@13 1004 {
Chris@13 1005 $this->shell = $shell;
Chris@13 1006 $this->doAddCommands();
Chris@13 1007 $this->doAddMatchers();
Chris@13 1008 }
Chris@13 1009
Chris@13 1010 /**
Chris@13 1011 * Set the PHP manual database file.
Chris@13 1012 *
Chris@13 1013 * This file should be an SQLite database generated from the phpdoc source
Chris@13 1014 * with the `bin/build_manual` script.
Chris@13 1015 *
Chris@13 1016 * @param string $filename
Chris@13 1017 */
Chris@13 1018 public function setManualDbFile($filename)
Chris@13 1019 {
Chris@13 1020 $this->manualDbFile = (string) $filename;
Chris@13 1021 }
Chris@13 1022
Chris@13 1023 /**
Chris@13 1024 * Get the current PHP manual database file.
Chris@13 1025 *
Chris@13 1026 * @return string Default: '~/.local/share/psysh/php_manual.sqlite'
Chris@13 1027 */
Chris@13 1028 public function getManualDbFile()
Chris@13 1029 {
Chris@13 1030 if (isset($this->manualDbFile)) {
Chris@13 1031 return $this->manualDbFile;
Chris@13 1032 }
Chris@13 1033
Chris@13 1034 $files = ConfigPaths::getDataFiles(['php_manual.sqlite'], $this->dataDir);
Chris@13 1035 if (!empty($files)) {
Chris@17 1036 if ($this->warnOnMultipleConfigs && \count($files) > 1) {
Chris@17 1037 $msg = \sprintf('Multiple manual database files found: %s. Using %s', \implode($files, ', '), $files[0]);
Chris@17 1038 \trigger_error($msg, E_USER_NOTICE);
Chris@13 1039 }
Chris@13 1040
Chris@13 1041 return $this->manualDbFile = $files[0];
Chris@13 1042 }
Chris@13 1043 }
Chris@13 1044
Chris@13 1045 /**
Chris@13 1046 * Get a PHP manual database connection.
Chris@13 1047 *
Chris@13 1048 * @return \PDO
Chris@13 1049 */
Chris@13 1050 public function getManualDb()
Chris@13 1051 {
Chris@13 1052 if (!isset($this->manualDb)) {
Chris@13 1053 $dbFile = $this->getManualDbFile();
Chris@17 1054 if (\is_file($dbFile)) {
Chris@13 1055 try {
Chris@13 1056 $this->manualDb = new \PDO('sqlite:' . $dbFile);
Chris@13 1057 } catch (\PDOException $e) {
Chris@13 1058 if ($e->getMessage() === 'could not find driver') {
Chris@13 1059 throw new RuntimeException('SQLite PDO driver not found', 0, $e);
Chris@13 1060 } else {
Chris@13 1061 throw $e;
Chris@13 1062 }
Chris@13 1063 }
Chris@13 1064 }
Chris@13 1065 }
Chris@13 1066
Chris@13 1067 return $this->manualDb;
Chris@13 1068 }
Chris@13 1069
Chris@13 1070 /**
Chris@13 1071 * Add an array of casters definitions.
Chris@13 1072 *
Chris@13 1073 * @param array $casters
Chris@13 1074 */
Chris@13 1075 public function addCasters(array $casters)
Chris@13 1076 {
Chris@13 1077 $this->getPresenter()->addCasters($casters);
Chris@13 1078 }
Chris@13 1079
Chris@13 1080 /**
Chris@13 1081 * Get the Presenter service.
Chris@13 1082 *
Chris@13 1083 * @return Presenter
Chris@13 1084 */
Chris@13 1085 public function getPresenter()
Chris@13 1086 {
Chris@13 1087 if (!isset($this->presenter)) {
Chris@13 1088 $this->presenter = new Presenter($this->getOutput()->getFormatter(), $this->forceArrayIndexes());
Chris@13 1089 }
Chris@13 1090
Chris@13 1091 return $this->presenter;
Chris@13 1092 }
Chris@13 1093
Chris@13 1094 /**
Chris@13 1095 * Enable or disable warnings on multiple configuration or data files.
Chris@13 1096 *
Chris@13 1097 * @see self::warnOnMultipleConfigs()
Chris@13 1098 *
Chris@13 1099 * @param bool $warnOnMultipleConfigs
Chris@13 1100 */
Chris@13 1101 public function setWarnOnMultipleConfigs($warnOnMultipleConfigs)
Chris@13 1102 {
Chris@13 1103 $this->warnOnMultipleConfigs = (bool) $warnOnMultipleConfigs;
Chris@13 1104 }
Chris@13 1105
Chris@13 1106 /**
Chris@13 1107 * Check whether to warn on multiple configuration or data files.
Chris@13 1108 *
Chris@13 1109 * By default, PsySH will use the file with highest precedence, and will
Chris@13 1110 * silently ignore all others. With this enabled, a warning will be emitted
Chris@13 1111 * (but not an exception thrown) if multiple configuration or data files
Chris@13 1112 * are found.
Chris@13 1113 *
Chris@13 1114 * This will default to true in a future release, but is false for now.
Chris@13 1115 *
Chris@13 1116 * @return bool
Chris@13 1117 */
Chris@13 1118 public function warnOnMultipleConfigs()
Chris@13 1119 {
Chris@13 1120 return $this->warnOnMultipleConfigs;
Chris@13 1121 }
Chris@13 1122
Chris@13 1123 /**
Chris@13 1124 * Set the current color mode.
Chris@13 1125 *
Chris@13 1126 * @param string $colorMode
Chris@13 1127 */
Chris@13 1128 public function setColorMode($colorMode)
Chris@13 1129 {
Chris@13 1130 $validColorModes = [
Chris@13 1131 self::COLOR_MODE_AUTO,
Chris@13 1132 self::COLOR_MODE_FORCED,
Chris@13 1133 self::COLOR_MODE_DISABLED,
Chris@13 1134 ];
Chris@13 1135
Chris@17 1136 if (\in_array($colorMode, $validColorModes)) {
Chris@13 1137 $this->colorMode = $colorMode;
Chris@13 1138 } else {
Chris@13 1139 throw new \InvalidArgumentException('invalid color mode: ' . $colorMode);
Chris@13 1140 }
Chris@13 1141 }
Chris@13 1142
Chris@13 1143 /**
Chris@13 1144 * Get the current color mode.
Chris@13 1145 *
Chris@13 1146 * @return string
Chris@13 1147 */
Chris@13 1148 public function colorMode()
Chris@13 1149 {
Chris@13 1150 return $this->colorMode;
Chris@13 1151 }
Chris@13 1152
Chris@13 1153 /**
Chris@13 1154 * Set an update checker service instance.
Chris@13 1155 *
Chris@13 1156 * @param Checker $checker
Chris@13 1157 */
Chris@13 1158 public function setChecker(Checker $checker)
Chris@13 1159 {
Chris@13 1160 $this->checker = $checker;
Chris@13 1161 }
Chris@13 1162
Chris@13 1163 /**
Chris@13 1164 * Get an update checker service instance.
Chris@13 1165 *
Chris@13 1166 * If none has been explicitly defined, this will create a new instance.
Chris@13 1167 *
Chris@13 1168 * @return Checker
Chris@13 1169 */
Chris@13 1170 public function getChecker()
Chris@13 1171 {
Chris@13 1172 if (!isset($this->checker)) {
Chris@13 1173 $interval = $this->getUpdateCheck();
Chris@13 1174 switch ($interval) {
Chris@13 1175 case Checker::ALWAYS:
Chris@13 1176 $this->checker = new GitHubChecker();
Chris@13 1177 break;
Chris@13 1178
Chris@13 1179 case Checker::DAILY:
Chris@13 1180 case Checker::WEEKLY:
Chris@13 1181 case Checker::MONTHLY:
Chris@13 1182 $checkFile = $this->getUpdateCheckCacheFile();
Chris@13 1183 if ($checkFile === false) {
Chris@13 1184 $this->checker = new NoopChecker();
Chris@13 1185 } else {
Chris@13 1186 $this->checker = new IntervalChecker($checkFile, $interval);
Chris@13 1187 }
Chris@13 1188 break;
Chris@13 1189
Chris@13 1190 case Checker::NEVER:
Chris@13 1191 $this->checker = new NoopChecker();
Chris@13 1192 break;
Chris@13 1193 }
Chris@13 1194 }
Chris@13 1195
Chris@13 1196 return $this->checker;
Chris@13 1197 }
Chris@13 1198
Chris@13 1199 /**
Chris@13 1200 * Get the current update check interval.
Chris@13 1201 *
Chris@13 1202 * One of 'always', 'daily', 'weekly', 'monthly' or 'never'. If none is
Chris@13 1203 * explicitly set, default to 'weekly'.
Chris@13 1204 *
Chris@13 1205 * @return string
Chris@13 1206 */
Chris@13 1207 public function getUpdateCheck()
Chris@13 1208 {
Chris@13 1209 return isset($this->updateCheck) ? $this->updateCheck : Checker::WEEKLY;
Chris@13 1210 }
Chris@13 1211
Chris@13 1212 /**
Chris@13 1213 * Set the update check interval.
Chris@13 1214 *
Chris@13 1215 * @throws \InvalidArgumentDescription if the update check interval is unknown
Chris@13 1216 *
Chris@13 1217 * @param string $interval
Chris@13 1218 */
Chris@13 1219 public function setUpdateCheck($interval)
Chris@13 1220 {
Chris@13 1221 $validIntervals = [
Chris@13 1222 Checker::ALWAYS,
Chris@13 1223 Checker::DAILY,
Chris@13 1224 Checker::WEEKLY,
Chris@13 1225 Checker::MONTHLY,
Chris@13 1226 Checker::NEVER,
Chris@13 1227 ];
Chris@13 1228
Chris@17 1229 if (!\in_array($interval, $validIntervals)) {
Chris@13 1230 throw new \InvalidArgumentException('invalid update check interval: ' . $interval);
Chris@13 1231 }
Chris@13 1232
Chris@13 1233 $this->updateCheck = $interval;
Chris@13 1234 }
Chris@13 1235
Chris@13 1236 /**
Chris@13 1237 * Get a cache file path for the update checker.
Chris@13 1238 *
Chris@13 1239 * @return string|false Return false if config file/directory is not writable
Chris@13 1240 */
Chris@13 1241 public function getUpdateCheckCacheFile()
Chris@13 1242 {
Chris@13 1243 $dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
Chris@13 1244
Chris@13 1245 return ConfigPaths::touchFileWithMkdir($dir . '/update_check.json');
Chris@13 1246 }
Chris@13 1247
Chris@13 1248 /**
Chris@13 1249 * Set the startup message.
Chris@13 1250 *
Chris@13 1251 * @param string $message
Chris@13 1252 */
Chris@13 1253 public function setStartupMessage($message)
Chris@13 1254 {
Chris@13 1255 $this->startupMessage = $message;
Chris@13 1256 }
Chris@13 1257
Chris@13 1258 /**
Chris@13 1259 * Get the startup message.
Chris@13 1260 *
Chris@13 1261 * @return string|null
Chris@13 1262 */
Chris@13 1263 public function getStartupMessage()
Chris@13 1264 {
Chris@13 1265 return $this->startupMessage;
Chris@13 1266 }
Chris@13 1267
Chris@13 1268 /**
Chris@13 1269 * Set the prompt.
Chris@13 1270 *
Chris@13 1271 * @param string $prompt
Chris@13 1272 */
Chris@13 1273 public function setPrompt($prompt)
Chris@13 1274 {
Chris@13 1275 $this->prompt = $prompt;
Chris@13 1276 }
Chris@13 1277
Chris@13 1278 /**
Chris@13 1279 * Get the prompt.
Chris@13 1280 *
Chris@13 1281 * @return string
Chris@13 1282 */
Chris@13 1283 public function getPrompt()
Chris@13 1284 {
Chris@13 1285 return $this->prompt;
Chris@13 1286 }
Chris@13 1287
Chris@13 1288 /**
Chris@13 1289 * Get the force array indexes.
Chris@13 1290 *
Chris@13 1291 * @return bool
Chris@13 1292 */
Chris@13 1293 public function forceArrayIndexes()
Chris@13 1294 {
Chris@13 1295 return $this->forceArrayIndexes;
Chris@13 1296 }
Chris@13 1297
Chris@13 1298 /**
Chris@13 1299 * Set the force array indexes.
Chris@13 1300 *
Chris@13 1301 * @param bool $forceArrayIndexes
Chris@13 1302 */
Chris@13 1303 public function setForceArrayIndexes($forceArrayIndexes)
Chris@13 1304 {
Chris@13 1305 $this->forceArrayIndexes = $forceArrayIndexes;
Chris@13 1306 }
Chris@13 1307 }