Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
14 / 14
CRAP
100.00% covered (success)
100.00%
116 / 116
Interval
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
14 / 14
53
100.00% covered (success)
100.00%
116 / 116
 __construct($inf, $infIncluded, $sup, $supIncluded)
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 __get($property)
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
11 / 11
 __set($property, $value)
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
26 / 26
 __toString()
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
2 / 2
 jsonSerialize()
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
12 / 12
 fromJson($json)
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
7 / 7
 fromString($string)
100.00% covered (success)
100.00%
1 / 1
8
100.00% covered (success)
100.00%
25 / 25
 copy(Interval $interval)
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 universe()
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 closed($inf, $sup)
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 opened($inf, $sup)
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 isEmpty()
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
1 / 1
 contains($value)
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
2 / 2
 intersection(Interval $interval)
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
17 / 17
<?php
/**
 * chdemko\Interval\Interval class
 *
 * @author     Christophe Demko <chdemko@gmail.com>
 * @copyright  Copyright (C) 2014 Christophe Demko. All rights reserved.
 *
 * @license    http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html The CeCILL B license
 *
 * This file is part of the php-interval package https://github.com/chdemko/php-interval
 */
// Declare chdemko\Interval namespace
namespace chdemko\Interval;
/**
 * Interval on the real line
 *
 * @package  Interval
 * 
 * @since    1.0.0
 *
 * @todo     Declare properties
 */
