4 * This file is part of Psy Shell.
6 * (c) 2012-2018 Justin Hileman
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
14 use Psy\Exception\DeprecatedException;
15 use Psy\Exception\RuntimeException;
16 use Psy\Output\OutputPager;
17 use Psy\Output\ShellOutput;
18 use Psy\Readline\GNUReadline;
19 use Psy\Readline\HoaConsole;
20 use Psy\Readline\Libedit;
21 use Psy\Readline\Readline;
22 use Psy\Readline\Transient;
23 use Psy\TabCompletion\AutoCompleter;
24 use Psy\VarDumper\Presenter;
25 use Psy\VersionUpdater\Checker;
26 use Psy\VersionUpdater\GitHubChecker;
27 use Psy\VersionUpdater\IntervalChecker;
28 use Psy\VersionUpdater\NoopChecker;
31 * The Psy Shell configuration.
35 const COLOR_MODE_AUTO = 'auto';
36 const COLOR_MODE_FORCED = 'forced';
37 const COLOR_MODE_DISABLED = 'disabled';
39 private static $AVAILABLE_OPTIONS = [
61 'warnOnMultipleConfigs',
64 private $defaultIncludes;
69 /** @var string|false */
72 private $eraseDuplicates;
73 private $manualDbFile;
76 private $useBracketedPaste;
79 private $newCommands = [];
80 private $requireSemicolons = false;
82 private $useTabCompletion;
83 private $newMatchers = [];
84 private $errorLoggingLevel = E_ALL;
85 private $warnOnMultipleConfigs = false;
88 private $startupMessage;
89 private $forceArrayIndexes = false;
99 private $autoCompleter;
104 * Construct a Configuration instance.
106 * Optionally, supply an array of configuration values to load.
108 * @param array $config Optional array of configuration values
110 public function __construct(array $config = [])
112 $this->setColorMode(self::COLOR_MODE_AUTO);
114 // explicit configFile option
115 if (isset($config['configFile'])) {
116 $this->configFile = $config['configFile'];
117 } elseif ($configFile = getenv('PSYSH_CONFIG')) {
118 $this->configFile = $configFile;
121 // legacy baseDir option
122 if (isset($config['baseDir'])) {
123 $msg = "The 'baseDir' configuration option is deprecated; " .
124 "please specify 'configDir' and 'dataDir' options instead";
125 throw new DeprecatedException($msg);
128 unset($config['configFile'], $config['baseDir']);
130 // go go gadget, config!
131 $this->loadConfig($config);
136 * Initialize the configuration.
138 * This checks for the presence of Readline and Pcntl extensions.
140 * If a config file is available, it will be loaded and merged with the current config.
142 * If no custom config file was specified and a local project config file
143 * is available, it will be loaded and merged with the current config.
145 public function init()
148 $this->hasReadline = function_exists('readline');
149 $this->hasPcntl = function_exists('pcntl_signal') && function_exists('posix_getpid');
151 if ($configFile = $this->getConfigFile()) {
152 $this->loadConfigFile($configFile);
155 if (!$this->configFile && $localConfig = $this->getLocalConfigFile()) {
156 $this->loadConfigFile($localConfig);
161 * Get the current PsySH config file.
163 * If a `configFile` option was passed to the Configuration constructor,
164 * this file will be returned. If not, all possible config directories will
165 * be searched, and the first `config.php` or `rc.php` file which exists
168 * If you're trying to decide where to put your config file, pick
170 * ~/.config/psysh/config.php
174 public function getConfigFile()
176 if (isset($this->configFile)) {
177 return $this->configFile;
180 $files = ConfigPaths::getConfigFiles(['config.php', 'rc.php'], $this->configDir);
182 if (!empty($files)) {
183 if ($this->warnOnMultipleConfigs && count($files) > 1) {
184 $msg = sprintf('Multiple configuration files found: %s. Using %s', implode($files, ', '), $files[0]);
185 trigger_error($msg, E_USER_NOTICE);
193 * Get the local PsySH config file.
195 * Searches for a project specific config file `.psysh.php` in the current
200 public function getLocalConfigFile()
202 $localConfig = getcwd() . '/.psysh.php';
204 if (@is_file($localConfig)) {
210 * Load configuration values from an array of options.
212 * @param array $options
214 public function loadConfig(array $options)
216 foreach (self::$AVAILABLE_OPTIONS as $option) {
217 if (isset($options[$option])) {
218 $method = 'set' . ucfirst($option);
219 $this->$method($options[$option]);
223 // legacy `tabCompletion` option
224 if (isset($options['tabCompletion'])) {
225 $msg = '`tabCompletion` is deprecated; use `useTabCompletion` instead.';
226 @trigger_error($msg, E_USER_DEPRECATED);
228 $this->setUseTabCompletion($options['tabCompletion']);
231 foreach (['commands', 'matchers', 'casters'] as $option) {
232 if (isset($options[$option])) {
233 $method = 'add' . ucfirst($option);
234 $this->$method($options[$option]);
238 // legacy `tabCompletionMatchers` option
239 if (isset($options['tabCompletionMatchers'])) {
240 $msg = '`tabCompletionMatchers` is deprecated; use `matchers` instead.';
241 @trigger_error($msg, E_USER_DEPRECATED);
243 $this->addMatchers($options['tabCompletionMatchers']);
248 * Load a configuration file (default: `$HOME/.config/psysh/config.php`).
250 * This configuration instance will be available to the config file as $config.
251 * The config file may directly manipulate the configuration, or may return
252 * an array of options which will be merged with the current configuration.
254 * @throws \InvalidArgumentException if the config file returns a non-array result
256 * @param string $file
258 public function loadConfigFile($file)
260 $__psysh_config_file__ = $file;
261 $load = function ($config) use ($__psysh_config_file__) {
262 $result = require $__psysh_config_file__;
267 $result = $load($this);
269 if (!empty($result)) {
270 if (is_array($result)) {
271 $this->loadConfig($result);
273 throw new \InvalidArgumentException('Psy Shell configuration must return an array of options');
279 * Set files to be included by default at the start of each shell session.
281 * @param array $includes
283 public function setDefaultIncludes(array $includes = [])
285 $this->defaultIncludes = $includes;
289 * Get files to be included by default at the start of each shell session.
293 public function getDefaultIncludes()
295 return $this->defaultIncludes ?: [];
299 * Set the shell's config directory location.
303 public function setConfigDir($dir)
305 $this->configDir = (string) $dir;
309 * Get the current configuration directory, if any is explicitly set.
313 public function getConfigDir()
315 return $this->configDir;
319 * Set the shell's data directory location.
323 public function setDataDir($dir)
325 $this->dataDir = (string) $dir;
329 * Get the current data directory, if any is explicitly set.
333 public function getDataDir()
335 return $this->dataDir;
339 * Set the shell's temporary directory location.
343 public function setRuntimeDir($dir)
345 $this->runtimeDir = (string) $dir;
349 * Get the shell's temporary directory location.
351 * Defaults to `/psysh` inside the system's temp dir unless explicitly
356 public function getRuntimeDir()
358 if (!isset($this->runtimeDir)) {
359 $this->runtimeDir = ConfigPaths::getRuntimeDir();
362 if (!is_dir($this->runtimeDir)) {
363 mkdir($this->runtimeDir, 0700, true);
366 return $this->runtimeDir;
370 * Set the readline history file path.
372 * @param string $file
374 public function setHistoryFile($file)
376 $this->historyFile = ConfigPaths::touchFileWithMkdir($file);
380 * Get the readline history file path.
382 * Defaults to `/history` inside the shell's base config dir unless
383 * explicitly overridden.
387 public function getHistoryFile()
389 if (isset($this->historyFile)) {
390 return $this->historyFile;
393 $files = ConfigPaths::getConfigFiles(['psysh_history', 'history'], $this->configDir);
395 if (!empty($files)) {
396 if ($this->warnOnMultipleConfigs && count($files) > 1) {
397 $msg = sprintf('Multiple history files found: %s. Using %s', implode($files, ', '), $files[0]);
398 trigger_error($msg, E_USER_NOTICE);
401 $this->setHistoryFile($files[0]);
403 // fallback: create our own history file
404 $dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
405 $this->setHistoryFile($dir . '/psysh_history');
408 return $this->historyFile;
412 * Set the readline max history size.
416 public function setHistorySize($value)
418 $this->historySize = (int) $value;
422 * Get the readline max history size.
426 public function getHistorySize()
428 return $this->historySize;
432 * Sets whether readline erases old duplicate history entries.
436 public function setEraseDuplicates($value)
438 $this->eraseDuplicates = (bool) $value;
442 * Get whether readline erases old duplicate history entries.
446 public function getEraseDuplicates()
448 return $this->eraseDuplicates;
452 * Get a temporary file of type $type for process $pid.
454 * The file will be created inside the current temporary directory.
456 * @see self::getRuntimeDir
458 * @param string $type
461 * @return string Temporary file name
463 public function getTempFile($type, $pid)
465 return tempnam($this->getRuntimeDir(), $type . '_' . $pid . '_');
469 * Get a filename suitable for a FIFO pipe of $type for process $pid.
471 * The pipe will be created inside the current temporary directory.
473 * @param string $type
476 * @return string Pipe name
478 public function getPipe($type, $pid)
480 return sprintf('%s/%s_%s', $this->getRuntimeDir(), $type, $pid);
484 * Check whether this PHP instance has Readline available.
486 * @return bool True if Readline is available
488 public function hasReadline()
490 return $this->hasReadline;
494 * Enable or disable Readline usage.
496 * @param bool $useReadline
498 public function setUseReadline($useReadline)
500 $this->useReadline = (bool) $useReadline;
504 * Check whether to use Readline.
506 * If `setUseReadline` as been set to true, but Readline is not actually
507 * available, this will return false.
509 * @return bool True if the current Shell should use Readline
511 public function useReadline()
513 return isset($this->useReadline) ? ($this->hasReadline && $this->useReadline) : $this->hasReadline;
517 * Set the Psy Shell readline service.
519 * @param Readline $readline
521 public function setReadline(Readline $readline)
523 $this->readline = $readline;
527 * Get the Psy Shell readline service.
529 * By default, this service uses (in order of preference):
533 * * A transient array-based readline emulation.
537 public function getReadline()
539 if (!isset($this->readline)) {
540 $className = $this->getReadlineClass();
541 $this->readline = new $className(
542 $this->getHistoryFile(),
543 $this->getHistorySize(),
544 $this->getEraseDuplicates()
548 return $this->readline;
552 * Get the appropriate Readline implementation class name.
554 * @see self::getReadline
558 private function getReadlineClass()
560 if ($this->useReadline()) {
561 if (GNUReadline::isSupported()) {
562 return 'Psy\Readline\GNUReadline';
563 } elseif (Libedit::isSupported()) {
564 return 'Psy\Readline\Libedit';
565 } elseif (HoaConsole::isSupported()) {
566 return 'Psy\Readline\HoaConsole';
570 return 'Psy\Readline\Transient';
574 * Enable or disable bracketed paste.
576 * Note that this only works with readline (not libedit) integration for now.
578 * @param bool $useBracketedPaste
580 public function setUseBracketedPaste($useBracketedPaste)
582 $this->useBracketedPaste = (bool) $useBracketedPaste;
586 * Check whether to use bracketed paste with readline.
588 * When this works, it's magical. Tabs in pastes don't try to autcomplete.
589 * Newlines in paste don't execute code until you get to the end. It makes
590 * readline act like you'd expect when pasting.
592 * But it often (usually?) does not work. And when it doesn't, it just spews
593 * escape codes all over the place and generally makes things ugly :(
595 * If `useBracketedPaste` has been set to true, but the current readline
596 * implementation is anything besides GNU readline, this will return false.
598 * @return bool True if the shell should use bracketed paste
600 public function useBracketedPaste()
602 // For now, only the GNU readline implementation supports bracketed paste.
603 $supported = ($this->getReadlineClass() === 'Psy\Readline\GNUReadline');
605 return $supported && $this->useBracketedPaste;
607 // @todo mebbe turn this on by default some day?
608 // return isset($this->useBracketedPaste) ? ($supported && $this->useBracketedPaste) : $supported;
612 * Check whether this PHP instance has Pcntl available.
614 * @return bool True if Pcntl is available
616 public function hasPcntl()
618 return $this->hasPcntl;
622 * Enable or disable Pcntl usage.
624 * @param bool $usePcntl
626 public function setUsePcntl($usePcntl)
628 $this->usePcntl = (bool) $usePcntl;
632 * Check whether to use Pcntl.
634 * If `setUsePcntl` has been set to true, but Pcntl is not actually
635 * available, this will return false.
637 * @return bool True if the current Shell should use Pcntl
639 public function usePcntl()
641 return isset($this->usePcntl) ? ($this->hasPcntl && $this->usePcntl) : $this->hasPcntl;
645 * Enable or disable strict requirement of semicolons.
647 * @see self::requireSemicolons()
649 * @param bool $requireSemicolons
651 public function setRequireSemicolons($requireSemicolons)
653 $this->requireSemicolons = (bool) $requireSemicolons;
657 * Check whether to require semicolons on all statements.
659 * By default, PsySH will automatically insert semicolons at the end of
660 * statements if they're missing. To strictly require semicolons, set
661 * `requireSemicolons` to true.
665 public function requireSemicolons()
667 return $this->requireSemicolons;
671 * Enable or disable Unicode in PsySH specific output.
673 * Note that this does not disable Unicode output in general, it just makes
674 * it so PsySH won't output any itself.
676 * @param bool $useUnicode
678 public function setUseUnicode($useUnicode)
680 $this->useUnicode = (bool) $useUnicode;
684 * Check whether to use Unicode in PsySH specific output.
686 * Note that this does not disable Unicode output in general, it just makes
687 * it so PsySH won't output any itself.
691 public function useUnicode()
693 if (isset($this->useUnicode)) {
694 return $this->useUnicode;
697 // @todo detect `chsh` != 65001 on Windows and return false
702 * Set the error logging level.
704 * @see self::errorLoggingLevel
706 * @param bool $errorLoggingLevel
708 public function setErrorLoggingLevel($errorLoggingLevel)
710 $this->errorLoggingLevel = (E_ALL | E_STRICT) & $errorLoggingLevel;
714 * Get the current error logging level.
716 * By default, PsySH will automatically log all errors, regardless of the
717 * current `error_reporting` level. Additionally, if the `error_reporting`
718 * level warrants, an ErrorException will be thrown.
720 * Set `errorLoggingLevel` to 0 to prevent logging non-thrown errors. Set it
721 * to any valid error_reporting value to log only errors which match that
724 * http://php.net/manual/en/function.error-reporting.php
728 public function errorLoggingLevel()
730 return $this->errorLoggingLevel;
734 * Set a CodeCleaner service instance.
736 * @param CodeCleaner $cleaner
738 public function setCodeCleaner(CodeCleaner $cleaner)
740 $this->cleaner = $cleaner;
744 * Get a CodeCleaner service instance.
746 * If none has been explicitly defined, this will create a new instance.
748 * @return CodeCleaner
750 public function getCodeCleaner()
752 if (!isset($this->cleaner)) {
753 $this->cleaner = new CodeCleaner();
756 return $this->cleaner;
760 * Enable or disable tab completion.
762 * @param bool $useTabCompletion
764 public function setUseTabCompletion($useTabCompletion)
766 $this->useTabCompletion = (bool) $useTabCompletion;
770 * @deprecated Call `setUseTabCompletion` instead
772 * @param bool $useTabCompletion
774 public function setTabCompletion($useTabCompletion)
776 $this->setUseTabCompletion($useTabCompletion);
780 * Check whether to use tab completion.
782 * If `setUseTabCompletion` has been set to true, but readline is not
783 * actually available, this will return false.
785 * @return bool True if the current Shell should use tab completion
787 public function useTabCompletion()
789 return isset($this->useTabCompletion) ? ($this->hasReadline && $this->useTabCompletion) : $this->hasReadline;
793 * @deprecated Call `useTabCompletion` instead
797 public function getTabCompletion()
799 return $this->useTabCompletion();
803 * Set the Shell Output service.
805 * @param ShellOutput $output
807 public function setOutput(ShellOutput $output)
809 $this->output = $output;
813 * Get a Shell Output service instance.
815 * If none has been explicitly provided, this will create a new instance
816 * with VERBOSITY_NORMAL and the output page supplied by self::getPager
818 * @see self::getPager
820 * @return ShellOutput
822 public function getOutput()
824 if (!isset($this->output)) {
825 $this->output = new ShellOutput(
826 ShellOutput::VERBOSITY_NORMAL,
827 $this->getOutputDecorated(),
833 return $this->output;
837 * Get the decoration (i.e. color) setting for the Shell Output service.
839 * @return null|bool 3-state boolean corresponding to the current color mode
841 public function getOutputDecorated()
843 if ($this->colorMode() === self::COLOR_MODE_AUTO) {
845 } elseif ($this->colorMode() === self::COLOR_MODE_FORCED) {
847 } elseif ($this->colorMode() === self::COLOR_MODE_DISABLED) {
853 * Set the OutputPager service.
855 * If a string is supplied, a ProcOutputPager will be used which shells out
856 * to the specified command.
858 * @throws \InvalidArgumentException if $pager is not a string or OutputPager instance
860 * @param string|OutputPager $pager
862 public function setPager($pager)
864 if ($pager && !is_string($pager) && !$pager instanceof OutputPager) {
865 throw new \InvalidArgumentException('Unexpected pager instance');
868 $this->pager = $pager;
872 * Get an OutputPager instance or a command for an external Proc pager.
874 * If no Pager has been explicitly provided, and Pcntl is available, this
875 * will default to `cli.pager` ini value, falling back to `which less`.
877 * @return string|OutputPager
879 public function getPager()
881 if (!isset($this->pager) && $this->usePcntl()) {
882 if ($pager = ini_get('cli.pager')) {
883 // use the default pager (5.4+)
884 $this->pager = $pager;
885 } elseif ($less = exec('which less 2>/dev/null')) {
886 // check for the presence of less...
887 $this->pager = $less . ' -R -S -F -X';
895 * Set the Shell AutoCompleter service.
897 * @param AutoCompleter $autoCompleter
899 public function setAutoCompleter(AutoCompleter $autoCompleter)
901 $this->autoCompleter = $autoCompleter;
905 * Get an AutoCompleter service instance.
907 * @return AutoCompleter
909 public function getAutoCompleter()
911 if (!isset($this->autoCompleter)) {
912 $this->autoCompleter = new AutoCompleter();
915 return $this->autoCompleter;
919 * @deprecated Nothing should be using this anymore
923 public function getTabCompletionMatchers()
929 * Add tab completion matchers to the AutoCompleter.
931 * This will buffer new matchers in the event that the Shell has not yet
932 * been instantiated. This allows the user to specify matchers in their
933 * config rc file, despite the fact that their file is needed in the Shell
936 * @param array $matchers
938 public function addMatchers(array $matchers)
940 $this->newMatchers = array_merge($this->newMatchers, $matchers);
941 if (isset($this->shell)) {
942 $this->doAddMatchers();
947 * Internal method for adding tab completion matchers. This will set any new
948 * matchers once a Shell is available.
950 private function doAddMatchers()
952 if (!empty($this->newMatchers)) {
953 $this->shell->addMatchers($this->newMatchers);
954 $this->newMatchers = [];
959 * @deprecated Use `addMatchers` instead
961 * @param array $matchers
963 public function addTabCompletionMatchers(array $matchers)
965 $this->addMatchers($matchers);
969 * Add commands to the Shell.
971 * This will buffer new commands in the event that the Shell has not yet
972 * been instantiated. This allows the user to specify commands in their
973 * config rc file, despite the fact that their file is needed in the Shell
976 * @param array $commands
978 public function addCommands(array $commands)
980 $this->newCommands = array_merge($this->newCommands, $commands);
981 if (isset($this->shell)) {
982 $this->doAddCommands();
987 * Internal method for adding commands. This will set any new commands once
988 * a Shell is available.
990 private function doAddCommands()
992 if (!empty($this->newCommands)) {
993 $this->shell->addCommands($this->newCommands);
994 $this->newCommands = [];
999 * Set the Shell backreference and add any new commands to the Shell.
1001 * @param Shell $shell
1003 public function setShell(Shell $shell)
1005 $this->shell = $shell;
1006 $this->doAddCommands();
1007 $this->doAddMatchers();
1011 * Set the PHP manual database file.
1013 * This file should be an SQLite database generated from the phpdoc source
1014 * with the `bin/build_manual` script.
1016 * @param string $filename
1018 public function setManualDbFile($filename)
1020 $this->manualDbFile = (string) $filename;
1024 * Get the current PHP manual database file.
1026 * @return string Default: '~/.local/share/psysh/php_manual.sqlite'
1028 public function getManualDbFile()
1030 if (isset($this->manualDbFile)) {
1031 return $this->manualDbFile;
1034 $files = ConfigPaths::getDataFiles(['php_manual.sqlite'], $this->dataDir);
1035 if (!empty($files)) {
1036 if ($this->warnOnMultipleConfigs && count($files) > 1) {
1037 $msg = sprintf('Multiple manual database files found: %s. Using %s', implode($files, ', '), $files[0]);
1038 trigger_error($msg, E_USER_NOTICE);
1041 return $this->manualDbFile = $files[0];
1046 * Get a PHP manual database connection.
1050 public function getManualDb()
1052 if (!isset($this->manualDb)) {
1053 $dbFile = $this->getManualDbFile();
1054 if (is_file($dbFile)) {
1056 $this->manualDb = new \PDO('sqlite:' . $dbFile);
1057 } catch (\PDOException $e) {
1058 if ($e->getMessage() === 'could not find driver') {
1059 throw new RuntimeException('SQLite PDO driver not found', 0, $e);
1067 return $this->manualDb;
1071 * Add an array of casters definitions.
1073 * @param array $casters
1075 public function addCasters(array $casters)
1077 $this->getPresenter()->addCasters($casters);
1081 * Get the Presenter service.
1085 public function getPresenter()
1087 if (!isset($this->presenter)) {
1088 $this->presenter = new Presenter($this->getOutput()->getFormatter(), $this->forceArrayIndexes());
1091 return $this->presenter;
1095 * Enable or disable warnings on multiple configuration or data files.
1097 * @see self::warnOnMultipleConfigs()
1099 * @param bool $warnOnMultipleConfigs
1101 public function setWarnOnMultipleConfigs($warnOnMultipleConfigs)
1103 $this->warnOnMultipleConfigs = (bool) $warnOnMultipleConfigs;
1107 * Check whether to warn on multiple configuration or data files.
1109 * By default, PsySH will use the file with highest precedence, and will
1110 * silently ignore all others. With this enabled, a warning will be emitted
1111 * (but not an exception thrown) if multiple configuration or data files
1114 * This will default to true in a future release, but is false for now.
1118 public function warnOnMultipleConfigs()
1120 return $this->warnOnMultipleConfigs;
1124 * Set the current color mode.
1126 * @param string $colorMode
1128 public function setColorMode($colorMode)
1130 $validColorModes = [
1131 self::COLOR_MODE_AUTO,
1132 self::COLOR_MODE_FORCED,
1133 self::COLOR_MODE_DISABLED,
1136 if (in_array($colorMode, $validColorModes)) {
1137 $this->colorMode = $colorMode;
1139 throw new \InvalidArgumentException('invalid color mode: ' . $colorMode);
1144 * Get the current color mode.
1148 public function colorMode()
1150 return $this->colorMode;
1154 * Set an update checker service instance.
1156 * @param Checker $checker
1158 public function setChecker(Checker $checker)
1160 $this->checker = $checker;
1164 * Get an update checker service instance.
1166 * If none has been explicitly defined, this will create a new instance.
1170 public function getChecker()
1172 if (!isset($this->checker)) {
1173 $interval = $this->getUpdateCheck();
1174 switch ($interval) {
1175 case Checker::ALWAYS:
1176 $this->checker = new GitHubChecker();
1179 case Checker::DAILY:
1180 case Checker::WEEKLY:
1181 case Checker::MONTHLY:
1182 $checkFile = $this->getUpdateCheckCacheFile();
1183 if ($checkFile === false) {
1184 $this->checker = new NoopChecker();
1186 $this->checker = new IntervalChecker($checkFile, $interval);
1190 case Checker::NEVER:
1191 $this->checker = new NoopChecker();
1196 return $this->checker;
1200 * Get the current update check interval.
1202 * One of 'always', 'daily', 'weekly', 'monthly' or 'never'. If none is
1203 * explicitly set, default to 'weekly'.
1207 public function getUpdateCheck()
1209 return isset($this->updateCheck) ? $this->updateCheck : Checker::WEEKLY;
1213 * Set the update check interval.
1215 * @throws \InvalidArgumentDescription if the update check interval is unknown
1217 * @param string $interval
1219 public function setUpdateCheck($interval)
1229 if (!in_array($interval, $validIntervals)) {
1230 throw new \InvalidArgumentException('invalid update check interval: ' . $interval);
1233 $this->updateCheck = $interval;
1237 * Get a cache file path for the update checker.
1239 * @return string|false Return false if config file/directory is not writable
1241 public function getUpdateCheckCacheFile()
1243 $dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
1245 return ConfigPaths::touchFileWithMkdir($dir . '/update_check.json');
1249 * Set the startup message.
1251 * @param string $message
1253 public function setStartupMessage($message)
1255 $this->startupMessage = $message;
1259 * Get the startup message.
1261 * @return string|null
1263 public function getStartupMessage()
1265 return $this->startupMessage;
1271 * @param string $prompt
1273 public function setPrompt($prompt)
1275 $this->prompt = $prompt;
1283 public function getPrompt()
1285 return $this->prompt;
1289 * Get the force array indexes.
1293 public function forceArrayIndexes()
1295 return $this->forceArrayIndexes;
1299 * Set the force array indexes.
1301 * @param bool $forceArrayIndexes
1303 public function setForceArrayIndexes($forceArrayIndexes)
1305 $this->forceArrayIndexes = $forceArrayIndexes;