Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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: 01.05.2026, 11:27 - 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