@maxisoft/instantcms-mcp 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/__tests__/artifact-tool.test.js +196 -0
  4. package/dist/__tests__/db-tool.test.js +152 -0
  5. package/dist/__tests__/define-tool.test.js +106 -0
  6. package/dist/__tests__/find-tool.test.js +185 -0
  7. package/dist/__tests__/get-component-api.test.js +144 -0
  8. package/dist/__tests__/hardening.test.js +73 -0
  9. package/dist/__tests__/hooks-tool.test.js +173 -0
  10. package/dist/__tests__/mcp-integration-extra.test.js +166 -0
  11. package/dist/__tests__/mcp-integration.test.js +53 -0
  12. package/dist/__tests__/pagination.test.js +114 -0
  13. package/dist/__tests__/performance-baseline.test.js +56 -0
  14. package/dist/__tests__/project-patch.test.js +144 -0
  15. package/dist/__tests__/project-source.test.js +44 -0
  16. package/dist/__tests__/project-workflows-extra.test.js +165 -0
  17. package/dist/__tests__/project-workflows.test.js +51 -0
  18. package/dist/__tests__/scaffold-addon-roundtrip.test.js +287 -0
  19. package/dist/__tests__/serialization.test.js +170 -0
  20. package/dist/__tests__/source-knowledge-parsers.test.js +42 -0
  21. package/dist/__tests__/template-development.test.js +78 -0
  22. package/dist/__tests__/template-productivity.test.js +87 -0
  23. package/dist/__tests__/tools.test.js +2143 -0
  24. package/dist/data/components.js +2818 -0
  25. package/dist/data/controllers-map.js +7571 -0
  26. package/dist/data/core-api.js +9356 -0
  27. package/dist/data/database-schema.js +4555 -0
  28. package/dist/data/events-map.js +1339 -0
  29. package/dist/data/fields-map.js +3692 -0
  30. package/dist/data/hooks.js +2257 -0
  31. package/dist/data/js-api.js +123 -0
  32. package/dist/data/libs-api.js +264 -0
  33. package/dist/data/routes-map.js +203 -0
  34. package/dist/data/schemas-validation.js +255 -0
  35. package/dist/data/schemas.js +1404 -0
  36. package/dist/data/traits-map.js +1004 -0
  37. package/dist/data/version-profiles.js +41 -0
  38. package/dist/data/widgets-map.js +131 -0
  39. package/dist/data/wysiwyg-map.js +486 -0
  40. package/dist/generated/components-source.js +14748 -0
  41. package/dist/generated/hooks-source.js +3399 -0
  42. package/dist/generated/knowledge-meta.js +101 -0
  43. package/dist/index.js +13 -0
  44. package/dist/registry/database-tools.js +112 -0
  45. package/dist/registry/extension-tools.js +473 -0
  46. package/dist/registry/generator-tools.js +506 -0
  47. package/dist/registry/knowledge-tools.js +441 -0
  48. package/dist/registry/language-tools.js +99 -0
  49. package/dist/registry/meta-tools.js +152 -0
  50. package/dist/registry/project-tools.js +48 -0
  51. package/dist/registry/resources.js +98 -0
  52. package/dist/registry/source-tools.js +211 -0
  53. package/dist/registry/template-development-tools.js +79 -0
  54. package/dist/server.js +32 -0
  55. package/dist/tools/addon-tool.js +1437 -0
  56. package/dist/tools/admin-partial-tool.js +498 -0
  57. package/dist/tools/api-tool.js +294 -0
  58. package/dist/tools/artifact-tool.js +95 -0
  59. package/dist/tools/cache-tool.js +360 -0
  60. package/dist/tools/component-tool.js +415 -0
  61. package/dist/tools/controllers-tool.js +125 -0
  62. package/dist/tools/cron-tool.js +197 -0
  63. package/dist/tools/crud-tool.js +659 -0
  64. package/dist/tools/db-tool.js +198 -0
  65. package/dist/tools/email-tool.js +222 -0
  66. package/dist/tools/external-api-tool.js +596 -0
  67. package/dist/tools/filter-tool.js +341 -0
  68. package/dist/tools/form-tool.js +275 -0
  69. package/dist/tools/grid-tool.js +189 -0
  70. package/dist/tools/hooks-tool.js +104 -0
  71. package/dist/tools/import-export-tool.js +548 -0
  72. package/dist/tools/lang-tool.js +251 -0
  73. package/dist/tools/layout-override-tool.js +125 -0
  74. package/dist/tools/layout-tool.js +548 -0
  75. package/dist/tools/maria-tool.js +127 -0
  76. package/dist/tools/mariadb.js +201 -0
  77. package/dist/tools/migration-tool.js +329 -0
  78. package/dist/tools/oauth-tool.js +520 -0
  79. package/dist/tools/parser/components-parser.js +76 -0
  80. package/dist/tools/parser/controllers-parser.js +313 -0
  81. package/dist/tools/parser/core-parser.js +294 -0
  82. package/dist/tools/parser/coverage-generator.js +424 -0
  83. package/dist/tools/parser/events-parser.js +127 -0
  84. package/dist/tools/parser/fields-parser.js +382 -0
  85. package/dist/tools/parser/hooks-parser.js +106 -0
  86. package/dist/tools/parser/sql-parser.js +197 -0
  87. package/dist/tools/parser/traits-parser.js +161 -0
  88. package/dist/tools/parser/widgets-parser.js +150 -0
  89. package/dist/tools/permission-tool.js +348 -0
  90. package/dist/tools/project-patch-tool.js +73 -0
  91. package/dist/tools/project-source-tool.js +188 -0
  92. package/dist/tools/project-workflow-tool.js +186 -0
  93. package/dist/tools/requirement-tool.js +212 -0
  94. package/dist/tools/scaffold-tool.js +815 -0
  95. package/dist/tools/seo-tool.js +412 -0
  96. package/dist/tools/source-tool.js +155 -0
  97. package/dist/tools/template-development-tool.js +271 -0
  98. package/dist/tools/template-overrides-tool.js +294 -0
  99. package/dist/tools/template-productivity-tool.js +319 -0
  100. package/dist/tools/template-tool.js +665 -0
  101. package/dist/tools/test-tool.js +183 -0
  102. package/dist/tools/webhook-tool.js +427 -0
  103. package/dist/tools/widget-tool.js +331 -0
  104. package/dist/tools/wysiwyg-tool.js +137 -0
  105. package/dist/types/scaffold.js +68 -0
  106. package/dist/utils/define-tool.js +37 -0
  107. package/dist/utils/find-tool.js +97 -0
  108. package/dist/utils/mcp-result.js +18 -0
  109. package/dist/utils/pagination.js +27 -0
  110. package/dist/utils/serialization.js +27 -0
  111. package/package.json +94 -0
