1+ <?php
2+
3+ declare (strict_types=1 );
4+ /**
5+ * This file is part of Hyperf.
6+ *
7+ * @link https://www.hyperf.io
8+ * @document https://doc.hyperf.io
9+ * @contact group@hyperf.io
10+ * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+ */
12+
13+ namespace HPlus \DevTool \Command ;
14+
15+ use HPlus \UI \Form \Model ;
16+ use HPlus \Validate \Validate ;
17+ use Hyperf \Command \Annotation \Command ;
18+ use Hyperf \Contract \ConfigInterface ;
19+ use Hyperf \Database \Schema \Schema ;
20+ use Hyperf \DbConnection \Db ;
21+ use Hyperf \Utils \ApplicationContext ;
22+ use Hyperf \Utils \Arr ;
23+ use Hyperf \Utils \CodeGen \Project ;
24+ use Hyperf \Utils \Str ;
25+ use Psr \Container \ContainerInterface ;
26+ use Symfony \Component \Console \Input \InputArgument ;
27+ use Symfony \Component \Console \Input \InputInterface ;
28+ use Symfony \Component \Console \Input \InputOption ;
29+ use Symfony \Component \Console \Output \OutputInterface ;
30+
31+ use Nette \PhpGenerator \ClassType ;
32+ use Nette \PhpGenerator \Helpers ;
33+ use Nette \PhpGenerator \Literal ;
34+ use Nette \PhpGenerator \Method ;
35+ use Nette \PhpGenerator \Parameter ;
36+ use Nette \PhpGenerator \PhpNamespace ;
37+ use Nette \PhpGenerator \PsrPrinter ;
38+
39+ /**
40+ * @Command
41+ */
42+ class ValidateCommand extends GeneratorCommand
43+ {
44+
45+ public function __construct ()
46+ {
47+ parent ::__construct ('gen:validation ' );
48+ $ this ->setDescription ('Create a new validate class ' );
49+ }
50+
51+ /**
52+ * Get the console command options.
53+ *
54+ * @return array
55+ */
56+ protected function getOptions ()
57+ {
58+ return [
59+ ['name ' , 'd ' , InputOption::VALUE_OPTIONAL , 'desc ' , '' ],
60+ ['force ' , 'f ' , InputOption::VALUE_NONE , 'Whether force to rewrite. ' ],
61+ ['namespace ' , 'N ' , InputOption::VALUE_OPTIONAL , 'The namespace for class. ' , null ],
62+ ];
63+ }
64+
65+ /**
66+ * Execute the console command.
67+ *
68+ * @return int
69+ */
70+ public function execute (InputInterface $ input , OutputInterface $ output )
71+ {
72+ $ this ->input = $ input ;
73+ $ this ->output = $ output ;
74+ $ class_name = $ this ->getNameInput ();
75+ $ class_name = ucfirst ($ class_name );
76+ $ model_name = ucfirst ($ class_name );
77+
78+ $ name = $ this ->qualifyClass ($ class_name );
79+ try {
80+ $ path = $ this ->getPath ($ name );
81+ } catch (\RuntimeException $ exception ) {
82+ $ output ->writeln (sprintf ('<fg=red>%s</> ' , $ name . ' 命名空间不存在! ' ));
83+ return 0 ;
84+ }
85+
86+ $ table = Schema::getColumnTypeListing ($ this ->getNameInput ());
87+ #验证是否已经存在了。存在就不能在搞了。不然会覆盖,如果想重新生成加force可以强制覆盖
88+ if (($ input ->getOption ('force ' ) === false ) && $ this ->alreadyExists ($ this ->getNameInput ())) {
89+ $ output ->writeln (sprintf ('<fg=red>%s</> ' , $ class_name . ' already exists! ' ));
90+ return 0 ;
91+ }
92+ #对应模型存在才会创建
93+ if (!$ table ) {
94+ $ output ->writeln (sprintf ('<fg=red>%s</> ' , $ class_name . '数据表不存在,请确认表名称是否正确! ' ));
95+ return 0 ;
96+ }
97+ $ rule = [
98+ 'limit ' => 'integer ' ,
99+ 'page ' => 'integer '
100+ ];
101+ $ field = [
102+ 'limit ' => '条数限制 ' ,
103+ 'page ' => '分页ID '
104+ ];
105+ $ scene = [];
106+ $ sceneTmp = [];
107+ foreach ($ table as $ item ) {
108+ $ rule [$ item ['column_name ' ]] = $ this ->getRule ($ item );
109+ $ field [$ item ['column_name ' ]] = $ item ['column_comment ' ];
110+ $ sceneTmp [] = $ item ['column_name ' ];
111+ }
112+
113+ $ scene ['create ' ] = $ sceneTmp ;
114+ $ scene ['update ' ] = $ sceneTmp ;
115+ $ scene ['delete ' ] = 'id ' ;
116+ $ scene ['list ' ] = ['limit ' , 'page ' ];
117+ $ class_name = $ class_name . 'Validate ' ;
118+ $ namespacePath = $ namespaceInput ?? $ this ->getValidateNamespace ();
119+ $ namespace = new PhpNamespace ($ namespacePath );
120+ $ namespace ->addUse ('HPlus\Validate\Validate ' );
121+ $ class = new \Nette \PhpGenerator \ClassType ();
122+ $ class ->setName ($ class_name );
123+ $ class ->setComment ('验证器类 ' );
124+ $ class ->addProperty ('rule ' )
125+ ->setProtected ()
126+ ->setValue ($ rule )
127+ ->setInitialized ();
128+
129+ $ class ->addProperty ('field ' )
130+ ->setProtected ()
131+ ->setValue ($ field )
132+ ->setInitialized ();
133+
134+ $ class ->addProperty ('scene ' )
135+ ->setProtected ()
136+ ->setValue ($ scene )
137+ ->setInitialized ();
138+
139+ $ class ->addExtend (Validate::class);
140+ $ namespace ->add ($ class );
141+ $ this ->makeDirectory ($ path );
142+ file_put_contents ($ path , "<?php \n\ndeclare(strict_types=1); \n
143+ /**
144+ * This file is part of Hyperf.plus
145+ *
146+ * @link https://www.hyperf.plus
147+ * @document https://doc.hyperf.plus
148+ * @contact 4213509@qq.com
149+ * @license https://github.com/hyperf-plus/admin/blob/master/LICENSE
150+ */ \n\n" . $ namespace );
151+ $ output ->writeln (sprintf ('<info>%s</info> ' , $ name . ' created successfully. ' ));
152+ return 1 ;
153+ }
154+
155+ /**
156+ * Replace the class name for the given stub.
157+ *
158+ * @param string $stub
159+ * @param string $name
160+ *
161+ * @return string
162+ */
163+ protected function replaceClass ($ stub , $ name )
164+ {
165+ $ class = str_replace ($ this ->getNamespace ($ name ) . '\\' , '' , $ name );
166+ $ stub = str_replace ('%CLASS% ' , $ class , $ stub );
167+ $ stub = str_replace ('%TITLE% ' , $ this ->input ->getArgument ('t ' ) ?? $ class , $ stub );
168+ $ stub = str_replace ('%DESC% ' , $ this ->input ->getArgument ('d ' ), $ stub );
169+ return $ stub ;
170+ }
171+
172+ protected function getRule ($ data )
173+ {
174+ $ ext = '' ;
175+ if ($ data ['data_type ' ] === 'varchar ' && $ data ['column_type ' ]) {
176+ $ tmp = str_replace ('varchar( ' , '' , $ data ['column_type ' ]);
177+ $ tmp = str_replace ('char( ' , '' , $ tmp );
178+ $ tmp = trim ($ tmp , ') ' );
179+ $ ext = '|length:0, ' . $ tmp ;
180+ }
181+
182+ switch ($ data ['data_type ' ] ?? '' ) {
183+ case 'datetime ' :
184+ case 'timestamp ' :
185+ case 'date ' :
186+ return 'dateFormat ' ;
187+ case 'time ' :
188+ return 'time ' ;
189+ case 'tinyint ' :
190+ return 'integer ' ;
191+ case 'varchar ' :
192+ return 'string ' . $ ext ;
193+ default :
194+
195+ break ;
196+ }
197+ return '' ;
198+ }
199+
200+ /**
201+ * @param $table
202+ *
203+ * @return \HPlus\Admin\Model\Model
204+ */
205+ protected function getModel ($ table )
206+ {
207+ $ class = $ this ->getConfig ()['model_namespace ' ] ?? 'App \\Model \\' . $ table ;
208+ if (!class_exists ($ class )) {
209+ return false ;
210+ }
211+ return new $ class ;
212+ }
213+
214+ /**
215+ * @param $table
216+ *
217+ * @return \HPlus\Admin\Model\Model
218+ */
219+ protected function getValidateNamespace ()
220+ {
221+ return $ this ->getConfig ()['model_namespace ' ] ?? 'App \\Validate ' ;
222+ }
223+
224+
225+ /**
226+ * Parse the class name and format according to the root namespace.
227+ *
228+ * @param string $name
229+ *
230+ * @return string
231+ */
232+ protected function qualifyClass ($ name )
233+ {
234+ $ name = ltrim ($ name , '\\/ ' );
235+
236+ $ name = str_replace ('/ ' , '\\' , $ name );
237+
238+ $ namespace = $ this ->input ->getOption ('namespace ' );
239+ if (empty ($ namespace )) {
240+ $ namespace = $ this ->getValidateNamespace ();
241+ }
242+
243+ return $ namespace . '\\' . $ name . 'Validate ' ;
244+ }
245+
246+
247+ /**
248+ * Get the custom config for generator.
249+ */
250+ protected function getConfig (): array
251+ {
252+ $ class = Arr::last (explode ('\\' , static ::class));
253+ $ class = Str::replaceLast ('Command ' , '' , $ class );
254+ $ key = 'admindev.generator.controller ' ;
255+ return $ this ->getContainer ()->get (ConfigInterface::class)->get ($ key ) ?? [];
256+ }
257+
258+ protected function getContainer (): ContainerInterface
259+ {
260+ return ApplicationContext::getContainer ();
261+ }
262+ }
0 commit comments