skqr/hateoas

View on GitHub
Metadata/Resource/MiningTools.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php
/**
 * @copyright 2014 Integ S.A.
 * @license http://opensource.org/licenses/MIT The MIT License (MIT)
 * @author Javier Lorenzana <javier.lorenzana@gointegro.com>
 */

namespace GoIntegro\Hateoas\Metadata\Resource;

// Interfaces.
use GoIntegro\Hateoas\JsonApi\ResourceEntityInterface;
// Metadata.
use GoIntegro\Hateoas\Metadata\Entity\MetadataCache;
// Datos.
use GoIntegro\Hateoas\Util\Inflector;
// ORM.
use Doctrine\ORM\Mapping\ClassMetadata;
// Reflexión.
use GoIntegro\Hateoas\Util\Reflection;
// Recursos.
use GoIntegro\Hateoas\JsonApi\EntityResource;
// Excepciones.
use Exception;

trait MiningTools
{
    /**
     * @var array
     * @see http://jsonapi.org/format/#document-structure-resource-object-attributes
     */
    private static $reservedGetters = ["getId", "getType", "getHref", "getLinks"];

    /**
     * @param string|ResourceEntityInterface $entityClassName
     * @return \ReflectionClass
     * @todo Support searching through any number of parent classes?
     */
    public function getResourceClass($entityClassName)
    {
        $className = MetadataMiner::DEFAULT_RESOURCE_CLASS;
        $class = $this->metadataCache->getReflection($entityClassName);
        $parentClass = $class->getParentClass();
        $resourceClassName = $this->entityClassToResourceClass($class);

        if (class_exists($resourceClassName)) {
            $className = $resourceClassName;
        } elseif (
            !empty($parentClass)
            && $parentClass->implementsInterface(
                MetadataMiner::RESOURCE_ENTITY_INTERFACE
            )
        ) {
            $resourceClassName
                = $this->entityClassToResourceClass($parentClass);

            if (class_exists($resourceClassName)) {
                $className = $resourceClassName;
            }
        }

        return $this->metadataCache->getReflection($className);
    }

    /**
     * @param \ReflectionClass $class
     * @return string
     */
    protected function entityClassToResourceClass(\ReflectionClass $class)
    {
        $path = strtr($this->resourceClassPath, '/', '\\');

        return str_replace('Entity', $path, $class->getName()) . 'Resource';
    }

    /**
     * @param string|ResourceEntityInterface $entityClass
     * @return string
     */
    protected function parseSubtype($entityClassName)
    {
        $class = $this->metadataCache->getReflection($entityClassName);

        return Inflector::typify($class->getShortName());
    }

    /**
     * @param \GoIntegro\Hateoas\JsonApi\ResourceEntityInterface|string $entityClassName
     * @param ResourceRelationships $relationships
     * @return array
     * @todo Publicar o eliminar el parámetro $entityClassName.
     */
    protected function getFields(
        $entityClassName,
        ResourceRelationships $relationships
    )
    {
        $fields = [];
        $class = $this->metadataCache->getReflection($entityClassName);

        foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
            if (in_array($method->getShortName(), self::$reservedGetters)) {
                continue;
            }

            if (Reflection::isMethodGetter($method)) {
                $fields[] = Inflector::hyphenate(
                    substr($method->getShortName(), 3)
                );
            }
        }

        foreach (ResourceRelationships::$kinds as $kind) {
            $fields = array_diff($fields, array_keys($relationships->$kind));
        }

        $fields = array_diff($fields, $relationships->dbOnly);

        return new ResourceFields($fields);
    }
}