class Interval implements \JsonSerializable
{
    /**
     * @var     number  inf mark
     *
     * @since   1.0.0
     */
    private $inf;
    /**
     * @var     boolean  included inf mark flag
     *
     * @since   1.0.0
     */
    private $infIncluded;
    /**
     * @var     number  sup mark
     *
     * @since   1.0.0
     */
    private $sup;
    /**
     * @var     boolean  included sup mark flag
     *
     * @since   1.0.0
     */
    private $supIncluded;
    /**
     * Create a new interval
     *
     * @param   float    $inf          The inf mark
     * @param   boolean  $infIncluded  The included inf mark flag
     * @param   float    $sup          The sup mark
     * @param   boolean  $supIncluded  The included sup mark flag
     *
     * @since   1.0.0
     */
    public function __construct($inf, $infIncluded, $sup, $supIncluded)
    {
        $this->inf = (float) $inf;
        $this->sup = (float) $sup;
        $this->infIncluded = is_infinite($this->inf) ? false : (bool) $infIncluded;
        $this->supIncluded = is_infinite($this->sup) ? false : (bool) $supIncluded;
    }
    /**
     * Magic get method
     *
     * @param   string  $property  The property
     *
     * @throws  \RuntimeException  If the property does not exist
     *
     * @return  mixed  The value associated to the property
     *
     * @since   1.0.0
     */
    public function __get($property)
    {
        switch ($property)
        {
            case 'inf':
                return $this->inf;
            break;
            case 'infIncluded':
                return $this->infIncluded;
            break;
            case 'sup':
                return $this->sup;
            break;
            case 'supIncluded':
                return $this->supIncluded;
            break;
            default:
                throw new \RuntimeException('Undefined property');
            break;
        }
    }
    /**
     * Magic set method
     *
     * @param   string  $property  The property
     * @param   mixed   $value     The new value
     *
     * @throws  \RuntimeException  If the property does not exist
     *
     * @return  void
     *
     * @since   1.0.0
     */
    public function __set($property, $value)
    {
        switch ($property)
        {
            case 'inf':
                $value = (float) $value;
                if (is_infinite($value))
                {
                    $this->infIncluded = false;
                }
                $this->inf = $value;
            break;
            case 'infIncluded':
                $this->infIncluded = (bool) $value;
            break;
            case 'sup':
                $value = (float) $value;
                if (is_infinite($value))
                {
                    $this->supIncluded = false;
                }
                $this->sup = $value;
            break;
            case 'supIncluded':
                $this->supIncluded = (bool) $value;
            break;
            default:
                throw new \RuntimeException('Undefined property');
            break;
        }
    }
    /**
     * Convert the object to a string
     *
     * @return  string  String representation of this object
     *
     * @since   1.0.0
     */
    public function __toString()
    {
        return
            ($this->infIncluded ? '[' : ']') . $this->inf . ',' .
            $this->sup . ($this->supIncluded ? ']' : '[');
    }
    /**
     * Serialize the object
     *
     * @return  array  Array of values
     *
     * @since   1.0.0
     */
    public function jsonSerialize()
    {
        $array = [];
        if (!is_infinite($this->inf))
        {
            $array['inf'] = $this->inf;
            $array['infIncluded'] = $this->infIncluded;
        }
        if (!is_infinite($this->sup))
        {
            $array['sup'] = $this->sup;
            $array['supIncluded'] = $this->supIncluded;
        }
        return $array;
    }
    /**
     * Create a new Interval from json
     *
     * @param   string  $json  A json encoded value
     *
     * @return  Interval  A new Interval
     *
     * @since   1.0.0
     */
    public static function fromJson($json)
    {
        $values = json_decode($json);
        return new Interval(
            isset($values->inf) ? $values->inf : - INF,
            isset($values->infIncluded) ? $values->infIncluded : true,
            isset($values->sup) ? $values->sup : INF,
            isset($values->supIncluded) ? $values->supIncluded : true
        );
    }
    /**
     * Create a new Interval from string
     *
     * @param   string  $string  An interval as a string
     *
     * @return  Interval  A new Interval
     *
     * @since   1.0.0
     */
    public static function fromString($string)
    {
        if (preg_match('/(\[|\])(.*),(.*)(\[|\])/', $string, $matches))
        {
            if ($matches[2] == '-INF')
            {
                if ($matches[1] == ']')
                {
                    $inf = - INF;
                }
                else
                {
                    throw new \InvalidArgumentException('Argument must be a correct interval string');
                }
            }
            else
            {
                $inf = filter_var($matches[2], FILTER_VALIDATE_FLOAT);
            }
            if ($matches[3] == 'INF')
            {
                if ($matches[4] == '[')
                {
                    $sup = INF;
                }
                else
                {
                    throw new \InvalidArgumentException('Argument must be a correct interval string');
                }
            }
            else
            {
                $sup = filter_var($matches[3], FILTER_VALIDATE_FLOAT);
            }
            if ($inf && $sup)
            {
                return new Interval($inf, $matches[1] == '[', $sup, $matches[4] == ']');
            }
            else
            {
                throw new \InvalidArgumentException('Argument must be a correct interval string');
            }
        }
        else
        {
            throw new \InvalidArgumentException('Argument must be a correct interval string');
        }
    }
    /**
     * Copy an Interval
     *
     * @return  Interval  $this for chaining
     *
     * @since   1.0.0
     */
    public function copy(Interval $interval)
    {
        $this->inf = $interval->inf;
        $this->infIncluded = $interval->infIncluded;
        $this->sup = $interval->sup;
        $this->supIncluded = $interval->supIncluded;
        return $this;
    }
    /**
     * Create a new Interval containing all the real line
     *
     * @return  Interval  A new Interval
     *
     * @since   1.0.0
     */
    public static function universe()
    {
        return new Interval(-INF, false, INF, false);
    }
    /**
     * Create a new closed Interval
     *
     * @param   float  $inf  The inf mark
     * @param   float  $sup  The sup mark
     *
     * @return  Interval  A new Interval
     *
     * @since   1.0.0
     */
    public static function closed($inf, $sup)
    {
        return new Interval($inf, true, $sup, true);
    }
    /**
     * Create a new opened Interval
     *
     * @param   float  $inf  The inf mark
     * @param   float  $sup  The sup mark
     *
     * @return  Interval  A new Interval
     *
     * @since   1.0.0
     */
    public static function opened($inf, $sup)
    {
        return new Interval($inf, false, $sup, false);
    }
    /**
     * Test if an interval is empty
     *
     * @return  boolean  True if the interval is empty
     *
     * @since   1.0.0
     */
    public function isEmpty()
    {
        return $this->inf > $this->sup || $this->inf == $this->sup && !($this->infIncluded && $this->supIncluded);
    }
    /**
     * Test if a value is contained in the interval
     *
     * @param   float  $value  Value to be tested
     *
     * @return  boolean  Membership of value
     *
     * @since   1.0.0
     */
    public function contains($value)
    {
        return
            ($this->infIncluded ? ($value >= $this->inf) : ($value > $this->inf)) &&
            ($this->supIncluded ? ($value <= $this->sup) : ($value < $this->sup));
    }
    /**
     * Compute the intersection with another interval
     *
     * @param   Interval  $interval  Interval from which to compute intersection
     *
     * @return  Interval  $this for chaining
     *
     * @since   1.0.0
     */
    public function intersection(Interval $interval)
    {
        if ($this->inf < $interval->inf)
        {
            $this->inf = $interval->inf;
            $this->infIncluded = $interval->infIncluded;
        }
        elseif ($this->inf == $interval->inf)
        {
            $this->infIncluded = $this->infIncluded && $interval->infIncluded;
        }
        if ($this->sup > $interval->sup)
        {
            $this->sup = $interval->sup;
            $this->supIncluded = $interval->supIncluded;
        }
        elseif ($this->sup == $interval->sup)
        {
            $this->supIncluded = $this->supIncluded && $interval->supIncluded;
        }
        return $this;
    }
}