1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\PhpGenerator;
9:
10: use Nette\InvalidStateException;
11: use Nette\Object;
12: use Nette\Utils\Strings;
13:
14:
15: 16: 17: 18: 19: 20: 21: 22:
23: class PhpNamespace extends Object
24: {
25:
26: private $name;
27:
28:
29: private $bracketedSyntax = FALSE;
30:
31:
32: private $uses = array();
33:
34:
35: private $classes = array();
36:
37:
38: public function __construct($name = NULL)
39: {
40: $this->setName($name);
41: }
42:
43:
44: 45: 46:
47: public function getName()
48: {
49: return $this->name;
50: }
51:
52:
53: 54: 55: 56:
57: public function setName($name)
58: {
59: $this->name = (string) $name;
60: return $this;
61: }
62:
63:
64: 65: 66:
67: public function getBracketedSyntax()
68: {
69: return $this->bracketedSyntax;
70: }
71:
72:
73: 74: 75: 76: 77:
78: public function setBracketedSyntax($state = TRUE)
79: {
80: $this->bracketedSyntax = (bool) $state;
81: return $this;
82: }
83:
84:
85: 86: 87:
88: public function getUses()
89: {
90: return $this->uses;
91: }
92:
93:
94: 95: 96: 97: 98: 99: 100:
101: public function addUse($name, $alias = NULL, &$aliasOut = NULL)
102: {
103: $name = ltrim($name, '\\');
104: if ($alias === NULL && $this->name === Helpers::extractNamespace($name)) {
105: $alias = Helpers::extractShortName($name);
106: }
107: if ($alias === NULL) {
108: $path = explode('\\', $name);
109: $counter = NULL;
110: do {
111: if (empty($path)) {
112: $counter++;
113: } else {
114: $alias = array_pop($path) . $alias;
115: }
116: } while (isset($this->uses[$alias . $counter]) && $this->uses[$alias . $counter] !== $name);
117: $alias .= $counter;
118:
119: } elseif (isset($this->uses[$alias]) && $this->uses[$alias] !== $name) {
120: throw new InvalidStateException(
121: "Alias '$alias' used already for '{$this->uses[$alias]}', cannot use for '{$name}'."
122: );
123: }
124:
125: $aliasOut = $alias;
126: $this->uses[$alias] = $name;
127: return $this;
128: }
129:
130:
131: 132: 133: 134:
135: public function unresolveName($name)
136: {
137: $name = ltrim($name, '\\');
138: $res = NULL;
139: $lower = strtolower($name);
140: foreach ($this->uses as $alias => $for) {
141: if (Strings::startsWith($lower . '\\', strtolower($for) . '\\')) {
142: $short = $alias . substr($name, strlen($for));
143: if (!isset($res) || strlen($res) > strlen($short)) {
144: $res = $short;
145: }
146: }
147: }
148:
149: if (!$res && Strings::startsWith($lower, strtolower($this->name) . '\\')) {
150: return substr($name, strlen($this->name) + 1);
151: } else {
152: return $res ?: '\\' . $name;
153: }
154: }
155:
156:
157: 158: 159:
160: public function getClasses()
161: {
162: return $this->classes;
163: }
164:
165:
166: 167: 168: 169:
170: public function addClass($name)
171: {
172: if (!isset($this->classes[$name])) {
173: $this->addUse($this->name . '\\' . $name);
174: $this->classes[$name] = new ClassType($name, $this);
175: }
176: return $this->classes[$name];
177: }
178:
179:
180: 181: 182: 183:
184: public function addInterface($name)
185: {
186: return $this->addClass($name)->setType(ClassType::TYPE_INTERFACE);
187: }
188:
189:
190: 191: 192: 193:
194: public function addTrait($name)
195: {
196: return $this->addClass($name)->setType(ClassType::TYPE_TRAIT);
197: }
198:
199:
200: 201: 202:
203: public function __toString()
204: {
205: $uses = array();
206: asort($this->uses);
207: foreach ($this->uses as $alias => $name) {
208: $useNamespace = Helpers::extractNamespace($name);
209:
210: if ($this->name !== $useNamespace) {
211: if ($alias === $name || substr($name, -(strlen($alias) + 1)) === '\\' . $alias) {
212: $uses[] = "use {$name};";
213: } else {
214: $uses[] = "use {$name} as {$alias};";
215: }
216: }
217: }
218:
219: $body = ($uses ? implode("\n", $uses) . "\n\n" : '')
220: . implode("\n", $this->classes);
221:
222: if ($this->bracketedSyntax) {
223: return 'namespace' . ($this->name ? ' ' . $this->name : '') . " {\n\n"
224: . Strings::indent($body)
225: . "\n}\n";
226:
227: } else {
228: return ($this->name ? "namespace {$this->name};\n\n" : '')
229: . $body;
230: }
231: }
232:
233: }
234: