Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
59 / 59
Range
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
13 / 13
28
100.00% covered (success)
100.00%
59 / 59
 setValidator
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getValidator
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getParser
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setParser
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getPatternDescription
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setPatternDescription
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 addRangeSpec
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getRange
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 addStringItemToRange
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
13 / 13
 addItem
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 addRange
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
6 / 6
 containsValue
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getRangeSpec
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
20 / 20
<?php declare(strict_types = 1);
/**
 * @package: pvc
 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
 * @version: 1.0
 */
namespace pvc\range;
use pvc\parser\ParserInterface;
use pvc\validator\base\ValidatorInterface;
abstract class Range
{
    /**
     * @var ParserInterface
     */
    protected ParserInterface $rangeElementParser;
    /**
     * @var ValidatorInterface
     */
    protected ValidatorInterface $rangeElementValidator;
    /**
     * @var array[int]mixed
     */
    protected array $range = [];
    /**
     * @var string
     */
    protected string $patternDescription;
    /**
     * @function setValidator
     * @param ValidatorInterface $validator
     */
    public function setValidator(ValidatorInterface $validator) : void
    {
        $this->rangeElementValidator = $validator;
    }
    /**
     * @function getValidator
     * @return ValidatorInterface
     */
    public function getValidator(): ValidatorInterface
    {
        return $this->rangeElementValidator;
    }
    /**
     * @function getParser
     * @return ParserInterface
     */
    public function getParser(): ParserInterface
    {
        return $this->rangeElementParser;
    }
    /**
     * @function setParser
     * @param ParserInterface $parser
     */
    public function setParser(ParserInterface $parser): void
    {
        $this->rangeElementParser = $parser;
    }
    /**
     * @function getPatternDescription
     * @return string
     */
    public function getPatternDescription(): string
    {
        return $this->patternDescription;
    }
    /**
     * @function setPatternDescription
     * @param string $description
     */
    public function setPatternDescription(string $description): void
    {
        $this->patternDescription = $description;
    }
    /**
     * @function addRangeSpec
     * @param string $rangeSpec
     * @throws SetRangeException
     */
    public function addRangeSpec(string $rangeSpec) : void
    {
        $rangeShell = explode(',', $rangeSpec);
        foreach ($rangeShell as $item) {
            $this->addStringItemToRange($item);
        }
    }
    /**
     * @function getRange
     * @return array|array[]
     */
    public function getRange()
    {
        return $this->range;
    }
    /**
     * @function addStringItemToRange
     * @param string $item
     * @throws SetRangeException
     */
    public function addStringItemToRange(string $item) : void
    {
        if ($this->rangeElementParser->parse($item)) {
            $this->addItem($this->rangeElementParser->getParsedValue());
            return;
        }
        if (preg_match('/^(.+)-(.+)$/', $item, $matches)) {
            if (false === $this->rangeElementParser->parse($matches[1])) {
                throw new SetRangeException($this->patternDescription, $item);
            }
            $start = $this->rangeElementParser->getParsedValue();
            if (false === $this->rangeElementParser->parse($matches[2])) {
                throw new SetRangeException($this->patternDescription, $item);
            }
            $end = $this->rangeElementParser->getParsedValue();
            $this->addRange($start, $end);
            return;
        }
        throw new SetRangeException($this->patternDescription, $item);
    }
    /**
     * @function addItem
     * @param int $i
     * @throws SetRangeException
     */
    public function addItem(int $i) : void
    {
        if (!$this->rangeElementValidator->validate($i)) {
            throw new SetRangeException($this->patternDescription, $i);
        }
        if (!in_array($i, $this->range)) {
            $this->range[] = $i;
        }
    }
    /**
     * @function addRange
     * @param int $start
     * @param int $end
     * @throws SetRangeException
     */
    public function addRange(int $start, int $end) : void
    {
        if (!$this->rangeElementValidator->validate($start)) {
            throw new SetRangeException($this->patternDescription, $start);
        }
        if (!$this->rangeElementValidator->validate($end)) {
            throw new SetRangeException($this->patternDescription, $end);
        }
        $this->range = array_unique(array_merge($this->range, range($start, $end)));
    }
    /**
     * @function containsValue
     * @param int $value
     * @return bool
     */
    public function containsValue(int $value)
    {
        return in_array($value, $this->range);
    }
    /**
     * @function getRangeSpec
     * @return string
     */
    public function getRangeSpec(): string
    {
        $resultArray = [];
        // end cases
        if (empty($this->range)) {
            return '';
        }
        if (count($this->range) == 1) {
            return (string) $this->range[0];
        }
        // sort range array into ascending values
        asort($this->range);
        // set up pointers to drag through the array
        $arrayLength = count($this->range);
        $beginningOfRange = $this->range[0];
        $previousValue = $this->range[0];
        for ($i = 1; $i < $arrayLength; $i++) {
            if ($this->range[$i] != $previousValue + 1) {
                // previous value is the end of the prior range so add the prior range to the result array
                if ($beginningOfRange == $previousValue) {
                    $resultArray[] = $previousValue;
                } else {
                    $resultArray[] = $beginningOfRange . '-' . $previousValue;
                }
                // start a new range
                $beginningOfRange = $this->range[$i];
            }
            $previousValue = $this->range[$i];
        }
        // add the last range
        if ($beginningOfRange == $previousValue) {
            $resultArray[] = $previousValue;
        } else {
            $resultArray[] = $beginningOfRange . '-' . $previousValue;
        }
        // convert the result array to a string
        return implode(',', $resultArray);
    }
}