prompt = $prompt; $this->reader = $reader ?: new Stdin(); } /** * Do it! Prompt the user for information! * * @return string */ public function prompt() { $this->writePrompt(); $response = $this->valueOrDefault($this->getUserInput()); if ($this->isValidResponse($response)) { return $response; } return $this->prompt(); } /** * Define the acceptable responses and whether or not to * display them to the user * * @param array|object $acceptable * @param boolean $show * * @return \League\CLImate\TerminalObject\Dynamic\Input */ public function accept($acceptable, $show = false) { $this->acceptable = $acceptable; $this->show_acceptable = $show; return $this; } /** * Define whether we should be strict about exact responses * * @return \League\CLImate\TerminalObject\Dynamic\Input */ public function strict() { $this->strict = true; return $this; } /** * Set a default response * * @param string $default * * @return \League\CLImate\TerminalObject\Dynamic\Input */ public function defaultTo($default) { $this->default = $default; return $this; } /** * Set multiline input to true * * @return \League\CLImate\TerminalObject\Dynamic\Input */ public function multiLine() { $this->multiLine = true; return $this; } /** * @return string */ protected function getUserInput() { if ($this->multiLine) { return $this->reader->multiLine(); } return $this->reader->line(); } /** * Write out the formatted prompt */ protected function writePrompt() { $prompt = $this->parser->apply($this->promptFormatted()); $this->output->sameLine()->write($prompt); } /** * If no response was given and there is a default, return it, * otherwise return response * * @param string $response * * @return string */ protected function valueOrDefault($response) { if (strlen($response) == 0 && strlen($this->default)) { return $this->default; } return $response; } /** * Format the acceptable responses as options * * @return string */ protected function acceptableFormatted() { if (!is_array($this->acceptable)) { return ''; } $this->acceptable = array_map([$this, 'acceptableItemFormatted'], $this->acceptable); return '[' . implode('/', $this->acceptable) . ']'; } /** * Format the acceptable item depending on whether it is the default or not * * @param string $item * * @return string */ protected function acceptableItemFormatted($item) { if ($item == $this->default) { return '' . $item . ''; } return $item; } /** * Format the prompt incorporating spacing and any acceptable options * * @return string */ protected function promptFormatted() { $prompt = $this->prompt . ' '; if ($this->show_acceptable) { $prompt .= $this->acceptableFormatted() . ' '; } return $prompt; } /** * Apply some string manipulation functions for normalization * * @param string|array $var * @return array */ protected function levelPlayingField($var) { $levelers = ['trim', 'strtolower']; foreach ($levelers as $leveler) { if (is_array($var)) { $var = array_map($leveler, $var); } else { $var = $leveler($var); } } return $var; } /** * Determine whether or not the acceptable property is of type closure * * @return boolean */ protected function acceptableIsClosure() { return (is_object($this->acceptable) && $this->acceptable instanceof \Closure); } /** * Determine if the user's response is in the acceptable responses array * * @param string $response * * @return boolean $response */ protected function isAcceptableResponse($response) { if ($this->strict) { return in_array($response, $this->acceptable); } $acceptable = $this->levelPlayingField($this->acceptable); $response = $this->levelPlayingField($response); return in_array($response, $acceptable); } /** * Determine if the user's response is valid based on the current settings * * @param string $response * * @return boolean $response */ protected function isValidResponse($response) { if (empty($this->acceptable)) { return true; } if ($this->acceptableIsClosure()) { return call_user_func($this->acceptable, $response); } return $this->isAcceptableResponse($response); } }