/** * Construct, configure, and return a PHP class file code generation object * * Creates a Zend\Code\Generator\FileGenerator object that has * created the specified class and service locator methods. * * @param null|string $filename * @throws \Zend\Di\Exception\RuntimeException * @return FileGenerator */ public function getCodeGenerator($filename = null) { $injector = $this->injector; $im = $injector->instanceManager(); $indent = ' '; $aliases = $this->reduceAliases($im->getAliases()); $caseStatements = array(); $getters = array(); $definitions = $injector->definitions(); $fetched = array_unique(array_merge($definitions->getClasses(), $im->getAliases())); foreach ($fetched as $name) { $getter = $this->normalizeAlias($name); $meta = $injector->get($name); $params = $meta->getParams(); // Build parameter list for instantiation foreach ($params as $key => $param) { if (null === $param || is_scalar($param) || is_array($param)) { $string = var_export($param, 1); if (strstr($string, '::__set_state(')) { throw new Exception\RuntimeException('Arguments in definitions may not contain objects'); } $params[$key] = $string; } elseif ($param instanceof GeneratorInstance) { /* @var $param GeneratorInstance */ $params[$key] = sprintf('$this->%s()', $this->normalizeAlias($param->getName())); } else { $message = sprintf('Unable to use object arguments when building containers. Encountered with "%s", parameter of type "%s"', $name, get_class($param)); throw new Exception\RuntimeException($message); } } // Strip null arguments from the end of the params list $reverseParams = array_reverse($params, true); foreach ($reverseParams as $key => $param) { if ('NULL' === $param) { unset($params[$key]); continue; } break; } // Create instantiation code $constructor = $meta->getConstructor(); if ('__construct' != $constructor) { // Constructor callback $callback = var_export($constructor, 1); if (strstr($callback, '::__set_state(')) { throw new Exception\RuntimeException('Unable to build containers that use callbacks requiring object instances'); } if (count($params)) { $creation = sprintf('$object = call_user_func(%s, %s);', $callback, implode(', ', $params)); } else { $creation = sprintf('$object = call_user_func(%s);', $callback); } } else { // Normal instantiation $className = '\\' . ltrim($name, '\\'); $creation = sprintf('$object = new %s(%s);', $className, implode(', ', $params)); } // Create method call code $methods = ''; foreach ($meta->getMethods() as $methodData) { if (!isset($methodData['name']) && !isset($methodData['method'])) { continue; } $methodName = isset($methodData['name']) ? $methodData['name'] : $methodData['method']; $methodParams = $methodData['params']; // Create method parameter representation foreach ($methodParams as $key => $param) { if (null === $param || is_scalar($param) || is_array($param)) { $string = var_export($param, 1); if (strstr($string, '::__set_state(')) { throw new Exception\RuntimeException('Arguments in definitions may not contain objects'); } $methodParams[$key] = $string; } elseif ($param instanceof GeneratorInstance) { $methodParams[$key] = sprintf('$this->%s()', $this->normalizeAlias($param->getName())); } else { $message = sprintf('Unable to use object arguments when generating method calls. Encountered with class "%s", method "%s", parameter of type "%s"', $name, $methodName, get_class($param)); throw new Exception\RuntimeException($message); } } // Strip null arguments from the end of the params list $reverseParams = array_reverse($methodParams, true); foreach ($reverseParams as $key => $param) { if ('NULL' === $param) { unset($methodParams[$key]); continue; } break; } $methods .= sprintf("\$object->%s(%s);\n", $methodName, implode(', ', $methodParams)); } // Generate caching statement $storage = ''; if ($im->hasSharedInstance($name, $params)) { $storage = sprintf("\$this->services['%s'] = \$object;\n", $name); } // Start creating getter $getterBody = ''; // Create fetch of stored service if ($im->hasSharedInstance($name, $params)) { $getterBody .= sprintf("if (isset(\$this->services['%s'])) {\n", $name); $getterBody .= sprintf("%sreturn \$this->services['%s'];\n}\n\n", $indent, $name); } // Creation and method calls $getterBody .= sprintf("%s\n", $creation); $getterBody .= $methods; // Stored service $getterBody .= $storage; // End getter body $getterBody .= "return \$object;\n"; $getterDef = new MethodGenerator(); $getterDef->setName($getter); $getterDef->setBody($getterBody); $getters[] = $getterDef; // Get cases for case statements $cases = array($name); if (isset($aliases[$name])) { $cases = array_merge($aliases[$name], $cases); } // Build case statement and store $statement = ''; foreach ($cases as $value) { $statement .= sprintf("%scase '%s':\n", $indent, $value); } $statement .= sprintf("%sreturn \$this->%s();\n", str_repeat($indent, 2), $getter); $caseStatements[] = $statement; } // Build switch statement $switch = sprintf("switch (%s) {\n%s\n", '$name', implode("\n", $caseStatements)); $switch .= sprintf("%sdefault:\n%sreturn parent::get(%s, %s);\n", $indent, str_repeat($indent, 2), '$name', '$params'); $switch .= "}\n\n"; // Build get() method $nameParam = new ParameterGenerator(); $nameParam->setName('name'); $paramsParam = new ParameterGenerator(); $paramsParam->setName('params')->setType('array')->setDefaultValue(array()); $get = new MethodGenerator(); $get->setName('get'); $get->setParameters(array($nameParam, $paramsParam)); $get->setBody($switch); // Create getters for aliases $aliasMethods = array(); foreach ($aliases as $class => $classAliases) { foreach ($classAliases as $alias) { $aliasMethods[] = $this->getCodeGenMethodFromAlias($alias, $class); } } // Create class code generation object $container = new ClassGenerator(); $container->setName($this->containerClass)->setExtendedClass('ServiceLocator')->addMethodFromGenerator($get)->addMethods($getters)->addMethods($aliasMethods); // Create PHP file code generation object $classFile = new FileGenerator(); $classFile->setUse('Zend\\Di\\ServiceLocator')->setClass($container); if (null !== $this->namespace) { $classFile->setNamespace($this->namespace); } if (null !== $filename) { $classFile->setFilename($filename); } return $classFile; }
public function testGeneratesNamespaceStatements() { $file = new FileGenerator(); $file->setNamespace('Foo\\Bar'); $generated = $file->generate(); $this->assertContains('namespace Foo\\Bar', $generated, $generated); }
/** * creates Module class */ protected function createModuleClass() { $moduleClassFilePath = $this->moduleRoot() . '/Module.php'; if (!file_exists($moduleClassFilePath)) { $this->console('creating Module Class'); $moduleClassFile = new FileGenerator(); $moduleClassFile->setNamespace($this->params->getParam('moduleName')); $moduleClass = new ClassGenerator(); $moduleClass->setDocBlock($this->getFileDocBlock())->getDocBlock()->setShortDescription($this->codeLibrary()->get('module.moduleClassDescription')); $moduleClass->setName('Module'); // onbootstrap $onBootstrapMethod = new MethodGenerator(); $onBootstrapMethod->setName('onBootstrap')->setBody($this->codeLibrary()->get('module.onBootstrap.body')); $onBootstrapMethod->setDocBlock(new DocBlockGenerator($this->codeLibrary()->get('module.onBootstrap.shortdescription'), $this->codeLibrary()->get('module.onBootstrap.longdescription'), array(new ParamTag('e', '\\Zend\\Mvc\\MvcEvent')))); $eventParam = new ParameterGenerator('e', '\\Zend\\Mvc\\MvcEvent'); $onBootstrapMethod->setParameter($eventParam); $moduleClass->addMethodFromGenerator($onBootstrapMethod); // config $configMethod = new MethodGenerator('getConfig', array(), MethodGenerator::FLAG_PUBLIC, $this->codeLibrary()->get('module.config.body'), new DocBlockGenerator($this->codeLibrary()->get('module.config.shortdescription'), $this->codeLibrary()->get('module.config.longdescription'), array())); $moduleClass->addMethodFromGenerator($configMethod); // getAutoloaderConfig $getAutoloaderConfigMethod = new MethodGenerator('getAutoloaderConfig', array(), MethodGenerator::FLAG_PUBLIC, $this->codeLibrary()->get('module.getAutoloaderConfig.body'), new DocBlockGenerator($this->codeLibrary()->get('module.getAutoloaderConfig.shortdescription'), $this->codeLibrary()->get('module.getAutoloaderConfig.longdescription'), array())); $moduleClass->addMethodFromGenerator($getAutoloaderConfigMethod); // adding class method and generating file $moduleClassFile->setClass($moduleClass); file_put_contents($moduleClassFilePath, $moduleClassFile->generate()); } }
public function controllerAction() { $config = $this->getServiceLocator()->get('config'); $moduleName = $config['VisioCrudModeler']['params']['moduleName']; $modulePath = $config['VisioCrudModeler']['params']['modulesDirectory']; $db = $this->getServiceLocator()->get('Zend\\Db\\Adapter\\Adapter'); $dataSourceDescriptor = new DbDataSourceDescriptor($db, 'K08_www_biedronka_pl'); $listDataSets = $dataSourceDescriptor->listDataSets(); $filter = new \Zend\Filter\Word\UnderscoreToCamelCase(); foreach ($listDataSets as $d) { $className = $filter->filter($d) . 'Controller'; $file = new FileGenerator(); $file->setFilename($className); $file->setNamespace($moduleName)->setUse('Zend\\Mvc\\Controller\\AbstractActionController'); $foo = new ClassGenerator(); $docblock = DocBlockGenerator::fromArray(array('shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend\\Code\\Generator.', 'tags' => array(array('name' => 'version', 'description' => '$Rev:$'), array('name' => 'license', 'description' => 'New BSD')))); $foo->setName($className); $foo->setExtendedClass('Base' . $className); $foo->setDocblock($docblock); $file->setClass($foo); echo '<pre>'; echo htmlentities($file->generate()); echo '</pre>'; $fileView = new FileGenerator(); $body = "echo '{$className}';"; $fileView->setBody($body); echo '<pre>'; echo htmlentities($fileView->generate()); echo '</pre>'; } echo '<hr />'; foreach ($listDataSets as $d) { $className = 'Base' . $filter->filter($d) . 'Controller'; $fileBase = new FileGenerator(); $fileBase->setFilename($className); $fileBase->setNamespace($moduleName)->setUse('Zend\\Mvc\\Controller\\AbstractActionController'); $fooBase = new ClassGenerator(); $docblockBase = DocBlockGenerator::fromArray(array('shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend\\Code\\Generator.', 'tags' => array(array('name' => 'version', 'description' => '$Rev:$'), array('name' => 'license', 'description' => 'New BSD')))); $fooBase->setName($className); $index = new MethodGenerator(); $index->setName('indexAction'); $create = new MethodGenerator(); $create->setName('createAction'); $read = new MethodGenerator(); $read->setName('readAction'); $update = new MethodGenerator(); $update->setName('updateAction'); $delete = new MethodGenerator(); $delete->setName('deleteAction'); $fooBase->setExtendedClass('AbstractActionController'); //$fooBase->set $fooBase->setDocblock($docblock); $fooBase->addMethodFromGenerator($index); $fooBase->addMethodFromGenerator($create); $fooBase->addMethodFromGenerator($read); $fooBase->addMethodFromGenerator($update); $fooBase->addMethodFromGenerator($delete); $fileBase->setClass($fooBase); echo '<pre>'; echo htmlentities($fileBase->generate()); echo '</pre>'; } exit; }
/** * generates base controller for given dataSet * * @param DataSetDescriptorInterface $dataSet * @return string generated controller full class name */ protected function generateBaseController(DataSetDescriptorInterface $dataSet) { $name = $dataSet->getName(); $className = 'Base' . $this->underscoreToCamelCase->filter($name) . 'Controller'; $namespace = $this->params->getParam("moduleName") . '\\Controller\\Base'; $fullClassName = '\\' . $namespace . '\\' . $className; $moduleName = $this->params->getParam("moduleName"); $fileBase = new FileGenerator(); $fileBase->setFilename($className); $fileBase->setNamespace($namespace); $class = new ClassGenerator(); $class->setName($className)->setExtendedClass('\\' . $this->extendedController); $docBlock = new \Zend\Code\Generator\DocblockGenerator(sprintf($this->codeLibrary()->get('controller.standardBaseControllerDescription'), $name)); $docBlock->setTag(new GenericTag('author', $this->params->getParam('author')))->setTag(new GenericTag('project', $this->params->getParam('project')))->setTag(new GenericTag('license', $this->params->getParam('license')))->setTag(new GenericTag('copyright', $this->params->getParam('copyright'))); $class->setDocBlock($docBlock); $this->addControllerMethods($class, $dataSet); $fileBase->setClass($class); $modelClassFilePath = $this->moduleRoot() . "/src/" . $this->params->getParam("moduleName") . "/Controller/Base/" . $className . ".php"; file_put_contents($modelClassFilePath, $fileBase->generate()); return $fullClassName; }
public function setNamespace($namespace) { $this->generator->setNamespace($namespace); }
/** * @return \Zend\Code\Generator\FileGenerator|null */ public function getGeneratedFile() { $classConfig = $this->config->getClassConfig($this->fullClassName); $factoryName = $this->dic->getFactoryClassName($this->fullClassName); $classReflection = $this->dic->getClassReflection($this->fullClassName); if (strpos($classReflection->getDocComment(), '@generator ignore') !== false) { return null; } $file = new Generator\FileGenerator(); $factoryClass = new \rg\injektor\generators\FactoryClass($factoryName); $instanceMethod = new \rg\injektor\generators\InstanceMethod($this->factoryGenerator); $arguments = array(); $constructorMethodReflection = null; if ($this->dic->isSingleton($classReflection)) { $constructorMethodReflection = $classReflection->getMethod('getInstance'); $arguments = $constructorMethodReflection->getParameters(); } else { if ($classReflection->hasMethod('__construct')) { $constructorMethodReflection = $classReflection->getMethod('__construct'); $arguments = $constructorMethodReflection->getParameters(); } } $isSingleton = $this->dic->isConfiguredAsSingleton($classConfig, $classReflection); $isService = $this->dic->isConfiguredAsService($classConfig, $classReflection); $body = '$i = 0;' . PHP_EOL; if ($isSingleton || $isService) { $defaultValue = new Generator\PropertyValueGenerator(array(), Generator\ValueGenerator::TYPE_ARRAY, Generator\ValueGenerator::OUTPUT_SINGLE_LINE); $property = new Generator\PropertyGenerator('instance', $defaultValue, Generator\PropertyGenerator::FLAG_PRIVATE); $property->setStatic(true); $factoryClass->addPropertyFromGenerator($property); } if ($isSingleton) { $body .= '$singletonKey = serialize($parameters) . "#" . getmypid();' . PHP_EOL; $body .= 'if (isset(self::$instance[$singletonKey])) {' . PHP_EOL; $body .= ' return self::$instance[$singletonKey];' . PHP_EOL; $body .= '}' . PHP_EOL . PHP_EOL; } if ($isService) { $body .= 'if (self::$instance) {' . PHP_EOL; $body .= ' return self::$instance;' . PHP_EOL; $body .= '}' . PHP_EOL . PHP_EOL; } $providerClassName = $this->dic->getProviderClassName($classConfig, new \ReflectionClass($this->fullClassName), null); if ($providerClassName && $providerClassName->getClassName()) { $argumentFactory = $this->dic->getFullFactoryClassName($providerClassName->getClassName()); $this->factoryGenerator->processFileForClass($providerClassName->getClassName()); $body .= '$instance = \\' . $argumentFactory . '::getInstance(array())->get();' . PHP_EOL; $this->usedFactories[] = $argumentFactory; } else { // constructor method arguments if (count($arguments) > 0) { foreach ($arguments as $argument) { /** @var \ReflectionParameter $argument */ $argumentName = $argument->name; $this->constructorArguments[] = $argumentName; $this->constructorArgumentStringParts[] = '$' . $argumentName; $this->realConstructorArgumentStringParts[] = '$' . $argumentName; } $body .= 'if (!$parameters) {' . PHP_EOL; foreach ($arguments as $argument) { /** @var \ReflectionParameter $argument */ $injectionParameter = new \rg\injektor\generators\InjectionParameter($argument, $classConfig, $this->config, $this->dic, InjectionParameter::MODE_NO_ARGUMENTS); try { if ($injectionParameter->getClassName()) { $this->factoryGenerator->processFileForClass($injectionParameter->getClassName()); } if ($injectionParameter->getFactoryName()) { $this->usedFactories[] = $injectionParameter->getFactoryName(); } $body .= ' ' . $injectionParameter->getProcessingBody(); } catch (\Exception $e) { $body .= ' ' . $injectionParameter->getDefaultProcessingBody(); } } $body .= '}' . PHP_EOL; $body .= 'else if (array_key_exists(0, $parameters)) {' . PHP_EOL; foreach ($arguments as $argument) { /** @var \ReflectionParameter $argument */ $injectionParameter = new \rg\injektor\generators\InjectionParameter($argument, $classConfig, $this->config, $this->dic, InjectionParameter::MODE_NUMERIC); try { if ($injectionParameter->getClassName()) { $this->factoryGenerator->processFileForClass($injectionParameter->getClassName()); } if ($injectionParameter->getFactoryName()) { $this->usedFactories[] = $injectionParameter->getFactoryName(); } $body .= ' ' . $injectionParameter->getProcessingBody(); } catch (\Exception $e) { $body .= ' ' . $injectionParameter->getDefaultProcessingBody(); } } $body .= '}' . PHP_EOL; $body .= 'else {' . PHP_EOL; foreach ($arguments as $argument) { /** @var \ReflectionParameter $argument */ $injectionParameter = new \rg\injektor\generators\InjectionParameter($argument, $classConfig, $this->config, $this->dic, InjectionParameter::MODE_STRING); try { if ($injectionParameter->getClassName()) { $this->factoryGenerator->processFileForClass($injectionParameter->getClassName()); } if ($injectionParameter->getFactoryName()) { $this->usedFactories[] = $injectionParameter->getFactoryName(); } $body .= ' ' . $injectionParameter->getProcessingBody(); } catch (\Exception $e) { $body .= ' ' . $injectionParameter->getDefaultProcessingBody(); } } $body .= '}' . PHP_EOL; } // Property injection $this->injectProperties($classConfig, $classReflection); if (count($this->injectableProperties) > 0) { $proxyName = $this->dic->getProxyClassName($this->fullClassName); if ($this->dic->isSingleton($classReflection)) { $file->setClass($this->createProxyClass($proxyName)); $body .= PHP_EOL . '$instance = ' . $proxyName . '::getInstance(' . implode(', ', $this->constructorArgumentStringParts) . ');' . PHP_EOL; } else { $file->setClass($this->createProxyClass($proxyName)); $body .= PHP_EOL . '$instance = new ' . $proxyName . '(' . implode(', ', $this->constructorArgumentStringParts) . ');' . PHP_EOL; } } else { if ($this->dic->isSingleton($classReflection)) { $body .= PHP_EOL . '$instance = \\' . $this->fullClassName . '::getInstance(' . implode(', ', $this->constructorArgumentStringParts) . ');' . PHP_EOL; } else { $body .= PHP_EOL . '$instance = new \\' . $this->fullClassName . '(' . implode(', ', $this->constructorArgumentStringParts) . ');' . PHP_EOL; } } } if ($isSingleton) { $body .= 'self::$instance[$singletonKey] = $instance;' . PHP_EOL; } if ($isService) { $body .= 'self::$instance = $instance;' . PHP_EOL; } foreach ($this->injectableArguments as $injectableArgument) { $body .= '$instance->propertyInjection' . $injectableArgument->getName() . '();' . PHP_EOL; } $body .= 'return $instance;' . PHP_EOL; $instanceMethod->setBody($body); $instanceMethod->setStatic(true); $factoryClass->addMethodFromGenerator($instanceMethod); // Add Factory Method $methods = $classReflection->getMethods(); foreach ($methods as $method) { /** @var \ReflectionMethod $method */ if ($method->isPublic() && substr($method->name, 0, 2) !== '__') { $factoryMethod = $this->getFactoryMethod($method, $classConfig); $factoryClass->addMethodFromGenerator($factoryMethod); } } // Generate File $file->setNamespace('rg\\injektor\\generated'); $this->usedFactories = array_unique($this->usedFactories); foreach ($this->usedFactories as &$usedFactory) { $usedFactory = str_replace('rg\\injektor\\generated\\', '', $usedFactory); $usedFactory = $usedFactory . '.php'; } $file->setRequiredFiles($this->usedFactories); $file->setClass($factoryClass); $file->setFilename($this->factoryPath . DIRECTORY_SEPARATOR . $factoryName . '.php'); return $file; }