diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index 460a8ca2505..fd67711a514 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -9,12 +9,11 @@ */ return [ // # Issue statistics: - // PhanTypeMismatchArgument : 1230+ occurrences + // PhanTypeMismatchArgument : 1200+ occurrences // PhanUndeclaredProperty : 480+ occurrences - // PhanTypeMismatchArgumentNullable : 310+ occurrences - // PhanTypeMismatchProperty : 160+ occurrences + // PhanTypeMismatchArgumentNullable : 300+ occurrences + // PhanTypeMismatchProperty : 150+ occurrences // PhanUndeclaredGlobalVariable : 100+ occurrences - // PhanPluginUnknownArrayMethodReturnType : 60+ occurrences // PhanTypeExpectedObjectPropAccess : 25+ occurrences // PhanTypeInvalidDimOffset : 20+ occurrences // PhanTypeMismatchDimFetch : 20+ occurrences @@ -24,23 +23,22 @@ return [ // PhanTypeMismatchArgumentNullableInternal : 10+ occurrences // PhanPossiblyUndeclaredGlobalVariable : 9 occurrences // PhanUndeclaredMethod : 9 occurrences - // PhanTypeComparisonFromArray : 7 occurrences // PhanPluginDuplicateExpressionBinaryOp : 6 occurrences // PhanTypeArraySuspiciousNull : 6 occurrences + // PhanTypeComparisonFromArray : 6 occurrences // PhanParamTooMany : 4 occurrences // PhanPluginDuplicateArrayKey : 4 occurrences // PhanEmptyFQSENInClasslike : 3 occurrences // PhanInvalidFQSENInClasslike : 3 occurrences // PhanPluginSuspiciousParamPosition : 2 occurrences // PhanTypeMismatchDimAssignment : 2 occurrences + // PhanTypeMismatchReturn : 2 occurrences // PhanTypeSuspiciousStringExpression : 2 occurrences - // PhanAccessMethodProtected : 1 occurrence // PhanPluginBothLiteralsBinaryOp : 1 occurrence // PhanPluginDuplicateExpressionAssignmentOperation : 1 occurrence // PhanPluginUnknownArrayPropertyType : 1 occurrence // PhanPossiblyUndeclaredVariable : 1 occurrence // PhanTypeExpectedObjectPropAccessButGotNull : 1 occurrence - // PhanTypeMismatchReturn : 1 occurrence // Currently, file_suppressions and directory_suppressions are the only supported suppressions 'file_suppressions' => [ @@ -145,14 +143,12 @@ return [ 'htdocs/bookcal/class/availabilities.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/bookcal/class/calendar.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/bookmarks/card.php' => ['PhanTypeMismatchArgument'], - 'htdocs/categories/class/api_categories.class.php' => ['PhanAccessMethodProtected', 'PhanPluginUnknownArrayMethodReturnType'], 'htdocs/categories/class/categorie.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/categories/photos.php' => ['PhanTypeMismatchArgument'], 'htdocs/categories/viewcat.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/collab/index.php' => ['PhanUndeclaredProperty'], 'htdocs/comm/action/card.php' => ['PhanPluginBothLiteralsBinaryOp', 'PhanTypeMismatchArgument', 'PhanTypeMismatchProperty'], 'htdocs/comm/action/class/actioncomm.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], - 'htdocs/comm/action/class/api_agendaevents.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchProperty'], 'htdocs/comm/action/class/cactioncomm.class.php' => ['PhanPluginUnknownArrayPropertyType'], 'htdocs/comm/action/document.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/action/index.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty'], @@ -169,7 +165,6 @@ return [ 'htdocs/comm/multiprix.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/agenda.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], - 'htdocs/comm/propal/class/api_proposals.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/comm/propal/class/propal.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/comm/propal/class/propaleligne.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/contact.php' => ['PhanTypeMismatchArgument'], @@ -181,7 +176,7 @@ return [ 'htdocs/comm/remise.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/remx.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/card.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/class/api_orders.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], + 'htdocs/commande/class/api_orders.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/class/commande.class.php' => ['PhanUndeclaredProperty'], 'htdocs/commande/customer.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/commande/list.php' => ['PhanUndeclaredProperty'], @@ -194,7 +189,6 @@ return [ 'htdocs/compta/bank/card.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/categ.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/class/account.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], - 'htdocs/compta/bank/class/api_bankaccounts.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], 'htdocs/compta/bank/class/paymentvarious.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/graph.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/line.php' => ['PhanUndeclaredGlobalVariable'], @@ -217,7 +211,7 @@ return [ 'htdocs/compta/facture/agenda.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], 'htdocs/compta/facture/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'], - 'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeComparisonFromArray', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], + 'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/compta/facture/class/facture.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/compta/facture/class/factureligne.class.php' => ['PhanTypeMismatchArgument'], @@ -275,7 +269,6 @@ return [ 'htdocs/contact/list.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/contrat/agenda.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], 'htdocs/contrat/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredGlobalVariable'], - 'htdocs/contrat/class/api_contracts.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/contrat/class/contrat.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/contrat/class/contratligne.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/contrat/contact.php' => ['PhanTypeMismatchArgument'], @@ -436,7 +429,6 @@ return [ 'htdocs/delivery/class/delivery.class.php' => ['PhanUndeclaredProperty'], 'htdocs/don/admin/donation.php' => ['PhanUndeclaredMethod'], 'htdocs/don/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/don/class/api_donations.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/don/class/don.class.php' => ['PhanParamTooMany'], 'htdocs/don/document.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/don/info.php' => ['PhanUndeclaredGlobalVariable'], @@ -490,7 +482,6 @@ return [ 'htdocs/fichinter/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/filefunc.inc.php' => ['PhanPluginUndeclaredVariableIsset', 'PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'], 'htdocs/fourn/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/fourn/class/api_supplier_invoices.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/fourn/class/api_supplier_orders.class.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/fourn/class/fournisseur.commande.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/fourn/class/fournisseur.facture-rec.class.php' => ['PhanTypeMismatchArgument'], @@ -522,7 +513,6 @@ return [ 'htdocs/hrm/skill_card.php' => ['PhanTypeExpectedObjectPropAccess', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/imports/import.php' => ['PhanTypeMismatchArgument'], 'htdocs/intracommreport/card.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/knowledgemanagement/class/knowledgerecord.class.php' => ['PhanUndeclaredProperty'], 'htdocs/knowledgemanagement/knowledgerecord_card.php' => ['PhanTypeMismatchArgument'], 'htdocs/loan/class/paymentloan.class.php' => ['PhanTypeMismatchArgument'], @@ -532,17 +522,16 @@ return [ 'htdocs/mrp/class/mo.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/mrp/mo_movements.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/mrp/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], - 'htdocs/multicurrency/class/api_multicurrencies.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], + 'htdocs/multicurrency/class/api_multicurrencies.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/multicurrency/class/multicurrency.class.php' => ['PhanTypeExpectedObjectPropAccess'], 'htdocs/multicurrency/multicurrency_rate.php' => ['PhanTypeMismatchArgument'], 'htdocs/opensurvey/results.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/partnership/class/api_partnerships.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/partnership/class/partnership.class.php' => ['PhanUndeclaredProperty'], 'htdocs/partnership/core/modules/partnership/mod_partnership_advanced.php' => ['PhanUndeclaredProperty'], 'htdocs/partnership/partnership_card.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/partnership/partnership_list.php' => ['PhanUndeclaredProperty'], 'htdocs/product/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/product/class/api_products.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], + 'htdocs/product/class/api_products.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchReturn', 'PhanUndeclaredProperty'], 'htdocs/product/class/html.formproduct.class.php' => ['PhanUndeclaredProperty'], 'htdocs/product/class/productfournisseurprice.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/product/inventory/class/inventory.class.php' => ['PhanUndeclaredProperty'], @@ -550,8 +539,6 @@ return [ 'htdocs/product/price_suppliers.php' => ['PhanTypeMismatchProperty'], 'htdocs/product/reassort.php' => ['PhanTypeExpectedObjectPropAccessButGotNull'], 'htdocs/product/stock/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/product/stock/class/api_stockmovements.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], - 'htdocs/product/stock/class/api_warehouses.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/product/stock/info.php' => ['PhanUndeclaredProperty'], 'htdocs/product/stock/list.php' => ['PhanUndeclaredProperty'], 'htdocs/product/stock/movement_card.php' => ['PhanPluginUndeclaredVariableIsset', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], @@ -567,7 +554,6 @@ return [ 'htdocs/product/stock/tpl/stocktransfer.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/projet/admin/project.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/projet/card.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable'], - 'htdocs/projet/class/api_tasks.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/projet/tasks.php' => ['PhanTypeMismatchArgument'], 'htdocs/projet/tasks/time.php' => ['PhanTypeInvalidDimOffset', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/projet/tasks/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], @@ -582,7 +568,6 @@ return [ 'htdocs/public/recruitment/view.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/public/webportal/tpl/menu.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/reception/card.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/reception/class/api_receptions.class.php' => ['PhanTypeMismatchArgumentNullable'], 'htdocs/reception/class/reception.class.php' => ['PhanUndeclaredProperty'], 'htdocs/reception/list.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/class/recruitmentcandidature.class.php' => ['PhanUndeclaredProperty'], @@ -597,24 +582,21 @@ return [ 'htdocs/recruitment/recruitmentjobposition_card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/recruitmentjobposition_document.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/recruitmentjobposition_note.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/salaries/class/api_salaries.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/salaries/paiement_salary.php' => ['PhanUndeclaredProperty'], 'htdocs/salaries/virement_request.php' => ['PhanUndeclaredProperty'], 'htdocs/societe/ajax/company.php' => ['PhanUndeclaredProperty'], 'htdocs/societe/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/societe/class/api_thirdparties.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchArgumentProbablyReal', 'PhanTypeMismatchProperty'], 'htdocs/societe/class/societe.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/societe/paymentmodes.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgument'], 'htdocs/stripe/class/stripe.class.php' => ['PhanTypeExpectedObjectPropAccess'], 'htdocs/supplier_proposal/card.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanUndeclaredProperty'], + 'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanUndeclaredProperty'], 'htdocs/supplier_proposal/class/supplier_proposal.class.php' => ['PhanUndeclaredProperty'], 'htdocs/takepos/index.php' => ['PhanPluginUndeclaredVariableIsset'], 'htdocs/takepos/invoice.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'], 'htdocs/takepos/split.php' => ['PhanPluginUndeclaredVariableIsset'], 'htdocs/ticket/card.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/class/actions_ticket.class.php' => ['PhanUndeclaredProperty'], - 'htdocs/ticket/class/api_tickets.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/ticket/class/cticketcategory.class.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/class/ticket.class.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/contact.php' => ['PhanTypeMismatchArgument'], @@ -623,7 +605,6 @@ return [ 'htdocs/variants/tpl/productattributevalueline_edit.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/variants/tpl/productattributevalueline_view.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/viewimage.php' => ['PhanUndeclaredMethod'], - 'htdocs/webhook/class/api_webhook.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/webhook/class/target.class.php' => ['PhanUndeclaredMethod'], 'htdocs/webhook/target_card.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/webportal/admin/setup.php' => ['PhanTypeMismatchArgument'], diff --git a/dev/tools/phan/config.php b/dev/tools/phan/config.php index d45a1e422c0..2b371b1d984 100644 --- a/dev/tools/phan/config.php +++ b/dev/tools/phan/config.php @@ -462,7 +462,7 @@ return [ 'PhanPluginUnknownClosureReturnType', // When we use closure (we must avoid), we do not have PHP doc // 'PhanPluginUnknownArrayMethodParamType', // All fixed - // 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* + // 'PhanPluginUnknownArrayMethodReturnType', // All fixed // '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. '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/dev/tools/phan/config_extended.php b/dev/tools/phan/config_extended.php index fa84a395df7..c42693162df 100644 --- a/dev/tools/phan/config_extended.php +++ b/dev/tools/phan/config_extended.php @@ -87,7 +87,7 @@ $config['suppress_issue_types'] = [ 'PhanPluginNonBoolBranch', // Not essential - 31240+ occurrences 'PhanPluginNumericalComparison', // Not essential - 19870+ occurrences - 'PhanTypeMismatchArgument', // Not showing in cti.dolibarr until low count - Can detect missing array keys, invalid types, objects being passed when scalar expected - Not all reported by phpstan - <=3800 cases (was: 12300+ before) + 'PhanTypeMismatchArgument', // Not showing in cti.dolibarr until low count - Can detect missing array keys, invalid types, objects being passed when scalar expected - Not all reported by phpstan - <=1200 cases (was: 12300+ before) 'PhanPluginNonBoolInLogicalArith', // Not essential - 11040+ occurrences 'PhanPluginConstantVariableScalar', // Not essential - 5180+ occurrences 'PhanPluginDuplicateAdjacentStatement', @@ -98,7 +98,7 @@ $config['suppress_issue_types'] = [ 'PhanPluginDuplicateCatchStatementBody', // Requires PHP7.1 - 50+ occurrences // 'PhanPluginUnknownArrayMethodParamType', // All fixed - 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* at this time + // 'PhanPluginUnknownArrayMethodReturnType', // All fixed '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/api/class/api.class.php b/htdocs/api/class/api.class.php index ceae1f08b0c..d707562f3b8 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Laurent Destailleur * Copyright (C) 2020-2025 Frédéric France - * 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 @@ -29,12 +29,12 @@ require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; class DolibarrApi { /** - * @var DoliDB $db Database object + * @var DoliDB Database object */ protected $db; /** - * @var Restler $r Restler object + * @var Restler Restler object */ public $r; @@ -129,9 +129,13 @@ class DolibarrApi /** * Filter properties that will be returned on object * + * @phpstan-template T of Object + * * @param Object $object Object to clean - * @param String $properties Comma separated list of properties names + * @param string $properties Comma separated list of properties names * @return Object Object with cleaned properties + * @phpstan-param T $object + * @phpstan-return T */ protected function _filterObjectProperties($object, $properties) { diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index 304a2b690c5..c7c92f9514d 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -55,7 +55,7 @@ class DolibarrApiAccess implements iAuthenticate public $db; /** - * @var array role required by API method user / external / admin + * @var string[] role required by API method user / external / admin */ public static $requires = array('user', 'external', 'admin'); diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 2e8605e205f..47b792a1121 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -312,8 +312,8 @@ class Categories extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array Array of category objects - * @phan-return Categorie[] - * @phpstan-return Categorie[] + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @throws RestException * diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 1cb3d491737..419e13369ab 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -317,6 +317,8 @@ class Proposals extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return PropaleLigne[] + * @phpstan-return PropaleLigne[] */ public function getLines($id, $sqlfilters = '') { @@ -622,6 +624,8 @@ class Proposals extends DolibarrApi * @param string $type Type of the external contact (BILLING, SHIPPING, CUSTOMER), internal contact (SALESREPFOLL) * @param string $source Source of the contact (internal, external) * @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} * diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index c4890f69f67..69f467d2b51 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -338,6 +338,8 @@ class Orders extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return OrderLine[] + * @phpstan-return OrderLine[] */ public function getLines($id) { @@ -1037,6 +1039,8 @@ class Orders extends DolibarrApi * @url GET {id}/shipment * * @return array + * @phan-return Expedition[] + * @phpstan-return Expedition[] * * @throws RestException 401 * @throws RestException 404 diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index e86deabfe43..125150dd63c 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -62,6 +62,8 @@ class BankAccounts extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.import_key:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array List of account objects + * @phan-return Account[] + * @phpstan-return Account[] * * @throws RestException */ @@ -271,14 +273,14 @@ class BankAccounts extends DolibarrApi */ if (!$error) { - $bank_line_id_from = $accountfrom->addline($date, $typefrom, $description, -1 * (float) price2num($amount), '', '', $user, $cheque_number); + $bank_line_id_from = $accountfrom->addline((int) $date, $typefrom, $description, -1 * (float) price2num($amount), '', 0, $user, $cheque_number); } if (!($bank_line_id_from > 0)) { $error++; } if (!$error) { - $bank_line_id_to = $accountto->addline($date, $typeto, $description, price2num($amount_to), '', '', $user, $cheque_number); + $bank_line_id_to = $accountto->addline((int) $date, $typeto, $description, (float) price2num($amount_to), '', 0, $user, $cheque_number); } if (!($bank_line_id_to > 0)) { $error++; @@ -446,6 +448,8 @@ class BankAccounts extends DolibarrApi * * @param int $id ID of account * @return array Array of AccountLine objects + * @phan-return AccountLine[] + * @phpstan-return AccountLine[] * * @throws RestException * @@ -538,7 +542,7 @@ class BankAccounts extends DolibarrApi $num_releve = sanitizeVal($num_releve); $result = $account->addline( - $date, + (int) $date, $type, $label, $amount, @@ -548,7 +552,7 @@ class BankAccounts extends DolibarrApi $cheque_writer, $cheque_bank, $accountancycode, - $datev, + (int) $datev, $num_releve ); if ($result < 0) { @@ -605,6 +609,8 @@ class BankAccounts extends DolibarrApi * @param int $id ID of account * @param int $line_id ID of account line * @return array Array of links + * @phan-return array + * @phpstan-return array * * @throws RestException * diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 9a214e95a18..bc10b732054 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -448,6 +448,8 @@ class Invoices extends DolibarrApi * * @param int $id Id of invoice * @return array Array of lines + * @phan-return CommonInvoiceLine[] + * @phpstan-return CommonInvoiceLine[] * * @url GET {id}/lines */ @@ -1448,6 +1450,8 @@ class Invoices extends DolibarrApi * * @param int $id Id of invoice * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/payments * @@ -1475,7 +1479,7 @@ class Invoices extends DolibarrApi } $result = $this->invoice->getListOfPayments(); - if ($result < 0) { + if (!is_array($result) && $result < 0) { throw new RestException(405, $this->invoice->error); } @@ -1662,7 +1666,7 @@ class Invoices extends DolibarrApi // Loop on each invoice to pay foreach ($arrayofamounts as $id => $amountarray) { - $result = $this->invoice->fetch($id); + $result = $this->invoice->fetch((int) $id); if (!$result) { $this->db->rollback(); throw new RestException(404, 'Invoice ID '.$id.' not found'); diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index d53f60c940b..674cb399081 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -244,6 +244,8 @@ class Contracts extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return ContratLigne[] + * @phpstan-return ContratLigne[] */ public function getLines($id) { @@ -417,7 +419,7 @@ class Contracts extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, $datestart, $dateend, $comment); + $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, (int) $datestart, $dateend, $comment); if ($updateRes > 0) { $result = $this->get($id); @@ -455,7 +457,7 @@ class Contracts extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, $datestart, $comment); + $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, (int) $datestart, $comment); if ($updateRes > 0) { $result = $this->get($id); diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 47652e94d1d..45799c1ff6e 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2005-2013 Regis Houssin * Copyright (C) 2012-2014 Juanjo Menent * Copyright (C) 2022 Ferran Marcet - * 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 @@ -983,7 +983,7 @@ class modSociete extends DolibarrModules 'sr.datec' => 'date used for creating direct debit UMR formatted as '.dol_print_date( dol_now(), '%Y-%m-%d' - ), + ), 'sr.bank' => 'bank name eg: "ING-Direct"', 'sr.code_banque' => 'account sort code (GB)/Routing number (US) eg. "8456"', 'sr.code_guichet' => "bank code for office/branch", diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 49fc7e4ce8f..080805676cc 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -408,6 +408,8 @@ class SupplierInvoices extends DolibarrApi * @url GET {id}/payments * * @return array + * @phan-return array + * @phpstan-return array * @throws RestException 400 * @throws RestException 403 * @throws RestException 404 @@ -550,6 +552,8 @@ class SupplierInvoices extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return CommonInvoiceLine[] + * @phpstan-return CommonInvoiceLine[] * * @throws RestException 403 * @throws RestException 404 @@ -631,7 +635,7 @@ class SupplierInvoices extends DolibarrApi $request_data->price_base_type ? $request_data->price_base_type : 'HT', $request_data->product_type, $request_data->rang, - false, + 0, $request_data->array_options, $request_data->fk_unit, $request_data->origin_id, @@ -697,7 +701,7 @@ class SupplierInvoices extends DolibarrApi $request_data->info_bits, $request_data->product_type, $request_data->remise_percent, - false, + 0, $request_data->date_start, $request_data->date_end, $request_data->array_options, diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index 06bf957bf1f..b77c5c28e7c 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; class SupplierOrders extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid' diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index 2b4fc1d20c5..1f789d19b54 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -330,7 +330,7 @@ class KnowledgeManagement extends DolibarrApi // Clean data // $this->knowledgerecord->abc = sanitizeVal($this->knowledgerecord->abc, 'alphanohtml'); - if ($this->knowledgerecord->update(DolibarrApiAccess::$user, false) > 0) { + if ($this->knowledgerecord->update(DolibarrApiAccess::$user, 0) > 0) { return $this->get($id); } else { throw new RestException(500, $this->knowledgerecord->error); diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php index c9437431d10..03c1df80d15 100644 --- a/htdocs/multicurrency/class/api_multicurrencies.class.php +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -51,6 +51,8 @@ class MultiCurrencies extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) 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 warehouse objects + * @phan-return MultiCurrency[] + * @phpstan-return MultiCurrency[] * * @throws RestException */ @@ -234,7 +236,7 @@ class MultiCurrencies extends DolibarrApi // Add default rate if defined if (isset($request_data['rate']) && $request_data['rate'] > 0) { - if ($multicurrency->addRate($request_data['rate']) < 0) { + if ($multicurrency->addRate((float) $request_data['rate']) < 0) { throw new RestException(500, "Error adding currency rate", array_merge(array($multicurrency->error), $multicurrency->errors)); } @@ -349,7 +351,7 @@ class MultiCurrencies extends DolibarrApi } // Add rate - if ($multicurrency->addRate($request_data['rate']) < 0) { + if ($multicurrency->addRate((float) $request_data['rate']) < 0) { throw new RestException(500, "Error updating currency rate", array_merge(array($multicurrency->error), $multicurrency->errors)); } diff --git a/htdocs/partnership/class/api_partnerships.class.php b/htdocs/partnership/class/api_partnerships.class.php index 6be059f25f9..34078bf00a6 100644 --- a/htdocs/partnership/class/api_partnerships.class.php +++ b/htdocs/partnership/class/api_partnerships.class.php @@ -97,6 +97,8 @@ class Partnerships 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 Partnership[] + * @phpstan-return Partnership[] * * @throws RestException * @@ -266,7 +268,7 @@ class Partnerships extends DolibarrApi // Clean data // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); - if ($this->partnership->update(DolibarrApiAccess::$user, false) > 0) { + if ($this->partnership->update(DolibarrApiAccess::$user, 0) > 0) { return $this->get($id); } else { throw new RestException(500, $this->partnership->error); diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 17b3d31f93c..746ad2d6a24 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -566,6 +566,8 @@ class Products extends DolibarrApi * * @param int $id Id of parent product/service * @return array + * @phan-return array + * @phpstan-return array * * @throws RestException * @throws RestException 401 @@ -766,9 +768,9 @@ class Products extends DolibarrApi require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; $prodcustprice = new ProductCustomerPrice($this->db); $filter = array(); - $filter['t.fk_product'] = $id; + $filter['t.fk_product'] = (string) $id; if ($thirdparty_id) { - $filter['t.fk_soc'] = $thirdparty_id; + $filter['t.fk_soc'] = (string) $thirdparty_id; } $result = $prodcustprice->fetchAll('', '', 0, 0, $filter); } @@ -942,6 +944,8 @@ class Products extends DolibarrApi * @param int $supplier Use this param to filter list by supplier * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)" * @return array Array of product objects + * @phan-return array + * @phpstan-return array * * @url GET purchase_prices */ @@ -1045,7 +1049,9 @@ class Products extends DolibarrApi * @param string $ref Ref of element * @param string $ref_ext Ref ext of element * @param string $barcode Barcode of element - * @return array|mixed Data without useless information + * @return array Data without useless information + * @phan-return ProductFournisseur[] + * @phpstan-return ProductFournisseur[] * * @url GET {id}/purchase_prices * @@ -1100,6 +1106,8 @@ class Products extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:color)" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array + * @phan-return ProductAttribute[] + * @phpstan-return ProductAttribute[] * * @throws RestException 401 * @throws RestException 404 @@ -1206,6 +1214,8 @@ class Products extends DolibarrApi * * @param string $ref Reference of Attribute * @return array + * @phan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} + * @phpstan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} * * @throws RestException 401 * @throws RestException 404 @@ -1231,13 +1241,13 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attr = array(); - $attr['id'] = $result->rowid; - $attr['ref'] = $result->ref; - $attr['ref_ext'] = $result->ref_ext; - $attr['label'] = $result->label; - $attr['rang'] = $result->position; - $attr['position'] = $result->position; - $attr['entity'] = $result->entity; + $attr['id'] = (int) $result->rowid; + $attr['ref'] = (string) $result->ref; + $attr['ref_ext'] = (string) $result->ref_ext; + $attr['label'] = (string) $result->label; + $attr['rang'] = (int) $result->position; + $attr['position'] = (int) $result->position; + $attr['entity'] = (string) $result->entity; $sql = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."product_attribute_combination2val as pac2v"; $sql .= " JOIN ".$this->db->prefix()."product_attribute_combination as pac ON pac2v.fk_prod_combination = pac.rowid"; @@ -1256,6 +1266,8 @@ class Products extends DolibarrApi * * @param string $ref_ext External reference of Attribute * @return array + * @phan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} + * @phpstan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} * * @throws RestException 500 System error * @throws RestException 401 @@ -1281,13 +1293,13 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attr = array(); - $attr['id'] = $result->rowid; - $attr['ref'] = $result->ref; - $attr['ref_ext'] = $result->ref_ext; - $attr['label'] = $result->label; - $attr['rang'] = $result->position; - $attr['position'] = $result->position; - $attr['entity'] = $result->entity; + $attr['id'] = (int) $result->rowid; + $attr['ref'] = (string) $result->ref; + $attr['ref_ext'] = (string) $result->ref_ext; + $attr['label'] = (string) $result->label; + $attr['rang'] = (int) $result->position; + $attr['position'] = (int) $result->position; + $attr['entity'] = (string) $result->entity; $sql = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."product_attribute_combination2val as pac2v"; $sql .= " JOIN ".$this->db->prefix()."product_attribute_combination as pac ON pac2v.fk_prod_combination = pac.rowid"; @@ -1422,6 +1434,8 @@ class Products extends DolibarrApi * * @param int $id ID of Attribute value * @return array + * @phan-return array{id:int,fk_product_attribute:int,ref:string,value:string} + * @phpstan-return array{id:int,fk_product_attribute:int,ref:string,value:string} * * @throws RestException 500 System error * @throws RestException 401 @@ -1449,8 +1463,8 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attrval = array(); - $attrval['id'] = $result->rowid; - $attrval['fk_product_attribute'] = $result->fk_product_attribute; + $attrval['id'] = (int) $result->rowid; + $attrval['fk_product_attribute'] = (int) $result->fk_product_attribute; $attrval['ref'] = $result->ref; $attrval['value'] = $result->value; @@ -1463,6 +1477,8 @@ class Products extends DolibarrApi * @param int $id ID of Attribute value * @param string $ref Ref of Attribute value * @return array + * @phan-return array{id:int,fk_product_attribute:int,ref:string,value:string} + * @phpstan-return array{id:int,fk_product_attribute:int,ref:string,value:string} * * @throws RestException 500 System error * @throws RestException 401 @@ -1493,11 +1509,10 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attrval = array(); - $attrval['id'] = $result->rowid; - $attrval['fk_product_attribute'] = $result->fk_product_attribute; + $attrval['id'] = (int) $result->rowid; + $attrval['fk_product_attribute'] = (int) $result->fk_product_attribute; $attrval['ref'] = $result->ref; $attrval['value'] = $result->value; - return $attrval; } @@ -1549,6 +1564,8 @@ class Products extends DolibarrApi * * @param int $id ID of an Attribute * @return array + * @phan-return ProductAttributeValue[] + * @phpstan-return ProductAttributeValue[] * * @throws RestException 401 * @throws RestException 500 System error @@ -1581,6 +1598,8 @@ class Products extends DolibarrApi * * @param string $ref Ref of an Attribute * @return array + * @phan-return ProductAttributeValue[] + * @phpstan-return ProductAttributeValue[] * * @throws RestException 401 * @@ -1736,6 +1755,8 @@ class Products extends DolibarrApi * @param int $id ID of Product * @param int $includestock Default value 0. If parameter is set to 1 the response will contain stock data of each variant * @return array + * @phan-return ProductCombination[] + * @phpstan-return ProductCombination[] * * @throws RestException 500 System error * @throws RestException 401 @@ -1759,7 +1780,7 @@ class Products extends DolibarrApi if (!empty($includestock) && DolibarrApiAccess::$user->hasRight('stock', 'lire')) { $productModel = new Product($this->db); $productModel->fetch((int) $combination->fk_product_child); - $productModel->load_stock($includestock); + $productModel->load_stock((string) $includestock); $combinations[$key]->stock_warehouse = $this->_cleanObjectDatas($productModel)->stock_warehouse; } } @@ -1772,6 +1793,8 @@ class Products extends DolibarrApi * * @param string $ref Ref of Product * @return array + * @phan-return ProductCombination[] + * @phpstan-return ProductCombination[] * * @throws RestException 500 System error * @throws RestException 401 @@ -1842,6 +1865,7 @@ class Products extends DolibarrApi $prodattr = new ProductAttribute($this->db); $prodattr_val = new ProductAttributeValue($this->db); + $cleanedFeatures = array(); foreach ($features as $id_attr => $id_value) { if ($prodattr->fetch((int) $id_attr) < 0) { throw new RestException(400, 'Invalid attribute ID: '.$id_attr); @@ -1849,6 +1873,7 @@ class Products extends DolibarrApi if ($prodattr_val->fetch((int) $id_value) < 0) { throw new RestException(400, 'Invalid attribute value ID: '.$id_value); } + $cleanedFeatures[(int) $id_attr] = (int) $id_value; } $result = $this->product->fetch((int) $id); @@ -1858,7 +1883,7 @@ class Products extends DolibarrApi $prodcomb = new ProductCombination($this->db); - $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact, $reference, $ref_ext); + $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $cleanedFeatures, array(), $price_impact_is_percent, (is_numeric($price_impact) ? (float) $price_impact : false), (is_numeric($weight_impact) ? (float) $weight_impact : false), $reference, $ref_ext); if ($result > 0) { return $result; } else { @@ -1901,6 +1926,7 @@ class Products extends DolibarrApi $prodattr = new ProductAttribute($this->db); $prodattr_val = new ProductAttributeValue($this->db); + $cleanedFeatures = []; foreach ($features as $id_attr => $id_value) { if ($prodattr->fetch((int) $id_attr) < 0) { throw new RestException(404); @@ -1908,6 +1934,7 @@ class Products extends DolibarrApi if ($prodattr_val->fetch((int) $id_value) < 0) { throw new RestException(404); } + $cleanedFeatures[(int) $id_attr] = (int) $id_value; } $result = $this->product->fetch(0, trim($ref)); @@ -1916,8 +1943,8 @@ class Products extends DolibarrApi } $prodcomb = new ProductCombination($this->db); - if (!$prodcomb->fetchByProductCombination2ValuePairs($this->product->id, $features)) { - $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact); + if (!$prodcomb->fetchByProductCombination2ValuePairs($this->product->id, $cleanedFeatures)) { + $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $cleanedFeatures, array(), $price_impact_is_percent, (is_numeric($price_impact) ? (float) $price_impact : false), (is_numeric($weight_impact) ? (float) $weight_impact : false)); if ($result > 0) { return $result; } else { @@ -2042,10 +2069,14 @@ class Products extends DolibarrApi // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore /** - * Clean sensible object datas + * Clean sensitive object data + * @phpstan-template T of Object * * @param Object $object Object to clean * @return Object Object with cleaned properties + * + * @phpstan-param T $object + * @phpstan-return T */ protected function _cleanObjectDatas($object) { @@ -2170,7 +2201,7 @@ class Products extends DolibarrApi } if (!empty($includestockdata) && DolibarrApiAccess::$user->hasRight('stock', 'lire')) { - $this->product->load_stock($includestockdata); + $this->product->load_stock((string) $includestockdata); if (is_array($this->product->stock_warehouse)) { foreach ($this->product->stock_warehouse as $keytmp => $valtmp) { diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index 2a51192218b..7d611017be6 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; class StockMovements extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'product_id', @@ -92,6 +92,8 @@ class StockMovements extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) 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 warehouse objects + * @phan-return MouvementStock[] + * @phpstan-return MouvementStock[] * * @throws RestException */ @@ -198,7 +200,7 @@ class StockMovements extends DolibarrApi $dateMvt = empty($datem) ? '' : dol_stringtotime($datem); $this->stockmovement->setOrigin($origin_type, $origin_id); - if ($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, $dateMvt, $eatBy, $sellBy, $lot) <= 0) { + if ($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, (float) $price, $movementlabel, $movementcode, $dateMvt, $eatBy, $sellBy, $lot) <= 0) { $errormessage = $this->stockmovement->error; if (empty($errormessage)) { $errormessage = implode(',', $this->stockmovement->errors); diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php index c4fd8472e5f..6c7c8011298 100644 --- a/htdocs/product/stock/class/api_warehouses.class.php +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; class Warehouses extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'label', @@ -92,6 +92,8 @@ class Warehouses extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'WH-%') 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 warehouse objects + * @phan-return Entrepot[] + * @phpstan-return Entrepot[] * * @throws RestException */ diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 774cebd33d4..85710483550 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; class Tasks extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'ref', @@ -106,6 +106,8 @@ class Tasks 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 project objects + * @phan-return Task[] + * @phpstan-return Task[] */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '') { @@ -132,7 +134,7 @@ class Tasks extends DolibarrApi $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet AS p ON p.rowid = t.fk_projet"; $sql .= ' WHERE t.entity IN ('.getEntity('project').')'; if ($socids) { - $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")"; + $sql .= " AND t.fk_soc IN (".$this->db->sanitize((string) $socids).")"; } // Search on sale representative if ($search_sale && $search_sale != '-1') { @@ -270,6 +272,8 @@ class Tasks extends DolibarrApi * @param int $id Id of task * @param int $userid Id of user (0 = connected user) * @return array Array of roles + * @phan-return array + * @phpstan-return array * * @url GET {id}/roles */ @@ -295,7 +299,7 @@ class Tasks extends DolibarrApi $usert = new User($this->db); $usert->fetch($userid); } - $this->task->roles = $this->task->getUserRolesForProjectsOrTasks(null, $usert, 0, $id); + $this->task->roles = $this->task->getUserRolesForProjectsOrTasks(null, $usert, '0', $id); $result = array(); foreach ($this->task->roles as $line) { array_push($result, $this->_cleanObjectDatas($line)); @@ -531,6 +535,7 @@ class Tasks extends DolibarrApi * * @param int $id Task ID * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) + * @phan-param string $date * @param int $duration Duration in seconds (3600 = 1h) * @param int $user_id User (Use 0 for connected user) * @param string $note Note @@ -593,6 +598,7 @@ class Tasks extends DolibarrApi * @param int $id Task ID * @param int $timespent_id Time spent ID (llx_element_time.rowid) * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) + * @phan-param string $date * @param int $duration Duration in seconds (3600 = 1h) * @param int $user_id User (Use 0 for connected user) * @param string $note Note @@ -696,10 +702,14 @@ class Tasks extends DolibarrApi // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore /** - * Clean sensible object datas + * Clean sensitive object data + * @phpstan-template T of Object * * @param Object $object Object to clean * @return Object Object with cleaned properties + * + * @phpstan-param T $object + * @phpstan-return T */ protected function _cleanObjectDatas($object) { diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index 68cc80eaa61..f860207193a 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -765,12 +765,15 @@ class Receptions extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify + * @param ?array $data Array with data to verify * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $reception = array(); foreach (Receptions::$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 8470768b1b1..4d1171ce34d 100644 --- a/htdocs/salaries/class/api_salaries.class.php +++ b/htdocs/salaries/class/api_salaries.class.php @@ -41,7 +41,7 @@ class Salaries extends DolibarrApi ); /** - * string[] $FIELDS Mandatory fields, checked when creating an object + * @var string[] Mandatory fields for mayment, checked when creating an object */ public static $FIELDSPAYMENT = array( "paiementtype", @@ -68,6 +68,8 @@ class Salaries extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array List of salary objects + * @phan-return Salary[] + * @phpstan-return Salary[] * * @throws RestException */ @@ -235,6 +237,8 @@ class Salaries extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array List of paymentsalary objects + * @phan-return PaymentSalary[] + * @phpstan-return PaymentSalary[] * * @url GET /payments * diff --git a/htdocs/societe/canvas/actions_card_common.class.php b/htdocs/societe/canvas/actions_card_common.class.php index 860c3e071f6..2876c174b10 100644 --- a/htdocs/societe/canvas/actions_card_common.class.php +++ b/htdocs/societe/canvas/actions_card_common.class.php @@ -357,7 +357,7 @@ abstract class ActionsCardCommon $i = 0; foreach ($listsalesrepresentatives as $val) { $userstatic->id = $val['id']; - $userstatic->lastname = $val['name']; + $userstatic->lastname = $val['lastname']; $userstatic->firstname = $val['firstname']; $this->tpl['sales_representatives'] .= $userstatic->getNomUrl(1); $i++; diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 4517ed911e9..f7e5c811a03 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -86,6 +86,8 @@ class Thirdparties extends DolibarrApi * * @param string $email Email of third party to load * @return array|mixed Cleaned Societe object + * @phan-return Societe + * @phpstan-return Societe * * @url GET email/{email} * @@ -303,7 +305,9 @@ class Thirdparties extends DolibarrApi * @param array $request_data Data * @phan-param ?array $request_data * @phpstan-param ?array $request_data - * @return Object|false Updated object + * @return Object Updated object + * @phan-return Societe + * @phpstan-return Societe * * @throws RestException 401 * @throws RestException 404 @@ -364,6 +368,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty to keep (the target third party) * @param int $idtodelete ID of thirdparty to remove (the thirdparty to delete), once data has been merged into the target third party. * @return Object Return the resulted third party. + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/merge/{idtodelete} */ @@ -425,7 +431,7 @@ class Thirdparties extends DolibarrApi if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) { throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $this->company->oldcopy = clone $this->company; + $this->company->oldcopy = clone $this->company; // @phan-suppress-current-line PhanTypeMismatchProperty $res = $this->company->delete($id); if ($res < 0) { @@ -578,7 +584,9 @@ class Thirdparties extends DolibarrApi * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number - * @return array|void + * @return array + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @url GET {id}/categories */ @@ -613,7 +621,9 @@ class Thirdparties extends DolibarrApi * * @param int $id Id of thirdparty * @param int $category_id Id of category - * @return Object|void + * @return Object + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/categories/{category_id} */ @@ -651,7 +661,9 @@ class Thirdparties extends DolibarrApi * @param int $id Id of thirdparty * @param int $category_id Id of category * - * @return Object|void + * @return Object + * @phan-return Societe + * @phpstan-return Societe * * @url DELETE {id}/categories/{category_id} */ @@ -692,7 +704,9 @@ class Thirdparties extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * - * @return mixed + * @return array + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @url GET {id}/supplier_categories */ @@ -729,6 +743,8 @@ class Thirdparties extends DolibarrApi * @param int $category_id Id of category * * @return mixed + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/supplier_categories/{category_id} */ @@ -767,6 +783,8 @@ class Thirdparties extends DolibarrApi * @param int $category_id Id of category * * @return mixed + * @phan-return Societe + * @phpstan-return Societe * * @url DELETE {id}/supplier_categories/{category_id} */ @@ -808,6 +826,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/outstandingproposals * * @return array List of outstandings proposals of thirdparty + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -850,6 +870,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/outstandingorders * * @return array List of outstandings orders of thirdparty + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -890,7 +912,9 @@ class Thirdparties extends DolibarrApi * * @url GET {id}/outstandinginvoices * - * @return array List of outstandings invoices of thirdparty + * @return array List of outstanding invoices of third party + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -932,6 +956,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/representatives * * @return array List of representatives of thirdparty + * @phan-return int[]|array + * @phpstan-return int[]|array * * @throws RestException 400 * @throws RestException 401 @@ -952,7 +978,7 @@ class Thirdparties extends DolibarrApi } $result = $this->company->fetch($id); - if (!$result) { + if (!is_array($result)) { throw new RestException(404, 'Thirdparty not found'); } @@ -972,6 +998,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/fixedamountdiscounts * * @return array List of fixed discount of thirdparty + * @phan-return stdClass[] + * @phpstan-return stdClass[] * * @throws RestException 400 * @throws RestException 401 @@ -1035,6 +1063,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/getinvoicesqualifiedforreplacement * * @return array + * @phan-return array|int + * @phpstan-return array|int * @throws RestException 400 * @throws RestException 401 * @throws RestException 404 @@ -1078,6 +1108,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/getinvoicesqualifiedforcreditnote * * @return array + * @phan-return array|int + * @phpstan-return array|int * * @throws RestException 400 * @throws RestException 401 @@ -1105,7 +1137,7 @@ class Thirdparties extends DolibarrApi require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $invoice = new Facture($this->db); $result = $invoice->list_qualified_avoir_invoices($id); - if ($result < 0) { + if (!is_array($result) && $result < 0) { throw new RestException(405, $invoice->error); } @@ -1118,6 +1150,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty * * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/notifications */ @@ -1177,6 +1211,7 @@ class Thirdparties extends DolibarrApi $returnNotifications[] = $object; } + // Too complex for phan ?: @phan-suppress-next-line PhanTypeMismatchReturn return $returnNotifications; } @@ -1217,9 +1252,9 @@ class Thirdparties extends DolibarrApi $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem"; $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def"; - $exists_sql .= " WHERE fk_action = '".$this->db->escape($event)."'"; - $exists_sql .= " AND fk_soc = '".$this->db->escape($socid)."'"; - $exists_sql .= " AND fk_contact = '".$this->db->escape($contact_id)."'"; + $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'"; + $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'"; + $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'"; $exists_result = $this->db->query($exists_sql); if ($this->db->num_rows($exists_result) > 0) { @@ -1287,9 +1322,9 @@ class Thirdparties extends DolibarrApi $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem"; $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def"; - $exists_sql .= " WHERE fk_action = '".$this->db->escape($event)."'"; - $exists_sql .= " AND fk_soc = '".$this->db->escape($socid)."'"; - $exists_sql .= " AND fk_contact = '".$this->db->escape($contact_id)."'"; + $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'"; + $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'"; + $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'"; $exists_result = $this->db->query($exists_sql); if ($this->db->num_rows($exists_result) > 0) { @@ -1383,6 +1418,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty * * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/bankaccounts */ @@ -1498,7 +1535,7 @@ class Thirdparties extends DolibarrApi if (empty($account->rum)) { require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; $prelevement = new BonPrelevement($this->db); - $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id); + $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, (string) $account->id); $account->date_rum = dol_now(); } @@ -1553,7 +1590,7 @@ class Thirdparties extends DolibarrApi if (empty($account->rum)) { require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; $prelevement = new BonPrelevement($this->db); - $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id); + $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, (string) $account->id); $account->date_rum = dol_now(); } @@ -1600,6 +1637,8 @@ class Thirdparties extends DolibarrApi * @param int $companybankid Companybank id * @param string $model Model of document to generate * @return array + * @phan-return array{success:int<0,1>} + * @phpstan-return array{success:int<0,1>} * * @url GET {id}/generateBankAccountDocument/{companybankid}/{model} */ @@ -2024,7 +2063,7 @@ class Thirdparties extends DolibarrApi * Delete a specific site account attached to a thirdparty (by account id) * * @param int $id ID of thirdparty - * @param int $site Site key + * @param string $site Site key * * @return void * @throws RestException 401 Unauthorized: User does not have permission to delete thirdparties accounts @@ -2183,6 +2222,8 @@ class Thirdparties extends DolibarrApi * @param string $email Email of third party (Warning, this can return several records) * @param string $ref_alias Name_alias of third party (Warning, this can return several records) * @return object cleaned Societe object + * @phan-return Societe + * @phpstan-return Societe * * @throws RestException */ @@ -2192,7 +2233,7 @@ class Thirdparties extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login.'. No read permission on thirdparties.'); } - if ($rowid === 0) { + if ($rowid == 0) { $result = $this->company->initAsSpecimen(); } else { $result = $this->company->fetch($rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias); @@ -2216,8 +2257,8 @@ class Thirdparties extends DolibarrApi $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')"; } - $absolute_discount = $this->company->getAvailableDiscounts('', $filterabsolutediscount); - $absolute_creditnote = $this->company->getAvailableDiscounts('', $filtercreditnote); + $absolute_discount = $this->company->getAvailableDiscounts(null, $filterabsolutediscount); + $absolute_creditnote = $this->company->getAvailableDiscounts(null, $filtercreditnote); $this->company->absolute_discount = price2num($absolute_discount, 'MT'); $this->company->absolute_creditnote = price2num($absolute_creditnote, 'MT'); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 1828e733dba..94f69e34908 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -85,7 +85,7 @@ class Societe extends CommonObject public $fieldsforcombobox = 'nom,name_alias'; /** - * @var array> List of child tables. To test if we can delete object. + * @var array List of child tables. To test if we can delete object. */ protected $childtables = array( 'supplier_proposal' => array('name' => 'SupplierProposal'), @@ -2674,10 +2674,10 @@ class Societe extends CommonObject * Return array of sales representatives * * @param User $user Object user (not used) - * @param int $mode 0=Array with properties, 1=Array of IDs. + * @param int<0,1> $mode 0=Array with properties, 1=Array of IDs. * @param ?string $sortfield List of sort fields, separated by comma. Example: 't1.fielda,t2.fieldb' * @param ?string $sortorder Sort order, separated by comma. Example: 'ASC,DESC'; - * @return array|int Array of sales representatives of the current third party or <0 if KO + * @return int<-1,-1>|int[]|array Array of sales representatives of the current third party or <0 if KO */ public function getSalesRepresentatives(User $user, $mode = 0, $sortfield = null, $sortorder = null) { @@ -2712,7 +2712,7 @@ class Societe extends CommonObject $obj = $this->db->fetch_object($resql); if (empty($mode)) { - $reparray[$i]['id'] = $obj->rowid; + $reparray[$i]['id'] = (int) $obj->rowid; $reparray[$i]['lastname'] = $obj->lastname; $reparray[$i]['firstname'] = $obj->firstname; $reparray[$i]['email'] = $obj->email; @@ -2729,7 +2729,7 @@ class Societe extends CommonObject $reparray[$i]['photo'] = $obj->photo; $reparray[$i]['gender'] = $obj->gender; } else { - $reparray[] = $obj->rowid; + $reparray[] = (int) $obj->rowid; } $i++; } diff --git a/htdocs/webhook/class/api_webhook.class.php b/htdocs/webhook/class/api_webhook.class.php index 32474da267c..95aad63f9b8 100644 --- a/htdocs/webhook/class/api_webhook.class.php +++ b/htdocs/webhook/class/api_webhook.class.php @@ -261,6 +261,8 @@ class Webhook extends DolibarrApi * Get the list of all available triggers * * @return array + * @phan-return array + * @phpstan-return array * * @url GET triggers */ diff --git a/htdocs/zapier/class/api_zapier.class.php b/htdocs/zapier/class/api_zapier.class.php index d917d192024..859d2f7a598 100644 --- a/htdocs/zapier/class/api_zapier.class.php +++ b/htdocs/zapier/class/api_zapier.class.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/zapier/class/hook.class.php'; class Zapier extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'url',