dolibarr 25.0.0-alpha
api_objectlinks.class.php
1<?php
2/* Copyright (C) 2025 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
3 * Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
4 * Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20use Luracast\Restler\RestException;
21
22require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
23require_once DOL_DOCUMENT_ROOT.'/core/class/objectlink.class.php';
24
25
33{
37 public static $FIELDS = array(
38 'fk_source',
39 'sourcetype',
40 'fk_target',
41 'targettype'
42 );
43
47 public $objectlink;
48
52 private $notrigger;
53
57 public function __construct()
58 {
59 global $db;
60 $this->db = $db;
61 $this->objectlink = new ObjectLink($this->db);
62 }
63
80 public function getById($id)
81 {
82 return $this->_fetch($id);
83 }
84
85
86
94 private function _setObjectLinkField($field, $value)
95 {
96 $clean_field = $this->_checkValForAPI($field, $value, $this->objectlink);
97
101 $intFields = array(
102 'fk_source',
103 'fk_target'
104 );
105
106 if (in_array($field, $intFields)) {
107 $this->objectlink->$field = (int) $clean_field; // Clean by _checkValForAPI previously
108 } else {
109 $this->objectlink->$field = (string) $clean_field; // Clean by _checkValForAPI previously
110 }
111 }
112
113
135 public function create($request_data = null)
136 {
137 // Check mandatory fields
138 $result = $this->_validate($request_data);
139
140 foreach ($request_data as $field => $value) {
141 if ($field == 'notrigger') {
142 $this->notrigger = (int) $value;
143 } else {
144 $this->_setObjectLinkField($field, $value);
145 }
146 }
147
148 // Permission check
149 $srctype = $this->objectlink->sourcetype;
150 if ($this->objectlink->sourcetype == 'subscription') {
151 $srctype = 'adherent';
152 }
153 if ($this->objectlink->sourcetype == 'conferenceorboothattendee') {
154 $srctype = 'projet';
155 }
156 $tgttype = $this->objectlink->targettype;
157 if ($this->objectlink->targettype == 'subscription') {
158 $tgttype = 'adherent';
159 }
160 if ($this->objectlink->targettype == 'conferenceorboothattendee') {
161 $tgttype = 'projet';
162 }
163 if (!DolibarrApiAccess::$user->hasRight((string) $srctype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $srctype, 'write')) {
164 throw new RestException(403, 'denied access to create the objectlinks sourcetype='.$this->objectlink->sourcetype);
165 }
166 if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
167 throw new RestException(403, 'denied access to create the objectlinks targettype='.$this->objectlink->targettype);
168 }
169 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
170 throw new RestException(403, 'denied access to create the objectlinks sourcetype='.$this->objectlink->sourcetype);
171 }
172 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
173 throw new RestException(403, 'denied access to create the objectlinks targettype='.$this->objectlink->targettype);
174 }
175
176 // Create object link (in database)
177 $result = $this->objectlink->create(DolibarrApiAccess::$user, $this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype, $this->notrigger);
178
179 if ($result < 0) {
180 throw new RestException(500, 'when create objectlink : '.$this->objectlink->error);
181 }
182
183 if ($result == 0) {
184 throw new RestException(304, 'Object link already exists');
185 }
186
187 return array(
188 'success' => array(
189 'code' => 200,
190 'message' => 'object link created'
191 )
192 );
193 }
194
209 public function deleteById($id)
210 {
211 // Reverse permission check. First we find out which kind of objects are linked, and if the user has rights to that then we delete it.
212 $result = $this->objectlink->fetch($id);
213 if ($result) {
214 $srctype = $this->objectlink->sourcetype;
215 if ($this->objectlink->sourcetype == 'subscription') {
216 $srctype = 'adherent';
217 }
218 if ($this->objectlink->sourcetype == 'conferenceorboothattendee') {
219 $srctype = 'projet';
220 }
221 $tgttype = $this->objectlink->targettype;
222 if ($this->objectlink->targettype == 'subscription') {
223 $tgttype = 'adherent';
224 }
225 if ($this->objectlink->targettype == 'conferenceorboothattendee') {
226 $tgttype = 'projet';
227 }
228 if (!DolibarrApiAccess::$user->hasRight(((string) $srctype), 'creer') && !DolibarrApiAccess::$user->hasRight(((string) $srctype), 'write')) {
229 throw new RestException(403, 'denied access to the objectlinks sourcetype');
230 }
231 if (!DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'creer') && !DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'write')) {
232 throw new RestException(403, 'denied access to the objectlinks targettype');
233 }
234 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
235 throw new RestException(403, 'denied access to the objectlinks sourcetype');
236 }
237 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
238 throw new RestException(403, 'denied access to the objectlinks targettype');
239 }
240 } else {
241 throw new RestException(404, 'Object Link not found');
242 }
243
244 if (!$this->objectlink->delete(DolibarrApiAccess::$user)) {
245 throw new RestException(500, 'Error when delete objectlink : '.$this->objectlink->error);
246 }
247
248 return array(
249 'success' => array(
250 'code' => 200,
251 'message' => 'object link deleted'
252 )
253 );
254 }
255
274 public function getByValues($fk_source, $sourcetype, $fk_target, $targettype, $relationtype = null)
275 {
276 $request_data = array(
277 'fk_source' => ((int) $fk_source),
278 'sourcetype' => (string) $sourcetype,
279 'fk_target' => ((int) $fk_target),
280 'targettype' => (string) $targettype,
281 'relationtype' => $relationtype,
282 );
283
284 // Check mandatory fields
285 $result = $this->_validate($request_data);
286
287 foreach ($request_data as $field => $value) {
288 $this->_setObjectLinkField($field, $value);
289 }
290
291 // Permission check
292 $srctype = $this->objectlink->sourcetype;
293 if ($this->objectlink->sourcetype == 'subscription') {
294 $srctype = 'adherent';
295 }
296 if ($this->objectlink->sourcetype == 'conferenceorboothattendee') {
297 $srctype = 'projet';
298 }
299 $tgttype = $this->objectlink->targettype;
300 if ($this->objectlink->targettype == 'subscription') {
301 $tgttype = 'adherent';
302 }
303 if ($this->objectlink->targettype == 'conferenceorboothattendee') {
304 $tgttype = 'projet';
305 }
306 if (!DolibarrApiAccess::$user->hasRight((string) $srctype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $srctype, 'write')) {
307 throw new RestException(403, 'denied access to get the objectlinks sourcetype='.$this->objectlink->sourcetype);
308 }
309 if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
310 throw new RestException(403, 'denied access to get the objectlinks targettype='.$this->objectlink->targettype);
311 }
312 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
313 throw new RestException(403, 'denied access to the objectlinks sourcetype');
314 }
315 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
316 throw new RestException(403, 'denied access to the objectlinks targettype');
317 }
318
319 $findresult = $this->objectlink->fetchByValues($this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype);
320
321 if ($findresult < 0) {
322 throw new RestException(500, 'Error when finding objectlink : '.$this->objectlink->error);
323 } elseif ($findresult > 0) {
324 return $this->_cleanObjectDatas($this->objectlink);
325 } else {
326 throw new RestException(404, 'Object Link not found');
327 }
328 }
329
330
350 public function deleteByValues($fk_source, $sourcetype, $fk_target, $targettype, $relationtype = null, $notrigger = 0)
351 {
352 $request_data = array(
353 'fk_source' => ((int) $fk_source),
354 'sourcetype' => (string) $sourcetype,
355 'fk_target' => ((int) $fk_target),
356 'targettype' => (string) $targettype,
357 'relationtype' => $relationtype,
358 );
359
360 // Check mandatory fields
361 $result = $this->_validate($request_data);
362
363 foreach ($request_data as $field => $value) {
364 $this->_setObjectLinkField($field, $value);
365 }
366
367 // Permission check
368 $srctype = $this->objectlink->sourcetype;
369 if ($this->objectlink->sourcetype == 'subscription') {
370 $srctype = 'adherent';
371 }
372 if ($this->objectlink->sourcetype == 'conferenceorboothattendee') {
373 $srctype = 'projet';
374 }
375 $tgttype = $this->objectlink->targettype;
376 if ($this->objectlink->targettype == 'subscription') {
377 $tgttype = 'adherent';
378 }
379 if ($this->objectlink->targettype == 'conferenceorboothattendee') {
380 $tgttype = 'projet';
381 }
382 if (!DolibarrApiAccess::$user->hasRight((string) $srctype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $srctype, 'write')) {
383 throw new RestException(403, 'denied access to delete the objectlinks sourcetype='.$this->objectlink->sourcetype);
384 }
385 if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
386 throw new RestException(403, 'denied access to delete the objectlinks targettype='.$this->objectlink->targettype);
387 }
388 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
389 throw new RestException(403, 'denied access to the objectlinks sourcetype');
390 }
391 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
392 throw new RestException(403, 'denied access to the objectlinks targettype');
393 }
394
395 $findresult = $this->objectlink->fetchByValues($this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype);
396
397 if ($findresult < 0) {
398 throw new RestException(500, 'Error when finding objectlink : '.$this->objectlink->error);
399 } elseif ($findresult > 0) {
400 $result = $this->objectlink->delete(DolibarrApiAccess::$user, $notrigger);
401
402 if ($result < 0) {
403 throw new RestException(500, 'Error when delete objectlink : '.$this->objectlink->error);
404 }
405
406 return array(
407 'success' => array(
408 'code' => 200,
409 'message' => 'object link deleted'
410 )
411 );
412 } else {
413 throw new RestException(404, 'Object Link not found');
414 }
415 }
416
430 private function _fetch($id)
431 {
432 $result = $this->objectlink->fetch($id);
433 if ($result) {
434 $srctype = $this->objectlink->sourcetype;
435 if ($this->objectlink->sourcetype == 'subscription') {
436 $srctype = 'adherent';
437 }
438 if ($this->objectlink->sourcetype == 'conferenceorboothattendee') {
439 $srctype = 'projet';
440 }
441 $tgttype = $this->objectlink->targettype;
442 if ($this->objectlink->targettype == 'subscription') {
443 $tgttype = 'adherent';
444 }
445 if ($this->objectlink->targettype == 'conferenceorboothattendee') {
446 $tgttype = 'projet';
447 }
448 if (!DolibarrApiAccess::$user->hasRight(((string) $srctype), 'lire') && !DolibarrApiAccess::$user->hasRight(((string) $srctype), 'read')) {
449 throw new RestException(403, 'denied access to the objectlinks sourcetype');
450 }
451 if (!DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'lire') && !DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'read')) {
452 throw new RestException(403, 'denied access to the objectlinks targettype');
453 }
454 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
455 throw new RestException(403, 'denied access to the objectlinks sourcetype');
456 }
457 if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
458 throw new RestException(403, 'denied access to the objectlinks targettype');
459 }
460 } else {
461 throw new RestException(404, 'Object Link not found');
462 }
463
464 return $this->_cleanObjectDatas($this->objectlink);
465 }
466
467 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
480 protected function _cleanObjectDatas($object)
481 {
482 // phpcs:enable
483 $object = parent::_cleanObjectDatas($object);
484
485 unset($object->module);
486 unset($object->entity);
487 unset($object->import_key);
488 unset($object->array_languages);
489 unset($object->contacts_ids);
490 unset($object->linkedObjectsIds);
491 unset($object->canvas);
492 unset($object->fk_project);
493 unset($object->contact_id);
494 unset($object->user);
495 unset($object->origin_type);
496 unset($object->origin_id);
497 unset($object->ref);
498 unset($object->ref_ext);
499 unset($object->statut);
500 unset($object->status);
501 unset($object->country_id);
502 unset($object->country_code);
503 unset($object->state_id);
504 unset($object->region_id);
505 unset($object->barcode_type);
506 unset($object->barcode_type_coder);
507 unset($object->mode_reglement_id);
508 unset($object->cond_reglement_id);
509 unset($object->demand_reason_id);
510 unset($object->transport_mode_id);
511 unset($object->shipping_method_id);
512 unset($object->shipping_method);
513 unset($object->fk_multicurrency);
514 unset($object->multicurrency_code);
515 unset($object->multicurrency_tx);
516 unset($object->multicurrency_total_ht);
517 unset($object->multicurrency_total_tva);
518 unset($object->multicurrency_total_ttc);
519 unset($object->multicurrency_total_localtax1);
520 unset($object->multicurrency_total_localtax2);
521 unset($object->last_main_doc);
522 unset($object->fk_account);
523 unset($object->note_public);
524 unset($object->note_private);
525 unset($object->total_ht);
526 unset($object->total_tva);
527 unset($object->total_localtax1);
528 unset($object->total_localtax2);
529 unset($object->total_ttc);
530 unset($object->lines);
531 unset($object->actiontypecode);
532 unset($object->name);
533 unset($object->lastname);
534 unset($object->firstname);
535 unset($object->civility_id);
536 unset($object->date_creation);
537 unset($object->date_validation);
538 unset($object->date_modification);
539 unset($object->tms);
540 unset($object->date_cloture);
541 unset($object->user_creation_id);
542 unset($object->user_validation_id);
543 unset($object->user_closing_id);
544 unset($object->user_modification_id);
545 unset($object->fk_user_creat);
546 unset($object->fk_user_modif);
547 unset($object->totalpaid);
548 unset($object->totalcreditnotes);
549 unset($object->totaldeposits);
550 unset($object->totalpaid_multicurrency);
551 unset($object->totalcreditnotes_multicurrency);
552 unset($object->totaldeposits_multicurrency);
553 unset($object->product);
554 unset($object->cond_reglement_supplier_id);
555 unset($object->deposit_percent);
556 unset($object->retained_warranty_fk_cond_reglement);
557 unset($object->warehouse_id);
558 unset($object->target);
559 unset($object->array_options);
560 unset($object->extraparams);
561 unset($object->specimen);
562
563 return $object;
564 }
565
566 // source before modifications was api_orders.class.php
576 private function _validate($data)
577 {
578 $objectlink = array();
579 foreach (ObjectLinks::$FIELDS as $field) {
580 if (!isset($data[$field])) {
581 throw new RestException(400, $field." field missing");
582 }
583 $objectlink[$field] = $data[$field];
584 }
585 return $objectlink;
586 }
587}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class for API REST v1.
Definition api.class.php:35
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
checkUserAccessToObject($user, array $featuresarray, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='', $dbt_select='rowid', $parenttableforentity='')
Check that access by a given user to an object is ok.