Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Code / Generator / FileGenerator.php
blob8894ccc1443bb26885e0f4cd89c9678dfac3a0f2
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Code\Generator;
12 use Zend\Code\Reflection\Exception as ReflectionException;
13 use Zend\Code\Reflection\FileReflection;
15 class FileGenerator extends AbstractGenerator
17 /**
18 * @var string
20 protected $filename = null;
22 /**
23 * @var DocBlockGenerator
25 protected $docBlock = null;
27 /**
28 * @var array
30 protected $requiredFiles = array();
32 /**
33 * @var string
35 protected $namespace = null;
37 /**
38 * @var array
40 protected $uses = array();
42 /**
43 * @var array
45 protected $classes = array();
47 /**
48 * @var string
50 protected $body = null;
52 /**
53 * Passes $options to {@link setOptions()}.
55 * @param array|\Traversable $options
57 public function __construct($options = null)
59 if (null !== $options) {
60 $this->setOptions($options);
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
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
74 public static function fromReflectedFileName($filePath, $includeIfNotAlreadyIncluded = true)
76 $fileReflector = new FileReflection($filePath, $includeIfNotAlreadyIncluded);
77 $codeGenerator = static::fromReflection($fileReflector);
79 return $codeGenerator;
82 /**
83 * @param FileReflection $fileReflection
84 * @return FileGenerator
86 public static function fromReflection(FileReflection $fileReflection)
88 $file = new static();
90 $file->setSourceContent($fileReflection->getContents());
91 $file->setSourceDirty(false);
93 $body = $fileReflection->getContents();
95 $uses = $fileReflection->getUses();
97 foreach ($fileReflection->getClasses() as $class) {
98 $phpClass = ClassGenerator::fromReflection($class);
99 $phpClass->setContainingFileGenerator($file);
101 foreach ($uses as $fileUse) {
102 $phpClass->addUse($fileUse['use'], $fileUse['as']);
105 $file->setClass($phpClass);
107 $classStartLine = $class->getStartLine(true);
108 $classEndLine = $class->getEndLine();
110 $bodyLines = explode("\n", $body);
111 $bodyReturn = array();
112 for ($lineNum = 1, $count = count($bodyLines); $lineNum <= $count; $lineNum++) {
113 if ($lineNum == $classStartLine) {
114 $bodyReturn[] = str_replace(
115 '?',
116 $class->getName(),
117 '/* Zend_Code_Generator_Php_File-ClassMarker: {?} */'
120 $lineNum = $classEndLine;
121 } else {
122 $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion
125 $body = implode("\n", $bodyReturn);
126 unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine);
129 $namespace = $fileReflection->getNamespace();
131 if ($namespace != '') {
132 $file->setNamespace($namespace);
135 if ($uses) {
136 $file->setUses($uses);
139 if (($fileReflection->getDocComment() != '')) {
140 $docBlock = $fileReflection->getDocBlock();
141 $file->setDocBlock(DocBlockGenerator::fromReflection($docBlock));
143 $bodyLines = explode("\n", $body);
144 $bodyReturn = array();
145 for ($lineNum = 1, $count = count($bodyLines); $lineNum <= $count; $lineNum++) {
146 if ($lineNum == $docBlock->getStartLine()) {
147 $bodyReturn[] = str_replace(
148 '?',
149 $class->getName(),
150 '/* Zend_Code_Generator_FileGenerator-DocBlockMarker */'
152 $lineNum = $docBlock->getEndLine();
153 } else {
154 $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion
157 $body = implode("\n", $bodyReturn);
158 unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine);
161 $file->setBody($body);
163 return $file;
167 * @param array $values
168 * @return FileGenerator
170 public static function fromArray(array $values)
172 $fileGenerator = new static;
173 foreach ($values as $name => $value) {
174 switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
175 case 'filename':
176 $fileGenerator->setFilename($value);
177 continue;
178 case 'class':
179 $fileGenerator->setClass(($value instanceof ClassGenerator) ? $value : ClassGenerator::fromArray($value));
180 continue;
181 case 'requiredfiles':
182 $fileGenerator->setRequiredFiles($value);
183 continue;
184 default:
185 if (property_exists($fileGenerator, $name)) {
186 $fileGenerator->{$name} = $value;
187 } elseif (method_exists($fileGenerator, 'set' . $name)) {
188 $fileGenerator->{'set' . $name}($value);
193 return $fileGenerator;
197 * @param DocBlockGenerator|string $docBlock
198 * @throws Exception\InvalidArgumentException
199 * @return FileGenerator
201 public function setDocBlock($docBlock)
203 if (is_string($docBlock)) {
204 $docBlock = array('shortDescription' => $docBlock);
207 if (is_array($docBlock)) {
208 $docBlock = new DocBlockGenerator($docBlock);
209 } elseif (!$docBlock instanceof DocBlockGenerator) {
210 throw new Exception\InvalidArgumentException(sprintf(
211 '%s is expecting either a string, array or an instance of %s\DocBlockGenerator',
212 __METHOD__,
213 __NAMESPACE__
217 $this->docBlock = $docBlock;
218 return $this;
222 * @return DocBlockGenerator
224 public function getDocBlock()
226 return $this->docBlock;
230 * @param array $requiredFiles
231 * @return FileGenerator
233 public function setRequiredFiles(array $requiredFiles)
235 $this->requiredFiles = $requiredFiles;
236 return $this;
240 * @return array
242 public function getRequiredFiles()
244 return $this->requiredFiles;
248 * @param array $classes
249 * @return FileGenerator
251 public function setClasses(array $classes)
253 foreach ($classes as $class) {
254 $this->setClass($class);
257 return $this;
261 * @return string
263 public function getNamespace()
265 return $this->namespace;
269 * @param string $namespace
270 * @return FileGenerator
272 public function setNamespace($namespace)
274 $this->namespace = (string) $namespace;
275 return $this;
279 * Returns an array with the first element the use statement, second is the as part.
280 * If $withResolvedAs is set to true, there will be a third element that is the
281 * "resolved" as statement, as the second part is not required in use statements
283 * @param bool $withResolvedAs
284 * @return array
286 public function getUses($withResolvedAs = false)
288 $uses = $this->uses;
289 if ($withResolvedAs) {
290 for ($useIndex = 0, $count = count($uses); $useIndex < $count; $useIndex++) {
291 if ($uses[$useIndex][1] == '') {
292 if (($lastSeparator = strrpos($uses[$useIndex][0], '\\')) !== false) {
293 $uses[$useIndex][2] = substr($uses[$useIndex][0], $lastSeparator + 1);
294 } else {
295 $uses[$useIndex][2] = $uses[$useIndex][0];
297 } else {
298 $uses[$useIndex][2] = $uses[$useIndex][1];
303 return $uses;
307 * @param array $uses
308 * @return FileGenerator
310 public function setUses(array $uses)
312 foreach ($uses as $use) {
313 $use = (array) $use;
314 if (array_key_exists('use', $use) && array_key_exists('as', $use)) {
315 $import = $use['use'];
316 $alias = $use['as'];
317 } elseif (count($use) == 2) {
318 list($import, $alias) = $use;
319 } else {
320 $import = current($use);
321 $alias = null;
323 $this->setUse($import, $alias);
325 return $this;
329 * @param string $use
330 * @param null|string $as
331 * @return FileGenerator
333 public function setUse($use, $as = null)
335 if (!in_array(array($use, $as), $this->uses)) {
336 $this->uses[] = array($use, $as);
338 return $this;
342 * @param string $name
343 * @return ClassGenerator
345 public function getClass($name = null)
347 if ($name == null) {
348 reset($this->classes);
350 return current($this->classes);
353 return $this->classes[(string) $name];
357 * @param array|string|ClassGenerator $class
358 * @throws Exception\InvalidArgumentException
359 * @return FileGenerator
361 public function setClass($class)
363 if (is_array($class)) {
364 $class = ClassGenerator::fromArray($class);
365 } elseif (is_string($class)) {
366 $class = new ClassGenerator($class);
367 } elseif (!$class instanceof ClassGenerator) {
368 throw new Exception\InvalidArgumentException(sprintf(
369 '%s is expecting either a string, array or an instance of %s\ClassGenerator',
370 __METHOD__,
371 __NAMESPACE__
375 // @todo check for dup here
376 $className = $class->getName();
377 $this->classes[$className] = $class;
379 return $this;
383 * @param string $filename
384 * @return FileGenerator
386 public function setFilename($filename)
388 $this->filename = (string) $filename;
389 return $this;
393 * @return string
395 public function getFilename()
397 return $this->filename;
401 * @return ClassGenerator[]
403 public function getClasses()
405 return $this->classes;
409 * @param string $body
410 * @return FileGenerator
412 public function setBody($body)
414 $this->body = (string) $body;
415 return $this;
419 * @return string
421 public function getBody()
423 return $this->body;
427 * @return bool
429 public function isSourceDirty()
431 $docBlock = $this->getDocBlock();
432 if ($docBlock && $docBlock->isSourceDirty()) {
433 return true;
436 foreach ($this->classes as $class) {
437 if ($class->isSourceDirty()) {
438 return true;
442 return parent::isSourceDirty();
446 * @return string
448 public function generate()
450 if ($this->isSourceDirty() === false) {
451 return $this->sourceContent;
454 $output = '';
456 // start with the body (if there), or open tag
457 $body = $this->getBody();
458 if (preg_match('#(?:\s*)<\?php#', $body) == false) {
459 $output = '<?php' . self::LINE_FEED;
462 // if there are markers, put the body into the output
463 if (preg_match('#/\* Zend_Code_Generator_FileGenerator-(.*?)Marker:#', $body)) {
464 $tokens = token_get_all($body);
465 foreach ($tokens as $token) {
466 if (is_array($token) && in_array($token[0], array(T_OPEN_TAG, T_COMMENT, T_DOC_COMMENT, T_WHITESPACE))
468 $output .= $token[1];
471 $body = '';
474 // Add file DocBlock, if any
475 if (null !== ($docBlock = $this->getDocBlock())) {
476 $docBlock->setIndentation('');
478 if (preg_match('#/* Zend_Code_Generator_FileGenerator-DocBlockMarker */#', $output)) {
479 $output = preg_replace('#/* Zend_CodeGenerator_Php_File-DocBlockMarker */#', $docBlock->generate(),
480 $output, 1);
481 } else {
482 $output .= $docBlock->generate() . self::LINE_FEED;
486 // newline
487 $output .= self::LINE_FEED;
489 // namespace, if any
490 $namespace = $this->getNamespace();
491 if ($namespace) {
492 $output .= sprintf('namespace %s;%s', $namespace, str_repeat(self::LINE_FEED, 2));
495 // process required files
496 // @todo marker replacement for required files
497 $requiredFiles = $this->getRequiredFiles();
498 if (!empty($requiredFiles)) {
499 foreach ($requiredFiles as $requiredFile) {
500 $output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED;
503 $output .= self::LINE_FEED;
506 // process import statements
507 $uses = $this->getUses();
508 if (!empty($uses)) {
509 foreach ($uses as $use) {
510 list($import, $alias) = $use;
511 if (null === $alias) {
512 $output .= sprintf('use %s;%s', $import, self::LINE_FEED);
513 } else {
514 $output .= sprintf('use %s as %s;%s', $import, $alias, self::LINE_FEED);
517 $output .= self::LINE_FEED;
520 // process classes
521 $classes = $this->getClasses();
522 if (!empty($classes)) {
523 foreach ($classes as $class) {
524 $regex = str_replace('?', $class->getName(),
525 '/* Zend_Code_Generator_FileGenerator-ClassMarker: {?} */');
526 $regex = preg_quote($regex, '#');
527 if (preg_match('#' . $regex . '#', $output)) {
528 $output = preg_replace('#' . $regex . '#', $class->generate(), $output, 1);
529 } else {
530 if ($namespace) {
531 $class->setNamespaceName(null);
533 $output .= $class->generate() . self::LINE_FEED;
538 if (!empty($body)) {
539 // add an extra space between classes and
540 if (!empty($classes)) {
541 $output .= self::LINE_FEED;
544 $output .= $body;
547 return $output;
551 * @return FileGenerator
552 * @throws Exception\RuntimeException
554 public function write()
556 if ($this->filename == '' || !is_writable(dirname($this->filename))) {
557 throw new Exception\RuntimeException('This code generator object is not writable.');
559 file_put_contents($this->filename, $this->generate());
561 return $this;