Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

FileGenerator.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 17.82 KiB


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