@@ -0,0 +1,2818 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.components = void 0;
4
+ const components_source_js_1 = require("../generated/components-source.js");
5
+ const curatedComponents = [
6
+ {
7
+ name: 'cmsModel',
8
+ class: 'cmsModel',
9
+ description: 'Базовый класс для работы с базой данных. Query builder с fluent interface. Все модели контроллеров наследуют этот класс.',
10
+ access: "$this->model — в контроллере. cmsCore::getModel('controller_name') — глобально.",
11
+ methods: [
12
+ {
13
+ name: 'filterEqual',
14
+ signature: 'filterEqual(string $field, mixed $value): static',
15
+ description: 'Фильтр WHERE field = value',
16
+ parameters: [
17
+ { name: '$field', type: 'string', description: 'Поле таблицы', required: true },
18
+ { name: '$value', type: 'mixed', description: 'Значение для сравнения', required: true },
19
+ ],
20
+ return_type: 'static',
21
+ example: `$items = $this->model->filterEqual('is_pub', 1)->filterEqual('user_id', 5)->get('articles');`,
22
+ },
23
+ {
24
+ name: 'filterNotEqual',
25
+ signature: 'filterNotEqual(string $field, mixed $value): static',
26
+ description: 'Фильтр WHERE field != value',
27
+ parameters: [
28
+ { name: '$field', type: 'string', description: 'Поле таблицы', required: true },
29
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
30
+ ],
31
+ return_type: 'static',
32
+ example: `$items = $this->model->filterNotEqual('status', 'deleted')->get('items');`,
33
+ },
34
+ {
35
+ name: 'filterIn',
36
+ signature: 'filterIn(string $field, array $values): static',
37
+ description: 'Фильтр WHERE field IN (values)',
38
+ parameters: [
39
+ { name: '$field', type: 'string', description: 'Поле', required: true },
40
+ { name: '$values', type: 'array', description: 'Массив значений', required: true },
41
+ ],
42
+ return_type: 'static',
43
+ example: `$items = $this->model->filterIn('id', [1, 2, 3])->get('items');`,
44
+ },
45
+ {
46
+ name: 'filterLike',
47
+ signature: 'filterLike(string $field, string $value): static',
48
+ description: 'Фильтр WHERE field LIKE %value%',
49
+ parameters: [
50
+ { name: '$field', type: 'string', description: 'Поле', required: true },
51
+ { name: '$value', type: 'string', description: 'Строка для поиска', required: true },
52
+ ],
53
+ return_type: 'static',
54
+ example: `$items = $this->model->filterLike('title', 'поиск')->get('items');`,
55
+ },
56
+ {
57
+ name: 'filterGt',
58
+ signature: 'filterGt(string $field, mixed $value): static',
59
+ description: 'Фильтр WHERE field > value',
60
+ parameters: [
61
+ { name: '$field', type: 'string', description: 'Поле', required: true },
62
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
63
+ ],
64
+ return_type: 'static',
65
+ example: `$items = $this->model->filterGt('rating', 3)->get('items');`,
66
+ },
67
+ {
68
+ name: 'filterLt',
69
+ signature: 'filterLt(string $field, mixed $value): static',
70
+ description: 'Фильтр WHERE field < value',
71
+ parameters: [
72
+ { name: '$field', type: 'string', description: 'Поле', required: true },
73
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
74
+ ],
75
+ return_type: 'static',
76
+ example: `$items = $this->model->filterLt('date_expire', date('Y-m-d H:i:s'))->get('items');`,
77
+ },
78
+ {
79
+ name: 'orderBy',
80
+ signature: "orderBy(string $field, string $order = 'asc'): static",
81
+ description: 'Сортировка результатов',
82
+ parameters: [
83
+ { name: '$field', type: 'string', description: 'Поле для сортировки', required: true },
84
+ { name: '$order', type: 'string', description: "'asc' или 'desc'", default: 'asc' },
85
+ ],
86
+ return_type: 'static',
87
+ example: `$items = $this->model->orderBy('date_pub', 'desc')->get('items');`,
88
+ },
89
+ {
90
+ name: 'limit',
91
+ signature: 'limit(int $offset, int $count): static',
92
+ description: 'LIMIT для запроса. Если один параметр — только COUNT.',
93
+ parameters: [
94
+ {
95
+ name: '$offset',
96
+ type: 'int',
97
+ description: 'Смещение (или количество, если один аргумент)',
98
+ required: true,
99
+ },
100
+ { name: '$count', type: 'int', description: 'Количество записей', required: false },
101
+ ],
102
+ return_type: 'static',
103
+ example: `$items = $this->model->limit(10)->get('items');
104
+ $page_items = $this->model->limit(0, 20)->get('items');`,
105
+ },
106
+ {
107
+ name: 'limitPage',
108
+ signature: 'limitPage(int $page, int $perpage): static',
109
+ description: 'LIMIT для постраничной навигации',
110
+ parameters: [
111
+ { name: '$page', type: 'int', description: 'Номер страницы (с 1)', required: true },
112
+ { name: '$perpage', type: 'int', description: 'Записей на страницу', required: true },
113
+ ],
114
+ return_type: 'static',
115
+ example: `$items = $this->model->limitPage($page, 15)->get('items');`,
116
+ },
117
+ {
118
+ name: 'get',
119
+ signature: 'get(string $table): array',
120
+ description: 'Получить все записи по условиям фильтрации',
121
+ parameters: [
122
+ {
123
+ name: '$table',
124
+ type: 'string',
125
+ description: 'Имя таблицы без префикса',
126
+ required: true,
127
+ },
128
+ ],
129
+ return_type: 'array',
130
+ example: `$items = $this->model->filterEqual('is_pub', 1)->orderBy('id', 'desc')->limit(10)->get('myaddon_items');`,
131
+ },
132
+ {
133
+ name: 'getItem',
134
+ signature: 'getItem(string $table): array|false',
135
+ description: 'Получить одну запись (LIMIT 1)',
136
+ parameters: [
137
+ { name: '$table', type: 'string', description: 'Имя таблицы', required: true },
138
+ ],
139
+ return_type: 'array|false',
140
+ example: `$item = $this->model->filterEqual('id', $id)->getItem('myaddon_items');
141
+ if (!$item) { return cmsCore::error404(); }`,
142
+ },
143
+ {
144
+ name: 'getItemByField',
145
+ signature: 'getItemByField(string $table, string $field, mixed $value): array|false',
146
+ description: 'Получить запись по полю. Shortcut для filterEqual()->getItem()',
147
+ parameters: [
148
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
149
+ { name: '$field', type: 'string', description: 'Поле', required: true },
150
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
151
+ ],
152
+ return_type: 'array|false',
153
+ example: `$item = $this->model->getItemByField('myaddon_items', 'slug', $slug);`,
154
+ },
155
+ {
156
+ name: 'getCount',
157
+ signature: 'getCount(string $table): int',
158
+ description: 'Получить количество записей по условиям фильтра',
159
+ parameters: [{ name: '$table', type: 'string', description: 'Таблица', required: true }],
160
+ return_type: 'int',
161
+ example: `$total = $this->model->filterEqual('user_id', $user_id)->getCount('myaddon_items');`,
162
+ },
163
+ {
164
+ name: 'insert',
165
+ signature: 'insert(string $table, array $data): int',
166
+ description: 'Вставка записи. Возвращает ID вставленной записи.',
167
+ parameters: [
168
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
169
+ {
170
+ name: '$data',
171
+ type: 'array',
172
+ description: "Данные для вставки ['field' => value]",
173
+ required: true,
174
+ },
175
+ ],
176
+ return_type: 'int',
177
+ example: `$id = $this->model->insert('myaddon_items', [
178
+ 'title' => $data['title'],
179
+ 'user_id' => $this->cms_user->id,
180
+ 'date_pub' => date('Y-m-d H:i:s'),
181
+ 'is_pub' => 1
182
+ ]);`,
183
+ },
184
+ {
185
+ name: 'update',
186
+ signature: 'update(string $table, int $id, array $data): bool',
187
+ description: 'Обновление записи по ID',
188
+ parameters: [
189
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
190
+ { name: '$id', type: 'int', description: 'ID записи', required: true },
191
+ { name: '$data', type: 'array', description: 'Данные для обновления', required: true },
192
+ ],
193
+ return_type: 'bool',
194
+ example: `$this->model->update('myaddon_items', $id, [
195
+ 'title' => $data['title'],
196
+ 'is_pub' => $data['is_pub']
197
+ ]);`,
198
+ },
199
+ {
200
+ name: 'updateFiltered',
201
+ signature: 'updateFiltered(string $table, array $data): bool',
202
+ description: 'Обновление записей по условиям фильтра',
203
+ parameters: [
204
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
205
+ { name: '$data', type: 'array', description: 'Данные для обновления', required: true },
206
+ ],
207
+ return_type: 'bool',
208
+ example: `// Скрыть все записи пользователя
209
+ $this->model->filterEqual('user_id', $user_id)->updateFiltered('myaddon_items', ['is_pub' => 0]);`,
210
+ },
211
+ {
212
+ name: 'delete',
213
+ signature: "delete(string $table, int $id, string $id_field = 'id'): bool",
214
+ description: 'Удаление записи по ID',
215
+ parameters: [
216
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
217
+ { name: '$id', type: 'int', description: 'ID записи', required: true },
218
+ { name: '$id_field', type: 'string', description: 'Поле ID', default: 'id' },
219
+ ],
220
+ return_type: 'bool',
221
+ example: `$this->model->delete('myaddon_items', $id);`,
222
+ },
223
+ {
224
+ name: 'deleteFiltered',
225
+ signature: 'deleteFiltered(string $table): bool',
226
+ description: 'Удаление записей по условиям фильтра',
227
+ parameters: [{ name: '$table', type: 'string', description: 'Таблица', required: true }],
228
+ return_type: 'bool',
229
+ example: `$this->model->filterEqual('user_id', $user_id)->deleteFiltered('myaddon_items');`,
230
+ },
231
+ {
232
+ name: 'useCache',
233
+ signature: 'useCache(string $key): static',
234
+ description: 'Кэширование результата следующего запроса',
235
+ parameters: [{ name: '$key', type: 'string', description: 'Ключ кэша', required: true }],
236
+ return_type: 'static',
237
+ example: `$items = $this->model->useCache('myaddon.items.list')->get('myaddon_items');`,
238
+ },
239
+ {
240
+ name: 'select',
241
+ signature: 'select(string $fields): static',
242
+ description: 'Указать поля для SELECT',
243
+ parameters: [
244
+ { name: '$fields', type: 'string', description: 'SQL-строка полей', required: true },
245
+ ],
246
+ return_type: 'static',
247
+ example: `$items = $this->model->select('id, title, date_pub')->get('myaddon_items');`,
248
+ },
249
+ {
250
+ name: 'join',
251
+ signature: 'join(string $type, string $table, string $on): static',
252
+ description: 'JOIN таблиц',
253
+ parameters: [
254
+ {
255
+ name: '$type',
256
+ type: 'string',
257
+ description: "'left', 'inner', 'right'",
258
+ required: true,
259
+ },
260
+ { name: '$table', type: 'string', description: 'Таблица для JOIN', required: true },
261
+ { name: '$on', type: 'string', description: 'ON условие', required: true },
262
+ ],
263
+ return_type: 'static',
264
+ example: `$items = $this->model
265
+ ->join('left', 'cms_users u', 'u.id = i.user_id')
266
+ ->select('i.*, u.login as user_login')
267
+ ->get('myaddon_items i');`,
268
+ },
269
+ {
270
+ name: 'groupBy',
271
+ signature: 'groupBy(string $field): static',
272
+ description: 'GROUP BY для агрегации',
273
+ parameters: [
274
+ { name: '$field', type: 'string', description: 'Поле группировки', required: true },
275
+ ],
276
+ return_type: 'static',
277
+ example: `$stats = $this->model->select('user_id, COUNT(*) as cnt')->groupBy('user_id')->get('myaddon_items');`,
278
+ },
279
+ {
280
+ name: 'increment',
281
+ signature: 'increment(string $table, int $id, string $field, int $step = 1): bool',
282
+ description: 'Инкремент поля в записи',
283
+ parameters: [
284
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
285
+ { name: '$id', type: 'int', description: 'ID записи', required: true },
286
+ { name: '$field', type: 'string', description: 'Поле для инкремента', required: true },
287
+ { name: '$step', type: 'int', description: 'Шаг инкремента', default: '1' },
288
+ ],
289
+ return_type: 'bool',
290
+ example: `$this->model->increment('myaddon_items', $id, 'views');`,
291
+ },
292
+ {
293
+ name: 'decrement',
294
+ signature: 'decrement(string $table, int $id, string $field, int $step = 1): bool',
295
+ description: 'Декремент поля в записи',
296
+ parameters: [
297
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
298
+ { name: '$id', type: 'int', description: 'ID записи', required: true },
299
+ { name: '$field', type: 'string', description: 'Поле для декремента', required: true },
300
+ { name: '$step', type: 'int', description: 'Шаг декремента', default: '1' },
301
+ ],
302
+ return_type: 'bool',
303
+ example: `$this->model->decrement('myaddon_items', $id, 'count');`,
304
+ },
305
+ {
306
+ name: 'distinctSelect',
307
+ signature: 'distinctSelect(string $fields): static',
308
+ description: 'DISTINCT SELECT для уникальных значений',
309
+ parameters: [{ name: '$fields', type: 'string', description: 'Поля', required: true }],
310
+ return_type: 'static',
311
+ example: `$items = $this->model->distinctSelect('DISTINCT user_id')->get('myaddon_items');`,
312
+ },
313
+ {
314
+ name: 'having',
315
+ signature: 'having(string $field, string $operator, mixed $value): static',
316
+ description: 'Условие HAVING для GROUP BY',
317
+ parameters: [
318
+ { name: '$field', type: 'string', description: 'Поле', required: true },
319
+ {
320
+ name: '$operator',
321
+ type: 'string',
322
+ description: 'Оператор: >, <, =, >=, <=',
323
+ required: true,
324
+ },
325
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
326
+ ],
327
+ return_type: 'static',
328
+ example: `$stats = $this->model->select('user_id, COUNT(*) as cnt')->groupBy('user_id')->having('cnt', '>', 5)->get('myaddon_items');`,
329
+ },
330
+ {
331
+ name: 'resetFilters',
332
+ signature: 'resetFilters(): void',
333
+ description: 'Сброс всех фильтров WHERE',
334
+ parameters: [],
335
+ return_type: 'void',
336
+ example: `$this->model->resetFilters()->limit(10)->get('myaddon_items');`,
337
+ },
338
+ {
339
+ name: 'enableMultiInsert',
340
+ signature: 'enableMultiInsert(): void',
341
+ description: 'Включить режим множественной вставки (batch insert)',
342
+ parameters: [],
343
+ return_type: 'void',
344
+ example: `$this->model->enableMultiInsert()->insert('myaddon_items', $batch);`,
345
+ },
346
+ {
347
+ name: 'getJoinedTables',
348
+ signature: 'getJoinedTables(): array',
349
+ description: 'Получить список присоединённых таблиц',
350
+ parameters: [],
351
+ return_type: 'array',
352
+ example: `$tables = $this->model->getJoinedTables();`,
353
+ },
354
+ {
355
+ name: 'joinInner',
356
+ signature: 'joinInner(string $table, string $on): static',
357
+ description: 'INNER JOIN таблицы',
358
+ parameters: [
359
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
360
+ { name: '$on', type: 'string', description: 'ON условие', required: true },
361
+ ],
362
+ return_type: 'static',
363
+ example: `$items = $this->model->joinInner('cms_users', 'cms_users.id = i.user_id')->get('myaddon_items i');`,
364
+ },
365
+ {
366
+ name: 'joinLeft',
367
+ signature: 'joinLeft(string $table, string $on): static',
368
+ description: 'LEFT JOIN таблицы',
369
+ parameters: [
370
+ { name: '$table', type: 'string', description: 'Таблица', required: true },
371
+ { name: '$on', type: 'string', description: 'ON условие', required: true },
372
+ ],
373
+ return_type: 'static',
374
+ example: `$items = $this->model->joinLeft('cms_users', 'cms_users.id = i.user_id')->get('myaddon_items i');`,
375
+ },
376
+ ],
377
+ },
378
+ {
379
+ name: 'cmsController / cmsFrontend / cmsBackend',
380
+ class: 'cmsController',
381
+ description: 'Базовые классы контроллеров. cmsFrontend — для фронтенда, cmsBackend — для админ-панели.',
382
+ access: "$this — внутри контроллера. cmsCore::getController('name') — глобально.",
383
+ methods: [
384
+ {
385
+ name: 'href_to',
386
+ signature: "href_to(string $action = '', mixed ...$params): string",
387
+ description: 'Генерация URL в рамках текущего контроллера',
388
+ parameters: [
389
+ {
390
+ name: '$action',
391
+ type: 'string',
392
+ description: 'Действие контроллера',
393
+ required: false,
394
+ default: "''",
395
+ },
396
+ { name: '$params', type: 'mixed', description: 'Параметры URL', required: false },
397
+ ],
398
+ return_type: 'string',
399
+ example: `$url = $this->href_to('view', $item['id']);
400
+ // Результат: /myaddon/view/123`,
401
+ },
402
+ {
403
+ name: 'redirect',
404
+ signature: 'redirect(string $url, int $code = 302): void',
405
+ description: 'HTTP редирект',
406
+ parameters: [
407
+ { name: '$url', type: 'string', description: 'URL для редиректа', required: true },
408
+ { name: '$code', type: 'int', description: 'HTTP код', default: '302' },
409
+ ],
410
+ return_type: 'void',
411
+ example: `return $this->redirect($this->href_to());`,
412
+ },
413
+ {
414
+ name: 'renderJSON',
415
+ signature: 'renderJSON(array $data): void',
416
+ description: 'Ответ в формате JSON (для AJAX запросов)',
417
+ parameters: [
418
+ { name: '$data', type: 'array', description: 'Данные ответа', required: true },
419
+ ],
420
+ return_type: 'void',
421
+ example: `return $this->renderJSON(['success' => true, 'id' => $new_id]);`,
422
+ },
423
+ {
424
+ name: 'getForm',
425
+ signature: 'getForm(string $form_name, array $data = []): cmsForm',
426
+ description: 'Получить объект формы из файла forms/{form_name}.php',
427
+ parameters: [
428
+ { name: '$form_name', type: 'string', description: 'Имя файла формы', required: true },
429
+ { name: '$data', type: 'array', description: 'Данные для инициализации', default: '[]' },
430
+ ],
431
+ return_type: 'cmsForm',
432
+ example: `$form = $this->getForm('item_form', ['id' => $item_id]);`,
433
+ },
434
+ {
435
+ name: 'makeForm',
436
+ signature: 'makeForm(string $form_name, array $data = []): cmsForm',
437
+ description: 'Создать и инициализировать форму. Проксирует хук form_make.',
438
+ parameters: [
439
+ { name: '$form_name', type: 'string', description: 'Имя формы', required: true },
440
+ { name: '$data', type: 'array', description: 'Данные', default: '[]' },
441
+ ],
442
+ return_type: 'cmsForm',
443
+ example: `$form = $this->makeForm('options', $this->options);
444
+ $form_data = $form->render();`,
445
+ },
446
+ {
447
+ name: 'loadLanguage',
448
+ signature: "loadLanguage(string $lang = ''): void",
449
+ description: 'Загрузить языковой файл контроллера',
450
+ parameters: [
451
+ {
452
+ name: '$lang',
453
+ type: 'string',
454
+ description: 'Код языка (по умолчанию из конфига)',
455
+ default: "''",
456
+ },
457
+ ],
458
+ return_type: 'void',
459
+ example: `// В конструкторе или __construct
460
+ $this->loadLanguage();
461
+ // Теперь доступны константы из languages/{lang}/lang.php`,
462
+ },
463
+ {
464
+ name: 'cmsCore::getController',
465
+ signature: 'cmsCore::getController(string $name): cmsController',
466
+ description: 'Получить экземпляр контроллера по имени',
467
+ parameters: [
468
+ { name: '$name', type: 'string', description: 'Имя контроллера', required: true },
469
+ ],
470
+ return_type: 'cmsController',
471
+ example: `$activity = cmsCore::getController('activity');
472
+ $activity->addEntry('myaddon', 'create', ['subject_id' => $id]);`,
473
+ },
474
+ ],
475
+ },
476
+ {
477
+ name: 'cmsTemplate',
478
+ class: 'cmsTemplate',
479
+ description: 'Движок шаблонов. Singleton. Управляет рендерингом, CSS/JS, блоками страницы.',
480
+ access: '$this->cms_template — в контроллере. cmsTemplate::getInstance() — глобально.',
481
+ methods: [
482
+ {
483
+ name: 'render',
484
+ signature: 'render(string $tpl_file, array $data = []): string',
485
+ description: 'Рендер шаблонного файла .tpl.php и вывод на страницу',
486
+ parameters: [
487
+ {
488
+ name: '$tpl_file',
489
+ type: 'string',
490
+ description: 'Имя файла шаблона (без .tpl.php)',
491
+ required: true,
492
+ },
493
+ { name: '$data', type: 'array', description: 'Переменные для шаблона', default: '[]' },
494
+ ],
495
+ return_type: 'string',
496
+ example: `return $this->cms_template->render('index', [
497
+ 'items' => $items,
498
+ 'total' => $total,
499
+ 'page' => $page,
500
+ 'perpage' => $perpage
501
+ ]);`,
502
+ },
503
+ {
504
+ name: 'renderInternal',
505
+ signature: 'renderInternal(cmsController $ctrl, string $tpl, array $data = []): string',
506
+ description: 'Рендер шаблона из директории конкретного контроллера (для хуков и виджетов)',
507
+ parameters: [
508
+ {
509
+ name: '$ctrl',
510
+ type: 'cmsController',
511
+ description: 'Контроллер-владелец шаблона',
512
+ required: true,
513
+ },
514
+ { name: '$tpl', type: 'string', description: 'Имя шаблона', required: true },
515
+ { name: '$data', type: 'array', description: 'Переменные', default: '[]' },
516
+ ],
517
+ return_type: 'string',
518
+ example: `return $this->cms_template->renderInternal($this, 'list', ['items' => $items]);`,
519
+ },
520
+ {
521
+ name: 'fetch',
522
+ signature: 'fetch(string $tpl_file, array $data = []): string',
523
+ description: 'Рендер шаблона в строку (без вывода)',
524
+ parameters: [
525
+ { name: '$tpl_file', type: 'string', description: 'Путь к шаблону', required: true },
526
+ { name: '$data', type: 'array', description: 'Переменные', default: '[]' },
527
+ ],
528
+ return_type: 'string',
529
+ example: `$html = $this->cms_template->fetch('myaddon/block', ['item' => $item]);
530
+ echo $html;`,
531
+ },
532
+ {
533
+ name: 'setTitle',
534
+ signature: 'setTitle(string $title): void',
535
+ description: 'Установить заголовок страницы (<title>)',
536
+ parameters: [
537
+ { name: '$title', type: 'string', description: 'Заголовок страницы', required: true },
538
+ ],
539
+ return_type: 'void',
540
+ example: `$this->cms_template->setTitle('Название страницы | ' . cmsConfig::get('sitename'));`,
541
+ },
542
+ {
543
+ name: 'addHeadCSS',
544
+ signature: 'addHeadCSS(string $file, bool $no_merge = false): void',
545
+ description: 'Добавить CSS файл в <head>',
546
+ parameters: [
547
+ { name: '$file', type: 'string', description: 'URL CSS файла', required: true },
548
+ {
549
+ name: '$no_merge',
550
+ type: 'bool',
551
+ description: 'Не объединять с другими CSS',
552
+ default: 'false',
553
+ },
554
+ ],
555
+ return_type: 'void',
556
+ example: `$this->cms_template->addHeadCSS('/static/myaddon/style.css');`,
557
+ },
558
+ {
559
+ name: 'addHeadJS',
560
+ signature: 'addHeadJS(string $file, bool $no_merge = false): void',
561
+ description: 'Добавить JS файл в <head>',
562
+ parameters: [
563
+ { name: '$file', type: 'string', description: 'URL JS файла', required: true },
564
+ { name: '$no_merge', type: 'bool', description: 'Не объединять', default: 'false' },
565
+ ],
566
+ return_type: 'void',
567
+ example: `$this->cms_template->addHeadJS('/static/myaddon/app.js');`,
568
+ },
569
+ {
570
+ name: 'addBottom',
571
+ signature: 'addBottom(string $html): void',
572
+ description: 'Добавить HTML перед закрывающим </body>',
573
+ parameters: [
574
+ { name: '$html', type: 'string', description: 'HTML для вставки', required: true },
575
+ ],
576
+ return_type: 'void',
577
+ example: `$this->cms_template->addBottom('<script>initMyPlugin();</script>');`,
578
+ },
579
+ {
580
+ name: 'renderJSON',
581
+ signature: 'renderJSON(array $data): void',
582
+ description: 'Вернуть JSON ответ и завершить выполнение',
583
+ parameters: [{ name: '$data', type: 'array', description: 'Данные', required: true }],
584
+ return_type: 'void',
585
+ example: `$this->cms_template->renderJSON(['success' => true, 'message' => 'OK']);`,
586
+ },
587
+ ],
588
+ },
589
+ {
590
+ name: 'cmsCache',
591
+ class: 'cmsCache',
592
+ description: 'Кэширование данных. Поддерживает файловый кэш, Memcache, Redis.',
593
+ access: 'cmsCache::getInstance()',
594
+ methods: [
595
+ {
596
+ name: 'get',
597
+ signature: 'get(string $key): mixed|false',
598
+ description: 'Получить данные из кэша. false если не найдено или устарело.',
599
+ parameters: [{ name: '$key', type: 'string', description: 'Ключ кэша', required: true }],
600
+ return_type: 'mixed|false',
601
+ example: `$cache = cmsCache::getInstance();
602
+ $data = $cache->get('myaddon.list');
603
+ if ($data === false) {
604
+ $data = $this->model->get('items');
605
+ $cache->set('myaddon.list', $data, 300);
606
+ }`,
607
+ },
608
+ {
609
+ name: 'set',
610
+ signature: 'set(string $key, mixed $data, int $ttl = 0): bool',
611
+ description: 'Сохранить данные в кэш',
612
+ parameters: [
613
+ { name: '$key', type: 'string', description: 'Ключ', required: true },
614
+ { name: '$data', type: 'mixed', description: 'Данные', required: true },
615
+ {
616
+ name: '$ttl',
617
+ type: 'int',
618
+ description: 'Время жизни в секундах (0 = бессрочно)',
619
+ default: '0',
620
+ },
621
+ ],
622
+ return_type: 'bool',
623
+ example: `cmsCache::getInstance()->set('myaddon.count', $count, 3600);`,
624
+ },
625
+ {
626
+ name: 'clean',
627
+ signature: 'clean(string $key): bool',
628
+ description: 'Удалить ключ из кэша',
629
+ parameters: [
630
+ {
631
+ name: '$key',
632
+ type: 'string',
633
+ description: 'Ключ или префикс для очистки',
634
+ required: true,
635
+ },
636
+ ],
637
+ return_type: 'bool',
638
+ example: `// Очищать кэш при изменении данных
639
+ cmsCache::getInstance()->clean('myaddon.list');
640
+ cmsCache::getInstance()->clean('myaddon.count');`,
641
+ },
642
+ ],
643
+ },
644
+ {
645
+ name: 'cmsRequest',
646
+ class: 'cmsRequest',
647
+ description: 'Обработка HTTP-запросов. GET/POST параметры, проверки типа запроса.',
648
+ access: '$this->request — в контроллере.',
649
+ methods: [
650
+ {
651
+ name: 'get',
652
+ signature: 'get(string $key, mixed $default = null): mixed',
653
+ description: 'Получить параметр из GET',
654
+ parameters: [
655
+ { name: '$key', type: 'string', description: 'Имя параметра', required: true },
656
+ {
657
+ name: '$default',
658
+ type: 'mixed',
659
+ description: 'Значение по умолчанию',
660
+ default: 'null',
661
+ },
662
+ ],
663
+ return_type: 'mixed',
664
+ example: `$page = $this->request->get('page', 1);
665
+ $sort = $this->request->get('sort', 'date');`,
666
+ },
667
+ {
668
+ name: 'post',
669
+ signature: 'post(string $key, mixed $default = null): mixed',
670
+ description: 'Получить параметр из POST',
671
+ parameters: [
672
+ { name: '$key', type: 'string', description: 'Имя параметра', required: true },
673
+ {
674
+ name: '$default',
675
+ type: 'mixed',
676
+ description: 'Значение по умолчанию',
677
+ default: 'null',
678
+ },
679
+ ],
680
+ return_type: 'mixed',
681
+ example: `$title = $this->request->post('title', '');
682
+ $is_pub = $this->request->post('is_pub', 0);`,
683
+ },
684
+ {
685
+ name: 'isPost',
686
+ signature: 'isPost(): bool',
687
+ description: 'Проверить, является ли запрос POST',
688
+ parameters: [],
689
+ return_type: 'bool',
690
+ example: `if ($this->request->isPost()) {
691
+ // Обработать форму
692
+ $data = $form->parse($this->request->data('post'));
693
+ }`,
694
+ },
695
+ {
696
+ name: 'isAjax',
697
+ signature: 'isAjax(): bool',
698
+ description: 'Проверить, является ли запрос AJAX',
699
+ parameters: [],
700
+ return_type: 'bool',
701
+ example: `if ($this->request->isAjax()) {
702
+ return $this->renderJSON(['success' => true]);
703
+ }`,
704
+ },
705
+ {
706
+ name: 'data',
707
+ signature: 'data(string $type): array',
708
+ description: 'Получить все данные POST или GET',
709
+ parameters: [
710
+ { name: '$type', type: 'string', description: "'post' или 'get'", required: true },
711
+ ],
712
+ return_type: 'array',
713
+ example: `$form_data = $form->parse($this->request->data('post'));`,
714
+ },
715
+ ],
716
+ },
717
+ {
718
+ name: 'cmsEventsManager',
719
+ class: 'cmsEventsManager',
720
+ description: 'Система хуков и событий. Диспетчер событий InstantCMS.',
721
+ access: 'cmsEventsManager:: (статические методы)',
722
+ methods: [
723
+ {
724
+ name: 'hook',
725
+ signature: 'cmsEventsManager::hook(string $event, mixed $data, mixed $default = null, mixed $request = null): mixed',
726
+ description: 'Запустить хук. Данные последовательно проходят через всех слушателей.',
727
+ parameters: [
728
+ { name: '$event', type: 'string', description: 'Имя события', required: true },
729
+ { name: '$data', type: 'mixed', description: 'Данные для передачи', required: true },
730
+ {
731
+ name: '$default',
732
+ type: 'mixed',
733
+ description: 'Значение по умолчанию',
734
+ default: 'null',
735
+ },
736
+ {
737
+ name: '$request',
738
+ type: 'mixed',
739
+ description: 'Дополнительный контекст',
740
+ default: 'null',
741
+ },
742
+ ],
743
+ return_type: 'mixed',
744
+ example: `// Простой хук
745
+ $items = cmsEventsManager::hook('myaddon_before_list', $items);
746
+
747
+ // Хук с дополнительными данными
748
+ $item = cmsEventsManager::hook('content_before_item', $item, $item, ['ctype' => $ctype]);`,
749
+ },
750
+ {
751
+ name: 'hookAll',
752
+ signature: 'cmsEventsManager::hookAll(string $event, mixed $data, mixed $default = null): array',
753
+ description: 'Запустить хук и собрать результаты от всех слушателей в массив',
754
+ parameters: [
755
+ { name: '$event', type: 'string', description: 'Имя события', required: true },
756
+ { name: '$data', type: 'mixed', description: 'Данные', required: true },
757
+ {
758
+ name: '$default',
759
+ type: 'mixed',
760
+ description: 'Значение по умолчанию',
761
+ default: 'null',
762
+ },
763
+ ],
764
+ return_type: 'array',
765
+ example: `// Собрать пункты меню от всех дополнений
766
+ $menu_items = cmsEventsManager::hookAll('menu_admin', []);`,
767
+ },
768
+ ],
769
+ },
770
+ {
771
+ name: 'cmsCore (утилиты)',
772
+ class: 'cmsCore',
773
+ description: 'Главный singleton CMS. Содержит утилиты для получения компонентов.',
774
+ access: 'cmsCore:: (статические методы)',
775
+ methods: [
776
+ {
777
+ name: 'cmsCore::getModel',
778
+ signature: 'cmsCore::getModel(string $controller): cmsModel',
779
+ description: 'Получить модель контроллера',
780
+ parameters: [
781
+ { name: '$controller', type: 'string', description: 'Имя контроллера', required: true },
782
+ ],
783
+ return_type: 'cmsModel',
784
+ example: `$content_model = cmsCore::getModel('content');
785
+ $items = $content_model->filterEqual('is_pub', 1)->get('con_articles');`,
786
+ },
787
+ {
788
+ name: 'cmsCore::error404',
789
+ signature: 'cmsCore::error404(): void',
790
+ description: 'Показать страницу 404',
791
+ parameters: [],
792
+ return_type: 'void',
793
+ example: `if (!$item) { return cmsCore::error404(); }`,
794
+ },
795
+ {
796
+ name: 'cmsConfig::get',
797
+ signature: 'cmsConfig::get(string $key, mixed $default = null): mixed',
798
+ description: 'Получить значение из конфигурации сайта',
799
+ parameters: [
800
+ { name: '$key', type: 'string', description: 'Ключ конфига', required: true },
801
+ {
802
+ name: '$default',
803
+ type: 'mixed',
804
+ description: 'Значение по умолчанию',
805
+ default: 'null',
806
+ },
807
+ ],
808
+ return_type: 'mixed',
809
+ example: `$sitename = cmsConfig::get('sitename');
810
+ $template = cmsConfig::get('template', 'default');
811
+ $db_prefix = cmsConfig::get('db_prefix', 'cms_');`,
812
+ },
813
+ ],
814
+ },
815
+ // ─────────────────────────────────────────────────────────────────────────
816
+ // cmsWidget — базовый класс виджетов
817
+ // ─────────────────────────────────────────────────────────────────────────
818
+ {
819
+ name: 'cmsWidget',
820
+ class: 'cmsWidget',
821
+ description: 'Базовый класс всех виджетов для публичных страниц. Виджеты размещаются в позициях шаблона через панель виджетов. Файл: widgets/{widget_name}/widget.php',
822
+ access: 'Наследование: class widget{Name}{WidgetName} extends cmsWidget',
823
+ methods: [
824
+ {
825
+ name: 'run',
826
+ signature: 'run(): array|false',
827
+ description: 'Основной метод виджета. Должен вернуть массив переменных для шаблона или false для пропуска рендеринга.',
828
+ parameters: [],
829
+ return_type: 'array|false',
830
+ example: `class widgetCatalogList extends cmsWidget {
831
+
832
+ // Отключить кэш для динамического контента:
833
+ public $is_cacheable = false;
834
+
835
+ public function run() {
836
+
837
+ $limit = $this->getOption('limit', 5);
838
+
839
+ $controller = cmsCore::getController('catalog');
840
+ $items = $controller->model
841
+ ->filterEqual('is_pub', 1)
842
+ ->orderBy('date_pub', 'desc')
843
+ ->limit($limit)
844
+ ->get('catalog_items');
845
+
846
+ if (!$items) {
847
+ return false; // Виджет не выводится
848
+ }
849
+
850
+ // Шаблон: /templates/{theme}/controllers/catalog/list.tpl.php
851
+ return [
852
+ 'items' => $items,
853
+ 'limit' => $limit
854
+ ];
855
+ }
856
+ }`,
857
+ },
858
+ {
859
+ name: 'getOption',
860
+ signature: 'getOption(string $key, mixed $default = false): mixed',
861
+ description: "Получить значение настройки виджета. Поддерживает вложенные ключи через ':' (например 'options:ctype_id').",
862
+ parameters: [
863
+ {
864
+ name: '$key',
865
+ type: 'string',
866
+ description: "Имя опции или вложенный путь через ':'",
867
+ required: true,
868
+ },
869
+ {
870
+ name: '$default',
871
+ type: 'mixed',
872
+ description: 'Значение по умолчанию',
873
+ default: 'false',
874
+ },
875
+ ],
876
+ return_type: 'mixed',
877
+ example: `$limit = $this->getOption('limit', 10);
878
+ $ctype = $this->getOption('ctype_id', 0);
879
+ $dataset = $this->getOption('options:dataset', 'all'); // вложенный ключ`,
880
+ },
881
+ {
882
+ name: 'getOptions',
883
+ signature: 'getOptions(): array',
884
+ description: 'Получить все настройки виджета в виде массива',
885
+ parameters: [],
886
+ return_type: 'array',
887
+ example: `$all_options = $this->getOptions();
888
+ // Передача всех опций в метод контроллера:
889
+ return $this->controller_tags->getTagsWidgetParams($this->getOptions());`,
890
+ },
891
+ {
892
+ name: 'disableCache',
893
+ signature: 'disableCache(): void',
894
+ description: 'Отключить кэширование виджета в коде. Альтернатива: свойство public $is_cacheable = false.',
895
+ parameters: [],
896
+ return_type: 'void',
897
+ example: `public function run() {
898
+ $this->disableCache(); // или: public $is_cacheable = false;
899
+ // ...
900
+ }`,
901
+ },
902
+ {
903
+ name: 'setTemplate',
904
+ signature: 'setTemplate(string $template): void',
905
+ description: 'Изменить имя шаблона виджета (по умолчанию = имя виджета)',
906
+ parameters: [
907
+ {
908
+ name: '$template',
909
+ type: 'string',
910
+ description: 'Имя шаблона без .tpl.php',
911
+ required: true,
912
+ },
913
+ ],
914
+ return_type: 'void',
915
+ example: `// По умолчанию шаблон = имя виджета ('list')
916
+ // Чтобы использовать другой шаблон:
917
+ $this->setTemplate('list_compact');
918
+ // Ищет: /templates/{theme}/controllers/{name}/list_compact.tpl.php`,
919
+ },
920
+ ],
921
+ },
922
+ // ─────────────────────────────────────────────────────────────────────────
923
+ // cmsBackend — базовый класс бэкенд-контроллеров
924
+ // ─────────────────────────────────────────────────────────────────────────
925
+ {
926
+ name: 'cmsBackend',
927
+ class: 'cmsBackend',
928
+ description: 'Базовый класс всех бэкенд-контроллеров. Файл backend.php: class backend{Name} extends cmsBackend. Содержит getBackendMenu() и before(). Экшены — в отдельных файлах backend/actions/.',
929
+ access: 'Наследование: class backend{Name} extends cmsBackend',
930
+ methods: [
931
+ {
932
+ name: 'getBackendMenu',
933
+ signature: 'getBackendMenu(): array',
934
+ description: 'Возвращает пункты меню левой панели в бэкенде. Поддерживает иконки, счётчики, подменю.',
935
+ parameters: [],
936
+ return_type: 'array',
937
+ example: `public function getBackendMenu() {
938
+ return [
939
+ // Простой пункт
940
+ [
941
+ 'title' => LANG_CATALOG_CP_ITEMS,
942
+ 'url' => href_to($this->root_url, 'items'),
943
+ 'options' => ['icon' => 'list']
944
+ ],
945
+ // Пункт со счётчиком
946
+ [
947
+ 'title' => LANG_CATALOG_CP_PENDING,
948
+ 'counter' => $this->model->getPendingCount(),
949
+ 'url' => href_to($this->root_url, 'pending'),
950
+ 'options' => ['icon' => 'clock']
951
+ ],
952
+ // Родительский пункт с подменю
953
+ [
954
+ 'title' => LANG_CATALOG_CP_PRICES,
955
+ 'url' => href_to($this->root_url, 'prices'),
956
+ 'childs_count' => 2,
957
+ 'options' => ['icon' => 'money-bill']
958
+ ],
959
+ // Дочерние пункты (level 2)
960
+ [
961
+ 'title' => LANG_CATALOG_CP_PRICES_BASIC,
962
+ 'level' => 2,
963
+ 'url' => href_to($this->root_url, 'prices', 'basic')
964
+ ],
965
+ [
966
+ 'title' => LANG_CATALOG_CP_PRICES_VIP,
967
+ 'level' => 2,
968
+ 'url' => href_to($this->root_url, 'prices', 'vip')
969
+ ],
970
+ // Настройки
971
+ [
972
+ 'title' => LANG_OPTIONS,
973
+ 'url' => href_to($this->root_url, 'options'),
974
+ 'options' => ['icon' => 'cog']
975
+ ]
976
+ ];
977
+ }`,
978
+ },
979
+ {
980
+ name: 'before',
981
+ signature: 'before(string $action_name): bool',
982
+ description: 'Вызывается перед каждым экшеном бэкенда. Для дополнительных проверок доступа. Обязательно вызывать parent::before().',
983
+ parameters: [
984
+ {
985
+ name: '$action_name',
986
+ type: 'string',
987
+ description: 'Имя текущего экшена',
988
+ required: true,
989
+ },
990
+ ],
991
+ return_type: 'bool',
992
+ example: `public function before($action_name) {
993
+ if (!parent::before($action_name)) {
994
+ return false;
995
+ }
996
+ // Добавить заголовок безопасности
997
+ $this->cms_core->response->setHeader('X-Frame-Options', 'DENY');
998
+ return true;
999
+ }`,
1000
+ },
1001
+ ],
1002
+ },
1003
+ // ─────────────────────────────────────────────────────────────────────────
1004
+ // trait listgrid — для бэкенд экшенов-списков
1005
+ // ─────────────────────────────────────────────────────────────────────────
1006
+ {
1007
+ name: 'trait listgrid',
1008
+ class: 'icms\\traits\\controllers\\actions\\listgrid',
1009
+ description: 'Трейт для бэкенд экшенов, отображающих список с гридом. Подключается в backend/actions/*.php. Логика настраивается через свойства в __construct().',
1010
+ access: 'use icms\\traits\\controllers\\actions\\listgrid; в классе action{Name}X extends cmsAction',
1011
+ methods: [
1012
+ {
1013
+ name: 'Свойства трейта listgrid',
1014
+ signature: 'Properties',
1015
+ description: 'Свойства для настройки трейта в __construct()',
1016
+ parameters: [],
1017
+ return_type: 'void',
1018
+ example: `class actionCatalogItems extends cmsAction {
1019
+
1020
+ use icms\\traits\\controllers\\actions\\listgrid;
1021
+
1022
+ public function __construct($controller, $params = []) {
1023
+ parent::__construct($controller, $params);
1024
+
1025
+ // ОБЯЗАТЕЛЬНЫЕ:
1026
+ $this->table_name = 'catalog_items'; // основная таблица
1027
+ $this->grid_name = 'items'; // имя грида (файл backend/grids/grid_items.php)
1028
+ $this->title = LANG_CATALOG_CP_ITEMS; // заголовок страницы
1029
+
1030
+ // ТУЛБАР — кнопки над списком:
1031
+ $this->tool_buttons = [
1032
+ [
1033
+ 'class' => 'add', // CSS класс кнопки
1034
+ 'title' => LANG_CATALOG_CP_ADD,
1035
+ 'href' => $this->cms_template->href_to('items', 'add')
1036
+ ],
1037
+ [
1038
+ 'class' => 'btn btn-secondary',
1039
+ 'title' => LANG_EXPORT,
1040
+ 'href' => $this->cms_template->href_to('items', 'export'),
1041
+ 'icon' => 'download'
1042
+ ]
1043
+ ];
1044
+
1045
+ // ОПЦИОНАЛЬНЫЕ:
1046
+ // Хук для расширения тулбара другими дополнениями:
1047
+ $this->toolbar_hook = 'catalog_items_toolbar';
1048
+
1049
+ // Коллбэк для дополнительных JOIN-ов / фильтров модели:
1050
+ $this->list_callback = function (\\cmsModel $model) {
1051
+ return $model->joinLeft('users u', 'u.id = t.user_id', ['u.nickname as user_nickname']);
1052
+ };
1053
+
1054
+ // Коллбэк для постобработки записей:
1055
+ $this->items_callback = function ($items) {
1056
+ foreach ($items as &$item) {
1057
+ $item['status_label'] = $item['is_pub'] ? 'Активен' : 'Скрыт';
1058
+ }
1059
+ return $items;
1060
+ };
1061
+
1062
+ // Передача управления вложенным экшенам:
1063
+ // URL /admin/catalog/items/add → запустит action items_add
1064
+ $this->external_action_prefix = 'items_';
1065
+
1066
+ // Кол-во записей на страницу (по умолчанию 30):
1067
+ $this->default_perpage = 20;
1068
+ }
1069
+ }`,
1070
+ },
1071
+ ],
1072
+ },
1073
+ // ─────────────────────────────────────────────────────────────────────────
1074
+ // trait formItem — для бэкенд экшенов-форм
1075
+ // ─────────────────────────────────────────────────────────────────────────
1076
+ {
1077
+ name: 'trait formItem',
1078
+ class: 'icms\\traits\\controllers\\actions\\formItem',
1079
+ description: 'Трейт для бэкенд экшенов добавления/редактирования. Один экшен обрабатывает и add, и edit. Логика через свойства в __construct().',
1080
+ access: 'use icms\\traits\\controllers\\actions\\formItem; в классе action{Name}X extends cmsAction',
1081
+ methods: [
1082
+ {
1083
+ name: 'Свойства трейта formItem',
1084
+ signature: 'Properties',
1085
+ description: 'Свойства для настройки трейта в __construct()',
1086
+ parameters: [],
1087
+ return_type: 'void',
1088
+ example: `class actionCatalogItemsAdd extends cmsAction {
1089
+
1090
+ use icms\\traits\\controllers\\actions\\formItem;
1091
+
1092
+ public function __construct($controller, $params = []) {
1093
+ parent::__construct($controller, $params);
1094
+
1095
+ $list_url = $this->cms_template->href_to('items');
1096
+
1097
+ // ОБЯЗАТЕЛЬНЫЕ:
1098
+ $this->table_name = 'catalog_items'; // таблица БД
1099
+ $this->form_name = 'item'; // форма (файл backend/forms/form_item.php)
1100
+ $this->success_url = $list_url; // редирект после сохранения
1101
+
1102
+ // ЗАГОЛОВОК — строка или массив:
1103
+ $this->title = [
1104
+ 'add' => LANG_CATALOG_CP_ADD,
1105
+ 'edit' => '{title}' // {title} заменяется значением поля title записи
1106
+ ];
1107
+
1108
+ // ХЛЕБНЫЕ КРОШКИ:
1109
+ $this->breadcrumbs = [
1110
+ [LANG_CATALOG_CP_ITEMS, $list_url],
1111
+ isset($params[0]) ? '{title}' : LANG_CATALOG_CP_ADD
1112
+ ];
1113
+
1114
+ // ТУЛБАР — кнопки Сохранить/Отменить:
1115
+ $this->use_default_tool_buttons = true;
1116
+ // Или кастомные кнопки:
1117
+ // $this->tool_buttons = [...];
1118
+
1119
+ // ДЕФОЛТНЫЕ ЗНАЧЕНИЯ для новой записи:
1120
+ $this->default_item = [
1121
+ 'is_pub' => 1,
1122
+ 'date_pub' => date('Y-m-d H:i:s'),
1123
+ 'sort_order' => 0
1124
+ ];
1125
+
1126
+ // ПАРАМЕТРЫ ФОРМЫ (передаются в form->init()):
1127
+ // $this->form_opts = [$this->controller->getOptions()];
1128
+
1129
+ // КОЛЛБЭКИ:
1130
+ $this->add_callback = function($id, $data) {
1131
+ // После добавления записи
1132
+ cmsCache::getInstance()->clean('catalog');
1133
+ };
1134
+
1135
+ $this->update_callback = function($data) {
1136
+ // После обновления записи
1137
+ cmsCache::getInstance()->clean('catalog');
1138
+ };
1139
+
1140
+ // ПОЛЕ ЗАГОЛОВКА для копирования (добавляет " (1)"):
1141
+ $this->title_field = 'title';
1142
+
1143
+ // КЛЮЧ КЭША для сброса после сохранения:
1144
+ $this->cache_key = 'catalog';
1145
+
1146
+ // МЕТОДЫ МОДЕЛИ (по умолчанию insert/update):
1147
+ // $this->form_add_method = 'insert';
1148
+ // $this->form_edit_method = 'update';
1149
+ }
1150
+ }`,
1151
+ },
1152
+ ],
1153
+ },
1154
+ // ─────────────────────────────────────────────────────────────────────────
1155
+ // Grid Definition — структура файла грида
1156
+ // ─────────────────────────────────────────────────────────────────────────
1157
+ {
1158
+ name: 'Grid Definition (backend/grids/)',
1159
+ class: 'function grid_{name}',
1160
+ description: 'Определение грида в файле backend/grids/grid_{name}.php. ФУНКЦИЯ, не класс! Возвращает массив options/columns/actions.',
1161
+ access: 'Файл: backend/grids/grid_{name}.php. Функция: grid_{name}($controller, $model=null)',
1162
+ methods: [
1163
+ {
1164
+ name: 'options',
1165
+ signature: 'options: array',
1166
+ description: 'Настройки отображения и поведения грида',
1167
+ parameters: [],
1168
+ return_type: 'array',
1169
+ example: `$options = [
1170
+ 'is_sortable' => true, // Сортировка по клику на заголовок столбца
1171
+ 'is_filter' => true, // Показать панель фильтрации
1172
+ 'is_pagination' => true, // Пагинация (кол-во задаётся в экшене)
1173
+ 'is_draggable' => false, // Drag&drop строк для изменения порядка
1174
+ 'is_selectable' => false, // Чекбоксы для массовых операций
1175
+ 'order_by' => 'id', // Поле сортировки по умолчанию
1176
+ 'order_to' => 'desc', // Направление: 'asc' или 'desc'
1177
+ 'show_id' => true // Показать колонку ID
1178
+
1179
+ // Для drag&drop с сохранением порядка:
1180
+ // 'is_draggable' => true,
1181
+ // 'drag_save_url' => href_to('admin', 'reorder', 'catalog_items'),
1182
+ ];`,
1183
+ },
1184
+ {
1185
+ name: 'columns',
1186
+ signature: 'columns: array',
1187
+ description: 'Определение столбцов грида. Ключ = имя поля в БД.',
1188
+ parameters: [],
1189
+ return_type: 'array',
1190
+ example: `$columns = [
1191
+ // Простой столбец
1192
+ 'id' => ['title' => 'ID', 'width' => 60],
1193
+
1194
+ // Со ссылкой на редактирование
1195
+ 'title' => [
1196
+ 'title' => LANG_TITLE,
1197
+ 'href' => href_to($controller->root_url, 'items', ['edit', '{id}'])
1198
+ ],
1199
+
1200
+ // С JOIN-ом: указать order_by с алиасом таблицы
1201
+ 'user_nickname' => [
1202
+ 'title' => LANG_USER,
1203
+ 'width' => 150,
1204
+ 'href' => href_to('users', '{user_id}'),
1205
+ 'order_by' => 'u.nickname', // алиас из JOIN
1206
+ 'filter' => 'like',
1207
+ 'filter_by' => 'u.nickname' // поле для фильтрации
1208
+ ],
1209
+
1210
+ // Дата с форматированием
1211
+ 'date_pub' => [
1212
+ 'title' => LANG_DATE_PUB,
1213
+ 'width' => 150,
1214
+ 'filter' => 'date', // фильтр по диапазону дат
1215
+ 'handler' => function ($value) {
1216
+ return html_date_time($value);
1217
+ }
1218
+ ],
1219
+
1220
+ // Флаг с inline-переключателем
1221
+ 'is_pub' => [
1222
+ 'title' => LANG_IS_PUB,
1223
+ 'width' => 60,
1224
+ 'flag' => true,
1225
+ 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'catalog_items', 'is_pub'])
1226
+ ],
1227
+
1228
+ // Фильтр по выпадающему списку
1229
+ 'status' => [
1230
+ 'title' => LANG_STATUS,
1231
+ 'filter' => 'exact',
1232
+ 'filter_select' => [
1233
+ 'items' => function($name) {
1234
+ return ['' => LANG_ALL, 0 => LANG_INACTIVE, 1 => LANG_ACTIVE];
1235
+ }
1236
+ ],
1237
+ 'handler' => function ($value, $row) {
1238
+ return $value ? '<span class="text-success">'.LANG_ACTIVE.'</span>'
1239
+ : '<span class="text-muted">'.LANG_INACTIVE.'</span>';
1240
+ }
1241
+ ],
1242
+
1243
+ // Числовой диапазон
1244
+ 'price' => ['title' => LANG_PRICE, 'filter' => 'range'],
1245
+
1246
+ // Подсветка строки
1247
+ 'priority' => [
1248
+ 'title' => LANG_PRIORITY,
1249
+ 'class_handler' => function($row) {
1250
+ if ($row['priority'] > 5) return 'bg-warning';
1251
+ if ($row['priority'] < 0) return 'bg-danger';
1252
+ }
1253
+ ],
1254
+
1255
+ // Редактируемое поле inline (inline editing)
1256
+ 'sort_order' => [
1257
+ 'title' => LANG_ORDER,
1258
+ 'width' => 80,
1259
+ 'editable' => true // позволяет редактировать прямо в гриде
1260
+ ]
1261
+ ];
1262
+
1263
+ // Типы фильтров: 'like', 'exact', 'date', 'range'`,
1264
+ },
1265
+ {
1266
+ name: 'actions',
1267
+ signature: 'actions: array',
1268
+ description: 'Кнопки действий для каждой строки грида (правая колонка)',
1269
+ parameters: [],
1270
+ return_type: 'array',
1271
+ example: `$actions = [
1272
+ // Кнопка редактирования
1273
+ [
1274
+ 'title' => LANG_EDIT,
1275
+ 'icon' => 'pen',
1276
+ 'href' => href_to($controller->root_url, 'items', ['edit', '{id}'])
1277
+ ],
1278
+
1279
+ // Кнопка копирования записи
1280
+ [
1281
+ 'title' => LANG_COPY,
1282
+ 'icon' => 'copy',
1283
+ 'href' => href_to($controller->root_url, 'items_add', ['{id}', 1])
1284
+ ],
1285
+
1286
+ // Условная кнопка (показывается только при условии)
1287
+ [
1288
+ 'title' => LANG_APPROVE,
1289
+ 'icon' => 'check',
1290
+ 'href' => href_to($controller->root_url, 'items', ['approve', '{id}']),
1291
+ 'handler' => function ($item) {
1292
+ return $item['is_pub'] == 0; // показать только если не опубликован
1293
+ }
1294
+ ],
1295
+
1296
+ // Кнопка с подтверждением и кастомным стилем
1297
+ [
1298
+ 'title' => LANG_DELETE,
1299
+ 'class' => 'text-danger', // CSS класс кнопки
1300
+ 'icon' => 'times-circle', // FontAwesome иконка (без fa-)
1301
+ 'confirm' => LANG_DELETE_CONFIRM, // текст подтверждения
1302
+ 'href' => href_to($controller->root_url, 'items', ['delete', '{id}'])
1303
+ ]
1304
+ ];
1305
+
1306
+ // Плейсхолдеры в href: {id}, {title}, {user_id} и любое другое поле строки`,
1307
+ },
1308
+ {
1309
+ name: 'Пример полного грида',
1310
+ signature: 'function grid_items($controller, $model = null): array',
1311
+ description: 'Полный пример файла backend/grids/grid_items.php',
1312
+ parameters: [],
1313
+ return_type: 'array',
1314
+ example: `<?php
1315
+ // Файл: backend/grids/grid_items.php
1316
+ // ВАЖНО: функция, не класс!
1317
+
1318
+ function grid_items($controller) {
1319
+
1320
+ $options = [
1321
+ 'is_sortable' => true,
1322
+ 'is_filter' => true,
1323
+ 'is_pagination' => true,
1324
+ 'is_draggable' => false,
1325
+ 'is_selectable' => false,
1326
+ 'order_by' => 'id',
1327
+ 'order_to' => 'desc',
1328
+ 'show_id' => true
1329
+ ];
1330
+
1331
+ $columns = [
1332
+ 'title' => [
1333
+ 'title' => LANG_TITLE,
1334
+ 'filter' => 'like',
1335
+ 'href' => href_to($controller->root_url, 'items', ['edit', '{id}'])
1336
+ ],
1337
+ 'date_pub' => [
1338
+ 'title' => LANG_DATE_PUB,
1339
+ 'width' => 150,
1340
+ 'filter' => 'date',
1341
+ 'handler' => function ($value) { return html_date_time($value); }
1342
+ ],
1343
+ 'is_pub' => [
1344
+ 'title' => LANG_IS_PUB,
1345
+ 'width' => 60,
1346
+ 'flag' => true,
1347
+ 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'catalog_items', 'is_pub'])
1348
+ ]
1349
+ ];
1350
+
1351
+ $actions = [
1352
+ [
1353
+ 'title' => LANG_EDIT,
1354
+ 'icon' => 'pen',
1355
+ 'href' => href_to($controller->root_url, 'items', ['edit', '{id}'])
1356
+ ],
1357
+ [
1358
+ 'title' => LANG_DELETE,
1359
+ 'class' => 'text-danger',
1360
+ 'icon' => 'times-circle',
1361
+ 'confirm' => LANG_DELETE_CONFIRM,
1362
+ 'href' => href_to($controller->root_url, 'items', ['delete', '{id}'])
1363
+ ]
1364
+ ];
1365
+
1366
+ return ['options' => $options, 'columns' => $columns, 'actions' => $actions];
1367
+ }`,
1368
+ },
1369
+ ],
1370
+ },
1371
+ // ─────────────────────────────────────────────────────────────────────────
1372
+ // cmsForm — базовый класс форм
1373
+ // ─────────────────────────────────────────────────────────────────────────
1374
+ {
1375
+ name: 'cmsForm',
1376
+ class: 'cmsForm',
1377
+ description: 'Базовый класс форм. Используется для бэкенд форм (backend/forms/) и опций виджетов. Метод init() возвращает массив fieldset → childs → поля.',
1378
+ access: 'Наследование: class form{Name}Item extends cmsForm',
1379
+ methods: [
1380
+ {
1381
+ name: 'init',
1382
+ signature: 'init($do = null, ...$params): array',
1383
+ description: "Определяет структуру формы. Принимает $do ('add'/'edit') и дополнительные параметры из form_opts. Возвращает массив fieldset-ов с полями.",
1384
+ parameters: [
1385
+ {
1386
+ name: '$do',
1387
+ type: 'string',
1388
+ description: "'add' или 'edit' — тип операции",
1389
+ default: 'null',
1390
+ },
1391
+ ],
1392
+ return_type: 'array',
1393
+ example: `class formCatalogItem extends cmsForm {
1394
+
1395
+ // $do = 'add' или 'edit' (передаётся из трейта formItem)
1396
+ // $options = доп. параметры из $this->form_opts в экшене
1397
+ public function init($do, $options = []) {
1398
+
1399
+ return [
1400
+ // Секция (fieldset)
1401
+ 'basic' => [
1402
+ 'title' => LANG_CP_BASIC,
1403
+ 'type' => 'fieldset',
1404
+ 'childs' => [
1405
+ new fieldString('title', [
1406
+ 'title' => LANG_TITLE,
1407
+ 'rules' => [['required'], ['max_length', 255]]
1408
+ ]),
1409
+ new fieldHtml('content', [
1410
+ 'title' => LANG_CONTENT
1411
+ ]),
1412
+ // Поле со встроенной валидацией через замыкание:
1413
+ new fieldString('slug', [
1414
+ 'title' => LANG_SLUG,
1415
+ 'rules' => [
1416
+ [function ($controller, $data, $value) {
1417
+ if (empty($value)) return true;
1418
+ // Уникальность слага:
1419
+ if (!empty($data['id'])) {
1420
+ $controller->model->filterNotEqual('id', $data['id']);
1421
+ }
1422
+ $exists = $controller->model
1423
+ ->filterEqual('slug', $value)
1424
+ ->getCount('catalog_items');
1425
+ return $exists ? ERR_VALIDATE_UNIQUE : true;
1426
+ }]
1427
+ ]
1428
+ ]),
1429
+ new fieldCheckbox('is_pub', ['title' => LANG_IS_PUB, 'default' => 1]),
1430
+ new fieldDate('date_pub', [
1431
+ 'title' => LANG_DATE_PUB,
1432
+ 'default' => date('Y-m-d H:i:s')
1433
+ ])
1434
+ ]
1435
+ ],
1436
+ 'media' => [
1437
+ 'title' => LANG_MEDIA,
1438
+ 'type' => 'fieldset',
1439
+ 'childs' => [
1440
+ new fieldImage('image', [
1441
+ 'title' => LANG_IMAGE,
1442
+ 'max_width' => 1200,
1443
+ 'max_size' => 5120
1444
+ ])
1445
+ ]
1446
+ ]
1447
+ ];
1448
+ }
1449
+ }`,
1450
+ },
1451
+ ],
1452
+ },
1453
+ {
1454
+ name: 'cmsTemplate',
1455
+ class: 'cmsTemplate',
1456
+ description: 'Движок шаблонов InstantCMS. Доступен как $this в .tpl.php файлах. Предоставляет методы для вывода контента, CSS/JS, виджетов, навигации и динамического layout.',
1457
+ access: '$this — в .tpl.php файлах шаблона',
1458
+ methods: [
1459
+ {
1460
+ name: 'title',
1461
+ signature: 'title(): string',
1462
+ description: 'Возвращает заголовок страницы. МЕТОД с (), не свойство!',
1463
+ parameters: [],
1464
+ return_type: 'string',
1465
+ example: `<title><?= $this->title() ?></title>`,
1466
+ },
1467
+ {
1468
+ name: 'body',
1469
+ signature: 'body(): string',
1470
+ description: 'Возвращает основной HTML-контент страницы (результат экшена контроллера).',
1471
+ parameters: [],
1472
+ return_type: 'string',
1473
+ example: `<main class="content"><?= $this->body() ?></main>`,
1474
+ },
1475
+ {
1476
+ name: 'head',
1477
+ signature: 'head(bool $include_css_js = true, ...): string',
1478
+ description: 'Возвращает теги для вставки в <head>: мета-теги, CSS, JS.',
1479
+ parameters: [
1480
+ {
1481
+ name: '$include_css_js',
1482
+ type: 'bool',
1483
+ description: 'Включить CSS/JS теги (default: true)',
1484
+ required: false,
1485
+ default: 'true',
1486
+ },
1487
+ ],
1488
+ return_type: 'string',
1489
+ example: `<head>
1490
+ <meta charset="utf-8">
1491
+ <title><?= $this->title() ?></title>
1492
+ <?= $this->head(true) ?>
1493
+ </head>`,
1494
+ },
1495
+ {
1496
+ name: 'bottom',
1497
+ signature: 'bottom(): string',
1498
+ description: 'Возвращает JS-скрипты для вставки перед </body>.',
1499
+ parameters: [],
1500
+ return_type: 'string',
1501
+ example: ` <?= $this->bottom() ?>
1502
+ </body>`,
1503
+ },
1504
+ {
1505
+ name: 'widgets',
1506
+ signature: 'widgets(string $position): string',
1507
+ description: 'Выводит виджеты на указанной позиции.',
1508
+ parameters: [
1509
+ {
1510
+ name: '$position',
1511
+ type: 'string',
1512
+ description: 'Имя позиции: header, top, left-top, left-bottom, right-top, right-center, right-bottom, footer',
1513
+ required: true,
1514
+ },
1515
+ ],
1516
+ return_type: 'string',
1517
+ example: `<?= $this->widgets('header') ?>
1518
+ <?= $this->widgets('right-top') ?>
1519
+ <?= $this->widgets('footer') ?>`,
1520
+ },
1521
+ {
1522
+ name: 'hasWidgetsOn',
1523
+ signature: 'hasWidgetsOn(string|array $positions): bool',
1524
+ description: 'Проверяет наличие виджетов на позиции (или массиве позиций).',
1525
+ parameters: [
1526
+ {
1527
+ name: '$positions',
1528
+ type: 'string|array',
1529
+ description: 'Позиция или массив позиций',
1530
+ required: true,
1531
+ },
1532
+ ],
1533
+ return_type: 'bool',
1534
+ example: `<?php if ($this->hasWidgetsOn('right-top')): ?>
1535
+ <aside class="sidebar">
1536
+ <?= $this->widgets('right-top') ?>
1537
+ </aside>
1538
+ <?php endif ?>`,
1539
+ },
1540
+ {
1541
+ name: 'widgetsInHtml',
1542
+ signature: "widgetsInHtml(string $position, string $wrapper = ''): void",
1543
+ description: 'Выводит виджеты позиции в HTML-обёртке.',
1544
+ parameters: [
1545
+ { name: '$position', type: 'string', description: 'Позиция виджетов', required: true },
1546
+ {
1547
+ name: '$wrapper',
1548
+ type: 'string',
1549
+ description: 'HTML-обёртка (класс или тег)',
1550
+ required: false,
1551
+ },
1552
+ ],
1553
+ return_type: 'void',
1554
+ example: `<?php $this->widgetsInHtml('left-top', 'sidebar-section') ?>`,
1555
+ },
1556
+ {
1557
+ name: 'breadcrumbs',
1558
+ signature: 'breadcrumbs(): string',
1559
+ description: 'Возвращает HTML хлебных крошек.',
1560
+ parameters: [],
1561
+ return_type: 'string',
1562
+ example: `<nav aria-label="breadcrumb"><?= $this->breadcrumbs() ?></nav>`,
1563
+ },
1564
+ {
1565
+ name: 'linkCSS',
1566
+ signature: 'linkCSS(string $path): string',
1567
+ description: 'Возвращает <link> тег для CSS файла из папки темы.',
1568
+ parameters: [
1569
+ {
1570
+ name: '$path',
1571
+ type: 'string',
1572
+ description: 'Путь относительно папки темы',
1573
+ required: true,
1574
+ },
1575
+ ],
1576
+ return_type: 'string',
1577
+ example: `<?= $this->linkCSS('css/main.css') ?>`,
1578
+ },
1579
+ {
1580
+ name: 'linkJS',
1581
+ signature: 'linkJS(string $path): string',
1582
+ description: 'Возвращает <script> тег для JS файла из папки темы.',
1583
+ parameters: [
1584
+ {
1585
+ name: '$path',
1586
+ type: 'string',
1587
+ description: 'Путь относительно папки темы',
1588
+ required: true,
1589
+ },
1590
+ ],
1591
+ return_type: 'string',
1592
+ example: `<?= $this->linkJS('js/main.js') ?>`,
1593
+ },
1594
+ {
1595
+ name: 'renderLayoutChild',
1596
+ signature: 'renderLayoutChild(string $name, array $vars = []): void',
1597
+ description: 'Рендерит фрагмент из layout_childs/. Используется при is_dynamic_layout=true. Файл: layout_childs/{name}.tpl.php',
1598
+ parameters: [
1599
+ {
1600
+ name: '$name',
1601
+ type: 'string',
1602
+ description: 'Имя фрагмента (без .tpl.php): layout_childs/{name}.tpl.php',
1603
+ required: true,
1604
+ },
1605
+ {
1606
+ name: '$vars',
1607
+ type: 'array',
1608
+ description: 'Переменные для фрагмента',
1609
+ required: false,
1610
+ },
1611
+ ],
1612
+ return_type: 'void',
1613
+ example: `// В main.tpl.php (is_dynamic_layout = true):
1614
+ <?php $this->renderLayoutChild('scheme', ['rows' => $rows]) ?>
1615
+ // Рендерит layout_childs/main_scheme.tpl.php`,
1616
+ },
1617
+ {
1618
+ name: 'href_to',
1619
+ signature: "href_to(string $action = '', array $params = []): string",
1620
+ description: 'Формирует URL к экшену текущего контроллера.',
1621
+ parameters: [
1622
+ {
1623
+ name: '$action',
1624
+ type: 'string',
1625
+ description: "Имя экшена ('' = index)",
1626
+ required: false,
1627
+ },
1628
+ { name: '$params', type: 'array', description: 'GET-параметры', required: false },
1629
+ ],
1630
+ return_type: 'string',
1631
+ example: `<a href="<?= $this->href_to('view', ['id' => $item['id']]) ?>"><?= $item['title'] ?></a>
1632
+ <a href="<?= $this->href_to() ?>">← Назад</a>`,
1633
+ },
1634
+ {
1635
+ name: 'addMainTplCSSName',
1636
+ signature: 'addMainTplCSSName(string $name): void',
1637
+ description: 'Добавляет CSS-класс к корневому элементу шаблона.',
1638
+ parameters: [{ name: '$name', type: 'string', description: 'CSS-класс', required: true }],
1639
+ return_type: 'void',
1640
+ example: `<?php $this->addMainTplCSSName('page-catalog') ?>`,
1641
+ },
1642
+ {
1643
+ name: 'onDemandPrint',
1644
+ signature: 'onDemandPrint(): void',
1645
+ description: 'Выводит on-demand ресурсы (CSS/JS), добавленные контроллерами в процессе выполнения. Обычно вставляется перед </head>.',
1646
+ parameters: [],
1647
+ return_type: 'void',
1648
+ example: `<?= $this->onDemandPrint() ?>`,
1649
+ },
1650
+ ],
1651
+ },
1652
+ // ─────────────────────────────────────────────────────────────────────────
1653
+ // cmsUser — авторизация, сессии, работа с пользователем
1654
+ // system/core/user.php
1655
+ // ─────────────────────────────────────────────────────────────────────────
1656
+ {
1657
+ name: 'cmsUser',
1658
+ class: 'cmsUser',
1659
+ description: 'Класс для работы с текущим пользователем. Singleton. Содержит данные авторизованного пользователя, группы, друзей, сессии и права доступа.',
1660
+ access: 'cmsUser::getInstance() — глобально. $this->cms_user — в контроллере.',
1661
+ methods: [
1662
+ {
1663
+ name: 'login',
1664
+ signature: 'login(string $email, string $password, bool $remember = false, bool $complete_login = true, $model = null): int|array',
1665
+ description: 'Авторизует пользователя по email и паролю. Возвращает ID пользователя или массив (если complete_login=false).',
1666
+ parameters: [
1667
+ { name: '$email', type: 'string', description: 'Email пользователя', required: true },
1668
+ { name: '$password', type: 'string', description: 'Пароль', required: true },
1669
+ {
1670
+ name: '$remember',
1671
+ type: 'bool',
1672
+ description: 'Запомнить на 100 дней (cookie)',
1673
+ default: 'false',
1674
+ },
1675
+ {
1676
+ name: '$complete_login',
1677
+ type: 'bool',
1678
+ description: 'Завершить авторизацию сразу',
1679
+ default: 'true',
1680
+ },
1681
+ ],
1682
+ return_type: 'int|array',
1683
+ example: `$user_id = cmsUser::login($email, $password);
1684
+ if (!$user_id) {
1685
+ cmsUser::addSessionMessage('Неверный email или пароль', 'error');
1686
+ }`,
1687
+ },
1688
+ {
1689
+ name: 'logout',
1690
+ signature: 'logout(): bool',
1691
+ description: 'Выход пользователя из системы. Удаляет сессию, online-запись, cookie авторизации.',
1692
+ parameters: [],
1693
+ return_type: 'bool',
1694
+ example: `cmsUser::logout();
1695
+ $this->redirect(href_to('auth', 'login'));`,
1696
+ },
1697
+ {
1698
+ name: 'isLogged',
1699
+ signature: 'isLogged(): bool',
1700
+ description: 'Проверяет, авторизован ли текущий пользователь',
1701
+ parameters: [],
1702
+ return_type: 'bool',
1703
+ example: `if (!cmsUser::isLogged()) {
1704
+ return $this->redirectToLogin();
1705
+ }`,
1706
+ },
1707
+ {
1708
+ name: 'isAdmin',
1709
+ signature: 'isAdmin(): bool',
1710
+ description: 'Проверяет, является ли текущий пользователь администратором',
1711
+ parameters: [],
1712
+ return_type: 'bool',
1713
+ example: `if (cmsUser::isAdmin()) {
1714
+ // действия для админа
1715
+ }`,
1716
+ },
1717
+ {
1718
+ name: 'get',
1719
+ signature: 'get(string $key): mixed',
1720
+ description: 'Получить свойство пользователя (id, email, nickname, groups и т.д.)',
1721
+ parameters: [{ name: '$key', type: 'string', description: 'Имя свойства', required: true }],
1722
+ return_type: 'mixed',
1723
+ example: `$user_id = cmsUser::get('id');
1724
+ $groups = cmsUser::get('groups');`,
1725
+ },
1726
+ {
1727
+ name: 'isInGroup',
1728
+ signature: 'isInGroup(int $group_id): bool',
1729
+ description: 'Проверяет членство пользователя в группе',
1730
+ parameters: [{ name: '$group_id', type: 'int', description: 'ID группы', required: true }],
1731
+ return_type: 'bool',
1732
+ example: `if (!$this->cms_user->isInGroup(GUEST_GROUP_ID)) {
1733
+ // не гость
1734
+ }`,
1735
+ },
1736
+ {
1737
+ name: 'setUPS',
1738
+ signature: 'setUPS(string $key, mixed $data, int $user_id = null): bool',
1739
+ description: 'Устанавливает пользовательскую настройку (User Personal Setting)',
1740
+ parameters: [
1741
+ { name: '$key', type: 'string', description: 'Ключ настройки', required: true },
1742
+ { name: '$data', type: 'mixed', description: 'Значение', required: true },
1743
+ {
1744
+ name: '$user_id',
1745
+ type: 'int',
1746
+ description: 'ID пользователя (по умолчанию текущий)',
1747
+ required: false,
1748
+ },
1749
+ ],
1750
+ return_type: 'bool',
1751
+ example: `cmsUser::setUPS('notify_email', ['freq' => 'daily'], $user_id);`,
1752
+ },
1753
+ {
1754
+ name: 'getUPS',
1755
+ signature: 'getUPS(string $key, int $user_id = null): mixed',
1756
+ description: 'Получает пользовательскую настройку',
1757
+ parameters: [
1758
+ { name: '$key', type: 'string', description: 'Ключ настройки', required: true },
1759
+ { name: '$user_id', type: 'int', description: 'ID пользователя', required: false },
1760
+ ],
1761
+ return_type: 'mixed',
1762
+ example: `$settings = cmsUser::getUPS('notify_email', $user_id);`,
1763
+ },
1764
+ {
1765
+ name: 'addSessionMessage',
1766
+ signature: "addSessionMessage(string $message, string $class = 'info', bool $is_keep = false): void",
1767
+ description: 'Добавляет сообщение в сессию для отображения после редиректа',
1768
+ parameters: [
1769
+ { name: '$message', type: 'string', description: 'Текст сообщения', required: true },
1770
+ {
1771
+ name: '$class',
1772
+ type: 'string',
1773
+ description: 'CSS-класс: info, success, warning, error',
1774
+ default: "'info'",
1775
+ },
1776
+ {
1777
+ name: '$is_keep',
1778
+ type: 'bool',
1779
+ description: 'Сохранить после показа',
1780
+ default: 'false',
1781
+ },
1782
+ ],
1783
+ return_type: 'void',
1784
+ example: `cmsUser::addSessionMessage('Профиль обновлён!', 'success');
1785
+ return $this->redirect(href_to('profile'));`,
1786
+ },
1787
+ {
1788
+ name: 'getPermissionValue',
1789
+ signature: 'getPermissionValue(string $subject, string $permission): mixed',
1790
+ description: 'Получить значение разрешения для пользователя',
1791
+ parameters: [
1792
+ {
1793
+ name: '$subject',
1794
+ type: 'string',
1795
+ description: 'Субъект (имя контроллера)',
1796
+ required: true,
1797
+ },
1798
+ { name: '$permission', type: 'string', description: 'Имя разрешения', required: true },
1799
+ ],
1800
+ return_type: 'mixed',
1801
+ example: `$can_edit = cmsUser::getPermissionValue('catalog', 'edit');`,
1802
+ },
1803
+ {
1804
+ name: 'isAllowed',
1805
+ signature: 'isAllowed(string $subject, string $permission, mixed $value = true, bool $is_admin_strict = false): bool',
1806
+ description: 'Проверяет, разрешено ли действие',
1807
+ parameters: [
1808
+ { name: '$subject', type: 'string', description: 'Субъект', required: true },
1809
+ { name: '$permission', type: 'string', description: 'Разрешение', required: true },
1810
+ { name: '$value', type: 'mixed', description: 'Ожидаемое значение', default: 'true' },
1811
+ {
1812
+ name: '$is_admin_strict',
1813
+ type: 'bool',
1814
+ description: 'Не давать админу особые права',
1815
+ default: 'false',
1816
+ },
1817
+ ],
1818
+ return_type: 'bool',
1819
+ example: `if (!cmsUser::isAllowed('catalog', 'add_item')) {
1820
+ cmsCore::error404();
1821
+ }`,
1822
+ },
1823
+ {
1824
+ name: 'isDenied',
1825
+ signature: 'isDenied(string $subject, string $permission, mixed $value = true, bool $is_admin_strict = false): bool',
1826
+ description: 'Проверяет, запрещено ли действие',
1827
+ parameters: [
1828
+ { name: '$subject', type: 'string', description: 'Субъект', required: true },
1829
+ { name: '$permission', type: 'string', description: 'Разрешение', required: true },
1830
+ { name: '$value', type: 'mixed', description: 'Проверяемое значение', default: 'true' },
1831
+ {
1832
+ name: '$is_admin_strict',
1833
+ type: 'bool',
1834
+ description: 'Строгая проверка',
1835
+ default: 'false',
1836
+ },
1837
+ ],
1838
+ return_type: 'bool',
1839
+ example: `if (cmsUser::isDenied('content', 'is_premium', 1)) {
1840
+ return cmsCore::error404();
1841
+ }`,
1842
+ },
1843
+ {
1844
+ name: 'autoLogin',
1845
+ signature: 'autoLogin(string $auth_token): int',
1846
+ description: 'Авторизует пользователя по cookie-токену. Вызывается автоматически при загрузке cmsUser.',
1847
+ parameters: [
1848
+ {
1849
+ name: '$auth_token',
1850
+ type: 'string',
1851
+ description: '128-символьный SHA512 токен',
1852
+ required: true,
1853
+ },
1854
+ ],
1855
+ return_type: 'int',
1856
+ example: `// Вызывается автоматически в конструкторе cmsUser`,
1857
+ },
1858
+ {
1859
+ name: 'setCookie',
1860
+ signature: "setCookie(string $key, string $value, int $time = 3600, string $path = '/', bool $http_only = true, string $domain = ''): bool",
1861
+ description: "Устанавливает cookie с префиксом 'icms['",
1862
+ parameters: [
1863
+ { name: '$key', type: 'string', description: 'Имя cookie', required: true },
1864
+ { name: '$value', type: 'string', description: 'Значение', required: true },
1865
+ { name: '$time', type: 'int', description: 'Время жизни в секундах', default: '3600' },
1866
+ { name: '$path', type: 'string', description: 'Путь', default: "'/'" },
1867
+ {
1868
+ name: '$http_only',
1869
+ type: 'bool',
1870
+ description: 'Доступен только для PHP',
1871
+ default: 'true',
1872
+ },
1873
+ { name: '$domain', type: 'string', description: 'Домен', default: "''" },
1874
+ ],
1875
+ return_type: 'bool',
1876
+ example: `cmsUser::setCookie('my_cookie', 'value', 86400);`,
1877
+ },
1878
+ ],
1879
+ },
1880
+ // ─────────────────────────────────────────────────────────────────────────
1881
+ // cmsPermissions — система прав доступа
1882
+ // system/core/permissions.php
1883
+ // ─────────────────────────────────────────────────────────────────────────
1884
+ {
1885
+ name: 'cmsPermissions',
1886
+ class: 'cmsPermissions',
1887
+ description: 'Система разрешений и прав доступа. Проверяет membership в группах, лимиты, флаги.',
1888
+ access: '$this->cms_user->perms — в контроллере. cmsUser::getInstance()->perms',
1889
+ methods: [
1890
+ {
1891
+ name: 'getPermissionValue',
1892
+ signature: 'getPermissionValue(string $subject, string $permission): mixed',
1893
+ description: 'Возвращает значение конкретного разрешения для субъекта',
1894
+ parameters: [
1895
+ {
1896
+ name: '$subject',
1897
+ type: 'string',
1898
+ description: 'Субъект (имя контроллера)',
1899
+ required: true,
1900
+ },
1901
+ {
1902
+ name: '$permission',
1903
+ type: 'string',
1904
+ description: 'Название разрешения',
1905
+ required: true,
1906
+ },
1907
+ ],
1908
+ return_type: 'mixed',
1909
+ example: `$value = $this->cms_user->perms->getPermissionValue('catalog', 'max_items');`,
1910
+ },
1911
+ {
1912
+ name: 'isDenied',
1913
+ signature: 'isDenied(string $subject, string $permission, mixed $value = true, bool $is_admin_strict = false): bool',
1914
+ description: 'Проверяет запрет: принадлежит ли значение указанному',
1915
+ parameters: [
1916
+ { name: '$subject', type: 'string', description: 'Субъект', required: true },
1917
+ { name: '$permission', type: 'string', description: 'Разрешение', required: true },
1918
+ { name: '$value', type: 'mixed', description: 'Запрещающее значение', default: 'true' },
1919
+ {
1920
+ name: '$is_admin_strict',
1921
+ type: 'bool',
1922
+ description: 'Не пропускать админа',
1923
+ default: 'false',
1924
+ },
1925
+ ],
1926
+ return_type: 'bool',
1927
+ example: `if ($this->cms_user->perms->isDenied('catalog', 'is_locked', 1)) {
1928
+ return cmsCore::error404();
1929
+ }`,
1930
+ },
1931
+ {
1932
+ name: 'isAllowed',
1933
+ signature: 'isAllowed(string $subject, string $permission, mixed $value = true, bool $is_admin_strict = false): bool',
1934
+ description: 'Проверяет разрешение: совпадает ли значение с ожидаемым',
1935
+ parameters: [
1936
+ { name: '$subject', type: 'string', description: 'Субъект', required: true },
1937
+ { name: '$permission', type: 'string', description: 'Разрешение', required: true },
1938
+ { name: '$value', type: 'mixed', description: 'Ожидаемое значение', default: 'true' },
1939
+ {
1940
+ name: '$is_admin_strict',
1941
+ type: 'bool',
1942
+ description: 'Не пропускать админа',
1943
+ default: 'false',
1944
+ },
1945
+ ],
1946
+ return_type: 'bool',
1947
+ example: `if (!$this->cms_user->perms->isAllowed('catalog', 'add')) {
1948
+ cmsUser::addSessionMessage('Нет прав на добавление', 'error');
1949
+ $this->redirectBack();
1950
+ }`,
1951
+ },
1952
+ {
1953
+ name: 'isPermittedLimitReached',
1954
+ signature: 'isPermittedLimitReached(string $subject, string $permission, int $current_value = 0, bool $is_admin_strict = false): bool',
1955
+ description: 'Проверяет, достигнут ли лимит (current >= limit)',
1956
+ parameters: [
1957
+ { name: '$subject', type: 'string', description: 'Субъект', required: true },
1958
+ {
1959
+ name: '$permission',
1960
+ type: 'string',
1961
+ description: 'Лимит (например, max_items)',
1962
+ required: true,
1963
+ },
1964
+ { name: '$current_value', type: 'int', description: 'Текущее значение', default: '0' },
1965
+ {
1966
+ name: '$is_admin_strict',
1967
+ type: 'bool',
1968
+ description: 'Не пропускать админа',
1969
+ default: 'false',
1970
+ },
1971
+ ],
1972
+ return_type: 'bool',
1973
+ example: `if ($this->cms_user->perms->isPermittedLimitReached('catalog', 'max_images', $image_count)) {
1974
+ cmsUser::addSessionMessage('Достигнут лимит загрузки изображений', 'warning');
1975
+ }`,
1976
+ },
1977
+ {
1978
+ name: 'addRule',
1979
+ signature: 'addRule(string $controller, array $rule): int|false',
1980
+ description: 'Добавляет новое правило доступа в БД (статический метод)',
1981
+ parameters: [
1982
+ { name: '$controller', type: 'string', description: 'Имя контроллера', required: true },
1983
+ {
1984
+ name: '$rule',
1985
+ type: 'array',
1986
+ description: 'Массив: name, type (flag/list/number), options',
1987
+ required: true,
1988
+ },
1989
+ ],
1990
+ return_type: 'int|false',
1991
+ example: `cmsPermissions::addRule('catalog', [
1992
+ 'name' => 'use_api',
1993
+ 'type' => 'flag',
1994
+ 'options' => ''
1995
+ ]);`,
1996
+ },
1997
+ {
1998
+ name: 'getRulesList',
1999
+ signature: 'getRulesList(string $controller): array',
2000
+ description: 'Возвращает список всех доступных правил доступа для контроллера',
2001
+ parameters: [
2002
+ { name: '$controller', type: 'string', description: 'Имя контроллера', required: true },
2003
+ ],
2004
+ return_type: 'array',
2005
+ example: `$rules = cmsPermissions::getRulesList('catalog');`,
2006
+ },
2007
+ ],
2008
+ },
2009
+ // ─────────────────────────────────────────────────────────────────────────
2010
+ // cmsDatabase — прямые SQL операции
2011
+ // system/core/database.php
2012
+ // ─────────────────────────────────────────────────────────────────────────
2013
+ {
2014
+ name: 'cmsDatabase',
2015
+ class: 'cmsDatabase',
2016
+ description: 'Низкоуровневый класс работы с MySQL. Прямые запросы, транзакции, работа с таблицами. Обычно используется через cmsModel.',
2017
+ access: '$this->cms_core->db — в контроллере. cmsCore::getInstance()->db.',
2018
+ methods: [
2019
+ {
2020
+ name: 'query',
2021
+ signature: 'query(string $sql, array|string $params = false, bool $quiet = false): mixed',
2022
+ description: 'Выполняет SQL запрос с подстановкой параметров через vsprintf',
2023
+ parameters: [
2024
+ {
2025
+ name: '$sql',
2026
+ type: 'string',
2027
+ description: 'SQL запрос с %s плейсхолдерами',
2028
+ required: true,
2029
+ },
2030
+ {
2031
+ name: '$params',
2032
+ type: 'array|string',
2033
+ description: 'Параметры для подстановки',
2034
+ required: false,
2035
+ },
2036
+ {
2037
+ name: '$quiet',
2038
+ type: 'bool',
2039
+ description: 'Не выводить ошибку при неудаче',
2040
+ required: false,
2041
+ },
2042
+ ],
2043
+ return_type: 'mixed',
2044
+ example: `$result = $this->cms_core->db->query(
2045
+ "SELECT * FROM {#}my_table WHERE id = %d AND is_active = %d",
2046
+ [$id, 1]
2047
+ );`,
2048
+ },
2049
+ {
2050
+ name: 'insert',
2051
+ signature: 'insert(string $table, array $data, bool $skip_check_fields = false, bool $array_as_json = false, bool $ignore = false): int|bool',
2052
+ description: 'INSERT запрос. Возвращает ID вставленной записи.',
2053
+ parameters: [
2054
+ {
2055
+ name: '$table',
2056
+ type: 'string',
2057
+ description: 'Имя таблицы без префикса',
2058
+ required: true,
2059
+ },
2060
+ {
2061
+ name: '$data',
2062
+ type: 'array',
2063
+ description: 'Ассоциативный массив поле => значение',
2064
+ required: true,
2065
+ },
2066
+ {
2067
+ name: '$skip_check_fields',
2068
+ type: 'bool',
2069
+ description: 'Не проверять поля в таблице',
2070
+ default: 'false',
2071
+ },
2072
+ {
2073
+ name: '$array_as_json',
2074
+ type: 'bool',
2075
+ description: 'Массивы как JSON (иначе YAML)',
2076
+ default: 'false',
2077
+ },
2078
+ { name: '$ignore', type: 'bool', description: 'INSERT IGNORE', default: 'false' },
2079
+ ],
2080
+ return_type: 'int|bool',
2081
+ example: `$id = $this->cms_core->db->insert('my_items', [
2082
+ 'title' => $title,
2083
+ 'user_id' => $this->cms_user->id,
2084
+ 'date_add' => date('Y-m-d H:i:s')
2085
+ ]);`,
2086
+ },
2087
+ {
2088
+ name: 'update',
2089
+ signature: 'update(string $table, string $where, array $data, bool $skip_check_fields = false, bool $array_as_json = false): bool',
2090
+ description: 'UPDATE запрос',
2091
+ parameters: [
2092
+ { name: '$table', type: 'string', description: 'Имя таблицы', required: true },
2093
+ { name: '$where', type: 'string', description: 'WHERE условие', required: true },
2094
+ { name: '$data', type: 'array', description: 'Данные для обновления', required: true },
2095
+ ],
2096
+ return_type: 'bool',
2097
+ example: `$this->cms_core->db->update(
2098
+ 'my_items',
2099
+ 'id = ' . (int)$id,
2100
+ ['title' => $title, 'is_pub' => 1]
2101
+ );`,
2102
+ },
2103
+ {
2104
+ name: 'delete',
2105
+ signature: 'delete(string $table_name, string $where): bool',
2106
+ description: 'DELETE запрос',
2107
+ parameters: [
2108
+ { name: '$table_name', type: 'string', description: 'Имя таблицы', required: true },
2109
+ { name: '$where', type: 'string', description: 'WHERE условие', required: true },
2110
+ ],
2111
+ return_type: 'bool',
2112
+ example: `$this->cms_core->db->delete('my_items', 'id = ' . (int)$id);`,
2113
+ },
2114
+ {
2115
+ name: 'getRow',
2116
+ signature: "getRow(string $table, string $where = '1', string $fields = '*', string $order = ''): array|false",
2117
+ description: 'Получает одну строку из таблицы',
2118
+ parameters: [
2119
+ { name: '$table', type: 'string', description: 'Имя таблицы', required: true },
2120
+ { name: '$where', type: 'string', description: 'WHERE условие', default: "'1'" },
2121
+ { name: '$fields', type: 'string', description: 'Список полей', default: "'*'" },
2122
+ { name: '$order', type: 'string', description: 'ORDER BY', default: "''" },
2123
+ ],
2124
+ return_type: 'array|false',
2125
+ example: `$item = $this->cms_core->db->getRow('my_items', 'id = ' . (int)$id);`,
2126
+ },
2127
+ {
2128
+ name: 'getRows',
2129
+ signature: "getRows(string $table_name, string $where = '1', string $fields = '*', string $order = 'id ASC'): array|false",
2130
+ description: 'Получает все строки из таблицы',
2131
+ parameters: [
2132
+ { name: '$table_name', type: 'string', description: 'Имя таблицы', required: true },
2133
+ { name: '$where', type: 'string', description: 'WHERE условие', default: "'1'" },
2134
+ { name: '$fields', type: 'string', description: 'Список полей', default: "'*'" },
2135
+ { name: '$order', type: 'string', description: 'ORDER BY', default: "'id ASC'" },
2136
+ ],
2137
+ return_type: 'array|false',
2138
+ example: `$items = $this->cms_core->db->getRows('my_items', 'is_pub = 1', '*', 'date_add DESC');`,
2139
+ },
2140
+ {
2141
+ name: 'getField',
2142
+ signature: "getField(string $table, string $where, string $field, string $order = ''): mixed",
2143
+ description: 'Получает значение одного поля',
2144
+ parameters: [
2145
+ { name: '$table', type: 'string', description: 'Имя таблицы', required: true },
2146
+ { name: '$where', type: 'string', description: 'WHERE условие', required: true },
2147
+ { name: '$field', type: 'string', description: 'Имя поля', required: true },
2148
+ { name: '$order', type: 'string', description: 'ORDER BY', default: "''" },
2149
+ ],
2150
+ return_type: 'mixed',
2151
+ example: `$title = $this->cms_core->db->getField('my_items', 'id = ' . (int)$id, 'title');`,
2152
+ },
2153
+ {
2154
+ name: 'getRowsCount',
2155
+ signature: "getRowsCount(string $table, string $where = '1', int $limit = false): int|false",
2156
+ description: 'Возвращает количество строк',
2157
+ parameters: [
2158
+ { name: '$table', type: 'string', description: 'Имя таблицы', required: true },
2159
+ { name: '$where', type: 'string', description: 'WHERE условие', default: "'1'" },
2160
+ { name: '$limit', type: 'int', description: 'Лимит', default: 'false' },
2161
+ ],
2162
+ return_type: 'int|false',
2163
+ example: `$total = $this->cms_core->db->getRowsCount('my_items', 'is_pub = 1');`,
2164
+ },
2165
+ {
2166
+ name: 'beginTransaction',
2167
+ signature: 'beginTransaction(): cmsDatabase',
2168
+ description: 'Начинает транзакцию',
2169
+ parameters: [],
2170
+ return_type: 'cmsDatabase',
2171
+ example: `$this->cms_core->db->beginTransaction();
2172
+ // ... операции ...
2173
+ $this->cms_core->db->commit();`,
2174
+ },
2175
+ {
2176
+ name: 'commit',
2177
+ signature: 'commit(): cmsDatabase',
2178
+ description: 'Фиксирует транзакцию',
2179
+ parameters: [],
2180
+ return_type: 'cmsDatabase',
2181
+ example: `$this->cms_core->db->commit();`,
2182
+ },
2183
+ {
2184
+ name: 'rollback',
2185
+ signature: 'rollback(): cmsDatabase',
2186
+ description: 'Откатывает транзакцию',
2187
+ parameters: [],
2188
+ return_type: 'cmsDatabase',
2189
+ example: `$this->cms_core->db->rollback();`,
2190
+ },
2191
+ {
2192
+ name: 'lastId',
2193
+ signature: 'lastId(): int',
2194
+ description: 'Возвращает ID последней вставленной записи',
2195
+ parameters: [],
2196
+ return_type: 'int',
2197
+ example: `$id = $this->cms_core->db->lastId();`,
2198
+ },
2199
+ {
2200
+ name: 'escape',
2201
+ signature: 'escape(string|array $string): string|array',
2202
+ description: 'Экранирует строку или массив для SQL',
2203
+ parameters: [
2204
+ {
2205
+ name: '$string',
2206
+ type: 'string|array',
2207
+ description: 'Строка или массив',
2208
+ required: true,
2209
+ },
2210
+ ],
2211
+ return_type: 'string|array',
2212
+ example: `$safe_value = $this->cms_core->db->escape($user_input);`,
2213
+ },
2214
+ {
2215
+ name: 'prepareValue',
2216
+ signature: 'prepareValue(string $field, mixed $value, bool $array_as_json = false): string',
2217
+ description: 'Подготавливает значение поля для SQL запроса (экранирование, кавычки, NULL)',
2218
+ parameters: [
2219
+ {
2220
+ name: '$field',
2221
+ type: 'string',
2222
+ description: 'Имя поля (для определения типа)',
2223
+ required: true,
2224
+ },
2225
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
2226
+ {
2227
+ name: '$array_as_json',
2228
+ type: 'bool',
2229
+ description: 'Массив как JSON',
2230
+ default: 'false',
2231
+ },
2232
+ ],
2233
+ return_type: 'string',
2234
+ example: `// Используется внутренне insert/update`,
2235
+ },
2236
+ {
2237
+ name: 'autocommitOff',
2238
+ signature: 'autocommitOff(): cmsDatabase',
2239
+ description: 'Отключает автокоммит транзакций',
2240
+ parameters: [],
2241
+ return_type: 'cmsDatabase',
2242
+ example: `$this->cms_core->db->autocommitOff();`,
2243
+ },
2244
+ {
2245
+ name: 'autocommitOn',
2246
+ signature: 'autocommitOn(): cmsDatabase',
2247
+ description: 'Включает автокоммит транзакций',
2248
+ parameters: [],
2249
+ return_type: 'cmsDatabase',
2250
+ example: `$this->cms_core->db->autocommitOn();`,
2251
+ },
2252
+ {
2253
+ name: 'isTableExists',
2254
+ signature: 'isTableExists(string $table_name): bool',
2255
+ description: 'Проверяет существование таблицы',
2256
+ parameters: [
2257
+ {
2258
+ name: '$table_name',
2259
+ type: 'string',
2260
+ description: 'Имя таблицы без префикса',
2261
+ required: true,
2262
+ },
2263
+ ],
2264
+ return_type: 'bool',
2265
+ example: `if (!$this->cms_core->db->isTableExists('my_table')) {
2266
+ // создать таблицу
2267
+ }`,
2268
+ },
2269
+ {
2270
+ name: 'getTableFields',
2271
+ signature: 'getTableFields(string $table_name, bool $use_cache = true): array',
2272
+ description: 'Возвращает список полей таблицы',
2273
+ parameters: [
2274
+ { name: '$table_name', type: 'string', description: 'Имя таблицы', required: true },
2275
+ { name: '$use_cache', type: 'bool', description: 'Использовать кэш', default: 'true' },
2276
+ ],
2277
+ return_type: 'array',
2278
+ example: `$fields = $this->cms_core->db->getTableFields('my_items');`,
2279
+ },
2280
+ ],
2281
+ },
2282
+ // ─────────────────────────────────────────────────────────────────────────
2283
+ // cmsPaginator — пагинация
2284
+ // system/core/paginator.php
2285
+ // ─────────────────────────────────────────────────────────────────────────
2286
+ {
2287
+ name: 'cmsPaginator',
2288
+ class: 'cmsPaginator',
2289
+ description: 'Генерация HTML пагинации. Создаёт массив страниц и URL для навигации.',
2290
+ access: 'new cmsPaginator($total, $perpage, $current_page, $base_uri, $query = [])',
2291
+ methods: [
2292
+ {
2293
+ name: 'setMaxPagesToShow',
2294
+ signature: 'setMaxPagesToShow(int $max_show_pages): cmsPaginator',
2295
+ description: 'Максимальное количество видимых страниц',
2296
+ parameters: [
2297
+ {
2298
+ name: '$max_show_pages',
2299
+ type: 'int',
2300
+ description: 'Количество страниц',
2301
+ required: true,
2302
+ },
2303
+ ],
2304
+ return_type: 'cmsPaginator',
2305
+ example: `$paginator = new cmsPaginator($total, 20, $page, $base_url)->setMaxPagesToShow(7);`,
2306
+ },
2307
+ {
2308
+ name: 'setPageParamName',
2309
+ signature: 'setPageParamName(string $page_param_name): cmsPaginator',
2310
+ description: 'Имя GET параметра номера страницы',
2311
+ parameters: [
2312
+ {
2313
+ name: '$page_param_name',
2314
+ type: 'string',
2315
+ description: 'Имя параметра',
2316
+ default: "'page'",
2317
+ },
2318
+ ],
2319
+ return_type: 'cmsPaginator',
2320
+ example: `->setPageParamName('page_num')`,
2321
+ },
2322
+ {
2323
+ name: 'getRendered',
2324
+ signature: 'getRendered(): string',
2325
+ description: 'Возвращает готовый HTML пагинации',
2326
+ parameters: [],
2327
+ return_type: 'string',
2328
+ example: `<?= $paginator->getRendered() ?>`,
2329
+ },
2330
+ ],
2331
+ },
2332
+ // ─────────────────────────────────────────────────────────────────────────
2333
+ // cmsResponse — HTTP ответ
2334
+ // system/core/response.php
2335
+ // ─────────────────────────────────────────────────────────────────────────
2336
+ {
2337
+ name: 'cmsResponse',
2338
+ class: 'cmsResponse',
2339
+ description: 'Управление HTTP ответом: заголовки, body, отправка файлов, JSON.',
2340
+ access: '$this->cms_core->response — в контроллере. cmsResponse::getInstance() — глобально.',
2341
+ methods: [
2342
+ {
2343
+ name: 'setContent',
2344
+ signature: 'setContent(array|string $content): cmsResponse',
2345
+ description: 'Устанавливает тело ответа',
2346
+ parameters: [
2347
+ {
2348
+ name: '$content',
2349
+ type: 'array|string',
2350
+ description: 'HTML или массив для JSON',
2351
+ required: true,
2352
+ },
2353
+ ],
2354
+ return_type: 'cmsResponse',
2355
+ example: `$this->cms_core->response->setContent('<h1>Hello</h1>');`,
2356
+ },
2357
+ {
2358
+ name: 'setStatusCode',
2359
+ signature: 'setStatusCode(int $status_code): cmsResponse',
2360
+ description: 'Устанавливает HTTP статус-код',
2361
+ parameters: [
2362
+ {
2363
+ name: '$status_code',
2364
+ type: 'int',
2365
+ description: 'Код (200, 404, 403 и т.д.)',
2366
+ required: true,
2367
+ },
2368
+ ],
2369
+ return_type: 'cmsResponse',
2370
+ example: `$this->cms_core->response->setStatusCode(403);`,
2371
+ },
2372
+ {
2373
+ name: 'setHeader',
2374
+ signature: 'setHeader(string $name, string $value): cmsResponse',
2375
+ description: 'Добавляет HTTP заголовок',
2376
+ parameters: [
2377
+ { name: '$name', type: 'string', description: 'Имя заголовка', required: true },
2378
+ { name: '$value', type: 'string', description: 'Значение', required: true },
2379
+ ],
2380
+ return_type: 'cmsResponse',
2381
+ example: `$this->cms_core->response->setHeader('X-Custom-Header', 'value');`,
2382
+ },
2383
+ {
2384
+ name: 'send',
2385
+ signature: 'send(bool $exit = true): void',
2386
+ description: 'Отправляет заголовки и контент, завершает выполнение',
2387
+ parameters: [
2388
+ { name: '$exit', type: 'bool', description: 'Вызывать exit()', default: 'true' },
2389
+ ],
2390
+ return_type: 'void',
2391
+ example: `$this->cms_core->response->send();`,
2392
+ },
2393
+ {
2394
+ name: 'sendFile',
2395
+ signature: 'sendFile(string $file_path, array $headers = []): void',
2396
+ description: 'Отправляет файл как HTTP ответ',
2397
+ parameters: [
2398
+ { name: '$file_path', type: 'string', description: 'Путь к файлу', required: true },
2399
+ {
2400
+ name: '$headers',
2401
+ type: 'array',
2402
+ description: 'Дополнительные заголовки',
2403
+ default: '[]',
2404
+ },
2405
+ ],
2406
+ return_type: 'void',
2407
+ example: `$this->cms_core->response->sendFile($file_path, [
2408
+ 'Content-Disposition' => 'attachment; filename="file.pdf"'
2409
+ ]);`,
2410
+ },
2411
+ {
2412
+ name: 'sendAndExit',
2413
+ signature: 'sendAndExit(): void',
2414
+ description: 'Отправляет ответ и завершает выполнение',
2415
+ parameters: [],
2416
+ return_type: 'void',
2417
+ example: `$this->cms_core->response->sendAndExit();`,
2418
+ },
2419
+ {
2420
+ name: 'getNonce',
2421
+ signature: 'getNonce(): string',
2422
+ description: 'Возвращает nonce для CSP (генерируется один раз)',
2423
+ parameters: [],
2424
+ return_type: 'string',
2425
+ example: `$nonce = cmsResponse::getNonce();
2426
+ // Использовать в inline-скриптах: <script nonce="<?= $nonce ?>">`,
2427
+ },
2428
+ {
2429
+ name: 'renderJSON',
2430
+ signature: 'renderJSON(array $data): void',
2431
+ description: 'Отправляет JSON ответ и завершает выполнение',
2432
+ parameters: [
2433
+ { name: '$data', type: 'array', description: 'Данные для JSON', required: true },
2434
+ ],
2435
+ return_type: 'void',
2436
+ example: `$this->cms_core->response->renderJSON(['success' => true, 'id' => $id]);`,
2437
+ },
2438
+ ],
2439
+ },
2440
+ // ─────────────────────────────────────────────────────────────────────────
2441
+ // cmsImages — работа с изображениями
2442
+ // system/core/images.php
2443
+ // ─────────────────────────────────────────────────────────────────────────
2444
+ {
2445
+ name: 'cmsImages',
2446
+ class: 'cmsImages',
2447
+ description: 'Класс для работы с изображениями: ресайз, водяные знаки, превью, конвертация.',
2448
+ access: 'cmsImages::getInstance() — глобально. cmsCore::getInstance()->images',
2449
+ methods: [
2450
+ {
2451
+ name: 'resize',
2452
+ signature: 'resize(string $source_file, string $dest_file, int $width, int $height, bool $is_update_exif = true): bool',
2453
+ description: 'Изменяет размер изображения',
2454
+ parameters: [
2455
+ { name: '$source_file', type: 'string', description: 'Исходный файл', required: true },
2456
+ { name: '$dest_file', type: 'string', description: 'Результат', required: true },
2457
+ { name: '$width', type: 'int', description: 'Новая ширина', required: true },
2458
+ { name: '$height', type: 'int', description: 'Новая высота', required: true },
2459
+ { name: '$is_update_exif', type: 'bool', description: 'Обновить EXIF', default: 'true' },
2460
+ ],
2461
+ return_type: 'bool',
2462
+ example: `cmsImages::getInstance()->resize($src, $dst, 800, 600);`,
2463
+ },
2464
+ {
2465
+ name: 'getHandledFilePath',
2466
+ signature: 'getHandledFilePath(string $file_path, string $preset_name): string',
2467
+ description: 'Возвращает путь к пресету изображения (автоматически создаёт превью)',
2468
+ parameters: [
2469
+ { name: '$file_path', type: 'string', description: 'Путь к оригиналу', required: true },
2470
+ { name: '$preset_name', type: 'string', description: 'Имя пресета', required: true },
2471
+ ],
2472
+ return_type: 'string',
2473
+ example: `$thumb_path = cmsImages::getInstance()->getHandledFilePath($img, 'small');`,
2474
+ },
2475
+ {
2476
+ name: 'isImageFile',
2477
+ signature: 'isImageFile(string $file_path): bool',
2478
+ description: 'Проверяет, является ли файл изображением',
2479
+ parameters: [
2480
+ { name: '$file_path', type: 'string', description: 'Путь к файлу', required: true },
2481
+ ],
2482
+ return_type: 'bool',
2483
+ example: `if (cmsImages::getInstance()->isImageFile($path)) {
2484
+ // это изображение
2485
+ }`,
2486
+ },
2487
+ ],
2488
+ },
2489
+ // ─────────────────────────────────────────────────────────────────────────
2490
+ // cmsMailer — отправка email
2491
+ // system/core/mailer.php
2492
+ // ─────────────────────────────────────────────────────────────────────────
2493
+ {
2494
+ name: 'cmsMailer',
2495
+ class: 'cmsMailer',
2496
+ description: 'Отправка email. Поддерживает SMTP, шаблоны писем, вложения.',
2497
+ access: 'cmsCore::getInstance()->mailer — в контроллере. new cmsMailer()',
2498
+ methods: [
2499
+ {
2500
+ name: 'send',
2501
+ signature: 'send(array $letter): bool',
2502
+ description: 'Отправляет письмо. letter = [to, from, from_name, subject, body, attachments, is_html]',
2503
+ parameters: [
2504
+ { name: '$letter', type: 'array', description: 'Массив данных письма', required: true },
2505
+ ],
2506
+ return_type: 'bool',
2507
+ example: `return cmsCore::getInstance()->mailer->send([
2508
+ 'to' => $email,
2509
+ 'subject' => 'Подтверждение регистрации',
2510
+ 'body' => $html_content,
2511
+ 'is_html' => true
2512
+ ]);`,
2513
+ },
2514
+ {
2515
+ name: 'addLetter',
2516
+ signature: 'addLetter(array $letter): cmsMailer',
2517
+ description: 'Добавляет письмо в очередь на отправку',
2518
+ parameters: [
2519
+ { name: '$letter', type: 'array', description: 'Массив письма', required: true },
2520
+ ],
2521
+ return_type: 'cmsMailer',
2522
+ example: `cmsCore::getInstance()->mailer->addLetter([
2523
+ 'to' => $email,
2524
+ 'subject' => 'Привет!',
2525
+ 'body' => 'Добро пожаловать на сайт!'
2526
+ ]);`,
2527
+ },
2528
+ {
2529
+ name: 'queueSending',
2530
+ signature: 'queueSending(): void',
2531
+ description: 'Отправляет все письма из очереди',
2532
+ parameters: [],
2533
+ return_type: 'void',
2534
+ example: `cmsCore::getInstance()->mailer->queueSending();`,
2535
+ },
2536
+ ],
2537
+ },
2538
+ // ─────────────────────────────────────────────────────────────────────────
2539
+ // cmsGrid — рендеринг гридов
2540
+ // system/core/grid.php
2541
+ // ─────────────────────────────────────────────────────────────────────────
2542
+ {
2543
+ name: 'cmsGrid',
2544
+ class: 'cmsGrid',
2545
+ description: 'Класс для рендеринга табличных данных (используется в бэкенде для списков).',
2546
+ access: 'new cmsGrid($options) — создание грида в бэкенде',
2547
+ methods: [
2548
+ {
2549
+ name: 'setColumns',
2550
+ signature: 'setColumns(array $columns): cmsGrid',
2551
+ description: 'Устанавливает колонки грида',
2552
+ parameters: [
2553
+ { name: '$columns', type: 'array', description: 'Массив колонок', required: true },
2554
+ ],
2555
+ return_type: 'cmsGrid',
2556
+ example: `$grid = new cmsGrid($options);
2557
+ $grid->setColumns(['id', 'title', 'date_pub']);`,
2558
+ },
2559
+ {
2560
+ name: 'render',
2561
+ signature: 'render(array $rows): string',
2562
+ description: 'Рендерит грид с данными, возвращает HTML',
2563
+ parameters: [
2564
+ { name: '$rows', type: 'array', description: 'Массив строк данных', required: true },
2565
+ ],
2566
+ return_type: 'string',
2567
+ example: `$html = $grid->render($items);`,
2568
+ },
2569
+ {
2570
+ name: 'makeDataItem',
2571
+ signature: 'makeDataItem(array $item): array',
2572
+ description: 'Обрабатывает одну строку данных (фильтры, преобразования)',
2573
+ parameters: [
2574
+ { name: '$item', type: 'array', description: 'Строка данных', required: true },
2575
+ ],
2576
+ return_type: 'array',
2577
+ example: `$item = $grid->makeDataItem($row);`,
2578
+ },
2579
+ ],
2580
+ },
2581
+ // ─────────────────────────────────────────────────────────────────────────
2582
+ // cmsFormField — базовый класс полей формы
2583
+ // system/core/formfield.php
2584
+ // ─────────────────────────────────────────────────────────────────────────
2585
+ {
2586
+ name: 'cmsFormField',
2587
+ class: 'cmsFormField',
2588
+ description: 'Базовый класс для всех типов полей форм. Поля используются в cmsForm.',
2589
+ access: 'Используется автоматически cmsForm при рендеринге',
2590
+ methods: [
2591
+ {
2592
+ name: 'getOptions',
2593
+ signature: 'getOptions(): array',
2594
+ description: 'Возвращает настройки поля',
2595
+ parameters: [],
2596
+ return_type: 'array',
2597
+ example: `$opts = $form_field->getOptions();`,
2598
+ },
2599
+ {
2600
+ name: 'parse',
2601
+ signature: 'parse(array $data): mixed',
2602
+ description: 'Парсит значение поля из данных формы',
2603
+ parameters: [
2604
+ { name: '$data', type: 'array', description: 'POST/GET данные', required: true },
2605
+ ],
2606
+ return_type: 'mixed',
2607
+ example: `$value = $field->parse($this->request->data('post'));`,
2608
+ },
2609
+ {
2610
+ name: 'store',
2611
+ signature: 'store(mixed $value, cmsModel $model): mixed',
2612
+ description: 'Сохраняет значение поля в БД',
2613
+ parameters: [
2614
+ { name: '$value', type: 'mixed', description: 'Значение', required: true },
2615
+ { name: '$model', type: 'cmsModel', description: 'Модель', required: true },
2616
+ ],
2617
+ return_type: 'mixed',
2618
+ example: `$stored_value = $field->store($value, $this->model);`,
2619
+ },
2620
+ {
2621
+ name: 'getInput',
2622
+ signature: 'getInput(mixed $value): string',
2623
+ description: 'Возвращает HTML input для поля',
2624
+ parameters: [
2625
+ { name: '$value', type: 'mixed', description: 'Текущее значение', required: true },
2626
+ ],
2627
+ return_type: 'string',
2628
+ example: `echo $field->getInput($item['field_value']);`,
2629
+ },
2630
+ ],
2631
+ },
2632
+ // ─────────────────────────────────────────────────────────────────────────
2633
+ // cmsRequest — HTTP запрос (дополнение)
2634
+ // system/core/request.php
2635
+ // ─────────────────────────────────────────────────────────────────────────
2636
+ {
2637
+ name: 'cmsRequest (доп.)',
2638
+ class: 'cmsRequest',
2639
+ description: 'Дополнительные методы cmsRequest: работа с заголовками, IP, проверки типа устройства',
2640
+ access: '$this->request — в контроллере',
2641
+ methods: [
2642
+ {
2643
+ name: 'getClientIp',
2644
+ signature: 'getClientIp(bool $safe = true): string',
2645
+ description: 'Получить IP адрес клиента (с учётом прокси)',
2646
+ parameters: [
2647
+ {
2648
+ name: '$safe',
2649
+ type: 'bool',
2650
+ description: 'Безопасный режим (не доверяет X-Forwarded)',
2651
+ default: 'true',
2652
+ },
2653
+ ],
2654
+ return_type: 'string',
2655
+ example: `$ip = $this->request->getClientIp();`,
2656
+ },
2657
+ {
2658
+ name: 'isMobile',
2659
+ signature: 'isMobile(): bool',
2660
+ description: 'Проверяет, мобильное ли устройство',
2661
+ parameters: [],
2662
+ return_type: 'bool',
2663
+ example: `if ($this->request->isMobile()) {
2664
+ // мобильная версия
2665
+ }`,
2666
+ },
2667
+ {
2668
+ name: 'isSecure',
2669
+ signature: 'isSecure(): bool',
2670
+ description: 'Проверяет HTTPS соединение',
2671
+ parameters: [],
2672
+ return_type: 'bool',
2673
+ example: `if (!$this->request->isSecure()) {
2674
+ $this->redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
2675
+ }`,
2676
+ },
2677
+ {
2678
+ name: 'getUserAgent',
2679
+ signature: 'getUserAgent(): string',
2680
+ description: 'Возвращает User-Agent браузера',
2681
+ parameters: [],
2682
+ return_type: 'string',
2683
+ example: `$ua = $this->request->getUserAgent();`,
2684
+ },
2685
+ {
2686
+ name: 'hasHeader',
2687
+ signature: 'hasHeader(string $name): bool',
2688
+ description: 'Проверяет наличие HTTP заголовка',
2689
+ parameters: [
2690
+ { name: '$name', type: 'string', description: 'Имя заголовка', required: true },
2691
+ ],
2692
+ return_type: 'bool',
2693
+ example: `if ($this->request->hasHeader('X-Requested-With')) {
2694
+ // AJAX
2695
+ }`,
2696
+ },
2697
+ {
2698
+ name: 'getHeader',
2699
+ signature: 'getHeader(string $name, mixed $default = null): mixed',
2700
+ description: 'Получить значение HTTP заголовка',
2701
+ parameters: [
2702
+ { name: '$name', type: 'string', description: 'Имя заголовка', required: true },
2703
+ {
2704
+ name: '$default',
2705
+ type: 'mixed',
2706
+ description: 'Значение по умолчанию',
2707
+ required: false,
2708
+ },
2709
+ ],
2710
+ return_type: 'mixed',
2711
+ example: `$token = $this->request->getHeader('Authorization');`,
2712
+ },
2713
+ ],
2714
+ },
2715
+ // ─────────────────────────────────────────────────────────────────────────
2716
+ // cmsConfig (доп.) — расширенные методы
2717
+ // system/core/config.php
2718
+ // ─────────────────────────────────────────────────────────────────────────
2719
+ {
2720
+ name: 'cmsConfig (доп.)',
2721
+ class: 'cmsConfig',
2722
+ description: 'Дополнительные методы cmsConfig: пути, константы, управление конфигом',
2723
+ access: "cmsConfig::getInstance() — глобально. cmsConfig::get('key') — статический доступ",
2724
+ methods: [
2725
+ {
2726
+ name: 'get',
2727
+ signature: 'get(string $key, mixed $default = null): mixed',
2728
+ description: 'Получить значение конфига (статический шорткат)',
2729
+ parameters: [
2730
+ { name: '$key', type: 'string', description: 'Ключ конфига', required: true },
2731
+ {
2732
+ name: '$default',
2733
+ type: 'mixed',
2734
+ description: 'Значение по умолчанию',
2735
+ required: false,
2736
+ },
2737
+ ],
2738
+ return_type: 'mixed',
2739
+ example: `$template = cmsConfig::get('template', 'default');
2740
+ $db_prefix = cmsConfig::get('db_prefix');`,
2741
+ },
2742
+ {
2743
+ name: 'getAll',
2744
+ signature: 'getAll(): array',
2745
+ description: 'Возвращает все конфигурационные настройки',
2746
+ parameters: [],
2747
+ return_type: 'array',
2748
+ example: `$config = cmsConfig::getInstance()->getAll();`,
2749
+ },
2750
+ {
2751
+ name: 'getControllersMapping',
2752
+ signature: 'getControllersMapping(): array',
2753
+ description: 'Возвращает маппинг контроллеров (для ремапа URL)',
2754
+ parameters: [],
2755
+ return_type: 'array',
2756
+ example: `$map = cmsConfig::getControllersMapping();`,
2757
+ },
2758
+ {
2759
+ name: 'isReady',
2760
+ signature: 'isReady(): bool',
2761
+ description: 'Проверяет, загружена ли конфигурация',
2762
+ parameters: [],
2763
+ return_type: 'bool',
2764
+ example: `if (!cmsConfig::getInstance()->isReady()) {
2765
+ // конфиг не загружен
2766
+ }`,
2767
+ },
2768
+ {
2769
+ name: 'getUploadsPath',
2770
+ signature: 'getUploadsPath(): string',
2771
+ description: 'Возвращает абсолютный путь к папке загрузок',
2772
+ parameters: [],
2773
+ return_type: 'string',
2774
+ example: `$upload_path = cmsConfig::getInstance()->getUploadsPath();`,
2775
+ },
2776
+ {
2777
+ name: 'getCachePath',
2778
+ signature: 'getCachePath(): string',
2779
+ description: 'Возвращает абсолютный путь к папке кэша',
2780
+ parameters: [],
2781
+ return_type: 'string',
2782
+ example: `$cache_path = cmsConfig::getInstance()->getCachePath();`,
2783
+ },
2784
+ ],
2785
+ },
2786
+ ];
2787
+ const curatedComponentsByClass = new Map(curatedComponents.map(component => [component.class, component]));
2788
+ const sourceComponentClasses = new Set(components_source_js_1.sourceComponents.map(component => component.class));
2789
+ exports.components = [
2790
+ ...components_source_js_1.sourceComponents.map(source => {
2791
+ const curated = curatedComponentsByClass.get(source.class);
2792
+ const curatedMethods = new Map(curated?.methods.map(method => [method.name, method]) ?? []);
2793
+ return {
2794
+ name: source.name,
2795
+ class: source.class,
2796
+ description: curated?.description || source.description || `Класс ${source.class} InstantCMS`,
2797
+ access: curated?.access || `Используйте ${source.class} согласно API InstantCMS`,
2798
+ source: {
2799
+ repository: 'https://github.com/instantsoft/icms2',
2800
+ file: source.file,
2801
+ extends: source.extends,
2802
+ },
2803
+ methods: source.methods.map(method => {
2804
+ const documentation = curatedMethods.get(method.name);
2805
+ return {
2806
+ ...method,
2807
+ description: documentation?.description || method.description,
2808
+ parameters: method.parameters.map(parameter => {
2809
+ const documented = documentation?.parameters.find(item => item.name === parameter.name);
2810
+ return documented ? { ...parameter, ...documented } : parameter;
2811
+ }),
2812
+ example: documentation?.example || '',
2813
+ };
2814
+ }),
2815
+ };
2816
+ }),
2817
+ ...curatedComponents.filter(component => !sourceComponentClasses.has(component.class)),
2818
+ ].sort((left, right) => left.name.localeCompare(right.name));