PHP Classes

File: vendor/phpdocumentor/type-resolver/src/TypeResolver.php

Recommend this page to a friend!
  Classes of Renato De Oliveira Lucena   PHP Pokemon Script   vendor/phpdocumentor/type-resolver/src/TypeResolver.php   Download  
File: vendor/phpdocumentor/type-resolver/src/TypeResolver.php
Role: Class source
Content type: text/plain
Description: Class source
Class: PHP Pokemon Script
Provides an API to manage a database of Pokemons
Author: By
Last change:
Date: 6 years ago
Size: 8,862 bytes
 

Contents

Class file image Download
<?php
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use
phpDocumentor\Reflection\Types\Array_;
use
phpDocumentor\Reflection\Types\Compound;
use
phpDocumentor\Reflection\Types\Context;
use
phpDocumentor\Reflection\Types\Object_;

final class
TypeResolver
{
   
/** @var string Definition of the ARRAY operator for types */
   
const OPERATOR_ARRAY = '[]';

   
/** @var string Definition of the NAMESPACE operator in PHP */
   
const OPERATOR_NAMESPACE = '\\';

   
/** @var string[] List of recognized keywords and unto which Value Object they map */
   
private $keywords = array(
       
'string' => 'phpDocumentor\Reflection\Types\String_',
       
'int' => 'phpDocumentor\Reflection\Types\Integer',
       
'integer' => 'phpDocumentor\Reflection\Types\Integer',
       
'bool' => 'phpDocumentor\Reflection\Types\Boolean',
       
'boolean' => 'phpDocumentor\Reflection\Types\Boolean',
       
'float' => 'phpDocumentor\Reflection\Types\Float_',
       
'double' => 'phpDocumentor\Reflection\Types\Float_',
       
'object' => 'phpDocumentor\Reflection\Types\Object_',
       
'mixed' => 'phpDocumentor\Reflection\Types\Mixed',
       
'array' => 'phpDocumentor\Reflection\Types\Array_',
       
'resource' => 'phpDocumentor\Reflection\Types\Resource',
       
'void' => 'phpDocumentor\Reflection\Types\Void_',
       
'null' => 'phpDocumentor\Reflection\Types\Null_',
       
'scalar' => 'phpDocumentor\Reflection\Types\Scalar',
       
'callback' => 'phpDocumentor\Reflection\Types\Callable_',
       
'callable' => 'phpDocumentor\Reflection\Types\Callable_',
       
'false' => 'phpDocumentor\Reflection\Types\Boolean',
       
'true' => 'phpDocumentor\Reflection\Types\Boolean',
       
'self' => 'phpDocumentor\Reflection\Types\Self_',
       
'$this' => 'phpDocumentor\Reflection\Types\This',
       
'static' => 'phpDocumentor\Reflection\Types\Static_'
   
);

   
/** @var FqsenResolver */
   
private $fqsenResolver;

   
/**
     * Initializes this TypeResolver with the means to create and resolve Fqsen objects.
     *
     * @param FqsenResolver $fqsenResolver
     */
   
public function __construct(FqsenResolver $fqsenResolver = null)
    {
       
$this->fqsenResolver = $fqsenResolver ?: new FqsenResolver();
    }

   
/**
     * Analyzes the given type and returns the FQCN variant.
     *
     * When a type is provided this method checks whether it is not a keyword or
     * Fully Qualified Class Name. If so it will use the given namespace and
     * aliases to expand the type to a FQCN representation.
     *
     * This method only works as expected if the namespace and aliases are set;
     * no dynamic reflection is being performed here.
     *
     * @param string $type The relative or absolute type.
     * @param Context $context
     *
     * @uses Context::getNamespace() to determine with what to prefix the type name.
     * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
     * replaced with another namespace.
     *
     * @return Type|null
     */
   
public function resolve($type, Context $context = null)
    {
        if (!
is_string($type)) {
            throw new \
InvalidArgumentException(
               
'Attempted to resolve type but it appeared not to be a string, received: ' . var_export($type, true)
            );
        }

       
$type = trim($type);
        if (!
$type) {
            throw new \
InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
        }

        if (
$context === null) {
           
$context = new Context('');
        }

        switch (
true) {
            case
$this->isKeyword($type):
                return
$this->resolveKeyword($type);
            case (
$this->isCompoundType($type)):
                return
$this->resolveCompoundType($type, $context);
            case
$this->isTypedArray($type):
                return
$this->resolveTypedArray($type, $context);
            case
$this->isFqsen($type):
                return
$this->resolveTypedObject($type);
            case
$this->isPartialStructuralElementName($type):
                return
$this->resolveTypedObject($type, $context);
           
// @codeCoverageIgnoreStart
           
default:
               
// I haven't got the foggiest how the logic would come here but added this as a defense.
               
throw new \RuntimeException(
                   
'Unable to resolve type "' . $type . '", there is no known method to resolve it'
               
);
        }
       
// @codeCoverageIgnoreEnd
   
}

   
/**
     * Adds a keyword to the list of Keywords and associates it with a specific Value Object.
     *
     * @param string $keyword
     * @param string $typeClassName
     *
     * @return void
     */
   
public function addKeyword($keyword, $typeClassName)
    {
        if (!
class_exists($typeClassName)) {
            throw new \
InvalidArgumentException(
               
'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class'
               
. ' but we could not find the class ' . $typeClassName
           
);
        }

        if (!
in_array(Type::class, class_implements($typeClassName))) {
            throw new \
InvalidArgumentException(
               
'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"'
           
);
        }

       
$this->keywords[$keyword] = $typeClassName;
    }

   
/**
     * Detects whether the given type represents an array.
     *
     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
     *
     * @return bool
     */
   
private function isTypedArray($type)
    {
        return
substr($type, -2) === self::OPERATOR_ARRAY;
    }

   
/**
     * Detects whether the given type represents a PHPDoc keyword.
     *
     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
     *
     * @return bool
     */
   
private function isKeyword($type)
    {
        return
in_array(strtolower($type), array_keys($this->keywords), true);
    }

   
/**
     * Detects whether the given type represents a relative structural element name.
     *
     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
     *
     * @return bool
     */
   
private function isPartialStructuralElementName($type)
    {
        return (
$type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type);
    }

   
/**
     * Tests whether the given type is a Fully Qualified Structural Element Name.
     *
     * @param string $type
     *
     * @return bool
     */
   
private function isFqsen($type)
    {
        return
strpos($type, self::OPERATOR_NAMESPACE) === 0;
    }

   
/**
     * Tests whether the given type is a compound type (i.e. `string|int`).
     *
     * @param string $type
     *
     * @return bool
     */
   
private function isCompoundType($type)
    {
        return
strpos($type, '|') !== false;
    }

   
/**
     * Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set.
     *
     * @param string $type
     * @param Context $context
     *
     * @return Array_
     */
   
private function resolveTypedArray($type, Context $context)
    {
        return new
Array_($this->resolve(substr($type, 0, -2), $context));
    }

   
/**
     * Resolves the given keyword (such as `string`) into a Type object representing that keyword.
     *
     * @param string $type
     *
     * @return Type
     */
   
private function resolveKeyword($type)
    {
       
$className = $this->keywords[strtolower($type)];

        return new
$className();
    }

   
/**
     * Resolves the given FQSEN string into an FQSEN object.
     *
     * @param string $type
     *
     * @return Object_
     */
   
private function resolveTypedObject($type, Context $context = null)
    {
        return new
Object_($this->fqsenResolver->resolve($type, $context));
    }

   
/**
     * Resolves a compound type (i.e. `string|int`) into the appropriate Type objects or FQSEN.
     *
     * @param string $type
     * @param Context $context
     *
     * @return Compound
     */
   
private function resolveCompoundType($type, Context $context)
    {
       
$types = [];

        foreach (
explode('|', $type) as $part) {
           
$types[] = $this->resolve($part, $context);
        }

        return new
Compound($types);
    }
}