diff options
author | Fabio Bas <ctrlaltca@gmail.com> | 2014-08-23 13:08:33 +0200 |
---|---|---|
committer | Fabio Bas <ctrlaltca@gmail.com> | 2014-08-23 13:08:33 +0200 |
commit | 0269aefc30d65ddb5d197bac7819feed5bf78de8 (patch) | |
tree | 785c3e8d7438e78fcca7bf2867620910515109b4 /framework/Wsat/TWsatARGenerator.php | |
parent | 8e4409a70876175ba8dc54e1a084c37a7861bfbf (diff) |
Manually backported Wsat
Diffstat (limited to 'framework/Wsat/TWsatARGenerator.php')
-rw-r--r-- | framework/Wsat/TWsatARGenerator.php | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/framework/Wsat/TWsatARGenerator.php b/framework/Wsat/TWsatARGenerator.php new file mode 100644 index 00000000..7ae5e46e --- /dev/null +++ b/framework/Wsat/TWsatARGenerator.php @@ -0,0 +1,283 @@ +<?php + +/** + * @author Daniel Sampedro Bello <darthdaniel85@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat + */ + +Prado::using('System.Data.Common.TDbMetaData'); + +class TWsatARGenerator +{ + + /** + * @return TDbMetaData for retrieving metadata information, such as + * table and columns information, from a database connection. + */ + private $_dbMetaData; + + /** + * Output folder where AR classes will be saved. + */ + private $_opFile; + + /** + * Class name prefix + */ + private $_clasPrefix; + + /** + * Class name sufix + */ + private $_classSufix; + + /** + * all table relations array + */ + private $_relations; + + /** + * unquote chars + * @var array + */ + private $uqChars = array('[', ']', '"', '`', "'"); + + function __construct() + { + if(!class_exists("TActiveRecordManager", false)) + throw new Exception("You need to enable the ActiveRecord module in your application configuration file."); + $ar_manager = TActiveRecordManager::getInstance(); + $_conn = $ar_manager->getDbConnection(); + $_conn->Active = true; + $this->_dbMetaData = TDbMetaData::getInstance($_conn); + } + + public function setOpFile($op_file_namespace) + { + $op_file = Prado::getPathOfNamespace($op_file_namespace); + if (empty($op_file)) + throw new Exception("You need to fix your output folder namespace."); + if (!is_dir($op_file)) + mkdir($op_file, 0777, true); + $this->_opFile = $op_file; + } + + public function setClasPrefix($_clas_prefix) + { + $this->_clasPrefix = $_clas_prefix; + } + + public function setClassSufix($_clas_sufix) + { + $this->_classSufix = $_clas_sufix; + } + +//----------------------------------------------------------------------------- + // <editor-fold defaultstate="collapsed" desc="Main APIs"> + public function generate($tableName) + { + $tableInfo = $this->_dbMetaData->getTableInfo($tableName); + $this->_commonGenerate($tableName, $tableInfo); + } + + public function generateAll() + { + foreach ($this->_dbMetaData->findTableNames() as $tableName) + { + if ($tableName == "pradocache") + continue; + $tableInfo = $this->_dbMetaData->getTableInfo($tableName); + if (!empty($this->_relations)) + { + // Cancel generation of M-M relationships middle table + if (count($tableInfo->getPrimaryKeys()) === 2 && count($tableInfo->getColumns()) === 2)//M-M relationships + continue; + } + $this->_commonGenerate($tableName, $tableInfo); + } + } + + public function buildRelations() + { + $this->_relations = array(); + foreach ($this->_dbMetaData->findTableNames() as $table_name) + { + $tableInfo = $this->_dbMetaData->getTableInfo($table_name); + $pks = $tableInfo->getPrimaryKeys(); + $fks = $tableInfo->getForeignKeys(); + + if (count($pks) === 2 && count($tableInfo->getColumns()) === 2)//M-M relationships + { + $table_name_mm = $fks[0]["table"]; + $table_name_mm2 = $fks[1]["table"]; + + $this->_relations[$table_name_mm][] = array( + "prop_name" => strtolower($table_name_mm2), + "rel_type" => "self::MANY_TO_MANY", + "ref_class_name" => $this->_getProperClassName($table_name_mm2), + "prop_ref" => $table_name + ); + + $this->_relations[$table_name_mm2][] = array( + "prop_name" => strtolower($table_name_mm), + "rel_type" => "self::MANY_TO_MANY", + "ref_class_name" => $this->_getProperClassName($table_name_mm), + "prop_ref" => $table_name + ); + continue; + } + foreach ($fks as $fk_data)//1-M relationships + { + $owner_table = $fk_data["table"]; + $slave_table = $table_name; + $fk_prop = key($fk_data["keys"]); + + $this->_relations[$owner_table][] = array( + "prop_name" => strtolower($slave_table), + "rel_type" => "self::HAS_MANY", + "ref_class_name" => $this->_getProperClassName($slave_table), + "prop_ref" => $fk_prop + ); + + $this->_relations[$slave_table][] = array( + "prop_name" => strtolower($owner_table), + "rel_type" => "self::BELONGS_TO", + "ref_class_name" => $this->_getProperClassName($owner_table), + "prop_ref" => $fk_prop + ); + } + } + } + +// </editor-fold> +//----------------------------------------------------------------------------- + // <editor-fold defaultstate="collapsed" desc="Common Methods"> + + private function _commonGenerate($tableName, $tableInfo) + { + if (count($tableInfo->getColumns()) === 0) + throw new Exception("Unable to find table or view $tableName in " . $this->_dbMetaData->getDbConnection()->getConnectionString() . "."); + else + { + $properties = array(); + foreach ($tableInfo->getColumns() as $field => $column) + $properties[] = $this->generateProperty($field, $column); + $toString = $this->_buildSmartToString($tableInfo); + } + + $clasName = $this->_getProperClassName($tableName); + $class = $this->generateClass($properties, $tableName, $clasName, $toString); + $output = $this->_opFile . DIRECTORY_SEPARATOR . $clasName . ".php"; + file_put_contents($output, $class); + } + + private function _getProperClassName($tableName) + { + $table_name_words = str_replace("_", " ", strtolower($tableName)); + $final_conversion = str_replace(" ", "", ucwords($table_name_words)); + return $this->_clasPrefix . $final_conversion . $this->_classSufix; + } + + public function renderAllTablesInformation() + { + foreach ($this->_dbMetaData->findTableNames() as $table_name) + { + echo $table_name . "<br>"; + + $tableInfo = $this->_dbMetaData->getTableInfo($table_name); + echo "Table info:" . "<br>"; + echo "<pre>"; + var_dump($tableInfo); + echo "</pre>"; + } + } + +//----------------------------------------------------------------------------- + + protected function generateProperty($field, $column) + { + $prop = ''; + $name = '$' . $field; + + /* TODO use in version 2.0 */ + // $type = $column->getPHPType(); + + $prop .= "\tpublic $name;"; + return $prop; + } + + private function _renderRelations($tablename) + { + if (!isset($this->_relations[$tablename])) + return ""; + + $code = "\tpublic static \$RELATIONS = array ("; + foreach ($this->_relations[$tablename] as $rel_data) + $code .= "\n\t\t'" . $rel_data["prop_name"] . "' => array(" . $rel_data["rel_type"] . ", '" . $rel_data["ref_class_name"] . "', '" . $rel_data["prop_ref"] . "'),"; + + $code = substr($code, 0, -1); + $code .= "\n\t);"; + return $code; + } + + private function _buildSmartToString($tableInfo) + { + $code = "\tpublic function __toString() {"; + $property = "throw new THttpException(500, 'Not implemented yet.');"; + try + { + foreach ($tableInfo->getColumns() as $column) + { + if (isset($column->IsPrimaryKey) && $column->IsPrimaryKey) + $property = str_replace($this->uqChars, "", $column->ColumnName); + elseif ($column->PdoType == PDO::PARAM_STR && $column->DBType != "date") + { + $property = str_replace($this->uqChars, "", $column->ColumnName); + break; + } + } + } catch (Exception $ex) + { + Prado::trace($ex->getMessage()); + } + $code .= "\n\t\treturn \$this->$property;"; + $code .= "\n\t}"; + return $code; + } + + protected function generateClass($properties, $tablename, $classname, $toString) + { + $props = implode("\n", $properties); + $relations = $this->_renderRelations($tablename); + $date = date('Y-m-d h:i:s'); + $env_user = getenv("username"); + return <<<EOD +<?php +/** + * Auto generated by PRADO - WSAT on $date. + * @author $env_user + */ +class $classname extends TActiveRecord +{ + const TABLE='$tablename'; + +$props + + public static function finder(\$className=__CLASS__) { + return parent::finder(\$className); + } + +$relations + +$toString +} +EOD; + } + +// </editor-fold> +}
\ No newline at end of file |