1<?php
2/**
3 * This file is part of phpDocumentor.
4 *
5 * For the full copyright and license information, please view the LICENSE
6 * file that was distributed with this source code.
7 *
8 * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
9 * @license   http://www.opensource.org/licenses/mit-license.php MIT
10 * @link      http://phpdoc.org
11 */
12
13namespace phpDocumentor\Reflection;
14
15use phpDocumentor\Reflection\Types\Context;
16
17class FqsenResolver
18{
19    /** @var string Definition of the NAMESPACE operator in PHP */
20    const OPERATOR_NAMESPACE = '\\';
21
22    public function resolve($fqsen, Context $context = null)
23    {
24        if ($context === null) {
25            $context = new Context('');
26        }
27
28        if ($this->isFqsen($fqsen)) {
29            return new Fqsen($fqsen);
30        }
31
32        return $this->resolvePartialStructuralElementName($fqsen, $context);
33    }
34
35    /**
36     * Tests whether the given type is a Fully Qualified Structural Element Name.
37     *
38     * @param string $type
39     *
40     * @return bool
41     */
42    private function isFqsen($type)
43    {
44        return strpos($type, self::OPERATOR_NAMESPACE) === 0;
45    }
46
47    /**
48     * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
49     * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
50     *
51     * @param string $type
52     * @param Context $context
53     *
54     * @return Fqsen
55     * @throws \InvalidArgumentException when type is not a valid FQSEN.
56     */
57    private function resolvePartialStructuralElementName($type, Context $context)
58    {
59        $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2);
60
61        $namespaceAliases = $context->getNamespaceAliases();
62
63        // if the first segment is not an alias; prepend namespace name and return
64        if (!isset($namespaceAliases[$typeParts[0]])) {
65            $namespace = $context->getNamespace();
66            if ('' !== $namespace) {
67                $namespace .= self::OPERATOR_NAMESPACE;
68            }
69
70            return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type);
71        }
72
73        $typeParts[0] = $namespaceAliases[$typeParts[0]];
74
75        return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts));
76    }
77}
78