1<?php
2/*
3 * This file is part of PHPUnit.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11/**
12 * Constraint that checks if one value is equal to another.
13 *
14 * Equality is checked with PHP's == operator, the operator is explained in
15 * detail at {@url http://www.php.net/manual/en/types.comparisons.php}.
16 * Two values are equal if they have the same value disregarding type.
17 *
18 * The expected value is passed in the constructor.
19 */
20class PHPUnit_Framework_Constraint_IsEqual extends PHPUnit_Framework_Constraint
21{
22    /**
23     * @var mixed
24     */
25    protected $value;
26
27    /**
28     * @var float
29     */
30    protected $delta = 0.0;
31
32    /**
33     * @var int
34     */
35    protected $maxDepth = 10;
36
37    /**
38     * @var bool
39     */
40    protected $canonicalize = false;
41
42    /**
43     * @var bool
44     */
45    protected $ignoreCase = false;
46
47    /**
48     * @var SebastianBergmann\Comparator\ComparisonFailure
49     */
50    protected $lastFailure;
51
52    /**
53     * @param mixed $value
54     * @param float $delta
55     * @param int   $maxDepth
56     * @param bool  $canonicalize
57     * @param bool  $ignoreCase
58     *
59     * @throws PHPUnit_Framework_Exception
60     */
61    public function __construct($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
62    {
63        parent::__construct();
64
65        if (!is_numeric($delta)) {
66            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'numeric');
67        }
68
69        if (!is_int($maxDepth)) {
70            throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'integer');
71        }
72
73        if (!is_bool($canonicalize)) {
74            throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean');
75        }
76
77        if (!is_bool($ignoreCase)) {
78            throw PHPUnit_Util_InvalidArgumentHelper::factory(5, 'boolean');
79        }
80
81        $this->value        = $value;
82        $this->delta        = $delta;
83        $this->maxDepth     = $maxDepth;
84        $this->canonicalize = $canonicalize;
85        $this->ignoreCase   = $ignoreCase;
86    }
87
88    /**
89     * Evaluates the constraint for parameter $other
90     *
91     * If $returnResult is set to false (the default), an exception is thrown
92     * in case of a failure. null is returned otherwise.
93     *
94     * If $returnResult is true, the result of the evaluation is returned as
95     * a boolean value instead: true in case of success, false in case of a
96     * failure.
97     *
98     * @param mixed  $other        Value or object to evaluate.
99     * @param string $description  Additional information about the test
100     * @param bool   $returnResult Whether to return a result or throw an exception
101     *
102     * @return mixed
103     *
104     * @throws PHPUnit_Framework_ExpectationFailedException
105     */
106    public function evaluate($other, $description = '', $returnResult = false)
107    {
108        // If $this->value and $other are identical, they are also equal.
109        // This is the most common path and will allow us to skip
110        // initialization of all the comparators.
111        if ($this->value === $other) {
112            return true;
113        }
114
115        $comparatorFactory = SebastianBergmann\Comparator\Factory::getInstance();
116
117        try {
118            $comparator = $comparatorFactory->getComparatorFor(
119                $this->value,
120                $other
121            );
122
123            $comparator->assertEquals(
124                $this->value,
125                $other,
126                $this->delta,
127                $this->canonicalize,
128                $this->ignoreCase
129            );
130        } catch (SebastianBergmann\Comparator\ComparisonFailure $f) {
131            if ($returnResult) {
132                return false;
133            }
134
135            throw new PHPUnit_Framework_ExpectationFailedException(
136                trim($description . "\n" . $f->getMessage()),
137                $f
138            );
139        }
140
141        return true;
142    }
143
144    /**
145     * Returns a string representation of the constraint.
146     *
147     * @return string
148     */
149    public function toString()
150    {
151        $delta = '';
152
153        if (is_string($this->value)) {
154            if (strpos($this->value, "\n") !== false) {
155                return 'is equal to <text>';
156            } else {
157                return sprintf(
158                    'is equal to <string:%s>',
159                    $this->value
160                );
161            }
162        } else {
163            if ($this->delta != 0) {
164                $delta = sprintf(
165                    ' with delta <%F>',
166                    $this->delta
167                );
168            }
169
170            return sprintf(
171                'is equal to %s%s',
172                $this->exporter->export($this->value),
173                $delta
174            );
175        }
176    }
177}
178