From 0269aefc30d65ddb5d197bac7819feed5bf78de8 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 23 Aug 2014 13:08:33 +0200 Subject: Manually backported Wsat --- framework/Wsat/TWsatARGenerator.php | 283 +++++++++++++++++++++ framework/Wsat/TWsatService.php | 81 ++++++ framework/Wsat/pages/TWsatGenerateAR.page | 56 ++++ framework/Wsat/pages/TWsatGenerateAR.php | 57 +++++ framework/Wsat/pages/TWsatHome.page | 17 ++ framework/Wsat/pages/TWsatHome.php | 17 ++ framework/Wsat/pages/TWsatLogin.page | 45 ++++ framework/Wsat/pages/TWsatLogin.php | 33 +++ framework/Wsat/pages/TWsatScaffolding.page | 3 + framework/Wsat/pages/TWsatScaffolding.php | 17 ++ framework/Wsat/pages/config.xml | 9 + framework/Wsat/pages/layout/TWsatLayout.php | 36 +++ framework/Wsat/pages/layout/TWsatLayout.tpl | 53 ++++ framework/Wsat/themes/.htaccess | 1 + framework/Wsat/themes/PradoSoft/imgs/arrowdown.gif | Bin 0 -> 836 bytes framework/Wsat/themes/PradoSoft/imgs/mantisbg.jpg | Bin 0 -> 4043 bytes framework/Wsat/themes/PradoSoft/imgs/pradologo.gif | Bin 0 -> 3039 bytes framework/Wsat/themes/PradoSoft/main.css | 152 +++++++++++ 18 files changed, 860 insertions(+) create mode 100644 framework/Wsat/TWsatARGenerator.php create mode 100644 framework/Wsat/TWsatService.php create mode 100644 framework/Wsat/pages/TWsatGenerateAR.page create mode 100644 framework/Wsat/pages/TWsatGenerateAR.php create mode 100644 framework/Wsat/pages/TWsatHome.page create mode 100644 framework/Wsat/pages/TWsatHome.php create mode 100644 framework/Wsat/pages/TWsatLogin.page create mode 100644 framework/Wsat/pages/TWsatLogin.php create mode 100644 framework/Wsat/pages/TWsatScaffolding.page create mode 100644 framework/Wsat/pages/TWsatScaffolding.php create mode 100644 framework/Wsat/pages/config.xml create mode 100644 framework/Wsat/pages/layout/TWsatLayout.php create mode 100644 framework/Wsat/pages/layout/TWsatLayout.tpl create mode 100644 framework/Wsat/themes/.htaccess create mode 100644 framework/Wsat/themes/PradoSoft/imgs/arrowdown.gif create mode 100644 framework/Wsat/themes/PradoSoft/imgs/mantisbg.jpg create mode 100644 framework/Wsat/themes/PradoSoft/imgs/pradologo.gif create mode 100644 framework/Wsat/themes/PradoSoft/main.css (limited to 'framework') 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 @@ + + * @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; + } + +//----------------------------------------------------------------------------- + // + 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 + ); + } + } + } + +// +//----------------------------------------------------------------------------- + // + + 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 . "
"; + + $tableInfo = $this->_dbMetaData->getTableInfo($table_name); + echo "Table info:" . "
"; + echo "
";
+                        var_dump($tableInfo);
+                        echo "
"; + } + } + +//----------------------------------------------------------------------------- + + 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 << +} \ No newline at end of file diff --git a/framework/Wsat/TWsatService.php b/framework/Wsat/TWsatService.php new file mode 100644 index 00000000..63bfebc7 --- /dev/null +++ b/framework/Wsat/TWsatService.php @@ -0,0 +1,81 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat + */ + +/** + * TWsatService class + * + * Wsat is inspired in both Asp.Net - Web Site Administration Tool(WSAT) and Yii's Gii. + * Wsat enables you to generate code saving your time in too many tedious tasks in a GUI fashion. + * + * Current options: + * 1- Generate one or all Active Record Classes from your DataBase. + * 1.1- Automatically generate all relations between the AR Classes (new). + * 1.2- Automatically generate the __toString() magic method in a smart way (new). + * + * To use TWsatService, configure it in the application configuration file like following: + * + * + * ... + * + * + * + * ...and then you need to go to http://localhost/yoursite/index.php?wsat=TWsatLogin + * and generate code and configure your site. + * + * Warning: You should only use Wsat in development mode. + */ +class TWsatService extends TPageService +{ + + private $_pass = ''; + + public function init($config) + { + if ($this->getApplication()->getMode() === TApplicationMode::Performance || $this->getApplication()->getMode() === TApplicationMode::Normal) + throw new TInvalidOperationException("You should not use Prado WSAT in any of the production modes."); + + if (empty($this->_pass)) + throw new TConfigurationException("You need to specify the Password attribute."); + + $this->setDefaultPage("TWsatHome"); + $this->_startThemeManager(); + parent::init($config); + } + + public function getBasePath() + { + $basePath = Prado::getPathOfNamespace("System.Wsat.pages"); + return realpath($basePath); + } + + private function _startThemeManager() + { + $themeManager = new TThemeManager; + $themeManager->BasePath = "System.Wsat.themes"; + $url = Prado::getApplication()->getAssetManager()->publishFilePath(Prado::getPathOfNamespace('System.Wsat')); + $themeManager->BaseUrl = "$url/themes"; + + $themeManager->init(null); + $this->setThemeManager($themeManager); + } + + public function getPassword() + { + return $this->_pass; + } + + public function setPassword($_pass) + { + $this->_pass = $_pass; + } + +} \ No newline at end of file diff --git a/framework/Wsat/pages/TWsatGenerateAR.page b/framework/Wsat/pages/TWsatGenerateAR.page new file mode 100644 index 00000000..926d6b0f --- /dev/null +++ b/framework/Wsat/pages/TWsatGenerateAR.page @@ -0,0 +1,56 @@ + +
Active Record Classes Generator
+
+
+ +
+
+
    +
  • If you want to generate all AR Classes, keep the "Table Name" field as appears by default.
  • +
  • "Output Folder" field refers to the directory that the new AR class file should be generated under... where Application refers to the protected folder of your project. You can let this default field value and PRADO will create the proper folders for you.
  • +
+
+
+ +
+
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + + + +
+
+ + +
+
+ +
diff --git a/framework/Wsat/pages/TWsatGenerateAR.php b/framework/Wsat/pages/TWsatGenerateAR.php new file mode 100644 index 00000000..f0ce8430 --- /dev/null +++ b/framework/Wsat/pages/TWsatGenerateAR.php @@ -0,0 +1,57 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat.pages + */ +Prado::using("System.Wsat.TWsatARGenerator"); + +class TWsatGenerateAR extends TPage +{ + + public function generate($sender) + { + if ($this->IsValid) + { + $tableName = $this->table_name->Text; + $outputFolderNs = $this->output_folder->Text; + $classPrefix = $this->class_prefix->Text; + $classSuffix = $this->class_suffix->Text; + + try + { + $ar_generator = new TWsatARGenerator(); + $ar_generator->setOpFile($outputFolderNs); + $ar_generator->setClasPrefix($classPrefix); + $ar_generator->setClassSufix($classSuffix); + + if ($this->build_rel->Checked) + $ar_generator->buildRelations(); + + if ($tableName != "*") + $ar_generator->generate($tableName); + else + $ar_generator->generateAll(); + + $this->feedback_panel->CssClass = "green_panel"; + $this->generation_msg->Text = "The code has been generated successfully."; + } catch (Exception $ex) + { + $this->feedback_panel->CssClass = "red_panel"; + $this->generation_msg->Text = $ex->getMessage(); + } + $this->feedback_panel->Visible = true; + } + } + + public function preview($sender) + { +// throw new THttpException(500, "Not implemented yet."); + } + +} \ No newline at end of file diff --git a/framework/Wsat/pages/TWsatHome.page b/framework/Wsat/pages/TWsatHome.page new file mode 100644 index 00000000..e8796ccd --- /dev/null +++ b/framework/Wsat/pages/TWsatHome.page @@ -0,0 +1,17 @@ + + + +
Application Dir: <%= Prado::getPathOfNamespace('Application') %>
+ +
+ + + + + +
+ + + Enables you to generate all Active Record Classes with relations included. +
+
diff --git a/framework/Wsat/pages/TWsatHome.php b/framework/Wsat/pages/TWsatHome.php new file mode 100644 index 00000000..b5ae1bb4 --- /dev/null +++ b/framework/Wsat/pages/TWsatHome.php @@ -0,0 +1,17 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat.pages + */ +Prado::using("System.Wsat.TWsatARGenerator"); + +class TWsatHome extends TPage +{ + +} \ No newline at end of file diff --git a/framework/Wsat/pages/TWsatLogin.page b/framework/Wsat/pages/TWsatLogin.page new file mode 100644 index 00000000..79578f59 --- /dev/null +++ b/framework/Wsat/pages/TWsatLogin.page @@ -0,0 +1,45 @@ +<%@ MasterClass="" %> + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Wsat/pages/TWsatLogin.php b/framework/Wsat/pages/TWsatLogin.php new file mode 100644 index 00000000..21994c07 --- /dev/null +++ b/framework/Wsat/pages/TWsatLogin.php @@ -0,0 +1,33 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat.pages + */ +class TWsatLogin extends TPage +{ + + public function login() + { + if ($this->IsValid) + { + $this->Session["wsat_password"] = $this->getService()->getPassword(); + + $url = $this->Service->constructUrl('TWsatHome'); + $this->Response->redirect($url); + } + } + + public function validatePassword($sender, $param) + { + $config_pass = $this->Service->Password; + $user_pass = $this->password->Text; + $param->IsValid = $user_pass === $config_pass; + } + +} \ No newline at end of file diff --git a/framework/Wsat/pages/TWsatScaffolding.page b/framework/Wsat/pages/TWsatScaffolding.page new file mode 100644 index 00000000..42f78d09 --- /dev/null +++ b/framework/Wsat/pages/TWsatScaffolding.page @@ -0,0 +1,3 @@ + + Scaffolding will be avaliable in Prado 3.4 + diff --git a/framework/Wsat/pages/TWsatScaffolding.php b/framework/Wsat/pages/TWsatScaffolding.php new file mode 100644 index 00000000..b8e28b03 --- /dev/null +++ b/framework/Wsat/pages/TWsatScaffolding.php @@ -0,0 +1,17 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @since 3.3 + * @package Wsat.pages + */ +Prado::using("System.Wsat.TWsatARGenerator"); + +class TWsatScaffolding extends TPage +{ + +} \ No newline at end of file diff --git a/framework/Wsat/pages/config.xml b/framework/Wsat/pages/config.xml new file mode 100644 index 00000000..727e8eab --- /dev/null +++ b/framework/Wsat/pages/config.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/framework/Wsat/pages/layout/TWsatLayout.php b/framework/Wsat/pages/layout/TWsatLayout.php new file mode 100644 index 00000000..67caa77d --- /dev/null +++ b/framework/Wsat/pages/layout/TWsatLayout.php @@ -0,0 +1,36 @@ +validateSecurity(); + } + + private function validateSecurity() + { + if ($this->Session["wsat_password"] !== $this->getService()->getPassword()) + { + if (!$this->getPage() instanceof TWsatLogin) + { + $url = $this->Service->constructUrl('TWsatLogin'); + $this->Response->redirect($url); + } + } + } + + public function logout() + { + $this->Session["wsat_password"] = ""; + $url = $this->Service->constructUrl('TWsatLogin'); + $this->Response->redirect($url); + } + +} \ No newline at end of file diff --git a/framework/Wsat/pages/layout/TWsatLayout.tpl b/framework/Wsat/pages/layout/TWsatLayout.tpl new file mode 100644 index 00000000..d91ff333 --- /dev/null +++ b/framework/Wsat/pages/layout/TWsatLayout.tpl @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + +
+
+
+
Code Generation
+
    +
  • +
  • +
