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
11use SebastianBergmann\Exporter\Exporter;
12
13/**
14 * Abstract base class for constraints which can be applied to any value.
15 */
16abstract class PHPUnit_Framework_Constraint implements Countable, PHPUnit_Framework_SelfDescribing
17{
18    protected $exporter;
19
20    public function __construct()
21    {
22        $this->exporter = new Exporter;
23    }
24
25    /**
26     * Evaluates the constraint for parameter $other
27     *
28     * If $returnResult is set to false (the default), an exception is thrown
29     * in case of a failure. null is returned otherwise.
30     *
31     * If $returnResult is true, the result of the evaluation is returned as
32     * a boolean value instead: true in case of success, false in case of a
33     * failure.
34     *
35     * @param mixed  $other        Value or object to evaluate.
36     * @param string $description  Additional information about the test
37     * @param bool   $returnResult Whether to return a result or throw an exception
38     *
39     * @return mixed
40     *
41     * @throws PHPUnit_Framework_ExpectationFailedException
42     */
43    public function evaluate($other, $description = '', $returnResult = false)
44    {
45        $success = false;
46
47        if ($this->matches($other)) {
48            $success = true;
49        }
50
51        if ($returnResult) {
52            return $success;
53        }
54
55        if (!$success) {
56            $this->fail($other, $description);
57        }
58    }
59
60    /**
61     * Evaluates the constraint for parameter $other. Returns true if the
62     * constraint is met, false otherwise.
63     *
64     * This method can be overridden to implement the evaluation algorithm.
65     *
66     * @param mixed $other Value or object to evaluate.
67     *
68     * @return bool
69     */
70    protected function matches($other)
71    {
72        return false;
73    }
74
75    /**
76     * Counts the number of constraint elements.
77     *
78     * @return int
79     */
80    public function count()
81    {
82        return 1;
83    }
84
85    /**
86     * Throws an exception for the given compared value and test description
87     *
88     * @param mixed                                          $other             Evaluated value or object.
89     * @param string                                         $description       Additional information about the test
90     * @param SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure
91     *
92     * @throws PHPUnit_Framework_ExpectationFailedException
93     */
94    protected function fail($other, $description, SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null)
95    {
96        $failureDescription = sprintf(
97            'Failed asserting that %s.',
98            $this->failureDescription($other)
99        );
100
101        $additionalFailureDescription = $this->additionalFailureDescription($other);
102
103        if ($additionalFailureDescription) {
104            $failureDescription .= "\n" . $additionalFailureDescription;
105        }
106
107        if (!empty($description)) {
108            $failureDescription = $description . "\n" . $failureDescription;
109        }
110
111        throw new PHPUnit_Framework_ExpectationFailedException(
112            $failureDescription,
113            $comparisonFailure
114        );
115    }
116
117    /**
118     * Return additional failure description where needed
119     *
120     * The function can be overridden to provide additional failure
121     * information like a diff
122     *
123     * @param mixed $other Evaluated value or object.
124     *
125     * @return string
126     */
127    protected function additionalFailureDescription($other)
128    {
129        return '';
130    }
131
132    /**
133     * Returns the description of the failure
134     *
135     * The beginning of failure messages is "Failed asserting that" in most
136     * cases. This method should return the second part of that sentence.
137     *
138     * To provide additional failure information additionalFailureDescription
139     * can be used.
140     *
141     * @param mixed $other Evaluated value or object.
142     *
143     * @return string
144     */
145    protected function failureDescription($other)
146    {
147        return $this->exporter->export($other) . ' ' . $this->toString();
148    }
149}
150