Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x

ObjectProphecy.php

Namespace

Prophecy\Prophecy

File

vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php

View source
<?php


/*
 * This file is part of the Prophecy.
 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
 *     Marcello Duarte <marcello.duarte@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Prophecy\Prophecy;

use Prophecy\Comparator\FactoryProvider;
use SebastianBergmann\Comparator\ComparisonFailure;
use SebastianBergmann\Comparator\Factory as ComparatorFactory;
use Prophecy\Call\Call;
use Prophecy\Doubler\LazyDouble;
use Prophecy\Argument\ArgumentsWildcard;
use Prophecy\Call\CallCenter;
use Prophecy\Exception\Prophecy\ObjectProphecyException;
use Prophecy\Exception\Prophecy\MethodProphecyException;
use Prophecy\Exception\Prediction\AggregateException;
use Prophecy\Exception\Prediction\PredictionException;

/**
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @template-covariant T of object
 * @template-implements ProphecyInterface<T>
 */
class ObjectProphecy implements ProphecyInterface {
    
    /**
     * @var LazyDouble<T>
     */
    private $lazyDouble;
    private $callCenter;
    private $revealer;
    private $comparatorFactory;
    
    /**
     * @var array<string, list<MethodProphecy>>
     */
    private $methodProphecies = array();
    
    /**
     * @param LazyDouble<T> $lazyDouble
     */
    public function __construct(LazyDouble $lazyDouble, ?CallCenter $callCenter = null, ?RevealerInterface $revealer = null, ?ComparatorFactory $comparatorFactory = null) {
        $this->lazyDouble = $lazyDouble;
        $this->callCenter = $callCenter ?: new CallCenter();
        $this->revealer = $revealer ?: new Revealer();
        $this->comparatorFactory = $comparatorFactory ?: FactoryProvider::getInstance();
    }
    
    /**
     * Forces double to extend specific class.
     *
     * @param string $class
     *
     * @return $this
     *
     * @template U of object
     * @phpstan-param class-string<U> $class
     * @phpstan-this-out static<T&U>
     */
    public function willExtend($class) {
        $this->lazyDouble
            ->setParentClass($class);
        return $this;
    }
    
    /**
     * Forces double to implement specific interface.
     *
     * @param string $interface
     *
     * @return $this
     *
     * @template U of object
     * @phpstan-param class-string<U> $interface
     * @phpstan-this-out static<T&U>
     */
    public function willImplement($interface) {
        $this->lazyDouble
            ->addInterface($interface);
        return $this;
    }
    
    /**
     * Sets constructor arguments.
     *
     * @param array<mixed> $arguments
     *
     * @return $this
     */
    public function willBeConstructedWith(?array $arguments = null) {
        $this->lazyDouble
            ->setArguments($arguments);
        return $this;
    }
    
    /**
     * Reveals double.
     *
     * @return object
     *
     * @throws \Prophecy\Exception\Prophecy\ObjectProphecyException If double doesn't implement needed interface
     *
     * @phpstan-return T
     */
    public function reveal() {
        $double = $this->lazyDouble
            ->getInstance();
        if (!$double instanceof ProphecySubjectInterface) {
            throw new ObjectProphecyException("Generated double must implement ProphecySubjectInterface, but it does not.\n" . 'It seems you have wrongly configured doubler without required ClassPatch.', $this);
        }
        $double->setProphecy($this);
        return $double;
    }
    
    /**
     * Adds method prophecy to object prophecy.
     *
     * @param MethodProphecy $methodProphecy
     *
     * @return void
     */
    public function addMethodProphecy(MethodProphecy $methodProphecy) {
        $methodName = strtolower($methodProphecy->getMethodName());
        if (!isset($this->methodProphecies[$methodName])) {
            $this->methodProphecies[$methodName] = array();
        }
        $this->methodProphecies[$methodName][] = $methodProphecy;
    }
    
    /**
     * Returns either all or related to single method prophecies.
     *
     * @param null|string $methodName
     *
     * @return MethodProphecy[]|array<string, MethodProphecy[]>
     *
     * @phpstan-return ($methodName is string ? list<MethodProphecy> : array<string, list<MethodProphecy>>)
     */
    public function getMethodProphecies($methodName = null) {
        if (null === $methodName) {
            return $this->methodProphecies;
        }
        $methodName = strtolower($methodName);
        if (!isset($this->methodProphecies[$methodName])) {
            return array();
        }
        return $this->methodProphecies[$methodName];
    }
    
    /**
     * Makes specific method call.
     *
     * @param string $methodName
     * @param array<mixed> $arguments
     *
     * @return mixed
     */
    public function makeProphecyMethodCall($methodName, array $arguments) {
        $arguments = $this->revealer
            ->reveal($arguments);
        \assert(\is_array($arguments));
        $return = $this->callCenter
            ->makeCall($this, $methodName, $arguments);
        return $this->revealer
            ->reveal($return);
    }
    
    /**
     * Finds calls by method name & arguments wildcard.
     *
     * @param string            $methodName
     * @param ArgumentsWildcard $wildcard
     *
     * @return list<Call>
     */
    public function findProphecyMethodCalls($methodName, ArgumentsWildcard $wildcard) {
        return $this->callCenter
            ->findCalls($methodName, $wildcard);
    }
    
    /**
     * Checks that registered method predictions do not fail.
     *
     * @return void
     *
     * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail
     * @throws \Prophecy\Exception\Call\UnexpectedCallException
     */
    public function checkProphecyMethodsPredictions() {
        $exception = new AggregateException(sprintf("%s:\n", get_class($this->reveal())));
        $exception->setObjectProphecy($this);
        $this->callCenter
            ->checkUnexpectedCalls();
        foreach ($this->methodProphecies as $prophecies) {
            foreach ($prophecies as $prophecy) {
                try {
                    $prophecy->checkPrediction();
                } catch (PredictionException $e) {
                    $exception->append($e);
                }
            }
        }
        if (count($exception->getExceptions())) {
            throw $exception;
        }
    }
    
    /**
     * Creates new method prophecy using specified method name and arguments.
     *
     * @param string $methodName
     * @param array<mixed> $arguments
     *
     * @return MethodProphecy
     */
    public function __call($methodName, array $arguments) {
        $arguments = $this->revealer
            ->reveal($arguments);
        \assert(\is_array($arguments));
        $arguments = new ArgumentsWildcard($arguments);
        foreach ($this->getMethodProphecies($methodName) as $prophecy) {
            $argumentsWildcard = $prophecy->getArgumentsWildcard();
            $comparator = $this->comparatorFactory
                ->getComparatorFor($argumentsWildcard, $arguments);
            try {
                $comparator->assertEquals($argumentsWildcard, $arguments);
                return $prophecy;
            } catch (ComparisonFailure $failure) {
            }
        }
        return new MethodProphecy($this, $methodName, $arguments);
    }
    
    /**
     * Tries to get property value from double.
     *
     * @param string $name
     *
     * @return mixed
     */
    public function __get($name) {
        return $this->reveal()->{$name};
    }
    
    /**
     * Tries to set property value to double.
     *
     * @param string $name
     * @param mixed  $value
     *
     * @return void
     */
    public function __set($name, $value) {
        $this->reveal()->{$name} = $this->revealer
            ->reveal($value);
    }

}

Classes

Title Deprecated Summary
ObjectProphecy @author Konstantin Kudryashov <ever.zet@gmail.com>

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal