Example #1
0
 /**
  * Generator inner branches loop handler.
  *
  * @param Branch $branch Branch for looping its inner branches
  * @param bool $conditionStarted Return variable showing if inner branching has been started
  * @param string $pathValue Current routing logic $path variable name
  */
 protected function generatorBranchesLoop(Branch $branch, &$conditionStarted, $pathValue)
 {
     // First stage - open condition
     // If we have started condition branching but this branch has parameters
     if ($conditionStarted && $branch->isParametrized()) {
         $this->generator->endIfCondition()->defIfCondition($branch->toLogicConditionCode($pathValue));
     } elseif (!$conditionStarted) {
         // This is first inner branch
         // Start new condition
         $this->generator->defIfCondition($branch->toLogicConditionCode($pathValue));
         // Set flag that condition has started
         $conditionStarted = true;
     } else {
         // This is regular branching
         $this->generator->defElseIfCondition($branch->toLogicConditionCode($pathValue));
     }
     // Second stage receive parameters
     if ($branch->isParametrized()) {
         // Store parameter value received from condition
         $this->generator->newLine($branch->storeMatchedParameter());
     }
     /**
      * Optimization to remove nested string operations - we create temporary $path variables
      */
     $pathVariable = '$path' . mt_rand(0, 99999);
     // Do not output new $path variable creation if this is logic end
     if (count($branch->branches)) {
         $this->generator->newLine($pathVariable . ' = ' . $branch->removeMatchedPathCode($pathValue) . ';');
     }
     // We should subtract part of $path var to remove this parameter
     // Go deeper in recursion
     $this->innerGenerate2($branch, $pathVariable, false);
 }
Example #2
0
 /**
  * Generate routing conditions logic.
  *
  * @param Branch $parent Current branch in resursion
  * @param string $pathValue Current $path value in routing logic
  * @param bool $conditionStarted Flag that condition started
  */
 protected function innerGenerate2(Branch $parent, $pathValue = '$path', $conditionStarted = false)
 {
     // Iterate inner branches
     foreach ($parent->branches as $branch) {
         // First stage - open condition
         // If we have started condition branching but this branch has parameters
         if ($conditionStarted && $branch->isParametrized()) {
             $this->generator->endIfCondition()->defIfCondition($branch->toLogicConditionCode($pathValue));
         } elseif (!$conditionStarted) {
             // This is first inner branch
             // Start new condition
             $this->generator->defIfCondition($branch->toLogicConditionCode($pathValue));
             // Set flag that condition has started
             $conditionStarted = true;
         } else {
             // This is regular branching
             $this->generator->defElseIfCondition($branch->toLogicConditionCode($pathValue));
         }
         // Second stage receive parameters
         if ($branch->isParametrized()) {
             // Store parameter value received from condition
             $this->generator->newLine($branch->storeMatchedParameter());
         }
         /**
          * Optimization to remove nested string operations - we create temporary $path variables
          */
         $pathVariable = '$path' . rand(0, 99999);
         // Do not output new $path variable creation if this is logic end
         if (sizeof($branch->branches)) {
             $this->generator->newLine($pathVariable . ' = ' . $branch->removeMatchedPathCode($pathValue) . ';');
         }
         // We should subtract part of $path var to remove this parameter
         // Go deeper in recursion
         $this->innerGenerate2($branch, $pathVariable, false);
     }
     // Return route if branch has it
     if ($parent->hasRoute()) {
         // If we had other inner branch for this parent branch - we need to add else
         if (sizeof($parent->branches)) {
             $this->generator->defElseCondition();
         }
         $this->generator->newLine($parent->returnRouteCode());
     }
     // Close first condition
     if ($conditionStarted) {
         $this->generator->endIfCondition();
     }
 }
