/** * @return bool * @throws \Exception */ public function build() { $options = $this->_options; if (Tools::getDb()) { $config = Tools::getDb(); } if (!isset($config->adapter)) { throw new \Exception("Adapter was not found in the config. Please specify a config variable [database][adapter]"); } $adapter = ucfirst($config->adapter); $this->isSupportedAdapter($adapter); $di = new FactoryDefault(); $di->set('db', function () use($adapter, $config) { if (isset($config->adapter)) { $adapter = $config->adapter; } else { $adapter = 'Mysql'; } if (is_object($config)) { $configArray = $config->toArray(); } else { $configArray = $config; } $adapterName = 'Phalcon\\Db\\Adapter\\Pdo\\' . $adapter; unset($configArray['adapter']); return new $adapterName($configArray); }); $options['manager'] = $di->getShared('modelsManager'); $options['className'] = $options['name']; $options['fileName'] = str_replace('_', '-', Text::uncamelize($options['className'])); $modelsNamespace = $options['modelsNamespace']; if (isset($modelsNamespace) && substr($modelsNamespace, -1) !== '\\') { $modelsNamespace .= "\\"; } $modelName = $options['name']; $modelClass = $modelsNamespace . $modelName; if (!@dir($options['modelsDir'])) { if (!@mkdir($options['modelsDir'])) { throw new \Exception('Could not create directory on ' . $options['modelsDir']); } @chmod($options['modelsDir'], 0777); } $modelPath = $options['modelsDir'] . DIRECTORY_SEPARATOR . $modelName . '.php'; if (!file_exists($modelPath)) { $modelBuilder = new ModelBuilder(array('module' => $options['module'], 'name' => null, 'tableName' => $options['tableName'], 'schema' => $options['schema'], 'baseClass' => null, 'namespace' => $options['modelsNamespace'], 'foreignKeys' => true, 'defineRelations' => true, 'genSettersGetters' => $options['genSettersGetters'], 'directory' => $options['modelsDir'], 'force' => $options['force'])); $modelBuilder->build(); } if (!class_exists($modelClass)) { require_once $modelPath; } $entity = new $modelClass(); $metaData = $di['modelsMetadata']; $attributes = $metaData->getAttributes($entity); $dataTypes = $metaData->getDataTypes($entity); $identityField = $metaData->getIdentityField($entity); $primaryKeys = $metaData->getPrimaryKeyAttributes($entity); $setParams = array(); $selectDefinition = array(); $relationField = ''; $options['name'] = Text::uncamelize($options['name']); $options['plural'] = $this->_getPossiblePlural($options['name']); $options['singular'] = $this->_getPossibleSingular($options['name']); $options['modelClass'] = $options['modelsNamespace'] . '\\' . $this->_options['name']; $options['entity'] = $entity; $options['setParams'] = $setParams; $options['attributes'] = $attributes; $options['dataTypes'] = $dataTypes; $options['primaryKeys'] = $primaryKeys; $options['identityField'] = $identityField; $options['relationField'] = $relationField; $options['selectDefinition'] = $selectDefinition; $options['autocompleteFields'] = array(); $options['belongsToDefinitions'] = array(); //Build Controller $this->_makeController($options); if (isset($options['templateEngine']) && $options['templateEngine'] == 'volt') { //View layouts // $this->_makeLayoutsVolt($options); //View index.phtml $this->_makeViewIndexVolt(null, $options); //View search.phtml $this->_makeViewSearchVolt(null, $options); //View new.phtml $this->_makeViewNewVolt(null, $options); //View edit.phtml $this->_makeViewEditVolt(null, $options); } else { //View layouts // $this->_makeLayouts(null, $options); //View index.phtml $this->_makeViewIndex(null, $options); //View search.phtml $this->_makeViewSearch(null, $options); //View new.phtml $this->_makeViewNew(null, $options); //View edit.phtml $this->_makeViewEdit(null, $options); } return true; }
public function build() { $getSource = "\n public function getSource()\n {\n return '%s';\n }\n"; $templateThis = " \$this->%s(%s);" . PHP_EOL; $templateRelation = " \$this->%s('%s', '%s', '%s', %s);" . PHP_EOL; $templateSetter = "\n /**\n * Method to set the value of field %s\n *\n * @param %s \$%s\n * @return \$this\n */\n public function set%s(\$%s)\n {\n \$this->%s = \$%s;\n\n return \$this;\n }\n"; $templateValidateInclusion = "\n \$this->validate(\n new InclusionIn(\n array(\n 'field' => '%s',\n 'domain' => array(%s),\n 'required' => true,\n )\n )\n );"; $templateValidateEmail = "\n \$this->validate(\n new Email(\n array(\n 'field' => '%s',\n 'required' => true,\n )\n )\n );"; $templateValidationFailed = "\n if (\$this->validationHasFailed() == true) {\n return false;\n }"; $templateAttributes = "\n /**\n * @var %s\n */\n %s \$%s;\n"; $templateGetterMap = "\n /**\n * Returns the value of field %s\n *\n * @return %s\n */\n public function get%s()\n {\n if (\$this->%s) {\n return new %s(\$this->%s);\n } else {\n return null;\n }\n }\n"; $templateGetter = "\n /**\n * Returns the value of field %s\n *\n * @return %s\n */\n public function get%s()\n {\n return \$this->%s;\n }\n"; $templateValidations = "\n /**\n * Validations and business logic\n */\n public function validation()\n {\n%s\n }\n"; $templateInitialize = "\n /**\n * Initialize method for model.\n */\n public function initialize()\n {\n%s\n }\n"; $templateFind = "\n /**\n * @return %s[]\n */\n public static function find(\$parameters = array())\n {\n return parent::find(\$parameters);\n }\n\n /**\n * @return %s\n */\n public static function findFirst(\$parameters = array())\n {\n return parent::findFirst(\$parameters);\n }\n"; $templateUse = 'use %s;'; $templateUseAs = 'use %s as %s;'; $templateCode = "<?php\n%s%s%s%s\nclass %s extends %s\n{\n%s\n}\n"; $methodRawCode = array(); $modelPath = $this->_options['directory'] . DIRECTORY_SEPARATOR . $this->_options['name'] . '.php'; if (file_exists($modelPath)) { if (!$this->_options['force']) { throw new \Exception("The model file '" . $this->_options['name'] . ".php' already exists in " . $this->_options['directory']); } } if (Tools::getDb()) { $dbConfig = Tools::getDb(); } if (!isset($dbConfig->adapter)) { throw new \Exception("Adapter was not found in the config. " . "Please specify a config variable [database][adapter]"); } if (isset($this->_options['namespace'])) { $namespace = PHP_EOL . PHP_EOL . 'namespace ' . $this->_options['namespace'] . ';' . PHP_EOL . PHP_EOL; $methodRawCode[] = sprintf($getSource, $this->_options['tableName']); } else { $namespace = ''; } $useSettersGetters = $this->_options['genSettersGetters']; if (isset($this->_options['genDocMethods'])) { $genDocMethods = $this->_options['genDocMethods']; } else { $genDocMethods = false; } $this->isSupportedAdapter($dbConfig->adapter); if (isset($dbConfig->adapter)) { $adapter = $dbConfig->adapter; } else { $adapter = 'Mysql'; } $configArray = $dbConfig->toArray(); // An array for use statements $uses = array(sprintf($templateUse, $this->_options['baseClass'])); $adapterName = '\\Phalcon\\Db\\Adapter\\Pdo\\' . $adapter; unset($configArray['adapter']); $db = new $adapterName($configArray); $initialize = array(); if (isset($this->_options['schema'])) { if ($this->_options['schema'] != $dbConfig->dbname) { $initialize[] = sprintf($templateThis, 'setSchema', '"' . $this->_options['schema'] . '"'); } $schema = $this->_options['schema']; } elseif ($adapter == 'Postgresql') { $schema = 'public'; $initialize[] = sprintf($templateThis, 'setSchema', '"' . $schema . '"'); } else { $schema = $dbConfig->dbname; } if ($this->_options['name'] != $this->_options['tableName']) { $initialize[] = sprintf($templateThis, 'setSource', '\'' . $this->_options['tableName'] . '\''); } $table = $this->_options['tableName']; if ($db->tableExists($table, $schema)) { $fields = $db->describeColumns($table, $schema); } else { throw new \Exception('Table "' . $table . '" does not exist'); } foreach ($db->listTables() as $tableName) { foreach ($db->describeReferences($tableName) as $reference) { if ($reference->getReferencedTable() == $this->_options['tableName']) { if (isset($this->_options['namespace'])) { $entityNamespace = "{$this->_options['namespace']}\\"; } else { $entityNamespace = ''; } $initialize[] = sprintf($templateRelation, 'hasMany', $reference->getReferencedColumns()[0], $entityNamespace . ucfirst($tableName), $reference->getColumns()[0], "array('alias' => '" . ucfirst($tableName) . "')"); } } } foreach ($db->describeReferences($this->_options['tableName']) as $reference) { if (isset($this->_options['namespace'])) { $entityNamespace = "{$this->_options['namespace']}\\"; } else { $entityNamespace = ''; } $initialize[] = sprintf($templateRelation, 'belongsTo', $reference->getColumns()[0], $entityNamespace . ucfirst($reference->getReferencedTable()), $reference->getReferencedColumns()[0], "array('alias' => '" . ucfirst($reference->getReferencedTable()) . "')"); } if (isset($this->_options['hasMany'])) { if (count($this->_options['hasMany'])) { foreach ($this->_options['hasMany'] as $relation) { if (is_string($relation['fields'])) { $entityName = $relation['camelizedName']; if (isset($this->_options['namespace'])) { $entityNamespace = "{$this->_options['namespace']}\\"; $relation['options']['alias'] = $entityName; } else { $entityNamespace = ''; } $initialize[] = sprintf($templateRelation, 'hasMany', $relation['fields'], $entityNamespace . $entityName, $relation['relationFields'], $this->_buildRelationOptions(isset($relation['options']) ? $relation["options"] : NULL)); } } } } if (isset($this->_options['belongsTo'])) { if (count($this->_options['belongsTo'])) { foreach ($this->_options['belongsTo'] as $relation) { if (is_string($relation['fields'])) { $entityName = $relation['referencedModel']; if (isset($this->_options['namespace'])) { $entityNamespace = "{$this->_options['namespace']}\\"; $relation['options']['alias'] = $entityName; } else { $entityNamespace = ''; } $initialize[] = sprintf($templateRelation, 'belongsTo', $relation['fields'], $entityNamespace . $entityName, $relation['relationFields'], $this->_buildRelationOptions(isset($relation['options']) ? $relation["options"] : NULL)); } } } } $alreadyInitialized = false; $alreadyValidations = false; if (file_exists($modelPath)) { try { $possibleMethods = array(); if ($useSettersGetters) { foreach ($fields as $field) { $methodName = Text::camelize($field->getName()); $possibleMethods['set' . $methodName] = true; $possibleMethods['get' . $methodName] = true; } } require_once $modelPath; $linesCode = file($modelPath); $fullClassName = $this->_options['namespace']; $reflection = new \ReflectionClass($fullClassName); foreach ($reflection->getMethods() as $method) { if ($method->getDeclaringClass()->getName() == $fullClassName) { $methodName = $method->getName(); if (!isset($possibleMethods[$methodName])) { $methodRawCode[$methodName] = join('', array_slice($linesCode, $method->getStartLine() - 1, $method->getEndLine() - $method->getStartLine() + 1)); } else { continue; } if ($methodName == 'initialize') { $alreadyInitialized = true; } else { if ($methodName == 'validation') { $alreadyValidations = true; } } } } } catch (\ReflectionException $e) { } } $validations = array(); foreach ($fields as $field) { if ($field->getType() === Column::TYPE_CHAR) { $domain = array(); if (preg_match('/\\((.*)\\)/', $field->getType(), $matches)) { foreach (explode(',', $matches[1]) as $item) { $domain[] = $item; } } if (count($domain)) { $varItems = join(', ', $domain); $validations[] = sprintf($templateValidateInclusion, $field->getName(), $varItems); } } if ($field->getName() == 'email') { $validations[] = sprintf($templateValidateEmail, $field->getName()); $uses[] = sprintf($templateUse, '\\Phalcon\\Mvc\\Model\\Validator\\Email'); } } if (count($validations)) { $validations[] = $templateValidationFailed; } /** * Check if there have been any excluded fields */ $exclude = array(); if (isset($this->_options['excludeFields'])) { if (!empty($this->_options['excludeFields'])) { $keys = explode(',', $this->_options['excludeFields']); if (count($keys) > 0) { foreach ($keys as $key) { $exclude[trim($key)] = ''; } } } } $attributes = array(); $setters = array(); $getters = array(); foreach ($fields as $field) { $type = $this->getPHPType($field->getType()); if ($useSettersGetters) { if (!array_key_exists(strtolower($field->getName()), $exclude)) { $attributes[] = sprintf($templateAttributes, $type, 'protected', $field->getName()); $setterName = Text::camelize($field->getName()); $setters[] = sprintf($templateSetter, $field->getName(), $type, $field->getName(), $setterName, $field->getName(), $field->getName(), $field->getName()); if (isset($this->_typeMap[$type])) { $getters[] = sprintf($templateGetterMap, $field->getName(), $type, $setterName, $field->getName(), $this->_typeMap[$type], $field->getName()); } else { $getters[] = sprintf($templateGetter, $field->getName(), $type, $setterName, $field->getName()); } } } else { $attributes[] = sprintf($templateAttributes, $type, 'public', $field->getName()); } } if ($alreadyValidations == false) { if (count($validations) > 0) { $validationsCode = sprintf($templateValidations, join('', $validations)); } else { $validationsCode = ''; } } else { $validationsCode = ''; } if ($alreadyInitialized == false) { if (count($initialize) > 0) { $initCode = sprintf($templateInitialize, rtrim(join('', $initialize))); } else { $initCode = ''; } } else { $initCode = ''; } $content = join('', $attributes); if ($useSettersGetters) { $content .= join('', $setters) . join('', $getters); } $content .= $validationsCode . $initCode; foreach ($methodRawCode as $methodCode) { $content .= $methodCode; } if ($genDocMethods) { $content .= sprintf($templateFind, $this->_options['name'], $this->_options['name']); } if (isset($this->_options['mapColumn'])) { $content .= $this->_genColumnMapCode($fields); } $str_use = implode(PHP_EOL, $uses) . PHP_EOL . PHP_EOL; $str_doc = '/** * Class ' . $this->_options['name'] . ' * @package ' . $this->_options['namespace'] . ' */'; $base = explode('\\', $this->_options['baseClass']); $baseClass = end($base); $code = sprintf($templateCode, Tools::getCopyright(), $namespace, $str_use, $str_doc, $this->_options['name'], $baseClass, $content); if (!@is_dir($this->_options['directory'])) { @mkdir($this->_options['directory']); @chmod($this->_options['directory'], 0777); } if (!@file_put_contents($modelPath, $code)) { throw new \Exception("Unable to write to '{$modelPath}'"); } @chmod($modelPath, 0777); }