├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
└── images
│ ├── db-conf.png
│ ├── devtools-version.png
│ └── devtools.png
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
└── src
├── Ubiquity
└── devtools
├── cmd
└── commands
│ ├── AbstractCmdModel.php
│ ├── AbstractThemeCmd.php
│ ├── AuthCmd.php
│ ├── ConfigCmd.php
│ ├── ConfigSetCmd.php
│ ├── CreateCommandCmd.php
│ ├── CrudCmd.php
│ ├── DAOCmd.php
│ ├── DisplayAclsCmd.php
│ ├── EncryptNewKey.php
│ ├── HelpCmd.php
│ ├── IndexCrudCmd.php
│ ├── InfoMailerCmd.php
│ ├── InfoMigrationsCmd.php
│ ├── InfoModelCmd.php
│ ├── InfoModelsCmd.php
│ ├── InfoRoutesCmd.php
│ ├── InfoValidationCmd.php
│ ├── InitAclsCmd.php
│ ├── InitCacheCmd.php
│ ├── InstallThemeCmd.php
│ ├── LiveReloadCmd.php
│ ├── MigrationsCmd.php
│ ├── NewActionCmd.php
│ ├── NewClassCmd.php
│ ├── NewDomainCmd.php
│ ├── NewMailCmd.php
│ ├── NewModelCmd.php
│ ├── NewThemeCmd.php
│ ├── RestApiCmd.php
│ ├── RestCmd.php
│ ├── SendMailQueueCmd.php
│ ├── TemplateParserCmd.php
│ ├── popo
│ └── NewModel.php
│ └── traits
│ └── DbCheckTrait.php
├── core
├── ConsoleScaffoldController.php
├── themesConfig.php
└── toolsConfig.php
├── project-files
├── .htaccess
├── README.md
├── app
│ ├── .htaccess
│ ├── controllers
│ │ ├── Admin.php
│ │ ├── ControllerBase.php
│ │ └── IndexController.php
│ └── views
│ │ └── themes
│ │ ├── bootstrap
│ │ └── main
│ │ │ ├── vFooter.html
│ │ │ ├── vHeader.html
│ │ │ └── vMenu.html
│ │ ├── foundation
│ │ └── main
│ │ │ ├── vFooter.html
│ │ │ ├── vHeader.html
│ │ │ └── vMenu.html
│ │ ├── model
│ │ └── main
│ │ │ ├── vFooter.html
│ │ │ ├── vHeader.html
│ │ │ └── vMenu.html
│ │ └── semantic
│ │ └── main
│ │ ├── vFooter.html
│ │ ├── vHeader.html
│ │ └── vMenu.html
├── index.php
├── public
│ └── themes
│ │ ├── bootstrap
│ │ ├── css
│ │ │ ├── style.css
│ │ │ └── style.css.map
│ │ ├── img
│ │ │ └── .gitkeep
│ │ └── scss
│ │ │ ├── _myVariables.scss
│ │ │ └── app.scss
│ │ ├── foundation
│ │ ├── css
│ │ │ ├── style.css
│ │ │ └── style.css.map
│ │ ├── img
│ │ │ └── .gitkeep
│ │ └── scss
│ │ │ ├── _myVariables.scss
│ │ │ └── app.scss
│ │ ├── model
│ │ ├── css
│ │ │ └── style.css
│ │ ├── img
│ │ │ └── .gitkeep
│ │ └── js
│ │ │ └── .gitkeep
│ │ └── semantic
│ │ ├── css
│ │ └── style.css
│ │ └── img
│ │ └── .gitkeep
└── templates
│ ├── .env.tpl
│ ├── bootstrap.tpl
│ ├── config.tpl
│ ├── controller.tpl
│ ├── indexNoTheme.tpl
│ ├── indexThemes.tpl
│ ├── preloader.config.tpl
│ ├── preloader.script.tpl
│ ├── services.tpl
│ ├── vFooter.tpl
│ ├── vHeader.tpl
│ └── view.tpl
├── server
├── .htrouter.php
├── _index.php
├── _ngx.php
├── _react.php
├── _swoole.php
├── _swow.php
└── _workerman.php
└── utils
└── FrameworkParts.php
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[command] Element should do X"
5 | labels: ''
6 | assignees: jcheron
7 |
8 | ---
9 |
10 |
17 | ### Steps
18 |
19 | ### Expected Result
20 |
21 | ### Actual Result
22 |
23 | ### Versions
24 | - Ubiquity framework x.y.z
25 | - Ubiquity devtools x.y.z
26 | - php x.y.z
27 | - OS
28 |
--------------------------------------------------------------------------------
/.github/images/db-conf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpMv/ubiquity-devtools/8c0e8f5923cee82acb25db9e84897960de380875/.github/images/db-conf.png
--------------------------------------------------------------------------------
/.github/images/devtools-version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpMv/ubiquity-devtools/8c0e8f5923cee82acb25db9e84897960de380875/.github/images/devtools-version.png
--------------------------------------------------------------------------------
/.github/images/devtools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpMv/ubiquity-devtools/8c0e8f5923cee82acb25db9e84897960de380875/.github/images/devtools.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .buildpath
2 | .project
3 | .settings
4 | vendor/
5 | composer.lock
6 | .idea/
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [unreleased]
8 | - nothing
9 |
10 | ## [1.4.8] - 2023-02-05
11 | ### Added
12 | - **v(view)** option with **create-project(new)** command
13 |
14 | ## [1.4.3] - 2022-12-31
15 | ### Updated
16 | - `aclInit` command (add table and models creation)
17 | - `new project` (add init-cache after creation)
18 |
19 | ## [1.4.2] - 2022-12-19
20 | ### Fixed
21 | - add `vlucas/phpdotenv` in composer.json
22 |
23 | ## [1.4.1] - 2022-12-18
24 | ### Fixed
25 | - config cache first initialization
26 |
27 | ## [1.4.0] - 2022-12-18
28 | ### Updated
29 | - Compatibility with Ubiquity 2.5.0
30 | ### Added
31 | - env vars support
32 | ## [1.3.11] - 2022-05-06
33 | ### Updated
34 | - Change root directory to `public` for async platforms
35 |
36 | ## [1.3.10] - 2022-02-15
37 | ### Fixed
38 | - `InstallThemeCmd` pb with `DDDManager`
39 |
40 | ## [1.3.9] - 2022-02-13
41 |
42 | ### Updated
43 | - Default vHeader and vFooter templates
44 | - Add create and 2FA views for Auth controllers
45 |
46 |
47 | ## [1.3.8] - 2022-01-01
48 | ### Fixed
49 | - cache initialization pb with `new-model` command
50 |
51 | ### Changed
52 | - `str_pad` usage for questions in commands
53 | - relocate livereload starting (after nonce creation)
54 | - add nonce in template files
55 | - add default nonce
56 |
57 | ## [1.3.7] - 2021-12-02
58 | ### Fixed
59 | - Other models loading +cache re-init in `new-model` command
60 | - Re-init cache before migrations commands
61 | - typo in `addRelation`: `$namepsace`
62 |
63 | ## [1.3.6] - 2021-12-01
64 |
65 | ### Added
66 | #### Migrations commands:
67 |
68 | ```
69 | ■ info-migrations [] =>
70 | · Returns the migration infos.
71 | · Aliases : info_migrations,info:migrations,infoMigrations
72 | · Parameters :
73 | -d shortcut of --database
74 | The database offset.
75 | Default : [default]
76 |
77 | -o shortcut of --domain
78 | The domain in which the database models are.
79 |
80 | × Samples :
81 | Display all migrations for the default database
82 | · Ubiquity info:migrations
83 | ```
84 |
85 | ```
86 | ■ migrations [] =>
87 | · Display and execute the database migrations.
88 | · Aliases : migrations,migrate
89 | · Parameters :
90 | -d shortcut of --database
91 | The database offset.
92 | Default : [default]
93 |
94 | -o shortcut of --domain
95 | The domain in which the database models are.
96 |
97 | × Samples :
98 | Display and execute all migrations for the default database
99 | · Ubiquity migrations
100 | ```
101 | #### Models creation
102 |
103 | ```
104 | ■ model [modelName] =>
105 | · Generates models from scratch.
106 | · Aliases : create_model,create:model,create-model,createModel,new_model,new:model,new-model,newModel
107 | · Parameters :
108 | -d shortcut of --database
109 | The database connection to use
110 | Default : [default]
111 |
112 | -o shortcut of --domain
113 | The domain in which to create the model.
114 |
115 | -k shortcut of --autoincPk
116 | The default primary key defined as autoinc.
117 | Default : [id]
118 |
119 | × Samples :
120 | · Ubiquity model User
121 | · Ubiquity model Author -d=projects
122 | · Ubiquity model Group,User -o=orga
123 | ```
124 |
125 | ## [1.3.5] - 2021-11-01
126 |
127 | ### Added
128 | - Adds Domain option (`-o` or `--domain`) for commands: `controller, action, auth, crud-index, model, all-models, dao, rest, rest-api, info-model, info-models, info-validation`
129 |
130 | ### Updated
131 | - Command names parsing:
132 | For all commands with multiple parts in the name, the following syntaxes can be used:
133 | ex: for `Ubiquity all-models`
134 | - `Ubiquity all_models`
135 | - `Ubiquity all:models`
136 | - `Ubiquity allModels`
137 |
138 | ## [1.3.4] - 2021-10-07
139 | ### Fixed
140 | - assets folder location with Ubiquity server
141 |
142 | ## [1.3.3] - 2021-09-06
143 | ### Updated
144 | - Default index page
145 | - ui libraries
146 |
147 | ## [1.3.2] - 2021-07-11
148 | #### Added
149 | - `index-crud` command
150 |
151 | ## [1.3.1] - 2021-07-06
152 | #### Fixed
153 | - Application root pb (public folder) with embedded web server
154 |
155 | ## [1.3.0] - 2021-06-15
156 | #### Models generation
157 | - The regeneration of models preserves the code implemented on the existing models.
158 |
159 | #### Application root (breaking change)
160 | - For apache and nginX, root folder is set to public folder (for new projects since Ubiquity 2.4.5)
161 |
162 | For an old project (created with a version prior to 2.4.5), you have to modify ``index.php`` and move the ``index.php`` and ``.htaccess`` files to the ``public`` folder.
163 |
164 | ```php
165 | no routes displayed
182 |
183 | ## [1.2.26] - 2021-03-10
184 | ### Fixed
185 | - crud & rest commands bug
186 | >Call to a member function asAnnotation on null
187 | >BaseControllerCreator line 58
188 |
189 | ## [1.2.25] - 2021-02-15
190 | ### Fixed
191 | - Bug on new class command with parent class (inheritance)
192 |
193 | ## [1.2.24] - 2021-02-08
194 | ### Added
195 | - `newClass` command for creating a new class
196 |
197 | ## [1.2.23] - 2021-02-06
198 | ### Updated
199 | - replace `livereloadx` with `livereload`
200 | >livereloadx has not been updated for 2 years, and does not manage file operations (add, delete).
201 |
202 | - add livereload with default php server
203 |
204 | Starts php web server and livereload (on 35729 port)
205 | ```bash
206 | Ubiquity serve
207 | ```
208 |
209 | Starts php web server without livereload
210 | ```bash
211 | Ubiquity serve -n
212 | ```
213 |
214 | ## [1.2.22] - 2021-02-05
215 | ### Added
216 | - `live-reload` command for dev server
217 |
218 | ## [1.2.21] - 2021-01-17
219 | ### Added
220 | - `newKey` command for generating the encryption key with Ubiquity-security
221 |
222 | ## [1.2.20] - 2020-12-31
223 | ### Fixed
224 | - new action problem
225 | >Call to a member function asAnnotation() on null
226 |
227 | ## [1.2.19] - 2020-12-31
228 |
229 | ### Updated
230 | - Add attributes or annotations fix
231 |
232 | ## [1.2.18] - 2020-12-11
233 |
234 | ### Added
235 | - `display-acls` command
236 |
237 | ### Updated
238 | - composer for php 8
239 |
240 | ## [1.2.17] - 2020-09-30
241 | ### Updated
242 | - add access option (member access) to all-models & create-model cmd
243 | - add db offset param to info:models command
244 | - add OS in version command
245 |
246 | ## [1.2.16] - 2020-07-28
247 | ### Updated
248 | - Update client libraries for new projects (Fomantic 2.8.6)
249 | - Fix session name generation pb (only alphanumeric chars)
250 |
251 | ## [1.2.15] - 2020-06-27
252 | ### Added
253 | - Add `create:command`command
254 | - support for custom commands
255 | ### Updated
256 | - move utility classes to `ubiquity-commands` repo
257 | - Update client libraries for new projects (Fomantic 2.8.5)
258 |
259 | ## [1.2.14] - 2020-05-06
260 | #### Updated
261 | - Update client libraries for new projects (Fomantic 2.8.4, jQuery 3.5.1)
262 | - Add port checking for `Ubiquity serve` command
263 | ## [1.2.13] - 2020-03-23
264 | #### Added
265 | - roadrunner server command (Thanks @Lapinskas)
266 |
267 | `Ubiquity serve -t=roadrunner`
268 | #### Added
269 |
270 | ## [1.2.12] - 2020-01-25
271 | #### Added
272 | - Mailer commands (mailer, newMail, sendMail)
273 | - opcache preloading in project creation
274 | #### Changed
275 | - set `help` as default command
276 | - require php 7.4
277 |
278 | ## [1.2.11] - 2019-11-18
279 | #### Changed
280 | - Update client libraries for new projects (Fomantic 2.8, jQuery 3.4.1, phpMv-ui 2.3)
281 | - require php 7.2
282 |
283 | ## [1.2.10] - 2019-10-28
284 | #### Added
285 | - Composer create-project
286 | ```
287 | composer create-project phpmv/ubiquity-project {projectName}
288 | ```
289 |
290 | ## [1.2.9] - 2019-09-25
291 | ### Fixed
292 | - [Cannot set database](https://github.com/phpMv/ubiquity/issues/74)
293 | - https://github.com/phpMv/ubiquity/issues/72
294 | - Fix https://github.com/phpMv/ubiquity-devtools/commit/c06b6704126a4bf56b2a6a52c60aa1d40edcfcdb
295 | ### Added
296 | #### Commands
297 | - `composer` [cmd]
298 |
299 | Samples:
300 | ```
301 | Ubiquity composer update
302 | Ubiquity composer nodev
303 | Ubiquity composer optimize
304 | ```
305 | - `bootstrap` [cmd]
306 |
307 | Execute the `cmd` method from the `.ubiquity/_bootstrap.php` file to prepare an environment.
308 |
309 | Sample:
310 | ```
311 | Ubiquity bootstrap prod
312 | Ubiquity bootstrap dev
313 | ```
314 | ## [1.2.8] - 2019-08-01
315 | ### Changed
316 | - `model` (`create-model`) command
317 | - added parameter `d`(`database`): the database connection name defined in config file (use default connection if absent)
318 |
319 | Samples:
320 | ```
321 | Ubiquity model Author -d=projects
322 | Ubiquity model Author --database=projects
323 | ```
324 |
325 | - `all-models` (`create-all-models`) command
326 | - added parameter `d`(`database`): the database connection name defined in config file (use default connection if absent)
327 | - removed parameter `b`(`dbName`): the database name defined in config file
328 |
329 | Samples:
330 | ```
331 | Ubiquity all-models -d=projects
332 | Ubiquity create-all-models --database=projects
333 | ```
334 | ## [1.2.7] - 2019-07-03
335 | ### Changed
336 | - Checks if devtools are globally installed in ``sefUpdate`` op
337 | - Integrates ubiquity-webtools ``2.2.0`` (in a separate repository)
338 |
339 | ### Fixed
340 | - Remove warning for ``\DS`` constant redefinition (thanks @TakeMeNL)
341 |
342 | ## [1.2.6] - 2019-06-13
343 | ### Added
344 | - Ubiquity Swoole server: ``Ubiquity serve -t=swoole``
345 | - Parameters for `new` command see [#45](https://github.com/phpMv/ubiquity/issues/45)
346 | - `siteUrl (i)` : Sets the site base URL.
347 | - `rewriteBase (e)` : Sets .htaccess file rewriteBase.
348 |
349 | Use
350 | ```
351 | Ubiquity new fooProject -i=http://foo.local -w=foo
352 | ```
353 | or
354 | ```
355 | Ubiquity new fooProject --siteUrl=http://foo.local --rewriteBase=foo
356 | ```
357 | ## [1.2.5] - 2019-05-10
358 | ### Fixed
359 | - Warning in pages with php Web server Fix: [#5](https://github.com/phpMv/ubiquity-devtools/issues/5)
360 |
361 | ## [1.2.4] - 2019-05-09
362 | ### Added
363 | - **README.md** file for new projects
364 | - ReactPHP server: ```Ubiquity serve t=react```
365 |
366 | ### Fixed
367 | - Change of theme without control in the ``ct`` action of ``IndexController`` for new projects : see Ubiquity issue [#38](https://github.com/phpMv/ubiquity/issues/38)
368 |
369 | ## [1.2.3] - 2019-04-03
370 | - relooking of the messages for clarity
371 |
372 | ## [1.2.2] - 2019-04-02
373 | - Fix issue [#22](https://github.com/phpMv/ubiquity/issues/22) (install without -a option bug)
374 |
375 | ## [1.2.0] - 2019-04-01
376 | ### Added
377 | - Commands
378 | - `install-theme` for installing Bootstrap, Semantic-UI or Foundation
379 | - `create-theme` for creating a new theme (eventually based on a ref theme)
380 | ### Changed
381 | - `services.tpl file`
382 | ### Fixed
383 | - An exception is thrown In case of problem with the Database connection (in `DataBase::connect` method) see https://github.com/phpMv/ubiquity/issues/12
384 | >The connection to the database must be protected by a `try/catch` in `app/config/services.php`
385 | ```
386 | try{
387 | \Ubiquity\orm\DAO::startDatabase($config);
388 | }catch(Exception $e){
389 | echo $e->getMessage();
390 | }
391 | ```
392 |
393 | ## [1.1.6] - 2019-03-14
394 | ### Added
395 | - New commands
396 | - ``Ubiquity restapi`` -> create a REST API controller (based on JsonApi)
397 | - ``Ubiquity rest`` -> create a REST controller associated to a model
398 | - ``Ubiquity dao`` -> query the database
399 | - getOne
400 | - getAll
401 | - uGetOne
402 | - uGetAll
403 | - count
404 | - uCount
405 |
406 | ### Fixed
407 | - [New project template has invalid link to Admin page](https://github.com/phpMv/ubiquity/issues/8)
408 |
409 | ## [1.1.5] - 2019-02-22
410 | ### Added
411 | - New commands
412 | - ``Ubiquity config`` -> display config file variables
413 | - ``Ubiquity config:set --database.dbName=blog`` -> modify/add and save config variables
414 | - ``Ubiquity info:models`` -> display all models metadatas
415 | - ``Ubiquity info:model -m=User`` -> display metadatas for the selected model
416 | - ``Ubiquity info:validation`` -> display validation infos for all models or the selected one
417 |
418 | ### Changed
419 | - Project structure (commands are in separate classes).
420 | - services.tpl template for new project creation
421 |
422 | ## [1.1.4] - 2019-02-18
423 | ### Added
424 | - New commands
425 | - ``Ubiquity info:routes`` -> display the router informations/test the routes resolution (with -s parameter)
426 |
427 | ### Changed
428 | - Project structure (src folder).
429 |
430 | ## [1.1.3] - 2019-02-13
431 | ### Added
432 | - New commands
433 | - ``Ubiquity serve`` -> php internal web server for dev
434 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](https://packagist.org/packages/phpmv/ubiquity-devtools)
4 | [](https://packagist.org/packages/phpmv/ubiquity-devtools)
5 | [](https://packagist.org/packages/phpmv/ubiquity-devtools)
6 | [](http://micro-framework.readthedocs.io/en/latest/?badge=latest)
7 |
8 | Command line tools for [Ubiquity framework](https://github.com/phpMv/ubiquity)
9 | ## I - Installation
10 |
11 | ### Installing via Composer
12 |
13 | Install Composer in a common location or in your project:
14 |
15 | ```bash
16 | curl -s http://getcomposer.org/installer | php
17 | ```
18 | Run the composer installer :
19 |
20 | ```bash
21 | composer global require phpmv/ubiquity-devtools
22 | ```
23 | Make sure to place the `~/.composer/vendor/bin` directory in your PATH so the **Ubiquity** executable can be located by your system.
24 |
25 | To confirm **Ubiquity** was successfully installed, type ``Ubiquity version``:
26 |
27 | 
28 |
29 |
30 | If you get the message Ubiquity command not found
31 | Add composer's bin
directory to the system path
32 |
33 | - On windows
34 |
-
35 | by adding the value
%USERPROFILE%\AppData\Roaming\Composer\vendor\bin
to the system PATH variable
36 |
37 |
38 | - On other systems
39 |
-
40 | by placing
export PATH="$HOME/.composer/vendor/bin:$PATH"
into your ~/.bash_profile
(Mac OS users) or into your ~/.bashrc
(Linux users).
41 |
42 |
43 |
44 |
45 |
46 | ## II Devtools commands
47 | ### Information
48 | To get a list of available commands just run in console:
49 | ```bash
50 | Ubiquity help
51 | ```
52 | This command should display something similar to:
53 |
54 | ```bash
55 | Ubiquity devtools (1.3.6)
56 |
57 | ■ init-cache [] =>
58 | · Init the cache for models, router, rest.
59 | · Aliases : init_cache,init:cache,initCache
60 | · Parameters :
61 | -t shortcut of --type
62 | Defines the type of cache to create.
63 | Possibles values :
64 | all,controllers,acls,rest,models
65 | Default : [all]
66 |
67 | × Samples :
68 | Init all caches
69 | · Ubiquity init-cache
70 | Init models cache
71 | · Ubiquity init-cache -t=models
72 |
73 | ■ clear-cache [] =>
74 | · Clear models cache.
75 | · Aliases : clear_cache,clear:cache,clearCache
76 | · Parameters :
77 | -t shortcut of --type
78 | Defines the type of cache to reset.
79 | Possibles values :
80 | all,annotations,controllers,rest,models,queries,views
81 | Default : [all]
82 |
83 | × Samples :
84 | Clear all caches
85 | · Ubiquity clear-cache -t=all
86 | Clear models cache
87 | · Ubiquity clear-cache -t=models
88 |
89 | ■ controller [controllerName] =>
90 | · Creates a new controller.
91 | · Aliases : create_controller,create:controller,create-controller,createController
92 | · Parameters :
93 | -v shortcut of --views
94 | creates an associated view folder and index.html
95 | Possibles values :
96 | true,false
97 | Default : [false]
98 |
99 | -o shortcut of --domain
100 | The domain in which to create the controller.
101 |
102 | × Samples :
103 | Creates a controller
104 | · Ubiquity controller UserController
105 | with its associated view
106 | · Ubiquity controller UserController -v
107 | Creates a controller in the orga domain
108 | · Ubiquity controller OrgaController -o=orga
109 |
110 | ■ action [controller.action] =>
111 | · Creates a new action in a controller.
112 | · Aliases : new-action,new_action,new:action,newAction
113 | · Parameters :
114 | -p shortcut of --params
115 | The action parameters (or arguments)
116 |
117 | -r shortcut of --route
118 | The associated route path
119 |
120 | -v shortcut of --create-view
121 | Creates the associated view
122 | Possibles values :
123 | true,false
124 | Default : [false]
125 |
126 | -o shortcut of --domain
127 | The domain in which the controller is.
128 |
129 | × Samples :
130 | Adds the action all in controller Users
131 | · Ubiquity action Users.all
132 | Adds the action display in controller Users with a parameter
133 | · Ubiquity action Users.display -p=idUser
134 | and associates a route to it
135 | · Ubiquity action Users.display -p=idUser -r=/users/display/{idUser}
136 | with multiple parameters
137 | · Ubiquity action Users.search -p=name,address
138 | and create the associated view
139 | · Ubiquity action Users.search -p=name,address -v
140 |
141 | ■ auth [authControllerName] =>
142 | · Creates a new controller for authentification.
143 | · Aliases : auth-controller,auth_controller,auth:controller,authController
144 | · Parameters :
145 | -e shortcut of --extends
146 | The base class of the controller (must derived from AuthController)
147 | Default : [Ubiquity\controllers\auth\AuthController]
148 |
149 | -t shortcut of --templates
150 | The templates to modify
151 | Possibles values :
152 | index,info,noAccess,disconnected,message,baseTemplate
153 | Default : [index,info,noAccess,disconnected,message,baseTemplate]
154 |
155 | -p shortcut of --path
156 | The associated route
157 |
158 | -o shortcut of --domain
159 | The domain in which to create the controller.
160 |
161 | × Samples :
162 | Creates a new controller for authentification
163 | · Ubiquity auth AdminAuthController
164 | and associates a route to it
165 | · Ubiquity auth AdminAuthController -p=/admin/auth
166 | allows customization of index and info templates
167 | · Ubiquity auth AdminAuthController -t=index,info
168 |
169 | ■ crud-index [crudControllerName] =>
170 | · Creates a new index-CRUD controller.
171 | · Aliases : crud-index-controller,crud_index,crud:index,crudIndex
172 | · Parameters :
173 | -d shortcut of --datas
174 | The associated Datas class
175 | Possibles values :
176 | true,false
177 | Default : [true]
178 |
179 | -v shortcut of --viewer
180 | The associated Viewer class
181 | Possibles values :
182 | true,false
183 | Default : [true]
184 |
185 | -e shortcut of --events
186 | The associated Events class
187 | Possibles values :
188 | true,false
189 | Default : [true]
190 |
191 | -t shortcut of --templates
192 | The templates to modify
193 | Possibles values :
194 | index,form,display,item,itemHome
195 | Default : [index,form,display,home,itemHome]
196 |
197 | -p shortcut of --path
198 | The associated route
199 | Default : [{resource}]
200 |
201 | -o shortcut of --domain
202 | The domain in which to create the controller.
203 |
204 | × Samples :
205 | Creates an index crud controller
206 | · Ubiquity crud-index MainCrud -p=crud/{resource}
207 | allows customization of index and form templates
208 | · Ubiquity index-crud MainCrud -t=index,form
209 |
210 | ■ crud [crudControllerName] =>
211 | · Creates a new CRUD controller.
212 | · Aliases : crud_controller,crud:controller,crud-controller,crudController
213 | · Parameters :
214 | -r shortcut of --resource
215 | The model used
216 |
217 | -d shortcut of --datas
218 | The associated Datas class
219 | Possibles values :
220 | true,false
221 | Default : [true]
222 |
223 | -v shortcut of --viewer
224 | The associated Viewer class
225 | Possibles values :
226 | true,false
227 | Default : [true]
228 |
229 | -e shortcut of --events
230 | The associated Events class
231 | Possibles values :
232 | true,false
233 | Default : [true]
234 |
235 | -t shortcut of --templates
236 | The templates to modify
237 | Possibles values :
238 | index,form,display
239 | Default : [index,form,display]
240 |
241 | -p shortcut of --path
242 | The associated route
243 |
244 | -o shortcut of --domain
245 | The domain in which to create the controller.
246 |
247 | × Samples :
248 | Creates a crud controller for the class models\User
249 | · Ubiquity crud CrudUsers -r=User
250 | and associates a route to it
251 | · Ubiquity crud CrudUsers -r=User -p=/users
252 | allows customization of index and form templates
253 | · Ubiquity crud CrudUsers -r=User -t=index,form
254 | Creates a crud controller for the class models\projects\Author
255 | · Ubiquity crud Authors -r=models\projects\Author
256 |
257 | ■ new-class [name] =>
258 | · Creates a new class.
259 | · Aliases : new_class,new:class,newClass,class
260 | · Parameters :
261 | -p shortcut of --parent
262 | The class parent.
263 |
264 | × Samples :
265 | Creates a new class
266 | · Ubiquity class services.OrgaRepository
267 |
268 | ■ create-theme [themeName] =>
269 | · Creates a new theme or installs an existing one.
270 | · Aliases : create_theme,create:theme,createTheme
271 | · Parameters :
272 | -x shortcut of --extend
273 | If specified, inherits from an existing theme (bootstrap,semantic or foundation).
274 | Possibles values :
275 | bootstrap,semantic,foundation
276 |
277 | -o shortcut of --domain
278 | The domain in which to create the theme.
279 |
280 | × Samples :
281 | Creates a new theme custom
282 | · Ubiquity create-theme custom
283 | Creates a new theme inheriting from Bootstrap
284 | · Ubiquity theme myBootstrap -x=bootstrap
285 |
286 | ■ theme [themeName] =>
287 | · Installs an existing theme or creates a new one if the specified theme does not exists.
288 | · Aliases : install_theme,install-theme,install:theme,installTheme
289 | · Parameters :
290 | -o shortcut of --domain
291 | The domain in which to install the theme.
292 |
293 | × Samples :
294 | Creates a new theme custom
295 | · Ubiquity theme custom
296 | Install bootstrap theme
297 | · Ubiquity theme bootstrap
298 |
299 | ■ project [projectName] =>
300 | · Creates a new #ubiquity project.
301 | · Aliases : new,create_project
302 | · Parameters :
303 | -b shortcut of --dbName
304 | Sets the database name.
305 |
306 | -s shortcut of --serverName
307 | Defines the db server address.
308 | Default : [127.0.0.1]
309 |
310 | -p shortcut of --port
311 | Defines the db server port.
312 | Default : [3306]
313 |
314 | -u shortcut of --user
315 | Defines the db server user.
316 | Default : [root]
317 |
318 | -w shortcut of --password
319 | Defines the db server password.
320 |
321 | -h shortcut of --themes
322 | Install themes.
323 | Possibles values :
324 | semantic,bootstrap,foundation
325 |
326 | -m shortcut of --all-models
327 | Creates all models from database.
328 |
329 | -a shortcut of --admin
330 | Adds UbiquityMyAdmin tool.
331 | Possibles values :
332 | true,false
333 | Default : [false]
334 |
335 | -i shortcut of --siteUrl
336 | Sets the site base URL.
337 |
338 | -e shortcut of --rewriteBase
339 | Sets .htaccess file rewriteBase.
340 |
341 | × Samples :
342 | Creates a new project
343 | · Ubiquity new blog
344 | With admin interface
345 | · Ubiquity new blog -a
346 | and models generation
347 | · Ubiquity new blog -a -m -b=blogDB
348 |
349 | ■ serve [] =>
350 | · Start a web server.
351 | · Parameters :
352 | -h shortcut of --host
353 | Sets the host ip address.
354 | Default : [127.0.0.1]
355 |
356 | -p shortcut of --port
357 | Sets the listen port number.
358 | Default : [8090]
359 |
360 | -n shortcut of --nolr
361 | Starts without live-reload.
362 |
363 | -l shortcut of --lrport
364 | Sets the live-reload listen port number.
365 | Default : [35729]
366 |
367 | -t shortcut of --type
368 | Sets the server type.
369 | Possibles values :
370 | php,react,swoole,roadrunner
371 | Default : [php]
372 |
373 | × Samples :
374 | Starts a php server at 127.0.0.1:8090
375 | · Ubiquity serve
376 | Starts a reactPHP server at 127.0.0.1:8080
377 | · Ubiquity serve -t=react
378 |
379 | ■ livereload [path] =>
380 | · Start the live reload server.
381 | · Aliases : live-reload,live
382 | · Parameters :
383 | -p shortcut of --port
384 | Sets the listen port number.
385 | Default : [35729]
386 |
387 | -e shortcut of --exts
388 | Specify extentions to observe .
389 | Default : [php,html]
390 |
391 | -x shortcut of --exclusions
392 | Exclude file matching pattern .
393 | Default : [cache/,logs/]
394 |
395 | × Samples :
396 | Starts the live-reload server at 127.0.0.1:35729
397 | · Ubiquity live-reload
398 | Starts the live-reload server at 127.0.0.1:35800 excluding logs directory
399 | · Ubiquity live-reload -p=35800 -x=logs/
400 |
401 | ■ bootstrap [command] =>
402 | · Executes a command created in app/config/_bootstrap.php file for bootstraping the app.
403 | · Aliases : boot
404 | × Samples :
405 | Bootstrap for dev mode
406 | · Ubiquity bootstrap dev
407 | Bootstrap for prod mode
408 | · Ubiquity bootstrap prod
409 |
410 | ■ help [?] =>
411 | · Get some help about a dev-tools command.
412 | × Samples :
413 | Get some help about crud
414 | · Ubiquity help crud
415 |
416 | ■ version [] =>
417 | · Return PHP, Framework and dev-tools versions.
418 |
419 | ■ model [modelName] =>
420 | · Generates models from scratch.
421 | · Aliases : create_model,create:model,create-model,createModel,new_model,new:model,new-model,newModel
422 | · Parameters :
423 | -d shortcut of --database
424 | The database connection to use
425 | Default : [default]
426 |
427 | -o shortcut of --domain
428 | The domain in which to create the model.
429 |
430 | -k shortcut of --autoincPk
431 | The default primary key defined as autoinc.
432 | Default : [id]
433 |
434 | × Samples :
435 | · Ubiquity model User
436 | · Ubiquity model Author -d=projects
437 | · Ubiquity model Group,User -o=orga
438 |
439 | ■ genModel [tableName] =>
440 | · Generates a new model from an existing table.
441 | · Aliases : gen_model,gen:model,gen-model,genModel
442 | · Parameters :
443 | -d shortcut of --database
444 | The database connection to use
445 | Default : [default]
446 |
447 | -a shortcut of --access
448 | The default access to the class members
449 | Default : [private]
450 |
451 | -o shortcut of --domain
452 | The domain in which to create the model.
453 |
454 | × Samples :
455 | · Ubiquity genModel User
456 | · Ubiquity genModel Author -d=projects
457 | · Ubiquity genModel Author -d=projects -a=protected
458 |
459 | ■ all-models [] =>
460 | · Generates all models from database.
461 | · Aliases : create-all-models,all_models,all:models,allModels
462 | · Parameters :
463 | -d shortcut of --database
464 | The database connection to use (offset)
465 | Default : [default]
466 |
467 | -a shortcut of --access
468 | The default access to the class members
469 | Default : [private]
470 |
471 | -o shortcut of --domain
472 | The domain in which to create the models.
473 |
474 | × Samples :
475 | · Ubiquity all-models
476 | · Ubiquity all-models -d=projects
477 | · Ubiquity all-models -d=projects -a=protected
478 |
479 | ■ info-migrations [] =>
480 | · Returns the migration infos.
481 | · Aliases : info_migrations,info:migrations,infoMigrations
482 | · Parameters :
483 | -d shortcut of --database
484 | The database offset.
485 | Default : [default]
486 |
487 | -o shortcut of --domain
488 | The domain in which the database models are.
489 |
490 | × Samples :
491 | Display all migrations for the default database
492 | · Ubiquity info:migrations
493 |
494 | ■ migrations [] =>
495 | · Display and execute the database migrations.
496 | · Aliases : migrations,migrate
497 | · Parameters :
498 | -d shortcut of --database
499 | The database offset.
500 | Default : [default]
501 |
502 | -o shortcut of --domain
503 | The domain in which the database models are.
504 |
505 | × Samples :
506 | Display and execute all migrations for the default database
507 | · Ubiquity migrations
508 |
509 | ■ dao [command] =>
510 | · Executes a DAO command (getAll,getOne,count,uGetAll,uGetOne,uCount).
511 | · Aliases : DAO
512 | · Parameters :
513 | -r shortcut of --resource
514 | The model used
515 |
516 | -c shortcut of --condition
517 | The where part of the query
518 |
519 | -i shortcut of --included
520 | The associated members to load (boolean or array: client.*,commands)
521 |
522 | -p shortcut of --parameters
523 | The parameters for a parameterized query
524 |
525 | -f shortcut of --fields
526 | The fields to display in the response
527 |
528 | -o shortcut of --domain
529 | The domain in which the models are.
530 |
531 | × Samples :
532 | Returns all instances of models\User
533 | · Ubiquity dao getAll -r=User
534 | Returns all instances of models\User and includes their commands
535 | · Ubiquity dao getAll -r=User -i=commands
536 | Returns the User with the id 5
537 | · Ubiquity dao getOne -c="id=5"-r=User
538 | Returns the list of users belonging to the "Brittany" or "Normandy" regions
539 | · Ubiquity uGetAll -r=User -c="region.name= ? or region.name= ?" -p=Brittany,Normandy
540 |
541 | ■ self-update [] =>
542 | · Updates Ubiquity framework for the current project.
543 |
544 | ■ composer [command] =>
545 | · Executes a composer command.
546 | · Aliases : compo
547 | × Samples :
548 | composer update
549 | · Ubiquity composer update
550 | composer update with no-dev
551 | · Ubiquity composer nodev
552 | composer optimization for production
553 | · Ubiquity composer optimize
554 |
555 | ■ admin [] =>
556 | · Add UbiquityMyAdmin webtools to the current project.
557 |
558 | ■ rest [restControllerName] =>
559 | · Creates a new REST controller.
560 | · Aliases : rest-controller,rest:controller,rest_controller,restController
561 | · Parameters :
562 | -r shortcut of --resource
563 | The model used
564 |
565 | -p shortcut of --path
566 | The associated route
567 |
568 | -o shortcut of --domain
569 | The domain in which to create the controller.
570 |
571 | × Samples :
572 | Creates a REST controller for the class models\User
573 | · Ubiquity rest RestUsers -r=User -p=/rest/users
574 |
575 | ■ restapi [restControllerName] =>
576 | · Creates a new REST API controller.
577 | · Aliases : restapi-controller,restapi:controller,restapi_controller,restapiController
578 | · Parameters :
579 | -p shortcut of --path
580 | The associated route
581 |
582 | -o shortcut of --domain
583 | The domain in which to create the controller.
584 |
585 | × Samples :
586 | Creates a REST API controller
587 | · Ubiquity restapi -p=/rest
588 |
589 | ■ info-routes [] =>
590 | · Display the cached routes.
591 | · Aliases : info:r,info_routes,info:routes,infoRoutes
592 | · Parameters :
593 | -t shortcut of --type
594 | Defines the type of routes to display.
595 | Possibles values :
596 | all,routes,rest
597 |
598 | -l shortcut of --limit
599 | Specifies the number of routes to return.
600 |
601 | -o shortcut of --offset
602 | Specifies the number of routes to skip before starting to return.
603 |
604 | -s shortcut of --search
605 | Search routes corresponding to a path.
606 |
607 | -m shortcut of --method
608 | Allows to specify a method with search attribute.
609 | Possibles values :
610 | get,post,put,delete,patch
611 |
612 | × Samples :
613 | All routes
614 | · Ubiquity info:routes
615 | Rest routes
616 | · Ubiquity info:routes -type=rest
617 | Only the routes with the method post
618 | · Ubiquity info:routes -type=rest -m=-post
619 |
620 | ■ info-model [?infoType] =>
621 | · Returns the model meta datas.
622 | · Aliases : info_model,info:model,infoModel
623 | · Parameters :
624 | -s shortcut of --separate
625 | If true, returns each info in a separate table
626 | Possibles values :
627 | true,false
628 | Default : [false]
629 |
630 | -m shortcut of --model
631 | The model on which the information is sought.
632 |
633 | -f shortcut of --fields
634 | The fields to display in the table.
635 |
636 | -o shortcut of --domain
637 | The domain in which the models is.
638 |
639 | × Samples :
640 | Gets metadatas for User class
641 | · Ubiquity info:model -m=User
642 |
643 | ■ info-models [] =>
644 | · Returns the models meta datas.
645 | · Aliases : info_models,info:models,infoModels
646 | · Parameters :
647 | -d shortcut of --database
648 | The database connection to use (offset)
649 | Default : [default]
650 |
651 | -m shortcut of --models
652 | The models on which the information is sought.
653 |
654 | -f shortcut of --fields
655 | The fields to display in the table.
656 |
657 | -o shortcut of --domain
658 | The domain in which the models are.
659 |
660 | × Samples :
661 | Gets metadatas for all models in default db
662 | · Ubiquity info:models
663 | Gets metadatas for all models in messagerie db
664 | · Ubiquity info:models -d=messagerie
665 | Gets metadatas for User and Group models
666 | · Ubiquity info:models -m=User,Group
667 | Gets all primary keys for all models
668 | · Ubiquity info:models -f=#primaryKeys
669 |
670 | ■ info-validation [?memberName] =>
671 | · Returns the models validation info.
672 | · Aliases : info_validation,info:validation,infoValidation,info_validators,info-validators,info:validators,infoValidators
673 | · Parameters :
674 | -s shortcut of --separate
675 | If true, returns each info in a separate table
676 | Possibles values :
677 | true,false
678 | Default : [false]
679 |
680 | -m shortcut of --model
681 | The model on which the information is sought.
682 |
683 | -o shortcut of --domain
684 | The domain in which the models is.
685 |
686 | × Samples :
687 | Gets validators for User class
688 | · Ubiquity info:validation -m=User
689 | Gets validators for User class on member firstname
690 | · Ubiquity info:validation firstname -m=User
691 |
692 | ■ config [] =>
693 | · Returns the config informations from app/config/config.php.
694 | · Aliases : info_config,info-config,info:config,infoConfig
695 | · Parameters :
696 | -f shortcut of --fields
697 | The fields to display.
698 |
699 | × Samples :
700 | Display all config vars
701 | · Ubiquity config
702 | Display database config vars
703 | · Ubiquity config -f=database
704 |
705 | ■ config-set [] =>
706 | · Modify/add variables and save them in app/config/config.php. Supports only long parameters with --.
707 | · Aliases : set_config,set-config,set:config,setConfig
708 | × Samples :
709 | Assigns a new value to siteURL
710 | · Ubiquity config:set --siteURL=http://127.0.0.1/quick-start/
711 | Change the database name and port
712 | · Ubiquity config:set --database.dbName=blog --database.port=3307
713 |
714 | ■ mailer [part] =>
715 | · Displays mailer classes, mailer queue or mailer dequeue.
716 | × Samples :
717 | Display mailer classes
718 | · Ubiquity mailer classes
719 | Display mailer messages in queue(To send)
720 | · Ubiquity mailer queue
721 | Display mailer messages in dequeue(sent)
722 | · Ubiquity mailer dequeue
723 |
724 | ■ new-mail [name] =>
725 | · Creates a new mailer class.
726 | · Aliases : new_mail,new:mail,newMail
727 | · Parameters :
728 | -p shortcut of --parent
729 | The class parent.
730 | Default : [\Ubiquity\mailer\AbstractMail]
731 |
732 | -v shortcut of --view
733 | Add the associated view.
734 |
735 | × Samples :
736 | Creates a new mailer class
737 | · Ubiquity newMail InformationMail
738 |
739 | ■ send-mail [] =>
740 | · Send message(s) from queue.
741 | · Aliases : send-mails,send_mails,send:mails,sendMails
742 | · Parameters :
743 | -n shortcut of --num
744 | If specified, Send the mail at the position n in queue.
745 |
746 | × Samples :
747 | Send all messages to send from queue
748 | · Ubiquity semdMails
749 | Send the first message in queue
750 | · Ubiquity sendMail 1
751 |
752 | ■ create-command [commandName] =>
753 | · Creates a new custom command for the devtools.
754 | · Aliases : create_command,create:command,createCommand
755 | · Parameters :
756 | -v shortcut of --value
757 | The command value (first parameter).
758 |
759 | -p shortcut of --parameters
760 | The command parameters (comma separated).
761 |
762 | -d shortcut of --description
763 | The command description.
764 |
765 | -a shortcut of --aliases
766 | The command aliases (comma separated).
767 |
768 | × Samples :
769 | Creates a new custom command
770 | · Ubiquity create-command custom
771 |
772 | ■ acl-init [] =>
773 | · Initialize Acls defined with annotations in controllers.
774 | · Aliases : acl_init,acl:init,aclInit
775 | × Samples :
776 | Initialize Acls
777 | · Ubiquity aclInit
778 |
779 | ■ acl-display [] =>
780 | · Display Acls defined with annotations in controllers.
781 | · Aliases : acl_display,acl:display,aclDisplay
782 | · Parameters :
783 | -v shortcut of --value
784 | The ACL part to display.
785 | Possibles values :
786 | all,role,resource,permission,map,acl
787 | Default : [acl]
788 |
789 | × Samples :
790 | Display all defined roles with ACL annotations
791 | · Ubiquity aclDisplay role
792 |
793 | ■ new-key [cypher] =>
794 | · Generate a new encryption key using a cipher.
795 | · Aliases : new_key,new:key,newKey
796 | × Samples :
797 | Generate a key for AES-128
798 | · Ubiquity new-key 128
799 |
800 | ■ domain [name] =>
801 | · Creates a new domain (for a Domain Driven Design approach).
802 | · Aliases : new-domain,new_domain,new:domain,newDomain
803 | · Parameters :
804 | -b shortcut of --base
805 | The base folder for domains.
806 | Default : [domains]
807 |
808 | × Samples :
809 | Creates a new domain users
810 | · Ubiquity domain users
811 | ```
812 |
813 | ### Project creation
814 | Once installed, the simple `Ubiquity new` command will create a fresh micro installation in the directory you specify. For instance, `Micro new blog` would create a directory named blog containing an Ubiquity project:
815 | ```bash
816 | Ubiquity new blog
817 | ```
818 | You can see more options about installation by reading the [Project creation section](http://micro-framework.readthedocs.io/en/latest/install.html).
819 |
820 | ### Running
821 | You can test with the php web server,
822 | from the root folder of your web application, run :
823 | ```
824 | Ubiquity serve
825 | ```
826 |
827 | ### Models creation
828 | make sure that the database is configured properly in app/config/config.php file :
829 | ```bash
830 | Ubiquity config -f=database
831 | ```
832 |
833 | 
834 |
835 | Execute the command, make sure you are also in the project folder or one of its subfolders :
836 | ```bash
837 | Ubiquity all-models
838 | ```
839 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "phpmv/ubiquity-devtools",
3 | "description": "Command line tools for ubiquity-framework",
4 | "type": "installer",
5 | "keywords": [
6 | "php",
7 | "framework"
8 | ],
9 | "require": {
10 | "php": ">=7.4",
11 | "phpmv/ubiquity-commands":"^0.0",
12 | "symfony/process": "^5.2",
13 | "vlucas/phpdotenv": "^5.5"
14 | },
15 | "license": "Apache-2.0",
16 | "authors": [
17 | {
18 | "name": "Jean-Christophe HERON",
19 | "email": "myaddressmail@gmail.com",
20 | "role": "Lead developer"
21 | }
22 | ],
23 | "bin": [
24 | "src/Ubiquity"
25 | ],
26 | "autoload" : {
27 | "psr-4" : {
28 | "Ubiquity\\" : "src/"
29 | }
30 | },
31 | "extra": {
32 | "branch-alias": {
33 | "dev-master": "1.3.x-dev"
34 | }
35 | },
36 | "minimum-stability": "dev",
37 | "prefer-stable": true
38 | }
39 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/AbstractCmdModel.php:
--------------------------------------------------------------------------------
1 | setIndent(5);
26 | $rArray=new ClassicArray($infos,$what);
27 | if(is_array($aFields) && sizeof($aFields)>0){
28 | $rArray->setFields($aFields);
29 | }
30 | $tbl->setDatas($rArray->parse());
31 | if($what!=null){
32 | echo ConsoleFormatter::showInfo($what);
33 | }
34 | echo $tbl->getTable();
35 | if($rArray->hasMessages()){
36 | echo ConsoleFormatter::showMessage(implode("\n", $rArray->getMessages()),'error');
37 | }
38 | }
39 | }
40 |
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/AbstractThemeCmd.php:
--------------------------------------------------------------------------------
1 | addAuthController($what, $baseClass, $authView, $routePath);
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/ConfigCmd.php:
--------------------------------------------------------------------------------
1 | app/config/config.php file');
12 | $datas=$config;
13 | $fields=self::getOption($options, 'f', 'fields');
14 | if($fields!=null){
15 | $fields=explode(",", $fields);
16 | }
17 | if($what!=null && isset($config[$what])){
18 | $datas=$config[$what];
19 | }
20 | $tbl=new ConsoleTable();
21 | $tbl->setIndent(5);
22 | $rArray=new ClassicArray($datas,$what);
23 | if(is_array($fields) && sizeof($fields)>0){
24 | $rArray->setFields($fields);
25 | }
26 | $tbl->setDatas($rArray->parse());
27 | if($what!=null){
28 | echo ConsoleFormatter::showInfo($what);
29 | }
30 | echo $tbl->getTable();
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/ConfigSetCmd.php:
--------------------------------------------------------------------------------
1 | $value){
15 | if(is_string($option)){
16 | $optionParts=explode(".", $option);
17 | $oldValue=self::getConfigOption($config, $optionParts);
18 | if(isset($oldValue)){
19 | if(UString::isValid($oldValue)){
20 | if($value!==$oldValue){
21 | self::setConfigOption($config, $optionParts, $value);
22 | echo ConsoleFormatter::showMessage($option." : ".var_export($oldValue,true)." -> ".var_export($value,true)."","info");
23 | $modified=true;
24 | }
25 | }else{
26 | echo ConsoleFormatter::showMessage($option." : Unable to change a value of type object","error");
27 | }
28 | }else{
29 | self::setConfigOption($config, $optionParts, $value);
30 | echo ConsoleFormatter::showMessage($option." : inserted -> ".var_export($value,true)."","info");
31 | $modified=true;
32 | }
33 | }
34 | }
35 | if($modified){
36 | $content="1){
68 | self::setConfigOption($config[$options[0]], array_slice($options, 1), $value);
69 | }
70 | }
71 |
72 | private static function setConfigOption_(&$config,$option,$value){
73 | $optionParts=explode(".", $option);
74 | $c=$config;
75 | $nb=sizeof($optionParts);
76 | for ($i=0;$i<$nb-1;$i++){
77 | $opt=$optionParts[$i];
78 | if(!isset($c[$opt])){
79 | $c[$opt]=[];
80 | }
81 | $c=$c[$opt];
82 | }
83 | $c[$optionParts[$nb-1]]=$value;
84 | }
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/CreateCommandCmd.php:
--------------------------------------------------------------------------------
1 | create($pattern, $cmdPath)) {
19 | echo ConsoleFormatter::showMessage(sprintf('Command %s created in %s!', $what, $cmdPath), 'success', 'Command creation');
20 | Command::reloadCustomCommands($devtoolsConfig);
21 | HelpCmd::run($caller, $what);
22 | } else {
23 | echo ConsoleFormatter::showMessage(sprintf('Error during the creation of %s!', $what), 'error', 'Command creation');
24 | }
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/CrudCmd.php:
--------------------------------------------------------------------------------
1 | addCrudController($what, $resource, $crudDatas, $crudViewer, $crudEvents, $crudViews, $routePath);
23 | } else {
24 | echo ConsoleFormatter::showMessage("The models class {$resource} does not exists!", 'error', 'crud-controller');
25 | }
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/DAOCmd.php:
--------------------------------------------------------------------------------
1 | getDatas($objects);
40 | break;
41 | case 'getOne':
42 | $object = DAO::getOne($resource, $condition, $included, $parameters);
43 | $rf = new ResponseFormatter();
44 | $datas = $rf->cleanRestObject($object);
45 | break;
46 | case 'uGetAll':
47 | $objects = DAO::uGetAll($resource, $condition, $included, $parameters);
48 | $rf = new ResponseFormatter();
49 | $datas = $rf->getDatas($objects);
50 | break;
51 | case 'uGetOne':
52 | $object = DAO::uGetOne($resource, $condition, $included, $parameters);
53 | $rf = new ResponseFormatter();
54 | $datas = $rf->cleanRestObject($object);
55 | break;
56 | case 'count':
57 | $nb = DAO::count($resource, $condition, $parameters);
58 | echo ConsoleFormatter::showInfo($nb . " instances of " . $resource);
59 | break;
60 | case 'uCount':
61 | $nb = DAO::uCount($resource, $condition, $parameters);
62 | echo ConsoleFormatter::showInfo($nb . " instances of " . $resource);
63 | break;
64 | default:
65 | echo ConsoleFormatter::showMessage("Unknown command for dao : " . $what, 'error', 'dao');
66 | break;
67 | }
68 | if (\is_array($datas)) {
69 | $tbl = new ConsoleTable();
70 | $tbl->setIndent(5);
71 | $rArray = new ClassicArray($datas, $what);
72 | if (\is_array($fields) && \count($fields) > 0) {
73 | if (\is_array($objects)) {
74 | $rArray->setIFields($fields);
75 | } else {
76 | $rArray->setFields($fields);
77 | }
78 | }
79 | $tbl->setDatas($rArray->parse());
80 | if ($what != null) {
81 | echo ConsoleFormatter::showInfo($what);
82 | }
83 | echo $tbl->getTable();
84 | if (\is_array($objects)) {
85 | echo ConsoleFormatter::showInfo(\count($datas) . " instances of " . $resource);
86 | }
87 | echo ConsoleFormatter::showInfo(sprintf("Query executed in %.3f seconds", (float) microtime(true) - $start));
88 | } else {
89 | echo ConsoleFormatter::showInfo('Nothing to display');
90 | }
91 | } else {
92 | echo ConsoleFormatter::showMessage("The models class {$resource} does not exists!", 'error', 'dao');
93 | }
94 | }
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/DisplayAclsCmd.php:
--------------------------------------------------------------------------------
1 | getMap(), [
66 | 'controller.action',
67 | 'resource',
68 | 'permission'
69 | ]);
70 | break;
71 | }
72 | }
73 | }
74 |
75 | private static function displayPart($title, $datas, $fields) {
76 | $count = \count($datas);
77 | $tbl = new ConsoleTable();
78 | $rArray = new ReflectArray();
79 | $rArray->setProperties($fields);
80 | $rArray->setObjects($datas);
81 | $tbl->setDatas($rArray->parse());
82 | echo ConsoleFormatter::showInfo("$count $title(s)\n");
83 | echo $tbl->getTable();
84 | if ($rArray->hasMessages()) {
85 | echo ConsoleFormatter::showMessage(\implode("\n", $rArray->getMessages()), 'error');
86 | }
87 | }
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/EncryptNewKey.php:
--------------------------------------------------------------------------------
1 | longString());
33 | }
34 | $command = $info['cmd'];
35 | echo "\n";
36 | }
37 | }
38 |
39 | private static function info($caller) {
40 | echo $caller::getAppVersion() . "\n";
41 | $commands = Command::getCommands();
42 | foreach ($commands as $command) {
43 | echo ConsoleFormatter::formatHtml($command->longString());
44 | echo "\n";
45 | }
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/IndexCrudCmd.php:
--------------------------------------------------------------------------------
1 | 1) {
25 | $dbOffset = Console::question('Please select a valid database offset', $dbs);
26 | } else {
27 | $dbOffset = \current($dbs);
28 | }
29 | $scaffold->setActiveDb($dbOffset);
30 | }
31 | if (\strpos($routePath, '{resource') === false) {
32 | echo ConsoleFormatter::showMessage("The path variable {$routePath} does not contain the {resource} part!", 'error', 'index-crud-controller');
33 | } else {
34 | $scaffold->addIndexCrudController($what, $crudDatas, $crudViewer, $crudEvents, $crudViews, $routePath);
35 | }
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoMailerCmd.php:
--------------------------------------------------------------------------------
1 | setProperties(explode(",", $fields));
41 | $rArray->setObjects($mails);
42 | $tbl->setDatas($rArray->parse());
43 | echo $tbl->getTable();
44 | if ($rArray->hasMessages()) {
45 | echo ConsoleFormatter::showMessage(implode("\n", $rArray->getMessages()), 'error');
46 | }
47 | echo ConsoleFormatter::showInfo(sizeof($mails) . " mails in {$what}\n");
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoMigrationsCmd.php:
--------------------------------------------------------------------------------
1 | $domain";
22 | }
23 |
24 | $checker = new DatabaseChecker($dbOffset);
25 | $checker->checkAll();
26 |
27 | if ($checker->hasErrors()) {
28 | echo ConsoleFormatter::showMessage("Migrations to operate for db at offset $dbOffset$domainStr:", 'info', 'Migrations');
29 | $messages = [];
30 | $checker->displayAll(function ($type, $icons, $content) use (&$messages) {
31 | $messages[$icons][] = $content;
32 | });
33 | foreach ($messages as $title => $msgs) {
34 | $content = \implode(PHP_EOL, $msgs);
35 | echo ConsoleFormatter::showMessage($content, 'warning', $title);
36 | }
37 | } else {
38 | echo ConsoleFormatter::showMessage("No migrations to operate for db at offset $dbOffset$domainStr!", 'info', 'Migrations');
39 | }
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoModelCmd.php:
--------------------------------------------------------------------------------
1 | {$model} does not exists!", 'error', 'info:model');
22 | }
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoModelsCmd.php:
--------------------------------------------------------------------------------
1 | " . $model . "\n");
24 | self::displayModelInfo($fields, $infos, null, false);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoRoutesCmd.php:
--------------------------------------------------------------------------------
1 | setProperties(explode(",", $fields));
35 | $rArray->setObjects($routes);
36 | $tbl->setDatas($rArray->parse());
37 | echo $tbl->getTable();
38 | if ($rArray->hasMessages()) {
39 | echo ConsoleFormatter::showMessage(implode("\n", $rArray->getMessages()), 'error');
40 | }
41 | echo ConsoleFormatter::showInfo(sizeof($routes) . " routes ({$type})\n");
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InfoValidationCmd.php:
--------------------------------------------------------------------------------
1 | {$model} does not exists!", 'error', 'info:model');
19 | }
20 | }
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InitAclsCmd.php:
--------------------------------------------------------------------------------
1 | createModels($dbOffset);
48 | $classes=$dao->getModelClasses();
49 | echo ConsoleFormatter::showMessage("ACLs models created", 'success', 'init-cache: models');
50 | $tbl=new ConsoleTable();
51 | $tbl->setIndent(5);
52 | $rArray=new ClassicArray($classes);
53 | $tbl->setDatas($rArray->parse());
54 | echo $tbl->getTable();
55 | ob_start();
56 | CacheManager::initCache($config, 'models');
57 | $res = ob_get_clean();
58 | echo ConsoleFormatter::showMessage($res, 'success', 'init-cache: models');
59 | }
60 | }
61 |
62 |
63 | CacheManager::start($config);
64 | AclManager::start();
65 | AclManager::initFromProviders([
66 | new AclCacheProvider()
67 | ]);
68 | ob_start();
69 | AclManager::initCache($config);
70 | $res = ob_get_clean();
71 | echo ConsoleFormatter::showMessage($res, 'success', 'init-acls');
72 | }
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/InitCacheCmd.php:
--------------------------------------------------------------------------------
1 | ' . $what . ' does not exists!', 'warning', 'Themes installation');
19 | $answer = Console::question('Would-you like to create a new one ?', [
20 | 'y',
21 | 'n'
22 | ]);
23 | if (Console::isYes($answer)) {
24 | NewThemeCmd::run($config, $options, $what, $activeDir);
25 | }
26 | }
27 | }
28 |
29 | public static function addTheme($name, $baseTheme, $themeConfig, $activeDir, $standalone = false, &$composer = []) {
30 | $baseDir = getcwd();
31 | $dest = $baseDir . '/public/assets/' . $name;
32 | if (! file_exists($dest)) {
33 | echo ConsoleFormatter::showMessage('Files copy...', 'Info', 'Adding theme ' . $name);
34 | FileUtils::safeMkdir($dest);
35 | $source = $activeDir . '/devtools/project-files/public/themes/' . $baseTheme;
36 | FileUtils::xcopy($source, $dest);
37 |
38 | if (\class_exists(\Ubiquity\domains\DDDManager::class)) {
39 | $dest = DDDManager::getActiveViewFolder() . 'themes/' . $name;
40 | } else {
41 | $dest = $baseDir . '/app/views/themes/' . $name;
42 | }
43 | FileUtils::safeMkdir($dest);
44 | $source = $activeDir . '/devtools/project-files/app/views/themes/' . $baseTheme;
45 | FileUtils::xcopy($source, $dest);
46 |
47 | $composerRequires = $themeConfig['composer'];
48 | foreach ($composerRequires as $composerRequire => $version) {
49 | if ($standalone) {
50 | system('composer require ' . $composerRequire);
51 | } else {
52 | $composer['require'][$composerRequire] = $version;
53 | }
54 | }
55 | $vendorCopies = $themeConfig['vendor-copy'] ?? [];
56 | if ($standalone) {
57 | self::copyVendorFiles($name, $vendorCopies, $baseDir);
58 | self::saveActiveTheme($name);
59 | }
60 | return $vendorCopies;
61 | }
62 |
63 | echo ConsoleFormatter::showMessage(\sprintf('This theme seems to be already installed in %s!', $dest), 'warning', 'Theme installation');
64 | return [];
65 | }
66 |
67 | public static function copyVendorFiles($theme, $vendorCopies, $baseDir) {
68 | foreach ($vendorCopies as $src => $dest) {
69 | $dest = \str_replace('%theme%', $theme, $dest);
70 | FileUtils::xcopy($baseDir . $src, $baseDir . $dest);
71 | echo ConsoleFormatter::showInfo("Copy from " . $src . " to " . $dest . "...");
72 | }
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/LiveReloadCmd.php:
--------------------------------------------------------------------------------
1 | npm install -g livereload.\n", 'warning', 'live-reload');
24 | echo ConsoleFormatter::showInfo("Trying to install livereload\n");
25 | system('npm install -g livereload');
26 | }
27 | echo ConsoleFormatter::showInfo($msg . "Press Ctrl+C to stop it!\n");
28 | system($cmd . ' &');
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/MigrationsCmd.php:
--------------------------------------------------------------------------------
1 | $domain";
30 | }
31 |
32 | $generator = new DatabaseReversor(new DbGenerator(), $dbOffset);
33 | $generator->migrate();
34 | $script = $generator->getScript();
35 | if (\count($script) === 0) {
36 | echo ConsoleFormatter::showMessage("No migrations to operate for db at offset $dbOffset$domainStr!", 'info', 'Migrations');
37 | } else {
38 | echo ConsoleFormatter::showMessage("Migrations to operate for db at offset $dbOffset$domainStr:", 'info', 'Migrations');
39 | do {
40 | self::displayScript(self::scriptToLineArray($script));
41 | $rep = Console::question('Select your choices:', [
42 | 'Execute all commands',
43 | 'Delete a row',
44 | 'Quit'
45 | ]);
46 | switch ($rep) {
47 | case 'Delete a row':
48 | $count = \count($script);
49 | $row = Console::question("Enter a valid row between 1 and $count:");
50 | $delete = self::deleteScriptRow($row, $script);
51 | if ($delete !== false) {
52 | $script = $delete;
53 | }
54 | break;
55 | case 'Execute all commands':
56 | self::executeSQLTransaction($dbOffset, implode(';', $script), 'Database migrations');
57 | $rep = 'Quit';
58 | break;
59 | default:
60 | echo ConsoleFormatter::showInfo('Operation terminated, Bye!');
61 | }
62 | } while ($rep !== 'Quit');
63 | }
64 | }
65 |
66 | private static function deleteScriptRow(int $rowNum, array $script) {
67 | $rowNum --;
68 | if ($rowNum >= 0 && $rowNum < \count($script)) {
69 | unset($script[$rowNum]);
70 | return array_values($script);
71 | }
72 | return false;
73 | }
74 |
75 | private static function displayScript(array $script) {
76 | $tbl = new ConsoleTable();
77 | $tbl->setIndent(5);
78 | $tbl->setPadding(1);
79 | $tbl->setDatas($script);
80 | echo $tbl->getTable();
81 | }
82 |
83 | private static function scriptToLineArray(array $script): array {
84 | $result = [];
85 | $line = 1;
86 | $width = Screen::getWidth() - 20;
87 | foreach ($script as $sql) {
88 | $result[] = [
89 | 'line' => $line ++,
90 | 'sql' => \wordwrap($sql, $width, PHP_EOL)
91 | ];
92 | }
93 | return $result;
94 | }
95 |
96 | private static function executeSQLTransaction(string $activeDbOffset, string $sql, string $title) {
97 | $isValid = true;
98 | if (isset($sql)) {
99 | $db = DAO::getDatabase($activeDbOffset ?? 'default');
100 | if (! $db->isConnected()) {
101 | $db->setDbName('');
102 | try {
103 | $db->connect();
104 | } catch (\Exception $e) {
105 | $isValid = false;
106 | echo ConsoleFormatter::showMessage($e->getMessage(), 'error', $title);
107 | }
108 | }
109 | if ($isValid) {
110 | if ($db->beginTransaction()) {
111 | try {
112 | $db->execute($sql);
113 | if ($db->inTransaction()) {
114 | $db->commit();
115 | }
116 | echo ConsoleFormatter::showMessage("Database created/updated with success at offset $activeDbOffset!", 'success', $title);
117 | } catch (\Error $e) {
118 | if ($db->inTransaction()) {
119 | $db->rollBack();
120 | }
121 | echo ConsoleFormatter::showMessage($e->getMessage(), 'error', $title);
122 | }
123 | } else {
124 | $db->execute($sql);
125 | echo ConsoleFormatter::showMessage("Database created/updated with success at offset $activeDbOffset!", 'success', $title);
126 | }
127 | }
128 | }
129 | }
130 | }
131 |
132 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewActionCmd.php:
--------------------------------------------------------------------------------
1 | setConfig($config);
14 | @list ($controller, $action) = explode('.', $what);
15 | $domain = self::getOption($options, 'o', 'domain', '');
16 | if ($domain != '') {
17 | DDDManager::setDomain($domain);
18 | }
19 | if ($controller != null && $action != null) {
20 | $controller = self::getCompleteClassname($config, $controller, 'controllers');
21 | if (\class_exists($controller)) {
22 | $parameters = self::getOption($options, 'p', 'params');
23 | $routePath = self::getOption($options, 'r', 'route');
24 | $createView = self::getOption($options, 'v', 'create-view', false);
25 | $theme = self::getOption($options, 't', 'theme');
26 | $routeInfo = null;
27 | if ($routePath != null) {
28 | $routeInfo = [
29 | "path" => $routePath,
30 | "methods" => null
31 | ];
32 | }
33 | CacheManager::start($config);
34 | $scaffold->_newAction($controller, $action, $parameters, '', $routeInfo, $createView, $theme);
35 | } else {
36 | echo ConsoleFormatter::showMessage("The controller class {$controller} does not exists!", 'error', 'new-action');
37 | }
38 | } else {
39 | echo ConsoleFormatter::showMessage("You must use controller.action notation!", 'error', 'new-action');
40 | }
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewClassCmd.php:
--------------------------------------------------------------------------------
1 | setConfig($config);
22 | $msg = $scaffold->_createClass('class.tpl', $classname, $ns, '', $parent, '');
23 | echo ConsoleFormatter::showMessage("Class {$classname} created!", 'success', 'new-class');
24 | } else {
25 | echo ConsoleFormatter::showMessage("Class namespace must not be empty!", 'error', 'new-class');
26 | }
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewDomainCmd.php:
--------------------------------------------------------------------------------
1 | $originalBase, which is different from $base.\nWould you like to rename the base to $base?"), [
18 | 'y',
19 | 'n'
20 | ]);
21 | if (Console::isYes($rep)) {
22 | if (! DDDManager::setBase($base)) {
23 | echo ConsoleFormatter::showMessage("There was a problem during the base renaming to {$base}!", 'error', 'new-domain');
24 | } else {
25 | echo ConsoleFormatter::showMessage("Domains base was renamed to {$base}!", 'success', 'new-domain');
26 | }
27 | }
28 | }
29 |
30 | $domain = UString::cleanAttribute($what, '_');
31 | if (! DDDManager::domainExists($domain)) {
32 | if (DDDManager::createDomain($domain)) {
33 | $domainBase = DDDManager::getDomainBase($domain);
34 | echo ConsoleFormatter::showMessage("The domain {$domain} was successfully created in $domainBase!", 'success', 'new-domain');
35 | } else {
36 | echo ConsoleFormatter::showMessage("There was a problem during the creation of the domain {$domain}!", 'error', 'new-domain');
37 | }
38 | } else {
39 | echo ConsoleFormatter::showMessage("The domain {$domain} already exists!", 'error', 'new-domain');
40 | }
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewMailCmd.php:
--------------------------------------------------------------------------------
1 | setConfig($config);
19 | $msg = $scaffold->_createClass('mailer.tpl', $classname, $ns, 'use Ubiquity\\mailer\\MailerManager;', $parent, '');
20 | if ($hasView) {
21 | $vName = $scaffold->_createViewOp('mailer', $classname);
22 | }
23 | echo ConsoleFormatter::showMessage("Mailer class {$classname} created!", 'success', 'new-mailer-class');
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewModelCmd.php:
--------------------------------------------------------------------------------
1 | $model) {
71 | $oName = $name;
72 | if ($model->isUpdated()) {
73 | $name .= '*';
74 | }
75 | if (\strtolower($oName) === \strtolower(self::$currentModelName)) {
76 | $result[] = "$name";
77 | } else {
78 | $result[] = $name;
79 | }
80 | }
81 | return \implode(',', $result);
82 | }
83 |
84 | private static function addPk($pk) {
85 | $class = self::$currentModel;
86 | $class->addPk($pk);
87 |
88 | if (! $class->hasField($pk)) {
89 | echo ConsoleFormatter::showMessage("$pk is not in field list", 'warning', 'Add primary keys');
90 | $q = Console::yesNoQuestion("Would you like to add $pk in field list?", [
91 | 'yes',
92 | 'no'
93 | ]);
94 | if (Console::isYes($q)) {
95 | $fieldType = Console::question("Enter field type : ");
96 | self::addFields($pk, $fieldType, '');
97 | }
98 | }
99 | }
100 |
101 | private static function getFieldNames() {
102 | return self::$currentModel->getFieldNames();
103 | }
104 |
105 | private static function addFields($fields, $fieldTypes, $nullables) {
106 | $fields = Console::explodeResponse($fields);
107 | $fieldTypes = Console::explodeResponse($fieldTypes);
108 | $nullables = Console::explodeResponse($nullables);
109 | $newModel = self::$currentModel;
110 | foreach ($fields as $index => $field) {
111 | $field = \trim($field);
112 | if ($field != '') {
113 | $nullable = \array_search($field, $nullables) !== false;
114 | $newModel->addField($field, [
115 | 'Type' => $fieldTypes[$index] ?? DbTypes::DEFAULT_TYPE,
116 | 'Nullable' => $nullable ? 'true' : 'false'
117 | ]);
118 | }
119 | }
120 | }
121 |
122 | private static function generateClasses(string $namespace, string $dbOffset) {
123 | $messages = [];
124 | $classes = [];
125 | foreach (self::$allModels as $name => $newModel) {
126 | $class = $newModel->generateClass($name, $namespace, $dbOffset);
127 | $classes[$name] = $class;
128 | }
129 |
130 | self::createRelations($classes, $namespace);
131 |
132 | foreach (self::$allModels as $name => $newModel) {
133 | if ($newModel->isUpdated()) {
134 | $class = $classes[$name];
135 | $msg = self::createClass($class, $newModel, $name, $namespace);
136 | if ($msg['type'] === 'success') {
137 | $messages['success'][] = $msg['message'];
138 | } else {
139 | $messages['error'][] = $msg['message'];
140 | }
141 | }
142 | }
143 | self::showMessages('success', $messages);
144 | self::showMessages('error', $messages);
145 | $rep = Console::yesNoQuestion('Do you want to re-init models cache?', [
146 | 'yes',
147 | 'no'
148 | ]);
149 | if (Console::isYes($rep)) {
150 | global $argv;
151 | echo shell_exec($argv[0] . ' init-cache -t=models');
152 | }
153 | self::saveModelsInCache();
154 | die();
155 | }
156 |
157 | private static function createRelations($classes, $namespace) {
158 | foreach (self::$allModels as $name => $newModel) {
159 | $manyToOnes = $newModel->getManyToOne();
160 | $oneToManys = $newModel->getOneToMany();
161 | $manyToManys = $newModel->getManyToMany();
162 | $class = $classes[$name];
163 | foreach ($manyToOnes as $member => $manyToOne) {
164 | $class->addManyToOne($member, $manyToOne['fkField'], $namespace . $manyToOne['className'], $member);
165 | }
166 | foreach ($oneToManys as $member => $oneToMany) {
167 | $class->addOneToMany($member, $oneToMany['mappedBy'], $namespace . $oneToMany['className'], $member);
168 | }
169 |
170 | foreach ($manyToManys as $member => $manyToMany) {
171 | $class->addManyToMany($member, $namespace . $manyToMany['otherClassName'], $manyToMany['otherMember'], $manyToMany['joinTable'], $manyToMany['joinColumn'], $manyToMany['otherJoinColumn']);
172 | }
173 | }
174 | }
175 |
176 | private static function showMessages(string $type, array $messages): void {
177 | if (isset($messages[$type])) {
178 | echo ConsoleFormatter::showMessage(\implode(PHP_EOL, $messages[$type]), $type, 'Classes creation');
179 | }
180 | }
181 |
182 | private static function store(string $className, NewModel $newModel): void {
183 | $content = [
184 | 'defaultPk' => ($newModel->getDefaultPk() ?? ''),
185 | 'pks' => $newModel->getPks(),
186 | 'fields' => $newModel->getFields(),
187 | 'manyToOne' => $newModel->getManyToOne(),
188 | 'oneToMany' => $newModel->getOneToMany(),
189 | 'manyToMany' => $newModel->getManyToMany()
190 | ];
191 | CacheManager::$cache->store(self::CACHE_KEY . $className, $content);
192 | }
193 |
194 | private static function loadFromCache(string $className, ?NewModel $newModel = null): void {
195 | $result = CacheManager::$cache->fetch(self::CACHE_KEY . $className);
196 | $newModel ??= self::$currentModel;
197 | $newModel->setFields($result['fields']);
198 | $newModel->setDefaultPk($result['defaultPk']);
199 | $newModel->setPks($result['pks']);
200 | $newModel->setManyToOne($result['manyToOne'] ?? []);
201 | $newModel->setOneToMany($result['oneToMany'] ?? []);
202 | $newModel->setManyToMany($result['manyToMany'] ?? []);
203 | $newModel->setLoadedFromCache(true);
204 | }
205 |
206 | private static function reloadFromExistingClass(string $completeClassName): bool {
207 | if (CacheManager::modelCacheExists($completeClassName)) {
208 | $newModel = self::$currentModel;
209 | $metaDatas = CacheManager::getOrmModelCache($completeClassName);
210 | self::checkAutoInc($newModel, $completeClassName);
211 | $newModel->setPks(\array_keys($metaDatas['#primaryKeys']));
212 | $memberNames = \array_keys($metaDatas['#fieldNames']);
213 | $types = $metaDatas['#fieldTypes'];
214 | $nullables = $metaDatas['#nullable'];
215 | $fields = [];
216 | foreach ($memberNames as $memberName) {
217 | $fields[$memberName] = [
218 | 'Type' => $types[$memberName] ?? 'mixed',
219 | 'Nullable' => in_array($memberName, $nullables) ? 'true' : 'false'
220 | ];
221 | }
222 | $newModel->setFields($fields);
223 | $newModel->setTableName($metaDatas['#tableName']);
224 | self::reloadFromExistingClassRelations($newModel, $metaDatas);
225 | $newModel->setLoadedFromCache(true);
226 | $newModel->setLoaded(true);
227 | return true;
228 | }
229 | return false;
230 | }
231 |
232 | private static function reloadFromExistingClassRelations(NewModel $newModel, array $metaDatas) {
233 | $manyToOnes = $metaDatas['#manyToOne'] ?? [];
234 | $joinColumns = $metaDatas['#joinColumn'] ?? [];
235 | foreach ($manyToOnes as $manyToOne) {
236 | $joinColumn = $joinColumns[$manyToOne];
237 | $newModel->addManyToOne($manyToOne, $joinColumn['name'], ClassUtils::getClassSimpleName($joinColumn['className']));
238 | }
239 |
240 | $oneToManys = $metaDatas['#oneToMany'] ?? [];
241 | foreach ($oneToManys as $member => $oneToMany) {
242 | $newModel->addOneToMany($member, $oneToMany['mappedBy'], ClassUtils::getClassSimpleName($oneToMany['className']));
243 | }
244 |
245 | $manyToManys = $metaDatas['#manyToMany'] ?? [];
246 | $joinTables = $metaDatas['#joinTable'] ?? [];
247 | foreach ($manyToManys as $member => $manyToMany) {
248 | $jointable = $joinTables[$member];
249 | $joinColumn = $jointable['joinColumns'] ?? [];
250 | $inverseJoinColumn = $jointable['inverseJoinColumns'] ?? [];
251 | $newModel->addManyToMany($member, ClassUtils::getClassSimpleName($manyToMany['targetEntity']), $manyToMany['inversedBy'], $jointable['name'], $joinColumn, $inverseJoinColumn);
252 | }
253 | }
254 |
255 | private static function checkAutoInc(NewModel $newModel, string $completeClassName) {
256 | $validationMetas = ValidatorsManager::getCacheInfo($completeClassName);
257 | foreach ($validationMetas as $member => $validators) {
258 | foreach ($validators as $infos) {
259 | if ($infos['type'] === 'id') {
260 | if (($infos['constraints']['autoinc'] ?? false) === true) {
261 | $newModel->setDefaultPk($member);
262 | return;
263 | }
264 | }
265 | }
266 | }
267 | }
268 |
269 | private static function createClass(Model $model, NewModel $newModel, string $modelName, string $namespace): array {
270 | $className = $model->getName();
271 | $modelsDir = UFileSystem::getDirFromNamespace($namespace);
272 | echo ConsoleFormatter::showInfo("Creating the {$className} class");
273 | $classContent = $model->__toString();
274 | if (UFileSystem::save($modelsDir . \DS . $model->getSimpleName() . '.php', $classContent)) {
275 | return [
276 | 'type' => 'success',
277 | 'message' => "Class $className created with success!"
278 | ];
279 | }
280 | return [
281 | 'type' => 'error',
282 | 'message' => "Class $className not generated!"
283 | ];
284 | }
285 |
286 | private static function loadModel(NewModel $newModel, string $modelName, string $namespace): bool {
287 | $modelCompleteName = $namespace . $modelName;
288 |
289 | if (self::$loadCurrentModels && ! $newModel->isLoadedFromCache()) {
290 | self::reloadFromExistingClass($modelCompleteName);
291 | return false;
292 | }
293 | $restrict = false;
294 | if (! $newModel->isLoaded()) {
295 | if (CacheManager::$cache->exists(self::CACHE_KEY . $modelName) && ! \class_exists($modelCompleteName)) {
296 | $rep = Console::yesNoQuestion("A model with the name $modelName was already created.\nWould you like to reload it from cache?", [
297 | 'yes',
298 | 'no'
299 | ]);
300 | if (Console::isYes($rep)) {
301 | self::loadFromCache($modelName);
302 | }
303 | }
304 | if (\class_exists($modelCompleteName)) {
305 | echo ConsoleFormatter::showMessage("The class $modelCompleteName already exists!", 'warning', 'Update model');
306 | $rep = Console::yesNoQuestion('Would you like to modify the existing class?', [
307 | 'yes',
308 | 'no'
309 | ]);
310 | if (Console::isYes($rep)) {
311 | if (self::reloadFromExistingClass($modelCompleteName)) {
312 | echo ConsoleFormatter::showMessage("Loading infos for class $modelCompleteName from DAO cache.", 'info', 'Update model');
313 | } else {
314 | echo ConsoleFormatter::showMessage("No cache infos for $modelCompleteName.", 'error', 'Update model');
315 | die();
316 | }
317 | } else {
318 | $restrict = true;
319 | }
320 | }
321 | $newModel->setLoaded(true);
322 |
323 | if (! $newModel->isLoadedFromCache() && isset(self::$defaultPkValue)) {
324 | $newModel->setDefaultPk(self::$defaultPkValue);
325 | }
326 | }
327 |
328 | return $restrict;
329 | }
330 |
331 | private static function firstLoadAllModels(array $models) {
332 | foreach ($models as $index => $modelName) {
333 | self::getNewModel($modelName, $index === 0);
334 | }
335 | }
336 |
337 | private static function loadModelsFrom(array $config, string $dbOffset = 'default'): array {
338 | $models = CacheManager::getModels($config, true, $dbOffset);
339 | if (\count($models) > 0) {
340 | return \array_map(function ($model) {
341 | return ClassUtils::getClassSimpleName($model);
342 | }, $models);
343 | }
344 | return [];
345 | }
346 |
347 | public static function run(&$config, $options, $what) {
348 | $domain = self::updateDomain($options);
349 | $dbOffset = self::getOption($options, 'd', 'database', 'default');
350 | self::$defaultPkValue = self::getOption($options, 'k', 'autoincPk', 'id');
351 | self::checkDbOffset($config, $dbOffset);
352 |
353 | CacheManager::start($config);
354 |
355 | $models = Console::explodeResponse($what ?? '', function ($item) {
356 | return \ucfirst(\trim($item));
357 | });
358 |
359 | if (\count($models) === 0) {
360 | $models = self::loadModelsFrom($config, $dbOffset);
361 | if (count($models) > 0) {
362 | $rep = Console::yesNoQuestion("Would you like to load the current classes [" . \implode(',', $models) . "]?");
363 | if (Console::isNo($rep)) {
364 | $models = [];
365 | } else {
366 | self::$loadCurrentModels = true;
367 | }
368 | }
369 | }
370 | if (\count($models) > 0) {
371 | self::firstLoadAllModels($models);
372 |
373 | $modelName = self::$currentModelName;
374 | $newModel = self::$currentModel;
375 | } else {
376 | $modelName = Console::question("Enter a model name: ");
377 | $newModel = self::getNewModel($modelName);
378 | }
379 |
380 | $fields = '';
381 | $checkExisting = [];
382 | do {
383 | $namespace = self::getModelNamespace($domain, $dbOffset);
384 | $modelCompleteName = $namespace . $modelName;
385 |
386 | $restrict = self::loadModel($newModel, $modelName, $namespace);
387 | $tableName = $newModel->getTableName();
388 |
389 | echo ConsoleFormatter::showMessage("Model: $modelCompleteName", 'info', 'Model add/update');
390 |
391 | $caseChangeDbOffset = "Change dbOffset [$dbOffset]";
392 | $caseChangeActiveDomain = "Change active Domain [$domain]";
393 | $caseSwitchModel = "Add/switch to model [" . self::getAllModelsAsString() . "]";
394 |
395 | $fields = \implode(',', $newModel->getFieldNames());
396 | $caseAddFields = "Add fields [$fields]";
397 | $caseAddDefaultPk = "Add default auto-inc primary key [" . ($newModel->getDefaultPk() ?? '') . "]";
398 | $caseChangeTableName = "Change table name [$tableName]";
399 | $caseAddRelations = "Add relations [" . $newModel->getRelationsAsString() . "]";
400 |
401 | if (! $restrict) {
402 | $choices = [
403 | $caseAddFields,
404 | $caseAddDefaultPk,
405 | 'Add primary keys',
406 | $caseAddRelations,
407 | $caseChangeTableName,
408 | $caseChangeDbOffset,
409 | $caseChangeActiveDomain,
410 | $caseSwitchModel,
411 | 'Generate classes',
412 | 'Quit'
413 | ];
414 | } else {
415 | $choices = [
416 | 'Change class name',
417 | $caseChangeDbOffset,
418 | $caseChangeActiveDomain,
419 | 'Quit'
420 | ];
421 | }
422 | $rep = Console::question('Select your choices:', $choices);
423 |
424 | switch ($rep) {
425 |
426 | case 'Change class name':
427 | $modelName = Console::question("Enter model name: ");
428 | $modelName = \ucfirst($modelName);
429 | unset(self::$allModels[self::$currentModelName]);
430 | self::$allModels[$modelName] = self::$currentModel;
431 | self::$currentModelName = $modelName;
432 | $newModel->setUpdated(true);
433 | break;
434 |
435 | case $caseChangeTableName:
436 | $tbl = Console::question('Enter table name:');
437 | $newModel->setTableName(($tbl == '') ? null : $tbl);
438 | $newModel->setUpdated(true);
439 | break;
440 |
441 | case $caseAddFields:
442 | $field = Console::question("Enter field names: ");
443 | if ($field != '') {
444 | $fieldTypes = Console::question("Enter field types: ");
445 | $nullables = Console::question("Nullable fields: ");
446 | self::addFields($field, $fieldTypes, $nullables);
447 | $newModel->setUpdated(true);
448 | }
449 | break;
450 |
451 | case $caseSwitchModel:
452 | $modelName = Console::question('Enter an existing or a new model name:');
453 | $modelName = \ucfirst($modelName);
454 | $newModel = self::getNewModel($modelName);
455 | break;
456 |
457 | case 'Add primary keys':
458 | $pks = Console::question('Enter primary keys: ');
459 | $newModel->updatePks($pks);
460 | $newModel->setUpdated(true);
461 | break;
462 |
463 | case $caseAddRelations:
464 | $rType = Console::question('Type: ', [
465 | 'manyToOne',
466 | 'oneToMany',
467 | 'manyToMany'
468 | ]);
469 | self::addRelation($rType, $newModel, $namespace);
470 | break;
471 |
472 | case $caseAddDefaultPk:
473 | $newModel->setDefaultPk(Console::question('Primary key name: '));
474 | $newModel->setUpdated(true);
475 | break;
476 |
477 | case $caseChangeDbOffset:
478 | $dbOffset = Console::question('Database offset: ');
479 | self::checkDbOffset($config, $dbOffset);
480 | break;
481 |
482 | case $caseChangeActiveDomain:
483 | $newDomain = Console::question('Domain: ');
484 | $domain = self::updateDomain([
485 | 'o' => $newDomain
486 | ]);
487 | if ($domain == '') {
488 | DDDManager::resetActiveDomain();
489 | }
490 | break;
491 |
492 | case 'Generate classes':
493 | self::generateClasses(self::getModelNamespace($domain, $dbOffset), $dbOffset);
494 | break;
495 |
496 | default:
497 | self::saveModelsInCache();
498 | echo ConsoleFormatter::showInfo('Operation terminated, Bye!');
499 | }
500 | } while ($rep !== 'Quit');
501 | }
502 |
503 | private static function saveModelsInCache() {
504 | $cached = [];
505 | foreach (self::$allModels as $modelName => $newModel) {
506 | if ($newModel->isUpdated()) {
507 | self::store($modelName, $newModel);
508 | $cached[] = $modelName;
509 | }
510 | }
511 | if (\count($cached) > 0) {
512 | echo ConsoleFormatter::showInfo("Data caching for the models: " . \implode(',', $cached));
513 | }
514 | }
515 |
516 | private static function addRelation(string $rType, NewModel $newModel, string $namespace) {
517 | $modelName = $newModel->getOriginalModelName();
518 |
519 | switch ($rType) {
520 | case 'manyToOne':
521 | $fkClass = Console::question('Foreign member className:', \array_keys(self::$allModels), [
522 | 'ignoreCase' => true
523 | ]);
524 | $otherModel = self::getNewModel($fkClass, false);
525 | $otherModelName = $otherModel->getOriginalModelName();
526 |
527 | $padmax = \strlen("OneToMany member name in $otherModelName:");
528 |
529 | $fkField = Console::question(\str_pad('Foreign key name:', $padmax), null, [
530 | 'default' => 'id' . \ucfirst($otherModelName)
531 | ]);
532 | $member = Console::question(\str_pad('Member name:', $padmax), null, [
533 | 'default' => \lcfirst($otherModelName)
534 | ]);
535 |
536 | $manyMember = Console::question(\str_pad("OneToMany member name in $otherModelName:", $padmax), null, [
537 | 'default' => \lcfirst($modelName) . 's'
538 | ]);
539 |
540 | $newModel->addManyToOne($member, $fkField, $otherModelName);
541 | if (! $otherModel->isLoaded()) {
542 | self::loadModel($otherModel, $otherModelName, $namespace);
543 | }
544 | $otherModel->addOneToMany($manyMember, $member, $modelName);
545 |
546 | $newModel->setUpdated(true);
547 | $otherModel->setUpdated(true);
548 | break;
549 | case 'manyToMany':
550 | $padmax = 45;
551 | $fkClass = Console::question(\str_pad('Associated className:', $padmax), \array_keys(self::$allModels), [
552 | 'ignoreCase' => true
553 | ]);
554 | $otherModel = self::getNewModel($fkClass, false);
555 | $otherModelName = $otherModel->getOriginalModelName();
556 |
557 | $member = Console::question(\str_pad("Associated member name in $modelName:", $padmax), null, [
558 | 'default' => \lcfirst($otherModelName) . 's'
559 | ]);
560 | $otherAssociatedFk = Console::question(\str_pad("Associated fk name for $otherModelName:", $padmax), null, [
561 | 'default' => 'id' . \ucfirst($otherModelName)
562 | ]);
563 |
564 | $otherMember = Console::question(\str_pad("Associated member name in $otherModelName:", $padmax), null, [
565 | 'default' => \lcfirst($modelName) . 's'
566 | ]);
567 | $associatedFk = Console::question(\str_pad("Associated fk name for $modelName:", $padmax), null, [
568 | 'default' => 'id' . \ucfirst($modelName)
569 | ]);
570 | $jointable = Console::question(\str_pad('Jointable:', $padmax), null, [
571 | 'default' => \lcfirst($modelName) . '_' . \lcfirst($otherModelName) . 's'
572 | ]);
573 |
574 | $joinColumn = ($associatedFk !== $newModel->getDefaultFk()) ? [
575 | 'name' => $associatedFk,
576 | 'referencedColumnName' => $newModel->getFirstPk()
577 | ] : [];
578 | $otherJoinColumn = ($otherAssociatedFk !== $otherModel->getDefaultFk()) ? [
579 | 'name' => $otherAssociatedFk,
580 | 'referencedColumnName' => $otherModel->getFirstPk()
581 | ] : [];
582 |
583 | $newModel->addManyToMany($member, $otherModelName, $otherMember, $jointable, $joinColumn, $otherJoinColumn);
584 | if (! $otherModel->isLoaded()) {
585 | self::loadModel($otherModel, $otherModelName, $namespace);
586 | }
587 | $otherModel->addManyToMany($otherMember, $modelName, $member, $jointable, $otherJoinColumn, $joinColumn);
588 | $newModel->setUpdated(true);
589 | $otherModel->setUpdated(true);
590 |
591 | break;
592 | case 'oneToMany':
593 | $padmax = 45;
594 | $fkClass = Console::question(\str_pad('Associated member className:', $padmax), \array_keys(self::$allModels), [
595 | 'ignoreCase' => true
596 | ]);
597 | $otherModel = self::getNewModel($fkClass, false);
598 | $otherModelName = $otherModel->getOriginalModelName();
599 |
600 | $fkField = Console::question(\str_pad('Foreign key name:', $padmax), null, [
601 | 'default' => 'id' . \ucfirst($modelName)
602 | ]);
603 | $member = Console::question(\str_pad('Member name:', $padmax), null, [
604 | 'default' => \lcfirst($otherModelName) . 's'
605 | ]);
606 | $mappedBy = Console::question(\str_pad("MappedBy member name in $otherModelName:", $padmax), null, [
607 | 'default' => \lcfirst($modelName)
608 | ]);
609 |
610 | $newModel->addOneToMany($member, $mappedBy, $otherModelName);
611 | if (! $otherModel->isLoaded()) {
612 | self::loadModel($otherModel, $otherModelName, $namespace);
613 | }
614 | $otherModel->addManyToOne($mappedBy, $fkField, $modelName);
615 | $newModel->setUpdated(true);
616 | $otherModel->setUpdated(true);
617 | break;
618 | }
619 | }
620 | }
621 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/NewThemeCmd.php:
--------------------------------------------------------------------------------
1 | %s from %s', $what, $extend));
21 | InstallThemeCmd::addTheme($what, $extend, $themesConfig[$extend], $activeDir, true);
22 | } else {
23 | echo ConsoleFormatter::showMessage(sprintf('The theme %s does not exists!', $extend), 'error', 'Theme creation');
24 | }
25 | }
26 | } else {
27 | echo ConsoleFormatter::showMessage(sprintf('The theme %s is a reserved theme name!', $what), 'error', 'Theme creation');
28 | }
29 | }
30 |
31 | public static function addNew($what, $activeDir) {
32 | $msg = "";
33 | $baseDir = getcwd();
34 | $dest = $baseDir . '/public/assets/' . $what;
35 | if (! file_exists($dest)) {
36 | $sourceAssets = $activeDir . '/devtools/project-files/public/themes/model/';
37 | echo ConsoleFormatter::showInfo("Assets creation...");
38 | FileUtils::xcopy($sourceAssets, $dest);
39 | } else {
40 | $msg = sprintf("Assets creation failed : %s directory exists!\n", $dest);
41 | }
42 | $sourceView = $activeDir . '/devtools/project-files/app/views/themes/model/';
43 | $dest = DDDManager::getActiveViewFolder() . "themes/" . $what;
44 | if (! file_exists($dest)) {
45 | echo ConsoleFormatter::showInfo("Views creation...");
46 | FileUtils::xcopy($sourceView, $dest);
47 | } else {
48 | $msg = sprintf("Views creation failed : %s directory exists!\n", $dest);
49 | }
50 | if ($msg !== "") {
51 | echo ConsoleFormatter::showMessage($msg, "error", "Theme creation");
52 | } else {
53 | self::saveActiveTheme($what);
54 | echo ConsoleFormatter::showMessage(sprintf('Theme %s created with success!', $what), "success", "Theme creation");
55 | }
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/RestApiCmd.php:
--------------------------------------------------------------------------------
1 | addJsonRestController($what, $routePath);
17 | } else {
18 | $scaffold->addRestApiController($what, $routePath);
19 | }
20 | }
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/RestCmd.php:
--------------------------------------------------------------------------------
1 | addRestController($what, RestResourceController::class, $resource, $routePath);
19 | } else {
20 | echo ConsoleFormatter::showMessage("The models class {$resource} does not exists!", 'error', 'rest-controller');
21 | }
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/SendMailQueueCmd.php:
--------------------------------------------------------------------------------
1 | 0) {
22 | MailerManager::saveQueue();
23 | echo ConsoleFormatter::showMessage($count . ' email(s) sent with success!', 'success', 'Send mails from Queue');
24 | } else {
25 | echo ConsoleFormatter::showMessage('No mail sent!', 'info', 'Send mails from Queue');
26 | }
27 | }
28 | }
29 |
30 | private static function _sendMailQueue($index) {
31 | if (MailerManager::sendQueuedMail(-- $index)) {
32 | MailerManager::saveQueue();
33 | echo ConsoleFormatter::showMessage('Email sent with success!', 'success', 'Send mail from Queue');
34 | } else {
35 | echo ConsoleFormatter::showMessage(MailerManager::getErrorInfo(), 'error', 'Send mail from Queue');
36 | }
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/TemplateParserCmd.php:
--------------------------------------------------------------------------------
1 | generateTemplateSource($fileContent);
33 | $dDest = $destination . $ds . $realPath . $ds;
34 | UFileSystem::safeMkdir($dDest);
35 | \file_put_contents($dDest . $filename, $code);
36 | echo ConsoleFormatter::showInfo("$filename parsed to $destEngine in $destination");
37 | }
38 | } else {
39 | echo ConsoleFormatter::showMessage("Invalid template $destEngine", 'error', 'Template parser');
40 | }
41 | }
42 |
43 | private static function runComposer(array $commands, string $name) {
44 | if (isset($commands['repositories'])) {
45 | $repositories = $commands['repositories'];
46 | foreach ($repositories as $index => $repository) {
47 | $type = $repository['type'];
48 | $url = $repository['url'];
49 | \system("composer config repositories.{$name}{$index} $type $url");
50 | }
51 | }
52 | if (isset($commands['require'])) {
53 | $requires = $commands['require'];
54 | foreach ($requires as $require => $version) {
55 | \system('composer require ' . $require . ':' . $version);
56 | }
57 | }
58 | if (isset($commands['require-dev'])) {
59 | $requires = $commands['require-dev'];
60 | foreach ($requires as $require => $version) {
61 | \system('composer require ' . $require . ':' . $version . ' --dev');
62 | }
63 | }
64 | }
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/popo/NewModel.php:
--------------------------------------------------------------------------------
1 | originalModelName = $modelName;
34 | }
35 |
36 | /**
37 | *
38 | * @return string
39 | */
40 | public function getOriginalModelName(): string {
41 | return $this->originalModelName;
42 | }
43 |
44 | /**
45 | *
46 | * @param string $originalModelName
47 | */
48 | public function setOriginalModelName(string $originalModelName): void {
49 | $this->originalModelName = $originalModelName;
50 | }
51 |
52 | /**
53 | *
54 | * @return string
55 | */
56 | public function getTableName(): string {
57 | return $this->tableName ?? (\lcfirst($this->originalModelName));
58 | }
59 |
60 | /**
61 | *
62 | * @param string|null $tableName
63 | */
64 | public function setTableName(?string $tableName): void {
65 | $this->tableName = $tableName;
66 | }
67 |
68 | /**
69 | *
70 | * @return string|null
71 | */
72 | public function getDefaultPk(): ?string {
73 | return $this->defaultPk;
74 | }
75 |
76 | public function getDefaultFk(): string {
77 | return 'id' . \ucfirst($this->originalModelName);
78 | }
79 |
80 | public function hasDefaultPk(): bool {
81 | return isset($this->defaultPk) && $this->defaultPk != '';
82 | }
83 |
84 | /**
85 | *
86 | * @param string|null $defaultPk
87 | */
88 | public function setDefaultPk(?string $defaultPk): void {
89 | $this->defaultPk = $defaultPk;
90 | }
91 |
92 | /**
93 | *
94 | * @return array
95 | */
96 | public function getPks(): array {
97 | return $this->pks;
98 | }
99 |
100 | public function resetPks() {
101 | $this->pks = [];
102 | }
103 |
104 | /**
105 | *
106 | * @param array $pks
107 | */
108 | public function setPks(array $pks): void {
109 | $this->pks = $pks;
110 | }
111 |
112 | public function addPk(string $pk): bool {
113 | if (! \in_array($pk, $this->pks)) {
114 | $this->pks[] = $pk;
115 | return true;
116 | }
117 | return false;
118 | }
119 |
120 | /**
121 | *
122 | * @return array
123 | */
124 | public function getFields(): array {
125 | return $this->fields;
126 | }
127 |
128 | /**
129 | *
130 | * @param array $fields
131 | */
132 | public function setFields(array $fields): void {
133 | $this->fields = $fields;
134 | }
135 |
136 | public function addField(string $name, array $fieldInfos) {
137 | $this->fields[$name] = $fieldInfos;
138 | }
139 |
140 | public function hasField(string $name): bool {
141 | return isset($this->fields[$name]);
142 | }
143 |
144 | public function getFieldNames(): array {
145 | if (\is_array($this->fields)) {
146 | return \array_keys($this->fields);
147 | }
148 | return [];
149 | }
150 |
151 | public function updateFirstPk() {
152 | if ($this->hasDefaultPk()) {
153 | $this->addField($this->defaultPk, [
154 | 'Type' => 'int',
155 | 'Nullable' => 'false'
156 | ]);
157 | $this->addPk($this->defaultPk);
158 | }
159 | }
160 |
161 | public function getFirstPk(): ?string {
162 | return $this->defaultPk ?? ($this->pks[0] ?? null);
163 | }
164 |
165 | public function updatePks($pks) {
166 | $pks = \explode(',', $pks);
167 | $this->pks = [];
168 | $this->updateFirstPk();
169 | foreach ($pks as $pk) {
170 | $this->addPk($pk);
171 | }
172 | }
173 |
174 | public function setFieldsOrder() {
175 | $result = [];
176 | $fields = $this->fields;
177 | $pks = $this->getPks();
178 | foreach ($pks as $pk) {
179 | $result[$pk] = $fields[$pk];
180 | unset($fields[$pk]);
181 | }
182 | foreach ($fields as $field => $fieldInfos) {
183 | $result[$field] = $fieldInfos;
184 | }
185 | $this->fields = $result;
186 | }
187 |
188 | public function getSimpleMembers() {
189 | $members = [];
190 | foreach ($this->fields as $name => $fieldInfos) {
191 | if ($fieldInfos['Type'] !== 'mixed') {
192 | $members[] = $name;
193 | }
194 | }
195 | return $members;
196 | }
197 |
198 | public function generateClass($className, $namespace, $dbOffset): Model {
199 | $memberAccess = 'private';
200 | $this->updateFirstPk();
201 | $this->setFieldsOrder();
202 | $engine = CacheManager::getAnnotationsEngineInstance();
203 | $class = new Model($engine, \lcfirst($className), $namespace, $memberAccess);
204 | $class->setTable($this->getTableName());
205 | $class->setDatabase($dbOffset);
206 | $fieldsInfos = $this->selectFieldsForGeneration();
207 | $class->setSimpleMembers($this->getSimpleMembers());
208 | $keys = $this->pks;
209 | foreach ($fieldsInfos as $field => $info) {
210 | $member = new Member($class, $engine, $field, $memberAccess);
211 | if (\in_array($field, $keys)) {
212 | $member->setPrimary();
213 | }
214 | $member->setDbType($info);
215 | $member->addValidators();
216 | $member->setTransformer();
217 | $class->addMember($member);
218 | }
219 | $class->addMainAnnots();
220 | return $class;
221 | }
222 |
223 | private function selectFieldsForGeneration() {
224 | $fieldsInRelation = $this->getFieldsInRelations();
225 | $result = [];
226 | foreach ($this->fields as $f => $infos) {
227 | if (! in_array($f, $fieldsInRelation)) {
228 | $result[$f] = $infos;
229 | }
230 | }
231 | return $result;
232 | }
233 |
234 | private function getFieldsInRelations() {
235 | $result = [];
236 | foreach ($this->manyToOne as $f => $_) {
237 | $result[] = $f;
238 | }
239 | foreach ($this->oneToMany as $f => $_) {
240 | $result[] = $f;
241 | }
242 | foreach ($this->manyToMany as $f => $_) {
243 | $result[] = $f;
244 | }
245 | return $result;
246 | }
247 |
248 | public function addManyToOne($member, $fkField, $className) {
249 | $this->manyToOne[$member] = \compact('fkField', 'className');
250 | }
251 |
252 | public function addOneToMany($member, $mappedBy, $className) {
253 | $this->oneToMany[$member] = \compact('mappedBy', 'className');
254 | }
255 |
256 | public function addManyToMany($member, $otherClassName, $otherMember, $joinTable, $joinColumn, $otherJoinColumn) {
257 | $this->manyToMany[$member] = compact('otherClassName', 'otherMember', 'joinTable', 'joinColumn', 'otherJoinColumn');
258 | }
259 |
260 | /**
261 | *
262 | * @return array
263 | */
264 | public function getManyToOne(): array {
265 | return $this->manyToOne;
266 | }
267 |
268 | /**
269 | *
270 | * @return array
271 | */
272 | public function getOneToMany(): array {
273 | return $this->oneToMany;
274 | }
275 |
276 | /**
277 | *
278 | * @return array
279 | */
280 | public function getManyToMany(): array {
281 | return $this->manyToMany;
282 | }
283 |
284 | /**
285 | *
286 | * @return bool
287 | */
288 | public function isLoaded(): bool {
289 | return $this->loaded;
290 | }
291 |
292 | /**
293 | *
294 | * @param bool $loaded
295 | */
296 | public function setLoaded(bool $loaded): void {
297 | $this->loaded = $loaded;
298 | }
299 |
300 | /**
301 | *
302 | * @return bool
303 | */
304 | public function isUpdated(): bool {
305 | return $this->updated;
306 | }
307 |
308 | /**
309 | *
310 | * @param bool $updated
311 | */
312 | public function setUpdated(bool $updated): void {
313 | $this->updated = $updated;
314 | }
315 |
316 | /**
317 | *
318 | * @param array $manyToOne
319 | */
320 | public function setManyToOne(array $manyToOne): void {
321 | $this->manyToOne = $manyToOne;
322 | }
323 |
324 | /**
325 | *
326 | * @param array $oneToMany
327 | */
328 | public function setOneToMany(array $oneToMany): void {
329 | $this->oneToMany = $oneToMany;
330 | }
331 |
332 | /**
333 | *
334 | * @param array $manyToMany
335 | */
336 | public function setManyToMany(array $manyToMany): void {
337 | $this->manyToMany = $manyToMany;
338 | }
339 |
340 | public function getRelationsAsString() {
341 | $result = '';
342 | if (\count($this->manyToOne) > 0) {
343 | $result .= ' (1)=>(' . \implode(',', \array_keys($this->manyToOne)) . ')';
344 | }
345 | if (\count($this->oneToMany) > 0) {
346 | $result .= ' (1-*)=>(' . \implode(',', \array_keys($this->oneToMany)) . ')';
347 | }
348 | if (\count($this->manyToMany) > 0) {
349 | $result .= ' (*-*)=>(' . \implode(',', \array_keys($this->manyToMany)) . ')';
350 | }
351 | return $result;
352 | }
353 |
354 | /**
355 | *
356 | * @return bool
357 | */
358 | public function isLoadedFromCache(): bool {
359 | return $this->loadedFromCache;
360 | }
361 |
362 | /**
363 | *
364 | * @param bool $loadedFromCache
365 | */
366 | public function setLoadedFromCache(bool $loadedFromCache): void {
367 | $this->loadedFromCache = $loadedFromCache;
368 | }
369 | }
370 |
--------------------------------------------------------------------------------
/src/devtools/cmd/commands/traits/DbCheckTrait.php:
--------------------------------------------------------------------------------
1 | 0) {
21 | ob_start();
22 | CacheManager::initCache($config, 'models');
23 | $res = ob_get_clean();
24 | echo ConsoleFormatter::showMessage($res, 'success', 'init-cache: models');
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/devtools/core/ConsoleScaffoldController.php:
--------------------------------------------------------------------------------
1 | create($this, $reInit);
37 | }
38 |
39 | public function addRestApiController($restControllerName, $routePath = "", $reInit = true) {
40 | $this->addRestController($restControllerName, JsonApiRestController::class, '', $routePath, $reInit);
41 | }
42 |
43 | public function addJsonRestController($restControllerName, $routePath = "", $reInit = true) {
44 | $this->addRestController($restControllerName, JsonRestController::class, '', $routePath, $reInit);
45 | }
46 |
47 | public function initRestCache($refresh = true) {
48 | $config = Startup::getConfig();
49 | \ob_start();
50 | CacheManager::initCache($config, "rest");
51 | CacheManager::initCache($config, "controllers");
52 | $message = \ob_get_clean();
53 | echo $this->showSimpleMessage($message, "info", "Rest", "info cache re-init");
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/src/devtools/core/themesConfig.php:
--------------------------------------------------------------------------------
1 | [
4 | 'composer'=>['twitter/bootstrap'=>'^4.3','fortawesome/font-awesome'=>'^5.7'],
5 | 'vendor-copy'=>[
6 | '/vendor/fortawesome/font-awesome/css/all.min.css'=>'/public/assets/%theme%/css/all.min.css',
7 | '/vendor/fortawesome/font-awesome/webfonts'=>'/public/assets/%theme%/webfonts',
8 | ]
9 | ],
10 | 'foundation'=>[
11 | 'composer'=>['zurb/foundation'=>'^6.5']
12 | ],
13 | 'semantic'=>[
14 | 'composer'=>['fomantic/ui'=>'^2.8','frameworks/jquery'=> '~2.1'],
15 | 'vendor-copy'=>[
16 | '/vendor/fomantic/ui/dist/semantic.min.css'=>'/public/assets/%theme%/css/semantic.min.css',
17 | '/vendor/fomantic/ui/dist/semantic.min.js'=>'/public/assets/%theme%/js/semantic.min.js',
18 | '/vendor/frameworks/jquery/jquery.min.js'=>'/public/assets/%theme%/js/jquery.min.js'
19 | ]
20 | ]
21 | ];
22 |
--------------------------------------------------------------------------------
/src/devtools/core/toolsConfig.php:
--------------------------------------------------------------------------------
1 | [
4 | "jquery" => "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js",
5 | "bootstrap" => [
6 | "css" => "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css",
7 | "js" => "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"
8 | ],
9 | "semantic" => [
10 | "css" => "https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.css",
11 | "js" => "https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"
12 | ],
13 | "diff2html" => [
14 | "css" => "https://cdnjs.cloudflare.com/ajax/libs/diff2html/2.12.2/diff2html.min.css"
15 | ]
16 | ],
17 | "composer" => [
18 | "require" => [
19 | "php" => ">=7.4",
20 | "twig/twig" => "^3.0",
21 | "phpmv/ubiquity" => "^2.5"
22 | ],
23 | "require-dev" => [
24 | "monolog/monolog" => "^2.2",
25 | "phpmv/ubiquity-dev" => "^0.1",
26 | "phpmv/ubiquity-debug" => "^0.0"
27 | ],
28 | "autoload" => [
29 | "psr-4" => [
30 | "" => "app/"
31 | ]
32 | ]
33 | ]
34 | ];
35 |
--------------------------------------------------------------------------------
/src/devtools/project-files/.htaccess:
--------------------------------------------------------------------------------
1 | AddDefaultCharset UTF-8
2 |
3 |
4 | RewriteEngine On
5 | RewriteBase /%rewriteBase%/
6 |
7 | RewriteCond %{REQUEST_FILENAME} !-f
8 | RewriteCond %{HTTP_ACCEPT} !(.*images.*)
9 | RewriteRule ^(.*)$ index.php?c=$1 [L,QSA]
10 |
11 |
--------------------------------------------------------------------------------
/src/devtools/project-files/README.md:
--------------------------------------------------------------------------------
1 | # %projectName%
2 |
3 | This README outlines the details of collaborating on this Ubiquity application.
4 | A short introduction of this app could easily go here.
5 |
6 | ## Prerequisites
7 |
8 | You will need the following things properly installed on your computer.
9 |
10 | * php >=7.4
11 | * [Git](https://git-scm.com/)
12 | * [Composer](https://getcomposer.org)
13 | * [Ubiquity devtools](https://ubiquity.kobject.net/)
14 |
15 | ## Installation
16 |
17 | * `git clone ` this repository
18 | * `cd %projectName%`
19 | * `composer install`
20 |
21 | ## Running / Development
22 |
23 | * `Ubiquity serve`
24 | * Visit your app at [http://127.0.0.1:8090](http://127.0.0.1:8090).
25 |
26 | ### devtools
27 |
28 | Make use of the many generators for code, try `Ubiquity help` for more details
29 |
30 | ### Optimization for production
31 |
32 | Run:
33 | `composer install --optimize --no-dev --classmap-authoritative`
34 |
35 | ### Deploying
36 |
37 | Specify what it takes to deploy your app.
38 |
39 | ## Further Reading / Useful Links
40 |
41 | * [Ubiquity website](https://ubiquity.kobject.net/)
42 | * [Guide](http://micro-framework.readthedocs.io/en/latest/?badge=latest)
43 | * [Doc API](https://api.kobject.net/ubiquity/)
44 | * [Twig documentation](https://twig.symfony.com)
45 | * [Semantic-UI](https://semantic-ui.com)
46 |
--------------------------------------------------------------------------------
/src/devtools/project-files/app/.htaccess:
--------------------------------------------------------------------------------
1 | deny from all
--------------------------------------------------------------------------------
/src/devtools/project-files/app/controllers/Admin.php:
--------------------------------------------------------------------------------
1 | loadView($this->headerView);
19 | }
20 | }
21 |
22 | public function finalize() {
23 | if (! URequest::isAjax()) {
24 | $this->loadView($this->footerView);
25 | }
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/devtools/project-files/app/controllers/IndexController.php:
--------------------------------------------------------------------------------
1 | 0) {
21 | $this->loadView('@activeTheme/main/vMenu.html', \compact('themes', 'activeTheme'));
22 | }
23 | $this->loadView($defaultPage, \compact('defaultPage', 'links', 'infos', 'activeTheme'));
24 | }
25 |
26 | public function ct($theme) {
27 | $themes = Display::getThemes();
28 | if ($theme != null && \array_search($theme, $themes) !== false) {
29 | $config = ThemesManager::saveActiveTheme($theme);
30 | \header('Location: ' . $config['siteUrl']);
31 | } else {
32 | Logger::warn('Themes', \sprintf('The theme %s does not exists!', $theme), 'changeTheme(ct)');
33 | $this->forward(IndexController::class);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/devtools/project-files/app/views/themes/bootstrap/main/vFooter.html:
--------------------------------------------------------------------------------
1 | {% block footer %}
2 | {% endblock %}
3 | {% block scripts %}
4 |
5 |
6 |
7 | {% endblock %}
8 |