+
+
+ +
+ +
+ +
+
+ + +
+ + \ No newline at end of file diff --git a/framework/Wsat/themes/.htaccess b/framework/Wsat/themes/.htaccess new file mode 100644 index 00000000..f7661d04 --- /dev/null +++ b/framework/Wsat/themes/.htaccess @@ -0,0 +1 @@ +allow from all diff --git a/framework/Wsat/themes/PradoSoft/imgs/arrowdown.gif b/framework/Wsat/themes/PradoSoft/imgs/arrowdown.gif new file mode 100644 index 00000000..1b508cd6 Binary files /dev/null and b/framework/Wsat/themes/PradoSoft/imgs/arrowdown.gif differ diff --git a/framework/Wsat/themes/PradoSoft/imgs/mantisbg.jpg b/framework/Wsat/themes/PradoSoft/imgs/mantisbg.jpg new file mode 100644 index 00000000..ee06998d Binary files /dev/null and b/framework/Wsat/themes/PradoSoft/imgs/mantisbg.jpg differ diff --git a/framework/Wsat/themes/PradoSoft/imgs/pradologo.gif b/framework/Wsat/themes/PradoSoft/imgs/pradologo.gif new file mode 100644 index 00000000..3b073b80 Binary files /dev/null and b/framework/Wsat/themes/PradoSoft/imgs/pradologo.gif differ diff --git a/framework/Wsat/themes/PradoSoft/main.css b/framework/Wsat/themes/PradoSoft/main.css new file mode 100644 index 00000000..9970c88b --- /dev/null +++ b/framework/Wsat/themes/PradoSoft/main.css @@ -0,0 +1,152 @@ +html, body{ + margin: 0px; + padding: 0px; + font-family: 'Lucida Grande', Verdana, Geneva, Lucida, Helvetica, Arial, sans-serif; + font-weight: normal; +} + +#header { + font-size:25px; + font-weight:bold; + color: #666; +} + +.logo{ + width: 204px; + height:100px; + background-image: url('imgs/pradologo.gif'); + background-repeat: no-repeat; + float: left; +} + +.mantisbg{ + width: 221px; + height: 100px; + background-image: url('imgs/mantisbg.jpg'); + background-repeat: no-repeat; + float: right; +} + +.mainmenu { + padding:10px; + padding-right:10px; + background:#EDEDED; + border-bottom: 1px solid #A6A6A6; + border-top: 1px solid #DCDCDC; + color:white; + text-align:right; + font-size: 10pt; +} + +.mainmenu a { + color:#737373; + text-decoration:none; +} + +.mainmenu a:hover { + color: #FF0000; +} + +#toc { + background-color: #F3F3F3; + width:220px; + padding:0px 10px 0px 10px; + float: left; +} + +#content { + padding: 1em 1em 1em 1em; + line-height: 135%; + float: left; + width: 700px; +} + +.topic { + font-size: 9pt; + padding: 0px 0px 0px 0px; +} + +.topic div { + background-image: url('imgs/arrowdown.gif'); + background-repeat: no-repeat; + background-position: left center; + margin: 0px; + font-size: 8pt; + font-weight:bold; + color:#2A480A; + padding: 5px; + padding-left: 15px; + border-top: 1px solid #fff; + border-bottom: 1px solid #E2E2E2; +} + +.topic ul +{ + margin: 0px; + padding: 0px; +} + +.topic ul li +{ + list-style: none; + margin: 0px; + padding: 5px; + padding-left: 15px; + border-bottom: 1px dotted #D8D8D8; +} + +.topic a { + color:#4F811A; + font-size: 8pt; + text-decoration: none; +} + +.topic a:hover { + color:#2A480A; +} + +/* form styles */ +.form_row{ + margin: 10px; +} + +.in_text{ + width: 250px; +} + +.login_form{ + text-align: center; + margin: 30px auto; + border: 1px solid red; + border-radius: 5px; + padding: 10px; + width: 250px; + font-size: 11px; +} + +.green_panel{ + background-color: #C5FBBD; + border: 1px solid #76C376; + padding: 10px; + margin: 10px 0; + border-radius: 5px; + text-align: center; +} + +.red_panel{ + background-color: #ff6666; + border: 1px solid red; + padding: 10px; + margin: 10px 0; + border-radius: 5px; + text-align: center; +} + +#footer { + clear:both; + color: gray; + font-size:8pt; + text-align:center; + margin-top:25px; + padding:10px; +} \ No newline at end of file -- cgit v1.2.3