[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/zendframework/zend-code/src/Generator/ -> FileGenerator.php (source)

   1  <?php
   2  /**
   3   * Zend Framework (http://framework.zend.com/)
   4   *
   5   * @link      http://github.com/zendframework/zf2 for the canonical source repository
   6   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
   7   * @license   http://framework.zend.com/license/new-bsd New BSD License
   8   */
   9  
  10  namespace Zend\Code\Generator;
  11  
  12  use Zend\Code\Reflection\Exception as ReflectionException;
  13  use Zend\Code\Reflection\FileReflection;
  14  
  15  class FileGenerator extends AbstractGenerator
  16  {
  17      /**
  18       * @var string
  19       */
  20      protected $filename = null;
  21  
  22      /**
  23       * @var DocBlockGenerator
  24       */
  25      protected $docBlock = null;
  26  
  27      /**
  28       * @var array
  29       */
  30      protected $requiredFiles = array();
  31  
  32      /**
  33       * @var string
  34       */
  35      protected $namespace = null;
  36  
  37      /**
  38       * @var array
  39       */
  40      protected $uses = array();
  41  
  42      /**
  43       * @var array
  44       */
  45      protected $classes = array();
  46  
  47      /**
  48       * @var string
  49       */
  50      protected $body = null;
  51  
  52      /**
  53       * Passes $options to {@link setOptions()}.
  54       *
  55       * @param  array|\Traversable $options
  56       */
  57      public function __construct($options = null)
  58      {
  59          if (null !== $options) {
  60              $this->setOptions($options);
  61          }
  62      }
  63  
  64      /**
  65       * Use this if you intend on generating code generation objects based on the same file.
  66       * This will keep previous changes to the file in tact during the same PHP process
  67       *
  68       * @param  string $filePath
  69       * @param  bool $includeIfNotAlreadyIncluded
  70       * @throws ReflectionException\InvalidArgumentException If file does not exists
  71       * @throws ReflectionException\RuntimeException If file exists but is not included or required
  72       * @return FileGenerator
  73       */
  74      public static function fromReflectedFileName($filePath, $includeIfNotAlreadyIncluded = true)
  75      {
  76          $fileReflector = new FileReflection($filePath, $includeIfNotAlreadyIncluded);
  77          $codeGenerator = static::fromReflection($fileReflector);
  78  
  79          return $codeGenerator;
  80      }
  81  
  82      /**
  83       * @param  FileReflection $fileReflection
  84       * @return FileGenerator
  85       */
  86      public static function fromReflection(FileReflection $fileReflection)
  87      {
  88          $file = new static();
  89  
  90          $file->setSourceContent($fileReflection->getContents());
  91          $file->setSourceDirty(false);
  92  
  93          $uses = $fileReflection->getUses();
  94  
  95          foreach ($fileReflection->getClasses() as $class) {
  96              $phpClass = ClassGenerator::fromReflection($class);
  97              $phpClass->setContainingFileGenerator($file);
  98  
  99              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  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1