Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
90.91% covered (success)
90.91%
10 / 11
CRAP
85.00% covered (warning)
85.00%
34 / 40
Path
0.00% covered (danger)
0.00%
0 / 1
90.91% covered (success)
90.91%
10 / 11
21.35
85.00% covered (warning)
85.00%
34 / 40
 parse
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 __construct
0.00% covered (danger)
0.00%
0 / 1
6.60
45.45% covered (danger)
45.45%
5 / 11
 __toString
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 __clone
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 count
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 get
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
11 / 11
 push
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getSteps
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setSteps
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getArrayExpectation
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setArrayExpectation
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
<?php
/**
 * Copyright (c) Tony Bogdanov <tonybogdanov@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace DataTraveller\Path;
use DataExpectation\ArrayExpectation;
use DataExpectation\Exceptions\UnexpectedDataException;
use DataTraveller\Exceptions\MissingDataException;
use DataTraveller\Path\Exceptions\InvalidPathException;
use DataTraveller\Path\Step\LiteralStep;
use DataTraveller\Path\Step\StepInterface;
use Nette\Tokenizer\Exception;
use SebastianBergmann\Timer\RuntimeException;
/**
 * Class Path
 *
 * @package DataTraveller\Path
 * @author TonyBogdanov <tonybogdanov@gmail.com>
 */
class Path implements \Countable {
    /**
     * @var StepInterface[]
     */
    protected $steps;
    /**
     * @var ArrayExpectation
     */
    protected $arrayExpectation;
    /**
     * @param string $value
     * @param bool $disableRegex
     *
     * @return Path
     * @throws InvalidPathException
     */
    public static function parse( string $value, bool $disableRegex = false ): Path {
        try {
            return new static( ( new Parser( $disableRegex ) )->parse( $value ) );
        } catch ( Exception $e ) {
            throw new InvalidPathException( sprintf( 'Invalid path: %s', $value ), 0, $e );
        }
    }
    /**
     * Path constructor.
     *
     * @param StepInterface[] $steps
     */
    public function __construct( array $steps = [] ) {
        $this->steps = array_map( function ( $step ): StepInterface {
            if ( $step instanceof StepInterface ) {
                return $step;
            }
            if ( is_string( $step ) ) {
                return new LiteralStep( $step );
            }
            throw new RuntimeException( sprintf(
                'Invalid path step, expected a string or an instance of %1$s, got %2$s instead.',
                StepInterface::class,
                is_object( $step ) ? get_class( $step ) : gettype( $step )
            ) );
        }, $steps );
        $this->arrayExpectation = new ArrayExpectation();
    }
    /**
     * @return string
     */
    public function __toString(): string {
        return implode( '.', array_map( function ( StepInterface $step ) {
            return $step instanceof LiteralStep ? str_replace( '.', '\\.', $step ) : $step;
        }, $this->steps ) );
    }
    public function __clone() {
        $this->steps = array_map( function ( StepInterface $step ) {
            return clone $step;
        }, $this->steps );
        $this->arrayExpectation = clone $this->arrayExpectation;
    }
    /**
     * @return int
     */
    public function count(): int {
        return count( $this->steps );
    }
    /**
     * @param $data
     * @param Path|null $trail
     *
     * @return mixed
     * @throws MissingDataException
     * @throws UnexpectedDataException
     */
    public function get( $data, Path $trail = null ) {
        if ( 0 === count( $this->steps ) ) {
            return $data;
        }
        if ( ! isset( $trail ) ) {
            $trail = new static();
        }
        $this->arrayExpectation->expect( $data, $trail );
        $step = $this->steps[0];
        $trail->push( $step );
        foreach ( $data as $key => $value ) {
            if ( $step->expect( $key ) ) {
                return ( new Path( array_slice( $this->steps, 1 ) ) )->get( $value, $trail );
            }
        }
        throw new MissingDataException( $trail );
    }
    /**
     * @param StepInterface $step
     *
     * @return Path
     */
    public function push( StepInterface $step ): Path {
        $this->steps[] = $step;
        return $this;
    }
    /**
     * @return StepInterface[]
     */
    public function getSteps(): array {
        return $this->steps;
    }
    /**
     * @param StepInterface[] $steps
     *
     * @return $this
     */
    public function setSteps( array $steps ) {
        $this->steps = $steps;
        return $this;
    }
    /**
     * @return ArrayExpectation
     */
    public function getArrayExpectation(): ArrayExpectation {
        return $this->arrayExpectation;
    }
    /**
     * @param ArrayExpectation $arrayExpectation
     *
     * @return $this
     */
    public function setArrayExpectation( ArrayExpectation $arrayExpectation ) {
        $this->arrayExpectation = $arrayExpectation;
        return $this;
    }
}