Exemple #1
0
 /**
  * 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;
 }