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 * Logical XOR.
13 */
14class PHPUnit_Framework_Constraint_Xor extends PHPUnit_Framework_Constraint
15{
16    /**
17     * @var PHPUnit_Framework_Constraint[]
18     */
19    protected $constraints = [];
20
21    /**
22     * @param PHPUnit_Framework_Constraint[] $constraints
23     */
24    public function setConstraints(array $constraints)
25    {
26        $this->constraints = [];
27
28        foreach ($constraints as $constraint) {
29            if (!($constraint instanceof PHPUnit_Framework_Constraint)) {
30                $constraint = new PHPUnit_Framework_Constraint_IsEqual(
31                    $constraint
32                );
33            }
34
35            $this->constraints[] = $constraint;
36        }
37    }
38
39    /**
40     * Evaluates the constraint for parameter $other
41     *
42     * If $returnResult is set to false (the default), an exception is thrown
43     * in case of a failure. null is returned otherwise.
44     *
45     * If $returnResult is true, the result of the evaluation is returned as
46     * a boolean value instead: true in case of success, false in case of a
47     * failure.
48     *
49     * @param mixed  $other        Value or object to evaluate.
50     * @param string $description  Additional information about the test
51     * @param bool   $returnResult Whether to return a result or throw an exception
52     *
53     * @return mixed
54     *
55     * @throws PHPUnit_Framework_ExpectationFailedException
56     */
57    public function evaluate($other, $description = '', $returnResult = false)
58    {
59        $success    = true;
60        $lastResult = null;
61        $constraint = null;
62
63        foreach ($this->constraints as $constraint) {
64            $result = $constraint->evaluate($other, $description, true);
65
66            if ($result === $lastResult) {
67                $success = false;
68                break;
69            }
70
71            $lastResult = $result;
72        }
73
74        if ($returnResult) {
75            return $success;
76        }
77
78        if (!$success) {
79            $this->fail($other, $description);
80        }
81    }
82
83    /**
84     * Returns a string representation of the constraint.
85     *
86     * @return string
87     */
88    public function toString()
89    {
90        $text = '';
91
92        foreach ($this->constraints as $key => $constraint) {
93            if ($key > 0) {
94                $text .= ' xor ';
95            }
96
97            $text .= $constraint->toString();
98        }
99
100        return $text;
101    }
102
103    /**
104     * Counts the number of constraint elements.
105     *
106     * @return int
107     */
108    public function count()
109    {
110        $count = 0;
111
112        foreach ($this->constraints as $constraint) {
113            $count += count($constraint);
114        }
115
116        return $count;
117    }
118}
119