1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\Code;
11
12use function array_key_exists;
13use function array_search;
14use function is_array;
15use function is_int;
16use function is_string;
17use function ltrim;
18use function strlen;
19use function strpos;
20use function strrpos;
21use function substr;
22use function substr_replace;
23use function trim;
24
25class NameInformation
26{
27    /**
28     * @var string
29     */
30    protected $namespace;
31
32    /**
33     * @var array
34     */
35    protected $uses = [];
36
37    /**
38     * @param  string $namespace
39     * @param  array $uses
40     */
41    public function __construct($namespace = null, array $uses = [])
42    {
43        if ($namespace) {
44            $this->setNamespace($namespace);
45        }
46        if ($uses) {
47            $this->setUses($uses);
48        }
49    }
50
51    /**
52     * @param  string $namespace
53     * @return NameInformation
54     */
55    public function setNamespace($namespace)
56    {
57        $this->namespace = (string) $namespace;
58        return $this;
59    }
60
61    /**
62     * @return string
63     */
64    public function getNamespace()
65    {
66        return $this->namespace;
67    }
68
69    /**
70     * @return bool
71     */
72    public function hasNamespace()
73    {
74        return $this->namespace !== null;
75    }
76
77    /**
78     * @param  array $uses
79     * @return NameInformation
80     */
81    public function setUses(array $uses)
82    {
83        $this->uses = [];
84        $this->addUses($uses);
85
86        return $this;
87    }
88
89    /**
90     * @param  array $uses
91     * @return NameInformation
92     */
93    public function addUses(array $uses)
94    {
95        foreach ($uses as $use => $as) {
96            if (is_int($use)) {
97                $this->addUse($as);
98            } elseif (is_string($use)) {
99                $this->addUse($use, $as);
100            }
101        }
102
103        return $this;
104    }
105
106    /**
107     * @param  array|string $use
108     * @param  string $as
109     */
110    public function addUse($use, $as = null)
111    {
112        if (is_array($use) && array_key_exists('use', $use) && array_key_exists('as', $use)) {
113            $uses = $use;
114            $use  = $uses['use'];
115            $as   = $uses['as'];
116        }
117
118        $use = trim($use, '\\');
119        if ($as === null) {
120            $as                  = trim($use, '\\');
121            $nsSeparatorPosition = strrpos($as, '\\');
122            if ($nsSeparatorPosition !== false && $nsSeparatorPosition !== 0 && $nsSeparatorPosition != strlen($as)) {
123                $as = substr($as, $nsSeparatorPosition + 1);
124            }
125        }
126
127        $this->uses[$use] = $as;
128    }
129
130    /**
131     * @return array
132     */
133    public function getUses()
134    {
135        return $this->uses;
136    }
137
138    /**
139     * @param  string $name
140     * @return string
141     */
142    public function resolveName($name)
143    {
144        if ($this->namespace && ! $this->uses && strlen($name) > 0 && $name[0] != '\\') {
145            return $this->namespace . '\\' . $name;
146        }
147
148        if (! $this->uses || strlen($name) <= 0 || $name[0] == '\\') {
149            return ltrim($name, '\\');
150        }
151
152        if ($this->namespace || $this->uses) {
153            $firstPart = $name;
154            if (($firstPartEnd = strpos($firstPart, '\\')) !== false) {
155                $firstPart = substr($firstPart, 0, $firstPartEnd);
156            } else {
157                $firstPartEnd = strlen($firstPart);
158            }
159            if (($fqns = array_search($firstPart, $this->uses)) !== false) {
160                return substr_replace($name, $fqns, 0, $firstPartEnd);
161            }
162            if ($this->namespace) {
163                return $this->namespace . '\\' . $name;
164            }
165        }
166
167        return $name;
168    }
169}
170