public static function create($path, $name)
 {
     $parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative());
     $prettyPrinter = new CodePrinter();
     $path = explode(".", $path);
     $controllerPath = "";
     if (count($path) == 1) {
         $controllerPath = $path[0] . ".controllers." . $name;
     } else {
         if (count($path) == 2) {
             $controllerPath = $path[0] . ".modules." . $path[1] . ".controllers." . $name;
         }
     }
     try {
         $templatePath = Yii::getPathOfAlias("application.components.codegen.templates.controller") . ".php";
         $template = file_get_contents($templatePath);
         $stmts = $parser->parse($template);
         $stmts[0]->name = ucfirst($name);
         $generated = $prettyPrinter->prettyPrintFile($stmts);
         $cp = Yii::getPathOfAlias($controllerPath) . ".php";
         if (!is_dir(dirname($cp))) {
             mkdir(dirname($cp), 0777, true);
         }
         file_put_contents($cp, $generated);
         return true;
     } catch (Exception $e) {
         return false;
     }
 }
Exemple #2
0
 public function duplicate()
 {
     $printer = new CodePrinter();
     $printer->setLevel($this->level);
     return $printer;
 }
Exemple #3
0
 /**
  * Compiles the file
  *
  * @param Compiler $compiler
  * @param StringsManager $stringsManager
  */
 public function compile(Compiler $compiler, StringsManager $stringsManager)
 {
     if (!$this->_ir) {
         throw new CompilerException('IR related to compiled file is missing');
     }
     /**
      * External classes should not be compiled as part of the extension
      */
     if ($this->_external) {
         return;
     }
     /**
      * Compilation context stores common objects required by compilation entities
      */
     $compilationContext = new CompilationContext();
     /**
      * Set global compiler in the compilation context
      */
     $compilationContext->compiler = $compiler;
     /**
      * Set global config in the compilation context
      */
     $compilationContext->config = $this->_config;
     /**
      * Set global logger in the compilation context
      */
     $compilationContext->logger = $this->_logger;
     /**
      * Set global strings manager
      */
     $compilationContext->stringsManager = $stringsManager;
     /**
      * Headers manager
      */
     $headersManager = new HeadersManager();
     $compilationContext->headersManager = $headersManager;
     /**
      * Main code-printer for the file
      */
     $codePrinter = new CodePrinter();
     $compilationContext->codePrinter = $codePrinter;
     /**
      * Alias manager
      */
     $compilationContext->aliasManager = $this->_aliasManager;
     $codePrinter->outputBlankLine();
     $class = false;
     $interface = false;
     foreach ($this->_ir as $topStatement) {
         switch ($topStatement['type']) {
             case 'class':
                 if ($interface || $class) {
                     throw new CompilerException("More than one class defined in the same file", $topStatement);
                 }
                 $class = true;
                 $this->compileClass($compilationContext, $this->_namespace, $topStatement);
                 break;
             case 'interface':
                 if ($interface || $class) {
                     throw new CompilerException("More than one class defined in the same file", $topStatement);
                 }
                 $class = true;
                 $this->compileClass($compilationContext, $this->_namespace, $topStatement);
                 break;
             case 'comment':
                 $this->compileComment($compilationContext, $topStatement);
                 break;
         }
     }
     /* ensure functions are handled last */
     foreach ($this->_functionDefinitions as $funcDef) {
         $this->compileFunction($compilationContext, $funcDef);
     }
     /* apply headers */
     $this->applyClassHeaders($compilationContext);
     $classDefinition = $this->_classDefinition;
     if (!$classDefinition) {
         $this->_ir = null;
         return;
     }
     $classDefinition->setOriginalNode($this->_originalNode);
     $completeName = $classDefinition->getCompleteName();
     $path = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($completeName));
     $filePath = 'ext/' . $path . '.zep.c';
     $filePathHeader = 'ext/' . $path . '.zep.h';
     if (strpos($path, DIRECTORY_SEPARATOR)) {
         $dirname = dirname($filePath);
         if (!is_dir($dirname)) {
             mkdir($dirname, 0755, true);
         }
     }
     if ($codePrinter) {
         /**
          * If the file does not exists we create it for the first time
          */
         if (!file_exists($filePath)) {
             file_put_contents($filePath, $codePrinter->getOutput());
             if ($compilationContext->headerPrinter) {
                 file_put_contents($filePathHeader, $compilationContext->headerPrinter->getOutput());
             }
         } else {
             $fileSystem = $compiler->getFileSystem();
             /**
              * Use md5 hash to avoid rewrite the file again and again when it hasn't changed
              * thus avoiding unnecessary recompilations
              */
             $output = $codePrinter->getOutput();
             $hash = $fileSystem->getHashFile('md5', $filePath, true);
             if (md5($output) != $hash) {
                 file_put_contents($filePath, $output);
             }
             if ($compilationContext->headerPrinter) {
                 $output = $compilationContext->headerPrinter->getOutput();
                 $hash = $fileSystem->getHashFile('md5', $filePathHeader, true);
                 if (md5($output) != $hash) {
                     file_put_contents($filePathHeader, $output);
                 }
             }
         }
     }
     /**
      * Add to file compiled
      */
     $this->_compiledFile = $path . '.c';
     $this->_ir = null;
 }
