bkdotcom/PHPDebugConsole

View on GitHub
src/Teams/AbstractItem.php

Summary

Maintainability
A
40 mins
Test Coverage
C
72%
<?php

namespace bdk\Teams;

use bdk\Teams\CardUtilityTrait;
use bdk\Teams\ItemInterface;
use InvalidArgumentException;
use LogicException;
use OutOfBoundsException;

/**
 * The base object off of which Elements and Actions are built
 */
class AbstractItem implements ItemInterface
{
    use CardUtilityTrait;

    /** @var string Element type */
    protected $type;

    /** @var array<string,mixed> */
    protected $fields = array();

    /**
     * Constructor
     *
     * @param array<string,mixed> $fields Field values
     * @param string              $type   Item type
     */
    public function __construct(array $fields = array(), $type = 'Unknown')
    {
        $this->fields = \array_merge($this->fields, $fields);
        $this->type = $type;
    }

    /**
     * Return attribute/property value
     *
     * @param string $name Attribute name
     *
     * @return mixed
     *
     * @throws OutOfBoundsException
     */
    public function get($name)
    {
        if ($name === 'type') {
            return $this->type;
        }
        if (\array_key_exists($name, $this->fields)) {
            return $this->fields[$name];
        }
        throw new OutOfBoundsException(\sprintf(
            '%s does not have %s property',
            $this->type,
            $name
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function getContent($version) // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
    {
        return array(
            'type' => $this->type,
        );
    }

    /**
     * Assert that a value is of a certain type
     *
     * Support extreme range of PHP versions : 5.4 - 8.4 (and beyond)
     * `MyObj $obj = null` has been deprecated in PHP 8.4
     * must now be `?MyObj $obj = null` (which is a php 7.1 feature)
     * Workaround - remove type-hint when we allow null (not ideal) and call assertType
     * When we drop support for php < 7.1, we can remove this method and do proper type-hinting
     *
     * @param mixed  $value     Value to test
     * @param string $type      "array", "callable", "object", or className
     * @param bool   $allowNull (true) allow null?
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    protected static function assertType($value, $type, $allowNull = true)
    {
        if ($allowNull && $value === null) {
            return;
        }
        if (self::assertTypeCheck($value, $type)) {
            return;
        }
        throw new InvalidArgumentException(\sprintf(
            'Expected %s%s, got %s',
            $type,
            $allowNull ? ' (or null)' : '',
            self::getDebugType($value)
        ));
    }

    /**
     * Test if value is of a certain type
     *
     * @param mixed  $value Value to test
     * @param string $type  "array", "callable", "object", or className
     *
     * @return bool
     */
    private static function assertTypeCheck($value, $type)
    {
        // For teams we don't need 'array', 'callable', or 'object' tests
        switch ($type) {
            case 'array':
                return \is_array($value);
            case 'callable':
                return \is_callable($value);
            case 'object':
                return \is_object($value);
            default:
                return \is_a($value, $type);
        }
        return false;
    }

    /**
     * Return new instance with updated property value
     *
     * @param string $name  attribute/property name
     * @param mixed  $value new value
     *
     * @return static
     */
    protected function with($name, $value)
    {
        $new = clone $this;
        $new->fields[$name] = $value;
        return $new;
    }

    /**
     * Return new instance with value appended to array
     *
     * @param string $name  Name of array attribute
     * @param mixed  $value Value to append
     *
     * @return static
     *
     * @throws LogicException
     */
    protected function withAdded($name, $value)
    {
        $new = clone $this;
        if (\is_array($new->fields[$name]) === false) {
            throw new LogicException(\sprintf(
                '%s :  unable to add additional %s',
                $this->type,
                $name
            ));
        }
        $new->fields[$name][] = $value;
        return $new;
    }
}