Quellcode durchsuchen

init

tags/0.1.0
Robin Thoni vor 9 Jahren
Commit
212d213dc1

+ 3
- 0
.gitignore Datei anzeigen

@@ -0,0 +1,3 @@
1
+/.idea
2
+/composer.lock
3
+/vendor

+ 20
- 0
composer.json Datei anzeigen

@@ -0,0 +1,20 @@
1
+{
2
+    "name": "luticate/generator",
3
+    "description": "Luticate user management system code generator",
4
+    "authors": [
5
+        {
6
+            "name": "Robin THONI",
7
+            "email": "robin@rthoni.com"
8
+        }
9
+    ],
10
+    "require-dev": {
11
+      "laravel/lumen-framework": "5.1.x-dev",
12
+      "vlucas/phpdotenv": "~1.0",
13
+      "twig/twig": "1.x-dev"
14
+    },
15
+    "autoload": {
16
+      "psr-4": {
17
+        "Luticate\\": "src/"
18
+      }
19
+    }
20
+}

+ 269
- 0
src/Generator/LuGenerator.php Datei anzeigen

@@ -0,0 +1,269 @@
1
+<?php
2
+
3
+namespace Luticate\Generator;
4
+
5
+use PDO;
6
+use Twig_Autoloader;
7
+use Twig_Environment;
8
+use Twig_Loader_Filesystem;
9
+
10
+class LuGenerator {
11
+    private $_pdo;
12
+
13
+    public function __construct($db_connection, $db_database, $db_host, $db_port, $db_username, $db_password)
14
+    {
15
+        $dsn = $db_connection . ":dbname=" . $db_database . ";host="
16
+            . $db_host . ";port=" . $db_port;
17
+        $this->_pdo = new PDO($dsn, $db_username, $db_password);
18
+    }
19
+
20
+    protected function printError($query, $message)
21
+    {
22
+        echo $message . "\n";
23
+        var_dump($query->errorInfo());
24
+        var_dump($this->_pdo->errorInfo());
25
+        return null;
26
+    }
27
+
28
+    protected function buildTwigVars($vars)
29
+    {
30
+        foreach ($vars as $key => $value)
31
+        {
32
+            if (is_array($value))
33
+                $vars[$key] = $this->buildTwigVars($value);
34
+            else if (is_string($value))
35
+            {
36
+                $vars[$key] = array(
37
+                    "as_it" => $value,
38
+                    "camel_upper" => $this->snakeToCamelCase($value, true),
39
+                    "camel_lower" => $this->snakeToCamelCase($value, false)
40
+                );
41
+            }
42
+        }
43
+        return $vars;
44
+    }
45
+
46
+    protected function buildTwig($templateFile, $destFile, $vars)
47
+    {
48
+        $twig_vars = $this->buildTwigVars($vars);
49
+
50
+        Twig_Autoloader::register();
51
+        $loader = new Twig_Loader_Filesystem(__DIR__ );
52
+        $twig = new Twig_Environment($loader, array());
53
+        $template = $twig->loadTemplate($templateFile . '.twig');
54
+        $content = $template->render($twig_vars);
55
+        file_put_contents($destFile, $content);
56
+    }
57
+
58
+    public function getTables()
59
+    {
60
+        $tablesQuery = $this->_pdo->prepare("SELECT table_name
61
+FROM information_schema.tables
62
+WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')");
63
+        if ($tablesQuery->execute(array())) {
64
+            $tables = $tablesQuery->fetchAll();
65
+            echo "Found " . count($tables) . " tables\n";
66
+            return $tables;
67
+        }
68
+        else
69
+            return $this->printError($tablesQuery, "Failed to get tables");
70
+    }
71
+
72
+    public function getColumns($table_name)
73
+    {
74
+        $columnsQuery = $this->_pdo->prepare("SELECT column_name as name, data_type as data_type FROM information_schema.columns WHERE table_name = :table_name");
75
+        if ($columnsQuery->execute(array(":table_name" => $table_name)))
76
+        {
77
+            $columns = $columnsQuery->fetchAll();
78
+            echo "Found " . count($columns) . " columns in table " . $table_name . "\n";
79
+            return $columns;
80
+        }
81
+        else
82
+            return $this->printError($columnsQuery, "Failed to get columns from " . $table_name);
83
+    }
84
+
85
+    function snakeToCamelCase($string, $capitalizeFirstCharacter) {
86
+        $str = preg_replace_callback("/_[a-zA-Z]/", function($matches)
87
+        {
88
+            return strtoupper($matches[0][1]);
89
+        }, $string);
90
+        if ($capitalizeFirstCharacter)
91
+            $str[0] = strtoupper($str[0]);
92
+        return $str;
93
+    }
94
+
95
+    public function sqlTypeToPhpType($type)
96
+    {
97
+        if ($type == "character" || $type == "character varying")
98
+            return "string";
99
+        return $type;
100
+    }
101
+
102
+    public function sqlTypesToPhpTypes($array)
103
+    {
104
+        foreach ($array as $key => $value)
105
+        {
106
+            $array[$key]["data_type"] = array(
107
+                "sql" => $array[$key]["data_type"],
108
+                "php" => $this->sqlTypeToPhpType($array[$key]["data_type"])
109
+            );
110
+        }
111
+        return $array;
112
+    }
113
+
114
+    public function generateDbo($name, $columns, $file)
115
+    {
116
+        $vars = array(
117
+            "dbo_name" => $name,
118
+            "columns" => $columns
119
+        );
120
+        $this->buildTwig('dbo.php', $file, $vars);
121
+    }
122
+
123
+    public function generateModel($modelName, $dboName, $columns, $file)
124
+    {
125
+        $vars = array(
126
+            "model_name" => $modelName,
127
+            "dbo_name" => $dboName,
128
+            "columns" => $columns
129
+        );
130
+        $this->buildTwig('model.php', $file, $vars);
131
+    }
132
+
133
+    public function getStoredProcedures()
134
+    {
135
+        $spQuery = $this->_pdo->prepare("SELECT r.routine_name AS sp_name, r.data_type AS data_type, proc.proretset AS proretset
136
+FROM information_schema.routines r
137
+LEFT JOIN pg_catalog.pg_proc proc ON proc.proname = r.routine_name
138
+WHERE r.specific_schema='public'");
139
+        if ($spQuery->execute())
140
+        {
141
+            $sp = $spQuery->fetchAll();
142
+            echo "Found " . count($sp) . " stored procedures\n";
143
+            return $sp;
144
+        }
145
+        else
146
+            return $this->printError($spQuery, "Failed to get stored procedures");
147
+    }
148
+
149
+    public function getStoredProceduresArguments($sp)
150
+    {
151
+        $sp_name = $sp["sp_name"];
152
+        $spQuery = $this->_pdo->prepare("SELECT parameters.parameter_name as name, parameters.data_type, parameters.parameter_mode
153
+FROM information_schema.routines
154
+JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
155
+WHERE routines.specific_schema='public' AND routines.routine_name = :sp_name
156
+ORDER BY parameters.ordinal_position;");
157
+        if ($spQuery->execute(array("sp_name" => $sp_name)))
158
+        {
159
+            $sp_ = $spQuery->fetchAll();
160
+            $sps = array("in" => array(), "out" => array());
161
+            foreach ($sp_ as $p)
162
+                $sps[strtolower($p["parameter_mode"])][] = $p;
163
+            $out_count = count($sps['out']);
164
+            if ($out_count == 0)
165
+            {
166
+                $sps['out'][] = array(
167
+                    "name" => $sp_name,
168
+                    "data_type" => $sp["data_type"],
169
+                    "parameter_mode" => "OUT"
170
+                );
171
+                $out_count = 1;
172
+            }
173
+            echo "Found " . count($sps['in']) . " input arguments for stored procedure " . $sp_name . "\n";
174
+            echo "Found " . $out_count . " output arguments for stored procedure " . $sp_name . "\n";
175
+            return $sps;
176
+        }
177
+        else
178
+            return $this->printError($spQuery, "Failed to get arguments for stored procedure " . $sp_name);
179
+    }
180
+
181
+    public function generateSp($sp, $args, $file)
182
+    {
183
+        $vars = array(
184
+            "sp" => $sp,
185
+            "args" => $args
186
+        );
187
+        $this->buildTwig('sp.php', $file, $vars);
188
+    }
189
+
190
+    public function generateDataAccess($dataAccessName, $modelName, $dboName, $file)
191
+    {
192
+        if (file_exists($file))
193
+            return;
194
+        $vars = array(
195
+            "data_access_name" => $dataAccessName,
196
+            "model_name" => $modelName,
197
+            "dbo_name" => $dboName
198
+        );
199
+        $this->buildTwig('dataaccess.php', $file, $vars);
200
+    }
201
+
202
+    public function generateBusiness($businessName, $dataAccessName, $dboName, $file)
203
+    {
204
+        if (file_exists($file))
205
+            return;
206
+        $vars = array(
207
+            "business_name" => $businessName,
208
+            "data_access_name" => $dataAccessName,
209
+            "dbo_name" => $dboName
210
+        );
211
+        $this->buildTwig('business.php', $file, $vars);
212
+    }
213
+
214
+    public function mkdir($dir, $dir_mode)
215
+    {
216
+        if (!file_exists($dir))
217
+            mkdir($dir, $dir_mode, true);
218
+    }
219
+
220
+    public function run($dir_mode, $dbo_dir, $model_dir, $sp_dir, $manager_dir, $business_dir)
221
+    {
222
+        $dbo_dir .= "/";
223
+        $model_dir .= "/";
224
+        $sp_dir .= "/";
225
+        $manager_dir .= "/";
226
+        $business_dir .= "/";
227
+
228
+        $this->mkdir($dbo_dir, $dir_mode);
229
+        $this->mkdir($model_dir, $dir_mode);
230
+        $this->mkdir($sp_dir, $dir_mode);
231
+        $this->mkdir($manager_dir, $dir_mode);
232
+        $this->mkdir($business_dir, $dir_mode);
233
+
234
+        $tables = $this->getTables();
235
+        if (!is_null($tables)) {
236
+            foreach ($tables as $table) {
237
+                $table_name = $table["table_name"];
238
+                $columns = $this->getColumns($table_name);
239
+                if (is_null($columns))
240
+                    continue;
241
+                $columns = $this->sqlTypesToPhpTypes($columns);
242
+                $baseName = $this->snakeToCamelCase($table_name, true);
243
+                $modelName = $baseName;
244
+                $dboName = $baseName . "Dbo";
245
+                $dataAccessName = $baseName . "DataAccess";
246
+                $businessName = $baseName . "Business";
247
+                $this->generateDbo($dboName, $columns, $dbo_dir . $dboName . ".php");
248
+                $this->generateModel($modelName, $dboName, $columns, $model_dir . $modelName . ".php");
249
+                $this->generateDataAccess($dataAccessName, $modelName, $dboName, $manager_dir . $dataAccessName . ".php");
250
+                $this->generateBusiness($businessName, $dataAccessName, $dboName, $business_dir . $businessName . ".php");
251
+            }
252
+        }
253
+        $sps = $this->getStoredProcedures();
254
+        if (!is_null($sps)) {
255
+            foreach ($sps as $sp)
256
+            {
257
+                $sp_name = $sp["sp_name"];
258
+                $args = $this->getStoredProceduresArguments($sp);
259
+                if (is_null($args))
260
+                    continue;
261
+                $args["in"] = $this->sqlTypesToPhpTypes($args["in"]);
262
+                $args["out"] = $this->sqlTypesToPhpTypes($args["out"]);
263
+                $sp_model_name = $this->snakeToCamelCase($sp_name, true);
264
+                $this->generateSp($sp, $args, $sp_dir . $sp_model_name . ".php");
265
+            }
266
+        }
267
+    }
268
+}
269
+

+ 14
- 0
src/Generator/business.php.twig Datei anzeigen

@@ -0,0 +1,14 @@
1
+{{ "<?php" }}
2
+
3
+namespace App\Http\Business;
4
+
5
+use Luticate\Utils\LuBusiness;
6
+use App\Http\DataAccess\{{ data_access_name.as_it }};
7
+use App\Http\DBO\{{ dbo_name.as_it }};
8
+
9
+class {{ business_name.as_it }} extends LuBusiness {
10
+    public function __construct()
11
+    {
12
+        $this->dataAccess = new {{ data_access_name.as_it }}();
13
+    }
14
+}

+ 15
- 0
src/Generator/dataaccess.php.twig Datei anzeigen

@@ -0,0 +1,15 @@
1
+{{ "<?php" }}
2
+
3
+namespace App\Http\DataAccess;
4
+
5
+use Luticate\Utils\LuDataAccess;
6
+use App\Http\DataAccess\Models\{{ model_name.as_it }};
7
+use App\Http\DBO\{{ dbo_name.as_it }};
8
+
9
+class {{ data_access_name.as_it }} extends LuDataAccess {
10
+    public function __construct()
11
+    {
12
+        parent::__construct();
13
+        $this->model = new {{ model_name.as_it }}();
14
+    }
15
+}

+ 32
- 0
src/Generator/dbo.php.twig Datei anzeigen

@@ -0,0 +1,32 @@
1
+{{ "<?php" }}
2
+
3
+namespace App\Http\DBO;
4
+
5
+use Luticate\Utils\LuDbo;
6
+
7
+class {{ dbo_name.camel_upper }} extends LuDbo {
8
+
9
+    public function jsonSerialize()
10
+    {
11
+        return array(
12
+{% for column in columns %}
13
+            "{{ column.name.camel_upper }}" => $this->_{{ column.name.camel_lower }}{{ loop.last ? "" : "," }}
14
+{% endfor %}
15
+        );
16
+    }
17
+{% for column in columns %}
18
+
19
+    /**
20
+     * @var {{ column.data_type.php.as_it }}
21
+     */
22
+    protected $_{{ column.name.camel_lower }};
23
+    public function get{{ column.name.camel_upper }}()
24
+    {
25
+        return $this->_{{ column.name.camel_lower }};
26
+    }
27
+    public function set{{ column.name.camel_upper }}($value)
28
+    {
29
+        $this->_{{ column.name.camel_lower }} = $value;
30
+    }
31
+{% endfor %}
32
+}

+ 43
- 0
src/Generator/model.php.twig Datei anzeigen

@@ -0,0 +1,43 @@
1
+{{ "<?php" }}
2
+
3
+namespace App\Http\DataAccess\Models;
4
+
5
+use Luticate\Utils\LuModel;
6
+use App\Http\DBO\{{ dbo_name.camel_upper }};
7
+
8
+class {{ model_name.camel_upper }} extends LuModel
9
+{
10
+    function __construct()
11
+    {
12
+        parent::__construct();
13
+        $this->timestamps = false;
14
+    }
15
+
16
+    public function toDbo()
17
+    {
18
+        $dbo = new {{ dbo_name.camel_upper }}();
19
+
20
+{% for column in columns %}
21
+        $dbo->set{{ column.name.camel_upper }}($this->{{ column.name.as_it }});
22
+{% endfor %}
23
+
24
+        return $dbo;
25
+    }
26
+
27
+    /**
28
+     * @param $dbo \App\Http\DBO\{{ dbo_name.camel_upper }}
29
+     * @param $dam LuModel|null
30
+     * @return {{ model_name.camel_upper }}
31
+     */
32
+    public function fromDbo($dbo, $dam = null)
33
+    {
34
+        if (is_null($dam))
35
+            $dam = new {{ model_name.camel_upper }}();
36
+
37
+{% for column in columns %}
38
+        $dam->{{ column.name.as_it }} = $dbo->get{{ column.name.camel_upper }}();
39
+{% endfor %}
40
+
41
+        return $dam;
42
+    }
43
+}

+ 50
- 0
src/Generator/sp.php.twig Datei anzeigen

@@ -0,0 +1,50 @@
1
+{{ "<?php" }}
2
+
3
+namespace App\Http\DataAccess\SP;
4
+
5
+use Luticate\Utils\LuSpModel;
6
+use Illuminate\Support\Facades\DB;
7
+
8
+class {{ sp.sp_name.camel_upper }} extends LuSpModel {
9
+
10
+    protected static function damToDbo($dam)
11
+    {
12
+        if (is_null($dam))
13
+            return null;
14
+        $dbo = new {{ sp.sp_name.camel_upper }}();
15
+
16
+{% for arg in args.out %}
17
+        $dbo->set{{ arg.name.camel_upper }}($dam->{{ arg.name.as_it }});
18
+{% endfor %}
19
+
20
+        return $dbo;
21
+    }
22
+
23
+    public static function execute({% for arg in args.in %}${{ arg.name.as_it }}{{ loop.last ? "" : ", " }}{% endfor %})
24
+    {
25
+        $values = DB::select('SELECT * FROM {{ sp.sp_name.as_it }}({% for arg in args.in %}?{{ loop.last ? "" : ", " }}{% endfor %})', array({% for arg in args.in %}${{ arg.name.as_it }}{{ loop.last ? "" : ", " }}{% endfor %}));
26
+{% if sp.proretset %}
27
+        $dboValues = array();
28
+        foreach ($values as $value)
29
+            $dboValues[] = self::damToDbo($value);
30
+        return $dboValues;
31
+{% else %}
32
+        return self::damToDbo($values[0]);
33
+{% endif %}
34
+    }
35
+{% for arg in args.out %}
36
+
37
+    /**
38
+    * @var {{ arg.data_type.php.as_it }}
39
+    */
40
+    protected $_{{ arg.name.camel_lower }};
41
+    public function get{{ arg.name.camel_upper }}()
42
+    {
43
+        return $this->_{{ arg.name.camel_lower }};
44
+    }
45
+    public function set{{ arg.name.camel_upper }}($value)
46
+    {
47
+        $this->_{{ arg.name.camel_lower }} = $value;
48
+    }
49
+{% endfor %}
50
+}

Laden…
Abbrechen
Speichern