Exemple #4
0
 /**
  * Compiles a class/interface
  *
  * @param CompilationContext $compilationContext
  * @throws CompilerException
  */
 public function compile(CompilationContext $compilationContext)
 {
     /**
      * Sets the current object as global class definition
      */
     $compilationContext->classDefinition = $this;
     /**
      * Get the global codePrinter
      */
     $codePrinter = $compilationContext->codePrinter;
     /**
      * The ZEPHIR_INIT_CLASS defines properties and constants exported by the class
      */
     $codePrinter->output('ZEPHIR_INIT_CLASS(' . $this->getCNamespace() . '_' . $this->getName() . ') {');
     $codePrinter->outputBlankLine();
     $codePrinter->increaseLevel();
     /**
      * Method entry
      */
     $methods =& $this->methods;
     if (count($methods)) {
         $methodEntry = strtolower($this->getCNamespace()) . '_' . strtolower($this->getName()) . '_method_entry';
     } else {
         $methodEntry = 'NULL';
     }
     $namespace = str_replace('\\', '_', $compilationContext->config->get('namespace'));
     $abstractFlag = '0';
     if ($this->isAbstract()) {
         $abstractFlag = 'ZEND_ACC_EXPLICIT_ABSTRACT_CLASS';
     }
     /**
      * Register the class with extends + interfaces
      */
     $classExtendsDefinition = null;
     if ($this->extendsClass) {
         $classExtendsDefinition = $this->extendsClassDefinition;
         if (!$classExtendsDefinition->isInternal()) {
             $classEntry = $classExtendsDefinition->getClassEntry();
         } else {
             $classEntry = $this->getClassEntryByClassName($classExtendsDefinition->getName(), $compilationContext);
         }
         if ($this->getType() == 'class') {
             $codePrinter->output('ZEPHIR_REGISTER_CLASS_EX(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . strtolower($this->getSCName($namespace)) . ', ' . $classEntry . ', ' . $methodEntry . ', ' . $abstractFlag . ');');
             $codePrinter->outputBlankLine();
         } else {
             $codePrinter->output('ZEPHIR_REGISTER_INTERFACE_EX(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . strtolower($this->getSCName($namespace)) . ', ' . $classEntry . ', ' . $methodEntry . ');');
             $codePrinter->outputBlankLine();
         }
     } else {
         if ($this->getType() == 'class') {
             $codePrinter->output('ZEPHIR_REGISTER_CLASS(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . strtolower($this->getSCName($namespace)) . ', ' . $methodEntry . ', ' . $abstractFlag . ');');
         } else {
             $codePrinter->output('ZEPHIR_REGISTER_INTERFACE(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . strtolower($this->getSCName($namespace)) . ', ' . $methodEntry . ');');
         }
         $codePrinter->outputBlankLine();
     }
     $needBreak = true;
     /**
      * @todo Remove after removing support for php 5.3
      */
     $currentClassHref =& $this;
     $this->eventsManager->listen('setMethod', function (ClassMethod $method) use(&$methods, &$currentClassHref, $compilationContext, &$needBreak) {
         $needBreak = false;
         $methods[$method->getName()] = $method;
         $compilationContext->classDefinition->setMethods($methods);
     });
     /**
      * Compile properties
      * @var $property ClassProperty
      */
     foreach ($this->getProperties() as $property) {
         $docBlock = $property->getDocBlock();
         if ($docBlock) {
             $codePrinter->outputDocBlock($docBlock, true);
         }
         $property->compile($compilationContext);
         $codePrinter->outputBlankLine();
     }
     if (!$needBreak) {
         $compilationContext->codePrinter->clear();
         $currentClassHref->compile($compilationContext);
         return;
     }
     /**
      * Compile constants
      * @var $constant ClassConstant
      */
     foreach ($this->getConstants() as $constant) {
         $docBlock = $constant->getDocBlock();
         if ($docBlock) {
             $codePrinter->outputDocBlock($docBlock, true);
         }
         $constant->compile($compilationContext);
         $codePrinter->outputBlankLine();
     }
     /**
      * Implemented interfaces
      */
     $interfaces = $this->interfaces;
     $compiler = $compilationContext->compiler;
     if (is_array($interfaces)) {
         $codePrinter->outputBlankLine(true);
         foreach ($interfaces as $interface) {
             /**
              * Try to find the interface
              */
             $classEntry = false;
             if ($compiler->isInterface($interface)) {
                 $classInterfaceDefinition = $compiler->getClassDefinition($interface);
                 $classEntry = $classInterfaceDefinition->getClassEntry();
             } else {
                 if ($compiler->isInternalInterface($interface)) {
                     $classInterfaceDefinition = $compiler->getInternalClassDefinition($interface);
                     $classEntry = $this->getClassEntryByClassName($classInterfaceDefinition->getName(), $compilationContext);
                 }
             }
             if (!$classEntry) {
                 if ($compiler->isClass($interface)) {
                     throw new CompilerException("Cannot locate interface " . $interface . " when implementing interfaces on " . $this->getCompleteName() . '. ' . $interface . ' is currently a class', $this->originalNode);
                 } else {
                     throw new CompilerException("Cannot locate interface " . $interface . " when implementing interfaces on " . $this->getCompleteName(), $this->originalNode);
                 }
             }
             /**
              * We don't check if abstract classes implement the methods in their interfaces
              */
             if (!$this->isAbstract()) {
                 $this->checkInterfaceImplements($this, $classInterfaceDefinition);
             }
             $codePrinter->output('zend_class_implements(' . $this->getClassEntry() . ' TSRMLS_CC, 1, ' . $classEntry . ');');
         }
     }
     if (!$this->isAbstract()) {
         /**
          * Interfaces in extended classes may have
          */
         if ($classExtendsDefinition) {
             if (!$classExtendsDefinition->isInternal()) {
                 $interfaces = $classExtendsDefinition->getImplementedInterfaces();
                 if (is_array($interfaces)) {
                     foreach ($interfaces as $interface) {
                         $classInterfaceDefinition = null;
                         if ($compiler->isInterface($interface)) {
                             $classInterfaceDefinition = $compiler->getClassDefinition($interface);
                         } else {
                             if ($compiler->isInternalInterface($interface)) {
                                 $classInterfaceDefinition = $compiler->getInternalClassDefinition($interface);
                             }
                         }
                         if ($classInterfaceDefinition) {
                             $this->checkInterfaceImplements($this, $classInterfaceDefinition);
                         }
                     }
                 }
             }
         }
     }
     $codePrinter->output('return SUCCESS;');
     $codePrinter->outputBlankLine();
     $codePrinter->decreaseLevel();
     $codePrinter->output('}');
     $codePrinter->outputBlankLine();
     /**
      * Compile methods
      */
     foreach ($methods as $method) {
         $docBlock = $method->getDocBlock();
         if ($docBlock) {
             $codePrinter->outputDocBlock($docBlock);
         }
         if ($this->getType() == 'class') {
             $codePrinter->output('PHP_METHOD(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ') {');
             $codePrinter->outputBlankLine();
             if (!$method->isAbstract()) {
                 $method->compile($compilationContext);
             }
             $codePrinter->output('}');
             $codePrinter->outputBlankLine();
         } else {
             $codePrinter->output('ZEPHIR_DOC_METHOD(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ');');
             $codePrinter->outputBlankLine();
         }
     }
     /**
      * Create a code printer for the header file
      */
     $codePrinter = new CodePrinter();
     $codePrinter->outputBlankLine();
     $codePrinter->output('extern zend_class_entry *' . $this->getClassEntry() . ';');
     $codePrinter->outputBlankLine();
     $codePrinter->output('ZEPHIR_INIT_CLASS(' . $this->getCNamespace() . '_' . $this->getName() . ');');
     $codePrinter->outputBlankLine();
     if ($this->getType() == 'class') {
         if (count($methods)) {
             foreach ($methods as $method) {
                 $codePrinter->output('PHP_METHOD(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ');');
             }
             $codePrinter->outputBlankLine();
         }
     }
     /**
      * Create argument info
      */
     foreach ($methods as $method) {
         $parameters = $method->getParameters();
         if (count($parameters)) {
             $codePrinter->output('ZEND_BEGIN_ARG_INFO_EX(arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', 0, 0, ' . $method->getNumberOfRequiredParameters() . ')');
             foreach ($parameters->getParameters() as $parameter) {
                 switch ($parameter['data-type']) {
                     case 'array':
                         $codePrinter->output("\t" . 'ZEND_ARG_ARRAY_INFO(0, ' . $parameter['name'] . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
                         break;
                     case 'variable':
                         if (isset($parameter['cast'])) {
                             switch ($parameter['cast']['type']) {
                                 case 'variable':
                                     $value = $parameter['cast']['value'];
                                     $codePrinter->output("\t" . 'ZEND_ARG_OBJ_INFO(0, ' . $parameter['name'] . ', ' . Utils::escapeClassName($compilationContext->getFullName($value)) . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
                                     break;
                                 default:
                                     throw new Exception('Unexpected exception');
                             }
                         } else {
                             $codePrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
                         }
                         break;
                     default:
                         $codePrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
                         break;
                 }
             }
             $codePrinter->output('ZEND_END_ARG_INFO()');
             $codePrinter->outputBlankLine();
         }
     }
     if (count($methods)) {
         $codePrinter->output('ZEPHIR_INIT_FUNCS(' . strtolower($this->getCNamespace() . '_' . $this->getName()) . '_method_entry) {');
         foreach ($methods as $method) {
             $parameters = $method->getParameters();
             if ($this->getType() == 'class') {
                 if (count($parameters)) {
                     $codePrinter->output("\t" . 'PHP_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', ' . $method->getModifiers() . ')');
                 } else {
                     $codePrinter->output("\t" . 'PHP_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', NULL, ' . $method->getModifiers() . ')');
                 }
             } else {
                 if ($method->isStatic()) {
                     if (count($parameters)) {
                         $codePrinter->output("\t" . 'ZEND_FENTRY(' . $method->getName() . ', NULL, arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)');
                     } else {
                         $codePrinter->output("\t" . 'ZEND_FENTRY(' . $method->getName() . ', NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)');
                     }
                 } else {
                     if (count($parameters)) {
                         $codePrinter->output("\t" . 'PHP_ABSTRACT_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ')');
                     } else {
                         $codePrinter->output("\t" . 'PHP_ABSTRACT_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', NULL)');
                     }
                 }
             }
         }
         $codePrinter->output('  PHP_FE_END');
         $codePrinter->output('};');
     }
     $compilationContext->headerPrinter = $codePrinter;
 }