Example #3
0
 /**
  * Build resolving method injection declaration.
  *
  * @param array  $dependencies       Collection of method dependencies
  * @param string $methodName         Method name
  * @param string $containerVariable  Container declaration variable name
  * @param string $reflectionVariable Reflection class variable name
  * @param bool   $isPublic           Flag if method is public
  */
 protected function buildResolverMethodDeclaration(array $dependencies, string $methodName, string $containerVariable, string $reflectionVariable, bool $isPublic)
 {
     // Get method arguments
     $argumentsCount = count($dependencies);
     $this->generator->comment('Invoke ' . $methodName . '() and pass dependencies(y)');
     if ($isPublic) {
         $this->generator->newLine($containerVariable . '->' . $methodName . '(')->increaseIndentation();
     } else {
         $this->generator->newLine('$method = ' . $reflectionVariable . '->getMethod(\'' . $methodName . '\');')->newLine('$method->setAccessible(true);')->newLine('$method->invoke(')->increaseIndentation()->newLine($containerVariable . ',');
     }
     $i = 0;
     // Iterate method arguments
     foreach ($dependencies as $argument => $dependency) {
         // Add dependencies
         $this->buildResolverArgument($dependency);
         // Add comma if this is not last dependency
         if (++$i < $argumentsCount) {
             $this->generator->text(',');
         }
     }
     $this->generator->decreaseIndentation()->newLine(');');
 }
