autowp/autowp

View on GitHub
module/Application/src/Hydrator/Api/PictureItemHydrator.php

Summary

Maintainability
A
3 hrs
Test Coverage
B
82%
<?php

namespace Application\Hydrator\Api;

use Application\Model\Item;
use Application\Model\Picture;
use ArrayAccess;
use Autowp\User\Model\User;
use Casbin\Enforcer;
use Exception;
use Laminas\Hydrator\Exception\InvalidArgumentException;
use Laminas\ServiceManager\ServiceLocatorInterface;
use Laminas\Stdlib\ArrayUtils;
use Traversable;

use function is_array;

class PictureItemHydrator extends AbstractRestHydrator
{
    private int $userId = 0;

    private ?string $userRole;

    private Item $item;

    private Picture $picture;

    private Enforcer $acl;

    private User $userModel;

    public function __construct(ServiceLocatorInterface $serviceManager)
    {
        parent::__construct();

        $this->item      = $serviceManager->get(Item::class);
        $this->picture   = $serviceManager->get(Picture::class);
        $this->userModel = $serviceManager->get(User::class);

        $this->acl = $serviceManager->get(Enforcer::class);

        $strategy = new Strategy\Item($serviceManager);
        $this->addStrategy('item', $strategy);

        $strategy = new Strategy\Picture($serviceManager);
        $this->addStrategy('picture', $strategy);
    }

    /**
     * @param  array|Traversable $options
     * @throws InvalidArgumentException
     */
    public function setOptions($options): self
    {
        parent::setOptions($options);

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        } elseif (! is_array($options)) {
            throw new InvalidArgumentException(
                'The options parameter must be an array or a Traversable'
            );
        }

        if (isset($options['user_id'])) {
            $this->setUserId($options['user_id']);
        }

        return $this;
    }

    public function setUserId(?int $userId): self
    {
        $userId = (int) $userId;
        if ($this->userId !== $userId) {
            $this->userId   = $userId;
            $this->userRole = null;

            /** @var Strategy\Item $strategy */
            $strategy = $this->getStrategy('item');
            $strategy->setUserId($userId);
        }

        return $this;
    }

    /**
     * @param array|ArrayAccess $object
     * @throws Exception
     */
    public function extract($object): ?array
    {
        $result = [
            'picture_id'     => (int) $object['picture_id'],
            'item_id'        => (int) $object['item_id'],
            'type'           => (int) $object['type'],
            'perspective_id' => (int) $object['perspective_id'],
        ];

        $isModer = false;
        $role    = $this->getUserRole();
        if ($role) {
            $isModer = $this->acl->enforce($role, 'global', 'moderate');
        }

        if ($this->filterComposite->filter('item')) {
            $row = $this->item->getRow(['id' => (int) $object['item_id']]);

            $result['item'] = $row ? $this->extractValue('item', $row) : null;
        }

        if ($isModer) {
            if ($this->filterComposite->filter('picture')) {
                $row = $this->picture->getRow(['id' => (int) $object['picture_id']]);

                $result['picture'] = $row ? $this->extractValue('picture', $row) : null;
            }

            if ($this->filterComposite->filter('area')) {
                $hasArea        = $object['crop_width'] && $object['crop_height'];
                $result['area'] = null;
                if ($hasArea) {
                    $result['area'] = [
                        'left'   => (int) $object['crop_left'],
                        'top'    => (int) $object['crop_top'],
                        'width'  => (int) $object['crop_width'],
                        'height' => (int) $object['crop_height'],
                    ];
                }
            }
        }

        return $result;
    }

    /**
     * @throws Exception
     */
    private function getUserRole(): ?string
    {
        if (! $this->userId) {
            return null;
        }

        if (! isset($this->userRole)) {
            $this->userRole = $this->userModel->getUserRole($this->userId);
        }

        return $this->userRole;
    }

    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     * @param object $object
     * @throws Exception
     */
    public function hydrate(array $data, $object): object
    {
        throw new Exception("Not supported");
    }
}