diff --git a/dev/tools/phan/config.php b/dev/tools/phan/config.php index 00f9478aed9..d45a1e422c0 100644 --- a/dev/tools/phan/config.php +++ b/dev/tools/phan/config.php @@ -461,7 +461,7 @@ return [ 'PhanPluginUnknownClosureReturnType', // When we use closure (we must avoid), we do not have PHP doc - // 'PhanPluginUnknownArrayMethodParamType', // All fixed, except in api_* + // 'PhanPluginUnknownArrayMethodParamType', // All fixed // 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* // 'PhanUndeclaredGlobalVariable', // Helps identify variables that are not set/defined - add '@phan-var-force TYPE $varname' in tpl or includes to help type the variable // 'PhanPluginUnknownObjectMethodCall', // False positive for some class. Is enabled in config_extended only. diff --git a/dev/tools/phan/config_extended.php b/dev/tools/phan/config_extended.php index 41be1c5f8ad..fa84a395df7 100644 --- a/dev/tools/phan/config_extended.php +++ b/dev/tools/phan/config_extended.php @@ -97,7 +97,7 @@ $config['suppress_issue_types'] = [ 'PhanPluginRedundantAssignment', // Not essential, useless 'PhanPluginDuplicateCatchStatementBody', // Requires PHP7.1 - 50+ occurrences - 'PhanPluginUnknownArrayMethodParamType', // All fixed, except in api_* at this time + // 'PhanPluginUnknownArrayMethodParamType', // All fixed 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* at this time 'PhanTypeSuspiciousNonTraversableForeach', // Reports on `foreach ($object as $key => $value)` which works without php notices, so we ignore it because this is intentional in the code. ]; diff --git a/htdocs/adherents/class/api_members.class.php b/htdocs/adherents/class/api_members.class.php index e78430ffbfd..a08dc6cc2db 100644 --- a/htdocs/adherents/class/api_members.class.php +++ b/htdocs/adherents/class/api_members.class.php @@ -661,6 +661,9 @@ class Members extends DolibarrApi if (!DolibarrApiAccess::$user->hasRight('adherent', 'cotisation', 'creer')) { throw new RestException(403); } + if (is_numeric($start_date) || !is_numeric($end_date) || !is_numeric($amount)) { + throw new RestException(422, 'Malformed data'); + } $member = new Adherent($this->db); $result = $member->fetch($id); @@ -668,7 +671,7 @@ class Members extends DolibarrApi throw new RestException(404, 'member not found'); } - return $member->subscription($start_date, $amount, 0, '', $label, '', '', '', $end_date); + return $member->subscription((int) $start_date, (float) $amount, 0, '', $label, '', '', '', (int) $end_date); } /** diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index f01a6d56538..304a2b690c5 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Laurent Destailleur * Copyright (C) 2023 Ferran Marcet - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -44,7 +44,6 @@ use Luracast\Restler\RestException; /** * Dolibarr API access class - * */ class DolibarrApiAccess implements iAuthenticate { @@ -56,12 +55,12 @@ class DolibarrApiAccess implements iAuthenticate public $db; /** - * @var array $requires role required by API method user / external / admin + * @var array role required by API method user / external / admin */ public static $requires = array('user', 'external', 'admin'); /** - * @var string $role user role + * @var string user role */ public static $role = 'user'; @@ -158,7 +157,7 @@ class DolibarrApiAccess implements iAuthenticate throw new RestException(503, 'Error when fetching user api_key : More than 1 user with this apikey'); } } else { - throw new RestException(503, 'Error when fetching user api_key :'.$this->db->error_msg); + throw new RestException(503, 'Error when fetching user api_key :'.$this->db->error); } if ($login && $stored_key != $api_key) { // This should not happen since we did a search on api_key @@ -248,7 +247,7 @@ class DolibarrApiAccess implements iAuthenticate /** * Verify access * - * @param array $m Properties of method + * @param array{class:array{DolibarrApiAccess:array{properties:array{requires?:bool}}}} $m Properties of method * * @access private * @return bool diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index 71b42aea8a8..e24ed7924b8 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -54,6 +54,8 @@ class Documents extends DolibarrApi * @param string $modulepart Name of module or area concerned by file download ('facture', ...) * @param string $original_file Relative path with filename, relative to modulepart (for example: IN201701-999/IN201701-999.pdf) * @return array List of documents + * @phan-return array{filename:string,content-type:string,filesize:false|int,content:string,encoding:string} + * @phpstan-return array{filename:string,content-type:string,filesize:false|int,content:string,encoding:string} * * @url GET /download * @@ -123,6 +125,8 @@ class Documents extends DolibarrApi * @param string $doctemplate Set here the doc template to use for document generation (If not set, use the default template). * @param string $langcode Language code like 'en_US', 'fr_FR', 'es_ES', ... (If not set, use the default language). * @return array List of documents + * @phan-return array{filename:string,content-type:string,filesize:false|int,content:string,langcode:string,template:?string,encoding:string} + * @phpstan-return array{filename:string,content-type:string,filesize:false|int,content:string,langcode:string,template:?string,encoding:string} * * @url PUT /builddoc * @@ -306,6 +310,8 @@ class Documents extends DolibarrApi * @param string $sortfield Sort criteria ('','fullname','relativename','name','date','size') * @param string $sortorder Sort order ('asc' or 'desc') * @return array Array of documents with path + * @phan-return array> + * @phpstan-return array> * * @url GET / * @@ -621,6 +627,7 @@ class Documents extends DolibarrApi for ($i = 0 ; $i < $count ; $i++) { foreach ($ecmfile->lines as $line) { if ($filearray[$i]['name'] == $line->filename) { + // Next line converts EcmFilesLine properties to array $filearray[$i] = array_merge($filearray[$i], (array) $line); } } @@ -666,7 +673,7 @@ class Documents extends DolibarrApi * @param int $createdirifnotexists Create subdirectories if the doesn't exists (1 by default) * @param int $position Position * @param string $cover Cover info - * @param array $array_options array of options + * @param array $array_options array of options * @return string * * @url POST /upload @@ -791,7 +798,7 @@ class Documents extends DolibarrApi if (is_object($object)) { if ($fetchbyid) { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition - $result = $object->fetch($ref); + $result = $object->fetch((int) $ref); } else { $result = $object->fetch(0, $ref); } @@ -965,7 +972,9 @@ class Documents extends DolibarrApi * * @param string $modulepart Name of module or area concerned by file download ('product', ...) * @param string $original_file Relative path with filename, relative to modulepart (for example: PRODUCT-REF-999/IMAGE-999.jpg) - * @return array List of documents + * @return array Success code + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url DELETE / * diff --git a/htdocs/api/class/api_login.class.php b/htdocs/api/class/api_login.class.php index ab7db1569eb..eba65d098d8 100644 --- a/htdocs/api/class/api_login.class.php +++ b/htdocs/api/class/api_login.class.php @@ -1,7 +1,7 @@ * Copyright (C) 2016 Laurent Destailleur - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -60,6 +60,8 @@ class Login * @param string $entity Entity (when multicompany module is used). '' means 1=first company. * @param int $reset Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access) * @return array Response status and user token + * @phan-return array{success:array{code:int,message:string,token:array{pass_encrypted:string,pass_encoding:string}|string,entity:int}} + * @phpstan-return array{success:array{code:int,message:string,token:array{pass_encrypted:string,pass_encoding:string}|string,entity:int}} * * @throws RestException 403 Access denied * @throws RestException 500 System error @@ -84,6 +86,8 @@ class Login * @param string $entity Entity (when multicompany module is used). '' means 1=first company. * @param int $reset Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access) * @return array Response status and user token + * @phan-return array{success:array{code:int,message:string,token:array{pass_encrypted:string,pass_encoding:string}|string,entity:int}} + * @phpstan-return array{success:array{code:int,message:string,token:array{pass_encrypted:string,pass_encoding:string}|string,entity:int}} * * @throws RestException 403 Access denied * @throws RestException 500 System error @@ -138,7 +142,7 @@ class Login $token = 'failedtogenerateorgettoken'; $tmpuser = new User($this->db); - $tmpuser->fetch(0, $login, 0, 0, $entity); + $tmpuser->fetch(0, $login, '0', 0, $entity); if (empty($tmpuser->id)) { throw new RestException(500, 'Failed to load user'); } diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index f888c5a1efe..2f0bcd86001 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2018-2024 Frédéric France * Copyright (C) 2018-2022 Thibault FOUCART * Copyright (C) 2024 Jon Bendtsen - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * * * This program is free software; you can redistribute it and/or modify @@ -65,7 +65,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the type must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'SO-%')" * @return array List of extra fields - * @phan-return Object[] List of extra fields + * @phan-return array + * @phpstan-return array * * @url GET actiontriggers * @@ -137,6 +138,8 @@ class Setup extends DolibarrApi * @url GET dictionary/ordering_methods * * @return array [List of ordering methods] + * @phan-return array + * @phpstan-return array * * @throws RestException 400 Bad value for sqlfilters * @throws RestException 403 Access denied @@ -199,6 +202,8 @@ class Setup extends DolibarrApi * @param int $active Payment type is active or not {@min 0} {@max 1} * @param string $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')" * @return array [List of ordering reasons] + * @phan-return array + * @phpstan-return array * * @url GET dictionary/ordering_origins * @@ -266,6 +271,8 @@ class Setup extends DolibarrApi * @url GET dictionary/payment_types * * @return array [List of payment types] + * @phan-return array + * @phpstan-return array * * @throws RestException 400 Bad value for sqlfilters * @throws RestException 403 Access denied @@ -331,6 +338,8 @@ class Setup extends DolibarrApi * @param string $filter To filter the regions by name * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of regions + * @phan-return Cregion[] + * @phpstan-return Cregion[] * * @url GET dictionary/regions * @@ -395,6 +404,8 @@ class Setup extends DolibarrApi * * @param int $id ID of region * @return Object Object with cleaned properties + * @phan-return Cregion + * @phpstan-return Cregion * * @url GET dictionary/regions/{id} * @@ -411,6 +422,8 @@ class Setup extends DolibarrApi * * @param string $code Code of region * @return Object Object with cleaned properties + * @phan-return Cregion + * @phpstan-return Cregion * * @url GET dictionary/regions/byCode/{code} * @@ -438,6 +451,8 @@ class Setup extends DolibarrApi * @param string $filter To filter the states by name * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of states + * @phan-return Cstate[] + * @phpstan-return Cstate[] * * @url GET dictionary/states * @@ -504,6 +519,8 @@ class Setup extends DolibarrApi * * @param int $id ID of state * @return Object Object with cleaned properties + * @phan-return Cstate + * @phpstan-return Cstate * * @url GET dictionary/states/{id} * @@ -520,6 +537,8 @@ class Setup extends DolibarrApi * * @param string $code Code of state * @return Object Object with cleaned properties + * @phan-return Cstate + * @phpstan-return Cstate * * @url GET dictionary/states/byCode/{code} * @@ -547,6 +566,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the countries must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of countries + * @phan-return Ccountry[] + * @phpstan-return Ccountry[] * * @url GET dictionary/countries * @@ -612,6 +633,8 @@ class Setup extends DolibarrApi * @param int $id ID of country * @param string $lang Code of the language the name of the country must be translated to * @return Object Object with cleaned properties + * @phan-return Ccountry + * @phpstan-return Ccountry * * @url GET dictionary/countries/{id} * @@ -629,6 +652,8 @@ class Setup extends DolibarrApi * @param string $code Code of country (2 characters) * @param string $lang Code of the language the name of the country must be translated to * @return Object Object with cleaned properties + * @phan-return Ccountry + * @phpstan-return Ccountry * * @url GET dictionary/countries/byCode/{code} * @@ -663,6 +688,8 @@ class Setup extends DolibarrApi * @param int $id ID of region * @param string $code Code of region * @return Object Object with cleaned properties + * @phan-return Cregion + * @phpstan-return Cregion * * @throws RestException */ @@ -670,7 +697,7 @@ class Setup extends DolibarrApi { $region = new Cregion($this->db); - $result = $region->fetch($id, $code); + $result = $region->fetch($id, (int) $code); if ($result < 0) { throw new RestException(503, 'Error when retrieving region : '.$region->error); } elseif ($result == 0) { @@ -686,6 +713,8 @@ class Setup extends DolibarrApi * @param int $id ID of state * @param string $code Code of state * @return Object Object with cleaned properties + * @phan-return Cstate + * @phpstan-return Cstate * * @throws RestException */ @@ -711,6 +740,8 @@ class Setup extends DolibarrApi * @param string $iso ISO of country (3 characters) * @param string $lang Code of the language the name of the country must be translated to * @return Object Object with cleaned properties + * @phan-return Ccountry + * @phpstan-return Ccountry * * @throws RestException */ @@ -744,6 +775,8 @@ class Setup extends DolibarrApi * @url GET dictionary/availability * * @return array [List of availability] + * @phan-return array + * @phpstan-return array * * @throws RestException 400 Bad value for sqlfilters * @throws RestException 403 Access denied @@ -820,7 +853,7 @@ class Setup extends DolibarrApi * @param object $object Object with label to translate * @param string $lang Code of the language the name of the object must be translated to * @param string $prefix Prefix for translation key - * @param array $dict Array of dictionary for translation + * @param string[] $dict Array of dictionary for translation * @return void */ private function translateLabel($object, $lang, $prefix = 'Country', $dict = array('dict')) @@ -856,6 +889,8 @@ class Setup extends DolibarrApi * @param int $active Event's type is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of events types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/event_types * @@ -923,6 +958,8 @@ class Setup extends DolibarrApi * @param int $active Event's type is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of expense report types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/expensereport_types * @@ -989,6 +1026,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the civility must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of Contacts types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/contact_types * @@ -1058,6 +1097,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the civility must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of civility types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/civilities * @@ -1123,6 +1164,8 @@ class Setup extends DolibarrApi * @param int $active Payment term is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of currencies + * @phan-return array + * @phpstan-return array * * @url GET dictionary/currencies * @@ -1193,6 +1236,8 @@ class Setup extends DolibarrApi * @param string $elementtype Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...) * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'SO-%')" * @return array List of extra fields + * @phan-return array> + * @phpstan-return array> * * @url GET extrafields * @@ -1279,9 +1324,10 @@ class Setup extends DolibarrApi * @param string $attrname extrafield attrname * @param string $elementtype extrafield elementtype * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url DELETE extrafields/{elementtype}/{attrname} - * */ public function deleteExtrafieldsFromNames($attrname, $elementtype) { @@ -1315,11 +1361,12 @@ class Setup extends DolibarrApi * @param string $attrname extrafield attrname * @param string $elementtype extrafield elementtype * @return array List of extra fields + * @phan-return array> + * @phpstan-return array> * * @url GET extrafields/{elementtype}/{attrname} * * @suppress PhanPluginUnknownArrayMethodParamType Luracast limitation - * */ public function getExtrafields($attrname, $elementtype) { @@ -1390,13 +1437,14 @@ class Setup extends DolibarrApi * * @param string $attrname extrafield attrname * @param string $elementtype extrafield elementtype - * @param array $request_data Request datas + * @param array $request_data Request data + * @phan-param ?array $request_data + * @phpstan-param ?array $request_data * @return int ID of extrafield * * @url POST extrafields/{elementtype}/{attrname} * * @suppress PhanPluginUnknownArrayMethodParamType Luracast limitation - * */ public function postExtrafields($attrname, $elementtype, $request_data = null) { @@ -1449,7 +1497,7 @@ class Setup extends DolibarrApi $pos = $request_data['pos']; $moreparams = array(); - if (0 > $extrafields->addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $default_value, $param, $alwayseditable, $perms, $list, $help, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams)) { + if (0 > $extrafields->addExtraField($attrname, $label, $type, (int) $pos, $size, $elementtype, (int) $unique, (int) $required, $default_value, $param, (int) $alwayseditable, $perms, $list, $help, $computed, (string) $entity, $langfile, (string) $enabled, (int) $totalizable, (int) $printable, $moreparams)) { throw new RestException(500, 'Error creating extrafield', array_merge(array($extrafields->errno), $extrafields->errors)); } @@ -1474,18 +1522,18 @@ class Setup extends DolibarrApi } /** - * Update Extrafield object * * @param string $attrname extrafield attrname * @param string $elementtype extrafield elementtype - * @param array $request_data Request datas + * @param array $request_data Request data + * @phan-param ?array $request_data + * @phpstan-param ?array $request_data * @return int ID of extrafield * * @url PUT extrafields/{elementtype}/{attrname} * * @suppress PhanPluginUnknownArrayMethodParamType Luracast limitation - * */ public function updateExtrafields($attrname, $elementtype, $request_data = null) { @@ -1535,7 +1583,7 @@ class Setup extends DolibarrApi $moreparams = array(); dol_syslog(get_class($this).'::updateExtraField', LOG_DEBUG); - if (0 > $extrafields->updateExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $default_value, $param, $alwayseditable, $perms, $list, $help, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams)) { + if (0 > $extrafields->updateExtraField($attrname, $label, $type, (int) $pos, $size, $elementtype, (int) $unique, (int) $required, $default_value, $param, (int) $alwayseditable, $perms, $list, $help, $computed, (string) $entity, $langfile, (string) $enabled, (int) $totalizable, (int) $printable, $moreparams)) { throw new RestException(500, 'Error updating extrafield', array_merge(array($extrafields->errno), $extrafields->errors)); } @@ -1571,6 +1619,8 @@ class Setup extends DolibarrApi * @param int $active Town is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of towns + * @phan-return array + * @phpstan-return array * * @url GET dictionary/towns * @@ -1639,6 +1689,8 @@ class Setup extends DolibarrApi * @url GET dictionary/payment_terms * * @return array List of payment terms + * @phan-return array + * @phpstan-return array * * @throws RestException 400 Bad value for sqlfilters * @throws RestException 403 Access denied @@ -1704,6 +1756,8 @@ class Setup extends DolibarrApi * @url GET dictionary/shipping_methods * * @return array List of shipping methods + * @phan-return array + * @phpstan-return array * * @throws RestException 400 Bad value for sqlfilters * @throws RestException 503 Error when retrieving list of shipping modes @@ -1764,6 +1818,8 @@ class Setup extends DolibarrApi * @param int $active Measuring unit is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of measuring unit + * @phan-return array + * @phpstan-return array * * @url GET dictionary/units * @@ -1824,6 +1880,8 @@ class Setup extends DolibarrApi * @param int $active Lega form is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of legal form + * @phan-return array + * @phpstan-return array * * @url GET dictionary/legal_form * @@ -1886,6 +1944,8 @@ class Setup extends DolibarrApi * @param int $active Staff is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of staff + * @phan-return array + * @phpstan-return array * * @url GET dictionary/staff * @@ -1945,6 +2005,8 @@ class Setup extends DolibarrApi * @param int $active Social network is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of social networks + * @phan-return array + * @phpstan-return array * * @url GET dictionary/socialnetworks * @@ -2012,6 +2074,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the category must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of ticket categories + * @phan-return array + * @phpstan-return array * * @url GET dictionary/ticket_categories * @@ -2075,6 +2139,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the severity must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of ticket severities + * @phan-return array + * @phpstan-return array * * @url GET dictionary/ticket_severities * @@ -2138,6 +2204,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the type must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of ticket types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/ticket_types * @@ -2202,6 +2270,8 @@ class Setup extends DolibarrApi * @param string $lang Code of the language the label of the type must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of incoterm types + * @phan-return array + * @phpstan-return array * * @url GET dictionary/incoterms * @@ -2258,7 +2328,9 @@ class Setup extends DolibarrApi * * @url GET /company * - * @return array|mixed Mysoc object + * @return array Mysoc object + * @phan-return Societe My Company properties + * @phpstan-return Societe * * @throws RestException 403 Forbidden */ @@ -2312,6 +2384,8 @@ class Setup extends DolibarrApi * Get the list of establishments. * * @return array List of establishments + * @phan-return array + * @phpstan-return array * * @url GET /establishments * @@ -2407,6 +2481,8 @@ class Setup extends DolibarrApi * * @param string $target Can be 'local' or 'default' or Url of the signatures file to use for the test. Must be reachable by the tested Dolibarr. * @return array Result of file and setup integrity check + * @phan-return array{resultcode:string,resultcomment:string,expectedchecksum:string,currentchecksum:string,out:string} + * @phpstan-return array{resultcode:string,resultcomment:string,expectedchecksum:string,currentchecksum:string,out:string} * * @url GET checkintegrity * @@ -2729,7 +2805,9 @@ class Setup extends DolibarrApi * * @url GET /modules * - * @return array|mixed Data without useless information + * @return array Data without useless information + * @phan-return array + * @phpstan-return array * * @throws RestException 403 Forbidden */ diff --git a/htdocs/api/class/api_status.class.php b/htdocs/api/class/api_status.class.php index f6cf09e289f..d03d7a85f3f 100644 --- a/htdocs/api/class/api_status.class.php +++ b/htdocs/api/class/api_status.class.php @@ -2,6 +2,7 @@ /* * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2023 Christian Foellmann + * Copyright (C) 2025 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 @@ -42,6 +43,8 @@ class Status extends DolibarrApi * Get status (Dolibarr version) * * @return array + * @phan-return array{success:array{code:int,dolibarr_version:string,access_locked:string,environment?:string,timestamp_now_utc?:int,timestamp_php_tz?:string,date_tz?:string}} + * @phpstan-return array{success:array{code:int,dolibarr_version:string,access_locked:string,environment?:string,timestamp_now_utc?:int,timestamp_php_tz?:string,date_tz?:string}} */ public function index() { diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index 6510e9063bc..6b5e61f24cc 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -61,6 +61,8 @@ class Boms extends DolibarrApi * * @param int $id ID of bom * @return Object Object with cleaned properties + * @phan-return BOM + * @phpstan-return BOM * * @url GET {id} * @@ -98,6 +100,8 @@ class Boms extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of order objects + * @phan-return BOM[] + * @phpstan-return BOM[] * * @throws RestException 400 Bad sqlfilters * @throws RestException 403 Access denied @@ -222,6 +226,8 @@ class Boms extends DolibarrApi * @phan-param ?array $request_data * @phpstan-param ?array $request_data * @return Object Object after update + * @phan-return BOM + * @phpstan-return BOM * * @throws RestException 403 Access denied * @throws RestException 404 BOM not found @@ -275,6 +281,8 @@ class Boms extends DolibarrApi * * @param int $id BOM ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 403 Access denied * @throws RestException 404 BOM not found @@ -314,6 +322,8 @@ class Boms extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return BOMLine[] + * @phpstan-return BOMLine[] * * @throws RestException 403 Access denied * @throws RestException 404 BOM not found @@ -458,6 +468,8 @@ class Boms extends DolibarrApi * @url DELETE {id}/lines/{lineid} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 403 Access denied * @throws RestException 404 BOM not found @@ -576,13 +588,16 @@ class Boms extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array of data to validate - * @return array + * @param ?array $data Array of data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $myobject = array(); foreach ($this->bom->fields as $field => $propfield) { if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) { diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 6141084e699..96af20da374 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -265,6 +265,8 @@ class Categories extends DolibarrApi * * @param int $id Category ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -731,13 +733,16 @@ class Categories extends DolibarrApi /** * Validate fields before create or update object * - * @param array|null $data Data to validate - * @return array Return array with validated mandatory fields and their value + * @param ?array $data Data to validate + * @return array Return array with validated mandatory fields and their value * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $category = array(); foreach (Categories::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/comm/action/class/api_agendaevents.class.php b/htdocs/comm/action/class/api_agendaevents.class.php index 001bd6776cc..3f9b20893e8 100644 --- a/htdocs/comm/action/class/api_agendaevents.class.php +++ b/htdocs/comm/action/class/api_agendaevents.class.php @@ -313,6 +313,8 @@ class AgendaEvents extends DolibarrApi * @param int $id Agenda Event ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -354,12 +356,15 @@ class AgendaEvents extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $event = array(); foreach (AgendaEvents::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index b24c12be8ca..54a017d39b7 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -777,6 +777,8 @@ class Proposals extends DolibarrApi * * @param int $id Commercial proposal ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -997,13 +999,16 @@ class Proposals extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $propal = array(); foreach (Proposals::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index 41cd7865981..5ebaec4be86 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -571,6 +571,8 @@ class Orders extends DolibarrApi * @param int $contactid Id of contact to add * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER) * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url POST {id}/contact/{contactid}/{type} * @@ -620,6 +622,8 @@ class Orders extends DolibarrApi * @url DELETE {id}/contact/{contactid}/{type} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 401 * @throws RestException 404 @@ -721,6 +725,8 @@ class Orders extends DolibarrApi * * @param int $id Order ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -1145,12 +1151,15 @@ class Orders extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $commande = array(); foreach (Orders::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index 45c7a0c1973..e86deabfe43 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -196,6 +196,8 @@ class BankAccounts extends DolibarrApi * @url POST /transfer * * @return array + * @phan-return array{success:array{code:int,message:string,bank_id_from:int,bank_id_to:int}} + * @phpstan-return array{success:array{code:int,message:string,bank_id_from:int,bank_id_to:int}} * * @status 201 * @@ -373,6 +375,8 @@ class BankAccounts extends DolibarrApi * * @param int $id ID of account * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -400,13 +404,16 @@ class BankAccounts extends DolibarrApi /** * Validate fields before creating an object * - * @param array|null $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $account = array(); foreach (BankAccounts::$FIELDS as $field) { if (!isset($data[$field])) { @@ -668,6 +675,8 @@ class BankAccounts extends DolibarrApi * @param int $id ID of account * @param int $line_id ID of account line * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url DELETE {id}/lines/{line_id} */ diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index d805d98eaae..bb7430d0000 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -330,7 +330,7 @@ class Invoices extends DolibarrApi throw new RestException(403, "Insuffisant rights"); } // Check mandatory fields - $result = $this->_validate($request_data); + $request_data = $this->_validate($request_data); foreach ($request_data as $field => $value) { if ($field === 'caller') { @@ -552,6 +552,8 @@ class Invoices extends DolibarrApi * @param int $contactid Id of contact to add * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER) * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url POST {id}/contact/{contactid}/{type} * @@ -744,6 +746,8 @@ class Invoices extends DolibarrApi * * @param int $id Invoice ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -1602,6 +1606,8 @@ class Invoices extends DolibarrApi * Example of value for parameter arrayofamounts: {"1": {"amount": "99.99", "multicurrency_amount": ""}, "2": {"amount": "", "multicurrency_amount": "10"}} * * @param array $arrayofamounts {@from body} Array with id of invoices with amount to pay for each invoice + * @phan-param array $arrayofamounts + * @phpstan-param array $arrayofamounts * @param string $datepaye {@from body} Payment date * @param int $paymentid {@from body} Payment mode Id {@min 1} * @param string $closepaidinvoices {@from body} Close paid invoices {@choice yes,no} @@ -1755,6 +1761,8 @@ class Invoices extends DolibarrApi * @url PUT payments/{id} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 400 Bad parameters * @throws RestException 401 Not allowed @@ -1819,13 +1827,16 @@ class Invoices extends DolibarrApi /** * Validate fields before create or update object * - * @param array|null $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $invoice = array(); foreach (Invoices::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index e6b638784d2..55771f352bf 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -558,6 +558,8 @@ class Contracts extends DolibarrApi * @param int $id Contract ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -594,6 +596,9 @@ class Contracts extends DolibarrApi * @url POST {id}/validate * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -640,6 +645,9 @@ class Contracts extends DolibarrApi * @url POST {id}/close * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -700,12 +708,15 @@ class Contracts extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $contrat = array(); foreach (Contracts::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 2a78aded5ac..998eeec9fc5 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -584,7 +584,7 @@ class Conf extends stdClass $modulename = strtolower($reg[1]); $partname = strtolower($reg[2]); - if (!isset($this->modules_parts[$partname]) || !is_array($this->modules_parts[$partname])) { + if (!array_key_exists($partname, $this->modules_parts) || !is_array($this->modules_parts[$partname])) { $this->modules_parts[$partname] = array(); } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 529dc1c8d6e..cb2fd403a9d 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -3712,7 +3712,7 @@ function dirbasename($pathfile) * Function to get list of updated or modified files. * $file_list is used as global variable * - * @param array{insignature:string[],missing?:array,updated:array} $file_list Array for response + * @param array{}|array{insignature:string[],missing?:array,updated:array} $file_list Array for response * @param SimpleXMLElement $dir SimpleXMLElement of files to test * @param string $path Path of files relative to $pathref. We start with ''. Used by recursive calls. * @param string $pathref Path ref (DOL_DOCUMENT_ROOT) diff --git a/htdocs/don/class/api_donations.class.php b/htdocs/don/class/api_donations.class.php index 161f850b5e3..4570fda0bf5 100644 --- a/htdocs/don/class/api_donations.class.php +++ b/htdocs/don/class/api_donations.class.php @@ -283,6 +283,8 @@ class Donations extends DolibarrApi * * @param int $id Order ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -395,12 +397,15 @@ class Donations extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $don = array(); foreach (Donations::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index 98bcacfdd1d..b77123f1959 100644 --- a/htdocs/expedition/class/api_shipments.class.php +++ b/htdocs/expedition/class/api_shipments.class.php @@ -98,6 +98,8 @@ class Shipments extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of shipment objects + * @phan-return Expedition[] + * @phpstan-return Expedition[] * * @throws RestException */ @@ -198,8 +200,8 @@ class Shipments extends DolibarrApi * Create shipment object * * @param array $request_data Request data - * @phan-param ?array $request_data - * @phpstan-param ?array $request_data + * @phan-param ?array>> $request_data + * @phpstan-param ?array>> $request_data * @return int ID of shipment created */ public function post($request_data = null) @@ -224,14 +226,14 @@ class Shipments extends DolibarrApi foreach ($request_data["lines"] as $line) { $shipmentline = new ExpeditionLigne($this->db); - $shipmentline->entrepot_id = $line['entrepot_id']; - $shipmentline->fk_element = $line['fk_element'] ?? $line['origin_id']; // example: order id. this->origin is 'commande' - $shipmentline->origin_line_id = $line['fk_elementdet'] ?? $line['origin_line_id']; // example: order id - $shipmentline->fk_elementdet = $line['fk_elementdet'] ?? $line['origin_line_id']; // example: order line id + $shipmentline->entrepot_id = (int) $line['entrepot_id']; + $shipmentline->fk_element = (int) ($line['fk_element'] ?? $line['origin_id']); // example: order id. this->origin is 'commande' + $shipmentline->origin_line_id = (int) ($line['fk_elementdet'] ?? $line['origin_line_id']); // example: order id + $shipmentline->fk_elementdet = (int) ($line['fk_elementdet'] ?? $line['origin_line_id']); // example: order line id $shipmentline->origin_type = $line['element_type'] ?? $line['origin_type']; // example 'commande' or 'order' $shipmentline->element_type = $line['element_type'] ?? $line['origin_type']; // example 'commande' or 'order' - $shipmentline->qty = $line['qty']; - $shipmentline->rang = $line['rang']; + $shipmentline->qty = (float) $line['qty']; + $shipmentline->rang = (string) $line['rang']; $shipmentline->array_options = $line['array_options']; $shipmentline->detail_batch = $line['detail_batch']; @@ -424,6 +426,8 @@ class Shipments extends DolibarrApi * @url DELETE {id}/lines/{lineid} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 401 * @throws RestException 404 @@ -513,6 +517,8 @@ class Shipments extends DolibarrApi * @param int $id Shipment ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -761,12 +767,15 @@ class Shipments extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $shipment = array(); foreach (Shipments::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/expensereport/class/api_expensereports.class.php b/htdocs/expensereport/class/api_expensereports.class.php index 5a2841c0da7..228bea22d65 100644 --- a/htdocs/expensereport/class/api_expensereports.class.php +++ b/htdocs/expensereport/class/api_expensereports.class.php @@ -108,6 +108,8 @@ class ExpenseReports extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return ExpenseReport[] + * @phpstan-return ExpenseReport[] */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $user_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false) { @@ -492,6 +494,8 @@ class ExpenseReports extends DolibarrApi * @param int $id Expense Report ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -573,6 +577,8 @@ class ExpenseReports extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array List of paymentExpenseReport objects + * @phan-return PaymentExpenseReport[] + * @phpstan-return PaymentExpenseReport[] * * @url GET /payments * @@ -814,12 +820,15 @@ class ExpenseReports extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $expensereport = array(); foreach (ExpenseReports::$FIELDS as $field) { if (!isset($data[$field])) { @@ -833,12 +842,15 @@ class ExpenseReports extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validatepayment($data) { + if ($data === null) { + $data = array(); + } $expensereport = array(); foreach (ExpenseReports::$FIELDSPAYMENT as $field) { if (!isset($data[$field])) { diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 8ac35076f27..4dbb43115be 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -232,7 +232,7 @@ class SupplierInvoices extends DolibarrApi throw new RestException(403, "Insuffisant rights"); } // Check mandatory fields - $result = $this->_validate($request_data); + $request_data = $this->_validate($request_data); foreach ($request_data as $field => $value) { if ($field === 'caller') { @@ -280,6 +280,10 @@ class SupplierInvoices extends DolibarrApi throw new RestException(404, 'Supplier invoice not found'); } + if (!is_array($request_data)) { + $request_data = array(); + } + foreach ($request_data as $field => $value) { if ($field == 'id') { continue; @@ -312,6 +316,8 @@ class SupplierInvoices extends DolibarrApi * @param int $id Supplier invoice ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 403 * @throws RestException 404 @@ -352,6 +358,8 @@ class SupplierInvoices extends DolibarrApi * @url POST {id}/validate * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 304 * @throws RestException 403 @@ -715,6 +723,8 @@ class SupplierInvoices extends DolibarrApi * @url DELETE {id}/lines/{lineid} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 400 Bad parameters * @throws RestException 403 Not allowed @@ -778,13 +788,16 @@ class SupplierInvoices extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $invoice = array(); foreach (SupplierInvoices::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index 1c805b156f2..06bf957bf1f 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -97,6 +97,8 @@ class SupplierOrders extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return CommandeFournisseur[]|array{data:CommandeFournisseur[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return CommandeFournisseur[]|array{data:CommandeFournisseur[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException */ @@ -224,7 +226,7 @@ class SupplierOrders extends DolibarrApi $obj_ret['pagination'] = [ 'total' => (int) $total, 'page' => $page, //count starts from 0 - 'page_count' => ceil((int) $total / $limit), + 'page_count' => (int) ceil((int) $total / $limit), 'limit' => $limit ]; } @@ -248,7 +250,7 @@ class SupplierOrders extends DolibarrApi throw new RestException(403, "Insuffisant rights"); } // Check mandatory fields - $result = $this->_validate($request_data); + $request_data = $this->_validate($request_data); foreach ($request_data as $field => $value) { if ($field === 'caller') { @@ -378,6 +380,8 @@ class SupplierOrders extends DolibarrApi * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...) * @param string $source Source of the contact (external, internal) * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url POST {id}/contact/{contactid}/{type}/{source} * @@ -428,6 +432,8 @@ class SupplierOrders extends DolibarrApi * @url DELETE {id}/contact/{contactid}/{type}/{source} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException 401 * @throws RestException 404 @@ -481,6 +487,8 @@ class SupplierOrders extends DolibarrApi * * @param int $id Supplier order ID * @return array Array of result + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -519,6 +527,9 @@ class SupplierOrders extends DolibarrApi * @url POST {id}/validate * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -567,6 +578,9 @@ class SupplierOrders extends DolibarrApi * @url POST {id}/approve * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -617,6 +631,9 @@ class SupplierOrders extends DolibarrApi * @url POST {id}/makeorder * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -681,10 +698,15 @@ class SupplierOrders extends DolibarrApi * @param integer $closeopenorder Close order if everything is received {@required false} * @param string $comment Comment {@required false} * @param array $lines Array of product dispatches + * @phan-param array $lines + * @phpstan-param array $lines * * @url POST {id}/receive * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} + * * FIXME An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." */ @@ -715,12 +737,12 @@ class SupplierOrders extends DolibarrApi $lineObj->eatby, $lineObj->sellby, $lineObj->batch, - $lineObj->id, + (int) $lineObj->id, $lineObj->notrigger ); if ($result < 0) { - throw new RestException(500, 'Error dispatch order line '.$line->id.': '.$this->order->error); + throw new RestException(500, 'Error dispatch order line '.$lineObj->id.': '.$this->order->error); } } @@ -765,13 +787,16 @@ class SupplierOrders extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $order = array(); foreach (SupplierOrders::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index 9ad0a3f0c1e..a46e075634b 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -340,6 +340,8 @@ class KnowledgeManagement extends DolibarrApi * * @param int $id KnowledgeRecord ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException * @@ -438,13 +440,16 @@ class KnowledgeManagement extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array of data to validate - * @return array + * @param ?array $data Array of data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $knowledgerecord = array(); foreach ($this->knowledgerecord->fields as $field => $propfield) { if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) { diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php index 82617fd1830..c9437431d10 100644 --- a/htdocs/multicurrency/class/api_multicurrencies.class.php +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -291,6 +291,8 @@ class MultiCurrencies extends DolibarrApi * * @param int $id Currency ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException */ diff --git a/htdocs/partnership/class/api_partnerships.class.php b/htdocs/partnership/class/api_partnerships.class.php index f00b71d37a3..6be059f25f9 100644 --- a/htdocs/partnership/class/api_partnerships.class.php +++ b/htdocs/partnership/class/api_partnerships.class.php @@ -278,6 +278,8 @@ class Partnerships extends DolibarrApi * * @param int $id Partnership ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @throws RestException * @@ -376,13 +378,16 @@ class Partnerships extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array of data to validate - * @return array + * @param ?array $data Array of data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $partnership = array(); foreach ($this->partnership->fields as $field => $propfield) { if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) { diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index fd425243af8..ce9d7803292 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -523,6 +523,8 @@ class Products extends DolibarrApi * * @param int $id Product ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -830,6 +832,8 @@ class Products extends DolibarrApi * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined. * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER) * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function). + * @phan-param array{0:string,1:string,2:string,3:string}|array{} $localtaxes_array + * @phpstan-param array{0:string,1:string,2:string,3:string}|array{} $localtaxes_array * @param string $newdefaultvatcode Default vat code * @param float $multicurrency_buyprice Purchase price for the quantity min in currency * @param string $multicurrency_price_base_type HT or TTC in currency @@ -1805,6 +1809,8 @@ class Products extends DolibarrApi * @param float $price_impact Price impact of variant * @param bool $price_impact_is_percent Price impact in percent (true or false) * @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...) + * @phan-param array $features + * @phpstan-param array $features * @param string $reference Customized reference of variant * @param string $ref_ext External reference of variant * @return int @@ -1868,6 +1874,8 @@ class Products extends DolibarrApi * @param float $price_impact Price impact of variant * @param bool $price_impact_is_percent Price impact in percent (true or false) * @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...) + * @phan-param array $features + * @phpstan-param array $features * @return int * * @throws RestException 500 System error @@ -2100,12 +2108,15 @@ class Products extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $product = array(); foreach (Products::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index 39ae48d431d..2a51192218b 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -1,5 +1,6 @@ + * Copyright (C) 2025 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 @@ -29,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; class StockMovements extends DolibarrApi { /** - * @var array $FIELDS Mandatory fields, checked when create and update object + * @var array Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'product_id', @@ -38,7 +39,7 @@ class StockMovements extends DolibarrApi ); /** - * @var MouvementStock $stockmovement {@type MouvementStock} + * @var MouvementStock {@type MouvementStock} */ public $stockmovement; @@ -155,7 +156,7 @@ class StockMovements extends DolibarrApi * $price Can be set to update AWP (Average Weighted Price) when you make a stock increase * $dlc Eat-by date. Will be used if lot does not exists yet and will be created. * $dluo Sell-by date. Will be used if lot does not exists yet and will be created. - * + * * @param int $product_id Id product id {@min 1} {@from body} {@required true} * @param int $warehouse_id Id warehouse {@min 1} {@from body} {@required true} * @param float $qty Qty to add (Use negative value for a stock decrease) {@from body} {@required true} @@ -337,13 +338,16 @@ class StockMovements extends DolibarrApi /** * Validate fields before create or update object * - * @param array|null $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) // @phpstan-ignore-line { + if ($data === null) { + $data = array(); + } $stockmovement = array(); foreach (self::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php index 1a7cb9a550a..c4fd8472e5f 100644 --- a/htdocs/product/stock/class/api_warehouses.class.php +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -244,6 +244,8 @@ class Warehouses extends DolibarrApi * * @param int $id Warehouse ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -294,13 +296,16 @@ class Warehouses extends DolibarrApi /** * Validate fields before create or update object * - * @param array|null $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $warehouse = array(); foreach (Warehouses::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 08b0facb0ea..774cebd33d4 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -494,6 +494,8 @@ class Tasks extends DolibarrApi * @param int $id Task ID * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -537,6 +539,8 @@ class Tasks extends DolibarrApi * NOTE: Should be "POST {id}/timespent", since POST already implies "add" * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function addTimeSpent($id, $date, $duration, $user_id = 0, $note = '') { @@ -596,6 +600,8 @@ class Tasks extends DolibarrApi * @url PUT {id}/timespent/{timespent_id} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function putTimeSpent($id, $timespent_id, $date, $duration, $user_id = 0, $note = '') { @@ -641,6 +647,8 @@ class Tasks extends DolibarrApi * @url DELETE {id}/timespent/{timespent_id} * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function deleteTimeSpent($id, $timespent_id) { @@ -739,12 +747,15 @@ class Tasks extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Data to validate + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $object = array(); foreach (self::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/salaries/class/api_salaries.class.php b/htdocs/salaries/class/api_salaries.class.php index d55c3debb7d..a7227e4ebe6 100644 --- a/htdocs/salaries/class/api_salaries.class.php +++ b/htdocs/salaries/class/api_salaries.class.php @@ -424,13 +424,16 @@ class Salaries extends DolibarrApi /** * Validate fields before creating an object * - * @param array|null $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $salary = array(); foreach (Salaries::$FIELDS as $field) { if (!isset($data[$field])) { @@ -444,13 +447,16 @@ class Salaries extends DolibarrApi /** * Validate fields before creating an object * - * @param array|null $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validatepayments($data) { + if ($data === null) { + $data = array(); + } $paymentsalary = array(); $fields = Salaries::$FIELDSPAYMENT; if (isModEnabled("bank")) { diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index f5972267cc1..bfecfc45047 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -408,6 +408,8 @@ class Thirdparties extends DolibarrApi * * @param int $id Thirdparty ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -2141,13 +2143,16 @@ class Thirdparties extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $thirdparty = array(); foreach (Thirdparties::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php index a7b91c68681..0d607880f12 100644 --- a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php +++ b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php @@ -57,6 +57,8 @@ class SupplierProposals extends DolibarrApi * * @param int $id Supplier proposal ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -321,12 +323,15 @@ class SupplierProposals extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify - * @return array + * @param ?array $data Array with data to verify + * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $propal = array(); foreach (SupplierProposals::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/ticket/class/api_tickets.class.php b/htdocs/ticket/class/api_tickets.class.php index fafc67c469d..c633ab5085e 100644 --- a/htdocs/ticket/class/api_tickets.class.php +++ b/htdocs/ticket/class/api_tickets.class.php @@ -433,6 +433,8 @@ class Tickets extends DolibarrApi * * @param int $id Ticket ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -463,13 +465,16 @@ class Tickets extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $ticket = array(); foreach (Tickets::$FIELDS as $field) { if (!isset($data[$field])) { @@ -483,13 +488,16 @@ class Tickets extends DolibarrApi /** * Validate fields before create or update object message * - * @param array $data Data to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validateMessage($data) { + if ($data === null) { + $data = array(); + } $ticket = array(); foreach (Tickets::$FIELDS_MESSAGES as $field) { if (!isset($data[$field])) { diff --git a/htdocs/webhook/class/api_webhook.class.php b/htdocs/webhook/class/api_webhook.class.php index 55d7ae209f9..e51a73ff463 100644 --- a/htdocs/webhook/class/api_webhook.class.php +++ b/htdocs/webhook/class/api_webhook.class.php @@ -168,7 +168,7 @@ class Webhook extends DolibarrApi throw new RestException(403); } // Check mandatory fields - $this->_validate($request_data); + $request_data = $this->_validate($request_data); foreach ($request_data as $field => $value) { $this->target->$field = $this->_checkValForAPI($field, $value, $this->target); @@ -228,6 +228,8 @@ class Webhook extends DolibarrApi * * @param int $id Target ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} */ public function delete($id) { @@ -288,13 +290,16 @@ class Webhook extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Datas to validate - * @return array + * @param ?array $data Data to validate + * @return array * * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $target = array(); foreach (self::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/zapier/class/api_zapier.class.php b/htdocs/zapier/class/api_zapier.class.php index 1416009cdc2..d917d192024 100644 --- a/htdocs/zapier/class/api_zapier.class.php +++ b/htdocs/zapier/class/api_zapier.class.php @@ -97,6 +97,8 @@ class Zapier extends DolibarrApi * Return an array with hook information * * @return array data + * @phan-return array + * @phpstan-return array * * @url GET /getmoduleschoices/ * @throws RestException @@ -110,7 +112,7 @@ class Zapier extends DolibarrApi $arraychoices = array( 'invoices' => 'Invoices', 'orders' => 'Orders', - 'thirdparties' => 'Thirparties', + 'thirdparties' => 'ThirdParties', 'contacts' => 'Contacts', 'users' => 'Users', ); @@ -138,6 +140,8 @@ class Zapier extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of order objects + * @phan-return Hook[] + * @phpstan-return Hook[] * * @throws RestException * @@ -224,6 +228,8 @@ class Zapier extends DolibarrApi * @phan-param ?array $request_data * @phpstan-param ?array $request_data * @return array ID of hook + * @phan-return array{id:int} + * @phpstan-return array{id:int} * * @url POST /hook/ */ @@ -239,7 +245,7 @@ class Zapier extends DolibarrApi $fields = array( 'url', ); - $result = $this->validate($request_data, $fields); + $request_data = $this->validate($request_data, $fields); foreach ($request_data as $field => $value) { if ($field === 'caller') { @@ -266,6 +272,8 @@ class Zapier extends DolibarrApi * * @param int $id Hook ID * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url DELETE /hook/{id} */ @@ -314,8 +322,8 @@ class Zapier extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array of data to validate - * @param string[] $fields Array of fields needed + * @param ?array $data Array of data to validate + * @param string[] $fields Array of fields needed * @return array * * @throws RestException