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.
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: 09.10.2024, 12:57 - Dateigröße: 15.38 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-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