1<?php
2
3/*
4 * This file is part of the Prophecy.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6 *     Marcello Duarte <marcello.duarte@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Prophecy\Argument\Token;
13
14use SebastianBergmann\Comparator\ComparisonFailure;
15use Prophecy\Comparator\Factory as ComparatorFactory;
16use Prophecy\Util\StringUtil;
17
18/**
19 * Object state-checker token.
20 *
21 * @author Konstantin Kudryashov <ever.zet@gmail.com>
22 */
23class ObjectStateToken implements TokenInterface
24{
25    private $name;
26    private $value;
27    private $util;
28    private $comparatorFactory;
29
30    /**
31     * Initializes token.
32     *
33     * @param string            $methodName
34     * @param mixed             $value             Expected return value
35     * @param null|StringUtil   $util
36     * @param ComparatorFactory $comparatorFactory
37     */
38    public function __construct(
39        $methodName,
40        $value,
41        StringUtil $util = null,
42        ComparatorFactory $comparatorFactory = null
43    ) {
44        $this->name  = $methodName;
45        $this->value = $value;
46        $this->util  = $util ?: new StringUtil;
47
48        $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance();
49    }
50
51    /**
52     * Scores 8 if argument is an object, which method returns expected value.
53     *
54     * @param mixed $argument
55     *
56     * @return bool|int
57     */
58    public function scoreArgument($argument)
59    {
60        if (is_object($argument) && method_exists($argument, $this->name)) {
61            $actual = call_user_func(array($argument, $this->name));
62
63            $comparator = $this->comparatorFactory->getComparatorFor(
64                $this->value, $actual
65            );
66
67            try {
68                $comparator->assertEquals($this->value, $actual);
69                return 8;
70            } catch (ComparisonFailure $failure) {
71                return false;
72            }
73        }
74
75        if (is_object($argument) && property_exists($argument, $this->name)) {
76            return $argument->{$this->name} === $this->value ? 8 : false;
77        }
78
79        return false;
80    }
81
82    /**
83     * Returns false.
84     *
85     * @return bool
86     */
87    public function isLast()
88    {
89        return false;
90    }
91
92    /**
93     * Returns string representation for token.
94     *
95     * @return string
96     */
97    public function __toString()
98    {
99        return sprintf('state(%s(), %s)',
100            $this->name,
101            $this->util->stringify($this->value)
102        );
103    }
104}
105