1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* Copyright (C) 2009-2010 Laurent Destailleur <[email protected]> |
4
|
|
|
* Copyright (C) 2024 MDW <[email protected]> |
5
|
|
|
* Copyright (C) 2024 Rafael San José <[email protected]> |
6
|
|
|
* |
7
|
|
|
* This program is free software; you can redistribute it and/or modify |
8
|
|
|
* it under the terms of the GNU General Public License as published by |
9
|
|
|
* the Free Software Foundation; either version 3 of the License, or |
10
|
|
|
* (at your option) any later version. |
11
|
|
|
* |
12
|
|
|
* This program is distributed in the hope that it will be useful, |
13
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
* GNU General Public License for more details. |
16
|
|
|
* |
17
|
|
|
* You should have received a copy of the GNU General Public License |
18
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
19
|
|
|
* or see https://www.gnu.org/ |
20
|
|
|
*/ |
21
|
|
|
|
22
|
|
|
use Dolibarr\Lib\ViewMain; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* \file htdocs/core/lib/modulebuilder.lib.php |
26
|
|
|
* \brief Set of function for modulebuilder management |
27
|
|
|
*/ |
28
|
|
|
|
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Regenerate files .class.php |
32
|
|
|
* |
33
|
|
|
* @param string $destdir Directory |
34
|
|
|
* @param string $module Module name |
35
|
|
|
* @param string $objectname Name of object |
36
|
|
|
* @param string $newmask New mask |
37
|
|
|
* @param string $readdir Directory source (use $destdir when not defined) |
38
|
|
|
* @param array{}|array{name:string,key:string,type:string,label:string,picot?:string,enabled:int<0,1>,notnull:int<0,1>,position:int,visible:int,noteditable?:int<0,1>,alwayseditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int<0,1>,css?:string,cssview?:string,csslist?:string,help?:string,showoncombobox?:int<0,1>,disabled?:int<0,1>,autofocusoncreate?:int<0,1>,arrayofkeyval?:array<string,string>,validate?:int<0,1>,comment?:string} $addfieldentry Array of 1 field entry to add |
|
|
|
|
39
|
|
|
* @param string $delfieldentry Id of field to remove |
40
|
|
|
* @return int<-7,-1>|CommonObject Return integer <=0 if KO, Object if OK |
41
|
|
|
* @see rebuildObjectSql() |
42
|
|
|
*/ |
43
|
|
|
function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = '', $addfieldentry = array(), $delfieldentry = '') |
44
|
|
|
{ |
45
|
|
|
global $db, $langs; |
46
|
|
|
|
47
|
|
|
if (empty($objectname)) { |
48
|
|
|
return -6; |
49
|
|
|
} |
50
|
|
|
if (empty($readdir)) { |
51
|
|
|
$readdir = $destdir; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { |
55
|
|
|
dol_print_error(null, 'Bad parameter addfieldentry with a property arrayofkeyval defined but that is not an array.'); |
56
|
|
|
return -7; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
$error = 0; |
60
|
|
|
|
61
|
|
|
// Check parameters |
62
|
|
|
if (is_array($addfieldentry) && count($addfieldentry) > 0) { |
63
|
|
|
if (empty($addfieldentry['name'])) { |
64
|
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Name")), null, 'errors'); |
65
|
|
|
return -2; |
66
|
|
|
} |
67
|
|
|
if (empty($addfieldentry['label'])) { |
68
|
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Label")), null, 'errors'); |
69
|
|
|
return -2; |
70
|
|
|
} |
71
|
|
|
if ( |
72
|
|
|
!preg_match('/^(integer|price|sellist|varchar|double|text|html|duration)/', $addfieldentry['type']) |
73
|
|
|
&& !preg_match('/^(boolean|smallint|real|date|datetime|timestamp|phone|mail|url|ip|password)$/', $addfieldentry['type']) |
74
|
|
|
) { |
75
|
|
|
setEventMessages($langs->trans('BadValueForType', $addfieldentry['type']), null, 'errors'); |
76
|
|
|
return -2; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$pathoffiletoeditsrc = $readdir . '/class/' . strtolower($objectname) . '.class.php'; |
81
|
|
|
$pathoffiletoedittarget = $destdir . '/class/' . strtolower($objectname) . '.class.php' . ($readdir != $destdir ? '.new' : ''); |
82
|
|
|
if (!dol_is_file($pathoffiletoeditsrc)) { |
83
|
|
|
$langs->load("errors"); |
84
|
|
|
setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors'); |
85
|
|
|
return -3; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
//$pathoffiletoedittmp=$destdir.'/class/'.strtolower($objectname).'.class.php.tmp'; |
89
|
|
|
//dol_delete_file($pathoffiletoedittmp, 0, 1, 1); |
90
|
|
|
|
91
|
|
|
try { |
92
|
|
|
include_once $pathoffiletoeditsrc; |
93
|
|
|
if (class_exists($objectname)) { |
94
|
|
|
$object = new $objectname($db); |
95
|
|
|
} else { |
96
|
|
|
return -4; |
97
|
|
|
} |
98
|
|
|
'@phan-var-force CommonObject $object'; |
99
|
|
|
|
100
|
|
|
// Backup old file |
101
|
|
|
dol_copy($pathoffiletoedittarget, $pathoffiletoedittarget . '.back', $newmask, 1); |
102
|
|
|
|
103
|
|
|
// Edit class files |
104
|
|
|
$contentclass = file_get_contents(dol_osencode($pathoffiletoeditsrc)); |
105
|
|
|
|
106
|
|
|
// Update ->fields (to add or remove entries defined into $addfieldentry) |
107
|
|
|
if (count($object->fields)) { |
108
|
|
|
if (is_array($addfieldentry) && count($addfieldentry)) { |
109
|
|
|
$name = $addfieldentry['name']; |
110
|
|
|
unset($addfieldentry['name']); |
111
|
|
|
|
112
|
|
|
$object->fields[$name] = $addfieldentry; |
113
|
|
|
} |
114
|
|
|
if (!empty($delfieldentry)) { |
115
|
|
|
$name = $delfieldentry; |
116
|
|
|
unset($object->fields[$name]); |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
dol_sort_array($object->fields, 'position'); |
121
|
|
|
|
122
|
|
|
$i = 0; |
123
|
|
|
$texttoinsert = '// BEGIN MODULEBUILDER PROPERTIES' . "\n"; |
124
|
|
|
$texttoinsert .= "\t" . '/**' . "\n"; |
125
|
|
|
$texttoinsert .= "\t" . ' * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.' . "\n"; |
126
|
|
|
$texttoinsert .= "\t" . ' */' . "\n"; |
127
|
|
|
$texttoinsert .= "\t" . 'public $fields=array(' . "\n"; |
128
|
|
|
|
129
|
|
|
if (count($object->fields)) { |
130
|
|
|
foreach ($object->fields as $key => $val) { |
131
|
|
|
$i++; |
132
|
|
|
$texttoinsert .= "\t\t" . '"' . $key . '" => array('; |
133
|
|
|
$texttoinsert .= '"type"=>"' . dol_escape_php($val['type']) . '",'; |
134
|
|
|
$texttoinsert .= ' "label"=>"' . dol_escape_php($val['label']) . '",'; |
135
|
|
|
if (!empty($val['picto'])) { |
136
|
|
|
$texttoinsert .= ' "picto"=>"' . dol_escape_php($val['picto']) . '",'; |
137
|
|
|
} |
138
|
|
|
$texttoinsert .= ' "enabled"=>"' . ($val['enabled'] !== '' ? dol_escape_php($val['enabled']) : 1) . '",'; |
139
|
|
|
$texttoinsert .= " 'position'=>" . ($val['position'] !== '' ? (int)$val['position'] : 50) . ","; |
140
|
|
|
$texttoinsert .= " 'notnull'=>" . (empty($val['notnull']) ? 0 : (int)$val['notnull']) . ","; |
141
|
|
|
$texttoinsert .= ' "visible"=>"' . ($val['visible'] !== '' ? dol_escape_js($val['visible']) : -1) . '",'; |
142
|
|
|
if (!empty($val['noteditable'])) { |
143
|
|
|
$texttoinsert .= ' "noteditable"=>"' . dol_escape_php($val['noteditable']) . '",'; |
144
|
|
|
} |
145
|
|
|
if (!empty($val['alwayseditable'])) { |
146
|
|
|
$texttoinsert .= ' "alwayseditable"=>"' . dol_escape_php($val['alwayseditable']) . '",'; |
147
|
|
|
} |
148
|
|
|
if (array_key_exists('default', $val) && (!empty($val['default']) || $val['default'] === '0')) { |
149
|
|
|
$texttoinsert .= ' "default"=>"' . dol_escape_php($val['default']) . '",'; |
150
|
|
|
} |
151
|
|
|
if (!empty($val['index'])) { |
152
|
|
|
$texttoinsert .= ' "index"=>"' . (int)$val['index'] . '",'; |
153
|
|
|
} |
154
|
|
|
if (!empty($val['foreignkey'])) { |
155
|
|
|
$texttoinsert .= ' "foreignkey"=>"' . (int)$val['foreignkey'] . '",'; |
156
|
|
|
} |
157
|
|
|
if (!empty($val['searchall'])) { |
158
|
|
|
$texttoinsert .= ' "searchall"=>"' . (int)$val['searchall'] . '",'; |
159
|
|
|
} |
160
|
|
|
if (!empty($val['isameasure'])) { |
161
|
|
|
$texttoinsert .= ' "isameasure"=>"' . (int)$val['isameasure'] . '",'; |
162
|
|
|
} |
163
|
|
|
if (!empty($val['css'])) { |
164
|
|
|
$texttoinsert .= ' "css"=>"' . dol_escape_php($val['css']) . '",'; |
165
|
|
|
} |
166
|
|
|
if (!empty($val['cssview'])) { |
167
|
|
|
$texttoinsert .= ' "cssview"=>"' . dol_escape_php($val['cssview']) . '",'; |
168
|
|
|
} |
169
|
|
|
if (!empty($val['csslist'])) { |
170
|
|
|
$texttoinsert .= ' "csslist"=>"' . dol_escape_php($val['csslist']) . '",'; |
171
|
|
|
} |
172
|
|
|
if (!empty($val['help'])) { |
173
|
|
|
$texttoinsert .= ' "help"=>"' . dol_escape_php($val['help']) . '",'; |
174
|
|
|
} |
175
|
|
|
if (!empty($val['showoncombobox'])) { |
176
|
|
|
$texttoinsert .= ' "showoncombobox"=>"' . (int)$val['showoncombobox'] . '",'; |
177
|
|
|
} |
178
|
|
|
if (!empty($val['disabled'])) { |
179
|
|
|
$texttoinsert .= ' "disabled"=>"' . (int)$val['disabled'] . '",'; |
180
|
|
|
} |
181
|
|
|
if (!empty($val['autofocusoncreate'])) { |
182
|
|
|
$texttoinsert .= ' "autofocusoncreate"=>"' . (int)$val['autofocusoncreate'] . '",'; |
183
|
|
|
} |
184
|
|
|
if (!empty($val['arrayofkeyval'])) { |
185
|
|
|
$texttoinsert .= ' "arrayofkeyval"=>array('; |
186
|
|
|
$i = 0; |
187
|
|
|
foreach ($val['arrayofkeyval'] as $key2 => $val2) { |
188
|
|
|
if ($i) { |
189
|
|
|
$texttoinsert .= ", "; |
190
|
|
|
} |
191
|
|
|
$texttoinsert .= '"' . dol_escape_php($key2) . '" => "' . dol_escape_php($val2) . '"'; |
192
|
|
|
$i++; |
193
|
|
|
} |
194
|
|
|
$texttoinsert .= '),'; |
195
|
|
|
} |
196
|
|
|
if (!empty($val['validate'])) { |
197
|
|
|
$texttoinsert .= ' "validate"=>"' . (int)$val['validate'] . '",'; |
198
|
|
|
} |
199
|
|
|
if (!empty($val['comment'])) { |
200
|
|
|
$texttoinsert .= ' "comment"=>"' . dol_escape_php($val['comment']) . '"'; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
$texttoinsert .= "),\n"; |
204
|
|
|
//print $texttoinsert; |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
$texttoinsert .= "\t" . ');' . "\n"; |
209
|
|
|
//print ($texttoinsert);exit; |
210
|
|
|
|
211
|
|
|
if (count($object->fields)) { |
212
|
|
|
//$typetotypephp=array('integer'=>'integer', 'duration'=>'integer', 'varchar'=>'string'); |
213
|
|
|
|
214
|
|
|
foreach ($object->fields as $key => $val) { |
215
|
|
|
$i++; |
216
|
|
|
//$typephp=$typetotypephp[$val['type']]; |
217
|
|
|
$texttoinsert .= "\t" . 'public $' . $key . ";"; |
218
|
|
|
//if ($key == 'rowid') $texttoinsert.= ' AUTO_INCREMENT PRIMARY KEY'; |
219
|
|
|
//if ($key == 'entity') $texttoinsert.= ' DEFAULT 1'; |
220
|
|
|
//$texttoinsert.= ($val['notnull']?' NOT NULL':''); |
221
|
|
|
//if ($i < count($object->fields)) $texttoinsert.=";"; |
222
|
|
|
$texttoinsert .= "\n"; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
$texttoinsert .= "\t" . '// END MODULEBUILDER PROPERTIES'; |
227
|
|
|
|
228
|
|
|
//print($texttoinsert); |
229
|
|
|
|
230
|
|
|
$contentclass = preg_replace('/\/\/ BEGIN MODULEBUILDER PROPERTIES.*END MODULEBUILDER PROPERTIES/ims', $texttoinsert, $contentclass); |
231
|
|
|
//print $contentclass; |
232
|
|
|
|
233
|
|
|
dol_mkdir(dirname($pathoffiletoedittarget)); |
234
|
|
|
|
235
|
|
|
//file_put_contents($pathoffiletoedittmp, $contentclass); |
236
|
|
|
$result = file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); |
237
|
|
|
|
238
|
|
|
if ($result) { |
239
|
|
|
dolChmod($pathoffiletoedittarget, $newmask); |
240
|
|
|
} else { |
241
|
|
|
$error++; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
return $error ? -1 : $object; |
|
|
|
|
245
|
|
|
} catch (Exception $e) { |
246
|
|
|
print $e->getMessage(); |
247
|
|
|
return -5; |
248
|
|
|
} |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Save data into a memory area shared by all users, all sessions on server |
253
|
|
|
* |
254
|
|
|
* @param string $destdir Directory |
255
|
|
|
* @param string $module Module name |
256
|
|
|
* @param string $objectname Name of object |
257
|
|
|
* @param string $newmask New mask |
258
|
|
|
* @param string $readdir Directory source (use $destdir when not defined) |
259
|
|
|
* @param Object $object If object was already loaded/known, it is pass to avoid another include and new. |
260
|
|
|
* @param string $moduletype 'external' or 'internal' |
261
|
|
|
* @return int Return integer <=0 if KO, >0 if OK |
262
|
|
|
* @see rebuildObjectClass() |
263
|
|
|
*/ |
264
|
|
|
function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = '', $object = null, $moduletype = 'external') |
265
|
|
|
{ |
266
|
|
|
global $db, $langs; |
267
|
|
|
|
268
|
|
|
$error = 0; |
269
|
|
|
|
270
|
|
|
if (empty($objectname)) { |
271
|
|
|
return -1; |
272
|
|
|
} |
273
|
|
|
if (empty($readdir)) { |
274
|
|
|
$readdir = $destdir; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
$pathoffiletoclasssrc = $readdir . '/class/' . strtolower($objectname) . '.class.php'; |
278
|
|
|
|
279
|
|
|
// Edit .sql file |
280
|
|
|
if ($moduletype == 'internal') { |
281
|
|
|
$pathoffiletoeditsrc = '/../install/mysql/tables/llx_' . strtolower($module) . '_' . strtolower($objectname) . '.sql'; |
282
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
283
|
|
|
$pathoffiletoeditsrc = '/../install/mysql/tables/llx_' . strtolower($module) . '_' . strtolower($objectname) . '-' . strtolower($module) . '.sql'; |
284
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
285
|
|
|
$pathoffiletoeditsrc = '/../install/mysql/tables/llx_' . strtolower($module) . '-' . strtolower($module) . '.sql'; |
286
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
287
|
|
|
$pathoffiletoeditsrc = '/../install/mysql/tables/llx_' . strtolower($module) . '.sql'; |
288
|
|
|
} |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
} else { |
292
|
|
|
$pathoffiletoeditsrc = '/sql/llx_' . strtolower($module) . '_' . strtolower($objectname) . '.sql'; |
293
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
294
|
|
|
$pathoffiletoeditsrc = '/sql/llx_' . strtolower($module) . '_' . strtolower($objectname) . '-' . strtolower($module) . '.sql'; |
295
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
296
|
|
|
$pathoffiletoeditsrc = '/sql/llx_' . strtolower($module) . '-' . strtolower($module) . '.sql'; |
297
|
|
|
if (!dol_is_file($readdir . $pathoffiletoeditsrc)) { |
298
|
|
|
$pathoffiletoeditsrc = '/sql/llx_' . strtolower($module) . '.sql'; |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
// Complete path to be full path |
305
|
|
|
$pathoffiletoedittarget = $destdir . $pathoffiletoeditsrc . ($readdir != $destdir ? '.new' : ''); |
306
|
|
|
$pathoffiletoeditsrc = $readdir . $pathoffiletoeditsrc; |
307
|
|
|
|
308
|
|
|
if (!dol_is_file($pathoffiletoeditsrc)) { |
309
|
|
|
$langs->load("errors"); |
310
|
|
|
setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors'); |
311
|
|
|
return -1; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
// Load object from myobject.class.php |
315
|
|
|
try { |
316
|
|
|
if (!is_object($object)) { |
317
|
|
|
include_once $pathoffiletoclasssrc; |
318
|
|
|
if (class_exists($objectname)) { |
319
|
|
|
$object = new $objectname($db); |
320
|
|
|
} else { |
321
|
|
|
return -1; |
322
|
|
|
} |
323
|
|
|
} |
324
|
|
|
} catch (Exception $e) { |
325
|
|
|
print $e->getMessage(); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
// Backup old file |
329
|
|
|
dol_copy($pathoffiletoedittarget, $pathoffiletoedittarget . '.back', $newmask, 1); |
330
|
|
|
|
331
|
|
|
$contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc)); |
332
|
|
|
|
333
|
|
|
$i = 0; |
334
|
|
|
$texttoinsert = '-- BEGIN MODULEBUILDER FIELDS' . "\n"; |
335
|
|
|
if (count($object->fields)) { |
336
|
|
|
foreach ($object->fields as $key => $val) { |
337
|
|
|
$i++; |
338
|
|
|
|
339
|
|
|
$type = $val['type']; |
340
|
|
|
$type = preg_replace('/:.*$/', '', $type); // For case type = 'integer:Societe:societe/class/societe.class.php' |
341
|
|
|
|
342
|
|
|
if ($type == 'html') { |
343
|
|
|
$type = 'text'; // html modulebuilder type is a text type in database |
344
|
|
|
} elseif ($type == 'price') { |
345
|
|
|
$type = 'double'; // html modulebuilder type is a text type in database |
346
|
|
|
} elseif (in_array($type, array('link', 'sellist', 'duration'))) { |
347
|
|
|
$type = 'integer'; |
348
|
|
|
} elseif ($type == 'mail') { |
349
|
|
|
$type = 'varchar(128)'; |
350
|
|
|
} elseif ($type == 'phone') { |
351
|
|
|
$type = 'varchar(20)'; |
352
|
|
|
} elseif ($type == 'ip') { |
353
|
|
|
$type = 'varchar(32)'; |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
$texttoinsert .= "\t" . $key . " " . $type; |
357
|
|
|
if ($key == 'rowid') { |
358
|
|
|
$texttoinsert .= ' AUTO_INCREMENT PRIMARY KEY'; |
359
|
|
|
} elseif ($type == 'timestamp') { |
360
|
|
|
$texttoinsert .= ' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'; |
361
|
|
|
} |
362
|
|
|
if ($key == 'entity') { |
363
|
|
|
$texttoinsert .= ' DEFAULT 1'; |
364
|
|
|
} else { |
365
|
|
|
if (!empty($val['default'])) { |
366
|
|
|
if (preg_match('/^null$/i', $val['default'])) { |
367
|
|
|
$texttoinsert .= " DEFAULT NULL"; |
368
|
|
|
} elseif (preg_match('/varchar/', $type)) { |
369
|
|
|
$texttoinsert .= " DEFAULT '" . $db->escape($val['default']) . "'"; |
370
|
|
|
} else { |
371
|
|
|
$texttoinsert .= (($val['default'] > 0) ? ' DEFAULT ' . $val['default'] : ''); |
372
|
|
|
} |
373
|
|
|
} |
374
|
|
|
} |
375
|
|
|
$texttoinsert .= ((!empty($val['notnull']) && $val['notnull'] > 0) ? ' NOT NULL' : ''); |
376
|
|
|
if ($i < count($object->fields)) { |
377
|
|
|
$texttoinsert .= ", "; |
378
|
|
|
} |
379
|
|
|
$texttoinsert .= "\n"; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
$texttoinsert .= "\t" . '-- END MODULEBUILDER FIELDS'; |
383
|
|
|
|
384
|
|
|
$contentsql = preg_replace('/-- BEGIN MODULEBUILDER FIELDS.*END MODULEBUILDER FIELDS/ims', $texttoinsert, $contentsql); |
385
|
|
|
|
386
|
|
|
$result = file_put_contents($pathoffiletoedittarget, $contentsql); |
387
|
|
|
if ($result) { |
388
|
|
|
dolChmod($pathoffiletoedittarget, $newmask); |
389
|
|
|
} else { |
390
|
|
|
$error++; |
391
|
|
|
setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
// Edit .key.sql file |
395
|
|
|
$pathoffiletoeditsrc = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoeditsrc); |
396
|
|
|
$pathoffiletoedittarget = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoedittarget); |
397
|
|
|
$pathoffiletoedittarget = preg_replace('/\.sql.new$/', '.key.sql.new', $pathoffiletoedittarget); |
398
|
|
|
|
399
|
|
|
$contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc)); |
400
|
|
|
|
401
|
|
|
$i = 0; |
402
|
|
|
$texttoinsert = '-- BEGIN MODULEBUILDER INDEXES' . "\n"; |
403
|
|
|
if (count($object->fields)) { |
404
|
|
|
foreach ($object->fields as $key => $val) { |
405
|
|
|
$i++; |
406
|
|
|
if (!empty($val['index'])) { |
407
|
|
|
$texttoinsert .= "ALTER TABLE llx_" . strtolower($module) . '_' . strtolower($objectname) . " ADD INDEX idx_" . strtolower($module) . '_' . strtolower($objectname) . "_" . $key . " (" . $key . ");"; |
408
|
|
|
$texttoinsert .= "\n"; |
409
|
|
|
} |
410
|
|
|
if (!empty($val['foreignkey'])) { |
411
|
|
|
$tmp = explode('.', $val['foreignkey']); |
412
|
|
|
if (!empty($tmp[0]) && !empty($tmp[1])) { |
413
|
|
|
$texttoinsert .= "ALTER TABLE llx_" . strtolower($module) . '_' . strtolower($objectname) . " ADD CONSTRAINT llx_" . strtolower($module) . '_' . strtolower($objectname) . "_" . $key . " FOREIGN KEY (" . $key . ") REFERENCES llx_" . preg_replace('/^llx_/', '', $tmp[0]) . "(" . $tmp[1] . ");"; |
414
|
|
|
$texttoinsert .= "\n"; |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
} |
419
|
|
|
$texttoinsert .= '-- END MODULEBUILDER INDEXES'; |
420
|
|
|
|
421
|
|
|
$contentsql = preg_replace('/-- BEGIN MODULEBUILDER INDEXES.*END MODULEBUILDER INDEXES/ims', $texttoinsert, $contentsql); |
422
|
|
|
|
423
|
|
|
dol_mkdir(dirname($pathoffiletoedittarget)); |
424
|
|
|
|
425
|
|
|
$result2 = file_put_contents($pathoffiletoedittarget, $contentsql); |
426
|
|
|
if ($result2) { |
427
|
|
|
dolChmod($pathoffiletoedittarget, $newmask); |
428
|
|
|
} else { |
429
|
|
|
$error++; |
430
|
|
|
setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
return $error ? -1 : 1; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Get list of existing objects from a directory |
438
|
|
|
* |
439
|
|
|
* @param string $destdir Directory |
440
|
|
|
* @return array|int Return integer <=0 if KO, array if OK |
441
|
|
|
*/ |
442
|
|
|
function dolGetListOfObjectClasses($destdir) |
443
|
|
|
{ |
444
|
|
|
$objects = array(); |
445
|
|
|
$listofobject = dol_dir_list($destdir . '/class', 'files', 0, '\.class\.php$'); |
446
|
|
|
foreach ($listofobject as $fileobj) { |
447
|
|
|
if (preg_match('/^api_/', $fileobj['name'])) { |
448
|
|
|
continue; |
449
|
|
|
} |
450
|
|
|
if (preg_match('/^actions_/', $fileobj['name'])) { |
451
|
|
|
continue; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
$tmpcontent = file_get_contents($fileobj['fullname']); |
455
|
|
|
$reg = array(); |
456
|
|
|
if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { |
457
|
|
|
$objectnameloop = $reg[1]; |
458
|
|
|
$objects[$fileobj['fullname']] = $objectnameloop; |
459
|
|
|
} |
460
|
|
|
} |
461
|
|
|
if (count($objects) > 0) { |
462
|
|
|
return $objects; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
return -1; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* Function to check if comment BEGIN and END exists in modMyModule class |
470
|
|
|
* |
471
|
|
|
* @param string $file Filename or path |
472
|
|
|
* @param int $number 0 = For Menus, 1 = For permissions, 2 = For Dictionaries |
473
|
|
|
* @return int 1 if OK , -1 if KO |
474
|
|
|
*/ |
475
|
|
|
function checkExistComment($file, $number) |
476
|
|
|
{ |
477
|
|
|
if (!file_exists($file)) { |
478
|
|
|
return -1; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
$content = file_get_contents($file); |
482
|
|
|
if ($number === 0) { |
483
|
|
|
$ret = 0; |
484
|
|
|
if ( |
485
|
|
|
strpos($content, '/* BEGIN MODULEBUILDER TOPMENU MYOBJECT */') !== false |
486
|
|
|
|| strpos($content, '/* BEGIN MODULEBUILDER TOPMENU */') !== false |
487
|
|
|
) { |
488
|
|
|
$ret++; |
489
|
|
|
} |
490
|
|
|
if ( |
491
|
|
|
strpos($content, '/* END MODULEBUILDER TOPMENU MYOBJECT */') !== false |
492
|
|
|
|| strpos($content, '/* END MODULEBUILDER TOPMENU */') !== false |
493
|
|
|
) { |
494
|
|
|
$ret++; |
495
|
|
|
} |
496
|
|
|
if (strpos($content, '/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */') !== false) { |
497
|
|
|
$ret++; |
498
|
|
|
} |
499
|
|
|
if (strpos($content, '/* END MODULEBUILDER LEFTMENU MYOBJECT */') !== false) { |
500
|
|
|
$ret++; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
if ($ret == 4) { |
504
|
|
|
return 1; |
505
|
|
|
} |
506
|
|
|
} elseif ($number === 1) { |
507
|
|
|
if (strpos($content, '/* BEGIN MODULEBUILDER PERMISSIONS */') !== false && strpos($content, '/* END MODULEBUILDER PERMISSIONS */') !== false) { |
508
|
|
|
return 1; |
509
|
|
|
} |
510
|
|
|
} elseif ($number == 2) { |
511
|
|
|
if (strpos($content, '/* BEGIN MODULEBUILDER DICTIONARIES */') !== false && strpos($content, '/* END MODULEBUILDER DICTIONARIES */') !== false) { |
512
|
|
|
return 1; |
513
|
|
|
} |
514
|
|
|
} |
515
|
|
|
return -1; |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
/** |
519
|
|
|
* Delete all permissions |
520
|
|
|
* |
521
|
|
|
* @param string $file file with path |
522
|
|
|
* @return void |
523
|
|
|
*/ |
524
|
|
|
function deletePerms($file) |
525
|
|
|
{ |
526
|
|
|
$start = "/* BEGIN MODULEBUILDER PERMISSIONS */"; |
527
|
|
|
$end = "/* END MODULEBUILDER PERMISSIONS */"; |
528
|
|
|
$i = 1; |
529
|
|
|
$array = array(); |
530
|
|
|
$lines = file($file); |
531
|
|
|
// Search for start and end lines |
532
|
|
|
foreach ($lines as $i => $line) { |
533
|
|
|
if (strpos($line, $start) !== false) { |
534
|
|
|
$start_line = $i + 1; |
535
|
|
|
|
536
|
|
|
// Copy lines until the end on array |
537
|
|
|
while (($line = $lines[++$i]) !== false) { |
538
|
|
|
if (strpos($line, $end) !== false) { |
539
|
|
|
$end_line = $i + 1; |
540
|
|
|
break; |
541
|
|
|
} |
542
|
|
|
$array[] = $line; |
543
|
|
|
} |
544
|
|
|
break; |
545
|
|
|
} |
546
|
|
|
} |
547
|
|
|
$allContent = implode("", $array); |
548
|
|
|
dolReplaceInFile($file, array($allContent => '')); |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
/** |
552
|
|
|
* Compare two value |
553
|
|
|
* @param int|string $a value 1 |
554
|
|
|
* @param int|string $b value 2 |
555
|
|
|
* @return int less 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. |
556
|
|
|
*/ |
557
|
|
|
function compareFirstValue($a, $b) |
558
|
|
|
{ |
559
|
|
|
return strcmp($a[0], $b[0]); |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Rewriting all permissions after any actions |
564
|
|
|
* @param string $file filename or path |
565
|
|
|
* @param array<int,string[]> $permissions permissions existing in file |
566
|
|
|
* @param int|null $key key for permission needed |
567
|
|
|
* @param array{0:string,1:string}|null $right $right to update or add |
568
|
|
|
* @param string|null $objectname name of object |
569
|
|
|
* @param string|null $module name of module |
570
|
|
|
* @param int<-2,2> $action 0 for delete, 1 for add, 2 for update, -1 when delete object completely, -2 for generate rights after add |
571
|
|
|
* @return int<-1,1> 1 if OK,-1 if KO |
572
|
|
|
*/ |
573
|
|
|
function reWriteAllPermissions($file, $permissions, $key, $right, $objectname, $module, $action) |
574
|
|
|
{ |
575
|
|
|
$error = 0; |
576
|
|
|
$rights = array(); |
577
|
|
|
if ($action == 0) { |
578
|
|
|
// delete right from permissions array |
579
|
|
|
array_splice($permissions, array_search($permissions[$key], $permissions), 1); |
580
|
|
|
} elseif ($action == 1) { |
581
|
|
|
array_push($permissions, $right); |
582
|
|
|
} elseif ($action == 2 && !empty($right)) { |
583
|
|
|
// update right from permissions array |
584
|
|
|
array_splice($permissions, array_search($permissions[$key], $permissions), 1, $right); |
585
|
|
|
} elseif ($action == -1 && !empty($objectname)) { |
586
|
|
|
// when delete object |
587
|
|
|
$key = null; |
588
|
|
|
$right = null; |
589
|
|
|
foreach ($permissions as $perms) { |
590
|
|
|
if ($perms[4] === strtolower($objectname)) { |
591
|
|
|
array_splice($permissions, array_search($perms, $permissions), 1); |
592
|
|
|
} |
593
|
|
|
} |
594
|
|
|
} elseif ($action == -2 && !empty($objectname) && !empty($module)) { |
595
|
|
|
$key = null; |
596
|
|
|
$right = null; |
597
|
|
|
$objectOfRights = array(); |
598
|
|
|
//check if object already declared in rights file |
599
|
|
|
foreach ($permissions as $right) { |
|
|
|
|
600
|
|
|
$objectOfRights[] = $right[4]; |
601
|
|
|
} |
602
|
|
|
if (in_array(strtolower($objectname), $objectOfRights)) { |
603
|
|
|
$error++; |
604
|
|
|
} else { |
605
|
|
|
$permsToadd = array(); |
606
|
|
|
$perms = array( |
607
|
|
|
'read' => 'Read ' . $objectname . ' object of ' . ucfirst($module), |
608
|
|
|
'write' => 'Create/Update ' . $objectname . ' object of ' . ucfirst($module), |
609
|
|
|
'delete' => 'Delete ' . $objectname . ' object of ' . ucfirst($module) |
610
|
|
|
); |
611
|
|
|
$i = 0; |
612
|
|
|
foreach ($perms as $index => $value) { |
613
|
|
|
$permsToadd[$i][0] = ''; |
614
|
|
|
$permsToadd[$i][1] = $value; |
615
|
|
|
$permsToadd[$i][4] = strtolower($objectname); |
616
|
|
|
$permsToadd[$i][5] = $index; |
617
|
|
|
array_push($permissions, $permsToadd[$i]); |
618
|
|
|
$i++; |
619
|
|
|
} |
620
|
|
|
} |
621
|
|
|
} else { |
622
|
|
|
$error++; |
623
|
|
|
} |
624
|
|
|
'@phan-var-force array<int,string[]> $permissions'; |
625
|
|
|
if (!$error) { |
626
|
|
|
// prepare permissions array |
627
|
|
|
$count_perms = count($permissions); |
628
|
|
|
foreach (array_keys($permissions) as $i) { |
629
|
|
|
$permissions[$i][0] = "\$this->rights[\$r][0] = \$this->numero . sprintf('%02d', \$r + 1)"; |
630
|
|
|
$permissions[$i][1] = "\$this->rights[\$r][1] = '" . $permissions[$i][1] . "'"; |
631
|
|
|
$permissions[$i][4] = "\$this->rights[\$r][4] = '" . $permissions[$i][4] . "'"; |
632
|
|
|
$permissions[$i][5] = "\$this->rights[\$r][5] = '" . $permissions[$i][5] . "';\n\t\t"; |
633
|
|
|
} |
634
|
|
|
// for group permissions by object |
635
|
|
|
$perms_grouped = array(); |
636
|
|
|
foreach ($permissions as $perms) { |
637
|
|
|
$object = $perms[4]; |
638
|
|
|
if (!isset($perms_grouped[$object])) { |
639
|
|
|
$perms_grouped[$object] = []; |
640
|
|
|
} |
641
|
|
|
$perms_grouped[$object][] = $perms; |
642
|
|
|
} |
643
|
|
|
//$perms_grouped = array_values($perms_grouped); |
644
|
|
|
$permissions = $perms_grouped; |
645
|
|
|
|
646
|
|
|
|
647
|
|
|
// parcourir les objects |
648
|
|
|
$o = 0; |
649
|
|
|
foreach ($permissions as &$object) { |
650
|
|
|
// récupérer la permission de l'objet |
651
|
|
|
$p = 1; |
652
|
|
|
foreach ($object as &$obj) { |
653
|
|
|
if (str_contains($obj[5], 'read')) { |
654
|
|
|
$obj[0] = "\$this->rights[\$r][0] = \$this->numero . sprintf('%02d', (" . $o . " * 10) + 0 + 1)"; |
655
|
|
|
} elseif (str_contains($obj[5], 'write')) { |
656
|
|
|
$obj[0] = "\$this->rights[\$r][0] = \$this->numero . sprintf('%02d', (" . $o . " * 10) + 1 + 1)"; |
657
|
|
|
} elseif (str_contains($obj[5], 'delete')) { |
658
|
|
|
$obj[0] = "\$this->rights[\$r][0] = \$this->numero . sprintf('%02d', (" . $o . " * 10) + 2 + 1)"; |
659
|
|
|
} else { |
660
|
|
|
$obj[0] = "\$this->rights[\$r][0] = \$this->numero . sprintf('%02d', (" . $o . " * 10) + " . $p . " + 1)"; |
661
|
|
|
$p++; |
662
|
|
|
} |
663
|
|
|
} |
664
|
|
|
usort($object, 'compareFirstValue'); |
665
|
|
|
$o++; |
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
//convert to string |
669
|
|
|
foreach ($permissions as $perms) { |
670
|
|
|
foreach ($perms as $per) { |
671
|
|
|
$rights[] = implode(";\n\t\t", $per); |
672
|
|
|
$rights[] = "\$r++;\n\t\t"; |
673
|
|
|
} |
674
|
|
|
} |
675
|
|
|
$rights_str = implode("", $rights); |
676
|
|
|
// delete all permissions from file |
677
|
|
|
deletePerms($file); |
678
|
|
|
// rewrite all permissions again |
679
|
|
|
dolReplaceInFile($file, array('/* BEGIN MODULEBUILDER PERMISSIONS */' => '/* BEGIN MODULEBUILDER PERMISSIONS */' . "\n\t\t" . $rights_str)); |
680
|
|
|
return 1; |
681
|
|
|
} else { |
682
|
|
|
return -1; |
683
|
|
|
} |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
/** |
687
|
|
|
* Converts a formatted properties string into an associative array. |
688
|
|
|
* |
689
|
|
|
* @param string $string The formatted properties string. |
690
|
|
|
* @return array<string,bool|int|float|string|mixed[]> The resulting associative array. |
691
|
|
|
*/ |
692
|
|
|
function parsePropertyString($string) |
693
|
|
|
{ |
694
|
|
|
$string = str_replace("'", '', $string); |
695
|
|
|
|
696
|
|
|
// Uses a regular expression to capture keys and values |
697
|
|
|
preg_match_all('/\s*([^\s=>]+)\s*=>\s*([^,]+),?/', $string, $matches, PREG_SET_ORDER); |
698
|
|
|
$propertyArray = []; |
699
|
|
|
|
700
|
|
|
foreach ($matches as $match) { |
701
|
|
|
$key = trim($match[1]); |
702
|
|
|
$value = trim($match[2]); |
703
|
|
|
|
704
|
|
|
if (strpos($value, 'array(') === 0) { |
705
|
|
|
$nestedArray = substr($value, 6); |
706
|
|
|
$nestedArray = parsePropertyString($nestedArray); |
707
|
|
|
$value = $nestedArray; |
708
|
|
|
} elseif (strpos($value, '"Id")') !== false) { |
709
|
|
|
$value = str_replace(')', '', $value); |
710
|
|
|
} else { |
711
|
|
|
if (is_numeric($value)) { |
712
|
|
|
if (strpos($value, '.') !== false) { |
713
|
|
|
$value = (float)$value; |
714
|
|
|
} else { |
715
|
|
|
$value = (int)$value; |
716
|
|
|
} |
717
|
|
|
} else { |
718
|
|
|
if ($value === 'true') { |
719
|
|
|
$value = true; |
720
|
|
|
} elseif ($value === 'false') { |
721
|
|
|
$value = false; |
722
|
|
|
} |
723
|
|
|
} |
724
|
|
|
} |
725
|
|
|
$propertyArray[$key] = $value; |
726
|
|
|
} |
727
|
|
|
|
728
|
|
|
return $propertyArray; |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
/** |
732
|
|
|
* Write all properties of the object in AsciiDoc format |
733
|
|
|
* @param string $file path of the class |
734
|
|
|
* @param string $objectname name of the objectClass |
735
|
|
|
* @param string $destfile file where write table of properties |
736
|
|
|
* @return int 1 if OK, -1 if KO |
737
|
|
|
*/ |
738
|
|
|
function writePropsInAsciiDoc($file, $objectname, $destfile) |
739
|
|
|
{ |
740
|
|
|
|
741
|
|
|
// stock all properties in array |
742
|
|
|
$attributesUnique = array('type', 'label', 'enabled', 'position', 'notnull', 'visible', 'noteditable', 'index', 'default', 'foreignkey', 'arrayofkeyval', 'alwayseditable', 'validate', 'searchall', 'comment', 'isameasure', 'css', 'cssview', 'csslist', 'help', 'showoncombobox', 'picto'); |
743
|
|
|
|
744
|
|
|
$start = "public \$fields=array("; |
745
|
|
|
$end = ");"; |
746
|
|
|
$i = 1; |
747
|
|
|
$keys = array(); |
748
|
|
|
$lines = file($file); |
749
|
|
|
// Search for start and end lines |
750
|
|
|
foreach ($lines as $i => $line) { |
751
|
|
|
if (strpos($line, $start) !== false) { |
752
|
|
|
// Copy lines until the end on array |
753
|
|
|
while (($line = $lines[++$i]) !== false) { |
754
|
|
|
if (strpos($line, $end) !== false) { |
755
|
|
|
break; |
756
|
|
|
} |
757
|
|
|
$keys[] = $line; |
758
|
|
|
} |
759
|
|
|
break; |
760
|
|
|
} |
761
|
|
|
} |
762
|
|
|
// write the begin of table with specifics options |
763
|
|
|
$table = "== DATA SPECIFICATIONS\n"; |
764
|
|
|
$table .= "=== Table of fields with properties for object *$objectname* : \n"; |
765
|
|
|
$table .= "[options='header',grid=rows,frame=topbot,width=100%,caption=Organisation]\n"; |
766
|
|
|
$table .= "|===\n"; |
767
|
|
|
$table .= "|code"; |
768
|
|
|
// write all properties in the header of the table |
769
|
|
|
foreach ($attributesUnique as $attUnique) { |
770
|
|
|
$table .= "|" . $attUnique; |
771
|
|
|
} |
772
|
|
|
$table .= "\n"; |
773
|
|
|
$valuesModif = array(); |
774
|
|
|
foreach ($keys as $string) { |
775
|
|
|
$string = trim($string, "'"); |
776
|
|
|
$string = rtrim($string, ","); |
777
|
|
|
|
778
|
|
|
$array = parsePropertyString($string); |
779
|
|
|
|
780
|
|
|
// Iterate through the array to merge all key to one array |
781
|
|
|
$code = ''; |
782
|
|
|
foreach ($array as $key => $value) { |
783
|
|
|
if (is_array($value)) { |
784
|
|
|
$code = $key; |
785
|
|
|
continue; |
786
|
|
|
} else { |
787
|
|
|
$array[$code][$key] = $value; |
788
|
|
|
unset($array[$key]); |
789
|
|
|
} |
790
|
|
|
} |
791
|
|
|
// check if is array after parsing the string |
792
|
|
|
if (!is_array($array)) { |
793
|
|
|
return -1; |
794
|
|
|
} |
795
|
|
|
$field = array_keys($array); |
796
|
|
|
if ($field[0] === '') { |
797
|
|
|
$field[0] = 'label'; |
798
|
|
|
} |
799
|
|
|
$values = array_values($array)[0]; |
800
|
|
|
|
801
|
|
|
// check each field has all properties and add it if missed |
802
|
|
|
foreach ($attributesUnique as $attUnique) { |
803
|
|
|
if ($attUnique == 'type' && $field[0] === 'label') { |
804
|
|
|
$values[$attUnique] = 'varchar(255)'; |
805
|
|
|
} |
806
|
|
|
if (!array_key_exists($attUnique, $values)) { |
807
|
|
|
$valuesModif[$attUnique] = ''; |
808
|
|
|
} else { |
809
|
|
|
$valuesModif[$attUnique] = $values[$attUnique]; |
810
|
|
|
} |
811
|
|
|
} |
812
|
|
|
$table .= "|*" . $field[0] . "*|"; |
813
|
|
|
$table .= implode("|", $valuesModif) . "\n"; |
814
|
|
|
} |
815
|
|
|
|
816
|
|
|
// end table |
817
|
|
|
$table .= "|===\n"; |
818
|
|
|
$table .= "__ end table for object $objectname\n"; |
819
|
|
|
|
820
|
|
|
//write in file @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
821
|
|
|
$writeInFile = dolReplaceInFile($destfile, array('== DATA SPECIFICATIONS' => $table)); |
822
|
|
|
if ($writeInFile < 0) { |
823
|
|
|
return -1; |
824
|
|
|
} |
825
|
|
|
return 1; |
826
|
|
|
} |
827
|
|
|
|
828
|
|
|
|
829
|
|
|
/** |
830
|
|
|
* Delete property and permissions from documentation ascii file if we delete an object |
831
|
|
|
* |
832
|
|
|
* @param string $file file or path |
833
|
|
|
* @param string $objectname name of object wants to deleted |
834
|
|
|
* @return void |
835
|
|
|
*/ |
836
|
|
|
function deletePropsAndPermsFromDoc($file, $objectname) |
837
|
|
|
{ |
838
|
|
|
if (dol_is_file($file)) { |
839
|
|
|
$start = "== Table of fields and their properties for object *" . ucfirst($objectname) . "* : "; |
840
|
|
|
$end = "__ end table for object " . ucfirst($objectname); |
841
|
|
|
|
842
|
|
|
$str = file_get_contents($file); |
843
|
|
|
|
844
|
|
|
$search = '/' . preg_quote($start, '/') . '(.*?)' . preg_quote($end, '/') . '/s'; |
845
|
|
|
$new_contents = preg_replace($search, '', $str); |
846
|
|
|
file_put_contents($file, $new_contents); |
847
|
|
|
|
848
|
|
|
//perms If Exist |
849
|
|
|
$perms = "|*" . strtolower($objectname) . "*|"; |
850
|
|
|
$search_pattern_perms = '/' . preg_quote($perms, '/') . '.*?\n/'; |
851
|
|
|
$new_contents = preg_replace($search_pattern_perms, '', $new_contents); |
852
|
|
|
file_put_contents($file, $new_contents); |
853
|
|
|
} |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
|
857
|
|
|
/** |
858
|
|
|
* Search a string and return all lines needed from file. Does not include line $start nor $end |
859
|
|
|
* |
860
|
|
|
* @param string $file file for searching |
861
|
|
|
* @param string $start start line if exist |
862
|
|
|
* @param string $end end line if exist |
863
|
|
|
* @param string $excludestart Ignore if start line is $excludestart |
864
|
|
|
* @param int $includese Include start and end line |
865
|
|
|
* @return string Return the lines between first line with $start and $end. "" if not found. |
866
|
|
|
*/ |
867
|
|
|
function getFromFile($file, $start, $end, $excludestart = '', $includese = 0) |
868
|
|
|
{ |
869
|
|
|
$keys = array(); |
870
|
|
|
|
871
|
|
|
//$lines = file(dol_osencode($file)); |
872
|
|
|
$fhandle = fopen(dol_osencode($file), 'r'); |
873
|
|
|
if ($fhandle) { |
874
|
|
|
// Search for start and end lines |
875
|
|
|
//foreach ($lines as $i => $line) { |
876
|
|
|
while ($line = fgets($fhandle)) { |
877
|
|
|
if (strpos($line, $start) !== false && (empty($excludestart) || strpos($line, $excludestart) === false)) { |
878
|
|
|
if ($includese) { |
879
|
|
|
$keys[] = $line; |
880
|
|
|
} |
881
|
|
|
// Copy lines until we reach the end |
882
|
|
|
while (($line = fgets($fhandle)) !== false) { |
883
|
|
|
if (strpos($line, $end) !== false) { |
884
|
|
|
if ($includese) { |
885
|
|
|
$keys[] = $line; |
886
|
|
|
} |
887
|
|
|
break; |
888
|
|
|
} |
889
|
|
|
$keys[] = $line; |
890
|
|
|
} |
891
|
|
|
break; |
892
|
|
|
} |
893
|
|
|
} |
894
|
|
|
} |
895
|
|
|
fclose($fhandle); |
896
|
|
|
|
897
|
|
|
$content = implode("", $keys); |
898
|
|
|
return $content; |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
/** |
902
|
|
|
* Write all permissions of each object in AsciiDoc format |
903
|
|
|
* @param string $file path of the class |
904
|
|
|
* @param string $destfile file where write table of permissions |
905
|
|
|
* @return int<-1,1> 1 if OK, -1 if KO |
906
|
|
|
*/ |
907
|
|
|
function writePermsInAsciiDoc($file, $destfile) |
908
|
|
|
{ |
909
|
|
|
global $langs; |
910
|
|
|
//search and get all permissions in string |
911
|
|
|
$start = '/* BEGIN MODULEBUILDER PERMISSIONS */'; |
912
|
|
|
$end = '/* END MODULEBUILDER PERMISSIONS */'; |
913
|
|
|
$content = getFromFile($file, $start, $end); |
914
|
|
|
if (empty($content)) { |
915
|
|
|
return -1; |
916
|
|
|
} |
917
|
|
|
//prepare table |
918
|
|
|
$string = "[options='header',grid=rows,width=60%,caption=Organisation]\n"; |
919
|
|
|
$string .= "|===\n"; |
920
|
|
|
// header for table |
921
|
|
|
$header = array($langs->trans('Objects'), $langs->trans('Permission')); |
922
|
|
|
foreach ($header as $h) { |
923
|
|
|
$string .= "|" . $h; |
924
|
|
|
} |
925
|
|
|
$string .= "\n"; |
926
|
|
|
//content table |
927
|
|
|
$array = explode(";", $content); |
928
|
|
|
$permissions = array_filter($array); |
929
|
|
|
// delete occurrences "$r++" and ID |
930
|
|
|
$permissions = str_replace('$r++', '1', $permissions); |
931
|
|
|
|
932
|
|
|
$permsN = array(); |
933
|
|
|
foreach ($permissions as $i => $element) { |
934
|
|
|
if ($element == 1) { |
935
|
|
|
unset($permissions[$i]); |
936
|
|
|
} |
937
|
|
|
if (str_contains($element, '$this->numero')) { |
938
|
|
|
unset($permissions[$i]); |
939
|
|
|
} |
940
|
|
|
if (str_contains($element, '$this->rights[$r][5]')) { |
941
|
|
|
unset($permissions[$i]); |
942
|
|
|
} |
943
|
|
|
} |
944
|
|
|
// cleaning the string on each element |
945
|
|
|
foreach ($permissions as $key => $element) { |
946
|
|
|
$element = str_replace(" '", '', $element); |
947
|
|
|
$element = trim($element, "'"); |
948
|
|
|
$permsN[] = substr($element, strpos($element, "=") + 1); |
949
|
|
|
} |
950
|
|
|
array_pop($permsN); |
951
|
|
|
|
952
|
|
|
// Group permissions by Object and add it to string |
953
|
|
|
$final_array = []; |
954
|
|
|
$index = 0; |
955
|
|
|
while ($index < count($permsN)) { |
956
|
|
|
$temp_array = [$permsN[$index], $permsN[$index + 1]]; |
957
|
|
|
$final_array[] = $temp_array; |
958
|
|
|
$index += 2; |
959
|
|
|
} |
960
|
|
|
|
961
|
|
|
$result = array(); |
962
|
|
|
foreach ($final_array as $subarray) { |
963
|
|
|
// found object |
964
|
|
|
$key = $subarray[1]; |
965
|
|
|
// add sub array to object |
966
|
|
|
$result[$key][] = $subarray; |
967
|
|
|
} |
968
|
|
|
foreach ($result as $i => $pems) { |
969
|
|
|
$string .= "|*" . $i . "*|"; |
970
|
|
|
foreach ($pems as $tab) { |
971
|
|
|
$string .= $tab[0] . " , "; |
972
|
|
|
} |
973
|
|
|
$string .= "\n"; |
974
|
|
|
} |
975
|
|
|
// end table |
976
|
|
|
$string .= "\n|===\n"; |
977
|
|
|
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
978
|
|
|
$write = dolReplaceInFile($destfile, array('__DATA_PERMISSIONS__' => $string)); |
979
|
|
|
if ($write < 0) { |
980
|
|
|
return -1; |
981
|
|
|
} |
982
|
|
|
return 1; |
983
|
|
|
} |
984
|
|
|
|
985
|
|
|
/** |
986
|
|
|
* Add Object in ModuleApi File |
987
|
|
|
* |
988
|
|
|
* @param string $srcfile Source file to use as example |
989
|
|
|
* @param string $file Path of modified file |
990
|
|
|
* @param string[] $objects Array of objects in the module |
991
|
|
|
* @param string $modulename Name of module |
992
|
|
|
* @return int<-1,1> Return 1 if OK, -1 if KO |
993
|
|
|
*/ |
994
|
|
|
function addObjectsToApiFile($srcfile, $file, $objects, $modulename) |
995
|
|
|
{ |
996
|
|
|
global $langs, $user; |
997
|
|
|
|
998
|
|
|
if (!file_exists($file)) { |
999
|
|
|
return -1; |
1000
|
|
|
} |
1001
|
|
|
|
1002
|
|
|
$now = dol_now(); |
1003
|
|
|
$content = file($file); // $content is an array |
1004
|
|
|
|
1005
|
|
|
$includeClass = "dol_include_once\(\'\/\w+\/class\/\w+\.class\.php\'\);"; |
1006
|
|
|
$props = 'public\s+\$\w+;'; |
1007
|
|
|
$varcommented = '@var\s+\w+\s+\$\w+\s+{@type\s+\w+}'; |
1008
|
|
|
$constructObj = '\$this->\w+\s+=\s+new\s+\w+\(\$this->db\);'; |
1009
|
|
|
|
1010
|
|
|
// add properties and declare them in constructor |
1011
|
|
|
foreach ($content as $lineNumber => &$lineContent) { |
1012
|
|
|
if (preg_match('/' . $varcommented . '/', $lineContent)) { |
1013
|
|
|
$lineContent = ''; |
1014
|
|
|
foreach ($objects as $objectname) { |
1015
|
|
|
$lineContent .= "\t * @var " . $objectname . " \$" . strtolower($objectname) . " {@type " . $objectname . "}" . PHP_EOL; |
1016
|
|
|
} |
1017
|
|
|
//var_dump($lineContent);exit; |
1018
|
|
|
} elseif (preg_match('/' . $props . '/', $lineContent)) { |
1019
|
|
|
$lineContent = ''; |
1020
|
|
|
foreach ($objects as $objectname) { |
1021
|
|
|
$lineContent .= "\tpublic \$" . strtolower($objectname) . ";" . PHP_EOL; |
1022
|
|
|
} |
1023
|
|
|
} elseif (preg_match('/' . $constructObj . '/', $lineContent)) { |
1024
|
|
|
$lineContent = ''; |
1025
|
|
|
foreach ($objects as $objectname) { |
1026
|
|
|
$lineContent .= "\t\t\$this->" . strtolower($objectname) . " = new " . $objectname . "(\$this->db);" . PHP_EOL; |
1027
|
|
|
} |
1028
|
|
|
} elseif (preg_match('/' . $includeClass . '/', $lineContent)) { |
1029
|
|
|
$lineContent = ''; |
1030
|
|
|
foreach ($objects as $objectname) { |
1031
|
|
|
$lineContent .= "dol_include_once('/" . strtolower($modulename) . "/class/" . strtolower($objectname) . ".class.php');" . PHP_EOL; |
1032
|
|
|
} |
1033
|
|
|
} |
1034
|
|
|
} |
1035
|
|
|
|
1036
|
|
|
$allContent = implode("", $content); |
1037
|
|
|
file_put_contents($file, $allContent); |
1038
|
|
|
|
1039
|
|
|
// Add methods for each object |
1040
|
|
|
$allContent = getFromFile($srcfile, '/* BEGIN MODULEBUILDER API MYOBJECT */', '/* END MODULEBUILDER API MYOBJECT */'); |
1041
|
|
|
foreach ($objects as $objectname) { |
1042
|
|
|
$arrayreplacement = array( |
1043
|
|
|
'mymodule' => strtolower($modulename), |
1044
|
|
|
'MyModule' => $modulename, |
1045
|
|
|
'MYMODULE' => strtoupper($modulename), |
1046
|
|
|
'My module' => $modulename, |
1047
|
|
|
'my module' => $modulename, |
1048
|
|
|
'Mon module' => $modulename, |
1049
|
|
|
'mon module' => $modulename, |
1050
|
|
|
'htdocs/modulebuilder/template' => strtolower($modulename), |
1051
|
|
|
'myobject' => strtolower($objectname), |
1052
|
|
|
'MyObject' => $objectname, |
1053
|
|
|
'MYOBJECT' => strtoupper($objectname), |
1054
|
|
|
'---Put here your own copyright and developer email---' => dol_print_date($now, '%Y') . ' ' . $user->getFullName($langs) . ($user->email ? ' <' . $user->email . '>' : '') |
1055
|
|
|
); |
1056
|
|
|
$contentReplaced = make_substitutions($allContent, $arrayreplacement, null); |
1057
|
|
|
//$contentReplaced = str_replace(["myobject","MyObject"], [strtolower($object),$object], $allContent); |
1058
|
|
|
|
1059
|
|
|
dolReplaceInFile($file, array( |
1060
|
|
|
'/* BEGIN MODULEBUILDER API MYOBJECT */' => '/* BEGIN MODULEBUILDER API ' . strtoupper($objectname) . ' */' . $contentReplaced . "\t" . '/* END MODULEBUILDER API ' . strtoupper($objectname) . ' */' . "\n\n\n\t" . '/* BEGIN MODULEBUILDER API MYOBJECT */' |
1061
|
|
|
)); |
1062
|
|
|
} |
1063
|
|
|
|
1064
|
|
|
// Remove the block $allContent found in src file |
1065
|
|
|
// TODO Replace with a replacement of all text including into /* BEGIN MODULEBUILDER API MYOBJECT */ and /* END MODULEBUILDER API MYOBJECT */ |
1066
|
|
|
dolReplaceInFile($file, array($allContent => '')); |
1067
|
|
|
|
1068
|
|
|
return 1; |
1069
|
|
|
} |
1070
|
|
|
|
1071
|
|
|
/** |
1072
|
|
|
* Remove Object variables and methods from API_Module File |
1073
|
|
|
* |
1074
|
|
|
* @param string $file File api module |
1075
|
|
|
* @param string[] $objects Array of objects in the module |
1076
|
|
|
* @param string $objectname Name of object want to remove |
1077
|
|
|
* @return int<-1,1> 1 if OK, -1 if KO |
1078
|
|
|
*/ |
1079
|
|
|
function removeObjectFromApiFile($file, $objects, $objectname) |
1080
|
|
|
{ |
1081
|
|
|
if (!file_exists($file)) { |
1082
|
|
|
return -1; |
1083
|
|
|
} |
1084
|
|
|
|
1085
|
|
|
$content = file($file); // $content is an array |
1086
|
|
|
|
1087
|
|
|
$includeClass = "dol_include_once\(\'\/\w+\/class\/" . strtolower($objectname) . "\.class\.php\'\);"; |
1088
|
|
|
$props = 'public\s+\$' . strtolower($objectname); |
1089
|
|
|
$varcommented = '@var\s+\w+\s+\$' . strtolower($objectname) . '\s+{@type\s+\w+}'; |
1090
|
|
|
$constructObj = '\$this->' . strtolower($objectname) . '\s+=\s+new\s+\w+\(\$this->db\);'; |
1091
|
|
|
|
1092
|
|
|
// add properties and declare them in constructor |
1093
|
|
|
foreach ($content as $lineNumber => &$lineContent) { |
1094
|
|
|
if (preg_match('/' . $varcommented . '/i', $lineContent)) { |
1095
|
|
|
$lineContent = ''; |
1096
|
|
|
} elseif (preg_match('/' . $props . '/i', $lineContent)) { |
1097
|
|
|
$lineContent = ''; |
1098
|
|
|
} elseif (preg_match('/' . $constructObj . '/i', $lineContent)) { |
1099
|
|
|
$lineContent = ''; |
1100
|
|
|
} elseif (preg_match('/' . $includeClass . '/i', $lineContent)) { |
1101
|
|
|
$lineContent = ''; |
1102
|
|
|
} |
1103
|
|
|
} |
1104
|
|
|
|
1105
|
|
|
$allContent = implode("", $content); |
1106
|
|
|
file_put_contents($file, $allContent); |
1107
|
|
|
|
1108
|
|
|
// for delete methods of object |
1109
|
|
|
$begin = '/* BEGIN MODULEBUILDER API ' . strtoupper($objectname) . ' */'; |
1110
|
|
|
$end = '/* END MODULEBUILDER API ' . strtoupper($objectname) . ' */'; |
1111
|
|
|
$allContent = getFromFile($file, $begin, $end); |
1112
|
|
|
$check = dolReplaceInFile($file, array($allContent => '')); |
1113
|
|
|
if ($check) { |
1114
|
|
|
dolReplaceInFile($file, array($begin => '', $end => '')); |
1115
|
|
|
} |
1116
|
|
|
|
1117
|
|
|
return 1; |
1118
|
|
|
} |
1119
|
|
|
|
1120
|
|
|
|
1121
|
|
|
/** |
1122
|
|
|
* @param string $file path of filename |
1123
|
|
|
* @param array<int,array{commentgroup:string,fk_menu:string,type:string,titre:string,mainmenu:string,leftmenu:string,url:string,langs:string,position:int,enabled:int,perms:string,target:string,user:int}> $menus all menus for module |
1124
|
|
|
* @param mixed|null $menuWantTo menu get for do actions |
1125
|
|
|
* @param int|null $key key for the concerned menu |
1126
|
|
|
* @param int<-1,2> $action for specify what action (0 = delete perm, 1 = add perm, 2 = update perm, -1 = when we delete object) |
1127
|
|
|
* @return int<-1,1> 1 if OK, -1 if KO |
1128
|
|
|
*/ |
1129
|
|
|
function reWriteAllMenus($file, $menus, $menuWantTo, $key, $action) |
1130
|
|
|
{ |
1131
|
|
|
$errors = 0; |
1132
|
|
|
$counter = 0; |
1133
|
|
|
if (!file_exists($file)) { |
1134
|
|
|
return -1; |
1135
|
|
|
} |
1136
|
|
|
|
1137
|
|
|
if ($action == 0 && !empty($key)) { |
1138
|
|
|
// delete menu manually |
1139
|
|
|
array_splice($menus, array_search($menus[$key], $menus), 1); |
1140
|
|
|
} elseif ($action == 1) { |
1141
|
|
|
// add menu manually |
1142
|
|
|
array_push($menus, $menuWantTo); |
1143
|
|
|
} elseif ($action == 2 && !empty($key) && !empty($menuWantTo)) { |
1144
|
|
|
// update right from permissions array |
1145
|
|
|
$urlCounter = 0; |
1146
|
|
|
// check if the values already exists |
1147
|
|
|
foreach ($menus as $index => $menu) { |
1148
|
|
|
if ($index !== $key) { |
1149
|
|
|
if ($menu['type'] === $menuWantTo['type']) { |
1150
|
|
|
if (strcasecmp(str_replace(' ', '', $menu['titre']), str_replace(' ', '', $menuWantTo['titre'])) === 0) { |
1151
|
|
|
$counter++; |
1152
|
|
|
} |
1153
|
|
|
if (strcasecmp(str_replace(' ', '', $menu['url']), str_replace(' ', '', $menuWantTo['url'])) === 0) { |
1154
|
|
|
$urlCounter++; |
1155
|
|
|
} |
1156
|
|
|
} |
1157
|
|
|
} |
1158
|
|
|
} |
1159
|
|
|
if (!$counter && $urlCounter < 2) { |
1160
|
|
|
$menus[$key] = $menuWantTo; |
1161
|
|
|
} else { |
1162
|
|
|
$errors++; |
1163
|
|
|
} |
1164
|
|
|
} elseif ($action == -1 && !empty($menuWantTo)) { |
1165
|
|
|
// delete menus when delete Object |
1166
|
|
|
foreach ($menus as $index => $menu) { |
1167
|
|
|
if ((strpos(strtolower($menu['fk_menu']), strtolower($menuWantTo)) !== false) || (strpos(strtolower($menu['leftmenu']), strtolower($menuWantTo)) !== false)) { |
1168
|
|
|
array_splice($menus, array_search($menu, $menus), 1); |
1169
|
|
|
} |
1170
|
|
|
} |
1171
|
|
|
} else { |
1172
|
|
|
$errors++; |
1173
|
|
|
} |
1174
|
|
|
if (!$errors) { |
1175
|
|
|
// delete All LEFT Menus (except for commented template MYOBJECT) |
1176
|
|
|
$beginMenu = '/* BEGIN MODULEBUILDER LEFTMENU'; |
1177
|
|
|
$excludeBeginMenu = '/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT'; |
1178
|
|
|
$endMenu = '/* END MODULEBUILDER LEFTMENU'; |
1179
|
|
|
$protection = 0; |
1180
|
|
|
while ($protection <= 1000 && $allMenus = getFromFile($file, $beginMenu, $endMenu, $excludeBeginMenu, 1)) { |
1181
|
|
|
$protection++; |
1182
|
|
|
dolReplaceInFile($file, array($allMenus => '')); |
1183
|
|
|
} |
1184
|
|
|
|
1185
|
|
|
// forge the menu code in a string |
1186
|
|
|
$str_menu = ""; |
1187
|
|
|
foreach ($menus as $index => $menu) { |
1188
|
|
|
$menu['position'] = "1000 + \$r"; |
1189
|
|
|
if ($menu['type'] === 'left') { |
1190
|
|
|
$start = "\t\t" . '/* BEGIN MODULEBUILDER LEFTMENU ' . strtoupper(empty($menu['object']) ? $menu['titre'] : $menu['object']) . ' */'; |
1191
|
|
|
$end = "\t\t" . '/* END MODULEBUILDER LEFTMENU ' . strtoupper(empty($menu['object']) ? $menu['titre'] : $menu['object']) . ' */'; |
1192
|
|
|
|
1193
|
|
|
$val_actuel = $menu; |
1194
|
|
|
$next_val = empty($menus[$index + 1]) ? null : $menus[$index + 1]; |
1195
|
|
|
//var_dump(dol_escape_php($menu['perms'], 1)); exit; |
1196
|
|
|
|
1197
|
|
|
$str_menu .= $start . "\n"; |
1198
|
|
|
$str_menu .= "\t\t\$this->menu[\$r++]=array(\n"; |
1199
|
|
|
$str_menu .= "\t\t\t 'fk_menu' => '" . dol_escape_php($menu['fk_menu'], 1) . "',\n"; |
1200
|
|
|
$str_menu .= "\t\t\t 'type' => '" . dol_escape_php($menu['type'], 1) . "',\n"; |
1201
|
|
|
$str_menu .= "\t\t\t 'titre' => '" . dol_escape_php($menu['titre'], 1) . "',\n"; |
1202
|
|
|
$str_menu .= "\t\t\t 'mainmenu' => '" . dol_escape_php($menu['mainmenu'], 1) . "',\n"; |
1203
|
|
|
$str_menu .= "\t\t\t 'leftmenu' => '" . dol_escape_php($menu['leftmenu'], 1) . "',\n"; |
1204
|
|
|
$str_menu .= "\t\t\t 'url' => '" . dol_escape_php($menu['url'], 1) . "',\n"; |
1205
|
|
|
$str_menu .= "\t\t\t 'langs' => '" . dol_escape_php($menu['langs'], 1) . "',\n"; |
1206
|
|
|
$str_menu .= "\t\t\t 'position' => " . ((int)$menu['position']) . ",\n"; |
1207
|
|
|
$str_menu .= "\t\t\t 'enabled' => '" . dol_escape_php($menu['enabled'], 1) . "',\n"; |
1208
|
|
|
$str_menu .= "\t\t\t 'perms' => '" . dol_escape_php($menu['perms'], 1) . "',\n"; |
1209
|
|
|
$str_menu .= "\t\t\t 'target' => '" . dol_escape_php($menu['target'], 1) . "',\n"; |
1210
|
|
|
$str_menu .= "\t\t\t 'user' => " . ((int)$menu['user']) . ",\n"; |
1211
|
|
|
$str_menu .= "\t\t\t 'object' => '" . dol_escape_php($menu['object'], 1) . "',\n"; |
1212
|
|
|
$str_menu .= "\t\t);\n"; |
1213
|
|
|
|
1214
|
|
|
if (is_null($next_val) || $val_actuel['leftmenu'] !== $next_val['leftmenu']) { |
1215
|
|
|
$str_menu .= $end . "\n"; |
1216
|
|
|
} |
1217
|
|
|
} |
1218
|
|
|
} |
1219
|
|
|
|
1220
|
|
|
dolReplaceInFile($file, array('/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' => $str_menu . "\n\t\t/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */")); |
1221
|
|
|
return 1; |
1222
|
|
|
} |
1223
|
|
|
return -1; |
1224
|
|
|
} |
1225
|
|
|
|
1226
|
|
|
/** |
1227
|
|
|
* Updates a dictionary in a module descriptor file. |
1228
|
|
|
* |
1229
|
|
|
* @param string $module The name of the module. |
1230
|
|
|
* @param string $file The path to the module descriptor file. |
1231
|
|
|
* @param array<string,string|array<string,int|string>> $dicts The dictionary data to be updated. |
1232
|
|
|
* @return int Returns the number of replacements made in the file. |
1233
|
|
|
*/ |
1234
|
|
|
function updateDictionaryInFile($module, $file, $dicts) |
1235
|
|
|
{ |
1236
|
|
|
$isEmpty = false; |
1237
|
|
|
$dicData = "\t\t\$this->dictionaries=array(\n"; |
1238
|
|
|
$module = strtolower($module); |
1239
|
|
|
foreach ($dicts as $key => $value) { |
1240
|
|
|
if (empty($value)) { |
1241
|
|
|
$isEmpty = true; |
1242
|
|
|
$dicData = "\t\t\$this->dictionaries=array();"; |
1243
|
|
|
break; |
1244
|
|
|
} |
1245
|
|
|
|
1246
|
|
|
$dicData .= "\t\t\t'$key'=>"; |
1247
|
|
|
|
1248
|
|
|
if ($key === 'tabcond') { |
1249
|
|
|
$conditions = array_map( |
1250
|
|
|
/** |
1251
|
|
|
* @param mixed $val |
1252
|
|
|
* @return string|int |
1253
|
|
|
*/ |
1254
|
|
|
function ($val) use ($module) { |
1255
|
|
|
return is_bool($val) ? "isModEnabled('$module')" : $val; |
1256
|
|
|
}, |
1257
|
|
|
$value |
1258
|
|
|
); |
1259
|
|
|
$dicData .= "array(" . implode(",", $conditions) . ")"; |
1260
|
|
|
} elseif ($key === 'tabhelp') { |
1261
|
|
|
$helpItems = array(); |
1262
|
|
|
foreach ($value as $helpValue) { |
1263
|
|
|
$helpItems[] = "array('code'=>\$langs->trans('" . $helpValue['code'] . "'), 'field2' => 'field2tooltip')"; |
1264
|
|
|
} |
1265
|
|
|
$dicData .= "array(" . implode(",", $helpItems) . ")"; |
1266
|
|
|
} else { |
1267
|
|
|
if (is_array($value)) { |
1268
|
|
|
$dicData .= "array(" . implode( |
1269
|
|
|
",", |
1270
|
|
|
array_map( |
1271
|
|
|
/** |
1272
|
|
|
* @param string $val |
1273
|
|
|
* @return string |
1274
|
|
|
*/ |
1275
|
|
|
static function ($val) { |
1276
|
|
|
return "'$val'"; |
1277
|
|
|
}, |
1278
|
|
|
$value |
1279
|
|
|
) |
1280
|
|
|
) . ")"; |
1281
|
|
|
} else { |
1282
|
|
|
$dicData .= "'$value'"; |
1283
|
|
|
} |
1284
|
|
|
} |
1285
|
|
|
$dicData .= ",\n"; |
1286
|
|
|
} |
1287
|
|
|
$dicData .= (!$isEmpty ? "\t\t);" : ''); |
1288
|
|
|
|
1289
|
|
|
$stringDic = getFromFile($file, '/* BEGIN MODULEBUILDER DICTIONARIES */', '/* END MODULEBUILDER DICTIONARIES */'); |
1290
|
|
|
$writeInfile = dolReplaceInFile($file, array($stringDic => $dicData . "\n")); |
1291
|
|
|
|
1292
|
|
|
return $writeInfile; |
1293
|
|
|
} |
1294
|
|
|
|
1295
|
|
|
/** |
1296
|
|
|
* Creates a new dictionary table. |
1297
|
|
|
* |
1298
|
|
|
* for creating a new dictionary table in Dolibarr. It generates the necessary SQL code to define the table structure, |
1299
|
|
|
* including columns such as 'rowid', 'code', 'label', 'position', 'use_default', 'active', etc. The table name is constructed based on the provided $namedic parameter. |
1300
|
|
|
* |
1301
|
|
|
* @param string $modulename The lowercase name of the module for which the dictionary table is being created. |
1302
|
|
|
* @param string $file The file path to the Dolibarr module builder file where the dictionaries are defined. |
1303
|
|
|
* @param string $namedic The name of the dictionary, which will also be used as the base for the table name. |
1304
|
|
|
* @param array<string,string|array<string,int|string>> $dictionnaires An optional array containing pre-existing dictionary data, including 'tabname', 'tablib', 'tabsql', etc. |
1305
|
|
|
* @return int<-1,-1> Return int < 0 if error, return nothing on success |
1306
|
|
|
*/ |
1307
|
|
|
function createNewDictionnary($modulename, $file, $namedic, $dictionnaires = null) |
1308
|
|
|
{ |
1309
|
|
|
global $db, $langs; |
1310
|
|
|
|
1311
|
|
|
if (empty($namedic)) { |
1312
|
|
|
setEventMessages($langs->trans("ErrorEmptyNameDic"), null, 'errors'); |
1313
|
|
|
return -1; |
1314
|
|
|
} |
1315
|
|
|
if (!file_exists($file)) { |
1316
|
|
|
return -1; |
1317
|
|
|
} |
1318
|
|
|
$modulename = strtolower($modulename); |
1319
|
|
|
|
1320
|
|
|
if (empty($dictionnaires)) { |
1321
|
|
|
$dictionnaires = array('langs' => '', 'tabname' => array(), 'tablib' => array(), 'tabsql' => array(), 'tabsqlsort' => array(), 'tabfield' => array(), 'tabfieldvalue' => array(), 'tabfieldinsert' => array(), 'tabrowid' => array(), 'tabcond' => array(), 'tabhelp' => array()); |
1322
|
|
|
} |
1323
|
|
|
|
1324
|
|
|
$columns = array( |
1325
|
|
|
'rowid' => array('type' => 'integer', 'value' => 11, 'extra' => 'AUTO_INCREMENT'), |
1326
|
|
|
'code' => array('type' => 'varchar', 'value' => 255, 'null' => 'NOT NULL'), |
1327
|
|
|
'label' => array('type' => 'varchar', 'value' => 255, 'null' => 'NOT NULL'), |
1328
|
|
|
'position' => array('type' => 'integer', 'value' => 11, 'null' => 'NULL'), |
1329
|
|
|
'use_default' => array('type' => 'varchar', 'value' => 11, 'default' => '1'), |
1330
|
|
|
'active' => array('type' => 'integer', 'value' => 3) |
1331
|
|
|
); |
1332
|
|
|
|
1333
|
|
|
$primaryKey = 'rowid'; |
1334
|
|
|
foreach ($columns as $key => $value) { |
1335
|
|
|
if ($key === 'rowid') { |
1336
|
|
|
$primaryKey = 'rowid'; |
1337
|
|
|
break; |
1338
|
|
|
} |
1339
|
|
|
if (!array_key_exists('rowid', $columns)) { |
1340
|
|
|
$primaryKey = array_key_first($columns); |
1341
|
|
|
break; |
1342
|
|
|
} |
1343
|
|
|
} |
1344
|
|
|
|
1345
|
|
|
// check if tablename exist in Database and create it if not |
1346
|
|
|
$checkTable = $db->DDLDescTable(MAIN_DB_PREFIX . strtolower($namedic)); |
1347
|
|
|
if ($checkTable && $db->num_rows($checkTable) > 0) { |
1348
|
|
|
setEventMessages($langs->trans("ErrorTableExist", $namedic), null, 'errors'); |
1349
|
|
|
return -1; |
1350
|
|
|
} else { |
1351
|
|
|
$_results = $db->DDLCreateTable(MAIN_DB_PREFIX . strtolower($namedic), $columns, $primaryKey, ""); |
1352
|
|
|
if ($_results < 0) { |
1353
|
|
|
dol_print_error($db); |
1354
|
|
|
$langs->load("errors"); |
1355
|
|
|
setEventMessages($langs->trans("ErrorTableNotFound", $namedic), null, 'errors'); |
1356
|
|
|
} |
1357
|
|
|
} |
1358
|
|
|
|
1359
|
|
|
// rewrite dictionary if |
1360
|
|
|
$dictionnaires['langs'] = $modulename . '@' . $modulename; |
1361
|
|
|
$dictionnaires['tabname'][] = strtolower($namedic); |
1362
|
|
|
$dictionnaires['tablib'][] = ucfirst(substr($namedic, 2)); |
1363
|
|
|
$dictionnaires['tabsql'][] = 'SELECT t.rowid as rowid, t.code, t.label, t.active FROM ' . MAIN_DB_PREFIX . strtolower($namedic) . ' as t'; |
1364
|
|
|
$dictionnaires['tabsqlsort'][] = (array_key_exists('label', $columns) ? 'label ASC' : ''); |
1365
|
|
|
$dictionnaires['tabfield'][] = (array_key_exists('code', $columns) && array_key_exists('label', $columns) ? 'code,label' : ''); |
1366
|
|
|
$dictionnaires['tabfieldvalue'][] = (array_key_exists('code', $columns) && array_key_exists('label', $columns) ? 'code,label' : ''); |
1367
|
|
|
$dictionnaires['tabfieldinsert'][] = (array_key_exists('code', $columns) && array_key_exists('label', $columns) ? 'code,label' : ''); |
1368
|
|
|
$dictionnaires['tabrowid'][] = $primaryKey; |
1369
|
|
|
$dictionnaires['tabcond'][] = isModEnabled('$modulename'); // @phan-suppress-current-line UnknownModuleName |
1370
|
|
|
$dictionnaires['tabhelp'][] = (array_key_exists('code', $columns) ? array('code' => $langs->trans('CodeTooltipHelp'), 'field2' => 'field2tooltip') : ''); |
1371
|
|
|
|
1372
|
|
|
// Build the dictionary string |
1373
|
|
|
$writeInfile = updateDictionaryInFile($modulename, $file, $dictionnaires); |
1374
|
|
|
if ($writeInfile > 0) { |
1375
|
|
|
setEventMessages($langs->trans("DictionariesCreated", ucfirst(substr($namedic, 2))), null); |
1376
|
|
|
} |
1377
|
|
|
|
1378
|
|
|
return -1; |
1379
|
|
|
} |
1380
|
|
|
|
1381
|
|
|
/** |
1382
|
|
|
* Generate Urls and add them to documentation module |
1383
|
|
|
* |
1384
|
|
|
* @param string $file_api filename or path of api |
1385
|
|
|
* @param string $file_doc filename or path of documentation |
1386
|
|
|
* @return int<-1,1> -1 if KO, 1 if OK, 0 if nothing change |
1387
|
|
|
*/ |
1388
|
|
|
function writeApiUrlsInDoc($file_api, $file_doc) |
1389
|
|
|
{ |
1390
|
|
|
$error = 0; |
1391
|
|
|
if (!dol_is_file($file_api) || !dol_is_file($file_doc)) { |
1392
|
|
|
$error++; |
1393
|
|
|
} |
1394
|
|
|
$string = getFromFile($file_api, '/*begin methods CRUD*/', '/*end methods CRUD*/'); |
1395
|
|
|
$extractUrls = explode("\n", $string); |
1396
|
|
|
|
1397
|
|
|
// extract urls from file |
1398
|
|
|
$urlValues = []; |
1399
|
|
|
foreach ($extractUrls as $key => $line) { |
1400
|
|
|
$lineWithoutTabsSpaces = preg_replace('/^[\t\s]+/', '', $line); |
1401
|
|
|
if (strpos($lineWithoutTabsSpaces, '* @url') === 0) { |
1402
|
|
|
$urlValue = trim(substr($lineWithoutTabsSpaces, strlen('* @url'))); |
1403
|
|
|
$urlValues[] = $urlValue; |
1404
|
|
|
} |
1405
|
|
|
} |
1406
|
|
|
|
1407
|
|
|
// get urls by object |
1408
|
|
|
$str = $_SERVER['HTTP_HOST'] . '/api/index.php/'; |
1409
|
|
|
$groupedUrls = []; |
1410
|
|
|
foreach ($urlValues as $url) { |
1411
|
|
|
if (preg_match('/(?:GET|POST|PUT|DELETE) (\w+)s/', $url, $matches)) { |
1412
|
|
|
$objectName = $matches[1]; |
1413
|
|
|
$url = $str . trim(strstr($url, ' ')); |
1414
|
|
|
$groupedUrls[$objectName][] = $url; |
1415
|
|
|
} |
1416
|
|
|
} |
1417
|
|
|
if (empty($groupedUrls)) { |
1418
|
|
|
$error++; |
1419
|
|
|
} |
1420
|
|
|
|
1421
|
|
|
// build format asciidoc for urls in table |
1422
|
|
|
if (!$error) { |
1423
|
|
|
$asciiDocTable = "[options=\"header\"]\n|===\n|Object | URLs\n"; // phpcs:ignore |
1424
|
|
|
foreach ($groupedUrls as $objectName => $urls) { |
1425
|
|
|
$urlsList = implode(" +\n*", $urls); |
1426
|
|
|
$asciiDocTable .= "|$objectName | \n*$urlsList +\n"; |
1427
|
|
|
} |
1428
|
|
|
$asciiDocTable .= "|===\n"; |
1429
|
|
|
$file_write = dolReplaceInFile($file_doc, array('__API_DOC__' => '__API_DOC__' . "\n" . $asciiDocTable)); |
1430
|
|
|
if ($file_write < 0) { |
1431
|
|
|
return -1; |
1432
|
|
|
} |
1433
|
|
|
return 1; |
1434
|
|
|
} |
1435
|
|
|
return -1; |
1436
|
|
|
} |
1437
|
|
|
|
1438
|
|
|
|
1439
|
|
|
/** |
1440
|
|
|
* count directories or files in modulebuilder folder |
1441
|
|
|
* @param string $path path of directory |
1442
|
|
|
* @param int $type type of file 1= file,2=directory |
1443
|
|
|
* @return int|bool |
1444
|
|
|
*/ |
1445
|
|
|
function countItemsInDirectory($path, $type = 1) |
1446
|
|
|
{ |
1447
|
|
|
if (!is_dir($path)) { |
1448
|
|
|
return false; |
1449
|
|
|
} |
1450
|
|
|
|
1451
|
|
|
$allFilesAndDirs = scandir($path); |
1452
|
|
|
$count = 0; |
1453
|
|
|
|
1454
|
|
|
foreach ($allFilesAndDirs as $item) { |
1455
|
|
|
if ($item != '.' && $item != '..') { |
1456
|
|
|
if ($type == 1 && is_file($path . DIRECTORY_SEPARATOR . $item) && strpos($item, '.back') === false) { |
1457
|
|
|
$count++; |
1458
|
|
|
} elseif ($type == 2 && is_dir($path . DIRECTORY_SEPARATOR . $item)) { |
1459
|
|
|
$count++; |
1460
|
|
|
} |
1461
|
|
|
} |
1462
|
|
|
} |
1463
|
|
|
return $count; |
1464
|
|
|
} |
1465
|
|
|
|