diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f113a8a7a36..fb05f408e57 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -28,7 +28,7 @@ jobs: # This is faster for a big repo. - name: Get all changed php files (if PR) id: changed-php - uses: tj-actions/changed-files@v43 + uses: tj-actions/changed-files@v44 if: env.gh_event == 'pull_request' with: files: | @@ -66,7 +66,7 @@ jobs: # The next uses git, which is slow for a bit repo. # - name: Get all changed php files (if PR) # id: changed-php - # uses: tj-actions/changed-files@v43 + # uses: tj-actions/changed-files@v44 # if: env.gh_event == 'pull_request' # with: # files: | @@ -115,7 +115,7 @@ jobs: ls -l ~/.cache/pre-commit/ - name: Convert Raw Log to Annotations - uses: mdeweerd/logToCheckStyle@v2024.3.4 + uses: mdeweerd/logToCheckStyle@v2024.3.5 if: ${{ failure() }} with: in: ${{ env.RAW_LOG }} diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index f85ad2535be..7f550037416 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -157,7 +157,7 @@ jobs: for /f "tokens=2 delims==" %%A in ('doskey /m:err') do EXIT /B %%A - name: Convert Raw Log to Annotations - uses: mdeweerd/logToCheckStyle@v2024.3.4 + uses: mdeweerd/logToCheckStyle@v2024.3.5 if: ${{ failure() }} with: in: ${{ env.PHPUNIT_LOG }} diff --git a/dev/examples/mail/source_email_ticket_2_answer_from_ticket.txt b/dev/examples/mail/source_email_ticket_2_answer_from_ticket.txt index 350b9a93cad..969d4eec95a 100644 --- a/dev/examples/mail/source_email_ticket_2_answer_from_ticket.txt +++ b/dev/examples/mail/source_email_ticket_2_answer_from_ticket.txt @@ -10,7 +10,8 @@ To: customer@customercompany.fr Subject: [MyBigCompany - Ticket #TS2008-0040] Nouveau message Date: Thu, 20 Aug 2020 18:31:37 +0200 Message-ID: <1597941097.SMTPs-dolibarr-tic58@83b5bc91f83a56e458db71e0adac2b62> -References: <1597941097.SMTPs-dolibarr-tic58@83b5bc91f83a56e458db71e0adac2b62> +References: +In-Reply-To: X-Dolibarr-TRACKID: tic58@83b5bc91f83a56e458db71e0adac2b62 X-RemoteAddr: 127.0.0.1 X-Mailer: Dolibarr version 13.0.0-alpha (using SMTPs Mailer) @@ -25,17 +26,17 @@ Content-Type: multipart/alternative; boundary="mul_872cdd6a64216735955664484832b --mul_872cdd6a64216735955664484832b075 Content-Type: text/plain; charset=UTF-8 -Bonjour +Bonjour + - Une nouvelle réponse a été ajoutée à un ticket que vous suivez. Voici -le message :PredefinedMailContentTicket_send - - +le message :PredefinedMailContentTicket_send + + Vous pouvez voir la progression du ticket en cliquant sur le lien -ci-dessus. : fr5uw2yospypn2rz - Cordialement, - +ci-dessus. : fr5uw2yospypn2rz + Cordialement, + -- --mul_872cdd6a64216735955664484832b075 Content-Type: text/html; charset=UTF-8 diff --git a/dev/translation/dynamic_translation_keys.lst b/dev/translation/dynamic_translation_keys.lst index 41220044fe9..00a01c617ca 100644 --- a/dev/translation/dynamic_translation_keys.lst +++ b/dev/translation/dynamic_translation_keys.lst @@ -437,6 +437,7 @@ CardContent CardProduct0 CardProduct1 Cards +Cart CashAccounts CashDeskBankCB CashDeskBankCash @@ -2028,6 +2029,7 @@ Notify_MEMBER_MODIFY Notify_MEMBER_RESILIATE Notify_MEMBER_SUBSCRIPTION Notify_MEMBER_VALIDATE +Notify_ORDER_CANCEL Notify_ORDER_CLOSE Notify_ORDER_SENTBYMAIL Notify_ORDER_SUPPLIER_APPROVE diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 3f414262a72..0f153f57e01 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1122,8 +1122,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Categories if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) { print ''.$form->editfieldkey("Categories", 'memcats', '', $object, 0).''; - $cate_arbo = $form->select_all_categories(Categorie::TYPE_MEMBER, null, 'parent', null, null, 1); - print img_picto('', 'category').$form->multiselectarray('memcats', $cate_arbo, GETPOST('memcats', 'array'), null, null, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + $cate_arbo = $form->select_all_categories(Categorie::TYPE_MEMBER, 0, 'parent', 0, 0, 1); + print img_picto('', 'category').$form->multiselectarray('memcats', $cate_arbo, GETPOST('memcats', 'array'), 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); print ""; } diff --git a/htdocs/adherents/class/api_members.class.php b/htdocs/adherents/class/api_members.class.php index 941a685d326..a0586546b48 100644 --- a/htdocs/adherents/class/api_members.class.php +++ b/htdocs/adherents/class/api_members.class.php @@ -81,7 +81,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('adherent', $member->id) && $id > 0) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($member); @@ -114,7 +114,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('adherent', $member->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($member); @@ -153,7 +153,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('adherent', $member->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($member); @@ -192,7 +192,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('adherent', $member->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($member); @@ -301,11 +301,11 @@ class Members extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $member->context['caller'] = $request_data['caller']; + $member->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $member->$field = $value; + $member->$field = $this->_checkValForAPI($field, $value, $member); } if ($member->create(DolibarrApiAccess::$user) < 0) { throw new RestException(500, 'Error creating member', array_merge(array($member->error), $member->errors)); @@ -337,7 +337,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('member', $member->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { @@ -346,10 +346,15 @@ class Members extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $member->context['caller'] = $request_data['caller']; + $member->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); + continue; + } + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $member->array_options[$index] = $val; + } continue; } - // Process the status separately because it must be updated using // the validate(), resiliate() and exclude() methods of the class Adherent. if ($field == 'statut') { @@ -370,7 +375,7 @@ class Members extends DolibarrApi } } } else { - $member->$field = $value; + $member->$field = $this->_checkValForAPI($field, $value, $member); } } @@ -405,7 +410,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('member', $member->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -646,7 +651,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('member', $membertype->id, 'adherent_type')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($membertype); @@ -745,11 +750,11 @@ class Members extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $membertype->context['caller'] = $request_data['caller']; + $membertype->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $membertype->$field = $value; + $membertype->$field = $this->_checkValForAPI($field, $value, $membertype); } if ($membertype->create(DolibarrApiAccess::$user) < 0) { throw new RestException(500, 'Error creating member type', array_merge(array($membertype->error), $membertype->errors)); @@ -783,7 +788,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('member', $membertype->id, 'adherent_type')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { @@ -792,13 +797,13 @@ class Members extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $membertype->context['caller'] = $request_data['caller']; + $membertype->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } // Process the status separately because it must be updated using // the validate(), resiliate() and exclude() methods of the class AdherentType. - $membertype->$field = $value; + $membertype->$field = $this->_checkValForAPI($field, $value, $membertype); } // If there is no error, update() returns the number of affected rows @@ -834,7 +839,7 @@ class Members extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('member', $membertype->id, 'adherent_type')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $res = $membertype->delete(DolibarrApiAccess::$user); diff --git a/htdocs/adherents/class/api_subscriptions.class.php b/htdocs/adherents/class/api_subscriptions.class.php index a5f27263cbd..56eb2f0f0af 100644 --- a/htdocs/adherents/class/api_subscriptions.class.php +++ b/htdocs/adherents/class/api_subscriptions.class.php @@ -161,11 +161,11 @@ class Subscriptions extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $subscription->context['caller'] = $request_data['caller']; + $subscription->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $subscription->$field = $value; + $subscription->$field = $this->_checkValForAPI($field, $value, $subscription); } if ($subscription->create(DolibarrApiAccess::$user) < 0) { throw new RestException(500, 'Error when creating subscription', array_merge(array($subscription->error), $subscription->errors)); @@ -202,11 +202,11 @@ class Subscriptions extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $subscription->context['caller'] = $request_data['caller']; + $subscription->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $subscription->$field = $value; + $subscription->$field = $this->_checkValForAPI($field, $value, $subscription); } if ($subscription->update(DolibarrApiAccess::$user) > 0) { diff --git a/htdocs/admin/external_rss.php b/htdocs/admin/external_rss.php index 5d3228ae23a..5781b810489 100644 --- a/htdocs/admin/external_rss.php +++ b/htdocs/admin/external_rss.php @@ -7,6 +7,7 @@ * Copyright (C) 2005-2011 Regis Houssin * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2020 Tobias Sekan + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -280,7 +281,7 @@ if ($resql) { print ''; print "".$langs->trans("Status").""; print ""; - if ($result > 0 && empty($rss->error)) { + if ($result > 0 && empty($rssparser->error)) { print ''.$langs->trans("Online").''; } else { print ''.$langs->trans("Offline"); diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index 43e29dfb535..d7bb4315638 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -189,35 +189,25 @@ print '
'; print ''; print ''; -print '
'; +print '
'; print ''; print ''; print ''; print ''; print "\n"; + print ''; print ''; print ''; -print ''; -print ''; -print ''; print ''; @@ -231,6 +221,20 @@ if ($conf->use_javascript_ajax) { print ''; print ''; + +print ''; +print ''; +print ''; + + print ''; print ''; print ''; + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; print $langs->trans("NotificationEMailFrom").''; print img_picto('', 'email', 'class="pictofixedwidth"'); print ''; -if (getDolGlobalString('NOTIFICATION_EMAIL_FROM') && !isValidEmail($conf->global->NOTIFICATION_EMAIL_FROM)) { +if (getDolGlobalString('NOTIFICATION_EMAIL_FROM') && !isValidEmail(getDolGlobalString('NOTIFICATION_EMAIL_FROM'))) { print ' '.img_warning($langs->trans("ErrorBadEMail")); } print '
'; -print $langs->trans("NotificationDisableConfirmMessageContact").''; -if ($conf->use_javascript_ajax) { - print ajax_constantonoff('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT'); -} else { - $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT", $arrval, getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT')); -} -print '
'; print $langs->trans("NotificationDisableConfirmMessageUser").'
'; +print $langs->trans("NotificationDisableConfirmMessageContact").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT", $arrval, getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT')); +} +print '
'; print $langs->trans("NotificationDisableConfirmMessageFix").''; @@ -242,6 +246,8 @@ if ($conf->use_javascript_ajax) { } print '
'; print '
'; diff --git a/htdocs/admin/security_file.php b/htdocs/admin/security_file.php index 0c191d9ae7b..ba2d0be6054 100644 --- a/htdocs/admin/security_file.php +++ b/htdocs/admin/security_file.php @@ -2,6 +2,7 @@ /* Copyright (C) 2004-2017 Laurent Destailleur * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2013 Juanjo Menent + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,7 +87,7 @@ if ($action == 'updateform') { if (!preg_match('/^0/', $tmpumask)) { $tmpumask = '0'.$tmpumask; } - if (empty($tmpumask) || $tmpumask === '0') { + if (empty($tmpumask)) { // Also matches '0' $tmpumask = '0664'; } diff --git a/htdocs/api/admin/index.php b/htdocs/api/admin/index.php index 4a9abc9f307..8ac6eed0201 100644 --- a/htdocs/api/admin/index.php +++ b/htdocs/api/admin/index.php @@ -150,7 +150,7 @@ print ' '.$langs->trans("Example").': '.$langs->trans("IPListExample"); print ''; print ''; print ''; -print ''; +print ''; print ''; print ''; diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 63d504b14cb..1436eabd4b6 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -2,6 +2,7 @@ /* Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Laurent Destailleur * Copyright (C) 2020 Frédéric France + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -73,8 +74,6 @@ class DolibarrApi /** * Check and convert a string depending on its type/name. * - * Display a short message an return a http code 200 - * * @param string $field Field name * @param string|array $value Value to check/clean * @param Object $object Object @@ -84,16 +83,45 @@ class DolibarrApi { // phpcs:enable if (!is_array($value)) { - // TODO Use type detected in $object->fields if $object known and we can + // Sanitize the value using its type declared into ->fields of $object + if (!empty($object->fields) && !empty($object->fields[$field]) && !empty($object->fields[$field]['type'])) { + if (strpos($object->fields[$field]['type'], 'int') || strpos($object->fields[$field]['type'], 'double') || in_array($object->fields[$field]['type'], array('real', 'price', 'stock'))) { + return sanitizeVal($value, 'int'); + } + if ($object->fields[$field]['type'] == 'html') { + return sanitizeVal($value, 'restricthtml'); + } + if ($object->fields[$field]['type'] == 'select') { + // Check values are in the list of possible 'options' + // TODO + } + if ($object->fields[$field]['type'] == 'sellist' || $object->fields[$field]['type'] == 'checkbox') { + // TODO + } + if ($object->fields[$field]['type'] == 'boolean' || $object->fields[$field]['type'] == 'radio') { + // TODO + } + if ($object->fields[$field]['type'] == 'email') { + return sanitizeVal($value, 'email'); + } + if ($object->fields[$field]['type'] == 'password') { + return sanitizeVal($value, 'none'); + } + // Others will use 'alphanohtml' + } + if (in_array($field, array('note', 'note_private', 'note_public', 'desc', 'description'))) { return sanitizeVal($value, 'restricthtml'); } else { return sanitizeVal($value, 'alphanohtml'); } - } else { - // TODO Recall _checkValForAPI for each element of array + } else { // Example when $field = 'extrafields' and $value = content of $object->array_options + $newarrayvalue = array(); + foreach ($value as $tmpkey => $tmpvalue) { + $newarrayvalue[$tmpkey] = $this->_checkValForAPI($tmpkey, $tmpvalue, $object); + } - return $value; + return $newarrayvalue; } } @@ -107,16 +135,41 @@ class DolibarrApi */ protected function _filterObjectProperties($object, $properties) { + // phpcs:enable // If properties is empty, we return all properties if (empty($properties)) { return $object; } - // Else we filter properties + + // Copy of exploded array for efficiency + $arr_properties = explode(',', $properties); + $magic_properties = array(); + $real_properties = get_object_vars($object); + + // Unsetting real properties may unset magic properties. + // We keep a copy of the requested magic properties + foreach ($arr_properties as $key) { + if (!array_key_exists($key, $real_properties)) { + // Not a real property, + // check if $key is a magic property (we want to keep '$obj->$key') + if (property_exists($object, $key) && isset($object->$key)) { + $magic_properties[$key] = $object->$key; + } + } + } + + // Filter real properties (may indirectly unset magic properties) foreach (get_object_vars($object) as $key => $value) { - if (!in_array($key, explode(',', $properties))) { + if (!in_array($key, $arr_properties)) { unset($object->$key); } } + + // Restore the magic properties + foreach ($magic_properties as $key => $value) { + $object->$key = $value; + } + return $object; } diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 4b3385fe5ee..31e8dcf47c7 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -167,6 +167,7 @@ if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $ $refreshcache = true; if (!is_writable($conf->api->dir_temp)) { print 'Erreur temp dir api/temp not writable'; + header('HTTP/1.1 500 temp dir api/temp not writable'); exit(0); } } diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index 4c016282171..51b28f18427 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -158,7 +158,7 @@ class Asset extends CommonObject public $status; /** - * @var Asset object oldcopy + * @var static object oldcopy */ public $oldcopy; diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index f551600797a..3f9fe328199 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -196,11 +196,11 @@ class Boms extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->bom->context['caller'] = $request_data['caller']; + $this->bom->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->bom->$field = $value; + $this->bom->$field = $this->_checkValForAPI($field, $value, $this->bom); } $this->checkRefNumbering(); @@ -243,11 +243,18 @@ class Boms extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->bom->context['caller'] = $request_data['caller']; + $this->bom->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->bom->$field = $value; + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $this->bom->array_options[$index] = $this->_checkValForAPI('extrafields', $val, $this->bom); + } + continue; + } + + $this->bom->$field = $this->_checkValForAPI($field, $value, $this->bom); } $this->checkRefNumbering(); @@ -280,7 +287,7 @@ class Boms extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if (!$this->bom->delete(DolibarrApiAccess::$user)) { @@ -531,6 +538,14 @@ class Boms extends DolibarrApi unset($object->fk_incoterms); unset($object->label_incoterms); unset($object->location_incoterms); + unset($object->multicurrency_code); + unset($object->multicurrency_tx); + unset($object->multicurrency_total_ht); + unset($object->multicurrency_total_ttc); + unset($object->multicurrency_total_tva); + unset($object->multicurrency_total_localtax1); + unset($object->multicurrency_total_localtax2); + // If object has lines, remove $db property if (isset($object->lines) && is_array($object->lines) && count($object->lines) > 0) { diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 79b5007a241..f3b8c011f11 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -99,7 +99,7 @@ class Categories extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if ($include_childs) { @@ -203,11 +203,11 @@ class Categories extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->category->context['caller'] = $request_data['caller']; + $this->category->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->category->$field = $value; + $this->category->$field = $this->_checkValForAPI($field, $value, $this->category); } if ($this->category->create(DolibarrApiAccess::$user) < 0) { throw new RestException(500, 'Error when creating category', array_merge(array($this->category->error), $this->category->errors)); @@ -234,7 +234,7 @@ class Categories extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { @@ -243,11 +243,11 @@ class Categories extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->category->context['caller'] = $request_data['caller']; + $this->category->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->category->$field = $value; + $this->category->$field = $this->_checkValForAPI($field, $value, $this->category); } if ($this->category->update(DolibarrApiAccess::$user) > 0) { @@ -274,7 +274,7 @@ class Categories extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if (!$this->category->delete(DolibarrApiAccess::$user)) { @@ -767,7 +767,7 @@ class Categories extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('categorie', $this->category->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->category->getObjectsInCateg($type, $onlyids); diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 09e73b188f8..13066e7d6cf 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -60,14 +60,14 @@ class ActionComm extends CommonObject public $picto = 'action'; /** - * @var int 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + * @var int<0,2> 0=No test on entity, 1=Test with field entity, 2=Test with link by societe */ public $ismultientitymanaged = 1; /** - * @var integer 0=Default - * 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user - * 2=Same than 1 but accept record if fksoc is empty + * @var int<0,2> 0=Default + * 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user + * 2=Same than 1 but accept record if fksoc is empty */ public $restrictiononfksoc = 2; @@ -129,7 +129,7 @@ class ActionComm extends CommonObject * @var string Agenda event label * @deprecated Use $label */ - public $libelle; + private $libelle; /** * @var integer Date creation record (datec) @@ -197,7 +197,7 @@ class ActionComm extends CommonObject /** * @var int -1=Unknown duration - * @deprecated + * @deprecated Use ($datef - $datep) */ public $durationp = -1; @@ -212,7 +212,7 @@ class ActionComm extends CommonObject public $ponctuel; /** - * @var integer Percentage + * @var int<0,100> Percentage */ public $percentage; @@ -232,7 +232,7 @@ class ActionComm extends CommonObject public $priority; /** - * @var array Array of users + * @var array}> Array of users */ public $userassigned = array(); @@ -242,7 +242,7 @@ class ActionComm extends CommonObject public $userownerid; /** - * @var int[] Array of contact ids + * @var array,answer_status:int,transparency:int<0,1>}> Array of contact ids */ public $socpeopleassigned = array(); @@ -252,7 +252,7 @@ class ActionComm extends CommonObject public $otherassigned = array(); /** - * @var array Array of reminders + * @var array Array of reminders */ public $reminders = array(); @@ -268,14 +268,14 @@ class ActionComm extends CommonObject /** - * @var Societe|null Company linked to action (optional) + * @var ?Societe Company linked to action (optional) * @deprecated * @see $socid */ public $societe; /** - * @var Contact|null Contact linked to action (optional) + * @var ?Contact Contact linked to action (optional) * @deprecated * @see $contact_id */ @@ -318,7 +318,7 @@ class ActionComm extends CommonObject public $extraparams; /** - * @var array Actions + * @var array Actions */ public $actions = array(); @@ -377,12 +377,21 @@ class ActionComm extends CommonObject public $status; /** + * @var string IP address + */ + public $ip; + + /* * Properties to manage the recurring events */ - public $recurid; /* A string YYYYMMDDHHMMSS shared by allevent of same series */ - public $recurrule; /* Rule of recurring */ - public $recurdateend; /* Repeat until this date */ + /** @var string A string YYYYMMDDHHMMSS shared by allevent of same series */ + public $recurid; + /** @var string Rule of recurring */ + public $recurrule; + /** @var string Repeat until this date */ + public $recurdateend; + /** @var int Duration of phone call when the event is a phone call */ public $calling_duration; @@ -405,6 +414,19 @@ class ActionComm extends CommonObject public $fields = array(); + /** + * Provide list of deprecated properties and replacements + * + * @return array Old property to new property mapping + */ + protected function deprecatedProperties() + { + return array( + 'libelle' => 'label', + ) + parent::deprecatedProperties(); + } + + /** * Constructor * @@ -419,9 +441,9 @@ class ActionComm extends CommonObject * Add an action/event into database. * $this->type_id OR $this->type_code must be set. * - * @param User $user Object user making action - * @param int $notrigger 1 = disable triggers, 0 = enable triggers - * @return int Id of created event, < 0 if KO + * @param User $user Object user making action + * @param int<0,1> $notrigger 1 = disable triggers, 0 = enable triggers + * @return int Id of created event, < 0 if KO */ public function create(User $user, $notrigger = 0) { @@ -775,12 +797,12 @@ class ActionComm extends CommonObject /** * Load object from database * - * @param int $id Id of action to get - * @param string $ref Ref of action to get - * @param string $ref_ext Ref ext to get - * @param string $email_msgid Email msgid - * @param int $loadresources 1=Load also resources - * @return int Return integer <0 if KO, >0 if OK + * @param int $id Id of action to get + * @param string $ref Ref of action to get + * @param string $ref_ext Ref ext to get + * @param string $email_msgid Email msgid + * @param int<0,1> $loadresources 1=Load also resources + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '', $loadresources = 1) { @@ -926,7 +948,7 @@ class ActionComm extends CommonObject /** * Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event * - * @return int Return integer <0 if KO, >0 if OK + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function fetchResources() { @@ -972,7 +994,7 @@ class ActionComm extends CommonObject * Initialize this->userassigned array with list of id of user assigned to event * * @param bool $override Override $this->userownerid when empty. TODO This should be false by default. True is here to fix corrupted data. - * @return int Return integer <0 if KO, >0 if OK + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function fetch_userassigned($override = true) { @@ -1017,9 +1039,9 @@ class ActionComm extends CommonObject /** * Delete event from database * - * @param User $user User making the delete - * @param int $notrigger 1 = disable triggers, 0 = enable triggers - * @return int Return integer <0 if KO, >0 if OK + * @param User $user User making the delete + * @param int<0,1> $notrigger 1 = disable triggers, 0 = enable triggers + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function delete($user, $notrigger = 0) { @@ -1113,9 +1135,9 @@ class ActionComm extends CommonObject * Update action into database * If percentage = 100, on met a jour date 100% * - * @param User $user Object user making change - * @param int $notrigger 1 = disable triggers, 0 = enable triggers - * @return int Return integer <0 if KO, >0 if OK + * @param User $user Object user making change + * @param int<0,1> $notrigger 1 = disable triggers, 0 = enable triggers + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function update(User $user, $notrigger = 0) { @@ -1436,6 +1458,7 @@ class ActionComm extends CommonObject $resql = $this->db->query($sql); if ($resql) { + $response = null; // Ensure the variable is defined if (empty($load_state_board)) { $agenda_static = new ActionComm($this->db); $response = new WorkboardResponse(); @@ -1451,6 +1474,8 @@ class ActionComm extends CommonObject // This assignment in condition is not a bug. It allows walking the results. while ($obj = $this->db->fetch_object($resql)) { if (empty($load_state_board)) { + '@phan-var-force WorkboardResponse $response + @phan-var-force ActionComm $agenda_static'; $response->nbtodo++; $agenda_static->datep = $this->db->jdate($obj->dp); if ($agenda_static->hasDelay()) { @@ -1515,8 +1540,8 @@ class ActionComm extends CommonObject /** * Return the label of the status * - * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto - * @param int $hidenastatus 1=Show nothing if status is "Not applicable" + * @param int<0,7> $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto + * @param int<0,1> $hidenastatus 1=Show nothing if status is "Not applicable" * @return string String with status */ public function getLibStatut($mode, $hidenastatus = 0) @@ -1528,11 +1553,11 @@ class ActionComm extends CommonObject /** * Return label of action status * - * @param int $percent Percent - * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto - * @param int $hidenastatus 1=Show nothing if status is "Not applicable" - * @param int|string $datestart Date start of event - * @return string Label + * @param int<0,100> $percent Percent + * @param int<0,7> $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto + * @param int<0,1> $hidenastatus 1=Show nothing if status is "Not applicable" + * @param int|string $datestart Date start of event + * @return string Label */ public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '') { @@ -1580,9 +1605,9 @@ class ActionComm extends CommonObject /** * getTooltipContentArray - * @param array $params params to construct tooltip data + * @param array $params params to construct tooltip data * @since v18 - * @return array + * @return array{picto:string,ref?:string,title?:string,labeltype?:string,location?:string,transparency?:string,space?:string,mailtopic?:string,mailfrom?:string,mailto?:string,mailcc?:string,description?:string,note?:string,categories?:string} */ public function getTooltipContentArray($params) { @@ -1603,7 +1628,6 @@ class ActionComm extends CommonObject $labeltype = $langs->trans('ActionAC_MANUAL'); } } - $datas['picto'] = img_picto('', $this->picto).' '.$langs->trans('Action').''; if (!empty($this->ref)) { $datas['ref'] = '
'.$langs->trans('Ref').': '.dol_escape_htmltag($this->ref); @@ -1658,13 +1682,13 @@ class ActionComm extends CommonObject * Return URL of event * Use $this->id, $this->type_code, $this->label and $this->type_label * - * @param int $withpicto 0 = No picto, 1 = Include picto into link, 2 = Only picto - * @param int $maxlength Max number of characters into label. If negative, use the ref as label. - * @param string $classname Force style class on a link - * @param string $option '' = Link to action, 'birthday'= Link to contact, 'holiday' = Link to leave - * @param int $overwritepicto 1 = Overwrite picto with this one - * @param int $notooltip 1 = Disable tooltip - * @param int $save_lastsearch_value -1 = Auto, 0 = No save of lastsearch_values when clicking, 1 = Save lastsearch_values whenclicking + * @param int<0,2> $withpicto 0 = No picto, 1 = Include picto into link, 2 = Only picto + * @param int $maxlength Max number of characters into label. If negative, use the ref as label. + * @param string $classname Force style class on a link + * @param string $option '' = Link to action, 'birthday'= Link to contact, 'holiday' = Link to leave + * @param int<0,1> $overwritepicto 1 = Overwrite picto with this one + * @param int<0,1> $notooltip 1 = Disable tooltip + * @param int<-1,1> $save_lastsearch_value -1 = Auto, 0 = No save of lastsearch_values when clicking, 1 = Save lastsearch_values whenclicking * @return string Chaine avec URL */ public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1) @@ -1690,9 +1714,6 @@ class ActionComm extends CommonObject } $label = $this->label; - if (empty($label)) { - $label = $this->libelle; // For backward compatibility - } $result = ''; @@ -1903,7 +1924,7 @@ class ActionComm extends CommonObject * Existing categories are left untouch. * * @param int[]|int $categories Category or categories IDs - * @return int Return integer <0 if KO, >0 if OK + * @return int<-1,1> Return integer <0 if KO, >0 if OK */ public function setCategories($categories) { @@ -1948,9 +1969,9 @@ class ActionComm extends CommonObject * @param string $type The type of the export 'event' or 'journal' * @param integer $cachedelay Do not rebuild file if date older than cachedelay seconds * @param string $filename The name for the exported file. - * @param array $filters Array of filters. Example array('notolderthan'=>99, 'year'=>..., 'idfrom'=>..., 'notactiontype'=>'systemauto', 'project'=>123, ...) - * @param integer $exportholiday 0 = don't integrate holidays into the export, 1 = integrate holidays into the export - * @return integer -1 = error on build export file, 0 = export okay + * @param array $filters Array of filters. Example array('notolderthan'=>99, 'year'=>..., 'idfrom'=>..., 'notactiontype'=>'systemauto', 'project'=>123, ...) + * @param int<0,1> $exportholiday 0 = don't integrate holidays into the export, 1 = integrate holidays into the export + * @return int<-1,1> -1 = error on build export file, 0 = export okay */ public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0) { @@ -2124,7 +2145,7 @@ class ActionComm extends CommonObject $condition = '<>'; } $userforfilter = new User($this->db); - $result = $userforfilter->fetch('', $logina); + $result = $userforfilter->fetch(0, $logina); if ($result > 0) { $sql .= " AND a.fk_user_author ".$condition." ".$userforfilter->id; } elseif ($result < 0 || $condition == '=') { @@ -2139,7 +2160,7 @@ class ActionComm extends CommonObject $condition = '<>'; } $userforfilter = new User($this->db); - $result = $userforfilter->fetch('', $logint); + $result = $userforfilter->fetch(0, $logint); if ($result > 0) { $sql .= " AND ar.fk_element = ".((int) $userforfilter->id); } elseif ($result < 0 || $condition == '=') { @@ -2288,8 +2309,8 @@ class ActionComm extends CommonObject } if (getDolGlobalString('AGENDA_EXPORT_FIX_TZ')) { - $timestampStart = $timestampStart - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600); - $timestampEnd = $timestampEnd - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600); + $timestampStart -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600); + $timestampEnd -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600); } $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); @@ -2395,7 +2416,7 @@ class ActionComm extends CommonObject * Used to build previews or test instances. * id must be 0 if object instance is a specimen. * - * @return int >0 if ok + * @return int<1,1> >0 if ok */ public function initAsSpecimen() { @@ -2486,7 +2507,7 @@ class ActionComm extends CommonObject * @param string $type Type of reminder 'browser' or 'email' * @param int $fk_user Id of user * @param bool $onlypast true = get only past reminder, false = get all reminders linked to this - * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + * @return int<-1,max> < if OK, else count of number of reminders */ public function loadReminders($type = '', $fk_user = 0, $onlypast = true) { @@ -2547,7 +2568,7 @@ class ActionComm extends CommonObject * Send reminders by emails * CAN BE A CRON TASK * - * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + * @return int<-1,1>|string 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) */ public function sendEmailsReminder() { @@ -2589,6 +2610,7 @@ class ActionComm extends CommonObject if ($resql) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($this->db); + $to = null; // Ensure 'to' is defined for static analysis while ($obj = $this->db->fetch_object($resql)) { $res = $actionCommReminder->fetch($obj->id); @@ -2721,10 +2743,10 @@ class ActionComm extends CommonObject /** * Update the percent value of a event with the given id * - * @param int $id The id of the event - * @param int $percent The new percent value for the event - * @param int $usermodid The user who modified the percent - * @return int 1 when update of the event was suscessfull, otherwise -1 + * @param int $id The id of the event + * @param int<0,100> $percent The new percent value for the event + * @param int $usermodid The user who modified the percent + * @return int<-1,1> 1 when update of the event was successful, otherwise -1 */ public function updatePercent($id, $percent, $usermodid = 0) { diff --git a/htdocs/comm/action/class/api_agendaevents.class.php b/htdocs/comm/action/class/api_agendaevents.class.php index 6aa5bd090d8..4f1e49d5166 100644 --- a/htdocs/comm/action/class/api_agendaevents.class.php +++ b/htdocs/comm/action/class/api_agendaevents.class.php @@ -84,7 +84,7 @@ class AgendaEvents extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('agenda', $this->actioncomm->id, 'actioncomm', '', 'fk_soc', 'id')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->actioncomm); } @@ -204,7 +204,7 @@ class AgendaEvents extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->actioncomm->context['caller'] = $request_data['caller']; + $this->actioncomm->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } @@ -253,7 +253,7 @@ class AgendaEvents extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('actioncomm', $this->actioncomm->id, 'actioncomm', '', 'fk_soc', 'id')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -261,7 +261,7 @@ class AgendaEvents extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->actioncomm->context['caller'] = $request_data['caller']; + $this->actioncomm->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } @@ -304,7 +304,7 @@ class AgendaEvents extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('actioncomm', $this->actioncomm->id, 'actioncomm', '', 'fk_soc', 'id')) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if (!$this->actioncomm->delete(DolibarrApiAccess::$user)) { diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 37d2c7054c1..d1bd15fdc55 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -916,7 +916,6 @@ if ($resql) { $event->type = $obj->type_type; $event->type_picto = $obj->type_picto; - $event->libelle = $obj->label; // deprecated $event->label = $obj->label; $event->percentage = $obj->percent; @@ -2166,17 +2165,15 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa // Show title $titletoshow = $daterange; - $titletoshow .= ($titletoshow ? ' ' : '').dol_escape_htmltag($event->label ? $event->label : $event->libelle); + $titletoshow .= ($titletoshow ? ' ' : '').dol_escape_htmltag($event->label); if ($event->type_code != 'ICALEVENT') { - $savlabel = $event->label ? $event->label : $event->libelle; + $savlabel = $event->label; $event->label = $titletoshow; - $event->libelle = $titletoshow; // deprecatd // Note: List of users are inside $event->userassigned. Link may be clickable depending on permissions of user. $titletoshow = (($event->type_picto || $event->type_code) ? $event->getTypePicto() : ''); $titletoshow .= $event->getNomUrl(0, $maxnbofchar, 'cal_event cal_event_title valignmiddle', '', 0, 0); // do not add 'inline-block' in css here: it makes the title transformed completely into '...' $event->label = $savlabel; - $event->libelle = $savlabel; } // Loop on each assigned user diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 77f0c7ea647..4b7aa0ca172 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -422,6 +422,8 @@ if (isModEnabled('order') && $user->hasRight('commande', 'lire')) { */ if ((isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "commande", "lire")) || (isModEnabled("supplier_order") && $user->hasRight("supplier_order", "lire"))) { + $supplierorderstatic = new CommandeFournisseur($db); + $sql = "SELECT cf.rowid, cf.ref, cf.ref_supplier, cf.total_ht, cf.total_tva, cf.total_ttc, cf.fk_statut as status"; $sql .= ", s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; @@ -639,7 +641,7 @@ if (isModEnabled("societe") && $user->hasRight('societe', 'lire')) { } $num = $db->num_rows($resql); - startSimpleTable($langs->trans($header, min($max, $num)), "societe/list.php", "type=p,c", 1); + startSimpleTable($langs->trans($header, min($max, $num)), "societe/list.php", "type=p,c&sortfield=s.tms&sortorder=DESC", 1, -1, 'company'); if ($num) { $i = 0; diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 33cc0957c47..94a8647974f 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -132,7 +132,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // Add external contacts ids. @@ -255,11 +255,11 @@ class Proposals extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->propal->context['caller'] = $request_data['caller']; + $this->propal->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->propal->$field = $value; + $this->propal->$field = $this->_checkValForAPI($field, $value, $this->propal); } /*if (isset($request_data["lines"])) { $lines = array(); @@ -297,7 +297,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $sql = ''; @@ -339,7 +339,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -405,7 +405,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $errors = []; @@ -486,7 +486,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -564,7 +564,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $updateRes = $this->propal->deleteLine($lineid, $id); @@ -605,7 +605,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->propal->add_contact($contactid, $type, 'external'); @@ -649,7 +649,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $contacts = $this->propal->liste_contact(); @@ -686,7 +686,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -694,11 +694,17 @@ class Proposals extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->propal->context['caller'] = $request_data['caller']; + $this->propal->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); + continue; + } + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $this->propal->array_options[$index] = $this->_checkValForAPI($field, $val, $this->propal); + } continue; } - $this->propal->$field = $value; + $this->propal->$field = $this->_checkValForAPI($field, $value, $this->propal); } // update end of validity date @@ -735,7 +741,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if (!$this->propal->delete(DolibarrApiAccess::$user)) { @@ -769,7 +775,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->propal->setDraft(DolibarrApiAccess::$user); @@ -786,7 +792,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->propal->fetchObjectLinked(); @@ -825,7 +831,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->propal->valid(DolibarrApiAccess::$user, $notrigger); @@ -842,7 +848,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->propal->fetchObjectLinked(); @@ -872,7 +878,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->propal->closeProposal(DolibarrApiAccess::$user, $status, $note_private, $notrigger); @@ -889,7 +895,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->propal->fetchObjectLinked(); @@ -916,7 +922,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->propal->classifyBilled(DolibarrApiAccess::$user); @@ -930,7 +936,7 @@ class Proposals extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->propal->fetchObjectLinked(); diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 499ab5088af..8e875f598ac 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -130,7 +130,7 @@ class Propal extends CommonObject public $ref_customer; /** - * @var Propal oldcopy with propal properties + * @var static oldcopy with propal properties */ public $oldcopy; diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index d70dab85cb7..7256ee8e790 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -128,7 +128,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // Add external contacts ids @@ -273,11 +273,11 @@ class Orders extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->commande->context['caller'] = $request_data['caller']; + $this->commande->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->commande->$field = $value; + $this->commande->$field = $this->_checkValForAPI($field, $value, $this->commande); } /*if (isset($request_data["lines"])) { $lines = array(); @@ -315,7 +315,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->commande->getLinesArray(); $result = array(); @@ -347,7 +347,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -414,7 +414,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -482,7 +482,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $updateRes = $this->commande->deleteLine(DolibarrApiAccess::$user, $lineid, $id); @@ -518,7 +518,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $contacts = $this->commande->liste_contact(-1, 'external', 0, $type); @@ -551,7 +551,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->commande->add_contact($contactid, $type, 'external'); @@ -599,7 +599,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $contacts = $this->commande->liste_contact(); @@ -641,7 +641,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -649,11 +649,17 @@ class Orders extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->commande->context['caller'] = $request_data['caller']; + $this->commande->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); + continue; + } + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $this->commande->array_options[$index] = $this->_checkValForAPI($field, $val, $this->commande); + } continue; } - $this->commande->$field = $value; + $this->commande->$field = $this->_checkValForAPI($field, $value, $this->commande); } // Update availability @@ -687,7 +693,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if (!$this->commande->delete(DolibarrApiAccess::$user)) { @@ -737,7 +743,7 @@ class Orders extends DolibarrApi $result = $this->commande->fetch_thirdparty(); // do not check result, as failure is not fatal (used only for mail notification substitutes) if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger); @@ -835,7 +841,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->commande->fetchObjectLinked(); @@ -863,7 +869,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->commande->cloture(DolibarrApiAccess::$user, $notrigger); @@ -880,7 +886,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->commande->fetchObjectLinked(); @@ -908,7 +914,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->commande->setDraft(DolibarrApiAccess::$user, $idwarehouse); @@ -925,7 +931,7 @@ class Orders extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->commande->fetchObjectLinked(); diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 1ca44dac3c1..05e3e590183 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -496,6 +496,7 @@ if (empty($reshook)) { $rang = ($nbOrders > 1) ? -1 : $lines[$i]->rang; //there may already be rows from previous orders if (!empty($createbills_onebythird)) { + $TFactThirdNbLines[$cmd->socid]++; $rang = $TFactThirdNbLines[$cmd->socid]; } @@ -531,9 +532,6 @@ if (empty($reshook)) { ); if ($result > 0) { $lineid = $result; - if (!empty($createbills_onebythird)) { //increment rang to keep order - $TFactThirdNbLines[$cmd->socid]++; - } } else { $lineid = 0; $error++; @@ -1734,14 +1732,6 @@ if (!empty($arrayfields['total_mark_rate']['checked'])) { print ''; } -// Extra fields -include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; - -// Fields from hook -$parameters = array('arrayfields' => $arrayfields); -$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook -print $hookmanager->resPrint; - // Date creation if (!empty($arrayfields['c.datec']['checked'])) { print ''; @@ -1785,17 +1775,28 @@ if (!empty($arrayfields['shippable']['checked'])) { } print ''; } + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields' => $arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + // Status billed if (!empty($arrayfields['c.facture']['checked'])) { print ''; print $form->selectyesno('search_billed', $search_billed, 1, 0, 1, 1); print ''; } + // Import key if (!empty($arrayfields['c.import_key']['checked'])) { print ''; print ''; } + // Status if (!empty($arrayfields['c.fk_statut']['checked'])) { print ''; @@ -1970,13 +1971,6 @@ if (!empty($arrayfields['total_mark_rate']['checked'])) { $totalarray['nbfield']++; } -// Extra fields -include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; - -// Hook fields -$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray); -$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook -print $hookmanager->resPrint; if (!empty($arrayfields['c.datec']['checked'])) { print_liste_field_titre($arrayfields['c.datec']['label'], $_SERVER["PHP_SELF"], "c.date_creation", "", $param, '', $sortfield, $sortorder, 'center nowrap '); $totalarray['nbfield']++; @@ -2001,6 +1995,14 @@ if (!empty($arrayfields['shippable']['checked'])) { print_liste_field_titre($arrayfields['shippable']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center '); $totalarray['nbfield']++; } +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; + +// Hook fields +$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + if (!empty($arrayfields['c.facture']['checked'])) { print_liste_field_titre($arrayfields['c.facture']['label'], $_SERVER["PHP_SELF"], 'c.facture', '', $param, '', $sortfield, $sortorder, 'center '); $totalarray['nbfield']++; @@ -2577,13 +2579,6 @@ while ($i < $imaxinloop) { } } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields' => $arrayfields, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation if (!empty($arrayfields['c.datec']['checked'])) { print ''; @@ -2740,6 +2735,13 @@ while ($i < $imaxinloop) { } } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields' => $arrayfields, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Billed if (!empty($arrayfields['c.facture']['checked'])) { print ''; diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index a05b8dfd965..94576ab0ebc 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -161,7 +161,7 @@ class BankAccounts extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $account->context['caller'] = $request_data['caller']; + $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } @@ -343,7 +343,7 @@ class BankAccounts extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $account->context['caller'] = $request_data['caller']; + $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 40abcfbca07..80126d347b6 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -146,7 +146,7 @@ class Invoices extends DolibarrApi $this->invoice->remaintopay = price2num($this->invoice->total_ttc - $this->invoice->totalpaid - $this->invoice->totalcreditnotes - $this->invoice->totaldeposits, 'MT'); if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // Add external contacts ids @@ -300,11 +300,11 @@ class Invoices extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->invoice->context['caller'] = $request_data['caller']; + $this->invoice->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->invoice->$field = $value; + $this->invoice->$field = $this->_checkValForAPI($field, $value, $this->invoice); } if (!array_key_exists('date', $request_data)) { $this->invoice->date = dol_now(); @@ -426,7 +426,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->invoice->getLinesArray(); $result = array(); @@ -462,7 +462,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -538,7 +538,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('invoice', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->add_contact($contactid, $type, 'external'); @@ -582,7 +582,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('invoice', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $contacts = $this->invoice->liste_contact(); @@ -624,7 +624,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->fetch($id); @@ -659,7 +659,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { @@ -668,11 +668,17 @@ class Invoices extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->invoice->context['caller'] = $request_data['caller']; + $this->invoice->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); + continue; + } + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $this->invoice->array_options[$index] = $this->_checkValForAPI($field, $val, $this->invoice); + } continue; } - $this->invoice->$field = $value; + $this->invoice->$field = $this->_checkValForAPI($field, $value, $this->invoice); // If cond reglement => update date lim reglement if ($field == 'cond_reglement_id') { @@ -711,7 +717,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->delete(DolibarrApiAccess::$user); @@ -764,7 +770,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -851,7 +857,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->add_contact($fk_socpeople, $type_contact, $source, $notrigger); @@ -865,7 +871,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->invoice); @@ -899,7 +905,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->setDraft(DolibarrApiAccess::$user, $idwarehouse); @@ -916,7 +922,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->invoice); @@ -951,7 +957,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->validate(DolibarrApiAccess::$user, $force_number, $idwarehouse, $notrigger); @@ -968,7 +974,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // copy from order @@ -1004,7 +1010,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->setPaid(DolibarrApiAccess::$user, $close_code, $close_note); @@ -1022,7 +1028,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->invoice); @@ -1053,7 +1059,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->setUnpaid(DolibarrApiAccess::$user); @@ -1071,7 +1077,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->invoice); @@ -1099,7 +1105,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $discountcheck = new DiscountAbsolute($this->db); @@ -1142,7 +1148,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } if ($this->invoice->paye) { @@ -1313,7 +1319,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->fetch($id); @@ -1360,7 +1366,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $discount = new DiscountAbsolute($this->db); $result = $discount->fetch($discountid); @@ -1399,7 +1405,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facture', $id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->invoice->fetch($id); @@ -1811,7 +1817,7 @@ class Invoices extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('facturerec', $this->template_invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // Add external contacts ids diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 710cf3edaab..9f3f554e229 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -221,7 +221,7 @@ class Facture extends CommonInvoice public $tab_next_situation_invoice = array(); /** - * @var Facture object oldcopy + * @var static object oldcopy */ public $oldcopy; diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 2371f6ff59a..0b0b394ace7 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -6,6 +6,7 @@ * Copyright (C) 2010-2014 Juanjo Menent * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2018-2024 Frédéric France + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,7 +65,7 @@ if ($type == 'bank-transfer') { // Load object if ($id > 0 || !empty($ref)) { $ret = $object->fetch($id, $ref); - $isdraft = (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); + $isdraft = (($object->status == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); if ($ret > 0) { $object->fetch_thirdparty(); } @@ -146,7 +147,7 @@ if (empty($reshook)) { } else { // We refresh object data $ret = $object->fetch($id, $ref); - $isdraft = (($object->statut == Facture::STATUS_DRAFT) ? 1 : 0); + $isdraft = (($object->status == Facture::STATUS_DRAFT) ? 1 : 0); if ($ret > 0) { $object->fetch_thirdparty(); } @@ -161,7 +162,7 @@ if (empty($reshook)) { } else { // We refresh object data $ret = $object->fetch($id, $ref); - $isdraft = (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); + $isdraft = (($object->status == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); if ($ret > 0) { $object->fetch_thirdparty(); } @@ -280,7 +281,7 @@ if ($object->id > 0) { //$resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT); $resteapayer = price2num($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT'); - if ($object->paye) { + if ($object->paid) { $resteapayer = 0; } $resteapayeraffiche = $resteapayer; @@ -755,7 +756,7 @@ if ($object->id > 0) { } // Add a transfer request - if ($object->statut > $object::STATUS_DRAFT && $object->paye == 0 && $num == 0) { + if ($object->status > $object::STATUS_DRAFT && $object->paid == 0 && $num == 0) { if ($resteapayer > 0) { if ($user_perms) { $remaintopaylesspendingdebit = $resteapayer - $pending; @@ -794,7 +795,7 @@ if ($object->id > 0) { } } else { if ($num == 0) { - if ($object->statut > $object::STATUS_DRAFT) { + if ($object->status > $object::STATUS_DRAFT) { print ''.$buttonlabel.''; } else { print ''.$buttonlabel.''; diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index 59fae4217d6..0d20375bcb5 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -11,6 +11,7 @@ * Copyright (C) 2020 Josep Lluís Amador * Copyright (C) 2021-2024 Frédéric France * Copyright (C) 2024 Rafael San José + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -339,7 +340,9 @@ if ((isModEnabled('fournisseur') && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMO $facstatic->total_tva = $obj->total_tva; $facstatic->total_ttc = $obj->total_ttc; $facstatic->statut = $obj->status; + $facstatic->status = $obj->status; $facstatic->paye = $obj->paye; + $facstatic->paid = $obj->paye; $facstatic->type = $obj->type; $facstatic->ref_supplier = $obj->ref_supplier; diff --git a/htdocs/compta/paymentbybanktransfer/index.php b/htdocs/compta/paymentbybanktransfer/index.php index 9b42490727d..1135ff97b42 100644 --- a/htdocs/compta/paymentbybanktransfer/index.php +++ b/htdocs/compta/paymentbybanktransfer/index.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2013 Florian Henry + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -159,6 +160,7 @@ if (isModEnabled('supplier_invoice')) { $invoicestatic->status = $obj->fk_statut; $invoicestatic->statut = $obj->fk_statut; // For backward compatibility $invoicestatic->paye = $obj->paye; + $invoicestatic->paid = $obj->paye; $invoicestatic->type = $obj->type; $invoicestatic->date = $db->jdate($obj->datef); $invoicestatic->date_echeance = $db->jdate($obj->date_lim_reglement); diff --git a/htdocs/contact/agenda.php b/htdocs/contact/agenda.php index 2c1a0d2ab99..5ef2652268c 100644 --- a/htdocs/contact/agenda.php +++ b/htdocs/contact/agenda.php @@ -144,7 +144,7 @@ if (empty($reshook)) { $form = new Form($db); -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +$title = $langs->trans("ContactEvents"); if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/contactnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->lastname) { $title = $object->lastname; } diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 16087378bf2..1e0e14dbbc4 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -574,7 +574,6 @@ if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/contactnameonly/', get $title = $object->lastname; } $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("NewContact") : $langs->trans("NewContactAddress")); llxHeader('', $title, $help_url); diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index ac7c96194cb..833919df82d 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -337,7 +337,7 @@ class Contact extends CommonObject /** * Old copy - * @var Contact + * @var static */ public $oldcopy; // To contains a clone of this when we need to save old properties of object diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index 66067b00e6e..158229e620a 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -111,7 +111,7 @@ $formother = new FormOther($db); $productstatic = new Product($db); $objsoc = new Societe($db); -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +$title = $langs->trans("ContactRelatedItems"); $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; llxHeader('', $title, $help_url); diff --git a/htdocs/contact/document.php b/htdocs/contact/document.php index c4b216d2679..efc55ac0e5b 100644 --- a/htdocs/contact/document.php +++ b/htdocs/contact/document.php @@ -110,7 +110,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; $form = new Form($db); -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +$title = $langs->trans("ContactLinkedFiles"); if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/contactnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->lastname) { $title = $object->lastname; } diff --git a/htdocs/contact/note.php b/htdocs/contact/note.php index 1f7a328e614..1f956e94821 100644 --- a/htdocs/contact/note.php +++ b/htdocs/contact/note.php @@ -78,7 +78,7 @@ if (empty($reshook)) { $now = dol_now(); -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +$title = $langs->trans("ContactNotes"); $form = new Form($db); diff --git a/htdocs/contact/perso.php b/htdocs/contact/perso.php index 90028857f99..0661a80b685 100644 --- a/htdocs/contact/perso.php +++ b/htdocs/contact/perso.php @@ -3,6 +3,7 @@ * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2018-2021 Frédéric France + * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -119,7 +120,7 @@ if ($action == 'update' && !GETPOST("cancel") && $user->hasRight('societe', 'con $now = dol_now(); -$title = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +$title = $langs->trans("ContactPersonalData"); if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/contactnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->lastname) { $title = $object->lastname; } @@ -294,8 +295,8 @@ if ($action == 'edit') { print '   '; //var_dump($birthdatearray); - $ageyear = convertSecondToTime($now - $object->birthday, 'year') - 1970; - $agemonth = convertSecondToTime($now - $object->birthday, 'month') - 1; + $ageyear = (int) convertSecondToTime($now - $object->birthday, 'year') - 1970; + $agemonth = (int) convertSecondToTime($now - $object->birthday, 'month') - 1; if ($ageyear >= 2) { print '('.$ageyear.' '.$langs->trans("DurationYears").')'; } elseif ($agemonth >= 2) { diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index cee27733140..c599ad6d82e 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -75,7 +75,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->contract->fetchObjectLinked(); @@ -192,11 +192,11 @@ class Contracts extends DolibarrApi foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->contract->context['caller'] = $request_data['caller']; + $this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); continue; } - $this->contract->$field = $value; + $this->contract->$field = $this->_checkValForAPI($field, $value, $this->contract); } /*if (isset($request_data["lines"])) { $lines = array(); @@ -233,7 +233,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $this->contract->getLinesArray(); $result = array(); @@ -265,7 +265,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -323,7 +323,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $request_data = (object) $request_data; @@ -386,7 +386,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, $datestart, $dateend, $comment); @@ -424,7 +424,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, $datestart, $comment); @@ -464,7 +464,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } // TODO Check the lineid $lineid is a line of object @@ -496,7 +496,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach ($request_data as $field => $value) { if ($field == 'id') { @@ -504,11 +504,17 @@ class Contracts extends DolibarrApi } if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller - $this->contract->context['caller'] = $request_data['caller']; + $this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09'); + continue; + } + if ($field == 'array_options' && is_array($value)) { + foreach ($value as $index => $val) { + $this->contract->array_options[$index] = $this->_checkValForAPI($field, $val, $this->contract);; + } continue; } - $this->contract->$field = $value; + $this->contract->$field = $this->_checkValForAPI($field, $value, $this->contract); } if ($this->contract->update(DolibarrApiAccess::$user) > 0) { @@ -624,7 +630,7 @@ class Contracts extends DolibarrApi } if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } $result = $this->contract->closeAll(DolibarrApiAccess::$user, $notrigger); diff --git a/htdocs/core/boxes/box_factures_fourn_imp.php b/htdocs/core/boxes/box_factures_fourn_imp.php index 777cea5a2ed..7806477433a 100644 --- a/htdocs/core/boxes/box_factures_fourn_imp.php +++ b/htdocs/core/boxes/box_factures_fourn_imp.php @@ -138,6 +138,7 @@ class box_factures_fourn_imp extends ModeleBoxes //$alreadypaid = $facturestatic->getSommePaiement(); $facturestatic->paye = $objp->paye; + $facturestatic->paid = $objp->paye; $facturestatic->alreadypaid = $objp->am; $thirdpartystatic->id = $objp->socid; diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 9d73998e151..323b544c9ba 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -52,7 +52,7 @@ class CMailFile public $subject; public $addr_from; // From: Label and EMail of sender (must include '<>'). For example '' or 'John Doe ' or ''). Note that with gmail smtps, value here is forced by google to account (but not the reply-to). // Sender: Who send the email ("Sender" has sent emails on behalf of "From"). - // Use it when the "From" is an email of a domain that is a SPF protected domain, and sending smtp server is not this domain. In such case, add Sender field with an email of the protected domain. + // Use it when the "From" is an email of a domain that is a SPF protected domain, and the sending smtp server is not this domain. In such case, add Sender field with an email of the protected domain. // Return-Path: Email where to send bounds. public $reply_to; // Reply-To: Email where to send replies from mailer software (mailer use From if reply-to not defined, Gmail use gmail account if reply-to not defined) public $errors_to; // Errors-To: Email where to send errors. @@ -114,7 +114,19 @@ class CMailFile * @var string Message-ID of the email to send (generated) */ public $msgid; + + /** + * @var string Value to use in In-reply-to when email is set as an answer of another email (The Msg-Id of received email) + */ + public $in_reply_to; + + /** + * @var string References to add to the email to send (generated from the email we answer) + */ + public $references; + public $headers; + public $message; /** @@ -172,10 +184,12 @@ class CMailFile * @param string $trackid Tracking string (contains type and id of related element) * @param string $moreinheader More in header. $moreinheader must contains the "\r\n" at end of each line * @param string $sendcontext 'standard', 'emailing', 'ticket', 'password', ... (used to define which sending mode and parameters to use) - * @param string $replyto Reply-to email (will be set to same value than From by default if not provided) + * @param string $replyto Reply-to email (will be set to the same value than From by default if not provided) * @param string $upload_dir_tmp Temporary directory (used to convert images embedded as img src=data:image) + * @param string $in_reply_to Message-ID of the message we reply Token + * @param string $references String with list of Message-ID of the thread ('<123> <456> ...') */ - public function __construct($subject, $to, $from, $msg, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = 0, $errors_to = '', $css = '', $trackid = '', $moreinheader = '', $sendcontext = 'standard', $replyto = '', $upload_dir_tmp = '') + public function __construct($subject, $to, $from, $msg, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = 0, $errors_to = '', $css = '', $trackid = '', $moreinheader = '', $sendcontext = 'standard', $replyto = '', $upload_dir_tmp = '', $in_reply_to = '', $references = '') { global $conf, $dolibarr_main_data_root, $user; @@ -428,6 +442,8 @@ class CMailFile $this->reply_to = dol_sanitizeEmail($replyto); $this->errors_to = dol_sanitizeEmail($errors_to); $this->trackid = $trackid; + $this->in_reply_to = $in_reply_to; + $this->references = $references; // Set arrays with attached files info $this->filename_list = $filename_list; $this->mimetype_list = $mimetype_list; @@ -462,7 +478,7 @@ class CMailFile $text_body = ""; $files_encoded = ""; - // Define smtp_headers (this also set ->msgid) + // Define smtp_headers (this also set SMTP headers from ->msgid, ->in_reply_to and ->references) $smtp_headers = $this->write_smtpheaders(); if (!empty($moreinheader)) { $smtp_headers .= $moreinheader; // $moreinheader contains the \r\n @@ -516,15 +532,23 @@ class CMailFile $smtps->setSubject($subjecttouse); $smtps->setTO($this->getValidAddress($this->addr_to, 0, 1)); $smtps->setFrom($this->getValidAddress($this->addr_from, 0, 1)); - $smtps->setTrackId($this->trackid); $smtps->setReplyTo($this->getValidAddress($this->reply_to, 0, 1)); - //X-Dolibarr-TRACKID is generated inside the smtps->getHeader + $smtps->setTrackId($this->trackid); + + if (!empty($this->in_reply_to)) { + $smtps->setInReplyTo($this->in_reply_to); + } + if (!empty($this->references)) { + $smtps->setReferences($this->references); + } if (!empty($moreinheader)) { $smtps->setMoreInHeader($moreinheader); } + //X-Dolibarr-TRACKID, In-Reply-To, References and $moreinheader will be added to header inside the smtps->getHeader + if (!empty($this->html)) { if (!empty($css)) { $this->css = $css; @@ -592,8 +616,14 @@ class CMailFile $msgid = $headers->get('Message-ID'); $msgid->setId($headerID); + // Add 'In-Reply-To:' header + if (!empty($this->in_reply_to)) { + $headers->addIdHeader('In-Reply-To', $this->in_reply_to); + } // Add 'References:' header - //$headers->addIdHeader('References', $headerID); + if (!empty($this->references)) { + $headers->addIdHeader('References', $this->references); + } if (!empty($moreinheader)) { $moreinheaderarray = preg_split('/[\r\n]+/', $moreinheader); @@ -1543,16 +1573,23 @@ class CMailFile $trackid = $this->trackid; if ($trackid) { - // References is kept in response and Message-ID is returned into In-Reply-To: $this->msgid = time().'.phpmail-dolibarr-'.$trackid.'@'.$host; $out .= 'Message-ID: <'.$this->msgid.">".$this->eol2; // Uppercase seems replaced by phpmail - //$out .= 'References: <'.$this->msgid.">".$this->eol2; $out .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host.$this->eol2; } else { $this->msgid = time().'.phpmail@'.$host; $out .= 'Message-ID: <'.$this->msgid.">".$this->eol2; } + // Add 'In-Reply-To:' header with the Message-Id we answer + if (!empty($this->in_reply_to)) { + $out .= 'In-Reply-To: <'.$this->in_reply_to.'>'.$this->eol2; + } + // Add 'References:' header with list of all Message-ID in thread history + if (!empty($this->references)) { + $out .= 'References: '.$this->references.$this->eol2; + } + if (!empty($_SERVER['REMOTE_ADDR'])) { $out .= "X-RemoteAddr: ".$_SERVER['REMOTE_ADDR'].$this->eol2; } diff --git a/htdocs/core/class/comment.class.php b/htdocs/core/class/comment.class.php index f60f5c44183..9ffa0d60a1e 100644 --- a/htdocs/core/class/comment.class.php +++ b/htdocs/core/class/comment.class.php @@ -77,7 +77,7 @@ class Comment extends CommonObject public $comments = array(); /** - * @var Comment Object oldcopy + * @var static Object oldcopy */ public $oldcopy; diff --git a/htdocs/core/class/discount.class.php b/htdocs/core/class/discount.class.php index d51210bff34..29e663f4e27 100644 --- a/htdocs/core/class/discount.class.php +++ b/htdocs/core/class/discount.class.php @@ -303,7 +303,7 @@ class DiscountAbsolute extends CommonObject * Delete object in database. If fk_facture_source is defined, we delete all family with same fk_facture_source. If not, only with id is removed * * @param User $user Object of user asking to delete - * @return int<-1,1> Return integer <0 if KO, >0 if OK + * @return int<-2,1> Return integer <0 if KO, >0 if OK */ public function delete($user) { @@ -427,7 +427,7 @@ class DiscountAbsolute extends CommonObject * * @param int $rowidline Invoice line id (To use discount into invoice lines) * @param int $rowidinvoice Invoice id (To use discount as a credit note to reduce payment of invoice) - * @return int<-1,1> Return integer <0 if KO, >0 if OK + * @return int<-3,1> Return integer <0 if KO, >0 if OK */ public function link_to_invoice($rowidline, $rowidinvoice) { @@ -483,7 +483,7 @@ class DiscountAbsolute extends CommonObject * Link the discount to a particular invoice line or a particular invoice. * Do not call this if discount is linked to a reconcialiated invoice * - * @return int<-1,1> Return integer <0 if KO, >0 if OK + * @return int<-3,1> Return integer <0 if KO, >0 if OK */ public function unlink_invoice() { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 410dfb85bca..337f2366b1f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -70,7 +70,9 @@ class Form public $errors = array(); // Some properties used to return data by some methods + /** @var array */ public $result; + /** @var int */ public $num; // Cache arrays @@ -213,7 +215,7 @@ class Form * @param string $formatfunc Call a specific method of $object->$formatfunc to output field in view mode (For example: 'dol_print_email') * @param string $paramid Key of parameter for id ('id', 'socid') * @param string $gm 'auto' or 'tzuser' or 'tzuserrel' or 'tzserver' (when $typeofdata is a date) - * @param array $moreoptions Array with more options. For example array('addnowlink'=>1), array('valuealreadyhtmlescaped'=>1) + * @param array $moreoptions Array with more options. For example array('addnowlink'=>1), array('valuealreadyhtmlescaped'=>1) * @param string $editaction [=''] use GETPOST default action or set action to edit mode * @return string HTML edit field */ @@ -408,7 +410,7 @@ class Form * Output edit in place form * * @param string $fieldname Name of the field - * @param object $object Object + * @param CommonObject $object Object * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) * @param string $check Same coe than $check parameter of GETPOST() @@ -814,7 +816,7 @@ class Form * Generate select HTML to choose massaction * * @param string $selected Value auto selected when at least one record is selected. Not a preselected value. Use '0' by default. - * @param array $arrayofaction array('code'=>'label', ...). The code is the key stored into the GETPOST('massaction') when submitting action. + * @param array $arrayofaction array('code'=>'label', ...). The code is the key stored into the GETPOST('massaction') when submitting action. * @param int $alwaysvisible 1=select button always visible * @param string $name Name for massaction * @param string $cssclass CSS class used to check for select @@ -927,10 +929,10 @@ class Form * @param string $morecss More css class * @param string $usecodeaskey ''=Use id as key (default), 'code3'=Use code on 3 alpha as key, 'code2"=Use code on 2 alpha as key * @param int<0,1>|string $showempty Show empty choice - * @param int $disablefavorites 1=Disable favorites, - * @param int $addspecialentries 1=Add dedicated entries for group of countries (like 'European Economic Community', ...) - * @param array $exclude_country_code Array of country code (iso2) to exclude - * @param int $hideflags Hide flags + * @param int<0,1> $disablefavorites 1=Disable favorites, + * @param int<0,1> $addspecialentries 1=Add dedicated entries for group of countries (like 'European Economic Community', ...) + * @param string[] $exclude_country_code Array of country code (iso2) to exclude + * @param int<0,1> $hideflags Hide flags * @return string HTML string with select */ public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0) @@ -1061,9 +1063,9 @@ class Form * @param string $page Defined the form action * @param string $htmlname Name of html select object * @param string $htmloption Options html on select object - * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification) - * @param array $events Event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) - * @param int $disableautocomplete Disable autocomplete + * @param int<0,1> $forcecombo Force to load all values and output a standard combobox (with no beautification) + * @param array}> $events Event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param int<0,1> $disableautocomplete Disable autocomplete * @return string HTML string with select and input */ public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0) @@ -1306,16 +1308,16 @@ class Form * @param string|int<1,1> $showempty Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty') * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification) - * @param array $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param array}> $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param int $limit Maximum number of elements * @param string $morecss Add more css styles to the SELECT component * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $selected_input_value Value of preselected input text (for use with ajax) - * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) - * @param array $ajaxoptions Options for ajax_autocompleter + * @param int<0,3> $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) + * @param array $ajaxoptions Options for ajax_autocompleter * @param bool $multiple add [] in the name of element and add 'multiple' attribute (not working with ajax_autocompleter) - * @param array $excludeids Exclude IDs from the select combo - * @param int $showcode Show code + * @param string[] $excludeids Exclude IDs from the select combo + * @param int<0,1> $showcode Show code * @return string HTML string with select box for thirdparty. */ public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0) @@ -1384,16 +1386,16 @@ class Form * @param string|int<0,1> $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') * @param int<0,1> $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to use standard HTML select component without beautification - * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param array}> $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param string $filterkey Filter on key value - * @param int $outputmode 0=HTML select string, 1=Array + * @param int<0,1> $outputmode 0=HTML select string, 1=Array * @param int $limit Limit number of answers * @param string $morecss Add more css styles to the SELECT component * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param bool $multiple add [] in the name of element and add 'multiple' attribute - * @param array $excludeids Exclude IDs from the select combo - * @param int $showcode Show code in list - * @return array|string HTML string with + * @param string[] $excludeids Exclude IDs from the select combo + * @param int<0,1> $showcode Show code in list + * @return array|string HTML string with */ public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0) { @@ -1727,7 +1729,7 @@ class Form * @param string $morecss Add more class to class style * @param integer $showsoc Add company into label * @param int $forcecombo Force to use combo box - * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param array}> $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param bool $options_only Return options only (for ajax treatment) * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $htmlid Html id to use instead of htmlname @@ -1758,7 +1760,7 @@ class Form * @param bool $options_only Return options only (for ajax treatment) * @param integer $showsoc Add company into label * @param int $forcecombo Force to use combo box (so no ajax beautify effect) - * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param array}> $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $htmlid Html id to use instead of htmlname * @param bool $multiple add [] in the name of element and add 'multiple' attribute @@ -1970,11 +1972,11 @@ class Form * * @param string $selected Id user preselected * @param string $htmlname Field name in form - * @param int $show_empty 0=liste sans valeur nulle, 1=ajoute valeur inconnue - * @param array $exclude Array list of users id to exclude - * @param int $disabled If select list must be disabled - * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me - * @param array|int $enableonly Array list of users id to be enabled. All other must be disabled + * @param int<0,1> $show_empty 0=liste sans valeur nulle, 1=ajoute valeur inconnue + * @param int[] $exclude Array list of users id to exclude + * @param int<0,1> $disabled If select list must be disabled + * @param int[]|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me + * @param int[]|int $enableonly Array list of users id to be enabled. All other must be disabled * @param string $force_entity '0' or Ids of environment to force * @return void * @deprecated Use select_dolusers instead @@ -1991,25 +1993,25 @@ class Form /** * Return select list of users * - * @param string|int $selected User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1 or '', keep unselected (if empty is allowed) + * @param string|int|User $selected User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1 or '', keep unselected (if empty is allowed) * @param string $htmlname Field name in form - * @param int|string $show_empty 0=list with no empty value, 1=add also an empty value into list - * @param array|null $exclude Array list of users id to exclude + * @param int<0,1>|string $show_empty 0=list with no empty value, 1=add also an empty value into list + * @param int[]|null $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled - * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me + * @param int[]|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me * @param array|string $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled * @param string $force_entity '0' or list of Ids of environment to force separated by a coma * @param int $maxlength Maximum length of string into list (0=no limit) - * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status + * @param int<-1,1> $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request (Example: 'employee = 1'). This value must not come from user input. * @param integer $show_every 0=default list, 1=add also a value "Everybody" at beginning of list * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty. * @param string $morecss More css - * @param int $notdisabled Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on). - * @param int $outputmode 0=HTML select string, 1=Array + * @param int<0,1> $notdisabled Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on). + * @param int<0,2> $outputmode 0=HTML select string, 1=Array * @param bool $multiple add [] in the name of element and add 'multiple' attribute - * @param int $forcecombo Force the component to be a simple combo box without ajax - * @return array|string HTML select string + * @param int<0,1> $forcecombo Force the component to be a simple combo box without ajax + * @return string|array HTML select string * @see select_dolgroups() */ public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0) @@ -2205,7 +2207,7 @@ class Form if (!empty($disableline)) { $out .= ' disabled'; } - if ((is_object($selected) && $selected->id == $obj->rowid) || (!is_object($selected) && in_array($obj->rowid, $selected))) { + if ((!empty($selected[0]) && is_object($selected[0])) ? $selected[0]->id == $obj->rowid : in_array($obj->rowid, $selected)) { $out .= ' selected'; } $out .= ' data-html="'; @@ -2265,19 +2267,19 @@ class Form * * @param string $action Value for $action * @param string $htmlname Field name in form - * @param int $show_empty 0=list without the empty value, 1=add empty value - * @param array $exclude Array list of users id to exclude - * @param int $disabled If select list must be disabled - * @param array $include Array list of users id to include or 'hierarchy' to have only supervised users - * @param array|int $enableonly Array list of users id to be enabled. All other must be disabled + * @param int<0,1> $show_empty 0=list without the empty value, 1=add empty value + * @param int[] $exclude Array list of users id to exclude + * @param int<0,1> $disabled If select list must be disabled + * @param int[]|string $include Array list of users id to include or 'hierarchy' to have only supervised users + * @param int[]|int $enableonly Array list of users id to be enabled. All other must be disabled * @param string $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) - * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status + * @param int<0,1> $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request * @param int $showproperties Show properties of each attendees - * @param array $listofuserid Array with properties of each user - * @param array $listofcontactid Array with properties of each contact - * @param array $listofotherid Array with properties of each other contact + * @param int[] $listofuserid Array with properties of each user + * @param int[] $listofcontactid Array with properties of each contact + * @param int[] $listofotherid Array with properties of each other contact * @return string HTML select string * @see select_dolgroups() */ @@ -2289,9 +2291,13 @@ class Form $userstatic = new User($this->db); $out = ''; - $assignedtouser = array(); if (!empty($_SESSION['assignedtouser'])) { $assignedtouser = json_decode($_SESSION['assignedtouser'], true); + if (!is_array($assignedtouser)) { + $assignedtouser = array(); + } + } else { + $assignedtouser = array(); } $nbassignetouser = count($assignedtouser); @@ -2360,16 +2366,16 @@ class Form * @param string $action Value for $action * @param string $htmlname Field name in form * @param int $show_empty 0=list without the empty value, 1=add empty value - * @param array $exclude Array list of users id to exclude - * @param int $disabled If select list must be disabled - * @param array $include Array list of users id to include or 'hierarchy' to have only supervised users - * @param array $enableonly Array list of users id to be enabled. All other must be disabled + * @param int[] $exclude Array list of users id to exclude + * @param int<0,1> $disabled If select list must be disabled + * @param int[]|string $include Array list of users id to include or 'hierarchy' to have only supervised users + * @param int[] $enableonly Array list of users id to be enabled. All other must be disabled * @param string $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) - * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status + * @param int<-1,1> $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request * @param int $showproperties Show properties of each attendees - * @param array $listofresourceid Array with properties of each resource + * @param array}> $listofresourceid Array with properties of each resource * @return string HTML select string */ public function select_dolresources_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofresourceid = array()) @@ -2383,9 +2389,13 @@ class Form $resourcestatic = new Dolresource($this->db); $out = ''; - $assignedtoresource = array(); if (!empty($_SESSION['assignedtoresource'])) { $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true); + if (!is_array($assignedtoresource)) { + $assignedtoresource = array(); + } + } else { + $assignedtoresource = array(); } $nbassignetoresource = count($assignedtoresource); @@ -2433,7 +2443,7 @@ class Form $events = array(); $out .= img_picto('', 'resource', 'class="pictofixedwidth"'); - $out .= $formresources->select_resource_list(0, $htmlname, [], 1, 1, 0, $events, '', 2, 0); + $out .= $formresources->select_resource_list(0, $htmlname, [], 1, 1, 0, $events, array(), 2, 0); //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter); $out .= ' '; $out .= '
'; @@ -2456,19 +2466,19 @@ class Form * @param int $finished 2=all, 1=finished, 0=raw material * @param string $selected_input_value Value of preselected input text (for use with ajax) * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) - * @param array $ajaxoptions Options for ajax_autocompleter + * @param array $ajaxoptions Options for ajax_autocompleter * @param int $socid Thirdparty Id (to get also price dedicated to this customer) * @param string|int<0,1> $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. * @param int $forcecombo Force to use combo box * @param string $morecss Add more css on select - * @param int $hidepriceinlabel 1=Hide prices in label + * @param int<0,1> $hidepriceinlabel 1=Hide prices in label * @param string $warehouseStatus Warehouse status filter to count the quantity in stock. Following comma separated filter options can be used * 'warehouseopen' = count products from open warehouses, * 'warehouseclosed' = count products from closed warehouses, * 'warehouseinternal' = count products from warehouses for internal correct/transfer only - * @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...]) - * @param int $nooutput No print if 1, return the output into a string - * @param int $status_purchase Purchase status: -1=No filter on purchase status, 0=Products not on purchase, 1=Products on purchase + * @param ?mixed[] $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...]) + * @param int<0,1> $nooutput No print if 1, return the output into a string + * @param int<-1,1> $status_purchase Purchase status: -1=No filter on purchase status, 0=Products not on purchase, 1=Products on purchase * @return void|string */ public function select_produits($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1) @@ -2618,17 +2628,17 @@ class Form /** * Return list of BOM for customer in Ajax if Ajax activated or go to select_produits_list * - * @param string $selected Preselected BOM id - * @param string $htmlname Name of HTML select field (must be unique in page). - * @param int $limit Limit on number of returned lines - * @param int $status Sell status -1=Return all bom, 0=Draft BOM, 1=Validated BOM - * @param int $type type of the BOM (-1=Return all BOM, 0=Return disassemble BOM, 1=Return manufacturing BOM) + * @param string $selected Preselected BOM id + * @param string $htmlname Name of HTML select field (must be unique in page). + * @param int $limit Limit on number of returned lines + * @param int $status Sell status -1=Return all bom, 0=Draft BOM, 1=Validated BOM + * @param int $type type of the BOM (-1=Return all BOM, 0=Return disassemble BOM, 1=Return manufacturing BOM) * @param string|int<0,1> $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. - * @param string $morecss Add more css on select - * @param string $nooutput No print, return the output into a string - * @param int $forcecombo Force to use combo box - * @param array $TProducts Add filter on a defined product - * @return void|string + * @param string $morecss Add more css on select + * @param string $nooutput No print, return the output into a string + * @param int $forcecombo Force to use combo box + * @param string[] $TProducts Add filter on a defined product + * @return void|string */ public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = []) { @@ -2952,7 +2962,7 @@ class Form $num = $this->db->num_rows($result); - $events = null; + $events = array(); if (!$forcecombo) { include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; @@ -3036,7 +3046,7 @@ class Form $objp->price = $price_result; $objp->unitprice = $price_result; //Calculate the VAT - $objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100)); + $objp->price_ttc = (float) price2num($objp->price) * (1 + ($objp->tva_tx / 100)); $objp->price_ttc = price2num($objp->price_ttc, 'MU'); } } @@ -3073,14 +3083,14 @@ class Form * This define value for &$opt and &$optJson. * This function is called by select_produits_list(). * - * @param object $objp Resultset of fetch + * @param stdClass $objp Resultset of fetch * @param string $opt Option (var used for returned value in string option format) - * @param array $optJson Option (var used for returned value in json format) + * @param array{key:string,value:string,label:string,label2:string,desc:string,type:string,price_ht:string,price_ttc:string,price_ht_locale:string,price_ttc_locale:string,pricebasetype:string,tva_tx:string,default_vat_code:string,qty:string,discount:string,duration_value:string,duration_unit:string,pbq:string,labeltrans:string,desctrans:string,ref_customer:string} $optJson Option (var used for returned value in json format) * @param int $price_level Price level * @param int $selected Preselected value - * @param int $hidepriceinlabel Hide price in label + * @param int<0,1> $hidepriceinlabel Hide price in label * @param string $filterkey Filter key to highlight - * @param int $novirtualstock Do not load virtual stock, even if slow option STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO is on. + * @param int<0,1> $novirtualstock Do not load virtual stock, even if slow option STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO is on. * @return void */ protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0) @@ -3416,9 +3426,9 @@ class Form * @param string $htmlname Name of HTML Select * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param string $filtre For a SQL filter - * @param array $ajaxoptions Options for ajax_autocompleter - * @param int $hidelabel Hide label (0=no, 1=yes) - * @param int $alsoproductwithnosupplierprice 1=Add also product without supplier prices + * @param array $ajaxoptions Options for ajax_autocompleter + * @param int<0,1> $hidelabel Hide label (0=no, 1=yes) + * @param int<0,1> $alsoproductwithnosupplierprice 1=Add also product without supplier prices * @param string $morecss More CSS * @param string $placeholder Placeholder * @return void @@ -3833,7 +3843,7 @@ class Form 'type' => $outtype, 'duration_value' => $outdurationvalue, 'duration_unit' => $outdurationunit, - 'disabled' => (empty($objp->idprodfournprice) ? true : false), + 'disabled' => empty($objp->idprodfournprice), 'description' => $objp->description ); if (isModEnabled('multicurrency')) { @@ -3872,7 +3882,7 @@ class Form 'type' => $outtype, 'duration_value' => $outdurationvalue, 'duration_unit' => $outdurationunit, - 'disabled' => (empty($objp->idprodfournprice) ? true : false), + 'disabled' => empty($objp->idprodfournprice), 'description' => $objp->description ); if (isModEnabled('multicurrency')) { @@ -5094,10 +5104,10 @@ class Form * - int (id of category) * - string (categories ids separated by comma) * - array (list of categories ids) - * @param int $outputmode 0=HTML select string, 1=Array with full label only, 2=Array extended, 3=Array with full picto + label - * @param int $include [=0] Removed or 1=Keep only + * @param int<0,3> $outputmode 0=HTML select string, 1=Array with full label only, 2=Array extended, 3=Array with full picto + label + * @param int<0,1> $include [=0] Removed or 1=Keep only * @param string $morecss More CSS - * @return string|array String list or Array of categories + * @return string|array|array|array String list or Array of categories * @see select_categories() */ public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0, $morecss = '') @@ -5175,6 +5185,7 @@ class Form $output .= "\n"; if ($outputmode == 2) { + // TODO: handle error when $cate_arbo is not an array return $cate_arbo; } elseif ($outputmode == 1) { return $outarray; @@ -5193,7 +5204,7 @@ class Form * @param string $title Title * @param string $question Question * @param string $action Action - * @param array $formquestion An array with forms complementary inputs + * @param array $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) * @param string $selectedchoice "" or "no" or "yes" * @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int $height Force height of box @@ -5224,9 +5235,9 @@ class Form * @param string $title Title * @param string $question Question * @param string $action Action - * @param array|string|null $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) - * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss', - * 'other', 'onecolumn' or 'hidden'... + * @param array}>|string|null $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) + * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss', + * 'other', 'onecolumn' or 'hidden'... * @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0 * @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $height Force height of box (0 = auto) @@ -5434,7 +5445,7 @@ class Form } } // Add name of fields to propagate with the GET when submitting the form with button KO. - if (isset($input['inputko']) && $input['inputko'] == 1) { + if (isset($input['inputko']) && $input['inputko'] == 1 && isset($input['name'])) { array_push($inputko, $input['name']); } } @@ -5448,7 +5459,7 @@ class Form if (!empty($more)) { $formconfirm .= '
' . $more . '
' . "\n"; } - $formconfirm .= ($question ? '
' . img_help('', '') . ' ' . $question . '
' : ''); + $formconfirm .= ($question ? '
' . img_help(0, '') . ' ' . $question . '
' : ''); $formconfirm .= '
' . "\n"; $formconfirm .= "\n\n"; @@ -5877,8 +5888,8 @@ class Form * @param string $page Page * @param string $selected Id of user preselected * @param string $htmlname Name of input html field. If 'none', we just output the user link. - * @param array $exclude List of users id to exclude - * @param array $include List of users id to include + * @param int[] $exclude List of users id to exclude + * @param int[] $include List of users id to include * @return void */ public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array()) @@ -6208,9 +6219,9 @@ class Form * @param string|int<0,1> $showempty Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty') * @param int<0,1> $showtype Show third party type in combolist (customer, prospect or supplier) * @param int<0,1> $forcecombo Force to use combo box - * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param array}> $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param int $nooutput No print output. Return it only. - * @param array $excludeids Exclude IDs from the select combo + * @param int[] $excludeids Exclude IDs from the select combo * @param string $textifnothirdparty Text to show if no thirdparty * @return string HTML output or '' */ @@ -6773,9 +6784,9 @@ class Form * @param int $m 1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty * @param int $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only * @param string $form_name Not used - * @param int $d 1=Show days, month, years - * @param int $addnowlink Add a link "Now", 1 with server time, 2 with local computer time - * @param int $disabled Disable input fields + * @param int<0,1> $d 1=Show days, month, years + * @param int<0,2> $addnowlink Add a link "Now", 1 with server time, 2 with local computer time + * @param int<0,1> $disabled Disable input fields * @param int|string $fullday When a checkbox with id #fullday is checked, hours are set with 00:00 (if value if 'fulldaystart') or 23:59 (if value is 'fulldayend') * @param string $addplusone Add a link "+1 hour". Value must be name of another selectDate field. * @param int|string|array $adddateof Add a link "Date of ..." using the following date. Must be array(array('adddateof'=>..., 'labeladddateof'=>...)) @@ -7223,7 +7234,7 @@ class Form * * @param string $prefix Prefix * @param string $selected Selected duration type - * @param array $excludetypes Array of duration types to exclude. Example array('y', 'm') + * @param string[] $excludetypes Array of duration types to exclude. Example array('y', 'm') * @return string HTML select string */ public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array()) @@ -7325,7 +7336,7 @@ class Form if ($typehour == 'select' || $typehour == 'textselect') { $retstring .= '