Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
143 / 143
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
AppRouterFactory
100.00% covered (success)
100.00%
142 / 142
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 createMatcher
100.00% covered (success)
100.00%
142 / 142
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Router;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use Yiisoft\Http\Method;
12use Yiisoft\Router\FastRoute\UrlMatcher;
13use Yiisoft\Router\Group;
14use Yiisoft\Router\Route;
15use Yiisoft\Router\RouteCollection;
16use Yiisoft\Router\RouteCollector;
17use Yiisoft\Router\UrlMatcherInterface;
18
19/**
20 * AppRouterFactory.
21 *
22 * Constructs and configures the compiled FastRoute URL matcher and route collections for all modules.
23 *
24 * @package App\Core\Router
25 */
26final class AppRouterFactory
27{
28    private const string ROUTE_TAX_RATE_ITEM = '/api/v1/tax/rates/{id:\d+}';
29    private const string ROUTE_DISCOUNT_ITEM = '/api/v1/discounts/{id:\d+}';
30
31    /**
32     * Builds the unified application UrlMatcher.
33     *
34     * @return UrlMatcherInterface Configured FastRoute URL matcher.
35     */
36    public static function createMatcher(): UrlMatcherInterface
37    {
38        $collector = new RouteCollector();
39
40        $dummyAction = static fn(): null => null;
41
42        $routes = [
43            // Static & Docs
44            Route::get('/api')->action($dummyAction)->name('api_doc_ui'),
45            Route::get('/api/')->action($dummyAction)->name('api_doc_ui_slash'),
46            Route::get('/api/v1/openapi.json')->action($dummyAction)->name('openapi_spec'),
47            Route::post('/api/v1/logs/js-error')->action($dummyAction)->name('js_error_log'),
48
49            // Auth
50            Route::methods([Method::GET, Method::POST], '/login')->action($dummyAction)->name('web_login'),
51            Route::methods([Method::GET, Method::POST], '/logout')->action($dummyAction)->name('web_logout'),
52            Route::post('/api/v1/auth/login')->action($dummyAction)->name('api_auth_login'),
53            Route::post('/api/v1/auth/logout')->action($dummyAction)->name('api_auth_logout'),
54            Route::get('/api/v1/auth/me')->action($dummyAction)->name('api_auth_me'),
55
56            // Locale & I18n
57            Route::post('/api/v1/locale/change')->action($dummyAction)->name('api_locale_change'),
58            Route::get('/api/v1/locale/translations')->action($dummyAction)->name('api_translations'),
59
60            // Calendar RSVP
61            Route::get('/calendar/rsvp')->action($dummyAction)->name('web_calendar_rsvp'),
62            Route::get('/calendar/rsvp/download')->action($dummyAction)->name('web_calendar_rsvp_download'),
63
64            // Mail
65            Route::post('/api/v1/mail/smtp/{id:\d+}/test-connection')->action($dummyAction)->name('api_mail_test_smtp'),
66            Route::post('/api/v1/mail/servers/{id:\d+}/test-connection')
67                ->action($dummyAction)
68                ->name('api_mail_test_server'),
69            Route::post('/api/v1/mail/mailboxes/{id:\d+}/test-connection')
70                ->action($dummyAction)
71                ->name('api_mail_test_mailbox'),
72            Route::post('/api/v1/mail/enqueue')->action($dummyAction)->name('api_mail_enqueue'),
73
74            // About & System Diagnostics
75            Route::get('/api/v1/about/licenses')->action($dummyAction)->name('api_about_licenses'),
76            Route::get('/api/v1/about/requirements')->action($dummyAction)->name('api_about_requirements'),
77
78            // Menu
79            Route::get('/api/v1/menu')->action($dummyAction)->name('api_menu_tree'),
80
81            // Central Engine API
82            Route::get('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/list')
83                ->action($dummyAction)
84                ->name('api_engine_list'),
85            Route::get('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/schema')
86                ->action($dummyAction)
87                ->name('api_engine_schema'),
88            Route::get('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/read/{id:\d+}')
89                ->action($dummyAction)
90                ->name('api_engine_read'),
91            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/create')
92                ->action($dummyAction)
93                ->name('api_engine_create'),
94            Route::methods([Method::PUT, Method::PATCH], '/api/v1/engine/{module:[a-zA-Z0-9_-]+}/update/{id:\d+}')
95                ->action($dummyAction)
96                ->name('api_engine_update'),
97            Route::delete('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/delete/{id:\d+}')
98                ->action($dummyAction)
99                ->name('api_engine_delete'),
100            Route::get('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/timeline/{id:\d+}')
101                ->action($dummyAction)
102                ->name('api_engine_timeline'),
103            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/{id:\d+}/favorite')
104                ->action($dummyAction)
105                ->name('api_engine_favorite'),
106            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/{id:\d+}/pin')
107                ->action($dummyAction)
108                ->name('api_engine_pin'),
109            Route::get('/api/v1/engine/picklist/values')
110                ->action($dummyAction)
111                ->name('api_picklist_values'),
112            Route::get('/api/v1/engine/fields/{moduleId:\d+}')
113                ->action($dummyAction)
114                ->name('api_module_fields'),
115            Route::get('/api/v1/engine/{module:[a-z0-9_]+}/fields')
116                ->action($dummyAction)
117                ->name('api_engine_module_fields'),
118            Route::get('/api/v1/engine/relations/{moduleId:\d+}')
119                ->action($dummyAction)
120                ->name('api_module_relations'),
121
122            // Data Exchange Endpoints (Import / Export)
123            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/export')
124                ->action($dummyAction)
125                ->name('api_engine_export'),
126            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/import/analyze')
127                ->action($dummyAction)
128                ->name('api_engine_import_analyze'),
129            Route::post('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/import/execute')
130                ->action($dummyAction)
131                ->name('api_engine_import_execute'),
132            Route::get('/api/v1/engine/{module:[a-zA-Z0-9_-]+}/import/jobs/{id:\d+}')
133                ->action($dummyAction)
134                ->name('api_engine_import_job_status'),
135
136            // Gantt & Kanban Endpoints
137            Route::get('/api/v1/projects/gantt')->action($dummyAction)->name('api_projects_gantt_all'),
138            Route::get('/api/v1/projects/{id:\d+}/gantt')->action($dummyAction)->name('api_projects_gantt'),
139            Route::get('/api/v1/project-stages/{id:\d+}/gantt')->action($dummyAction)->name('api_stages_gantt'),
140            Route::get('/api/v1/{module:[a-zA-Z0-9_-]+}/kanban')->action($dummyAction)->name('api_kanban_data'),
141            Route::methods(
142                [Method::PATCH, Method::PUT, Method::POST],
143                '/api/v1/{module:[a-zA-Z0-9_-]+}/{id:\d+}/status'
144            )->action($dummyAction)->name('api_kanban_status_update'),
145
146            // PDF Engine & Template Endpoints
147            Route::get('/api/v1/pdf/templates')->action($dummyAction)->name('api_pdf_templates'),
148            Route::get('/api/v1/pdf/variables')->action($dummyAction)->name('api_pdf_variables'),
149            Route::post('/api/v1/pdf/compile-blocks')->action($dummyAction)->name('api_pdf_compile_blocks'),
150            Route::get('/api/v1/pdf/generate/{templateId:\d+}/{recordId:\d+}')
151                ->action($dummyAction)
152                ->name('api_pdf_generate'),
153
154            // Tax Endpoints
155            Route::get('/api/v1/tax/rates')->action($dummyAction)->name('api_tax_rates_list'),
156            Route::get(self::ROUTE_TAX_RATE_ITEM)->action($dummyAction)->name('api_tax_rates_detail'),
157            Route::post('/api/v1/tax/rates')->action($dummyAction)->name('api_tax_rates_create'),
158            Route::methods([Method::PUT, Method::PATCH], self::ROUTE_TAX_RATE_ITEM)
159                ->action($dummyAction)
160                ->name('api_tax_rates_update'),
161            Route::delete(self::ROUTE_TAX_RATE_ITEM)->action($dummyAction)->name('api_tax_rates_delete'),
162            Route::post('/api/v1/tax/calculate')->action($dummyAction)->name('api_tax_calculate'),
163            Route::post('/api/v1/tax/simulate')->action($dummyAction)->name('api_tax_simulate'),
164
165            // Discount Endpoints
166            Route::get('/api/v1/discounts')->action($dummyAction)->name('api_discounts_list'),
167            Route::get(self::ROUTE_DISCOUNT_ITEM)->action($dummyAction)->name('api_discounts_detail'),
168            Route::post('/api/v1/discounts')->action($dummyAction)->name('api_discounts_create'),
169            Route::methods([Method::PUT, Method::PATCH], self::ROUTE_DISCOUNT_ITEM)
170                ->action($dummyAction)
171                ->name('api_discounts_update'),
172            Route::delete(self::ROUTE_DISCOUNT_ITEM)->action($dummyAction)->name('api_discounts_delete'),
173
174            // Inventory Fields Endpoints
175            Route::get('/api/v1/modules/{moduleId:\d+}/inventory-fields')
176                ->action($dummyAction)
177                ->name('api_module_inventory_fields_list'),
178            Route::post('/api/v1/modules/{moduleId:\d+}/inventory-fields')
179                ->action($dummyAction)
180                ->name('api_module_inventory_fields_create'),
181            Route::methods([Method::PUT, Method::PATCH], '/api/v1/modules/inventory-fields/{id:\d+}')
182                ->action($dummyAction)
183                ->name('api_module_inventory_fields_update'),
184            Route::delete('/api/v1/modules/inventory-fields/{id:\d+}')
185                ->action($dummyAction)
186                ->name('api_module_inventory_fields_delete'),
187
188            // Module Builder Endpoints
189            Route::get('/api/v1/system/module-builder/metadata-options')
190                ->action($dummyAction)
191                ->name('api_module_builder_metadata_options'),
192            Route::get('/api/v1/system/module-builder/schema/{id:\d+}')
193                ->action($dummyAction)
194                ->name('api_module_builder_schema'),
195            Route::post('/api/v1/system/module-builder/suggest-field')
196                ->action($dummyAction)
197                ->name('api_module_builder_suggest_field'),
198            Route::post('/api/v1/system/module-builder/create')
199                ->action($dummyAction)
200                ->name('api_module_builder_create'),
201            Route::methods([Method::PUT, Method::PATCH, Method::POST], '/api/v1/system/module-builder/update/{id:\d+}')
202                ->action($dummyAction)
203                ->name('api_module_builder_update'),
204            Route::delete('/api/v1/system/module-builder/{id:\d+}')
205                ->action($dummyAction)
206                ->name('api_module_builder_delete'),
207        ];
208
209        foreach ($routes as $route) {
210            $collector->addRoute($route);
211        }
212
213        return new UrlMatcher(new RouteCollection($collector));
214    }
215}