getFilename(); } if ($fileName == '') { require_once 'Zend/CodeGenerator/Php/Exception.php'; throw new Zend_CodeGenerator_Php_Exception('FileName does not exist.'); } // cannot use realpath since the file might not exist, but we do need to have the index // in the same DIRECTORY_SEPARATOR that realpath would use: $fileName = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $fileName); self::$_fileCodeGenerators[$fileName] = $fileCodeGenerator; } /** * fromReflectedFileName() - use this if you intend on generating code generation objects based on the same file. * This will keep previous changes to the file in tact during the same PHP process * * @param string $filePath * @param bool $usePreviousCodeGeneratorIfItExists * @param bool $includeIfNotAlreadyIncluded * @return Zend_CodeGenerator_Php_File */ public static function fromReflectedFileName($filePath, $usePreviousCodeGeneratorIfItExists = true, $includeIfNotAlreadyIncluded = true) { $realpath = realpath($filePath); if ($realpath === false) { if ( ($realpath = Zend_Reflection_file::findRealpathInIncludePath($filePath)) === false) { require_once 'Zend/CodeGenerator/Php/Exception.php'; throw new Zend_CodeGenerator_Php_Exception('No file for ' . $realpath . ' was found.'); } } if ($usePreviousCodeGeneratorIfItExists && isset(self::$_fileCodeGenerators[$realpath])) { return self::$_fileCodeGenerators[$realpath]; } if ($includeIfNotAlreadyIncluded && !in_array($realpath, get_included_files())) { include $realpath; } $codeGenerator = self::fromReflection(($fileReflector = new Zend_Reflection_File($realpath))); if (!isset(self::$_fileCodeGenerators[$fileReflector->getFileName()])) { self::$_fileCodeGenerators[$fileReflector->getFileName()] = $codeGenerator; } return $codeGenerator; } /** * fromReflection() * * @param Zend_Reflection_File $reflectionFile * @return Zend_CodeGenerator_Php_File */ public static function fromReflection(Zend_Reflection_File $reflectionFile) { $file = new self(); $file->setSourceContent($reflectionFile->getContents()); $file->setSourceDirty(false); $body = $reflectionFile->getContents(); // @todo this whole area needs to be reworked with respect to how body lines are processed foreach ($reflectionFile->getClasses() as $class) { $file->setClass(Zend_CodeGenerator_Php_Class::fromReflection($class)); $classStartLine = $class->getStartLine(true); $classEndLine = $class->getEndLine(); $bodyLines = explode("\n", $body); $bodyReturn = array(); for ($lineNum = 1; $lineNum <= count($bodyLines); $lineNum++) { if ($lineNum == $classStartLine) { $bodyReturn[] = str_replace('?', $class->getName(), self::$_markerClass); //'/* Zend_CodeGenerator_Php_File-ClassMarker: {' . $class->getName() . '} */'; $lineNum = $classEndLine; } else { $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion } } $body = implode("\n", $bodyReturn); unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine); } if (($reflectionFile->getDocComment() != '')) { $docblock = $reflectionFile->getDocblock(); $file->setDocblock(Zend_CodeGenerator_Php_Docblock::fromReflection($docblock)); $bodyLines = explode("\n", $body); $bodyReturn = array(); for ($lineNum = 1; $lineNum <= count($bodyLines); $lineNum++) { if ($lineNum == $docblock->getStartLine()) { $bodyReturn[] = str_replace('?', $class->getName(), self::$_markerDocblock); //'/* Zend_CodeGenerator_Php_File-ClassMarker: {' . $class->getName() . '} */'; $lineNum = $docblock->getEndLine(); } else { $bodyReturn[] = $bodyLines[$lineNum - 1]; // adjust for index -> line conversion } } $body = implode("\n", $bodyReturn); unset($bodyLines, $bodyReturn, $classStartLine, $classEndLine); } $file->setBody($body); return $file; } /** * setDocblock() Set the docblock * * @param Zend_CodeGenerator_Php_Docblock|array|string $docblock * @return Zend_CodeGenerator_Php_File */ public function setDocblock($docblock) { if (is_string($docblock)) { $docblock = array('shortDescription' => $docblock); } if (is_array($docblock)) { $docblock = new Zend_CodeGenerator_Php_Docblock($docblock); } elseif (!$docblock instanceof Zend_CodeGenerator_Php_Docblock) { require_once 'Zend/CodeGenerator/Php/Exception.php'; throw new Zend_CodeGenerator_Php_Exception('setDocblock() is expecting either a string, array or an instance of Zend_CodeGenerator_Php_Docblock'); } $this->_docblock = $docblock; return $this; } /** * Get docblock * * @return Zend_CodeGenerator_Php_Docblock */ public function getDocblock() { return $this->_docblock; } /** * setRequiredFiles * * @param array $requiredFiles * @return Zend_CodeGenerator_Php_File */ public function setRequiredFiles($requiredFiles) { $this->_requiredFiles = $requiredFiles; return $this; } /** * getRequiredFiles() * * @return array */ public function getRequiredFiles() { return $this->_requiredFiles; } /** * setClasses() * * @param array $classes * @return Zend_CodeGenerator_Php_File */ public function setClasses(Array $classes) { foreach ($classes as $class) { $this->setClass($class); } return $this; } /** * getClass() * * @param string $name * @return Zend_CodeGenerator_Php_Class */ public function getClass($name = null) { if ($name == null) { reset($this->_classes); return current($this->_classes); } return $this->_classes[$name]; } /** * setClass() * * @param Zend_CodeGenerator_Php_Class|array $class * @return Zend_CodeGenerator_Php_File */ public function setClass($class) { if (is_array($class)) { $class = new Zend_CodeGenerator_Php_Class($class); $className = $class->getName(); } elseif ($class instanceof Zend_CodeGenerator_Php_Class) { $className = $class->getName(); } else { require_once 'Zend/CodeGenerator/Php/Exception.php'; throw new Zend_CodeGenerator_Php_Exception('Expecting either an array or an instance of Zend_CodeGenerator_Php_Class'); } // @todo check for dup here $this->_classes[$className] = $class; return $this; } /** * setFilename() * * @param string $filename * @return Zend_CodeGenerator_Php_File */ public function setFilename($filename) { $this->_filename = $filename; return $this; } /** * getFilename() * * @return string */ public function getFilename() { return $this->_filename; } /** * getClasses() * * @return array Array of Zend_CodeGenerator_Php_Class */ public function getClasses() { return $this->_classes; } /** * setBody() * * @param string $body * @return Zend_CodeGenerator_Php_File */ public function setBody($body) { $this->_body = $body; return $this; } /** * getBody() * * @return string */ public function getBody() { return $this->_body; } /** * isSourceDirty() * * @return bool */ public function isSourceDirty() { if (($docblock = $this->getDocblock()) && $docblock->isSourceDirty()) { return true; } foreach ($this->_classes as $class) { if ($class->isSourceDirty()) { return true; } } return parent::isSourceDirty(); } /** * generate() * * @return string */ public function generate() { if ($this->isSourceDirty() === false) { return $this->_sourceContent; } $output = ''; // start with the body (if there), or open tag if (preg_match('#(?:\s*)<\?php#', $this->getBody()) == false) { $output = 'getBody(); if (preg_match('#/\* Zend_CodeGenerator_Php_File-(.*?)Marker:#', $body)) { $output .= $body; $body = ''; } // Add file docblock, if any if (null !== ($docblock = $this->getDocblock())) { $docblock->setIndentation(''); $regex = preg_quote(self::$_markerDocblock, '#'); if (preg_match('#'.$regex.'#', $output)) { $output = preg_replace('#'.$regex.'#', $docblock->generate(), $output, 1); } else { $output .= $docblock->generate() . self::LINE_FEED; } } // newline $output .= self::LINE_FEED; // process required files // @todo marker replacement for required files $requiredFiles = $this->getRequiredFiles(); if (!empty($requiredFiles)) { foreach ($requiredFiles as $requiredFile) { $output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED; } $output .= self::LINE_FEED; } // process classes $classes = $this->getClasses(); if (!empty($classes)) { foreach ($classes as $class) { $regex = str_replace('?', $class->getName(), self::$_markerClass); $regex = preg_quote($regex, '#'); if (preg_match('#'.$regex.'#', $output)) { $output = preg_replace('#'.$regex.'#', $class->generate(), $output, 1); } else { $output .= $class->generate() . self::LINE_FEED; } } } if (!empty($body)) { // add an extra space betwee clsses and if (!empty($classes)) { $output .= self::LINE_FEED; } $output .= $body; } return $output; } public function write() { if ($this->_filename == '' || !is_writable(dirname($this->_filename))) { require_once 'Zend/CodeGenerator/Php/Exception.php'; throw new Zend_CodeGenerator_Php_Exception('This code generator object is not writable.'); } file_put_contents($this->_filename, $this->generate()); return $this; } }