Skip to content

Commit

Permalink
Add standard input reader
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianfeldmann committed Jul 22, 2020
1 parent 2474ff1 commit f4aaad8
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/Reader.php
@@ -0,0 +1,32 @@
<?php

/**
* This file is part of SebastianFeldmann\Cli.
*
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace SebastianFeldmann\Cli;

use Iterator;

/**
* Interface Reader
*
* @package SebastianFeldmann\Cli
* @author Sebastian Feldmann <sf@sebastian-feldmann.info>
* @link https://github.com/sebastianfeldmann/cli
* @since Class available since Release 3.3.0
*/
interface Reader extends Iterator
{
/**
* Get the current line.
*
* @return string
*/
public function current(): string;
}
100 changes: 100 additions & 0 deletions src/Reader/Abstraction.php
@@ -0,0 +1,100 @@
<?php

/**
* This file is part of SebastianFeldmann\Cli.
*
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace SebastianFeldmann\Cli\Reader;

use Iterator;
use SebastianFeldmann\Cli\Reader;

/**
* Abstract Reader class
*
* @package SebastianFeldmann\Cli
* @author Sebastian Feldmann <sf@sebastian-feldmann.info>
* @link https://github.com/sebastianfeldmann/cli
* @since Class available since Release 3.3.0
*/
abstract class Abstraction implements Reader
{
/**
* Internal iterator to handle foreach
*
* @var \Iterator
*/
private $iterator;

/**
* Return the internal iterator
*
* @return \Iterator
*/
private function getIterator(): Iterator
{
return $this->iterator;
}

/**
* Set the pointer to the next line
*
* @return void
*/
public function next(): void
{
$this->getIterator()->next();
}

/**
* Get the line number of the current line
*
* @return int
*/
public function key(): int
{
return $this->getIterator()->key();
}

/**
* Check whether the current line is valid
*
* @return bool
*/
public function valid(): bool
{
return $this->getIterator()->valid();
}

/**
* Recreate/rewind the iterator
*
* @return void
*/
public function rewind(): void
{
$this->iterator = $this->createIterator();
}

/**
* Get the current line
*
* @return string
*/
public function current(): string
{
return $this->getIterator()->current();
}

/**
* Create the internal iterator
*
* @return iterable
*/
protected abstract function createIterator(): iterable;
}
63 changes: 63 additions & 0 deletions src/Reader/StandardInput.php
@@ -0,0 +1,63 @@
<?php

/**
* This file is part of SebastianFeldmann\Cli.
*
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace SebastianFeldmann\Cli\Reader;

use Exception;

/**
* StandardInput
*
* @package SebastianFeldmann\Cli
* @author Sebastian Feldmann <sf@sebastian-feldmann.info>
* @link https://github.com/sebastianfeldmann/cli
* @since Class available since Release 3.3.0
*/
class StandardInput extends Abstraction
{
/**
* Standard Input stream handle
*
* @var resource
*/
private $handle;

/**
* StandardInput constructor.
*
* @param $stdInHandle
*/
public function __construct($stdInHandle)
{
$this->handle = $stdInHandle;
}

/**
* Create the generator
*
* @return iterable
* @throws \Exception
*/
protected function createIterator(): iterable
{
$read = [$this->handle];
$write = [];
$except = [];
$result = stream_select($read, $write, $except, 0);

if ($result === false) {
throw new Exception('stream_select failed');
}
if ($result !== 0) {
yield stream_get_line($this->handle, null);
}
}
}
40 changes: 40 additions & 0 deletions tests/cli/Reader/StandardInputTest.php
@@ -0,0 +1,40 @@
<?php

/**
* This file is part of SebastianFeldmann\Cli.
*
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace SebastianFeldmann\Cli\Reader;

use PHPUnit\Framework\TestCase;

/**
* Class StandardInputTest
*
* @package SebastianFeldmann\Cli
* @author Sebastian Feldmann <sf@sebastian-feldmann.info>
* @link https://github.com/sebastianfeldmann/cli
* @since Class available since Release 3.3.0
*/
class StandardInputTest extends TestCase
{
/**
* Tests StandardInput::createIterator
*/
public function testReadStandardInput(): void
{
$pipe = new StandardInput(fopen(SF_CLI_PATH_FILES . '/misc/foo.txt', 'r'));

$input = '';
foreach ($pipe as $line) {
$input .= $line;
}

$this->assertStringContainsString('fooish', $input);
}
}

0 comments on commit f4aaad8

Please sign in to comment.