Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
FileGenerator.php
001 <?php
002 /**
003 * Zend Framework (http://framework.zend.com/)
004 *
005 * @link http://github.com/zendframework/zf2 for the canonical source repository
006 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
007 * @license http://framework.zend.com/license/new-bsd New BSD License
008 */
009
010 namespace Zend\Code\Generator;
011
012 use Zend\Code\Reflection\Exception as ReflectionException;
013 use Zend\Code\Reflection\FileReflection;
014
015 class FileGenerator extends AbstractGenerator
016 {
017 /**
018 * @var string
019 */
020 protected $filename = null;
021
022 /**
023 * @var DocBlockGenerator
024 */
025 protected $docBlock = null;
026
027 /**
028 * @var array
029 */
030 protected $requiredFiles = array();
031
032 /**
033 * @var string
034 */
035 protected $namespace = null;
036
037 /**
038 * @var array
039 */
040 protected $uses = array();
041
042 /**
043 * @var array
044 */
045 protected $classes = array();
046
047 /**
048 * @var string
049 */
050 protected $body = null;
051
052 /**
053 * Passes $options to {@link setOptions()}.
054 *
055 * @param array|\Traversable $options
056 */
057 public function __construct($options = null)
058 {
059 if (null !== $options) {
060 $this->setOptions($options);
061 }
062 }
063
064 /**
065 * Use this if you intend on generating code generation objects based on the same file.
066 * This will keep previous changes to the file in tact during the same PHP process
067 *
068 * @param string $filePath
069 * @param bool $includeIfNotAlreadyIncluded
070 * @throws ReflectionException\InvalidArgumentException If file does not exists
071 * @throws ReflectionException\RuntimeException If file exists but is not included or required
072 * @return FileGenerator
073 */
074 public static function fromReflectedFileName($filePath, $includeIfNotAlreadyIncluded = true)
075 {
076 $fileReflector = new FileReflection($filePath, $includeIfNotAlreadyIncluded);
077 $codeGenerator = static::fromReflection($fileReflector);
078
079 return $codeGenerator;
080 }
081
082 /**
083 * @param FileReflection $fileReflection
084 * @return FileGenerator
085 */
086 public static function fromReflection(FileReflection $fileReflection)
087 {
088 $file = new static();
089
090 $file->setSourceContent($fileReflection->getContents());
091 $file->setSourceDirty(false);
092
093 $uses = $fileReflection->getUses();
094
095 foreach ($fileReflection->getClasses() as $class) {
096 $phpClass = ClassGenerator::fromReflection($class);
097 $phpClass->setContainingFileGenerator($file);
098
099 foreach ($uses as $fileUse) {
100 $phpClass->addUse($fileUse['use'], $fileUse['as']);
101 }
102
103 $file->setClass($phpClass);
104 }
105
106 $namespace = $fileReflection->getNamespace();
107
108 if ($namespace != '') {
109 $file->setNamespace($namespace);
110 }
111
112 if ($uses) {
113 $file->setUses($uses);
114 }
115
116 if (($fileReflection->getDocComment() != '')) {
117 $docBlock = $fileReflection->getDocBlock();
118 $file->setDocBlock(DocBlockGenerator::fromReflection($docBlock));
119 }
120
121 return $file;
122 }
123
124 /**
125 * @param array $values
126 * @return FileGenerator
127 */
128 public static function fromArray(array $values)
129 {
130 $fileGenerator = new static;
131 foreach ($values as $name => $value) {
132 switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
133 case 'filename':
134 $fileGenerator->setFilename($value);
135 continue;
136 case 'class':
137 $fileGenerator->setClass(($value instanceof ClassGenerator) ? $value : ClassGenerator::fromArray($value));
138 continue;
139 case 'requiredfiles':
140 $fileGenerator->setRequiredFiles($value);
141 continue;
142 default:
143 if (property_exists($fileGenerator, $name)) {
144 $fileGenerator->{$name} = $value;
145 } elseif (method_exists($fileGenerator, 'set' . $name)) {
146 $fileGenerator->{'set' . $name}($value);
147 }
148 }
149 }
150
151 return $fileGenerator;
152 }
153
154 /**
155 * @param DocBlockGenerator|array|string $docBlock
156 * @throws Exception\InvalidArgumentException
157 * @return FileGenerator
158 */
159 public function setDocBlock($docBlock)
160 {
161 if (is_string($docBlock)) {
162 $docBlock = array('shortDescription' => $docBlock);
163 }
164
165 if (is_array($docBlock)) {
166 $docBlock = new DocBlockGenerator($docBlock);
167 } elseif (!$docBlock instanceof DocBlockGenerator) {
168 throw new Exception\InvalidArgumentException(sprintf(
169 '%s is expecting either a string, array or an instance of %s\DocBlockGenerator',
170 __METHOD__,
171 __NAMESPACE__
172 ));
173 }
174
175 $this->docBlock = $docBlock;
176 return $this;
177 }
178
179 /**
180 * @return DocBlockGenerator
181 */
182 public function getDocBlock()
183 {
184 return $this->docBlock;
185 }
186
187 /**
188 * @param array $requiredFiles
189 * @return FileGenerator
190 */
191 public function setRequiredFiles(array $requiredFiles)
192 {
193 $this->requiredFiles = $requiredFiles;
194 return $this;
195 }
196
197 /**
198 * @return array
199 */
200 public function getRequiredFiles()
201 {
202 return $this->requiredFiles;
203 }
204
205 /**
206 * @return string
207 */
208 public function getNamespace()
209 {
210 return $this->namespace;
211 }
212
213 /**
214 * @param string $namespace
215 * @return FileGenerator
216 */
217 public function setNamespace($namespace)
218 {
219 $this->namespace = (string) $namespace;
220 return $this;
221 }
222
223 /**
224 * Returns an array with the first element the use statement, second is the as part.
225 * If $withResolvedAs is set to true, there will be a third element that is the
226 * "resolved" as statement, as the second part is not required in use statements
227 *
228 * @param bool $withResolvedAs
229 * @return array
230 */
231 public function getUses($withResolvedAs = false)
232 {
233 $uses = $this->uses;
234 if ($withResolvedAs) {
235 for ($useIndex = 0, $count = count($uses); $useIndex < $count; $useIndex++) {
236 if ($uses[$useIndex][1] == '') {
237 if (($lastSeparator = strrpos($uses[$useIndex][0], '\\')) !== false) {
238 $uses[$useIndex][2] = substr($uses[$useIndex][0], $lastSeparator + 1);
239 } else {
240 $uses[$useIndex][2] = $uses[$useIndex][0];
241 }
242 } else {
243 $uses[$useIndex][2] = $uses[$useIndex][1];
244 }
245 }
246 }
247
248 return $uses;
249 }
250
251 /**
252 * @param array $uses
253 * @return FileGenerator
254 */
255 public function setUses(array $uses)
256 {
257 foreach ($uses as $use) {
258 $use = (array) $use;
259 if (array_key_exists('use', $use) && array_key_exists('as', $use)) {
260 $import = $use['use'];
261 $alias = $use['as'];
262 } elseif (count($use) == 2) {
263 list($import, $alias) = $use;
264 } else {
265 $import = current($use);
266 $alias = null;
267 }
268 $this->setUse($import, $alias);
269 }
270 return $this;
271 }
272
273 /**
274 * @param string $use
275 * @param null|string $as
276 * @return FileGenerator
277 */
278 public function setUse($use, $as = null)
279 {
280 if (!in_array(array($use, $as), $this->uses)) {
281 $this->uses[] = array($use, $as);
282 }
283 return $this;
284 }
285
286 /**
287 * @param array $classes
288 * @return FileGenerator
289 */
290 public function setClasses(array $classes)
291 {
292 foreach ($classes as $class) {
293 $this->setClass($class);
294 }
295
296 return $this;
297 }
298
299 /**
300 * @param string $name
301 * @return ClassGenerator
302 */
303 public function getClass($name = null)
304 {
305 if ($name === null) {
306 reset($this->classes);
307
308 return current($this->classes);
309 }
310
311 return $this->classes[(string) $name];
312 }
313
314 /**
315 * @param array|string|ClassGenerator $class
316 * @throws Exception\InvalidArgumentException
317 * @return FileGenerator
318 */
319 public function setClass($class)
320 {
321 if (is_array($class)) {
322 $class = ClassGenerator::fromArray($class);
323 } elseif (is_string($class)) {
324 $class = new ClassGenerator($class);
325 } elseif (!$class instanceof ClassGenerator) {
326 throw new Exception\InvalidArgumentException(sprintf(
327 '%s is expecting either a string, array or an instance of %s\ClassGenerator',
328 __METHOD__,
329 __NAMESPACE__
330 ));
331 }
332
333 // @todo check for dup here
334 $className = $class->getName();
335 $this->classes[$className] = $class;
336
337 return $this;
338 }
339
340 /**
341 * @param string $filename
342 * @return FileGenerator
343 */
344 public function setFilename($filename)
345 {
346 $this->filename = (string) $filename;
347 return $this;
348 }
349
350 /**
351 * @return string
352 */
353 public function getFilename()
354 {
355 return $this->filename;
356 }
357
358 /**
359 * @return ClassGenerator[]
360 */
361 public function getClasses()
362 {
363 return $this->classes;
364 }
365
366 /**
367 * @param string $body
368 * @return FileGenerator
369 */
370 public function setBody($body)
371 {
372 $this->body = (string) $body;
373 return $this;
374 }
375
376 /**
377 * @return string
378 */
379 public function getBody()
380 {
381 return $this->body;
382 }
383
384 /**
385 * @return bool
386 */
387 public function isSourceDirty()
388 {
389 $docBlock = $this->getDocBlock();
390 if ($docBlock && $docBlock->isSourceDirty()) {
391 return true;
392 }
393
394 foreach ($this->classes as $class) {
395 if ($class->isSourceDirty()) {
396 return true;
397 }
398 }
399
400 return parent::isSourceDirty();
401 }
402
403 /**
404 * @return string
405 */
406 public function generate()
407 {
408 if ($this->isSourceDirty() === false) {
409 return $this->sourceContent;
410 }
411
412 $output = '';
413
414 // @note body gets populated when FileGenerator created
415 // from a file. @see fromReflection and may also be set
416 // via FileGenerator::setBody
417 $body = $this->getBody();
418
419 // start with the body (if there), or open tag
420 if (preg_match('#(?:\s*)<\?php#', $body) == false) {
421 $output = '<?php' . self::LINE_FEED;
422 }
423
424 // if there are markers, put the body into the output
425 if (preg_match('#/\* Zend_Code_Generator_Php_File-(.*?)Marker:#m', $body)) {
426 $tokens = token_get_all($body);
427 foreach ($tokens as $token) {
428 if (is_array($token) && in_array($token[0], array(T_OPEN_TAG, T_COMMENT, T_DOC_COMMENT, T_WHITESPACE))
429 ) {
430 $output .= $token[1];
431 }
432 }
433 $body = '';
434 }
435
436 // Add file DocBlock, if any
437 if (null !== ($docBlock = $this->getDocBlock())) {
438 $docBlock->setIndentation('');
439
440 if (preg_match('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $output)) {
441 $output = preg_replace('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $docBlock->generate(), $output, 1);
442 } else {
443 $output .= $docBlock->generate() . self::LINE_FEED;
444 }
445 }
446
447 // newline
448 $output .= self::LINE_FEED;
449
450 // namespace, if any
451 $namespace = $this->getNamespace();
452 if ($namespace) {
453 $namespace = sprintf('namespace %s;%s', $namespace, str_repeat(self::LINE_FEED, 2));
454 if (preg_match('#/\* Zend_Code_Generator_FileGenerator-NamespaceMarker \*/#m', $output)) {
455 $output = preg_replace(
456 '#/\* Zend_Code_Generator_FileGenerator-NamespaceMarker \*/#m',
457 $namespace,
458 $output,
459 1
460 );
461 } else {
462 $output .= $namespace;
463 }
464 }
465
466 // process required files
467 // @todo marker replacement for required files
468 $requiredFiles = $this->getRequiredFiles();
469 if (!empty($requiredFiles)) {
470 foreach ($requiredFiles as $requiredFile) {
471 $output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED;
472 }
473
474 $output .= self::LINE_FEED;
475 }
476
477 $classes = $this->getClasses();
478 $classUses = array();
479 //build uses array
480 foreach ($classes as $class) {
481 //check for duplicate use statements
482 $uses = $class->getUses();
483 if (!empty($uses) && is_array($uses)) {
484 $classUses = array_merge($classUses, $uses);
485 }
486 }
487
488 // process import statements
489 $uses = $this->getUses();
490 if (!empty($uses)) {
491 $useOutput = '';
492
493 foreach ($uses as $use) {
494 list($import, $alias) = $use;
495 if (null === $alias) {
496 $tempOutput = sprintf('%s', $import);
497 } else {
498 $tempOutput = sprintf('%s as %s', $import, $alias);
499 }
500
501 //don't duplicate use statements
502 if (!in_array($tempOutput, $classUses)) {
503 $useOutput .= "use ". $tempOutput .";";
504 $useOutput .= self::LINE_FEED;
505 }
506 }
507 $useOutput .= self::LINE_FEED;
508
509 if (preg_match('#/\* Zend_Code_Generator_FileGenerator-UseMarker \*/#m', $output)) {
510 $output = preg_replace(
511 '#/\* Zend_Code_Generator_FileGenerator-UseMarker \*/#m',
512 $useOutput,
513 $output,
514 1
515 );
516 } else {
517 $output .= $useOutput;
518 }
519 }
520
521 // process classes
522 if (!empty($classes)) {
523 foreach ($classes as $class) {
524 $regex = str_replace('&', $class->getName(), '/\* Zend_Code_Generator_Php_File-ClassMarker: \{[A-Za-z0-9\\\]+?&\} \*/');
525 if (preg_match('#' . $regex . '#m', $output)) {
526 $output = preg_replace('#' . $regex . '#', $class->generate(), $output, 1);
527 } else {
528 if ($namespace) {
529 $class->setNamespaceName(null);
530 }
531 $output .= $class->generate() . self::LINE_FEED;
532 }
533 }
534 }
535
536 if (!empty($body)) {
537 // add an extra space between classes and
538 if (!empty($classes)) {
539 $output .= self::LINE_FEED;
540 }
541
542 $output .= $body;
543 }
544
545 return $output;
546 }
547
548 /**
549 * @return FileGenerator
550 * @throws Exception\RuntimeException
551 */
552 public function write()
553 {
554 if ($this->filename == '' || !is_writable(dirname($this->filename))) {
555 throw new Exception\RuntimeException('This code generator object is not writable.');
556 }
557 file_put_contents($this->filename, $this->generate());
558
559 return $this;
560 }
561 }
562