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