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