kahlan/kahlan

View on GitHub
src/Plugin/Call/Message.php

Summary

Maintainability
A
1 hr
Test Coverage
A
96%
<?php
namespace Kahlan\Plugin\Call;

use Kahlan\Arg;

class Message
{
    /**
     * Class dependencies.
     *
     * @var array
     */
    protected $_classes = [
        'arg' => Arg::class
    ];

    /**
     * Parent instance.
     *
     * @var mixed
     */
    protected $_parent = null;

    /**
     * Message reference.
     *
     * @var mixed
     */
    protected $_reference = null;

    /**
     * Message name.
     *
     * @var string
     */
    protected $_name = null;

    /**
     * Message arguments.
     *
     * @var array
     */
    protected $_args = null;

    /**
     * Static call.
     *
     * @var boolean
     */
    protected $_static = false;

    /**
     * The Constructor.
     *
     * @param array $config Possible options are:
     *                       - `'reference'` _mixed_  : The message reference.
     *                       - `'name'`      _string_ : The message name.
     *                       - `'args'`      _array_  : The message arguments.
     *                       - `'static'`    _boolean_: `true` if the method is static, `false` otherwise.
     */
    public function __construct($config = [])
    {
        $defaults = [
            'parent' => null,
            'reference' => null,
            'name' => '',
            'args' => null,
            'static' => false
        ];
        $config += $defaults;

        $static = $config['static'];
        $name = $config['name'];
        if (preg_match('/^::.*/', $name)) {
            $static = true;
            $name = substr($name, 2);
        }

        $this->_parent = $config['parent'];
        $this->_reference = $config['reference'];
        $this->_name = $name;
        $this->_args = $config['args'];
        $this->_static = $static;
    }

    /**
     * Set arguments requirement.
     *
     * @param  mixed ... <0,n> Argument(s).
     * @return self
     */
    public function with()
    {
        $this->_args = func_get_args();
        return $this;
    }

    /**
     * Set arguments requirement indexed by method name.
     *
     * @param  mixed ... <0,n> Argument(s).
     * @return self
     */
    public function where($requirements = [])
    {
        $this->_parent->where($requirements);
        return $this;
    }

    /**
     * Check if this message is compatible with passed call array.
     *
     * @param  array   $call     A call array.
     * @param  boolean $withArgs Boolean indicating if matching should take arguments into account.
     * @return boolean
     */
    public function match($call, $withArgs = true)
    {
        if (preg_match('/^::.*/', $call['name'])) {
            $call['static'] = true;
            $call['name'] = substr($call['name'], 2);
        }

        if (isset($call['static'])) {
            if ($call['static'] !== $this->_static) {
                return false;
            }
        }

        if ($call['name'] !== $this->_name) {
            return false;
        }

        if ($withArgs) {
            return $this->matchArgs($call['args']);
        }

        return true;
    }

    /**
     * Check if this stub is compatible with passed args.
     *
     * @param  array   $args The passed arguments.
     * @return boolean
     */
    public function matchArgs($args)
    {
        if ($this->_args === null || $args === null) {
            return true;
        }
        $arg = $this->_classes['arg'];
        foreach ($this->_args as $expected) {
            $actual = array_shift($args);
            if ($expected instanceof $arg) {
                if (!$expected->match($actual)) {
                    return false;
                }
            } elseif ($actual !== $expected) {
                return false;
            }
        }
        return true;
    }

    /**
     * Check if this stub does require some specific args
     *
     * @return boolean
     */
    public function requireArgs()
    {
        return $this->_args !== null;
    }

    /**
     * Get the parent.
     *
     * @return mixed
     */
    public function parent()
    {
        return $this->_parent;
    }

    /**
     * Get the message reference.
     *
     * @return mixed
     */
    public function reference()
    {
        return $this->_reference;
    }

    /**
     * Get message name.
     *
     * @return string
     */
    public function name()
    {
        return $this->isStatic() ? '::' . $this->_name : $this->_name;
    }

    /**
     * Get message arguments.
     *
     * @return array
     */
    public function args()
    {
        return $this->_args;
    }

    /**
     * Check if the method is a static method.
     *
     * @return boolean
     */
    public function isStatic()
    {
        return $this->_static;
    }
}