ama-team/php-projection-framework

View on GitHub
src/Filesystem/Pattern/Chunk.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace AmaTeam\Image\Projection\Filesystem\Pattern;

/**
 * TODO: implement proper tokenization/parsing mechanism
 */
class Chunk
{
    const TYPE_EXACT_MATCH = 'exact';
    const TYPE_EXPRESSION = 'match';
    const PATTERN = '/\{([\w\-]+)\}/';

    /**
     * Chunk type, one of Chunk::TYPE_* constants
     *
     * @var string
     */
    private $type;
    /**
     * Original chunk text value
     *
     * @var string
     */
    private $source;
    /**
     * Regular expression built to match the chunk
     *
     * @var string
     */
    private $expression;
    /**
     * List of parameters specified in chunk
     *
     * @var string[]
     */
    private $parameters = [];

    public function __construct($chunk)
    {
        $this->source = $chunk;
        $this->expression = $chunk;
        $this->type = self::TYPE_EXACT_MATCH;
        $expression = preg_replace_callback(self::PATTERN, function ($match) {
            $parameter = $match[1];
            if (in_array($parameter, $this->parameters)) {
                return '(?:[\w\-]+)';
            }
            $this->parameters[] = $parameter;
            return sprintf('(?<%s>[\w\-]+)', $parameter);
        }, $chunk);
        if ($expression === $chunk) {
            return;
        }
        $this->type = self::TYPE_EXPRESSION;
        $this->expression = '/^' . $expression . '$/';
    }

    /**
     * @param string $segment
     * @return bool
     */
    public function matches($segment)
    {
        if ($this->type === self::TYPE_EXACT_MATCH) {
            return $segment === $this->expression;
        }
        return !!preg_match($this->expression, $segment);
    }

    /**
     * @param string $segment
     * @return string[]
     */
    public function getParameters($segment)
    {
        if ($this->type === self::TYPE_EXACT_MATCH) {
            return [];
        }
        if (!preg_match($this->expression, $segment, $matches)) {
            return [];
        }
        $target = [];
        foreach ($this->parameters as $parameter) {
            $target[$parameter] = $matches[$parameter];
        }
        return $target;
    }

    /**
     * @param array $parameters
     * @return Chunk
     */
    public function resolve(array $parameters)
    {
        $chunk = $this->source;
        foreach ($parameters as $key => $value) {
            $needle = "{{$key}}";
            if (strpos($chunk, $needle) !== false) {
                $chunk = str_replace($needle, $value, $chunk);
            }
        }
        return new Chunk($chunk);
    }

    /**
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @return string
     */
    public function getExpression()
    {
        return $this->expression;
    }

    /**
     * @return string
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->source;
    }
}