Example #4
0
 /**
  * Create View class ancestor.
  *
  * @param Metadata $metadata View file metadata
  * @param string $path Entry path for generated classes and folders
  * @param null|callable $viewHandler View code handler
  */
 protected function generateViewClass(Metadata $metadata, $path, $viewHandler = null)
 {
     $metadataParentClass = eval('return ' . $metadata->parentClass . ';');
     // Read view file
     $viewCode = trim(file_get_contents($metadata->path));
     // If we have external handler - pass view code to it for conversion
     if (is_callable($viewHandler)) {
         $viewCode = call_user_func($viewHandler, $viewCode);
     }
     // Convert to string for defining
     $viewCode = '<<<\'EOT\'' . "\n" . $viewCode . "\n" . 'EOT';
     $parentClass = !isset($metadata->parentClass) ? $this->parentViewClass : $metadataParentClass;
     $this->generator->defNamespace($metadata->namespace)->multiComment(array('Class for view "' . $metadata->path . '" rendering'))->defClass($metadata->className, '\\' . $parentClass)->commentVar('string', 'Path to view file')->defClassVar('$file', 'protected', $metadata->path)->commentVar('string', 'Parent block name')->defClassVar('$parentBlock', 'protected', $metadata->parentBlock)->commentVar('array', 'Blocks list')->defClassVar('$blocks', 'protected', $metadata->blocks)->commentVar('string', 'View source code')->defClassVar('$source', 'protected', $viewCode);
     //->commentVar('array', 'Collection of view variables')
     //->defClassVar('$variables', 'public static', array_keys($metadata->variables))
     //->commentVar('array', 'Collection of view variable types')
     //->defClassVar('$types', 'public static', $metadata->types)
     // Iterate all view variables
     foreach (array_keys($metadata->variables) as $name) {
         $type = array_key_exists($name, $metadata->types) ? $metadata->types[$name] : 'mixed';
         $static = array_key_exists($name, $metadata->static) ? ' static' : '';
         $this->generator->commentVar($type, 'View variable')->defClassVar('$' . $name, 'public' . $static);
         // Do not generate setters for static variables
         if ($static !== ' static') {
             $this->generator->text($this->generateViewVariableSetter($name, $metadata->originalVariables[$name], $type));
         }
     }
     // Iterate namespace and create folder structure
     $path .= '/' . str_replace('\\', '/', $metadata->namespace);
     if (!is_dir($path)) {
         mkdir($path, 0777, true);
     }
     $newClassFile = $path . '/' . $metadata->className . '.php';
     file_put_contents($newClassFile, '<?php' . $this->generator->endClass()->flush());
     // Store path to generated class
     $metadata->generatedPath = $newClassFile;
     // Make generated cache files accessible
     chmod($newClassFile, 0777);
 }
 /** Generate database table relations */
 public function relations($cachePath = '')
 {
     // Generate unique file name
     $relations_file = $cachePath . '/relations/' . md5(serialize(TableRelation::$instances)) . '.php';
     // Relations file does not exists - create it
     if (!file_exists($relations_file)) {
         // Get directory path
         $dir = pathname($relations_file);
         // Create folder
         if (!file_exists($dir)) {
             mkdir($dir, 0777, TRUE);
         } else {
             File::clear($dir);
         }
         // Processed permanent table relations
         $db_relations = array();
         // Iterate permanent relations
         foreach (TableRelation::$instances as $row) {
             // Create relations data for specific table
             if (!isset($db_relations[$row->parent])) {
                 $db_relations[$row->parent] = array();
             }
             // Define child relation table name
             $child_relation = !isset($row->alias[0]) ? $row->child : $row->alias;
             $row->parent = self::$prefix . $row->parent;
             $row->child = self::$prefix . $row->child;
             // Save relation data
             $db_relations[$row->parent][$child_relation] = $row;
         }
         // TODO: Pass generator and others via constructor DI
         // Create code generator instance
         $g = new Generator('samson\\activerecord');
         $g->multicomment(array('Static ActiveRecord generated table relations'));
         // Array of "FROM" sql statements for related tables
         $sql_from = array();
         // Array of "SELECT" sql statements for related tables
         $sql_select = array();
         // Array related tables columns names and aliases
         $relations = array();
         // Array of table aliases
         $aliases = array();
         // Array of table relation type
         $types = array();
         // Array of columns map
         $map = array();
         // Iterate grouped relations
         foreach ($db_relations as $parent => $relation) {
             // Check if parent class in relation exists
             if (class_exists(__NAMESPACE__ . '\\' . $parent, false)) {
                 // Iterate table permanent relations
                 foreach ($relation as $r_table => $i) {
                     // Array of "SELECT" sql statements for this related tables
                     $_sql_select = array();
                     // Array related tables columns names and aliases for this related tables
                     $_relations = array();
                     // Parent table name
                     $r_table_name = isset($i->alias[0]) ? $i->alias : $i->child;
                     // Define start of join sql statement
                     $_sql_from = 'LEFT JOIN `' . $i->child . '`';
                     // If relation alias is defined
                     if (isset($i->alias[0])) {
                         $_sql_from = 'LEFT JOIN `' . $i->child . '` AS ' . $i->alias;
                     }
                     // Parent table name
                     $ptable = $i->parent;
                     // If parent field not specified - use parent table primary field
                     if (!isset($i->parent_field)) {
                         $pfield = $primary_field;
                     } else {
                         // Define if parent field name has table name in it
                         $tableinpf = strpos($i->parent_field, '.');
                         // Get parent table field name
                         $pfield = $tableinpf !== false ? substr($i->parent_field, $tableinpf + 1) : $i->parent_field;
                         // Parent table field
                         $ptable = $tableinpf !== false ? dbMySQLConnector::$prefix . substr($i->parent_field, 0, $tableinpf) : $i->parent;
                     }
                     // If no "." symbol in parent field name append parent table name
                     $pf = '`' . $ptable . '`.`' . $pfield . '`';
                     // If child field not specified
                     if (!isset($i->child_field[0])) {
                         $cf = '`' . (isset($i->alias[0]) ? $i->alias : $i->child) . '`.`' . $pfield . '`';
                     } else {
                         $cf = strpos($i->child_field, '.') === false ? '`' . (isset($i->alias[0]) ? $i->alias : $i->child) . '`.' . $i->child_field : $i->child_field;
                     }
                     // Build columns metadata
                     $this->__build_columns_map($i->child, $_sql_select, $map, $_relations, $i->alias);
                     // Array of "SELECT" sql statements to all related tables
                     $sql_select[$r_table_name] = implode(',', $_sql_select);
                     $relations[$r_table_name] = $_relations;
                     $sql_from[$r_table_name] = $_sql_from . ' ON ' . $pf . ' = ' . $cf;
                     $aliases[$r_table_name] = $i->child;
                     $types[$r_table_name] = $i->type;
                 }
                 // Remove prefix
                 $class_name = str_replace(self::$prefix, '', $parent);
                 // Generate code for this table
                 $g->newline()->comment('Relation data for table "' . $parent . '"')->defarraymerge($class_name . '::$_sql_from', $sql_from)->defarraymerge($class_name . '::$_sql_select', $sql_select)->defarraymerge($class_name . '::$_map', $map)->defvar($class_name . '::$_relation_alias', $aliases)->defvar($class_name . '::$_relation_type', $types)->defvar($class_name . '::$_relations', $relations);
             }
         }
         // Save file to wwwrot
         $g->write($relations_file);
         // Evaluate relations code
         eval($g->code);
     } else {
         include $relations_file;
     }
 }