Esempio n. 1
0
 /**
  * Construct, configure, and return a PHP classfile code generation object
  *
  * Creates a Zend\CodeGenerator\Php\PhpFile object that has 
  * created the specified class and service locator methods.
  * 
  * @param  null|string $filename 
  * @return CodeGen\PhpFile
  */
 public function getCodeGenerator($filename = null)
 {
     $injector = $this->injector;
     $im = $injector->getInstanceManager();
     $indent = '    ';
     $aliases = $this->reduceAliases($im->getAliases());
     $caseStatements = array();
     $getters = array();
     $definition = $injector->getDefinition();
     foreach ($definition->getClasses() 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) {
                 $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
         $creation = '';
         $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 $key => $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 CodeGen\PhpMethod();
         $getterDef->setName($getter)->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 CodeGen\PhpParameter();
     $nameParam->setName('name');
     $defaultParams = new CodeGen\PhpParameterDefaultValue();
     $defaultParams->setValue(array());
     $paramsParam = new CodeGen\PhpParameter();
     $paramsParam->setName('params')->setType('array')->setDefaultValue($defaultParams);
     $get = new CodeGen\PhpMethod();
     $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 CodeGen\PhpClass();
     $container->setName($this->containerClass)->setExtendedClass('ServiceLocator')->setMethod($get)->setMethods($getters)->setMethods($aliasMethods);
     // Create PHP file code generation object
     $classFile = new CodeGen\PhpFile();
     $classFile->setUse('Zend\\Di\\ServiceLocator')->setClass($container);
     if (null !== $this->namespace) {
         $classFile->setNamespace($this->namespace);
     }
     if (null !== $filename) {
         $classFile->setFilename($filename);
     }
     return $classFile;
 }
Esempio n. 2
0
    /**
     * @group ZF-11513
     */
    public function testAllowsClassConstantToHaveSameNameAsClassProperty()
    {
        $const = new Php\PhpProperty();
        $const->setName('name')->setDefaultValue('constant')->setConst(true);

        $property = new Php\PhpProperty();
        $property->setName('name')->setDefaultValue('property');

        $codeGenClass = new Php\PhpClass();
        $codeGenClass->setName('My_Class')->setProperties(array($const, $property));

        $expected = <<<CODE
class My_Class
{

    const name = 'constant';

    public \$name = 'property';


}

CODE;
        $this->assertEquals( $expected, $codeGenClass->generate() );
    }
Esempio n. 3
0
 /**
  * @group namespace
  */
 public function testPassingANamespacedClassnameShouldGenerateAClassnameWithoutItsNamespace()
 {
     $codeGenClass = new Php\PhpClass();
     $codeGenClass->setName('My\\Namespaced\\FunClass');
     $received = $codeGenClass->generate();
     $this->assertContains('class FunClass', $received, $received);
 }
Esempio n. 4
0
    /**
     * @group ZF-9602
     */
    public function testSetextendedclassShouldNotIgnoreNonEmptyClassnameOnGenerate()
    {
        $codeGenClass = new Php\PhpClass();
        $codeGenClass->setName('MyClass')->setExtendedClass('ParentClass');
        $expected = <<<CODE
class MyClass extends ParentClass
{


}

CODE;
        $this->assertEquals($expected, $codeGenClass->generate());
    }