/** * Build a Code Generation Php Object from a Class Reflection * * @param ClassReflection $classReflection * @return TraitGenerator */ public static function fromReflection(ClassReflection $classReflection) { // class generator $cg = new static($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } $properties = array(); foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $properties[] = PropertyGenerator::fromReflection($reflectionProperty); } } $cg->addProperties($properties); $methods = array(); foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getNamespaceName() ? $cg->getNamespaceName() . '\\' . $cg->getName() : $cg->getName(); if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } $cg->addMethods($methods); return $cg; }
/** * Build a Code Generation Php Object from a Class Reflection * * @param ClassReflection $classReflection * @return InterfaceGenerator */ public static function fromReflection(ClassReflection $classReflection) { if (!$classReflection->isInterface()) { throw new Exception\InvalidArgumentException(sprintf('Class %s is not a interface', $classReflection->getName())); } // class generator $cg = new static($classReflection->getName()); $methods = []; $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getNamespaceName() ? $cg->getNamespaceName() . '\\' . $cg->getName() : $cg->getName(); if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } foreach ($classReflection->getConstants() as $name => $value) { $cg->addConstant($name, $value); } $cg->addMethods($methods); return $cg; }
public function getClassUseName(ClassReflection $currentClass, ClassReflection $useClass) { $useNames = $this->fileReflectionUseStatementService->getUseNames($currentClass->getDeclaringFile()); $fullUseClassName = $useClass->getName(); $classUseName = null; if (array_key_exists($fullUseClassName, $useNames)) { $classUseName = $useNames[$fullUseClassName] ?: $useClass->getShortName(); } else { if (0 === strpos($fullUseClassName, $currentClass->getNamespaceName())) { $classUseName = substr($fullUseClassName, strlen($currentClass->getNamespaceName()) + 1); } else { $classUseName = '\\' . $fullUseClassName; } } return $classUseName; }
/** * Generate code to cache from class reflection. * This is a total mess, I know. Just wanted to flesh out the logic. * * @todo Refactor into a class, clean up logic, DRY it up, maybe move * some of this into Zend\Code * @param ClassReflection $r * @return string */ protected static function getCacheCode(ClassReflection $r) { $useString = ''; $usesNames = array(); if (count($uses = $r->getDeclaringFile()->getUses())) { foreach ($uses as $use) { $usesNames[$use['use']] = $use['as']; $useString .= "use {$use['use']}"; if ($use['as']) { $useString .= " as {$use['as']}"; } $useString .= ";\n"; } } $declaration = ''; if ($r->isAbstract() && !$r->isInterface()) { $declaration .= 'abstract '; } if ($r->isFinal()) { $declaration .= 'final '; } if ($r->isInterface()) { $declaration .= 'interface '; } if (!$r->isInterface()) { $declaration .= 'class '; } $declaration .= $r->getShortName(); $parentName = false; if (($parent = $r->getParentClass()) && $r->getNamespaceName()) { $parentName = array_key_exists($parent->getName(), $usesNames) ? $usesNames[$parent->getName()] ?: $parent->getShortName() : (0 === strpos($parent->getName(), $r->getNamespaceName()) ? substr($parent->getName(), strlen($r->getNamespaceName()) + 1) : '\\' . $parent->getName()); } else { if ($parent && !$r->getNamespaceName()) { $parentName = '\\' . $parent->getName(); } } if ($parentName) { $declaration .= " extends {$parentName}"; } $interfaces = array_diff($r->getInterfaceNames(), $parent ? $parent->getInterfaceNames() : array()); if (count($interfaces)) { foreach ($interfaces as $interface) { $iReflection = new ClassReflection($interface); $interfaces = array_diff($interfaces, $iReflection->getInterfaceNames()); } $declaration .= $r->isInterface() ? ' extends ' : ' implements '; $declaration .= implode(', ', array_map(function ($interface) use($usesNames, $r) { $iReflection = new ClassReflection($interface); return array_key_exists($iReflection->getName(), $usesNames) ? $usesNames[$iReflection->getName()] ?: $iReflection->getShortName() : (0 === strpos($iReflection->getName(), $r->getNamespaceName()) ? substr($iReflection->getName(), strlen($r->getNamespaceName()) + 1) : '\\' . $iReflection->getName()); }, $interfaces)); } $classContents = $r->getContents(false); $classFileDir = dirname($r->getFileName()); $classContents = trim(str_replace('__DIR__', sprintf("'%s'", $classFileDir), $classContents)); $return = "\nnamespace " . $r->getNamespaceName() . " {\n" . $useString . $declaration . "\n" . $classContents . "\n}\n"; return $return; }
private function getParentName(ClassReflection $classReflection) { $parentName = false; if (($parent = $classReflection->getParentClass()) && $classReflection->getNamespaceName()) { $parentName = $this->classUseNameService->getClassUseName($classReflection, $parent); } else { if ($parent && !$classReflection->getNamespaceName()) { $parentName = '\\' . $parent->getName(); } } return $parentName; }
/** * Build a Code Generation Php Object from a Class Reflection * * @param ClassReflection $classReflection * @return ClassGenerator */ public static function fromReflection(ClassReflection $classReflection) { $cg = new static($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } $cg->setAbstract($classReflection->isAbstract()); // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } /* @var \Zend\Code\Reflection\ClassReflection $parentClass */ $parentClass = $classReflection->getParentClass(); $interfaces = $classReflection->getInterfaces(); if ($parentClass) { $cg->setExtendedClass($parentClass->getName()); $interfaces = array_diff($interfaces, $parentClass->getInterfaces()); } $interfaceNames = array(); foreach ($interfaces as $interface) { /* @var \Zend\Code\Reflection\ClassReflection $interface */ $interfaceNames[] = $interface->getName(); } $cg->setImplementedInterfaces($interfaceNames); $properties = array(); foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $properties[] = PropertyGenerator::fromReflection($reflectionProperty); } } $cg->addProperties($properties); $constants = array(); foreach ($classReflection->getConstants() as $name => $value) { $constants[] = array('name' => $name, 'value' => $value); } $cg->addConstants($constants); $methods = array(); foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getNamespaceName() ? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName(); if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } $cg->addMethods($methods); return $cg; }
/** * Get forms for a module * * @param $moduleObject * * @return array */ protected function loadPluginsForModule($moduleObject) { // initialize plugins $plugins = array(); // check for configuration if (!method_exists($moduleObject, 'getConfig')) { return $plugins; } // get module configuration $moduleConfig = $moduleObject->getConfig(); // check for no configured plugins if (!isset($moduleConfig['controller_plugins'])) { return $plugins; } // loop through plugins foreach ($moduleConfig['controller_plugins'] as $type => $loadedPlugins) { // skip if not invokable nor factory if (!in_array($type, array('invokables', 'factories'))) { continue; } // initialize plugin type $plugins[$type] = array(); // loop through plugin list foreach ($loadedPlugins as $pluginKey => $pluginClass) { // check if plugin class or factory does not exist if (!class_exists($pluginClass)) { continue; } // check for factory if (in_array('Zend\\ServiceManager\\FactoryInterface', class_implements($pluginClass))) { // start class reflection $classReflection = new ClassReflection($pluginClass); // get create method and doc block $method = $classReflection->getMethod('createService'); $docBlock = $method->getDocBlock(); // check doc block for return tag and use class if ($docBlock) { // loop through all doc blocks foreach ($docBlock->getTags() as $tag) { /** @var $tag ReturnTag */ if ($tag->getName() != 'return') { continue; } $pluginClass = $classReflection->getNamespaceName() . '\\' . $tag->getTypes()[0]; } } else { // try to read plugin instantiation from method preg_match_all('^\\$plugin\\s*=\\s*new\\s*([a-zA-z0-9]+)\\(\\)\\;^', $method->getContents(), $matches); $pluginClass = $classReflection->getNamespaceName() . '\\' . $matches[1][0]; } } // check for class existence if (!class_exists($pluginClass)) { break; } // add plugin class for type $plugins[$type][$pluginKey] = $pluginClass; } } // loop through plugins foreach ($plugins as $type => $pluginList) { // check if any plugin exists for type if (empty($pluginList)) { unset($plugins[$type]); // otherwise sort plugins } else { ksort($plugins[$type]); } } return $plugins; }
/** * Build the interface part * * @param array $uses * @param Reflection\ClassReflection $class * @return string */ protected function buildInterface(&$uses, Reflection\ClassReflection $class) { $code = ''; $interfaces = $class->getInterfaces(); $parentClass = $class->getParentClass(); // Normalize interfaces array to string foreach ($interfaces as &$interface) { $interfaceReflections[$interface->getName()] = $interface; $interface = $interface->getName(); } // Remove interface from parent class if ($parentClass !== false) { $parentInterfaces = $parentClass->getInterfaces(); foreach ($parentInterfaces as &$parentInterface) { $interfaceReflections[$parentInterface->getName()] = $parentInterface; $parentInterface = $parentInterface->getName(); } $interfaces = array_diff($interfaces, $parentInterfaces); } // No interfaces found? Return '' if (count($interfaces) === 0) { return $code; } // Create extend/implement keyword $code .= $class->isInterface() ? ' extends ' : ' implements '; $classNamespace = $class->getNamespaceName(); // Retrieve interfaces from the interfaces foreach ($interfaces as &$interface) { $parentInterfaces = $interfaceReflections[$interface]->getInterfaces(); foreach ($parentInterfaces as &$parentInterface) { $interfaceReflections[$parentInterface->getName()] = $parentInterface; $parentInterface = $parentInterface->getName(); } // Remove already implemented interfaces $interfaces = array_diff($interfaces, $parentInterfaces); } // define interface names foreach ($interfaces as &$interface) { // Make sure the class has already been cached $this->processClassIntoCacheFile($interfaceReflections[$interface]); // Check if the interface has been defined in the uses if (array_key_exists($interface, $uses)) { // Set the use alias or the shortname when no alias has been set $interface = empty($uses[$interface]) ? $interfaceReflections[$interface]->getShortName() : $uses[$interface]; } else { // Check if we're implementing from a subnamespace $inNamespace = strpos($interface, $classNamespace) === 0; if ($inNamespace) { $interface = substr($interface, strlen($classNamespace) + 1); } else { $interface = "\\{$interface}"; } } } $code .= implode(', ', $interfaces); return $code; }
/** * fromReflection() - build a Code Generation Php Object from a Class Reflection * * @param ReflectionClass $classReflection * @return ClassGenerator */ public static function fromReflection(ClassReflection $classReflection) { // class generator $cg = new static($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocblock(DocblockGenerator::fromReflection($classReflection->getDocblock())); } $cg->setAbstract($classReflection->isAbstract()); // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } /* @var $parentClass \Zend\Code\Reflection\ReflectionClass */ if ($parentClass = $classReflection->getParentClass()) { $cg->setExtendedClass($parentClass->getName()); $interfaces = array_diff($classReflection->getInterfaces(), $parentClass->getInterfaces()); } else { $interfaces = $classReflection->getInterfaces(); } $interfaceNames = array(); foreach ($interfaces as $interface) { /* @var $interface \Zend\Code\Reflection\ReflectionClass */ $interfaceNames[] = $interface->getName(); } $cg->setImplementedInterfaces($interfaceNames); $properties = array(); foreach ($classReflection->getProperties() as $reflectionProperty) { /* @var $reflectionProperty \PropertyReflection\Code\Reflection\ReflectionProperty */ if ($reflectionProperty->getDeclaringClass()->getName() == $cg->getName()) { $properties[] = PropertyGenerator::fromReflection($reflectionProperty); } } $cg->setProperties($properties); $methods = array(); foreach ($classReflection->getMethods() as $reflectionMethod) { /* @var $reflectionMethod \MethodReflection\Code\Reflection\ReflectionMethod */ if ($reflectionMethod->getDeclaringClass()->getName() == $cg->getName()) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } $cg->setMethods($methods); return $cg; }
/** * @param ClassReflection $classReflection * @param $parent * @param $usesNames * @return string */ protected function extractInterfaceStatement(ClassReflection $classReflection, $parent, $usesNames) { $parentInterfaceNames = $parent instanceof ClassReflection ? $parent->getInterfaceNames() : array(); $interfaceNames = array_diff($classReflection->getInterfaceNames(), $parentInterfaceNames); $interfaceStatement = ''; if (!count($interfaceNames)) { return $interfaceStatement; } foreach ($interfaceNames as $interface) { $iReflection = new ClassReflection($interface); $interfaceNames = array_diff($interfaceNames, $iReflection->getInterfaceNames()); } $interfaceStatement .= $classReflection->isInterface() ? ' extends ' : ' implements '; $interfaceStatement .= implode(', ', array_map(function ($interface) use($usesNames, $classReflection) { $iReflection = new ClassReflection($interface); return array_key_exists($iReflection->getName(), $usesNames) ? $usesNames[$iReflection->getName()] ?: $iReflection->getShortName() : (0 === strpos($iReflection->getName(), $classReflection->getNamespaceName()) ? substr($iReflection->getName(), strlen($classReflection->getNamespaceName()) + 1) : '\\' . $iReflection->getName()); }, $interfaceNames)); return $interfaceStatement; }
/** * Create a new subclass and factory to override a factory-generated * service. * * @param mixed $factory Factory configuration for class to extend * @param string $module Module in which to create the new factory * * @return string * @throws \Exception */ protected function cloneFactory($factory, $module) { // Make sure we can figure out how to handle the factory; it should // either be a [controller, method] array or a "controller::method" // string; anything else will cause a problem. $parts = is_string($factory) ? explode('::', $factory) : $factory; if (!is_array($parts) || count($parts) != 2 || !class_exists($parts[0]) || !method_exists($parts[0], $parts[1])) { throw new \Exception('Unexpected factory configuration format.'); } list($factoryClass, $factoryMethod) = $parts; $newFactoryClass = $this->generateLocalClassName($factoryClass, $module); if (!class_exists($newFactoryClass)) { $this->createClassInModule($newFactoryClass, $module); $skipBackup = true; } else { $skipBackup = false; } if (method_exists($newFactoryClass, $factoryMethod)) { throw new \Exception("{$newFactoryClass}::{$factoryMethod} already exists."); } $oldReflection = new ClassReflection($factoryClass); $newReflection = new ClassReflection($newFactoryClass); $generator = ClassGenerator::fromReflection($newReflection); $method = MethodGenerator::fromReflection($oldReflection->getMethod($factoryMethod)); $this->createServiceClassAndUpdateFactory($method, $oldReflection->getNamespaceName(), $module); $generator->addMethodFromGenerator($method); $this->writeClass($generator, $module, true, $skipBackup); return $newFactoryClass . '::' . $factoryMethod; }
protected function findClassInCurrentNamespace(ClassReflection $reflection, $class) { $fqn = sprintf('%s\\%s', $reflection->getNamespaceName(), $class); if (class_exists($fqn) || interface_exists($fqn)) { return $fqn; } }
/** * Copied from ClassGenerator::fromReflection and tweaked slightly * @param ClassReflection $classReflection * * @return ClassGenerator */ public function getGeneratorFromReflection(ClassReflection $classReflection) { // class generator $cg = new ClassGenerator($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $docblock = DocBlockGenerator::fromReflection($classReflection->getDocBlock()); $docblock->setIndentation(Generator::$indentation); $cg->setDocBlock($docblock); } $cg->setAbstract($classReflection->isAbstract()); // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } /* @var \Zend\Code\Reflection\ClassReflection $parentClass */ $parentClass = $classReflection->getParentClass(); if ($parentClass) { $cg->setExtendedClass('\\' . ltrim($parentClass->getName(), '\\')); $interfaces = array_diff($classReflection->getInterfaces(), $parentClass->getInterfaces()); } else { $interfaces = $classReflection->getInterfaces(); } $interfaceNames = array(); foreach ($interfaces as $interface) { /* @var \Zend\Code\Reflection\ClassReflection $interface */ $interfaceNames[] = $interface->getName(); } $cg->setImplementedInterfaces($interfaceNames); $properties = array(); foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $property = PropertyGenerator::fromReflection($reflectionProperty); $property->setIndentation(Generator::$indentation); $properties[] = $property; } } $cg->addProperties($properties); $methods = array(); foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getNamespaceName() ? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName(); if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $method = MethodGenerator::fromReflection($reflectionMethod); $method->setBody(preg_replace("/^\\s+/m", '', $method->getBody())); $method->setIndentation(Generator::$indentation); $methods[] = $method; } } $cg->addMethods($methods); return $cg; }