dolibarr/htdocs/user/class/user.class.php

4567 lines
155 KiB
PHP
Raw Permalink Normal View History

<?php
/* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (c) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (c) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
* Copyright (C) 2005-2024 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2005 Lionel Cousteix <etm_ltd@tiscali.co.uk>
* Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
* Copyright (C) 2013-2019 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2013-2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2018 charlene Benke <charlie@patas-monkey.com>
2024-03-29 13:04:02 +00:00
* Copyright (C) 2018-2021 Nicolas ZABOURI <info@inovea-conseil.com>
NEW: #0 Resolve password generator/validator classes via modules_parts['models'] (#39486) Password generator/validator classes (USER_PASSWORD_GENERATED, modGeneratePassXxx extends ModeleGenPassword) could previously only live under htdocs/core/modules/security/generate/ — every call site resolving one by name hardcoded that path, so no third-party module could contribute its own generator without patching core. Reuse the modules_parts['models'] extension point already populated for any enabled module declaring $this->module_parts['models'] = 1 (the same mechanism every numbering-module scan in Dolibarr already uses — see e.g. Facture::getNextNumRef()), and wire it into the password-generator scan too: - admin/security.php's generator listing now scans core plus every enabled module declaring module_parts['models'], instead of only core/modules/security/generate/. - Added ModeleGenPassword::loadAndInstantiate($id, ...) in modules_genpassword.php, a shared factory doing that same multi-root resolution once, used by the four runtime call sites that previously hardcoded the core-only path: User::setPassword(), getRandomPassword() (security2.lib.php), FormSetupItem::generateInputFieldPassword() (html.formsetup.class.php), and PasswordField::verifyFieldValue() (passwordfield.class.php). getRandomPassword() falls back to the 'standard' generator (with a warning logged) if the configured generator's class can't be resolved, rather than silently generating and persisting an empty password. Behavior for the built-in Standard/None/Perso generators is unchanged — core is always the first root scanned, so it always wins for those ids.
2026-08-14 14:19:48 +00:00
* Copyright (C) 2019-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2019 Abbes Bahfir <dolipar@dolipar.org>
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
2024-03-29 13:04:02 +00:00
* Copyright (C) 2024 Lenin Rivas <lenin.rivas777@gmail.com>
NEW - Add substitution for user warehouse (#36670) * Fix trans and warning * Doc * Debug v23 * Debug v23 * Debug v23 * Doc * New import Leave Balance (Datastructure) (#37001) * New import Leave Balance (Datastructure) * fix --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> * Qual: Update Phan baseline.txt with reduced issue counts (#36996) This commit updates the Phan baseline.txt file. * Better log * Log * Better error management * Doc * Fix error message * CI * Try to fix CI * fix phan (#37007) * CI * fix phan (#37008) PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable) * CI * NEW Add new EUID number (#36997) * Doc * ci * Fix CI * Improve OAuth HTTP error details (#36951) Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins. Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add import of leave balance (Implementation) (#37011) * New add import Leave Balance * add eof * Update modHoliday.class.php --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add image format avif (#37014) * add format avif * Update functions.lib.php * Exclude non interesting warning * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * CI * CI * Trans * CI * CI * CI * Fix typo in phpstan.neon.dist for isset() rule (#37018) See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Try to fix phan * CI * CI * ci * ci * css * qual: Update french texts (comments) to english (#37009) * qual: Update french texts (comments) to english * Qual: Update comment to english in card-rec.php and card.php Translation of comments in the files card-rec.php and card.php. * Qual: Translate comments to English * Qual: Translate comments to English * Fix space into tab * Fix spelling * Qual: Translate comments to English * Update website.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * ci * Clean code * Fix test * Debug v23 * Merge manually changes from #37012 that seems good. * Log * More robust phpunit * Populate openid data from wellknow url (#37023) * Delete inexistant file File jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Populate openid parameters from wellknow url * CI * Debug v23 - fix code for rounding * MCP server sql part (#37025) * Create llx_ai_request_log.sql * Create llx_ai_request_log.key.sql * Update 23.0.0-24.0.0.sql * Update llx_ai_request_log.sql * Update 23.0.0-24.0.0.sql * Remove foreign key constraint from llx_ai_request_log Removed foreign key constraint for fk_user in llx_ai_request_log. --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v24 * Fix syntax error * NEW allow to disable freezone product on takepos (#37004) * allow to disable freezone product on takepos * Conditionally add FreeZone product to menus * Add NoFreeZoneProduct language entry --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix label of dispute * [database] Minimum amount and subscription's amount formula description (#37021) * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * css * Update llx_adherent_type.sql add minimumamount and amountformuladescription rows * Update 22.0.0-23.0.0.sql add minimumamount and amountformuladescription column --------- Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW: Display thirdparty name with ref in supplier orders linked objects (#36952) Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> * css * Debug v23 * Fix type * CI * CI * Test without file list * CI * Add api document management for holiday (#36915) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Invoice - List - use select2 multiselect for status (#36834) * NEW Invoice - List - use select2 multiselect for status * Optimize * CI * CI * Review * Duplicate line and last problem * CI --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX Pb in total price of line when adding the discount of a down payment when unit price was using a high accuracy. * Clean code * try to fix phan * Fix phan * Clean code * Clean code * Debug v23 * Fix LDAP * fix facture.class.php (#37031) * Debug v23 * Qual: Update french comments with 'nombre' (#37032) Update french comments with 'nombre' in their phrasing Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37029) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37030) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Doc * Doc comment * FIX When bank direct debit SEPA ref is > 99 * Fix when there is more than 99 direct debit in same month * Debug v24 * Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 * CSS * Fix when there is more than 99 direct debit in same month * Debug v24 * FIX Division by zero * FIX Division by zero * More log * More log * More log * More Log * Fix IPN payment * Fix IPN * Log * Clean code * Debug v23 - Fix ipn for dispute and withdraw funds. * fix CI (#37033) * fix CI (#37033) * CI * fix french doc (#36897) * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * Update html.form.class.php * Update html.form.class.php * Update index.php * fix * fix * fix * fix * fix * fix * fix * fix * Update modules_facture.php * Update phpstan.neon.dist --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Translate French comments to English (#37044) * Qual: Translate French comments to English * Qual: Translate French comments to English * Qual: Translate French comments to English ("niveau") (#37041) Translate French comments to English (comments with "niveau") * fix french doc (#37040) * warning error if no societe->id defined (#37039) * fix french doc (#37037) * fix french doc * Update dispatch.php * Update dispatch.php * Update graph.php * fix french doc (#37047) * fix french doc * Update index.php * Update index.php * Fix CI * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * Fix CI * Minimum amount and subscription's amount formula description (#37006) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043) * Warning on export - Add isset() protection in Export::load_arrays() * Warning on import - Add isset() protection in Import::load_arrays() --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Clean comment * Warning on account model (#37042) * Error on account model * Simplify rowid assignment in accountmodel.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix #35394 Display public note on first page (#36993) * Display public note (an incoterms and sales rep signat) only on real first page * Display public note (an incoterms and sales rep signat) only on real first page --------- Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix CI * Fix CI * Fix CI * Fix ci * Qual: Translate French comments to English (#37052) * Qual: Translate French 'valeur' in comments to English (#37051) * NEW Accountancy - Select between accrual accounting and cash accounting (#37050) * Qual: Translate french 'avec' comments to English (#37049) # Qual: Translate french 'avec' comments to English * FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046) * FIX rate_indirect to rate_direct Direct : 1 Divisa Currency = X Currency Main. Indirect : 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Divisa rate direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Add col rate_direct because Dolibarr use for.default rate indirect --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * CI * Add thumbnails for avif (#37045) * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX #36892 * NEW : Manage discount for all lines for supplier elements. (#36954) * NEW : Manage remise for all lines for supplier elements. * Cast remise_percent to float in updateline call --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix Signature position (#37048) Move up the position of the signature to fix its explosion on 3 pages * remove french doc and fix travis migration missing (#37053) * fix french doc * fix french doc * fix french doc * fix french doc * Clean up comments in card.php Removed unnecessary comments from card.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v23 * Fix CSS * Fix CSS * Fix sql syntax error * Fix sql syntax error * Add optionnal img to openid login (#37060) * fix french doc (#37056) * fix french doc * fix french doc * fix french doc * doc translation * doc translation * doc translation * doc translation * doc translation * load tables in init for create categorie table associated (#37059) * Fix situation invoice * Fix situation invoice * Debug v23 * Link and filter on ountry for holiday types * Link and filter on ountry for holiday types * Trans * Debug v23 * css * CSS on current day * Debug v23 * css * More complete message * Make array of dispute status a shared constant * Debug v23 * Debug v23 * bad link on sql in fichinter list (#37081) * bad link on sql in fichinter list (#37081) * FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078) * feat: CustomerDisplay through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * fix: looks like a typo * feat: for small screens * fix: attribut contenant le prix du produit ajouté * feat: ajout d'un callback de gestion d'erreur * Clean code for Takepos * Debug v23 * Fix new path of dolreceiptprinter.class.php * Adjust signature appearance position in PDF generation (#37076) * EmailCollector: exclude sender emails/domains (#37075) # Conflicts: # htdocs/langs/en_US/admin.lang Co-authored-by: braito4 <braito4@users.noreply.github.com> * fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-15053838 Co-authored-by: snyk-bot <snyk-bot@snyk.io> * translate french doc to english (#37064) * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * Trans * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Show total multicurrency on payment (#37070) * Total multicurrency * Total multicurrency paiment * total result multicurrency * show total multicurrency * Fix CI * CLOSE #37085 - Popup notif is just under the menu bar * fix: add missing geturl lib (#37088) * Fix CI * Restrict to modiied files * #36843 Update card-rec.php (#37062) The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button. * Clean code * Fix CI * Doc * Fix CI * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * Fix comment and keep external modules out of core modules * Close #36975 * Close #36975 * css * NEW : hide remise_except unit price on invoice lines (#37066) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW(API): create fixed amount discount (#37091) * NEW(API): create fixed amount discount * FIX CI * FIX CI --------- Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> * Fix phan * CI * FIX - Create commonobject fetchWarehouse * FIX - for eldy coment * FIX - Phan * copy --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net> Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com> Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: MDW <mdeweerd@users.noreply.github.com> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com> Co-authored-by: Braito <braito4@hotmail.com> Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com> Co-authored-by: Thatoo <Thatoo@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> Co-authored-by: Vincent Maury <artec.vm@arnac.net> Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Jyhere <jyhere@gmail.com> Co-authored-by: Lenin Rivas <53640168+leninrivas@users.noreply.github.com> Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr> Co-authored-by: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Co-authored-by: LePat <patrick.muscat@gmail.com> Co-authored-by: braito4 <braito4@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io> Co-authored-by: Vanyo <vanyolai@gmail.com> Co-authored-by: AWeerWolf <74211972+AWeerWolf@users.noreply.github.com> Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com> Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-08-10 23:33:15 +00:00
* Copyright (C) 2026 Anthony Berton <anthony.berton@bb2a.fr>
*
2002-04-30 10:51:35 +00:00
* 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
* the Free Software Foundation; either version 3 of the License, or
2002-04-30 10:51:35 +00:00
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
2019-09-23 19:55:30 +00:00
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2002-04-30 10:51:35 +00:00
*/
/**
2010-07-21 12:35:56 +00:00
* \file htdocs/user/class/user.class.php
2012-01-11 00:06:56 +00:00
* \brief File of class to manage users
2012-03-27 07:59:28 +00:00
* \ingroup core
*/
2023-03-13 11:48:25 +00:00
require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php';
2023-04-27 21:48:21 +00:00
require_once DOL_DOCUMENT_ROOT.'/core/class/commonpeople.class.php';
2007-11-05 22:37:41 +00:00
2023-03-13 11:48:25 +00:00
/**
2012-04-01 18:31:39 +00:00
* Class to manage Dolibarr users
*/
2007-11-05 22:37:41 +00:00
class User extends CommonObject
2003-08-11 18:56:42 +00:00
{
2023-04-27 21:48:21 +00:00
use CommonPeople;
2018-08-23 16:52:47 +00:00
/**
* @var string ID to identify managed object
*/
public $element = 'user';
2018-08-31 20:34:02 +00:00
2018-08-22 17:56:24 +00:00
/**
* @var string Name of table without prefix where object is stored
*/
public $table_element = 'user';
2018-08-31 20:34:02 +00:00
2018-10-06 10:04:17 +00:00
/**
2020-12-05 22:53:55 +00:00
* @var string Field with ID of parent key if this field has a parent
2018-10-06 10:04:17 +00:00
*/
public $fk_element = 'fk_user';
2018-10-06 10:04:17 +00:00
2020-11-05 07:55:04 +00:00
/**
* @var string picto
*/
2020-04-24 21:56:57 +00:00
public $picto = 'user';
/**
* @var int
*/
public $id = 0;
2023-07-27 15:45:40 +00:00
/**
* @var int
* @deprecated Use $status
2023-07-27 15:45:40 +00:00
* @see $status
*/
public $statut;
2023-07-27 15:45:40 +00:00
/**
* @var int
*/
2023-08-09 14:02:27 +00:00
public $status;
/**
* @var string Open ID
*/
public $openid;
/**
* @var string
*/
public $ldap_sid;
/**
* @var string
*/
public $search_sid;
/**
* @var int
*/
public $employee;
/**
* @var string
*/
public $civility_code;
2020-11-10 20:43:45 +00:00
2023-01-18 21:20:25 +00:00
/**
* @var string fullname
*/
public $fullname;
2020-11-10 20:43:45 +00:00
/**
2024-03-26 13:40:42 +00:00
* @var string|int<-1,-1> gender (man|woman|other)
2020-11-10 20:43:45 +00:00
*/
public $gender;
2022-05-16 23:21:33 +00:00
/**
* @var null|int|string
*/
public $birth;
2020-11-05 07:55:04 +00:00
/**
2025-03-01 15:25:22 +00:00
* @var ?string email
2020-11-05 07:55:04 +00:00
*/
public $email;
2018-10-12 09:29:47 +00:00
/**
* @var string email
*/
public $email_oauth2;
2020-11-05 07:55:04 +00:00
/**
* @var string personal email
*/
public $personal_email;
2019-09-12 16:04:24 +00:00
/**
* @var array<string,string> array of socialnetworks
*/
public $socialnetworks;
2019-09-12 16:04:24 +00:00
2020-11-05 18:00:45 +00:00
/**
* @var string job position
*/
public $job;
/**
* @var string user signature
*/
public $signature;
2018-10-06 10:01:00 +00:00
2020-11-05 18:00:45 +00:00
/**
* @var string office phone
*/
public $office_phone;
2020-11-05 18:00:45 +00:00
/**
* @var string office fax
*/
public $office_fax;
2020-11-05 18:00:45 +00:00
/**
* @var string phone mobile
*/
public $user_mobile;
2020-11-05 18:00:45 +00:00
/**
* @var string personal phone mobile
*/
public $personal_mobile;
2020-11-05 18:00:45 +00:00
/**
* @var int<0,1> 1 if admin 0 if standard user
2020-11-05 18:00:45 +00:00
*/
public $admin;
2020-11-05 18:00:45 +00:00
/**
* @var string user login
*/
public $login;
2020-11-05 18:00:45 +00:00
/**
* @var string user apikey
*/
public $api_key;
2018-08-31 16:27:16 +00:00
2020-11-05 07:55:04 +00:00
/**
* @var string Clear password in memory
*/
public $pass;
2020-11-05 07:55:04 +00:00
2023-07-27 15:45:40 +00:00
/**
* @var string Encrypted password in memory
2023-07-27 15:45:40 +00:00
*/
public $pass_crypted;
2020-11-05 07:55:04 +00:00
/**
* @var string Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
*/
public $pass_indatabase;
2020-11-05 07:55:04 +00:00
/**
* @var string Encrypted password in database (always defined)
*/
public $pass_indatabase_crypted;
2007-11-13 20:17:52 +00:00
2019-03-21 14:18:05 +00:00
/**
2020-11-06 15:28:26 +00:00
* @var string Temporary password
*/
public $pass_temp;
2019-03-21 19:15:19 +00:00
/**
* @var int 1 if user must change password at next login
*/
public $force_pass_change = 0;
2019-03-21 14:18:05 +00:00
/**
* Date creation record (datec)
*
* @var integer
*/
public $datec;
/**
* Date modification record (tms)
*
* @var integer
*/
public $datem;
/**
2020-11-05 18:00:45 +00:00
* @var int If this is defined, it is an external user
*/
public $socid;
2018-10-12 10:23:45 +00:00
/**
2020-11-05 18:00:45 +00:00
* @var int If this is defined, it is a user created from a contact
*/
public $contact_id;
2018-10-12 10:23:45 +00:00
/**
* @var int ID
*/
public $fk_member;
2018-08-31 15:55:31 +00:00
/**
* @var int User ID of supervisor
2018-08-31 15:55:31 +00:00
*/
public $fk_user;
2020-11-05 18:00:45 +00:00
/**
* @var int User ID of expense validator
*/
public $fk_user_expense_validator;
2020-11-05 18:00:45 +00:00
/**
* @var int User ID of holidays validator
*/
public $fk_user_holiday_validator;
2020-11-05 18:00:45 +00:00
/**
* @var string clicktodial url
2020-11-05 18:00:45 +00:00
*/
public $clicktodial_url;
2020-11-05 18:00:45 +00:00
/**
* @var string clicktodial login
*/
public $clicktodial_login;
2020-11-05 18:00:45 +00:00
/**
* @var string clicktodial password
*/
public $clicktodial_password;
2020-11-05 18:00:45 +00:00
/**
* @var string clicktodial poste
*/
public $clicktodial_poste;
2023-04-15 01:16:53 +00:00
/**
2024-01-22 17:08:49 +00:00
* @var int 0 by default, 1 if click to dial data were already loaded for this user
2023-04-15 01:16:53 +00:00
*/
public $clicktodial_loaded;
/**
* @var int|string
*/
public $datelastpassvalidation;
/**
* @var int|string
*/
public $datelastlogin;
/**
* @var int|string
*/
public $datepreviouslogin;
/**
* @var int|string
*/
public $flagdelsessionsbefore;
/**
* @var string
*/
public $iplastlogin;
/**
* @var string
*/
public $ippreviouslogin;
/**
* @var int|string
*/
public $datestartvalidity;
/**
* @var int|string
*/
public $dateendvalidity;
2020-11-05 18:00:45 +00:00
/**
* @var string photo filename
*/
public $photo;
2024-01-22 17:08:49 +00:00
/**
2024-01-22 17:10:02 +00:00
* @var string default language
2024-01-22 17:08:49 +00:00
*/
public $lang;
2020-11-05 18:00:45 +00:00
/**
* @var stdClass Class of permissions user->rights->permx
*/
public $rights;
/**
* @var int All permissions are loaded
*/
public $all_permissions_are_loaded;
2020-11-05 18:00:45 +00:00
/**
* @var int Number of rights granted to the user. Value loaded after a loadRights().
2020-11-05 18:00:45 +00:00
*/
public $nb_rights;
2021-06-04 23:17:16 +00:00
/**
* @var UserGroup[] To store list of groups of user (used by API /info for example)
2021-06-04 23:17:16 +00:00
*/
public $user_group_list;
2020-11-05 18:00:45 +00:00
/**
* @var array<string,int> Cache array of already loaded permissions
2020-11-05 18:00:45 +00:00
*/
private $_tab_loaded = array();
2020-11-05 18:00:45 +00:00
/**
* @var stdClass To store personal config
*/
public $conf;
2022-09-01 08:54:20 +00:00
/**
* @var array<string,array<string,mixed>>
*/
2022-09-01 08:54:20 +00:00
public $default_values; // To store default values for user. Loaded by loadDefaultValues().
/**
* @var array<string,array<string,string>>
*/
public $lastsearch_values_tmp; // To store current search criteria for user
/**
* @var array<string,string> Note: seems unused
*/
public $lastsearch_values; // To store last saved search criteria for user
2024-03-15 22:14:21 +00:00
/**
* @var array<int,User>|array<int,array{rowid:int,id:int,fk_user:int,fk_soc:int,firstname:string,lastname:string,login:string,statut:int,entity:int,email:string,gender:string|int<-1,-1>,admin:int<0,1>,photo:string,fullpath:string,fullname:string,level:int}> Array of User (filled from fetchAll) or Array with hierarchy of user information (filled with get_full_tree())
2024-03-15 22:14:21 +00:00
*/
public $users = array();
/**
* @var array<int,int>
*/
public $parentof; // To store an array of all parents for all ids.
/**
* @var array<int,array<int,int>>
*/
private $cache_childids; // Cache array of already loaded children
/**
* Accounting general account for salary
* @var string
*/
public $accountancy_code_user_general; // Accountancy code in prevision of the complete accountancy module
/**
* @var string
*/
public $accountancy_code; // Accountancy code in prevision of the complete accountancy module
2017-03-13 14:00:44 +00:00
/**
* @var string
*/
public $thm; // Average cost of employee - Used for valuation of time spent
/**
* @var string
*/
public $tjm; // Average cost of employee
2017-03-13 14:00:44 +00:00
/**
* @var string
*/
public $salary; // Monthly salary - Denormalized value from llx_user_employment
/**
* @var string
*/
public $salaryextra; // Monthly salary extra - Denormalized value from llx_user_employment
/**
* @var string
*/
public $weeklyhours; // Weekly hours - Denormalized value from llx_user_employment
2020-11-05 18:00:45 +00:00
/**
* @var string Define background color for user in agenda
*/
public $color;
2017-03-13 14:00:44 +00:00
/**
* @var int|string
*/
public $dateemployment; // Define date of employment by company
/**
* @var int|string
*/
public $dateemploymentend; // Define date of employment end by company
/**
* @var int
*/
public $default_c_exp_tax_cat;
/**
* @var string ref for employee
*/
public $ref_employee;
/**
* @var string national registration number
*/
public $national_registration_number;
/**
* @var int
*/
public $default_range;
2018-07-02 07:34:34 +00:00
2020-11-10 20:43:45 +00:00
/**
NEW - Add substitution for user warehouse (#36670) * Fix trans and warning * Doc * Debug v23 * Debug v23 * Debug v23 * Doc * New import Leave Balance (Datastructure) (#37001) * New import Leave Balance (Datastructure) * fix --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> * Qual: Update Phan baseline.txt with reduced issue counts (#36996) This commit updates the Phan baseline.txt file. * Better log * Log * Better error management * Doc * Fix error message * CI * Try to fix CI * fix phan (#37007) * CI * fix phan (#37008) PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable) * CI * NEW Add new EUID number (#36997) * Doc * ci * Fix CI * Improve OAuth HTTP error details (#36951) Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins. Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add import of leave balance (Implementation) (#37011) * New add import Leave Balance * add eof * Update modHoliday.class.php --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add image format avif (#37014) * add format avif * Update functions.lib.php * Exclude non interesting warning * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * CI * CI * Trans * CI * CI * CI * Fix typo in phpstan.neon.dist for isset() rule (#37018) See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Try to fix phan * CI * CI * ci * ci * css * qual: Update french texts (comments) to english (#37009) * qual: Update french texts (comments) to english * Qual: Update comment to english in card-rec.php and card.php Translation of comments in the files card-rec.php and card.php. * Qual: Translate comments to English * Qual: Translate comments to English * Fix space into tab * Fix spelling * Qual: Translate comments to English * Update website.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * ci * Clean code * Fix test * Debug v23 * Merge manually changes from #37012 that seems good. * Log * More robust phpunit * Populate openid data from wellknow url (#37023) * Delete inexistant file File jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Populate openid parameters from wellknow url * CI * Debug v23 - fix code for rounding * MCP server sql part (#37025) * Create llx_ai_request_log.sql * Create llx_ai_request_log.key.sql * Update 23.0.0-24.0.0.sql * Update llx_ai_request_log.sql * Update 23.0.0-24.0.0.sql * Remove foreign key constraint from llx_ai_request_log Removed foreign key constraint for fk_user in llx_ai_request_log. --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v24 * Fix syntax error * NEW allow to disable freezone product on takepos (#37004) * allow to disable freezone product on takepos * Conditionally add FreeZone product to menus * Add NoFreeZoneProduct language entry --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix label of dispute * [database] Minimum amount and subscription's amount formula description (#37021) * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * css * Update llx_adherent_type.sql add minimumamount and amountformuladescription rows * Update 22.0.0-23.0.0.sql add minimumamount and amountformuladescription column --------- Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW: Display thirdparty name with ref in supplier orders linked objects (#36952) Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> * css * Debug v23 * Fix type * CI * CI * Test without file list * CI * Add api document management for holiday (#36915) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Invoice - List - use select2 multiselect for status (#36834) * NEW Invoice - List - use select2 multiselect for status * Optimize * CI * CI * Review * Duplicate line and last problem * CI --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX Pb in total price of line when adding the discount of a down payment when unit price was using a high accuracy. * Clean code * try to fix phan * Fix phan * Clean code * Clean code * Debug v23 * Fix LDAP * fix facture.class.php (#37031) * Debug v23 * Qual: Update french comments with 'nombre' (#37032) Update french comments with 'nombre' in their phrasing Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37029) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37030) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Doc * Doc comment * FIX When bank direct debit SEPA ref is > 99 * Fix when there is more than 99 direct debit in same month * Debug v24 * Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 * CSS * Fix when there is more than 99 direct debit in same month * Debug v24 * FIX Division by zero * FIX Division by zero * More log * More log * More log * More Log * Fix IPN payment * Fix IPN * Log * Clean code * Debug v23 - Fix ipn for dispute and withdraw funds. * fix CI (#37033) * fix CI (#37033) * CI * fix french doc (#36897) * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * Update html.form.class.php * Update html.form.class.php * Update index.php * fix * fix * fix * fix * fix * fix * fix * fix * Update modules_facture.php * Update phpstan.neon.dist --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Translate French comments to English (#37044) * Qual: Translate French comments to English * Qual: Translate French comments to English * Qual: Translate French comments to English ("niveau") (#37041) Translate French comments to English (comments with "niveau") * fix french doc (#37040) * warning error if no societe->id defined (#37039) * fix french doc (#37037) * fix french doc * Update dispatch.php * Update dispatch.php * Update graph.php * fix french doc (#37047) * fix french doc * Update index.php * Update index.php * Fix CI * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * Fix CI * Minimum amount and subscription's amount formula description (#37006) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043) * Warning on export - Add isset() protection in Export::load_arrays() * Warning on import - Add isset() protection in Import::load_arrays() --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Clean comment * Warning on account model (#37042) * Error on account model * Simplify rowid assignment in accountmodel.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix #35394 Display public note on first page (#36993) * Display public note (an incoterms and sales rep signat) only on real first page * Display public note (an incoterms and sales rep signat) only on real first page --------- Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix CI * Fix CI * Fix CI * Fix ci * Qual: Translate French comments to English (#37052) * Qual: Translate French 'valeur' in comments to English (#37051) * NEW Accountancy - Select between accrual accounting and cash accounting (#37050) * Qual: Translate french 'avec' comments to English (#37049) # Qual: Translate french 'avec' comments to English * FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046) * FIX rate_indirect to rate_direct Direct : 1 Divisa Currency = X Currency Main. Indirect : 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Divisa rate direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Add col rate_direct because Dolibarr use for.default rate indirect --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * CI * Add thumbnails for avif (#37045) * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX #36892 * NEW : Manage discount for all lines for supplier elements. (#36954) * NEW : Manage remise for all lines for supplier elements. * Cast remise_percent to float in updateline call --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix Signature position (#37048) Move up the position of the signature to fix its explosion on 3 pages * remove french doc and fix travis migration missing (#37053) * fix french doc * fix french doc * fix french doc * fix french doc * Clean up comments in card.php Removed unnecessary comments from card.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v23 * Fix CSS * Fix CSS * Fix sql syntax error * Fix sql syntax error * Add optionnal img to openid login (#37060) * fix french doc (#37056) * fix french doc * fix french doc * fix french doc * doc translation * doc translation * doc translation * doc translation * doc translation * load tables in init for create categorie table associated (#37059) * Fix situation invoice * Fix situation invoice * Debug v23 * Link and filter on ountry for holiday types * Link and filter on ountry for holiday types * Trans * Debug v23 * css * CSS on current day * Debug v23 * css * More complete message * Make array of dispute status a shared constant * Debug v23 * Debug v23 * bad link on sql in fichinter list (#37081) * bad link on sql in fichinter list (#37081) * FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078) * feat: CustomerDisplay through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * fix: looks like a typo * feat: for small screens * fix: attribut contenant le prix du produit ajouté * feat: ajout d'un callback de gestion d'erreur * Clean code for Takepos * Debug v23 * Fix new path of dolreceiptprinter.class.php * Adjust signature appearance position in PDF generation (#37076) * EmailCollector: exclude sender emails/domains (#37075) # Conflicts: # htdocs/langs/en_US/admin.lang Co-authored-by: braito4 <braito4@users.noreply.github.com> * fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-15053838 Co-authored-by: snyk-bot <snyk-bot@snyk.io> * translate french doc to english (#37064) * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * Trans * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Show total multicurrency on payment (#37070) * Total multicurrency * Total multicurrency paiment * total result multicurrency * show total multicurrency * Fix CI * CLOSE #37085 - Popup notif is just under the menu bar * fix: add missing geturl lib (#37088) * Fix CI * Restrict to modiied files * #36843 Update card-rec.php (#37062) The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button. * Clean code * Fix CI * Doc * Fix CI * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * Fix comment and keep external modules out of core modules * Close #36975 * Close #36975 * css * NEW : hide remise_except unit price on invoice lines (#37066) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW(API): create fixed amount discount (#37091) * NEW(API): create fixed amount discount * FIX CI * FIX CI --------- Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> * Fix phan * CI * FIX - Create commonobject fetchWarehouse * FIX - for eldy coment * FIX - Phan * copy --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net> Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com> Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: MDW <mdeweerd@users.noreply.github.com> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com> Co-authored-by: Braito <braito4@hotmail.com> Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com> Co-authored-by: Thatoo <Thatoo@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> Co-authored-by: Vincent Maury <artec.vm@arnac.net> Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Jyhere <jyhere@gmail.com> Co-authored-by: Lenin Rivas <53640168+leninrivas@users.noreply.github.com> Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr> Co-authored-by: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Co-authored-by: LePat <patrick.muscat@gmail.com> Co-authored-by: braito4 <braito4@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io> Co-authored-by: Vanyo <vanyolai@gmail.com> Co-authored-by: AWeerWolf <74211972+AWeerWolf@users.noreply.github.com> Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com> Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-08-10 23:33:15 +00:00
* @var ?int id of warehouse
* @deprecated use $warehouse_id
2020-11-10 20:43:45 +00:00
*/
2019-02-15 04:20:33 +00:00
public $fk_warehouse;
2018-07-02 07:34:34 +00:00
2024-03-29 13:04:02 +00:00
/**
*@var int id of establishment
*/
public $fk_establishment;
/**
*@var string label of establishment
*/
public $label_establishment;
/**
2024-04-22 13:17:38 +00:00
* @var array<int> Entity in table llx_user_group
* @deprecated Seems not used.
*/
public $usergroup_entity;
2022-04-07 21:44:57 +00:00
2018-08-31 20:34:02 +00:00
public $fields = array(
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 20, 'searchall' => 1),
'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 10, 'searchall' => 1),
NEW - Add substitution for user warehouse (#36670) * Fix trans and warning * Doc * Debug v23 * Debug v23 * Debug v23 * Doc * New import Leave Balance (Datastructure) (#37001) * New import Leave Balance (Datastructure) * fix --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> * Qual: Update Phan baseline.txt with reduced issue counts (#36996) This commit updates the Phan baseline.txt file. * Better log * Log * Better error management * Doc * Fix error message * CI * Try to fix CI * fix phan (#37007) * CI * fix phan (#37008) PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable) * CI * NEW Add new EUID number (#36997) * Doc * ci * Fix CI * Improve OAuth HTTP error details (#36951) Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins. Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add import of leave balance (Implementation) (#37011) * New add import Leave Balance * add eof * Update modHoliday.class.php --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add image format avif (#37014) * add format avif * Update functions.lib.php * Exclude non interesting warning * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * CI * CI * Trans * CI * CI * CI * Fix typo in phpstan.neon.dist for isset() rule (#37018) See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Try to fix phan * CI * CI * ci * ci * css * qual: Update french texts (comments) to english (#37009) * qual: Update french texts (comments) to english * Qual: Update comment to english in card-rec.php and card.php Translation of comments in the files card-rec.php and card.php. * Qual: Translate comments to English * Qual: Translate comments to English * Fix space into tab * Fix spelling * Qual: Translate comments to English * Update website.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * ci * Clean code * Fix test * Debug v23 * Merge manually changes from #37012 that seems good. * Log * More robust phpunit * Populate openid data from wellknow url (#37023) * Delete inexistant file File jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Populate openid parameters from wellknow url * CI * Debug v23 - fix code for rounding * MCP server sql part (#37025) * Create llx_ai_request_log.sql * Create llx_ai_request_log.key.sql * Update 23.0.0-24.0.0.sql * Update llx_ai_request_log.sql * Update 23.0.0-24.0.0.sql * Remove foreign key constraint from llx_ai_request_log Removed foreign key constraint for fk_user in llx_ai_request_log. --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v24 * Fix syntax error * NEW allow to disable freezone product on takepos (#37004) * allow to disable freezone product on takepos * Conditionally add FreeZone product to menus * Add NoFreeZoneProduct language entry --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix label of dispute * [database] Minimum amount and subscription's amount formula description (#37021) * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * css * Update llx_adherent_type.sql add minimumamount and amountformuladescription rows * Update 22.0.0-23.0.0.sql add minimumamount and amountformuladescription column --------- Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW: Display thirdparty name with ref in supplier orders linked objects (#36952) Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> * css * Debug v23 * Fix type * CI * CI * Test without file list * CI * Add api document management for holiday (#36915) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Invoice - List - use select2 multiselect for status (#36834) * NEW Invoice - List - use select2 multiselect for status * Optimize * CI * CI * Review * Duplicate line and last problem * CI --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX Pb in total price of line when adding the discount of a down payment when unit price was using a high accuracy. * Clean code * try to fix phan * Fix phan * Clean code * Clean code * Debug v23 * Fix LDAP * fix facture.class.php (#37031) * Debug v23 * Qual: Update french comments with 'nombre' (#37032) Update french comments with 'nombre' in their phrasing Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37029) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37030) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Doc * Doc comment * FIX When bank direct debit SEPA ref is > 99 * Fix when there is more than 99 direct debit in same month * Debug v24 * Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 * CSS * Fix when there is more than 99 direct debit in same month * Debug v24 * FIX Division by zero * FIX Division by zero * More log * More log * More log * More Log * Fix IPN payment * Fix IPN * Log * Clean code * Debug v23 - Fix ipn for dispute and withdraw funds. * fix CI (#37033) * fix CI (#37033) * CI * fix french doc (#36897) * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * Update html.form.class.php * Update html.form.class.php * Update index.php * fix * fix * fix * fix * fix * fix * fix * fix * Update modules_facture.php * Update phpstan.neon.dist --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Translate French comments to English (#37044) * Qual: Translate French comments to English * Qual: Translate French comments to English * Qual: Translate French comments to English ("niveau") (#37041) Translate French comments to English (comments with "niveau") * fix french doc (#37040) * warning error if no societe->id defined (#37039) * fix french doc (#37037) * fix french doc * Update dispatch.php * Update dispatch.php * Update graph.php * fix french doc (#37047) * fix french doc * Update index.php * Update index.php * Fix CI * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * Fix CI * Minimum amount and subscription's amount formula description (#37006) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043) * Warning on export - Add isset() protection in Export::load_arrays() * Warning on import - Add isset() protection in Import::load_arrays() --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Clean comment * Warning on account model (#37042) * Error on account model * Simplify rowid assignment in accountmodel.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix #35394 Display public note on first page (#36993) * Display public note (an incoterms and sales rep signat) only on real first page * Display public note (an incoterms and sales rep signat) only on real first page --------- Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix CI * Fix CI * Fix CI * Fix ci * Qual: Translate French comments to English (#37052) * Qual: Translate French 'valeur' in comments to English (#37051) * NEW Accountancy - Select between accrual accounting and cash accounting (#37050) * Qual: Translate french 'avec' comments to English (#37049) # Qual: Translate french 'avec' comments to English * FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046) * FIX rate_indirect to rate_direct Direct : 1 Divisa Currency = X Currency Main. Indirect : 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Divisa rate direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Add col rate_direct because Dolibarr use for.default rate indirect --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * CI * Add thumbnails for avif (#37045) * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX #36892 * NEW : Manage discount for all lines for supplier elements. (#36954) * NEW : Manage remise for all lines for supplier elements. * Cast remise_percent to float in updateline call --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix Signature position (#37048) Move up the position of the signature to fix its explosion on 3 pages * remove french doc and fix travis migration missing (#37053) * fix french doc * fix french doc * fix french doc * fix french doc * Clean up comments in card.php Removed unnecessary comments from card.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v23 * Fix CSS * Fix CSS * Fix sql syntax error * Fix sql syntax error * Add optionnal img to openid login (#37060) * fix french doc (#37056) * fix french doc * fix french doc * fix french doc * doc translation * doc translation * doc translation * doc translation * doc translation * load tables in init for create categorie table associated (#37059) * Fix situation invoice * Fix situation invoice * Debug v23 * Link and filter on ountry for holiday types * Link and filter on ountry for holiday types * Trans * Debug v23 * css * CSS on current day * Debug v23 * css * More complete message * Make array of dispute status a shared constant * Debug v23 * Debug v23 * bad link on sql in fichinter list (#37081) * bad link on sql in fichinter list (#37081) * FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078) * feat: CustomerDisplay through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * fix: looks like a typo * feat: for small screens * fix: attribut contenant le prix du produit ajouté * feat: ajout d'un callback de gestion d'erreur * Clean code for Takepos * Debug v23 * Fix new path of dolreceiptprinter.class.php * Adjust signature appearance position in PDF generation (#37076) * EmailCollector: exclude sender emails/domains (#37075) # Conflicts: # htdocs/langs/en_US/admin.lang Co-authored-by: braito4 <braito4@users.noreply.github.com> * fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-15053838 Co-authored-by: snyk-bot <snyk-bot@snyk.io> * translate french doc to english (#37064) * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * Trans * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Show total multicurrency on payment (#37070) * Total multicurrency * Total multicurrency paiment * total result multicurrency * show total multicurrency * Fix CI * CLOSE #37085 - Popup notif is just under the menu bar * fix: add missing geturl lib (#37088) * Fix CI * Restrict to modiied files * #36843 Update card-rec.php (#37062) The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button. * Clean code * Fix CI * Doc * Fix CI * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * Fix comment and keep external modules out of core modules * Close #36975 * Close #36975 * css * NEW : hide remise_except unit price on invoice lines (#37066) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW(API): create fixed amount discount (#37091) * NEW(API): create fixed amount discount * FIX CI * FIX CI --------- Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> * Fix phan * CI * FIX - Create commonobject fetchWarehouse * FIX - for eldy coment * FIX - Phan * copy --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net> Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com> Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: MDW <mdeweerd@users.noreply.github.com> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com> Co-authored-by: Braito <braito4@hotmail.com> Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com> Co-authored-by: Thatoo <Thatoo@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> Co-authored-by: Vincent Maury <artec.vm@arnac.net> Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Jyhere <jyhere@gmail.com> Co-authored-by: Lenin Rivas <53640168+leninrivas@users.noreply.github.com> Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr> Co-authored-by: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Co-authored-by: LePat <patrick.muscat@gmail.com> Co-authored-by: braito4 <braito4@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io> Co-authored-by: Vanyo <vanyolai@gmail.com> Co-authored-by: AWeerWolf <74211972+AWeerWolf@users.noreply.github.com> Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com> Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-08-10 23:33:15 +00:00
'fk_warehouse' => array('type' => 'integer:Entrepot:product\stock\class\entrepot.class.php', 'label' => 'Warehouse', 'enabled' => "isModEnabled('stock')", 'visible' => 1, 'notnull' => 0, 'showoncombobox' => 1, 'index' => 1, 'position' => 50, 'searchall' => 1),
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
'ref_employee' => array('type' => 'varchar(50)', 'label' => 'RefEmployee', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 30, 'searchall' => 1),
'national_registration_number' => array('type' => 'varchar(50)', 'label' => 'NationalRegistrationNumber', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 40, 'searchall' => 1)
);
2017-03-13 14:00:44 +00:00
2019-10-31 22:29:17 +00:00
const STATUS_DISABLED = 0;
const STATUS_ENABLED = 1;
/**
2018-08-31 20:34:02 +00:00
* Constructor of the class
2011-09-04 18:41:19 +00:00
*
2025-02-18 18:06:26 +00:00
* @param DoliDB|null $db Database handler
*/
2019-02-25 19:35:59 +00:00
public function __construct($db)
{
2012-01-13 17:24:25 +00:00
$this->db = $db;
$this->ismultientitymanaged = 1;
$this->isextrafieldmanaged = 1;
2015-10-23 13:24:47 +00:00
// User preference
$this->clicktodial_loaded = 0;
2015-10-23 13:24:47 +00:00
// For cache usage
$this->all_permissions_are_loaded = 0;
$this->nb_rights = 0;
2016-03-17 08:22:12 +00:00
// Force some default values
2015-10-23 13:24:47 +00:00
$this->admin = 0;
$this->employee = 1;
2016-03-17 08:22:12 +00:00
2019-02-25 19:35:59 +00:00
$this->conf = new stdClass();
$this->rights = new stdClass();
$this->rights->user = new stdClass();
$this->rights->user->user = new stdClass();
$this->rights->user->self = new stdClass();
2021-10-22 08:49:47 +00:00
$this->rights->user->user_advance = new stdClass();
$this->rights->user->self_advance = new stdClass();
$this->rights->user->group_advance = new stdClass();
}
2007-04-13 16:11:44 +00:00
/**
2017-10-28 14:00:07 +00:00
* Load a user from database with its id or ref (login).
* This function does not load permissions, only user properties. Use loadRights() for this just after the fetch.
*
2026-03-20 16:22:05 +00:00
* @param int $id If defined, id to used for search
* @param string $login If defined, login to used for search
* @param string $sid If defined, sid to used for search
* @param int<0,1> $loadpersonalconf 1=also load personal conf of user (in $user->conf->xxx), 0=do not load personal conf.
2026-03-20 16:22:05 +00:00
* @param int $entity If a value is >= 0, we force the search on a specific entity. If -1, means search depends on default setup.
* @param string $email If defined, email to used for search
* @param int $fk_socpeople If defined, id of contact for search
* @param int<0,1> $use_email_oauth2 1=Use also email_oauth2 to fetch on email
2026-03-20 16:22:05 +00:00
* @return int Return integer <0 if KO, 0 not found, >0 if OK
*/
public function fetch($id = 0, $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1, $email = '', $fk_socpeople = 0, $use_email_oauth2 = 0)
2007-04-13 16:11:44 +00:00
{
global $conf, $user;
2007-01-05 09:25:52 +00:00
2011-06-29 10:23:32 +00:00
// Clean parameters
$login = trim($login);
2011-06-29 10:23:32 +00:00
// Get user
$sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.civility as civility_code, u.birth, u.job,";
$sql .= " u.email, u.email_oauth2, u.personal_email,";
$sql .= " u.socialnetworks,";
$sql .= " u.signature, u.office_phone, u.office_fax, u.user_mobile, u.personal_mobile,";
$sql .= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
2022-09-03 09:07:47 +00:00
$sql .= " u.admin, u.login, u.note_private, u.note_public,";
$sql .= " u.pass, u.pass_crypted, u.pass_temp, u.force_pass_change, u.api_key,";
$sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid, u.fk_user_expense_validator, u.fk_user_holiday_validator,";
$sql .= " fk_user_creat as user_creation_id, fk_user_modif as user_modification_id,";
2023-01-03 09:27:54 +00:00
$sql .= " u.statut as status, u.lang, u.entity,";
$sql .= " u.datec as datec,";
$sql .= " GREATEST(u.tms, uef.tms) as datem,";
$sql .= " u.datelastlogin as datel,";
$sql .= " u.datepreviouslogin as datep,";
$sql .= " u.flagdelsessionsbefore,";
2022-04-28 20:28:32 +00:00
$sql .= " u.iplastlogin,";
$sql .= " u.ippreviouslogin,";
$sql .= " u.datelastpassvalidation,";
$sql .= " u.datestartvalidity,";
$sql .= " u.dateendvalidity,";
$sql .= " u.photo as photo,";
$sql .= " u.openid as openid,";
$sql .= " u.accountancy_code_user_general,";
$sql .= " u.accountancy_code,";
$sql .= " u.thm,";
$sql .= " u.tjm,";
$sql .= " u.salary,";
$sql .= " u.salaryextra,";
$sql .= " u.weeklyhours,";
$sql .= " u.color,";
$sql .= " u.dateemployment, u.dateemploymentend,";
$sql .= " u.fk_warehouse,";
$sql .= " u.ref_ext,";
$sql .= " u.default_range, u.default_c_exp_tax_cat,"; // Expense report default mode
$sql .= " u.national_registration_number,";
$sql .= " u.ref_employee,";
$sql .= " c.code as country_code, c.label as country,";
2024-03-29 13:04:02 +00:00
$sql .= " d.code_departement as state_code, d.nom as state,";
$sql .= " s.label as label_establishment, u.fk_establishment";
$sql .= " FROM ".$this->db->prefix()."user as u";
$sql .= " LEFT JOIN ".$this->db->prefix()."user_extrafields as uef ON uef.fk_object = u.rowid";
$sql .= " LEFT JOIN ".$this->db->prefix()."c_country as c ON u.fk_country = c.rowid";
$sql .= " LEFT JOIN ".$this->db->prefix()."c_departements as d ON u.fk_state = d.rowid";
2024-03-29 13:04:02 +00:00
$sql .= " LEFT JOIN ".$this->db->prefix()."establishment as s ON u.fk_establishment = s.rowid";
if ($id > 0) {
$sql .= " WHERE u.rowid = ".((int) $id);
} else {
if ($entity < 0) {
if ((! isModEnabled('multicompany') || ! getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) && (! empty($user->entity))) {
$sql .= " WHERE u.entity IN (0, " . ((int) $conf->entity) . ")";
} else {
$sql .= " WHERE u.entity IS NOT NULL"; // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database
}
2020-11-05 07:55:04 +00:00
} else {
// The fetch was forced on an entity
if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
$sql .= " WHERE u.entity IS NOT NULL"; // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database
} else {
if ($entity != '' && $entity == 0) { // If $entity = 0
$sql .= " WHERE u.entity = 0";
} else { // if $entity is -1 or > 0
$sql .= " WHERE u.entity IN (0, " . ((int) ($entity > 0 ? ((int) $entity) : ((int) $conf->entity))) . ")";
}
2024-12-04 08:18:46 +00:00
}
2020-11-05 07:55:04 +00:00
}
2011-08-19 22:15:22 +00:00
}
2016-03-17 08:22:12 +00:00
if ($sid) {
// permet une recherche du user par son SID ActiveDirectory ou Samba
$sql .= " AND (u.ldap_sid = '".$this->db->escape($sid)."' OR u.login = '".$this->db->escape($login)."')";
2020-11-05 07:55:04 +00:00
} elseif ($login) {
$sql .= " AND u.login = '".$this->db->escape($login)."'";
2020-11-05 07:55:04 +00:00
} elseif ($email) {
$sql .= " AND (u.email = '".$this->db->escape($email)."'";
if ($use_email_oauth2) {
$sql .= " OR u.email_oauth2 = '".$this->db->escape($email)."'";
}
$sql .= ")";
2022-07-18 09:51:28 +00:00
} elseif ($fk_socpeople > 0) {
$sql .= " AND u.fk_socpeople = ".((int) $fk_socpeople);
2007-04-13 16:11:44 +00:00
}
$sql .= " ORDER BY u.entity ASC"; // Avoid random result when there is 2 login in 2 different entities
if ($sid) {
// permet une recherche du user par son SID ActiveDirectory ou Samba
$sql .= ' '.$this->db->plimit(1);
}
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
if ($num > 1) {
$this->error = "USERDUPLICATEFOUND";
dol_syslog(get_class($this)."::fetch more than 1 user found", LOG_WARNING);
$this->db->free($resql);
return 0;
}
$obj = $this->db->fetch_object($resql);
2020-10-28 23:34:41 +00:00
if ($obj) {
$this->id = $obj->rowid;
$this->ref = $obj->rowid;
2011-09-04 18:41:19 +00:00
2020-11-05 18:00:45 +00:00
$this->ref_ext = $obj->ref_ext;
2011-01-15 09:31:09 +00:00
2020-11-05 18:00:45 +00:00
$this->ldap_sid = $obj->ldap_sid;
$this->civility_code = $obj->civility_code;
2020-11-05 18:00:45 +00:00
$this->lastname = $obj->lastname;
$this->firstname = $obj->firstname;
$this->ref_employee = $obj->ref_employee;
$this->national_registration_number = $obj->national_registration_number;
2016-03-17 08:22:12 +00:00
2020-11-05 18:00:45 +00:00
$this->employee = $obj->employee;
$this->login = $obj->login;
$this->gender = $obj->gender;
$this->birth = $this->db->jdate($obj->birth);
2007-04-13 16:11:44 +00:00
$this->pass_indatabase = $obj->pass;
$this->pass_indatabase_crypted = $obj->pass_crypted;
$this->pass = $obj->pass;
$this->pass_temp = $obj->pass_temp;
$this->force_pass_change = $obj->force_pass_change;
$this->datelastpassvalidation = $obj->datelastpassvalidation;
2023-03-13 11:48:25 +00:00
$this->api_key = dolDecrypt($obj->api_key);
$this->address = $obj->address;
$this->zip = $obj->zip;
$this->town = $obj->town;
2019-02-25 19:35:59 +00:00
$this->country_id = $obj->country_id;
$this->country_code = $obj->country_id ? $obj->country_code : '';
2019-02-25 19:35:59 +00:00
//$this->country = $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
$this->state_id = $obj->state_id;
$this->state_code = $obj->state_code;
$this->state = ($obj->state != '-' ? $obj->state : '');
$this->office_phone = $obj->office_phone;
$this->office_fax = $obj->office_fax;
$this->user_mobile = $obj->user_mobile;
$this->personal_mobile = $obj->personal_mobile;
$this->email = $obj->email;
$this->email_oauth2 = $obj->email_oauth2;
2019-09-12 16:32:47 +00:00
$this->personal_email = $obj->personal_email;
2022-09-21 01:23:03 +00:00
$this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array());
$this->user_creation_id = $obj->user_creation_id;
$this->user_modification_id = $obj->user_modification_id;
2024-10-28 17:13:02 +00:00
$this->job = $obj->job;
$this->signature = $obj->signature;
$this->admin = $obj->admin;
$this->note_public = $obj->note_public;
$this->note_private = $obj->note_private;
2023-01-03 09:27:54 +00:00
$this->statut = $obj->status; // deprecated
$this->status = $obj->status;
2023-01-03 09:27:54 +00:00
$this->photo = $obj->photo;
$this->openid = $obj->openid;
$this->lang = $obj->lang;
$this->entity = $obj->entity;
$this->accountancy_code_user_general = $obj->accountancy_code_user_general;
2019-02-25 19:35:59 +00:00
$this->accountancy_code = $obj->accountancy_code;
$this->thm = $obj->thm;
$this->tjm = $obj->tjm;
$this->salary = $obj->salary;
$this->salaryextra = $obj->salaryextra;
2019-02-25 19:35:59 +00:00
$this->weeklyhours = $obj->weeklyhours;
$this->color = $obj->color;
2019-02-25 19:35:59 +00:00
$this->dateemployment = $this->db->jdate($obj->dateemployment);
2018-05-12 15:59:43 +00:00
$this->dateemploymentend = $this->db->jdate($obj->dateemploymentend);
$this->datec = $this->db->jdate($obj->datec);
$this->datem = $this->db->jdate($obj->datem);
$this->datelastlogin = $this->db->jdate($obj->datel);
$this->datepreviouslogin = $this->db->jdate($obj->datep);
$this->flagdelsessionsbefore = $this->db->jdate($obj->flagdelsessionsbefore, 'gmt');
2022-04-28 20:28:32 +00:00
$this->iplastlogin = $obj->iplastlogin;
$this->ippreviouslogin = $obj->ippreviouslogin;
$this->datestartvalidity = $this->db->jdate($obj->datestartvalidity);
$this->dateendvalidity = $this->db->jdate($obj->dateendvalidity);
$this->socid = $obj->fk_soc;
$this->contact_id = $obj->fk_socpeople;
$this->fk_member = $obj->fk_member;
$this->fk_user = $obj->fk_user;
$this->fk_user_expense_validator = $obj->fk_user_expense_validator;
$this->fk_user_holiday_validator = $obj->fk_user_holiday_validator;
2019-02-25 19:35:59 +00:00
$this->default_range = $obj->default_range;
$this->default_c_exp_tax_cat = $obj->default_c_exp_tax_cat;
$this->fk_warehouse = $obj->fk_warehouse;
NEW - Add substitution for user warehouse (#36670) * Fix trans and warning * Doc * Debug v23 * Debug v23 * Debug v23 * Doc * New import Leave Balance (Datastructure) (#37001) * New import Leave Balance (Datastructure) * fix --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> * Qual: Update Phan baseline.txt with reduced issue counts (#36996) This commit updates the Phan baseline.txt file. * Better log * Log * Better error management * Doc * Fix error message * CI * Try to fix CI * fix phan (#37007) * CI * fix phan (#37008) PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable) * CI * NEW Add new EUID number (#36997) * Doc * ci * Fix CI * Improve OAuth HTTP error details (#36951) Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins. Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add import of leave balance (Implementation) (#37011) * New add import Leave Balance * add eof * Update modHoliday.class.php --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add image format avif (#37014) * add format avif * Update functions.lib.php * Exclude non interesting warning * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * CI * CI * Trans * CI * CI * CI * Fix typo in phpstan.neon.dist for isset() rule (#37018) See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Try to fix phan * CI * CI * ci * ci * css * qual: Update french texts (comments) to english (#37009) * qual: Update french texts (comments) to english * Qual: Update comment to english in card-rec.php and card.php Translation of comments in the files card-rec.php and card.php. * Qual: Translate comments to English * Qual: Translate comments to English * Fix space into tab * Fix spelling * Qual: Translate comments to English * Update website.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * ci * Clean code * Fix test * Debug v23 * Merge manually changes from #37012 that seems good. * Log * More robust phpunit * Populate openid data from wellknow url (#37023) * Delete inexistant file File jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Populate openid parameters from wellknow url * CI * Debug v23 - fix code for rounding * MCP server sql part (#37025) * Create llx_ai_request_log.sql * Create llx_ai_request_log.key.sql * Update 23.0.0-24.0.0.sql * Update llx_ai_request_log.sql * Update 23.0.0-24.0.0.sql * Remove foreign key constraint from llx_ai_request_log Removed foreign key constraint for fk_user in llx_ai_request_log. --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v24 * Fix syntax error * NEW allow to disable freezone product on takepos (#37004) * allow to disable freezone product on takepos * Conditionally add FreeZone product to menus * Add NoFreeZoneProduct language entry --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix label of dispute * [database] Minimum amount and subscription's amount formula description (#37021) * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * css * Update llx_adherent_type.sql add minimumamount and amountformuladescription rows * Update 22.0.0-23.0.0.sql add minimumamount and amountformuladescription column --------- Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW: Display thirdparty name with ref in supplier orders linked objects (#36952) Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> * css * Debug v23 * Fix type * CI * CI * Test without file list * CI * Add api document management for holiday (#36915) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Invoice - List - use select2 multiselect for status (#36834) * NEW Invoice - List - use select2 multiselect for status * Optimize * CI * CI * Review * Duplicate line and last problem * CI --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX Pb in total price of line when adding the discount of a down payment when unit price was using a high accuracy. * Clean code * try to fix phan * Fix phan * Clean code * Clean code * Debug v23 * Fix LDAP * fix facture.class.php (#37031) * Debug v23 * Qual: Update french comments with 'nombre' (#37032) Update french comments with 'nombre' in their phrasing Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37029) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37030) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Doc * Doc comment * FIX When bank direct debit SEPA ref is > 99 * Fix when there is more than 99 direct debit in same month * Debug v24 * Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 * CSS * Fix when there is more than 99 direct debit in same month * Debug v24 * FIX Division by zero * FIX Division by zero * More log * More log * More log * More Log * Fix IPN payment * Fix IPN * Log * Clean code * Debug v23 - Fix ipn for dispute and withdraw funds. * fix CI (#37033) * fix CI (#37033) * CI * fix french doc (#36897) * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * Update html.form.class.php * Update html.form.class.php * Update index.php * fix * fix * fix * fix * fix * fix * fix * fix * Update modules_facture.php * Update phpstan.neon.dist --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Translate French comments to English (#37044) * Qual: Translate French comments to English * Qual: Translate French comments to English * Qual: Translate French comments to English ("niveau") (#37041) Translate French comments to English (comments with "niveau") * fix french doc (#37040) * warning error if no societe->id defined (#37039) * fix french doc (#37037) * fix french doc * Update dispatch.php * Update dispatch.php * Update graph.php * fix french doc (#37047) * fix french doc * Update index.php * Update index.php * Fix CI * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * Fix CI * Minimum amount and subscription's amount formula description (#37006) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043) * Warning on export - Add isset() protection in Export::load_arrays() * Warning on import - Add isset() protection in Import::load_arrays() --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Clean comment * Warning on account model (#37042) * Error on account model * Simplify rowid assignment in accountmodel.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix #35394 Display public note on first page (#36993) * Display public note (an incoterms and sales rep signat) only on real first page * Display public note (an incoterms and sales rep signat) only on real first page --------- Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix CI * Fix CI * Fix CI * Fix ci * Qual: Translate French comments to English (#37052) * Qual: Translate French 'valeur' in comments to English (#37051) * NEW Accountancy - Select between accrual accounting and cash accounting (#37050) * Qual: Translate french 'avec' comments to English (#37049) # Qual: Translate french 'avec' comments to English * FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046) * FIX rate_indirect to rate_direct Direct : 1 Divisa Currency = X Currency Main. Indirect : 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Divisa rate direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Add col rate_direct because Dolibarr use for.default rate indirect --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * CI * Add thumbnails for avif (#37045) * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX #36892 * NEW : Manage discount for all lines for supplier elements. (#36954) * NEW : Manage remise for all lines for supplier elements. * Cast remise_percent to float in updateline call --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix Signature position (#37048) Move up the position of the signature to fix its explosion on 3 pages * remove french doc and fix travis migration missing (#37053) * fix french doc * fix french doc * fix french doc * fix french doc * Clean up comments in card.php Removed unnecessary comments from card.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v23 * Fix CSS * Fix CSS * Fix sql syntax error * Fix sql syntax error * Add optionnal img to openid login (#37060) * fix french doc (#37056) * fix french doc * fix french doc * fix french doc * doc translation * doc translation * doc translation * doc translation * doc translation * load tables in init for create categorie table associated (#37059) * Fix situation invoice * Fix situation invoice * Debug v23 * Link and filter on ountry for holiday types * Link and filter on ountry for holiday types * Trans * Debug v23 * css * CSS on current day * Debug v23 * css * More complete message * Make array of dispute status a shared constant * Debug v23 * Debug v23 * bad link on sql in fichinter list (#37081) * bad link on sql in fichinter list (#37081) * FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078) * feat: CustomerDisplay through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * fix: looks like a typo * feat: for small screens * fix: attribut contenant le prix du produit ajouté * feat: ajout d'un callback de gestion d'erreur * Clean code for Takepos * Debug v23 * Fix new path of dolreceiptprinter.class.php * Adjust signature appearance position in PDF generation (#37076) * EmailCollector: exclude sender emails/domains (#37075) # Conflicts: # htdocs/langs/en_US/admin.lang Co-authored-by: braito4 <braito4@users.noreply.github.com> * fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-15053838 Co-authored-by: snyk-bot <snyk-bot@snyk.io> * translate french doc to english (#37064) * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * Trans * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Show total multicurrency on payment (#37070) * Total multicurrency * Total multicurrency paiment * total result multicurrency * show total multicurrency * Fix CI * CLOSE #37085 - Popup notif is just under the menu bar * fix: add missing geturl lib (#37088) * Fix CI * Restrict to modiied files * #36843 Update card-rec.php (#37062) The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button. * Clean code * Fix CI * Doc * Fix CI * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * Fix comment and keep external modules out of core modules * Close #36975 * Close #36975 * css * NEW : hide remise_except unit price on invoice lines (#37066) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW(API): create fixed amount discount (#37091) * NEW(API): create fixed amount discount * FIX CI * FIX CI --------- Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> * Fix phan * CI * FIX - Create commonobject fetchWarehouse * FIX - for eldy coment * FIX - Phan * copy --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net> Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com> Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: MDW <mdeweerd@users.noreply.github.com> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com> Co-authored-by: Braito <braito4@hotmail.com> Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com> Co-authored-by: Thatoo <Thatoo@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> Co-authored-by: Vincent Maury <artec.vm@arnac.net> Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Jyhere <jyhere@gmail.com> Co-authored-by: Lenin Rivas <53640168+leninrivas@users.noreply.github.com> Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr> Co-authored-by: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Co-authored-by: LePat <patrick.muscat@gmail.com> Co-authored-by: braito4 <braito4@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io> Co-authored-by: Vanyo <vanyolai@gmail.com> Co-authored-by: AWeerWolf <74211972+AWeerWolf@users.noreply.github.com> Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com> Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-08-10 23:33:15 +00:00
$this->warehouse_id = $obj->fk_warehouse; // To avoid that some code use $user->warehouse when it is not loaded. It must be loaded with $user->fetch_warehouse() before.
$this->warehouse = null; // To avoid that some code use $user->warehouse when it is not loaded. It must be loaded with $user->fetch_warehouse() before.
2024-03-29 13:04:02 +00:00
$this->fk_establishment = $obj->fk_establishment;
$this->label_establishment = $obj->label_establishment;
// Protection when module multicompany was set, admin was set to first entity and then, the module was disabled,
// in such case, this admin user must be admin for ALL entities.
2022-08-28 12:40:36 +00:00
if (!isModEnabled('multicompany') && $this->admin && $this->entity == 1) {
2020-10-28 23:34:41 +00:00
$this->entity = 0;
}
2016-03-17 08:22:12 +00:00
NEW - Add substitution for user warehouse (#36670) * Fix trans and warning * Doc * Debug v23 * Debug v23 * Debug v23 * Doc * New import Leave Balance (Datastructure) (#37001) * New import Leave Balance (Datastructure) * fix --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> * Qual: Update Phan baseline.txt with reduced issue counts (#36996) This commit updates the Phan baseline.txt file. * Better log * Log * Better error management * Doc * Fix error message * CI * Try to fix CI * fix phan (#37007) * CI * fix phan (#37008) PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable) * CI * NEW Add new EUID number (#36997) * Doc * ci * Fix CI * Improve OAuth HTTP error details (#36951) Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins. Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add import of leave balance (Implementation) (#37011) * New add import Leave Balance * add eof * Update modHoliday.class.php --------- Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW add image format avif (#37014) * add format avif * Update functions.lib.php * Exclude non interesting warning * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * CI * CI * Trans * CI * CI * CI * Fix typo in phpstan.neon.dist for isset() rule (#37018) See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Try to fix phan * CI * CI * ci * ci * css * qual: Update french texts (comments) to english (#37009) * qual: Update french texts (comments) to english * Qual: Update comment to english in card-rec.php and card.php Translation of comments in the files card-rec.php and card.php. * Qual: Translate comments to English * Qual: Translate comments to English * Fix space into tab * Fix spelling * Qual: Translate comments to English * Update website.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * ci * Clean code * Fix test * Debug v23 * Merge manually changes from #37012 that seems good. * Log * More robust phpunit * Populate openid data from wellknow url (#37023) * Delete inexistant file File jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * Populate openid parameters from wellknow url * CI * Debug v23 - fix code for rounding * MCP server sql part (#37025) * Create llx_ai_request_log.sql * Create llx_ai_request_log.key.sql * Update 23.0.0-24.0.0.sql * Update llx_ai_request_log.sql * Update 23.0.0-24.0.0.sql * Remove foreign key constraint from llx_ai_request_log Removed foreign key constraint for fk_user in llx_ai_request_log. --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v24 * Fix syntax error * NEW allow to disable freezone product on takepos (#37004) * allow to disable freezone product on takepos * Conditionally add FreeZone product to menus * Add NoFreeZoneProduct language entry --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix label of dispute * [database] Minimum amount and subscription's amount formula description (#37021) * Remove jstz.min.js from JavaScript array (#37017) jstz.min.js was deleted in https://github.com/Dolibarr/dolibarr/commit/5599ac733b07d990d64e3ff18b30b3dca16d5b86 * prevent ST_AsWKT() (#37013) * prevent ST_AsWKT() * Update commonobject.class.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * css * Update llx_adherent_type.sql add minimumamount and amountformuladescription rows * Update 22.0.0-23.0.0.sql add minimumamount and amountformuladescription column --------- Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW: Display thirdparty name with ref in supplier orders linked objects (#36952) Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> * css * Debug v23 * Fix type * CI * CI * Test without file list * CI * Add api document management for holiday (#36915) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Invoice - List - use select2 multiselect for status (#36834) * NEW Invoice - List - use select2 multiselect for status * Optimize * CI * CI * Review * Duplicate line and last problem * CI --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX Pb in total price of line when adding the discount of a down payment when unit price was using a high accuracy. * Clean code * try to fix phan * Fix phan * Clean code * Clean code * Debug v23 * Fix LDAP * fix facture.class.php (#37031) * Debug v23 * Qual: Update french comments with 'nombre' (#37032) Update french comments with 'nombre' in their phrasing Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37029) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * fix phan (#37030) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Doc * Doc comment * FIX When bank direct debit SEPA ref is > 99 * Fix when there is more than 99 direct debit in same month * Debug v24 * Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 * CSS * Fix when there is more than 99 direct debit in same month * Debug v24 * FIX Division by zero * FIX Division by zero * More log * More log * More log * More Log * Fix IPN payment * Fix IPN * Log * Clean code * Debug v23 - Fix ipn for dispute and withdraw funds. * fix CI (#37033) * fix CI (#37033) * CI * fix french doc (#36897) * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * fix french doc * Update html.form.class.php * Update html.form.class.php * Update index.php * fix * fix * fix * fix * fix * fix * fix * fix * Update modules_facture.php * Update phpstan.neon.dist --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Translate French comments to English (#37044) * Qual: Translate French comments to English * Qual: Translate French comments to English * Qual: Translate French comments to English ("niveau") (#37041) Translate French comments to English (comments with "niveau") * fix french doc (#37040) * warning error if no societe->id defined (#37039) * fix french doc (#37037) * fix french doc * Update dispatch.php * Update dispatch.php * Update graph.php * fix french doc (#37047) * fix french doc * Update index.php * Update index.php * Fix CI * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * CI * Fix CI * Minimum amount and subscription's amount formula description (#37006) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043) * Warning on export - Add isset() protection in Export::load_arrays() * Warning on import - Add isset() protection in Import::load_arrays() --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Clean comment * Warning on account model (#37042) * Error on account model * Simplify rowid assignment in accountmodel.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix #35394 Display public note on first page (#36993) * Display public note (an incoterms and sales rep signat) only on real first page * Display public note (an incoterms and sales rep signat) only on real first page --------- Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX: Add htmlname and selectedrate to parameters array for hook (#36998) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix CI * Fix CI * Fix CI * Fix ci * Qual: Translate French comments to English (#37052) * Qual: Translate French 'valeur' in comments to English (#37051) * NEW Accountancy - Select between accrual accounting and cash accounting (#37050) * Qual: Translate french 'avec' comments to English (#37049) # Qual: Translate french 'avec' comments to English * FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046) * FIX rate_indirect to rate_direct Direct : 1 Divisa Currency = X Currency Main. Indirect : 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * FIX divisa rate indirect to direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Divisa rate direct Direct : 1 Divisa Currency = X Currency Main. Indirect: 1 Currency Main = X Divisa Currency. Then for Dolibarr use is Indirect for default * Add col rate_direct because Dolibarr use for.default rate indirect --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * CI * Add thumbnails for avif (#37045) * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * vignette for avif * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * FIX #36892 * NEW : Manage discount for all lines for supplier elements. (#36954) * NEW : Manage remise for all lines for supplier elements. * Cast remise_percent to float in updateline call --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Fix Signature position (#37048) Move up the position of the signature to fix its explosion on 3 pages * remove french doc and fix travis migration missing (#37053) * fix french doc * fix french doc * fix french doc * fix french doc * Clean up comments in card.php Removed unnecessary comments from card.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Debug v23 * Fix CSS * Fix CSS * Fix sql syntax error * Fix sql syntax error * Add optionnal img to openid login (#37060) * fix french doc (#37056) * fix french doc * fix french doc * fix french doc * doc translation * doc translation * doc translation * doc translation * doc translation * load tables in init for create categorie table associated (#37059) * Fix situation invoice * Fix situation invoice * Debug v23 * Link and filter on ountry for holiday types * Link and filter on ountry for holiday types * Trans * Debug v23 * css * CSS on current day * Debug v23 * css * More complete message * Make array of dispute status a shared constant * Debug v23 * Debug v23 * bad link on sql in fichinter list (#37081) * bad link on sql in fichinter list (#37081) * FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078) * feat: CustomerDisplay through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * feat: WeighingScale through Webapp-Hardware-Bridge * fix: looks like a typo * feat: for small screens * fix: attribut contenant le prix du produit ajouté * feat: ajout d'un callback de gestion d'erreur * Clean code for Takepos * Debug v23 * Fix new path of dolreceiptprinter.class.php * Adjust signature appearance position in PDF generation (#37076) * EmailCollector: exclude sender emails/domains (#37075) # Conflicts: # htdocs/langs/en_US/admin.lang Co-authored-by: braito4 <braito4@users.noreply.github.com> * fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-15053838 Co-authored-by: snyk-bot <snyk-bot@snyk.io> * translate french doc to english (#37064) * fix french doc * fix french doc * fix french doc * fix french doc * fix * fix * fix * fix * Trans * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Change translation function to transnoentities (#37065) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW Show total multicurrency on payment (#37070) * Total multicurrency * Total multicurrency paiment * total result multicurrency * show total multicurrency * Fix CI * CLOSE #37085 - Popup notif is just under the menu bar * fix: add missing geturl lib (#37088) * Fix CI * Restrict to modiied files * #36843 Update card-rec.php (#37062) The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button. * Clean code * Fix CI * Doc * Fix CI * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * family assignment logic on user perms of external modules (#36456) * family assignment logic on user perms of external modules Updated family assignment logic to default to 'other' if family does not exist in $familyinfo. * Update copyright year for Charlene Benke * Fix comment and keep external modules out of core modules * Close #36975 * Close #36975 * css * NEW : hide remise_except unit price on invoice lines (#37066) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * NEW(API): create fixed amount discount (#37091) * NEW(API): create fixed amount discount * FIX CI * FIX CI --------- Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> * Fix phan * CI * FIX - Create commonobject fetchWarehouse * FIX - for eldy coment * FIX - Phan * copy --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net> Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com> Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com> Co-authored-by: MDW <mdeweerd@users.noreply.github.com> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com> Co-authored-by: Braito <braito4@hotmail.com> Co-authored-by: caminotravelcenter <caminotravelcenter@localhost> Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com> Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com> Co-authored-by: Thatoo <Thatoo@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa> Co-authored-by: Vincent Maury <artec.vm@arnac.net> Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD> Co-authored-by: Jyhere <jyhere@gmail.com> Co-authored-by: Lenin Rivas <53640168+leninrivas@users.noreply.github.com> Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr> Co-authored-by: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Co-authored-by: LePat <patrick.muscat@gmail.com> Co-authored-by: braito4 <braito4@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io> Co-authored-by: Vanyo <vanyolai@gmail.com> Co-authored-by: AWeerWolf <74211972+AWeerWolf@users.noreply.github.com> Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com> Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr> Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-08-10 23:33:15 +00:00
// If user is linked to a warehouse, we load it into memory
if (isModEnabled('stock') && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && (!empty($this->fk_warehouse) || !empty($this->warehouse_id))) {
$this->fetchWarehouse();
}
2020-10-23 18:08:35 +00:00
// Retrieve all extrafield
// fetch optionals attributes and labels
2018-02-20 18:38:18 +00:00
$this->fetch_optionals();
2007-04-13 16:11:44 +00:00
$this->db->free($resql);
2020-05-21 13:05:19 +00:00
} else {
$this->error = "USERNOTFOUND";
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::fetch user not found", LOG_DEBUG);
2007-04-13 16:11:44 +00:00
$this->db->free($resql);
2007-10-02 18:16:29 +00:00
return 0;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
2007-04-13 16:11:44 +00:00
return -1;
}
// To get back the global configuration unique to the user
2020-10-28 23:34:41 +00:00
if ($loadpersonalconf) {
2025-10-15 02:36:06 +00:00
$result = $this->loadPersonalConf($entity);
$result = $this->loadDefaultValues();
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$this->error = $this->db->lasterror();
return -3;
}
}
// Add option to allow an admin internal user to make quick debug for internal users. Not yet implemented completely.
// This is a special cas that is allowed to have a GETPOST inside a class.
if (GETPOSTINT('forceexternaluser') && $this->admin && empty($this->socid)) {
$this->socid = GETPOSTINT('forceexternaluser');
}
return 1;
}
2023-10-30 13:23:27 +00:00
/**
* Load const values from database table user_param and set it into user->conf->XXX
*
2025-10-15 02:36:06 +00:00
* @param int $entity If >=0, force the entity, if -1, use the default entity
2023-11-09 14:50:42 +00:00
* @return int >= 0 if OK, < 0 if KO
2023-10-30 13:23:27 +00:00
*/
2025-10-15 02:36:06 +00:00
public function loadPersonalConf($entity = -1)
2023-10-30 13:23:27 +00:00
{
global $conf;
// Load user->conf for user
$sql = "SELECT param, value FROM ".$this->db->prefix()."user_param";
$sql .= " WHERE fk_user = ".((int) $this->id);
if ($entity < 0) {
$sql .= " AND entity IN (0, ".((int) $conf->entity).")"; // IN (0, x)
} else {
$sql .= " AND entity = ".((int) $entity); // 0 or x
}
2025-10-15 02:36:06 +00:00
2023-10-30 13:23:27 +00:00
//dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
$p = (!empty($obj->param) ? $obj->param : '');
if (!empty($p)) {
$this->conf->$p = $obj->value;
}
$i++;
}
$this->db->free($resql);
2023-11-09 14:50:42 +00:00
return $num;
2023-10-30 13:23:27 +00:00
} else {
$this->error = $this->db->lasterror();
2023-11-09 14:50:42 +00:00
2023-10-30 13:23:27 +00:00
return -2;
}
}
/**
2021-03-20 20:36:42 +00:00
* Load default values from database table into property ->default_values
*
* @return int > 0 if OK, < 0 if KO
*/
2019-02-25 19:35:59 +00:00
public function loadDefaultValues()
{
global $conf;
2023-10-30 13:23:27 +00:00
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MAIN_ENABLE_DEFAULT_VALUES')) {
2021-03-01 19:36:42 +00:00
// Load user->default_values for user. TODO Save this in memcached ?
require_once DOL_DOCUMENT_ROOT.'/core/class/defaultvalues.class.php';
2021-03-01 19:36:42 +00:00
$defaultValues = new DefaultValues($this->db);
$result = $defaultValues->fetchAll('', '', 0, 0, '(t.user_id:in:0,'.$this->id.') AND (entity:in:'.(isset($this->entity) ? $this->entity : $conf->entity).','.$conf->entity.')'); // User 0 (all) + me (if defined)
//$result = $defaultValues->fetchAll('', '', 0, 0, array('t.user_id'=>array(0, $this->id), 'entity'=>array((isset($this->entity) ? $this->entity : $conf->entity), $conf->entity))); // User 0 (all) + me (if defined)
2021-03-01 19:36:42 +00:00
2021-03-02 13:44:31 +00:00
if (!is_array($result) && $result < 0) {
2021-03-01 20:00:32 +00:00
setEventMessages($defaultValues->error, $defaultValues->errors, 'errors');
2021-03-01 19:36:42 +00:00
dol_print_error($this->db);
return -1;
2021-03-02 14:34:43 +00:00
} elseif (count($result) > 0) {
2021-03-01 20:00:32 +00:00
foreach ($result as $defval) {
2021-03-01 19:36:42 +00:00
if (!empty($defval->page) && !empty($defval->type) && !empty($defval->param)) {
$pagewithoutquerystring = $defval->page;
$pagequeries = '';
$reg = array();
if (preg_match('/^([^\?]+)\?(.*)$/', $pagewithoutquerystring, $reg)) { // There is query param
$pagewithoutquerystring = $reg[1];
$pagequeries = $reg[2];
}
$this->default_values[$pagewithoutquerystring][$defval->type][$pagequeries ? $pagequeries : '_noquery_'][$defval->param] = $defval->value;
}
}
}
if (!empty($this->default_values)) {
2020-10-28 23:34:41 +00:00
foreach ($this->default_values as $a => $b) {
foreach ($b as $c => $d) {
krsort($this->default_values[$a][$c]);
}
}
}
}
2021-03-01 19:36:42 +00:00
return 1;
2007-04-13 16:11:44 +00:00
}
2025-11-26 23:05:04 +00:00
/**
* Return if a user is an admin user
* It replaces old syntax: if ($user->admin)
*
* @return int<0,1> Return integer 1 if user is admin, 0 if not.
*/
public function isAdmin()
{
return $this->admin;
}
/**
* Return if a user is an external user
* It replaces old syntax: if ($user->socid)
*
* @return int Return integer if user is an dexternal user, 0 if not.
*/
public function isExternalUser()
{
return $this->socid;
}
2025-11-26 23:05:04 +00:00
2021-08-24 12:47:50 +00:00
/**
* Return if a user has a permission.
* You can use it like this: if ($user->hasRight('module', 'level11')).
* It replaces old syntax: if ($user->rights->module->level1)
*
* @param string $module Module of permission to check
* @param string $permlevel1 Permission level1 (Example: 'read', 'write', 'delete')
2021-08-24 12:47:50 +00:00
* @param string $permlevel2 Permission level2
* @return int<0,1> Return integer 1 if user has permission, 0 if not.
* @see clearrights(), delrights(), loadRights(), hasRight()
2021-08-24 12:47:50 +00:00
*/
public function hasRight($module, $permlevel1, $permlevel2 = '')
{
// For compatibility with bad naming permissions on module
$moduletomoduletouse = array(
2025-05-05 16:45:14 +00:00
'category' => 'categorie',
'compta' => 'comptabilite',
'contract' => 'contrat',
2022-09-08 10:29:46 +00:00
'member' => 'adherent',
'mo' => 'mrp',
'order' => 'commande',
'produit' => 'product',
2025-04-25 23:52:31 +00:00
'productlot' => 'product',
'project' => 'projet',
2022-09-07 14:39:19 +00:00
'propale' => 'propal',
'shipping' => 'expedition',
'task' => 'task@projet',
'fichinter' => 'ficheinter',
2026-05-04 07:54:31 +00:00
'intervention' => 'ficheinter',
2021-12-19 02:54:04 +00:00
'inventory' => 'stock',
'invoice' => 'facture',
'invoice_supplier' => 'facture@fournisseur',
'order_supplier' => 'fournisseur',
'knowledgerecord' => 'knowledgerecord@knowledgemanagement',
'skill@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
'job@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
'position@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
'facturerec' => 'facture',
'margins' => 'margin',
);
2022-06-09 11:15:40 +00:00
if (!empty($moduletomoduletouse[$module])) {
$module = $moduletomoduletouse[$module];
}
// Compatibility layer for the supplier module split transition (MAIN_USE_NEW_SUPPLIERMOD).
// Allows both old and new permission syntaxes to work in parallel during migration.
// - Old: $user->hasRight('fournisseur', 'commande', 'lire')
// - New: $user->hasRight('supplier_order', 'lire')
// External modules are also transparently supported without any change on their side.
if (getDolGlobalInt('MAIN_USE_NEW_SUPPLIERMOD')) {
// New module names introduced by the split, mapped to their legacy equivalent.
// Format: 'new_module' => ['legacy_module', 'legacy_permlevel1']
$supplierNewToLegacy = array(
'supplier_order' => array('fournisseur', 'commande'),
'supplier_invoice' => array('fournisseur', 'facture'),
);
if (isset($supplierNewToLegacy[$module])) {
// Caller used new syntax: rewrite to legacy so the rights object resolves correctly.
// e.g. hasRight('supplier_order', 'lire') -> hasRight('fournisseur', 'commande', 'lire')
$permlevel2 = $permlevel1;
$permlevel1 = $supplierNewToLegacy[$module][1]; // e.g. 'commande'
$module = $supplierNewToLegacy[$module][0]; // e.g. 'fournisseur'
}
} else {
// Legacy mode: translate new module names back to old ones in case some
// updated code calls the new syntax while the option is not yet enabled.
$supplierLegacyCompat = array(
'supplier_order' => 'fournisseur',
'supplier_invoice' => 'fournisseur',
);
if (isset($supplierLegacyCompat[$module])) {
// e.g. hasRight('supplier_order', 'lire') stays routed through 'fournisseur'
$module = $supplierLegacyCompat[$module];
}
}
2022-06-09 11:15:40 +00:00
$moduleRightsMapping = array(
Fix #28071 - New branch to fix bad merge (#28083) * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Qual: Introduce getDataToShowPhoto to prepare generic code * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix missing trans * Fix langs * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Remove useless files in web templates * Clean code * Fix duplicate translation key * Fix duplicate translation key * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix duplicate key * Fix $object * Debug v19 * WIP SMSing * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * WIP EMAILINGS_SUPPORT_ALSO_SMS * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * WIP SMSing * Debug the "validate" feature * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Clean code * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Enhance rector to fix empty($user->rights->modulex->perm1) * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix template to use v19 dev rules * Fix use v19 dev rules * Fix phpunit * Debug v19 * Clean code * Use rector to convert user->rights into user->hasRight * Clean code * Use rector to convert user->rights into user->hasRight * Use rector to convert user->rights into user->hasRight * Clean code * Fix phpcs * add editorconfig for sql files (#27999) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * add model_pdf field in llx_ticket-ticket.sql (#27996) * add model_pdf field in llx_ticket-ticket.sql * Update 19.0.0-20.0.0.sql * Update 19.0.0-20.0.0.sql * Improve wording in README (#27994) * fix phpstan (#27989) * fix phpstan * Update UserRightsToFunction.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Fix spelling/working in datapolicy translations (#28006) # Qual: Fix spelling/wording in datapolicy translations Fixed some spelling and wording in datapolicy translations. * qual: phpstan for htdocs/ticket/class/ticketstats.class.php (#27986) htdocs/ticket/class/ticketstats.class.php 98 Parameter #1 $year (string) of method TicketStats::getNbByMonth() should be compatible with parameter $year (int) of method Stats::getNbByMonth() * Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into develop * Fix user with readonly perm on email template must be able to read. * Fix doc * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Better message * Add missing fields in merge of thirdparty * Debug v19 selection of ticket printer per terminal * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Use constant * NEW: Adding a recipient on emails sent, change status to sent partialy. * fix travis (#28052) * fix travis * Update partnership.class.php * fix php doc (#28047) * fix undefined array key (#28048) * Add region and departament for Cuba (#28046) * Update llx_10_c_regions.sql Add Cuba Regions (id_country=77) * Update llx_20_c_departements.sql Add Provinces Cuba (id country=77) * Find the typo (#28050) * Find the typo * clean code * add last_main_doc field to product (#28045) * add las_main_doc field to product * add field fetch * NEW Add Categorie filter for ActionComm (#28041) * New Add Categorie filter for ActionComm New Add Categorie filter for ActionComm * Fix space errors Fix space errors * Fix space errors 2 Fix space errors 2 * Update cunits.class.php (#28056) FIX: error SQL when creating a Cunit * Update codespell-lines-ignore.txt to avoid PR merge conflict --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: thibdrev <thibault.drevet@gmail.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Ikarus <44511582+LeKarSol@users.noreply.github.com> Co-authored-by: Anthony Damhet <73399671+EchoLoGeek@users.noreply.github.com> Co-authored-by: Quentin-Seekness <72733832+Quentin-Seekness@users.noreply.github.com>
2024-02-09 14:58:49 +00:00
'product' => 'produit',
'margin' => 'margins',
'comptabilite' => 'compta'
2022-06-09 11:15:40 +00:00
);
2022-06-09 11:20:59 +00:00
2022-06-09 11:15:40 +00:00
$rightsPath = $module;
if (!empty($moduleRightsMapping[$rightsPath])) {
$rightsPath = $moduleRightsMapping[$rightsPath];
}
Fix #28071 - New branch to fix bad merge (#28083) * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Qual: Introduce getDataToShowPhoto to prepare generic code * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix missing trans * Fix langs * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Remove useless files in web templates * Clean code * Fix duplicate translation key * Fix duplicate translation key * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix duplicate key * Fix $object * Debug v19 * WIP SMSing * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * WIP EMAILINGS_SUPPORT_ALSO_SMS * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * WIP SMSing * Debug the "validate" feature * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Clean code * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Move rights->x->y into hasRight('x', 'y') * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Enhance rector to fix empty($user->rights->modulex->perm1) * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Fix template to use v19 dev rules * Fix use v19 dev rules * Fix phpunit * Debug v19 * Clean code * Use rector to convert user->rights into user->hasRight * Clean code * Use rector to convert user->rights into user->hasRight * Use rector to convert user->rights into user->hasRight * Clean code * Fix phpcs * add editorconfig for sql files (#27999) Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * add model_pdf field in llx_ticket-ticket.sql (#27996) * add model_pdf field in llx_ticket-ticket.sql * Update 19.0.0-20.0.0.sql * Update 19.0.0-20.0.0.sql * Improve wording in README (#27994) * fix phpstan (#27989) * fix phpstan * Update UserRightsToFunction.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> * Qual: Fix spelling/working in datapolicy translations (#28006) # Qual: Fix spelling/wording in datapolicy translations Fixed some spelling and wording in datapolicy translations. * qual: phpstan for htdocs/ticket/class/ticketstats.class.php (#27986) htdocs/ticket/class/ticketstats.class.php 98 Parameter #1 $year (string) of method TicketStats::getNbByMonth() should be compatible with parameter $year (int) of method Stats::getNbByMonth() * Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into develop * Fix user with readonly perm on email template must be able to read. * Fix doc * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Better message * Add missing fields in merge of thirdparty * Debug v19 selection of ticket printer per terminal * Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop * Use constant * NEW: Adding a recipient on emails sent, change status to sent partialy. * fix travis (#28052) * fix travis * Update partnership.class.php * fix php doc (#28047) * fix undefined array key (#28048) * Add region and departament for Cuba (#28046) * Update llx_10_c_regions.sql Add Cuba Regions (id_country=77) * Update llx_20_c_departements.sql Add Provinces Cuba (id country=77) * Find the typo (#28050) * Find the typo * clean code * add last_main_doc field to product (#28045) * add las_main_doc field to product * add field fetch * NEW Add Categorie filter for ActionComm (#28041) * New Add Categorie filter for ActionComm New Add Categorie filter for ActionComm * Fix space errors Fix space errors * Fix space errors 2 Fix space errors 2 * Update cunits.class.php (#28056) FIX: error SQL when creating a Cunit * Update codespell-lines-ignore.txt to avoid PR merge conflict --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr> Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com> Co-authored-by: thibdrev <thibault.drevet@gmail.com> Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com> Co-authored-by: Ikarus <44511582+LeKarSol@users.noreply.github.com> Co-authored-by: Anthony Damhet <73399671+EchoLoGeek@users.noreply.github.com> Co-authored-by: Quentin-Seekness <72733832+Quentin-Seekness@users.noreply.github.com>
2024-02-09 14:58:49 +00:00
// If module is abc@module, we check permission user->hasRight(module, abc, permlevel1)
2022-06-09 11:15:40 +00:00
$tmp = explode('@', $rightsPath, 2);
2022-08-31 20:14:20 +00:00
if (!empty($tmp[1])) {
if (strpos($module, '@') !== false) {
$module = $tmp[1];
}
2024-02-16 22:56:07 +00:00
if ($tmp[0] != $tmp[1]) {
// If $module = 'myobject@mymodule'
$rightsPath = $tmp[1];
$permlevel2 = $permlevel1;
$permlevel1 = $tmp[0];
} else {
// If $module = 'abc@abc'
$rightsPath = $tmp[1];
}
}
// In $conf->modules, we have 'accounting', 'product', 'facture', ...
// In $user->rights, we have 'accounting', 'produit', 'facture', ...
2022-09-08 14:38:39 +00:00
//var_dump($this->rights->$rightsPath);
//var_dump($conf->modules);
2024-11-07 18:51:02 +00:00
//if ($module == 'fournisseur') { var_dump($module.' '.isModEnabled($module).' '.$rightsPath.' '.$permlevel1.' '.$permlevel2); }
2022-09-09 11:58:54 +00:00
if (!isModEnabled($module)) {
return 0;
}
2024-01-09 13:24:21 +00:00
// Special case for external user
if (!empty($this->socid)) {
2024-05-02 19:48:50 +00:00
if ($module == 'societe' && ($permlevel1 == 'creer' || $permlevel1 == 'write')) {
return 0; // An external user never has the permission ->societe->write to see all thirdparties (always restricted to himself)
}
if ($module == 'societe' && $permlevel1 == 'client' && $permlevel2 == 'voir') {
2024-01-09 13:24:21 +00:00
return 0; // An external user never has the permission ->societe->client->voir to see all thirdparties (always restricted to himself)
}
2024-05-02 19:48:50 +00:00
if ($module == 'societe' && $permlevel1 == 'export') {
return 0; // An external user never has the permission ->societe->export to see all thirdparties (always restricted to himself)
}
if ($module == 'societe' && ($permlevel1 == 'supprimer' || $permlevel1 == 'delete')) {
return 0; // An external user never has the permission ->societe->delete to see all thirdparties (always restricted to himself)
}
2024-01-09 13:24:21 +00:00
}
// For compatibility with bad naming permissions on permlevel1
if ($permlevel1 == 'propale') {
$permlevel1 = 'propal';
}
if ($permlevel1 == 'member') {
$permlevel1 = 'adherent';
}
if ($permlevel1 == 'recruitmentcandidature') {
$permlevel1 = 'recruitmentjobposition';
}
2022-06-09 11:15:40 +00:00
//var_dump($this->rights);
//var_dump($rightsPath.' '.$permlevel1.' '.$permlevel2);
2022-06-09 11:15:40 +00:00
if (empty($rightsPath) || empty($this->rights) || empty($this->rights->$rightsPath) || empty($permlevel1)) {
2021-08-24 12:47:50 +00:00
return 0;
}
if ($permlevel2) {
2022-06-09 11:15:40 +00:00
if (!empty($this->rights->$rightsPath->$permlevel1)) {
if (!empty($this->rights->$rightsPath->$permlevel1->$permlevel2)) {
return $this->rights->$rightsPath->$permlevel1->$permlevel2;
}
// For backward compatibility with old permissions called "lire", "creer", "create", "supprimer"
// instead of "read", "write", "delete"
2022-06-09 11:15:40 +00:00
if ($permlevel2 == 'read' && !empty($this->rights->$rightsPath->$permlevel1->lire)) {
return $this->rights->$rightsPath->$permlevel1->lire;
}
2022-06-09 11:15:40 +00:00
if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->creer)) {
2022-08-02 09:53:33 +00:00
return $this->rights->$rightsPath->$permlevel1->creer;
}
2022-06-09 11:15:40 +00:00
if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->create)) {
return $this->rights->$rightsPath->$permlevel1->create;
}
2022-06-09 11:15:40 +00:00
if ($permlevel2 == 'delete' && !empty($this->rights->$rightsPath->$permlevel1->supprimer)) {
return $this->rights->$rightsPath->$permlevel1->supprimer;
}
2021-08-24 12:47:50 +00:00
}
} else {
2022-06-09 11:15:40 +00:00
if (!empty($this->rights->$rightsPath->$permlevel1)) {
return $this->rights->$rightsPath->$permlevel1;
2021-08-24 12:47:50 +00:00
}
// For backward compatibility with old permissions called "lire", "creer", "create", "supprimer"
// instead of "read", "write", "delete"
2022-06-09 11:15:40 +00:00
if ($permlevel1 == 'read' && !empty($this->rights->$rightsPath->lire)) {
return $this->rights->$rightsPath->lire;
}
2022-06-09 11:15:40 +00:00
if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->creer)) {
2022-08-02 09:53:33 +00:00
return $this->rights->$rightsPath->creer;
}
2022-06-09 11:15:40 +00:00
if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->create)) {
return $this->rights->$rightsPath->create;
}
2022-06-09 11:15:40 +00:00
if ($permlevel1 == 'delete' && !empty($this->rights->$rightsPath->supprimer)) {
return $this->rights->$rightsPath->supprimer;
}
2021-08-24 12:47:50 +00:00
}
return 0;
}
/**
* Add a right to the user
2011-09-04 18:41:19 +00:00
*
2018-07-02 07:34:34 +00:00
* @param int $rid Id of permission to add or 0 to add several permissions
2019-06-20 00:43:56 +00:00
* @param string $allmodule Add all permissions of module $allmodule or 'allmodules' to include all modules.
* @param string $allperms Add all permissions of module $allmodule, subperms $allperms only or '' to include all permissions.
* @param int $entity Entity to use
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
add baseline exclude for phpstan (#31632) * add baseline exclude for phpstan * update * update * update * update * update * merge * restore one filter * delete old errors * fix * fix * fix * $moreforfilter can t be empty * fix * enable check * refresh baseline * add phpdoc * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-11-04 22:53:20 +00:00
* @return int Return integer > 0 if OK, < 0 if KO
* @see clearrights(), delrights(), loadRights(), hasRight()
*/
2019-02-25 19:35:59 +00:00
public function addrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
{
2017-02-28 10:48:46 +00:00
global $conf, $user, $langs;
$entity = (empty($entity) ? $conf->entity : $entity);
dol_syslog(get_class($this)."::addrights $rid, $allmodule, $allperms, $entity, $notrigger for user id=".$this->id);
2023-04-13 16:30:06 +00:00
if (empty($this->id)) {
$this->error = 'Try to call addrights on an object user with an empty id';
return -1;
}
$error = 0;
$whereforadd = '';
$this->db->begin();
2020-10-28 23:34:41 +00:00
if (!empty($rid)) {
2020-11-07 18:39:51 +00:00
$module = $perms = $subperms = '';
// If we ask to add a given permission, we first load properties of this permission (module, perms and subperms).
$sql = "SELECT module, perms, subperms";
$sql .= " FROM ".$this->db->prefix()."rights_def";
2020-11-07 18:39:51 +00:00
$sql .= " WHERE id = ".((int) $rid);
$sql .= " AND entity = ".((int) $entity);
$result = $this->db->query($sql);
if ($result) {
$obj = $this->db->fetch_object($result);
2020-11-07 18:39:51 +00:00
if ($obj) {
$module = $obj->module;
$perms = $obj->perms;
$subperms = $obj->subperms;
}
2020-05-21 13:05:19 +00:00
} else {
2017-02-28 10:48:46 +00:00
$error++;
dol_print_error($this->db);
}
// Define the where for the permission to add
2020-11-07 18:39:51 +00:00
$whereforadd = "id=".((int) $rid);
// Add also inherited permissions
2020-10-28 23:34:41 +00:00
if (!empty($subperms)) {
2020-11-07 18:39:51 +00:00
$whereforadd .= " OR (module='".$this->db->escape($module)."' AND perms='".$this->db->escape($perms)."' AND (subperms='lire' OR subperms='read'))";
2020-10-28 23:34:41 +00:00
} elseif (!empty($perms)) {
2024-08-31 10:24:49 +00:00
$whereforadd .= " OR (module='".$this->db->escape($module)."' AND (perms='lire' OR perms='read') AND (subperms IS NULL or subperms = ''))";
2020-10-28 23:34:41 +00:00
}
2020-05-21 13:05:19 +00:00
} else {
// A list of permission was requested (not a single specific permission)
// based on the name of a module of permissions
// Used in the where clause to determine the list of permissions to add.
2020-10-28 23:34:41 +00:00
if (!empty($allmodule)) {
if ($allmodule == 'allmodules') {
$whereforadd = 'allmodules';
2020-05-21 13:05:19 +00:00
} else {
$whereforadd = "module='".$this->db->escape($allmodule)."'";
2020-10-28 23:34:41 +00:00
if (!empty($allperms)) {
$whereforadd .= " AND perms='".$this->db->escape($allperms)."'";
}
}
2017-10-22 11:05:47 +00:00
}
}
2021-04-05 11:52:19 +00:00
// Add automatically other permission using the criteria whereforadd
// $whereforadd can be a SQL filter or the string 'allmodules'
2020-10-28 23:34:41 +00:00
if (!empty($whereforadd)) {
//print "$module-$perms-$subperms";
$sql = "SELECT id";
$sql .= " FROM ".$this->db->prefix()."rights_def";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE entity = ".((int) $entity);
if (!empty($whereforadd) && $whereforadd != 'allmodules') {
$sql .= " AND (".$whereforadd.")"; // Note: parenthesis are important because whereforadd can contains OR. Also note that $whereforadd is already sanitized
}
$sqldelete = "DELETE FROM ".$this->db->prefix()."user_rights";
$sqldelete .= " WHERE fk_user = ".((int) $this->id)." AND fk_id IN (";
$sqldelete .= $sql;
$sqldelete .= ") AND entity = ".((int) $entity);
if (!$this->db->query($sqldelete)) {
$error++;
}
if (!$error) {
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
if ($obj) {
$nid = $obj->id;
$sql = "INSERT INTO ".$this->db->prefix()."user_rights (entity, fk_user, fk_id) VALUES (".((int) $entity).", ".((int) $this->id).", ".((int) $nid).")";
if (!$this->db->query($sql)) {
$error++;
}
}
$i++;
}
} else {
$error++;
dol_print_error($this->db);
}
}
}
2020-10-28 23:34:41 +00:00
if (!$error && !$notrigger) {
2017-12-08 11:38:22 +00:00
$langs->load("other");
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
$this->context = array('audit' => $langs->trans("PermissionsAdd").($rid ? ' (id='.$rid.')' : ''));
2017-03-13 14:00:44 +00:00
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
2017-02-28 10:48:46 +00:00
}
2017-03-13 14:00:44 +00:00
2017-02-28 10:48:46 +00:00
if ($error) {
$this->db->rollback();
2017-02-28 10:48:46 +00:00
return -$error;
2020-05-21 13:05:19 +00:00
} else {
$this->db->commit();
return 1;
}
}
/**
* Remove a right to the user
2011-09-04 18:41:19 +00:00
*
2024-05-06 16:25:06 +00:00
* @param int $rid Id of permission to remove (or 0 when using the other filters)
* @param string $allmodule Retirer tous les droits du module allmodule
* @param string $allperms Retirer tous les droits du module allmodule, perms allperms
* @param int|string $entity Entity to use. Example: '1', or '0,1', or '2,3'
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
add baseline exclude for phpstan (#31632) * add baseline exclude for phpstan * update * update * update * update * update * merge * restore one filter * delete old errors * fix * fix * fix * $moreforfilter can t be empty * fix * enable check * refresh baseline * add phpdoc * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * update phpstan baseline * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-11-04 22:53:20 +00:00
* @return int Return integer > 0 if OK, < 0 if OK
* @see clearrights(), addrights(), loadRights(), hasRight()
*/
2019-02-25 19:35:59 +00:00
public function delrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
{
2017-02-28 10:48:46 +00:00
global $conf, $user, $langs;
$error = 0;
$wherefordel = '';
$entity = (!empty($entity) ? $entity : $conf->entity);
$this->db->begin();
if (!empty($rid)) {
2020-11-07 18:39:51 +00:00
$module = $perms = $subperms = '';
// When the request is to delete a specific permissions, this gets the
// les charactis for the module, permissions and sub-permission of this permission.
$sql = "SELECT module, perms, subperms";
$sql .= " FROM ".$this->db->prefix()."rights_def";
$sql .= " WHERE id = ".((int) $rid);
2024-05-06 16:25:06 +00:00
$sql .= " AND entity IN (".$this->db->sanitize($entity, 0, 0, 0, 0).")";
$result = $this->db->query($sql);
if ($result) {
$obj = $this->db->fetch_object($result);
2020-11-07 18:39:51 +00:00
if ($obj) {
$module = $obj->module;
$perms = $obj->perms;
$subperms = $obj->subperms;
}
2020-05-21 13:05:19 +00:00
} else {
2017-02-28 10:48:46 +00:00
$error++;
dol_print_error($this->db);
}
// Where clause for the list of permissions to delete
2020-11-07 18:39:51 +00:00
$wherefordel = "id=".((int) $rid);
// Removal of induced rights
2020-10-28 23:34:41 +00:00
if ($subperms == 'lire' || $subperms == 'read') {
2020-11-07 18:39:51 +00:00
$wherefordel .= " OR (module='".$this->db->escape($module)."' AND perms='".$this->db->escape($perms)."' AND subperms IS NOT NULL)";
2020-10-28 23:34:41 +00:00
}
if ($perms == 'lire' || $perms == 'read') {
2020-11-07 18:39:51 +00:00
$wherefordel .= " OR (module='".$this->db->escape($module)."')";
2020-10-28 23:34:41 +00:00
}
2019-02-25 19:35:59 +00:00
} else {
// The deletion of the permissions concerns the name of a module or
// list of permissions.
// Used in the Where clause to determine the list of permission to delete
2020-10-29 17:37:52 +00:00
if (!empty($allmodule)) {
if ($allmodule == 'allmodules') {
$wherefordel = 'allmodules';
2020-05-21 13:05:19 +00:00
} else {
$wherefordel = "module='".$this->db->escape($allmodule)."'";
2020-10-29 17:37:52 +00:00
if (!empty($allperms)) {
$wherefordel .= " AND perms='".$this->db->escape($allperms)."'";
}
}
}
}
2024-05-06 16:25:06 +00:00
// Delete permission according to a criteria set into $wherefordel
2020-10-28 23:34:41 +00:00
if (!empty($wherefordel)) {
//print "$module-$perms-$subperms";
$sql = "SELECT id";
$sql .= " FROM ".$this->db->prefix()."rights_def";
2024-05-06 16:25:06 +00:00
$sql .= " WHERE entity IN (".$this->db->sanitize($entity, 0, 0, 0, 0).")";
if (!empty($wherefordel) && $wherefordel != 'allmodules') {
$sql .= " AND (".$wherefordel.")"; // Note: parenthesis are important because wherefordel can contains OR. Also note that $wherefordel is already sanitized
}
2024-05-06 16:25:06 +00:00
// avoid admin to remove his own important rights
2020-10-28 23:34:41 +00:00
if ($this->admin == 1) {
$sql .= " AND id NOT IN (251, 252, 253, 254, 255, 256)"; // other users rights
$sql .= " AND id NOT IN (341, 342, 343, 344)"; // own rights
$sql .= " AND id NOT IN (351, 352, 353, 354)"; // groups rights
$sql .= " AND id NOT IN (358)"; // user export
}
$sqldelete = "DELETE FROM ".$this->db->prefix()."user_rights";
$sqldelete .= " WHERE fk_user = ".((int) $this->id)." AND fk_id IN (";
$sqldelete .= $sql;
$sqldelete .= ")";
2024-05-06 16:25:06 +00:00
$sqldelete .= " AND entity IN (".$this->db->sanitize($entity, 0, 0, 0, 0).")";
$resql = $this->db->query($sqldelete);
if (!$resql) {
2017-02-28 10:48:46 +00:00
$error++;
dol_print_error($this->db);
}
}
2020-10-28 23:34:41 +00:00
if (!$error && !$notrigger) {
2017-12-08 11:38:22 +00:00
$langs->load("other");
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
$this->context = array('audit' => $langs->trans("PermissionsDelete").($rid ? ' (id='.$rid.')' : ''));
2017-03-13 14:00:44 +00:00
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
2017-02-28 10:48:46 +00:00
}
2017-03-13 14:00:44 +00:00
2017-02-28 10:48:46 +00:00
if ($error) {
$this->db->rollback();
2017-02-28 10:48:46 +00:00
return -$error;
2020-05-21 13:05:19 +00:00
} else {
$this->db->commit();
return 1;
}
}
/**
2011-09-20 17:34:15 +00:00
* Clear all permissions array of user
*
* @return void
* @see loadRights(), hasRight()
*/
2019-02-25 19:35:59 +00:00
public function clearrights()
{
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::clearrights reset user->rights");
$this->rights = new stdClass();
$this->nb_rights = 0;
$this->all_permissions_are_loaded = 0;
$this->_tab_loaded = array();
}
2007-02-28 03:13:34 +00:00
/**
2024-02-26 18:08:00 +00:00
* Load permissions granted to a user->id into object user->rights
2011-09-04 18:41:19 +00:00
*
2018-07-02 07:34:34 +00:00
* @param string $moduletag Limit permission for a particular module ('' by default means load all permissions)
* @param int $forcereload Force reload of permissions even if they were already loaded (ignore cache)
2011-09-20 17:34:15 +00:00
* @return void
2021-08-24 12:47:50 +00:00
* @see clearrights(), delrights(), addrights(), hasRight()
2009-09-10 21:47:22 +00:00
*/
2024-04-28 19:36:33 +00:00
public function loadRights($moduletag = '', $forcereload = 0)
2007-02-28 03:13:34 +00:00
{
global $conf;
2024-03-13 14:34:29 +00:00
$alreadyloaded = false;
2020-10-28 23:34:41 +00:00
if (empty($forcereload)) {
if ($moduletag && isset($this->_tab_loaded[$moduletag]) && $this->_tab_loaded[$moduletag]) {
2018-07-02 07:34:34 +00:00
// Rights for this module are already loaded, so we leave
2024-03-13 14:34:29 +00:00
$alreadyloaded = true;
2018-07-02 07:34:34 +00:00
}
2007-02-28 03:13:34 +00:00
2020-10-28 23:34:41 +00:00
if (!empty($this->all_permissions_are_loaded)) {
2018-07-02 07:34:34 +00:00
// We already loaded all rights for this user, so we leave
2024-03-13 14:34:29 +00:00
$alreadyloaded = true;
2018-07-02 07:34:34 +00:00
}
2007-02-28 03:13:34 +00:00
}
2024-05-02 19:48:50 +00:00
// More init to avoid warnings/errors
if (!isset($this->rights) || !is_object($this->rights)) {
2024-05-02 19:48:50 +00:00
$this->rights = new stdClass();
}
if (!isset($this->rights->user) || !is_object($this->rights->user)) {
2024-05-02 19:48:50 +00:00
$this->rights->user = new stdClass();
}
2019-06-18 18:15:04 +00:00
// Get permission of users + Get permissions of groups
2024-03-13 14:34:29 +00:00
if (!$alreadyloaded) {
// First user permissions
$sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
$sql .= " FROM ".$this->db->prefix()."user_rights as ur,";
$sql .= " ".$this->db->prefix()."rights_def as r";
$sql .= " WHERE r.id = ur.fk_id";
if (getDolGlobalString('MULTICOMPANY_BACKWARD_COMPATIBILITY')) {
2024-08-02 09:17:14 +00:00
// On old version, we used entity defined into table r only
// @FIXME Test on MULTICOMPANY_BACKWARD_COMPATIBILITY is a very strange business rules because the select should be always the
// same than into user->loadRights() in user/perms.php and user/group/perms.php
// We should never use and remove this case.
$sql .= " AND r.entity IN (0,".(isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE') ? "1," : "").((int) $conf->entity).")";
2024-03-13 14:34:29 +00:00
} else {
2024-08-02 08:55:53 +00:00
// On table r=rights_def, the unique key is (id, entity) because id is hard coded into module descriptor and inserted during module activation.
2024-03-13 14:34:29 +00:00
// So we must include the filter on entity on both table r. and ur.
$sql .= " AND r.entity = ".((int) $conf->entity)." AND ur.entity = ".((int) $conf->entity);
}
2024-08-02 08:55:53 +00:00
$sql .= " AND ur.fk_user = ".((int) $this->id);
2024-03-13 14:34:29 +00:00
$sql .= " AND r.perms IS NOT NULL";
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
$sql .= " AND r.perms NOT LIKE '%_advance'"; // Hide advanced perms if option is not enabled
}
if ($moduletag) {
$sql .= " AND r.module = '".$this->db->escape($moduletag)."'";
}
2007-10-23 23:28:13 +00:00
2024-03-13 14:34:29 +00:00
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
if ($obj) {
$module = $obj->module;
$perms = $obj->perms;
$subperms = $obj->subperms;
if (!empty($perms)) {
if (!empty($module)) {
if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
$this->rights->$module = new stdClass();
2020-11-07 18:39:51 +00:00
}
2024-03-13 14:34:29 +00:00
if (!empty($subperms)) {
if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms)) {
$this->rights->$module->$perms = new stdClass();
}
2024-08-02 08:55:53 +00:00
if (empty($this->rights->$module->$perms->$subperms)) { // if not already counted
2024-03-13 14:34:29 +00:00
$this->nb_rights++;
}
$this->rights->$module->$perms->$subperms = 1;
} else {
2024-08-02 08:55:53 +00:00
if (empty($this->rights->$module->$perms)) { // if not already counted
2024-03-13 14:34:29 +00:00
$this->nb_rights++;
}
$this->rights->$module->$perms = 1;
2020-11-07 18:39:51 +00:00
}
2020-10-28 23:34:41 +00:00
}
}
2007-02-28 03:13:34 +00:00
}
2024-03-13 14:34:29 +00:00
$i++;
2007-02-28 03:13:34 +00:00
}
2024-03-13 14:34:29 +00:00
$this->db->free($resql);
2007-02-28 03:13:34 +00:00
}
2024-03-13 14:34:29 +00:00
// Now permissions of groups
2024-05-06 16:25:06 +00:00
$sql = "SELECT DISTINCT r.module, r.perms, r.subperms, r.entity";
2024-03-13 14:34:29 +00:00
$sql .= " FROM ".$this->db->prefix()."usergroup_rights as gr,";
$sql .= " ".$this->db->prefix()."usergroup_user as gu,";
$sql .= " ".$this->db->prefix()."rights_def as r";
$sql .= " WHERE r.id = gr.fk_id";
if (getDolGlobalString('MULTICOMPANY_BACKWARD_COMPATIBILITY')) {
2024-08-02 09:17:14 +00:00
// @FIXME Test on MULTICOMPANY_BACKWARD_COMPATIBILITY is a very strange business rules because the select should be always the
// same than into user->loadRights() in user/perms.php and user/group/perms.php
// We should never use and remove this case.
2024-03-13 14:34:29 +00:00
if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
$sql .= " AND gu.entity IN (0,".((int) $conf->entity).")";
2024-03-13 14:34:29 +00:00
} else {
$sql .= " AND r.entity = ".((int) $conf->entity);
}
} else {
2024-03-13 14:34:29 +00:00
$sql .= " AND gr.entity = ".((int) $conf->entity); // Only groups created in current entity
2024-05-06 16:25:06 +00:00
// The entity on the table gu=usergroup_user should be useless and should never be used because it is already into gr and r.
// but when using MULTICOMPANY_TRANSVERSE_MODE, we may have inserted record that make rubbish result here due to the duplicate record of
// other entities, so we are forced to add a filter on gu here
$sql .= " AND gu.entity IN (0,".((int) $conf->entity).")";
2024-03-13 14:34:29 +00:00
$sql .= " AND r.entity = ".((int) $conf->entity); // Only permission of modules enabled in current entity
}
// End of strange business rule
$sql .= " AND gr.fk_usergroup = gu.fk_usergroup";
$sql .= " AND gu.fk_user = ".((int) $this->id);
$sql .= " AND r.perms IS NOT NULL";
2024-08-02 08:55:53 +00:00
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
$sql .= " AND r.perms NOT LIKE '%_advance'"; // Hide advanced perms if option is not enabled
}
2024-03-13 14:34:29 +00:00
if ($moduletag) {
$sql .= " AND r.module = '".$this->db->escape($moduletag)."'";
}
2007-02-28 03:13:34 +00:00
2024-03-13 14:34:29 +00:00
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
if ($obj) {
$module = $obj->module;
$perms = $obj->perms;
$subperms = $obj->subperms;
if (!empty($perms)) {
if (!empty($module)) {
if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
$this->rights->$module = new stdClass();
2020-11-07 18:39:51 +00:00
}
2024-03-13 14:34:29 +00:00
if (!empty($subperms)) {
if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms)) {
$this->rights->$module->$perms = new stdClass();
}
2024-08-02 08:55:53 +00:00
if (empty($this->rights->$module->$perms->$subperms)) { // if not already counted
2024-03-13 14:34:29 +00:00
$this->nb_rights++;
}
$this->rights->$module->$perms->$subperms = 1;
} else {
// if we have already define a subperm like this $this->rights->$module->level1->level2 with llx_user_rights, we don't want override level1 because the level2 can be not define on user group
if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms)) {
2024-08-02 08:55:53 +00:00
if (empty($this->rights->$module->$perms)) { // if not already counted
$this->nb_rights++;
}
2024-03-13 14:34:29 +00:00
$this->rights->$module->$perms = 1;
}
2020-11-07 18:39:51 +00:00
}
}
2020-10-28 23:34:41 +00:00
}
2007-02-28 03:13:34 +00:00
}
2024-03-13 14:34:29 +00:00
$i++;
2007-02-28 03:13:34 +00:00
}
2024-03-13 14:34:29 +00:00
$this->db->free($resql);
2007-02-28 03:13:34 +00:00
}
2012-04-28 15:59:08 +00:00
2024-03-13 14:34:29 +00:00
// Force permission on user for admin
if (!empty($this->admin)) {
if (empty($this->rights->user->user)) {
$this->rights->user->user = new stdClass();
}
2024-03-13 14:34:29 +00:00
$listofpermtotest = array('lire', 'creer', 'password', 'supprimer', 'export');
foreach ($listofpermtotest as $permtotest) {
2024-03-13 14:34:29 +00:00
if (empty($this->rights->user->user->$permtotest)) {
$this->rights->user->user->$permtotest = 1;
$this->nb_rights++;
}
}
2024-03-13 14:34:29 +00:00
if (empty($this->rights->user->self)) {
$this->rights->user->self = new stdClass();
}
2024-03-13 14:34:29 +00:00
$listofpermtotest = array('creer', 'password');
foreach ($listofpermtotest as $permtotest) {
2024-03-13 14:34:29 +00:00
if (empty($this->rights->user->self->$permtotest)) {
$this->rights->user->self->$permtotest = 1;
$this->nb_rights++;
}
}
2024-03-13 14:34:29 +00:00
// Add test on advanced permissions
if (getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
if (empty($this->rights->user->user_advance)) {
$this->rights->user->user_advance = new stdClass();
}
$listofpermtotest = array('readperms', 'write');
foreach ($listofpermtotest as $permtotest) {
if (empty($this->rights->user->user_advance->$permtotest)) {
$this->rights->user->user_advance->$permtotest = 1;
$this->nb_rights++;
}
}
if (empty($this->rights->user->self_advance)) {
$this->rights->user->self_advance = new stdClass();
}
$listofpermtotest = array('readperms', 'writeperms');
foreach ($listofpermtotest as $permtotest) {
if (empty($this->rights->user->self_advance->$permtotest)) {
$this->rights->user->self_advance->$permtotest = 1;
$this->nb_rights++;
}
}
if (empty($this->rights->user->group_advance)) {
$this->rights->user->group_advance = new stdClass();
}
$listofpermtotest = array('read', 'readperms', 'write', 'delete');
foreach ($listofpermtotest as $permtotest) {
if (empty($this->rights->user) || empty($this->rights->user->group_advance->$permtotest)) {
$this->rights->user->group_advance->$permtotest = 1;
$this->nb_rights++;
}
}
}
}
2024-03-13 14:34:29 +00:00
// For backward compatibility
if (isset($this->rights->propale) && !isset($this->rights->propal)) {
$this->rights->propal = $this->rights->propale;
}
if (isset($this->rights->propal) && !isset($this->rights->propale)) {
$this->rights->propale = $this->rights->propal;
}
2007-02-28 03:13:34 +00:00
2024-03-13 14:34:29 +00:00
if (!$moduletag) {
// If the module was not define, then everything is loaded.
// Therefore, we can consider that the permissions are cached
// because they were all loaded for this user instance.
$this->all_permissions_are_loaded = 1;
} else {
// If the module is defined, we flag it as loaded into cache
$this->_tab_loaded[$moduletag] = 1;
}
2007-02-28 03:13:34 +00:00
}
}
2003-08-11 18:56:42 +00:00
2024-04-28 19:36:33 +00:00
/**
* Load permissions granted to a user->id into object user->rights
* TODO Remove this method. It has a name conflict with getRights() in CommonObject and was replaced in v20 with loadRights()
2024-04-28 19:36:33 +00:00
*
* @param string $moduletag Limit permission for a particular module ('' by default means load all permissions)
* @param int $forcereload Force reload of permissions even if they were already loaded (ignore cache)
* @return void
* @deprecated Use loadRights
2024-04-28 19:36:33 +00:00
*
* @see clearrights(), delrights(), addrights(), hasRight()
* @phpstan-ignore-next-line
*/
public function getrights($moduletag = '', $forcereload = 0)
{
$this->loadRights($moduletag, $forcereload);
}
/**
2011-09-20 17:34:15 +00:00
* Change status of a user
2011-09-04 18:41:19 +00:00
*
2019-11-02 10:36:48 +00:00
* @param int $status Status to set
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 if KO, 0 if nothing is done, >0 if OK
*/
2019-11-02 10:36:48 +00:00
public function setstatus($status)
{
global $conf, $langs, $user;
$error = 0;
// Check parameters
2023-01-03 10:32:33 +00:00
if (isset($this->statut)) {
if ($this->statut == $status) {
return 0;
}
} elseif (isset($this->status) && $this->status == $status) {
2020-10-28 23:34:41 +00:00
return 0;
}
$this->db->begin();
2019-11-02 10:36:48 +00:00
// Save in database
$sql = "UPDATE ".$this->db->prefix()."user";
2021-03-30 01:37:54 +00:00
$sql .= " SET statut = ".((int) $status);
$sql .= " WHERE rowid = ".((int) $this->id);
$result = $this->db->query($sql);
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::setstatus", LOG_DEBUG);
2020-10-28 23:34:41 +00:00
if ($result) {
if ($status == 0) {
$this->context['actionmsg'] = 'User '.$this->login.' disabled';
} else {
$this->context['actionmsg'] = 'User '.$this->login.' enabled';
}
// Call trigger
$result = $this->call_trigger('USER_ENABLEDISABLE', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
}
2020-10-28 23:34:41 +00:00
if ($error) {
$this->db->rollback();
return -$error;
2020-05-21 13:05:19 +00:00
} else {
2021-03-30 01:37:54 +00:00
$this->status = $status;
$this->statut = $status;
$this->db->commit();
return 1;
}
}
/**
* Set force password change flag
*
* @param User $user User making the change
* @param int $value 1 to force password change at next login, 0 to disable
* @return int Return integer <0 if KO, 0 if nothing is done, >0 if OK
*/
public function setForcePasswordChange($user, $value)
{
$error = 0;
$value = (int) $value;
// Check parameters : no change short line
if ($this->force_pass_change == $value) {
return 0;
}
$this->db->begin();
// Save in database
$sql = "UPDATE ".$this->db->prefix()."user";
$sql .= " SET force_pass_change = ".((int) $value);
$sql .= " WHERE rowid = ".((int) $this->id);
$result = $this->db->query($sql);
dol_syslog(get_class($this)."::setForcePasswordChange", LOG_DEBUG);
if ($result) {
$this->force_pass_change = $value;
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
if ($result < 0) {
$error++;
}
// End call triggers
} else {
$error++;
$this->error = $this->db->lasterror();
}
if ($error) {
$this->db->rollback();
return -$error;
} else {
$this->db->commit();
return 1;
}
}
2016-02-13 09:27:12 +00:00
/**
* Sets object to supplied categories.
*
* Deletes object from existing categories not supplied.
* Adds it to non existing supplied categories.
* Existing categories are left untouch.
*
2022-12-31 13:01:03 +00:00
* @param int[]|int $categories Category or categories IDs
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
2016-02-13 09:27:12 +00:00
*/
public function setCategories($categories)
{
2019-12-05 13:06:03 +00:00
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2020-12-23 22:32:50 +00:00
return parent::setCategoriesCommon($categories, Categorie::TYPE_USER);
2016-02-13 09:27:12 +00:00
}
/**
* Delete the user
2011-09-04 18:41:19 +00:00
*
* @param User $user User than delete
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2019-02-25 19:35:59 +00:00
public function delete(User $user)
{
$error = 0;
2012-01-07 14:01:30 +00:00
$this->db->begin();
$this->fetch($this->id);
2014-06-13 00:28:30 +00:00
dol_syslog(get_class($this)."::delete", LOG_DEBUG);
// Remove rights
$sql = "DELETE FROM ".$this->db->prefix()."user_rights WHERE fk_user = ".((int) $this->id);
2014-06-13 00:28:30 +00:00
2020-10-28 23:34:41 +00:00
if (!$error && !$this->db->query($sql)) {
$error++;
$this->error = $this->db->lasterror();
}
// Remove group
$sql = "DELETE FROM ".$this->db->prefix()."usergroup_user WHERE fk_user = ".((int) $this->id);
2020-10-28 23:34:41 +00:00
if (!$error && !$this->db->query($sql)) {
$error++;
$this->error = $this->db->lasterror();
}
2020-09-16 09:48:06 +00:00
// Remove params
$sql = "DELETE FROM ".$this->db->prefix()."user_param WHERE fk_user = ".((int) $this->id);
2020-10-28 23:34:41 +00:00
if (!$error && !$this->db->query($sql)) {
$error++;
$this->error = $this->db->lasterror();
}
// If contact, remove link
2020-10-28 23:34:41 +00:00
if ($this->contact_id > 0) {
$sql = "UPDATE ".$this->db->prefix()."socpeople SET fk_user_creat = null WHERE rowid = ".((int) $this->contact_id);
2020-10-28 23:34:41 +00:00
if (!$error && !$this->db->query($sql)) {
$error++;
$this->error = $this->db->lasterror();
}
}
2012-12-08 18:23:13 +00:00
// Remove extrafields
2020-10-28 23:34:41 +00:00
if (!$error) {
$result = $this->deleteExtraFields();
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
}
}
// Remove user
2020-10-28 23:34:41 +00:00
if (!$error) {
$sql = "DELETE FROM ".$this->db->prefix()."user WHERE rowid = ".((int) $this->id);
2020-10-28 23:34:41 +00:00
dol_syslog(get_class($this)."::delete", LOG_DEBUG);
if (!$this->db->query($sql)) {
$error++;
$this->error = $this->db->lasterror();
}
}
2020-10-28 23:34:41 +00:00
if (!$error) {
// Call trigger
$result = $this->call_trigger('USER_DELETE', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
$this->db->rollback();
return -1;
}
// End call triggers
2014-07-05 06:59:41 +00:00
$this->db->commit();
return 1;
2020-05-21 13:05:19 +00:00
} else {
$this->db->rollback();
return -1;
}
}
/**
* Create a user into database
2011-09-04 18:41:19 +00:00
*
* @param User $user Object user doing creation
2015-08-20 13:18:36 +00:00
* @param int $notrigger 1=do not execute triggers, 0 otherwise
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 if KO, id of created user if OK
*/
2019-02-25 19:35:59 +00:00
public function create($user, $notrigger = 0)
{
global $conf, $langs;
global $mysoc;
// Clean parameters
2020-10-28 19:57:36 +00:00
$this->setUpperOrLowerCase();
2019-12-12 16:29:11 +00:00
$this->civility_code = trim((string) $this->civility_code);
$this->login = trim((string) $this->login);
$this->user_creation_id = (int) $user->id;
2020-10-28 23:34:41 +00:00
if (!isset($this->entity)) {
$this->entity = $conf->entity; // If not defined, we use default value
}
dol_syslog(get_class($this)."::create login=".$this->login.", user=".(is_object($user) ? $user->id : ''), LOG_DEBUG);
$badCharUnauthorizedIntoLoginName = getDolGlobalLoginBadCharUnauthorized();
// Check parameters
if (getDolGlobalString('USER_MAIL_REQUIRED') && !isValidEmail($this->email)) {
$langs->load("errors");
$this->error = $langs->trans("ErrorBadEMail", $this->email);
return -1;
}
2020-10-28 19:57:36 +00:00
if (empty($this->login)) {
2015-08-20 13:18:36 +00:00
$langs->load("errors");
$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Login"));
2015-08-20 13:18:36 +00:00
return -1;
} elseif ($badCharUnauthorizedIntoLoginName !== '' && preg_match('/['.preg_quote($badCharUnauthorizedIntoLoginName, '/').']/', $this->login)) {
2021-07-20 22:35:08 +00:00
$langs->load("errors");
2022-11-30 16:37:29 +00:00
$this->error = $langs->trans("ErrorBadCharIntoLoginName", $langs->transnoentitiesnoconv("Login"));
2021-07-20 22:35:08 +00:00
return -1;
2015-08-20 13:18:36 +00:00
}
$this->datec = dol_now();
2010-05-05 17:27:12 +00:00
$error = 0;
$this->db->begin();
2021-06-13 17:05:48 +00:00
// Check if login already exists in same entity or into entity 0.
if ($this->login) {
2025-02-24 13:34:09 +00:00
$sqltochecklogin = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."user WHERE entity IN (".$this->db->sanitize(((int) $this->entity).", 0").") AND login = '".$this->db->escape($this->login)."'";
2021-06-13 17:05:48 +00:00
$resqltochecklogin = $this->db->query($sqltochecklogin);
if ($resqltochecklogin) {
$objtochecklogin = $this->db->fetch_object($resqltochecklogin);
if ($objtochecklogin && $objtochecklogin->nb > 0) {
$langs->load("errors");
$this->error = $langs->trans("ErrorLoginAlreadyExists", $this->login);
dol_syslog(get_class($this)."::create ".$this->error, LOG_DEBUG);
$this->db->rollback();
return -6;
}
$this->db->free($resqltochecklogin);
}
}
2022-02-07 13:25:20 +00:00
if (!empty($this->email)) {
2025-02-24 13:34:09 +00:00
$sqltochecklogin = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."user WHERE entity IN (".$this->db->sanitize(((int) $this->entity).", 0").") AND email = '".$this->db->escape($this->email)."'";
2021-06-13 17:05:48 +00:00
$resqltochecklogin = $this->db->query($sqltochecklogin);
if ($resqltochecklogin) {
$objtochecklogin = $this->db->fetch_object($resqltochecklogin);
if ($objtochecklogin && $objtochecklogin->nb > 0) {
$langs->load("errors");
$this->error = $langs->trans("ErrorEmailAlreadyExists", $this->email);
dol_syslog(get_class($this)."::create ".$this->error, LOG_DEBUG);
$this->db->rollback();
return -6;
}
$this->db->free($resqltochecklogin);
}
}
// Insert into database
$sql = "INSERT INTO ".$this->db->prefix()."user (datec, login, ldap_sid, fk_user_creat, entity)";
$sql .= " VALUES('".$this->db->idate($this->datec)."', '".$this->db->escape($this->login)."', '".$this->db->escape($this->ldap_sid)."', ".(int) $this->user_creation_id.", ".((int) $this->entity).")";
2021-06-13 17:05:48 +00:00
$result = $this->db->query($sql);
2017-03-13 14:00:44 +00:00
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::create", LOG_DEBUG);
2021-06-13 17:05:48 +00:00
if ($result) {
$this->id = $this->db->last_insert_id($this->db->prefix()."user");
2021-06-13 17:05:48 +00:00
// Set default rights
if ($this->set_default_rights() < 0) {
$this->error = 'ErrorFailedToSetDefaultRightOfUser';
2007-12-19 10:24:18 +00:00
$this->db->rollback();
2021-06-13 17:05:48 +00:00
return -5;
}
2020-05-28 17:10:06 +00:00
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && getDolGlobalString('STOCK_USERSTOCK_AUTOCREATE')) {
2021-06-13 17:05:48 +00:00
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
$langs->load("stocks");
2023-08-05 23:14:36 +00:00
2021-06-13 17:05:48 +00:00
$entrepot = new Entrepot($this->db);
$entrepot->label = $langs->trans("PersonalStock", $this->getFullName($langs));
$entrepot->libelle = $entrepot->label; // For backward compatibility
$entrepot->description = $langs->trans("ThisWarehouseIsPersonalStock", $this->getFullName($langs));
$entrepot->statut = 1;
$entrepot->country_id = $mysoc->country_id;
2023-08-05 23:14:36 +00:00
2021-06-13 17:05:48 +00:00
$warehouseid = $entrepot->create($user);
$this->fk_warehouse = $warehouseid;
}
2017-03-13 14:00:44 +00:00
2021-06-13 17:05:48 +00:00
// Update minor fields
$result = $this->update($user, 1, 1);
if ($result < 0) {
$this->db->rollback();
return -4;
}
2021-06-13 17:05:48 +00:00
if (!$notrigger) {
// Call trigger
$result = $this->call_trigger('USER_CREATE', $user);
if ($result < 0) {
$error++;
2006-12-05 22:55:50 +00:00
}
2021-06-13 17:05:48 +00:00
// End call triggers
}
if (!$error) {
$this->db->commit();
return $this->id;
} else {
//$this->error=$interface->error;
dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
$this->db->rollback();
return -3;
2006-12-05 22:55:50 +00:00
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
2006-12-05 22:55:50 +00:00
$this->db->rollback();
2021-06-13 17:05:48 +00:00
return -2;
2006-12-05 22:55:50 +00:00
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2011-09-20 17:34:15 +00:00
* Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
2011-09-04 18:41:19 +00:00
*
2011-09-20 17:34:15 +00:00
* @param Contact $contact Object for source contact
* @param string $login Login to force
* @param string $password Password to force
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 if error, if OK returns id of created user
*/
2019-02-25 19:35:59 +00:00
public function create_from_contact($contact, $login = '', $password = '')
{
// phpcs:enable
2025-09-18 14:26:38 +00:00
global $user;
$error = 0;
2012-01-07 14:01:30 +00:00
// Define parameters
2019-02-25 19:35:59 +00:00
$this->admin = 0;
$this->civility_code = $contact->civility_code;
2019-02-25 19:35:59 +00:00
$this->lastname = $contact->lastname;
$this->firstname = $contact->firstname;
2024-03-26 13:40:42 +00:00
//$this->gender = $contact->gender; // contact has no gender
2019-02-25 19:35:59 +00:00
$this->email = $contact->email;
2019-10-01 17:59:49 +00:00
$this->socialnetworks = $contact->socialnetworks;
2019-02-25 19:35:59 +00:00
$this->office_phone = $contact->phone_pro;
$this->office_fax = $contact->fax;
$this->user_mobile = $contact->phone_mobile;
$this->address = $contact->address;
$this->zip = $contact->zip;
$this->town = $contact->town;
2021-02-17 14:26:56 +00:00
$this->setUpperOrLowerCase();
2019-02-25 19:35:59 +00:00
$this->state_id = $contact->state_id;
$this->country_id = $contact->country_id;
$this->employee = 0;
2017-03-13 14:00:44 +00:00
if (empty($login)) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
$login = dol_buildlogin($contact->lastname, $contact->firstname);
}
$this->login = $login;
$this->db->begin();
2019-10-07 12:16:47 +00:00
// Create user and set $this->id. Trigger is disabled because executed later.
$result = $this->create($user, 1);
2020-10-28 23:34:41 +00:00
if ($result > 0) {
$sql = "UPDATE ".$this->db->prefix()."user";
2021-06-09 13:36:47 +00:00
$sql .= " SET fk_socpeople=".((int) $contact->id);
2021-01-19 08:24:15 +00:00
$sql .= ", civility='".$this->db->escape($contact->civility_code)."'";
2021-01-19 09:56:46 +00:00
if ($contact->socid > 0) {
2021-06-09 13:36:47 +00:00
$sql .= ", fk_soc=".((int) $contact->socid);
2020-10-28 23:34:41 +00:00
}
2021-01-19 09:56:46 +00:00
$sql .= " WHERE rowid=".((int) $this->id);
2021-01-18 16:06:06 +00:00
$resql = $this->db->query($sql);
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::create_from_contact", LOG_DEBUG);
2020-10-28 23:34:41 +00:00
if ($resql) {
$this->context['createfromcontact'] = 'createfromcontact';
// Call trigger
$result = $this->call_trigger('USER_CREATE', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
2023-12-04 12:53:48 +00:00
$error++;
$this->db->rollback();
return -1;
2020-10-28 23:34:41 +00:00
}
// End call triggers
2014-07-05 06:59:41 +00:00
$this->db->commit();
return $this->id;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->error();
$this->db->rollback();
return -1;
}
2020-05-21 13:05:19 +00:00
} else {
// $this->error already set
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::create_from_contact - 0");
$this->db->rollback();
return $result;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Create a user into database from a member object.
* If $member->fk_soc is set, it will be an external user.
2011-09-04 18:41:19 +00:00
*
* @param Adherent $member Object member source
* @param string $login Login to force
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 if KO, if OK, return id of created account
*/
2019-02-25 19:35:59 +00:00
public function create_from_member($member, $login = '')
{
// phpcs:enable
2024-04-22 16:42:34 +00:00
global $user;
2020-01-28 20:23:05 +00:00
// Set properties on new user
$this->admin = 0;
2024-04-22 16:42:34 +00:00
$this->civility_code = $member->civility_code;
$this->lastname = $member->lastname;
$this->firstname = $member->firstname;
2021-02-17 15:39:03 +00:00
$this->gender = $member->gender;
$this->email = $member->email;
$this->fk_member = $member->id;
$this->address = $member->address;
$this->zip = $member->zip;
$this->town = $member->town;
2021-02-17 14:26:56 +00:00
$this->setUpperOrLowerCase();
$this->state_id = $member->state_id;
$this->country_id = $member->country_id;
2020-01-28 20:23:05 +00:00
$this->socialnetworks = $member->socialnetworks;
2020-01-28 20:23:05 +00:00
$this->pass = $member->pass;
$this->pass_crypted = $member->pass_indatabase_crypted;
if (empty($login)) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
$login = dol_buildlogin($member->lastname, $member->firstname);
}
$this->login = $login;
$this->db->begin();
// Create and set $this->id
$result = $this->create($user);
2020-10-28 23:34:41 +00:00
if ($result > 0) {
if (!empty($this->pass)) { // If a clear password was received (this situation should not happen anymore now), we use it to save it into database
2020-01-28 20:23:05 +00:00
$newpass = $this->setPassword($user, $this->pass);
if (is_int($newpass) && $newpass < 0) {
2020-10-28 23:34:41 +00:00
$result = -2;
}
} elseif (!empty($this->pass_crypted)) { // If an encrypted password is already known, we save it directly into database because the previous create did not save it.
$sql = "UPDATE ".$this->db->prefix()."user";
2020-01-28 20:23:05 +00:00
$sql .= " SET pass_crypted = '".$this->db->escape($this->pass_crypted)."'";
2021-03-14 11:20:23 +00:00
$sql .= " WHERE rowid=".((int) $this->id);
2020-01-28 20:23:05 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if (!$resql) {
2020-01-28 20:23:05 +00:00
$result = -1;
}
}
if ($result > 0 && $member->socid) { // If member is linked to a thirdparty
$sql = "UPDATE ".$this->db->prefix()."user";
$sql .= " SET fk_soc=".((int) $member->socid);
2021-03-14 11:20:23 +00:00
$sql .= " WHERE rowid=".((int) $this->id);
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$this->db->commit();
return $this->id;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
}
2020-10-28 23:34:41 +00:00
if ($result > 0) {
$this->db->commit();
return $this->id;
2020-05-21 13:05:19 +00:00
} else {
// $this->error was already set
$this->db->rollback();
return -2;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Assign rights by default
2011-09-04 18:41:19 +00:00
*
* @return integer erreur <0, si ok renvoi le nbre de droits par default positions
*/
2019-02-25 19:35:59 +00:00
public function set_default_rights()
{
// phpcs:enable
global $conf;
$rd = array();
$num = 0;
$sql = "SELECT id FROM ".$this->db->prefix()."rights_def";
$sql .= " WHERE bydefault = 1";
2021-08-23 17:33:24 +00:00
$sql .= " AND entity = ".((int) $conf->entity);
$resql = $this->db->query($sql);
if ($resql) {
2010-08-14 02:44:07 +00:00
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
2010-08-14 02:44:07 +00:00
$row = $this->db->fetch_row($resql);
$rd[$i] = $row[0];
$i++;
}
2010-08-14 02:44:07 +00:00
$this->db->free($resql);
}
$i = 0;
while ($i < $num) {
$sql = "DELETE FROM ".$this->db->prefix()."user_rights WHERE fk_user = ".((int) $this->id)." AND fk_id=".((int) $rd[$i]);
$result = $this->db->query($sql);
$sql = "INSERT INTO ".$this->db->prefix()."user_rights (fk_user, fk_id) VALUES (".((int) $this->id).", ".((int) $rd[$i]).")";
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if (!$result) {
return -1;
}
$i++;
}
return $i;
}
/**
* Update a user into database (and also password if this->pass is defined)
2011-09-04 18:41:19 +00:00
*
2021-06-13 17:05:48 +00:00
* @param User $user User making update
* @param int $notrigger 1=do not execute triggers, 0 by default
2011-09-20 17:34:15 +00:00
* @param int $nosyncmember 0=Synchronize linked member (standard info), 1=Do not synchronize linked member
* @param int $nosyncmemberpass 0=Synchronize linked member (password), 1=Do not synchronize linked member
2017-12-19 15:16:31 +00:00
* @param int $nosynccontact 0=Synchronize linked contact, 1=Do not synchronize linked contact
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 if KO, >=0 if OK
*/
2019-02-25 19:35:59 +00:00
public function update($user, $notrigger = 0, $nosyncmember = 0, $nosyncmemberpass = 0, $nosynccontact = 0)
{
2025-09-18 14:26:38 +00:00
global $langs;
if (empty($this->country_id) && !empty($this->country_code)) {
$country_id = getCountry($this->country_code, '3');
$this->country_id = is_int($country_id) ? $country_id : 0;
}
$nbrowsaffected = 0;
$error = 0;
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncmember=".$nosyncmember.", nosyncmemberpass=".$nosyncmemberpass);
// Clean parameters
$this->civility_code = trim((string) $this->civility_code);
$this->lastname = trim((string) $this->lastname);
$this->firstname = trim((string) $this->firstname);
$this->ref_employee = trim((string) $this->ref_employee);
$this->national_registration_number = trim((string) $this->national_registration_number);
$this->employee = ($this->employee > 0 ? $this->employee : 0);
$this->login = trim((string) $this->login);
$this->gender = trim((string) $this->gender);
2023-01-27 13:06:31 +00:00
$this->pass = trim((string) $this->pass);
$this->api_key = trim((string) $this->api_key);
2023-01-27 13:06:31 +00:00
$this->datestartvalidity = empty($this->datestartvalidity) ? '' : $this->datestartvalidity;
$this->dateendvalidity = empty($this->dateendvalidity) ? '' : $this->dateendvalidity;
$this->address = trim((string) $this->address);
$this->zip = trim((string) $this->zip);
$this->town = trim((string) $this->town);
$this->state_id = ($this->state_id > 0 ? $this->state_id : 0);
$this->country_id = ($this->country_id > 0 ? $this->country_id : 0);
$this->office_phone = trim((string) $this->office_phone);
$this->office_fax = trim((string) $this->office_fax);
$this->user_mobile = trim((string) $this->user_mobile);
$this->personal_mobile = trim((string) $this->personal_mobile);
$this->email = trim((string) $this->email);
$this->personal_email = trim((string) $this->personal_email);
$this->job = trim((string) $this->job);
$this->signature = trim((string) $this->signature);
$this->note_public = trim((string) $this->note_public);
$this->note_private = trim((string) $this->note_private);
$this->openid = trim((string) $this->openid);
$this->admin = ($this->admin > 0 ? $this->admin : 0);
$this->user_modification_id = $user->id;
$this->accountancy_code_user_general = trim((string) $this->accountancy_code_user_general);
$this->accountancy_code = trim((string) $this->accountancy_code);
2025-11-09 01:40:40 +00:00
$this->color = trim(str_replace('#', '', (string) $this->color));
$this->dateemployment = empty($this->dateemployment) ? '' : $this->dateemployment;
$this->dateemploymentend = empty($this->dateemploymentend) ? '' : $this->dateemploymentend;
2023-01-27 13:06:31 +00:00
$this->birth = empty($this->birth) ? '' : $this->birth;
$this->fk_warehouse = (int) $this->fk_warehouse;
2024-03-29 13:04:02 +00:00
$this->fk_establishment = (int) $this->fk_establishment;
2022-07-28 13:13:13 +00:00
$this->setUpperOrLowerCase();
// Check parameters
$badCharUnauthorizedIntoLoginName = getDolGlobalLoginBadCharUnauthorized();
if (getDolGlobalString('USER_MAIL_REQUIRED') && !isValidEmail($this->email)) {
$langs->load("errors");
$this->error = $langs->trans("ErrorBadEMail", $this->email);
return -1;
}
2020-10-28 23:34:41 +00:00
if (empty($this->login)) {
2015-08-20 13:18:36 +00:00
$langs->load("errors");
2020-09-21 14:31:51 +00:00
$this->error = $langs->trans("ErrorFieldRequired", 'Login');
2015-08-20 13:18:36 +00:00
return -1;
} elseif ($badCharUnauthorizedIntoLoginName !== '' && preg_match('/['.preg_quote($badCharUnauthorizedIntoLoginName, '/').']/', $this->login)) {
2021-07-20 22:35:08 +00:00
$langs->load("errors");
2022-11-30 16:37:29 +00:00
$this->error = $langs->trans("ErrorBadCharIntoLoginName", $langs->transnoentitiesnoconv("Login"));
2021-07-20 22:35:08 +00:00
return -1;
2015-08-20 13:18:36 +00:00
}
2016-03-17 08:22:12 +00:00
$this->db->begin();
// Check if login already exists in same entity or into entity 0.
if (is_object($this->oldcopy) && !$this->oldcopy->isEmpty() && $this->oldcopy->login != $this->login) {
2025-02-24 13:32:05 +00:00
$sqltochecklogin = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."user WHERE entity IN (".$this->db->sanitize(((int) $this->entity).", 0").") AND login = '".$this->db->escape($this->login)."'";
$resqltochecklogin = $this->db->query($sqltochecklogin);
if ($resqltochecklogin) {
$objtochecklogin = $this->db->fetch_object($resqltochecklogin);
if ($objtochecklogin && $objtochecklogin->nb > 0) {
$langs->load("errors");
$this->error = $langs->trans("ErrorLoginAlreadyExists", $this->login);
2021-06-13 17:05:48 +00:00
dol_syslog(get_class($this)."::create ".$this->error, LOG_DEBUG);
$this->db->rollback();
return -1;
}
}
}
if (is_object($this->oldcopy) && !$this->oldcopy->isEmpty() && !empty($this->email) && $this->oldcopy->email != $this->email) {
2025-02-24 13:32:05 +00:00
$sqltochecklogin = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."user WHERE entity IN (".$this->db->sanitize(((int) $this->entity).", 0").") AND email = '".$this->db->escape($this->email)."'";
$resqltochecklogin = $this->db->query($sqltochecklogin);
if ($resqltochecklogin) {
$objtochecklogin = $this->db->fetch_object($resqltochecklogin);
if ($objtochecklogin && $objtochecklogin->nb > 0) {
$langs->load("errors");
$this->error = $langs->trans("ErrorEmailAlreadyExists", $this->email);
2021-06-13 17:05:48 +00:00
dol_syslog(get_class($this)."::create ".$this->error, LOG_DEBUG);
$this->db->rollback();
return -1;
}
}
}
// Update data
$sql = "UPDATE ".$this->db->prefix()."user SET";
$sql .= " civility = '".$this->db->escape($this->civility_code)."'";
$sql .= ", lastname = '".$this->db->escape($this->lastname)."'";
$sql .= ", firstname = '".$this->db->escape($this->firstname)."'";
$sql .= ", ref_employee = '".$this->db->escape($this->ref_employee)."'";
$sql .= ", national_registration_number = '".$this->db->escape($this->national_registration_number)."'";
$sql .= ", employee = ".(int) $this->employee;
$sql .= ", login = '".$this->db->escape($this->login)."'";
2023-03-13 11:48:25 +00:00
$sql .= ", api_key = ".($this->api_key ? "'".$this->db->escape(dolEncrypt($this->api_key, '', '', 'dolibarr'))."'" : "null");
2024-03-26 13:40:42 +00:00
$sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman' or 'other'
2022-04-06 12:09:44 +00:00
$sql .= ", birth=".(strval($this->birth) != '' ? "'".$this->db->idate($this->birth, 'tzserver')."'" : 'null');
2020-10-28 23:34:41 +00:00
if (!empty($user->admin)) {
$sql .= ", admin = ".(int) $this->admin; // admin flag can be set/unset only by an admin user
}
$sql .= ", address = '".$this->db->escape($this->address)."'";
$sql .= ", zip = '".$this->db->escape($this->zip)."'";
$sql .= ", town = '".$this->db->escape($this->town)."'";
$sql .= ", fk_state = ".((!empty($this->state_id) && $this->state_id > 0) ? ((int) $this->state_id) : "null");
$sql .= ", fk_country = ".((!empty($this->country_id) && $this->country_id > 0) ? ((int) $this->country_id) : "null");
$sql .= ", office_phone = '".$this->db->escape($this->office_phone)."'";
$sql .= ", office_fax = '".$this->db->escape($this->office_fax)."'";
$sql .= ", user_mobile = '".$this->db->escape($this->user_mobile)."'";
$sql .= ", personal_mobile = '".$this->db->escape($this->personal_mobile)."'";
$sql .= ", email = '".$this->db->escape($this->email)."'";
$sql .= ", personal_email = '".$this->db->escape($this->personal_email)."'";
$sql .= ", socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'";
$sql .= ", job = '".$this->db->escape($this->job)."'";
$sql .= ", signature = '".$this->db->escape($this->signature)."'";
$sql .= ", accountancy_code_user_general = '".$this->db->escape($this->accountancy_code_user_general)."'";
$sql .= ", accountancy_code = '".$this->db->escape($this->accountancy_code)."'";
$sql .= ", color = '".$this->db->escape($this->color)."'";
$sql .= ", dateemployment=".(strval($this->dateemployment) != '' ? "'".$this->db->idate($this->dateemployment)."'" : 'null');
$sql .= ", dateemploymentend=".(strval($this->dateemploymentend) != '' ? "'".$this->db->idate($this->dateemploymentend)."'" : 'null');
$sql .= ", datestartvalidity=".(strval($this->datestartvalidity) != '' ? "'".$this->db->idate($this->datestartvalidity)."'" : 'null');
$sql .= ", dateendvalidity=".(strval($this->dateendvalidity) != '' ? "'".$this->db->idate($this->dateendvalidity)."'" : 'null');
2022-09-03 09:07:47 +00:00
$sql .= ", note_private = '".$this->db->escape($this->note_private)."'";
$sql .= ", note_public = '".$this->db->escape($this->note_public)."'";
$sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
$sql .= ", openid = ".($this->openid ? "'".$this->db->escape($this->openid)."'" : "null");
$sql .= ", fk_user = ".($this->fk_user > 0 ? ((int) $this->fk_user) : "null");
$sql .= ", fk_user_modif = ".($this->user_modification_id > 0 ? ((int) $this->user_modification_id) : "null");
$sql .= ", fk_user_expense_validator = ".($this->fk_user_expense_validator > 0 ? ((int) $this->fk_user_expense_validator) : "null");
$sql .= ", fk_user_holiday_validator = ".($this->fk_user_holiday_validator > 0 ? ((int) $this->fk_user_holiday_validator) : "null");
2020-10-28 23:34:41 +00:00
if (isset($this->thm) || $this->thm != '') {
$sql .= ", thm= ".($this->thm != '' ? "'".$this->db->escape($this->thm)."'" : "null");
}
if (isset($this->tjm) || $this->tjm != '') {
$sql .= ", tjm= ".($this->tjm != '' ? "'".$this->db->escape($this->tjm)."'" : "null");
}
if (isset($this->salary) || $this->salary != '') {
$sql .= ", salary= ".($this->salary != '' ? "'".$this->db->escape($this->salary)."'" : "null");
}
if (isset($this->salaryextra) || $this->salaryextra != '') {
$sql .= ", salaryextra= ".($this->salaryextra != '' ? "'".$this->db->escape($this->salaryextra)."'" : "null");
}
$sql .= ", weeklyhours= ".($this->weeklyhours != '' ? "'".$this->db->escape($this->weeklyhours)."'" : "null");
if (!empty($user->admin) && empty($user->entity) && $user->id != $this->id) {
$sql .= ", entity = ".((int) $this->entity); // entity flag can be set/unset only by an another superadmin user
}
$sql .= ", default_range = ".($this->default_range > 0 ? ((int) $this->default_range) : 'null');
$sql .= ", default_c_exp_tax_cat = ".($this->default_c_exp_tax_cat > 0 ? ((int) $this->default_c_exp_tax_cat) : 'null');
$sql .= ", fk_warehouse = ".($this->fk_warehouse > 0 ? ((int) $this->fk_warehouse) : "null");
$sql .= ", fk_establishment = ".($this->fk_establishment > 0 ? ((int) $this->fk_establishment) : "null");
2020-08-07 12:22:43 +00:00
$sql .= ", lang = ".($this->lang ? "'".$this->db->escape($this->lang)."'" : "null");
$sql .= ", force_pass_change = ".($this->force_pass_change ? ((int) $this->force_pass_change) : "0");
2021-08-23 17:33:24 +00:00
$sql .= " WHERE rowid = ".((int) $this->id);
2017-03-13 14:00:44 +00:00
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::update", LOG_DEBUG);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$nbrowsaffected += $this->db->affected_rows($resql);
// Update password
2020-10-28 23:34:41 +00:00
if (!empty($this->pass)) {
2023-01-16 09:57:31 +00:00
if ($this->pass != $this->pass_indatabase && !dol_verifyHash($this->pass, $this->pass_indatabase_crypted)) {
// If a new value for password is set and different than the one encrypted into database
2023-01-16 09:57:31 +00:00
$result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass, 0, 1);
if (is_int($result) && $result < 0) {
2022-01-21 14:26:54 +00:00
return -5;
2020-10-28 23:34:41 +00:00
}
}
}
// If user is linked to a member, remove old link to this member
2020-10-28 23:34:41 +00:00
if ($this->fk_member > 0) {
dol_syslog(get_class($this)."::update remove link with member. We will recreate it later", LOG_DEBUG);
$sql = "UPDATE ".$this->db->prefix()."user SET fk_member = NULL where fk_member = ".((int) $this->fk_member);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if (!$resql) {
2023-12-04 12:53:48 +00:00
$this->error = $this->db->error();
$this->db->rollback();
return -5;
2020-10-28 23:34:41 +00:00
}
}
// Set link to user
dol_syslog(get_class($this)."::update set link with member", LOG_DEBUG);
$sql = "UPDATE ".$this->db->prefix()."user SET fk_member =".($this->fk_member > 0 ? ((int) $this->fk_member) : 'null')." where rowid = ".((int) $this->id);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if (!$resql) {
2023-12-04 12:53:48 +00:00
$this->error = $this->db->error();
$this->db->rollback();
return -5;
2020-10-28 23:34:41 +00:00
}
2020-10-28 23:34:41 +00:00
if ($nbrowsaffected) { // If something has changed in data
if ($this->fk_member > 0 && !$nosyncmember) {
dol_syslog(get_class($this)."::update user is linked with a member. We try to update member too.", LOG_DEBUG);
2017-03-13 14:00:44 +00:00
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
2017-12-19 15:16:31 +00:00
// This user is linked with a member, so we also update member information
// if this is an update.
$adh = new Adherent($this->db);
$result = $adh->fetch($this->fk_member);
2020-10-28 23:34:41 +00:00
if ($result > 0) {
$adh->civility_code = $this->civility_code;
$adh->firstname = $this->firstname;
$adh->lastname = $this->lastname;
$adh->login = $this->login;
$adh->gender = $this->gender;
$adh->birth = $this->birth;
2017-03-13 14:00:44 +00:00
$adh->pass = $this->pass;
2017-03-13 14:00:44 +00:00
$adh->address = $this->address;
$adh->town = $this->town;
$adh->zip = $this->zip;
$adh->state_id = $this->state_id;
$adh->country_id = $this->country_id;
2018-08-31 20:34:02 +00:00
$adh->email = $this->email;
2018-10-12 09:29:47 +00:00
$adh->socialnetworks = $this->socialnetworks;
2018-10-12 09:29:47 +00:00
$adh->phone = $this->office_phone;
$adh->phone_mobile = $this->user_mobile;
2022-08-07 08:14:05 +00:00
$adh->default_lang = $this->lang;
$adh->user_id = $this->id;
$adh->user_login = $this->login;
$result = $adh->update($user, 0, 1, 0);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$this->error = $adh->error;
$this->errors = $adh->errors;
dol_syslog(get_class($this)."::update error after calling adh->update to sync it with user: ".$this->error, LOG_ERR);
$error++;
}
2020-10-28 23:34:41 +00:00
} elseif ($result < 0) {
$this->error = $adh->error;
$this->errors = $adh->errors;
$error++;
}
}
2017-12-19 15:16:31 +00:00
2020-10-28 23:34:41 +00:00
if ($this->contact_id > 0 && !$nosynccontact) {
2017-12-19 15:16:31 +00:00
dol_syslog(get_class($this)."::update user is linked with a contact. We try to update contact too.", LOG_DEBUG);
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
// This user is linked with a contact, so we also update contact information if this is an update.
$tmpobj = new Contact($this->db);
$result = $tmpobj->fetch($this->contact_id);
2017-12-19 15:16:31 +00:00
2020-10-28 23:34:41 +00:00
if ($result >= 0) {
$tmpobj->civility_code = $this->civility_code;
$tmpobj->firstname = $this->firstname;
$tmpobj->lastname = $this->lastname;
$tmpobj->login = $this->login;
$tmpobj->gender = $this->gender;
$tmpobj->birth = $this->birth;
2017-12-19 15:16:31 +00:00
//$tmpobj->pass=$this->pass;
$tmpobj->email = $this->email;
2018-10-12 09:29:47 +00:00
$tmpobj->socialnetworks = $this->socialnetworks;
2018-10-12 09:29:47 +00:00
$tmpobj->phone_pro = $this->office_phone;
$tmpobj->phone_mobile = $this->user_mobile;
$tmpobj->fax = $this->office_fax;
2017-12-19 15:16:31 +00:00
2022-08-07 08:14:05 +00:00
$tmpobj->default_lang = $this->lang;
$tmpobj->address = $this->address;
$tmpobj->town = $this->town;
$tmpobj->zip = $this->zip;
$tmpobj->state_id = $this->state_id;
$tmpobj->country_id = $this->country_id;
2017-12-19 15:16:31 +00:00
$tmpobj->user_id = $this->id;
$tmpobj->user_login = $this->login;
2017-12-19 15:16:31 +00:00
$result = $tmpobj->update($tmpobj->id, $user, 0, 'update', 1);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$this->error = $tmpobj->error;
$this->errors = $tmpobj->errors;
2017-12-19 15:16:31 +00:00
dol_syslog(get_class($this)."::update error after calling adh->update to sync it with user: ".$this->error, LOG_ERR);
$error++;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $tmpobj->error;
$this->errors = $tmpobj->errors;
2017-12-19 15:16:31 +00:00
$error++;
}
}
2011-09-03 16:44:34 +00:00
}
2011-09-04 18:41:19 +00:00
$action = 'update';
// Actions on extra fields
2020-10-28 23:34:41 +00:00
if (!$error) {
$result = $this->insertExtraFields();
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
2012-12-02 10:03:23 +00:00
}
}
2020-10-28 23:34:41 +00:00
if (!$error && !$notrigger) {
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
}
2020-10-28 23:34:41 +00:00
if (!$error) {
$this->db->commit();
2011-09-03 16:37:12 +00:00
return $nbrowsaffected;
2020-05-21 13:05:19 +00:00
} else {
dol_syslog(get_class($this)."::update error=".$this->error, LOG_ERR);
$this->db->rollback();
2011-09-03 16:37:12 +00:00
return -1;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
2011-09-03 16:37:12 +00:00
$this->db->rollback();
return -2;
}
2008-02-24 17:01:48 +00:00
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Update the user's last login date in the database.
* Function called when a new connection is made by the user
2011-09-04 18:41:19 +00:00
*
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 si echec, >=0 si ok
*/
2019-02-25 19:35:59 +00:00
public function update_last_login_date()
{
// phpcs:enable
$now = dol_now();
$userremoteip = getUserRemoteIP();
$sql = "UPDATE ".$this->db->prefix()."user SET";
$sql .= " datepreviouslogin = datelastlogin,";
$sql .= " ippreviouslogin = iplastlogin,";
$sql .= " datelastlogin = '".$this->db->idate($now)."',";
$sql .= " iplastlogin = '".$this->db->escape($userremoteip)."',";
$sql .= " tms = tms"; // The last update date must change because the last login date is updated
2021-08-23 17:33:24 +00:00
$sql .= " WHERE rowid = ".((int) $this->id);
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::update_last_login_date user->id=".$this->id." ".$sql, LOG_DEBUG);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$this->datepreviouslogin = $this->datelastlogin;
$this->datelastlogin = $now;
$this->ippreviouslogin = $this->iplastlogin;
$this->iplastlogin = $userremoteip;
return 1;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror().' sql='.$sql;
return -1;
}
}
/**
* Change password of a user
2011-09-04 18:41:19 +00:00
*
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
* @param User $user Object user of user requesting the change (not the user for who we change the password). May be unknown.
* @param string $password New password, in clear text or already encrypted (to generate if not provided)
* @param int<0,1> $changelater 0=Default, 1=Save password into pass_temp to change password only after clicking on confirm email
* @param int<0,1> $notrigger 1=Does not launch triggers
* @param int<0,1> $nosyncmember Do not synchronize linked member
* @param int<0,1> $passwordalreadycrypted 0=Value is cleartext password, 1=Value is encrypted value.
* @param int $flagdelsessionsbefore 1=Save also the current date to ask to invalidate all other session before this date.
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
* @return int<-3,0>|string If OK return clear password, 0 if no change (warning, you may retrieve 1 instead of 0 even if password was same), < 0 if error
*/
public function setPassword($user, $password = '', $changelater = 0, $notrigger = 0, $nosyncmember = 0, $passwordalreadycrypted = 0, $flagdelsessionsbefore = 1)
{
global $conf, $langs;
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
2011-09-20 17:19:46 +00:00
$error = 0;
dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i', '*', $password)." changelater=".$changelater." notrigger=".$notrigger." nosyncmember=".$nosyncmember, LOG_DEBUG);
2011-09-23 23:46:14 +00:00
// If new password not provided, we generate one
2020-10-28 23:34:41 +00:00
if (!$password) {
$password = getRandomPassword(false);
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
$passwordalreadycrypted = 0; // Just generated, so not crypted
}
2022-01-03 11:26:57 +00:00
// Check and encrypt the password
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
if (!empty($passwordalreadycrypted)) {
$password_crypted = $password; // Reuse crypted password
} else {
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('USER_PASSWORD_GENERATED')) {
2022-01-03 11:26:57 +00:00
// Add a check on rules for password syntax using the setup of the password generator
NEW: #0 Resolve password generator/validator classes via modules_parts['models'] (#39486) Password generator/validator classes (USER_PASSWORD_GENERATED, modGeneratePassXxx extends ModeleGenPassword) could previously only live under htdocs/core/modules/security/generate/ — every call site resolving one by name hardcoded that path, so no third-party module could contribute its own generator without patching core. Reuse the modules_parts['models'] extension point already populated for any enabled module declaring $this->module_parts['models'] = 1 (the same mechanism every numbering-module scan in Dolibarr already uses — see e.g. Facture::getNextNumRef()), and wire it into the password-generator scan too: - admin/security.php's generator listing now scans core plus every enabled module declaring module_parts['models'], instead of only core/modules/security/generate/. - Added ModeleGenPassword::loadAndInstantiate($id, ...) in modules_genpassword.php, a shared factory doing that same multi-root resolution once, used by the four runtime call sites that previously hardcoded the core-only path: User::setPassword(), getRandomPassword() (security2.lib.php), FormSetupItem::generateInputFieldPassword() (html.formsetup.class.php), and PasswordField::verifyFieldValue() (passwordfield.class.php). getRandomPassword() falls back to the 'standard' generator (with a warning logged) if the configured generator's class can't be resolved, rather than silently generating and persisting an empty password. Behavior for the built-in Standard/None/Perso generators is unchanged — core is always the first root scanned, so it always wins for those ids.
2026-08-14 14:19:48 +00:00
require_once DOL_DOCUMENT_ROOT.'/core/modules/security/generate/modules_genpassword.php';
$modGeneratePass = ModeleGenPassword::loadAndInstantiate(getDolGlobalString('USER_PASSWORD_GENERATED'), $this->db, $conf, $langs, $user);
if ($modGeneratePass) {
'@phan-var-force ModeleGenPassword $modGeneratePass';
2022-01-03 11:26:57 +00:00
// To check an input user password, we disable the cleaning on ambiguous characters (this is used only for auto-generated password)
$modGeneratePass->WithoutAmbi = 0;
2022-01-03 11:26:57 +00:00
// Call to validatePassword($password) to check pass match rules
$testpassword = $modGeneratePass->validatePassword($password);
if (!$testpassword) {
$this->error = $modGeneratePass->error;
return -1;
2022-01-03 11:26:57 +00:00
}
}
2022-01-03 11:26:57 +00:00
}
2022-01-21 14:26:54 +00:00
2022-01-03 11:26:57 +00:00
// Now, we encrypt the new password
Qual: Fix phan notices (#37837) * Qual: Ignore PhanUndeclaredProperty for specific lines * Fix: Update payment mode reference in PDF generation # Fix: Update payment mode reference in PDF generation The payment mode reference in the PDF generation was incorrectly using `type_payment_code`, an unknown property in Salary. It has been updated to use `type_code` as used elsewhere for the same purpose. * Qual: Typing of several DDLUpdateField field_desc items made optional # Qual: Typing of several DDLUpdateField field_desc items made optional Not all fields are required for updateing the DB typing, and ExtraFields was not providing all of them. * Qual: Update typing for phan notices # Qual: Update typing for phan notices Fix typing mismatches * Qual: Fix extrafields typing in objectline_create.tpl.php # Qual: Fix extrafields typing in objectline_create.tpl.php - Update typing for phan * Qual: Fix typing for Phan & re-use encrypted password when requested # Qual: Fix typing for Phan & re-use encrypted password when requested - Added a cast to string for the crypted password to hint phan that it returns the string version (not the array) - Added a check to ensure the password is not already crypted before generating a new password. - Updated the type hints for parameters `$changelater`, `$notrigger`, `$nosyncmember`, and `$passwordalreadycrypted` to include the range of possible values. - Updated the return type hint for the `setPassword` method to include the range of possible error values. * Qual: Fix file argument to showPreview() calls # Qual: Fix file argument to showPreview() calls Fix argument type mismatches by adjusting '$file' arguments in showPreview calls. * Qual: Update login_c type to string # Qual: Update login_c type to string login_c is username from db. * Qual: Update type hints in treeview.lib.php # Qual: Update type hints in treeview.lib.php Update type hints for static analysis. * Qual: Add null check for objecttmp in selectForFormsList # Qual: Add null check for objecttmp in selectForFormsList Add null check for objecttmp before calling selectForFormsList to ensure static analysis * Qual: Fix phan through null check on object argument # Qual: Fix phan through null check on object argument - Do null check to avoid null parameter (fix phan); - Set more specific type for argument. * Qual: Change type hint of $remise_percent parameter to float # Qual: Change type hint of $remise_percent parameter to float DB type is float, so correct arg type to fix phan notice. * Qual: Ignore some phan notices The descriptions for the linkedObjectsFullLoaded and oldcopy properties have been updated to avoid modification by code formatting tools * Qual: Update phan baseline * Qual: Cast remise_percent to float to match typing requirements * Qual: Cast label to string to help static analysis * Qual: Update date_cancel property type and assignment To fix phan notices: - The date_cancel property type was changed from 'int|string' to 'int|""' to match return type from jdate(). - Additionally, the assignment of date_cancel was updated to use dol_now() instead of $this->db->idate(dol_now()). * Qual: Provide the expected user_id instead of the User object Changed the user fetch logic from using `user_author` to `user_creation_id` * Qual: Correct bool argument from 0 to false ($fill) * Qual/Fix: Correct date converted to dol_print_date * Qual: Fix argument type for addline() * Qual: Update Phan baseline.txt
2026-04-13 10:50:23 +00:00
$password_crypted = (string) dol_hash($password);
}
// Update password
2020-10-28 23:34:41 +00:00
if (!$changelater) {
if (!is_object($this->oldcopy)) {
$this->oldcopy = clone $this;
}
$now = dol_now();
$this->db->begin();
2014-07-05 06:59:41 +00:00
$sql = "UPDATE ".$this->db->prefix()."user";
$sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."',";
$sql .= " datelastpassvalidation = '".$this->db->idate(dol_now())."',";
$sql .= " pass_temp = null,";
$sql .= " force_pass_change = 0";
if (!empty($flagdelsessionsbefore)) {
$sql .= ", flagdelsessionsbefore = '".$this->db->idate($now - 5, 'gmt')."'";
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('DATABASE_PWD_ENCRYPTED')) {
$sql .= ", pass = null";
2020-05-21 13:05:19 +00:00
} else {
$sql .= ", pass = '".$this->db->escape($password)."'";
}
2021-08-23 17:33:24 +00:00
$sql .= " WHERE rowid = ".((int) $this->id);
2014-07-02 19:29:07 +00:00
dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
if ($this->db->affected_rows($result)) {
$this->pass = $password;
$this->pass_indatabase = $password;
$this->pass_indatabase_crypted = (string) $password_crypted;
$this->force_pass_change = 0;
2020-10-28 23:34:41 +00:00
if ($this->fk_member && !$nosyncmember) {
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
// This user is linked with a member, so we also update members information
// if this is an update.
$adh = new Adherent($this->db);
$result = $adh->fetch($this->fk_member);
2020-10-28 23:34:41 +00:00
if ($result >= 0) {
$result = $adh->setPassword($user, $this->pass, (!getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 0 : 1), 1); // The encryption is not managed in the 'adherent' module
if (is_int($result) && $result < 0) {
$this->error = $adh->error;
dol_syslog(get_class($this)."::setPassword ".$this->error, LOG_ERR);
$error++;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $adh->error;
$error++;
}
}
2011-01-12 02:43:48 +00:00
dol_syslog(get_class($this)."::setPassword notrigger=".$notrigger." error=".$error, LOG_DEBUG);
// Call trigger for the "security events" log
$user->context['audit'] = 'login='.$user->login;
if (!empty($flagdelsessionsbefore)) {
2024-11-07 14:43:51 +00:00
$user->context['audit'] .= " - flagdelsessionsbefore set to '".$this->db->idate($now - 5, 'gmt')."'";
}
2020-10-28 23:34:41 +00:00
if (!$error && !$notrigger) {
// Call trigger
$result = $this->call_trigger('USER_NEW_PASSWORD', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
2023-12-04 12:53:48 +00:00
$error++;
$this->db->rollback();
return -1;
2020-10-28 23:34:41 +00:00
}
// End call triggers
}
2014-07-05 06:59:41 +00:00
2014-07-03 12:01:01 +00:00
$this->db->commit();
return $this->pass;
2020-05-21 13:05:19 +00:00
} else {
$this->db->rollback();
return 0;
}
2020-05-21 13:05:19 +00:00
} else {
$this->db->rollback();
dol_print_error($this->db);
return -1;
}
2020-05-21 13:05:19 +00:00
} else {
// We store password in password temporary field.
// After receiving confirmation link, we will erase and store it in pass_crypted
$sql = "UPDATE ".$this->db->prefix()."user";
$sql .= " SET pass_temp = '".$this->db->escape($password)."'";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE rowid = ".((int) $this->id);
dol_syslog(get_class($this)."::setPassword", LOG_DEBUG); // No log
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
return $password;
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
return -3;
}
}
}
2002-12-18 18:02:06 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Send a new password (or instructions to reset it) by email
2011-09-04 18:41:19 +00:00
*
2023-02-19 01:41:53 +00:00
* @param User $user Object user that send the email (not the user we send to) @todo object $user is not used !
* @param string $password New password
2019-12-11 18:11:13 +00:00
* @param int $changelater 0=Send clear passwod into email, 1=Change password only after clicking on confirm email. @todo Add method 2 = Send link to reset password
2023-12-06 14:46:39 +00:00
* @return int Return integer < 0 si erreur, > 0 si ok
*/
2019-02-25 19:35:59 +00:00
public function send_password($user, $password = '', $changelater = 0)
{
// phpcs:enable
global $conf, $langs;
2011-12-05 18:41:38 +00:00
global $dolibarr_main_url_root;
2012-01-07 14:01:30 +00:00
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
$msgishtml = 0;
// Define $msg
$mesg = '';
$outputlangs = new Translate("", $conf);
2019-05-19 00:06:37 +00:00
if (getDolGlobalString('MAIN_LANG_DEFAULT')) {
$outputlangs->setDefaultLang(getDolGlobalString('MAIN_LANG_DEFAULT'));
} else { // If user has not defined its own language, we used current language
$outputlangs = $langs;
}
// Load translation files required by the page
2018-09-18 15:37:08 +00:00
$outputlangs->loadLangs(array("main", "errors", "users", "other"));
2023-09-29 14:27:07 +00:00
$appli = getDolGlobalString('MAIN_APPLICATION_TITLE', constant('DOL_APPLICATION_TITLE'));
2017-03-13 14:00:44 +00:00
2023-09-29 14:27:07 +00:00
$subject = '['.$appli.'] '.$outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli);
2012-12-12 13:46:13 +00:00
// Define $urlwithroot
$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
2020-10-28 23:34:41 +00:00
if (!$changelater) {
$url = $urlwithroot.'/';
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('URL_REDIRECTION_AFTER_CHANGEPASSWORD')) {
2024-01-05 03:18:53 +00:00
$url = getDolGlobalString('URL_REDIRECTION_AFTER_CHANGEPASSWORD');
}
dol_syslog(get_class($this)."::send_password changelater is off, url=".$url);
$mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."\n";
$mesg .= $outputlangs->transnoentitiesnoconv("NewKeyIs")." :\n\n";
$mesg .= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n";
$mesg .= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n";
$mesg .= "\n";
2017-03-13 14:00:44 +00:00
$mesg .= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli).': '.$url."\n\n";
$mesg .= "--\n";
$mesg .= $user->getFullName($outputlangs); // Username that send the email (not the user for who we want to reset password)
2020-05-21 13:05:19 +00:00
} else {
2023-05-03 10:01:36 +00:00
//print $password.'-'.$this->id.'-'.$conf->file->instance_unique_id;
$url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword';
2023-05-03 10:01:36 +00:00
$url .= '&username='.urlencode($this->login)."&passworduidhash=".urlencode(dol_hash($password.'-'.$this->id.'-'.$conf->file->instance_unique_id));
2023-04-18 08:46:24 +00:00
if (isModEnabled('multicompany')) {
2023-02-18 15:24:56 +00:00
$url .= '&entity='.(!empty($this->entity) ? $this->entity : 1);
}
dol_syslog(get_class($this)."::send_password changelater is on, url=".$url);
$msgishtml = 1;
$mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."<br>\n";
$mesg .= $outputlangs->transnoentitiesnoconv("NewKeyWillBe")." :<br>\n<br>\n";
$mesg .= '<strong>'.$outputlangs->transnoentitiesnoconv("Login")."</strong> = ".$this->login."<br>\n";
$mesg .= '<strong>'.$outputlangs->transnoentitiesnoconv("Password")."</strong> = ".$password."<br>\n<br>\n";
$mesg .= "<br>\n";
$mesg .= $outputlangs->transnoentitiesnoconv("YouMustClickToChange")." :<br>\n";
$mesg .= '<a href="'.$url.'" rel="noopener">'.$outputlangs->transnoentitiesnoconv("ConfirmPasswordChange").'</a>'."<br>\n<br>\n";
$mesg .= $outputlangs->transnoentitiesnoconv("ForgetIfNothing")."<br>\n<br>\n";
}
2020-05-06 13:03:57 +00:00
$trackid = 'use'.$this->id;
$sendcontext = 'passwordreset';
2020-05-06 12:48:02 +00:00
$mailfile = new CMailFile(
$subject,
$this->email,
getDolGlobalString("MAIN_MAIL_EMAIL_FROM_PASSWORDRESET", getDolGlobalString("MAIN_MAIL_EMAIL_FROM")),
$mesg,
array(),
array(),
array(),
'',
'',
0,
$msgishtml,
'',
'',
$trackid,
'',
$sendcontext
2023-12-04 12:53:48 +00:00
);
2020-10-28 23:34:41 +00:00
if ($mailfile->sendfile()) {
return 1;
2020-05-21 13:05:19 +00:00
} else {
2011-09-23 23:46:14 +00:00
$langs->trans("errors");
$this->error = $langs->trans("ErrorFailedToSendPassword").' '.$mailfile->error;
return -1;
}
}
/**
* Returns the last functional error when manipulating the object
2011-09-04 18:41:19 +00:00
*
* @return string error string
*/
2019-02-25 19:35:59 +00:00
public function error()
{
return $this->error;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2019-11-14 17:40:30 +00:00
* Read clicktodial information for user
2011-09-04 18:41:19 +00:00
*
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2019-02-25 19:35:59 +00:00
public function fetch_clicktodial()
{
// phpcs:enable
$sql = "SELECT url, login, pass, poste ";
$sql .= " FROM ".$this->db->prefix()."user_clicktodial as u";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE u.fk_user = ".((int) $this->id);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
if ($this->db->num_rows($resql)) {
$obj = $this->db->fetch_object($resql);
2005-01-14 14:18:45 +00:00
$this->clicktodial_url = $obj->url;
$this->clicktodial_login = $obj->login;
$this->clicktodial_password = $obj->pass;
$this->clicktodial_poste = $obj->poste;
}
2005-01-14 14:18:45 +00:00
$this->clicktodial_loaded = 1; // Data loaded (found or not)
$this->db->free($resql);
return 1;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->error();
return -1;
}
2005-01-14 14:18:45 +00:00
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2011-09-20 17:34:15 +00:00
* Update clicktodial info
*
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
public function update_clicktodial()
{
// phpcs:enable
2011-09-23 23:46:14 +00:00
$this->db->begin();
$sql = "DELETE FROM ".$this->db->prefix()."user_clicktodial";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE fk_user = ".((int) $this->id);
2002-12-18 18:02:06 +00:00
2014-06-12 23:34:39 +00:00
dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
2024-09-01 10:46:17 +00:00
$result = $this->db->query($sql);
2005-01-14 14:18:45 +00:00
$sql = "INSERT INTO ".$this->db->prefix()."user_clicktodial";
$sql .= " (fk_user,url,login,pass,poste)";
$sql .= " VALUES (".((int) $this->id);
$sql .= ", '".$this->db->escape($this->clicktodial_url)."'";
$sql .= ", '".$this->db->escape($this->clicktodial_login)."'";
$sql .= ", '".$this->db->escape($this->clicktodial_password)."'";
$sql .= ", '".$this->db->escape($this->clicktodial_poste)."')";
2014-06-12 23:34:39 +00:00
dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
2024-09-01 10:46:17 +00:00
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
2011-09-23 23:46:14 +00:00
$this->db->commit();
return 1;
2020-05-21 13:05:19 +00:00
} else {
2011-09-23 23:46:14 +00:00
$this->db->rollback();
$this->error = $this->db->lasterror();
2011-09-23 23:46:14 +00:00
return -1;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2011-09-20 17:34:15 +00:00
* Add user into a group
2011-09-04 18:41:19 +00:00
*
2021-03-22 12:31:06 +00:00
* @param int $group Id of group
2011-09-20 17:34:15 +00:00
* @param int $entity Entity
* @param int $notrigger Disable triggers
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2019-02-25 19:35:59 +00:00
public function SetInGroup($group, $entity, $notrigger = 0)
{
// phpcs:enable
2025-09-18 14:26:38 +00:00
global $langs, $user;
2011-06-29 10:23:32 +00:00
$error = 0;
2011-05-28 00:16:12 +00:00
$this->db->begin();
$sql = "DELETE FROM ".$this->db->prefix()."usergroup_user";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE fk_user = ".((int) $this->id);
2021-03-22 12:31:06 +00:00
$sql .= " AND fk_usergroup = ".((int) $group);
2021-08-23 17:33:24 +00:00
$sql .= " AND entity = ".((int) $entity);
$result = $this->db->query($sql);
$sql = "INSERT INTO ".$this->db->prefix()."usergroup_user (entity, fk_user, fk_usergroup)";
2021-08-23 17:33:24 +00:00
$sql .= " VALUES (".((int) $entity).",".((int) $this->id).",".((int) $group).")";
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
if (!$error && !$notrigger) {
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
$this->context = array('audit' => $langs->trans("UserSetInGroup"), 'newgroupid' => $group);
2017-03-13 14:00:44 +00:00
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
}
2011-06-29 10:23:32 +00:00
2020-10-28 23:34:41 +00:00
if (!$error) {
$this->db->commit();
return 1;
2020-05-21 13:05:19 +00:00
} else {
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::SetInGroup ".$this->error, LOG_ERR);
$this->db->rollback();
return -2;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2011-09-20 17:34:15 +00:00
* Remove a user from a group
2011-09-04 18:41:19 +00:00
*
2021-03-22 12:31:06 +00:00
* @param int $group Id of group
2011-09-23 23:46:14 +00:00
* @param int $entity Entity
* @param int $notrigger Disable triggers
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2019-02-25 19:35:59 +00:00
public function RemoveFromGroup($group, $entity, $notrigger = 0)
{
// phpcs:enable
2025-09-18 14:26:38 +00:00
global $langs, $user;
2011-06-29 10:23:32 +00:00
$error = 0;
2011-09-23 23:46:14 +00:00
$this->db->begin();
2011-05-28 00:16:12 +00:00
$sql = "DELETE FROM ".$this->db->prefix()."usergroup_user";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE fk_user = ".((int) $this->id);
2021-03-22 12:31:06 +00:00
$sql .= " AND fk_usergroup = ".((int) $group);
2023-01-14 01:40:44 +00:00
if (empty($entity)) {
$sql .= " AND entity IN (0, 1)"; // group may be in entity 0 (so $entity=0) and link with user into entity 1.
} else {
$sql .= " AND entity = ".((int) $entity);
}
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
if (!$error && !$notrigger) {
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
$this->context = array('audit' => $langs->trans("UserRemovedFromGroup"), 'oldgroupid' => $group);
2017-03-13 14:00:44 +00:00
// Call trigger
$result = $this->call_trigger('USER_MODIFY', $user);
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$error++;
}
// End call triggers
}
2011-05-28 00:16:12 +00:00
2020-10-28 23:34:41 +00:00
if (!$error) {
$this->db->commit();
return 1;
2020-05-21 13:05:19 +00:00
} else {
2011-09-23 23:46:14 +00:00
dol_syslog(get_class($this)."::RemoveFromGroup ".$this->error, LOG_ERR);
$this->db->rollback();
return -2;
}
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
2023-01-27 13:06:31 +00:00
/**
* Return a link with photo
* Use this->id,this->photo
*
2023-01-27 13:27:51 +00:00
* @return int 0=Valid, >0 if not valid
2023-01-27 13:06:31 +00:00
*/
2023-01-27 13:27:51 +00:00
public function isNotIntoValidityDateRange()
2023-01-27 13:06:31 +00:00
{
include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$now = dol_now();
2023-01-27 13:27:51 +00:00
//dol_syslog("isNotIntoValidityDateRange ".$this->datestartvalidity);
2023-01-27 13:06:31 +00:00
// Check date start validity
if ($this->datestartvalidity && $this->datestartvalidity > dol_get_last_hour($now)) {
2023-01-27 13:27:51 +00:00
return 1;
2023-01-27 13:06:31 +00:00
}
// Check date end validity
if ($this->dateendvalidity && $this->dateendvalidity < dol_get_first_hour($now)) {
2023-01-27 13:27:51 +00:00
return 1;
2023-01-27 13:06:31 +00:00
}
2023-01-27 13:27:51 +00:00
return 0;
2023-01-27 13:06:31 +00:00
}
/**
2015-05-30 23:06:51 +00:00
* Return a link with photo
* Use this->id,this->photo
*
2015-05-30 23:06:51 +00:00
* @param int $width Width of image
* @param int $height Height of image
2015-05-31 15:31:15 +00:00
* @param string $cssclass Force a css class
* @param string $imagesize 'mini', 'small' or '' (original)
2015-05-30 23:06:51 +00:00
* @return string String with URL link
2024-01-23 14:56:31 +00:00
* @see getImagePublicURLOfObject()
*/
2019-02-25 19:35:59 +00:00
public function getPhotoUrl($width, $height, $cssclass = '', $imagesize = '')
{
$result = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
$result .= Form::showphoto('userphoto', $this, $width, $height, 0, $cssclass, $imagesize);
$result .= '</a>';
return $result;
}
2023-01-30 22:24:23 +00:00
/**
* getTooltipContentArray
* @param array<string,mixed> $params params to construct tooltip data
2023-01-30 22:24:23 +00:00
* @since v18
* @return array{picto?:string,ref?:string,refsupplier?:string,label?:string,date?:string,date_echeance?:string,amountht?:string,total_ht?:string,totaltva?:string,amountlt1?:string,amountlt2?:string,amountrevenustamp?:string,totalttc?:string}|array{optimize:string}
2023-01-30 22:24:23 +00:00
*/
public function getTooltipContentArray($params)
{
global $conf, $langs, $menumanager;
2023-11-17 01:10:45 +00:00
global $dolibarr_main_demo;
2023-01-30 22:24:23 +00:00
$infologin = $params['infologin'] ?? 0;
$option = $params['option'] ?? '';
$data = [];
2023-01-30 22:24:23 +00:00
if (!empty($this->photo)) {
$photo = '<div class="photointooltip floatright">';
$photo .= Form::showphoto('userphoto', $this, 0, 60, 0, 'photoref photowithmargin photologintooltip', 'small', 0, 1); // Force height to 60 so we total height of tooltip can be calculated and collision can be managed
$photo .= '</div>';
$data['photo'] = $photo;
2023-01-30 22:24:23 +00:00
//$label .= '<div style="clear: both;"></div>';
}
// Info Login
$data['opendiv'] = '<div class="centpercent divtooltip">';
$data['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("User").'</u> '.$this->getLibStatut(4);
$data['name'] = '<br><b>'.$langs->trans('Name').':</b> '.dol_string_nohtmltag($this->getFullName($langs));
2023-01-30 22:24:23 +00:00
if (!empty($this->login)) {
$data['login'] = '<br><b>'.$langs->trans('Login').':</b> '.dol_string_nohtmltag($this->login);
2023-01-30 22:24:23 +00:00
}
if (!empty($this->job)) {
$data['job'] = '<br><b>'.$langs->trans("Job").':</b> '.dol_string_nohtmltag($this->job);
2023-01-30 22:24:23 +00:00
}
$data['email'] = '<br><b>'.$langs->trans("Email").':</b> '.dol_string_nohtmltag($this->email);
2023-01-30 22:24:23 +00:00
if (!empty($this->office_phone) || !empty($this->office_fax) || !empty($this->fax)) {
$phonelist = array();
if ($this->office_phone) {
$phonelist[] = dol_print_phone($this->office_phone, $this->country_code, $this->id, 0, '', '&nbsp', 'phone');
}
if ($this->office_fax) {
$phonelist[] = dol_print_phone($this->office_fax, $this->country_code, $this->id, 0, '', '&nbsp', 'fax');
}
if ($this->user_mobile) {
$phonelist[] = dol_print_phone($this->user_mobile, $this->country_code, $this->id, 0, '', '&nbsp', 'mobile');
}
$data['phones'] = '<br><b>'.$langs->trans('Phone').':</b> '.implode('&nbsp;', $phonelist);
2023-01-30 22:24:23 +00:00
}
if (!empty($this->admin)) {
$data['administrator'] = '<br><b>'.$langs->trans("Administrator").'</b>: '.yn($this->admin);
2023-01-30 22:24:23 +00:00
}
if (!empty($this->accountancy_code) || $option == 'accountancy') {
2023-11-06 16:30:21 +00:00
$langs->load("companies");
$data['accountancycode'] = '<br><b>'.$langs->trans("AccountancyCode").'</b>: '.$this->accountancy_code;
2023-01-30 22:24:23 +00:00
}
$company = '';
if (!empty($this->socid)) { // Add thirdparty for external users
$thirdpartystatic = new Societe($this->db);
$thirdpartystatic->fetch($this->socid);
2023-11-17 01:10:45 +00:00
$companyimg = '';
if (empty($params['hidethirdpartylogo'])) {
2024-07-30 09:52:40 +00:00
$companyimg = ' '.$thirdpartystatic->getNomUrl(2, 'nolink', 0, 1); // picto only of company
2023-01-30 22:24:23 +00:00
}
2023-11-17 01:10:45 +00:00
$company = ' ('.$langs->trans("Company").': '.($companyimg ? $companyimg : img_picto('', 'company')).' '.dol_string_nohtmltag($thirdpartystatic->name).')';
2023-01-30 22:24:23 +00:00
}
$type = ($this->socid ? $langs->trans("ExternalUser").$company : $langs->trans("InternalUser"));
$data['type'] = '<br><b>'.$langs->trans("Type").':</b> '.$type;
$data['closediv'] = '</div>';
2023-04-27 13:55:21 +00:00
2023-01-30 22:24:23 +00:00
if ($infologin > 0) {
$data['newlinelogin'] = '<br>';
$data['session'] = '<br><u>'.$langs->trans("Session").'</u>';
$data['ip'] = '<br><b>'.$langs->trans("IPAddress").'</b>: '.dol_string_nohtmltag(getUserRemoteIP());
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MAIN_MODULE_MULTICOMPANY')) {
$data['multicompany'] = '<br><b>'.$langs->trans("ConnectedOnMultiCompany").':</b> '.$conf->entity.' (User entity '.$this->entity.')';
2023-01-30 22:24:23 +00:00
}
$data['authentication'] = '<br><b>'.$langs->trans("AuthenticationMode").':</b> '.dol_string_nohtmltag($_SESSION["dol_authmode"].(empty($dolibarr_main_demo) ? '' : ' (demo)'));
$data['connectedsince'] = '<br><b>'.$langs->trans("ConnectedSince").':</b> '.dol_print_date($this->datelastlogin, "dayhour", 'tzuser');
$data['previousconnexion'] = '<br><b>'.$langs->trans("PreviousConnexion").':</b> '.dol_print_date($this->datepreviouslogin, "dayhour", 'tzuser');
$data['currenttheme'] = '<br><b>'.$langs->trans("CurrentTheme").':</b> '.dol_string_nohtmltag($conf->theme);
// @phan-suppress-next-line PhanRedefinedClassReference
$data['currentmenumanager'] = '<br><b>'.$langs->trans("CurrentMenuManager").':</b> '.dol_string_nohtmltag($menumanager->name);
2023-01-30 22:24:23 +00:00
$s = picto_from_langcode($langs->getDefaultLang());
$data['currentuserlang'] = '<br><b>'.$langs->trans("CurrentUserLanguage").':</b> '.dol_string_nohtmltag(($s ? $s.' ' : '').$langs->getDefaultLang());
$data['browser'] = '<br><b>'.$langs->trans("Browser").':</b> '.dol_string_nohtmltag($conf->browser->name.($conf->browser->version ? ' '.$conf->browser->version : '').' ('.$_SERVER['HTTP_USER_AGENT'].')');
$data['layout'] = '<br><b>'.$langs->trans("Layout").':</b> '.dol_string_nohtmltag($conf->browser->layout);
$data['screen'] = '<br><b>'.$langs->trans("Screen").':</b> '.dol_string_nohtmltag($_SESSION['dol_screenwidth'].' x '.$_SESSION['dol_screenheight']);
2023-01-30 22:24:23 +00:00
if ($conf->browser->layout == 'phone') {
$data['phone'] = '<br><b>'.$langs->trans("Phone").':</b> '.$langs->trans("Yes");
2023-01-30 22:24:23 +00:00
}
if (!empty($_SESSION["disablemodules"])) {
Qual: Apply automatic phan fixes (deprecations, unneeded imports) (#28154) * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports). * Qual: Apply automatic phan fixes (deprecations, unneeded imports) # Qual: Apply automatic phan fixes (deprecations, unneeded imports) This applies automatic fixes by phan for deprecated functions, unneeded imports).
2024-02-13 20:46:12 +00:00
$data['disabledmodules'] = '<br><b>'.$langs->trans("DisabledModules").':</b> <br>'.dol_string_nohtmltag(implode(', ', explode(',', $_SESSION["disablemodules"])));
2023-01-30 22:24:23 +00:00
}
}
return $data;
2023-01-30 22:24:23 +00:00
}
/**
* Return a HTML link to the user card (with optionally the picto)
2013-02-23 14:26:39 +00:00
* Use this->id,this->lastname, this->firstname
2011-09-04 18:41:19 +00:00
*
2025-11-21 00:02:28 +00:00
* @param int $withpictoimg Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small, -4=Include photo very small into link)
* @param string $option On what the link point to ('leave', 'accountancy', 'nolink', )
* @param integer $infologin 0=Add default info tooltip, 1=Add complete info tooltip, -1=No info tooltip
* @param integer $notooltip 1=Disable tooltip on picto and name
* @param int $maxlen Max length of visible user name
* @param int $hidethirdpartylogo Hide logo of thirdparty if user is external user
* @param string $mode ''=Show firstname and lastname, 'firstname'=Show only firstname, 'firstelselast'=Show firstname or lastname if not defined, 'login'=Show login
* @param string $morecss Add more css on link
* @param int<-1,1> $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string String with URL
*/
2025-11-08 10:28:10 +00:00
public function getNomUrl($withpictoimg = 0, $option = '', $infologin = 0, $notooltip = 0, $maxlen = 24, $hidethirdpartylogo = 0, $mode = '', $morecss = '', $save_lastsearch_value = -1)
{
2024-07-30 09:52:40 +00:00
global $langs, $hookmanager, $user;
2015-01-25 00:20:58 +00:00
2022-09-06 13:37:00 +00:00
if (!$user->hasRight('user', 'user', 'read') && $user->id != $this->id) {
2020-10-28 23:34:41 +00:00
$option = 'nolink';
}
2018-07-05 09:52:41 +00:00
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') && $withpictoimg) {
2020-10-28 23:34:41 +00:00
$withpictoimg = 0;
}
2016-03-17 08:22:12 +00:00
2023-02-06 22:00:42 +00:00
$result = '';
$params = [
'id' => $this->id,
'objecttype' => $this->element,
'infologin' => $infologin,
'option' => $option,
'hidethirdpartylogo' => $hidethirdpartylogo,
2023-02-06 22:00:42 +00:00
];
$classfortooltip = 'classfortooltip';
$dataparams = '';
if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
$classfortooltip = 'classforajaxtooltip';
2023-04-03 17:51:40 +00:00
$dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
$label = '';
} else {
$label = implode($this->getTooltipContentArray($params));
2021-05-03 10:01:26 +00:00
}
2023-04-03 17:51:40 +00:00
2023-02-06 22:00:42 +00:00
$companylink = '';
2020-10-28 23:34:41 +00:00
if (!empty($this->socid)) { // Add thirdparty for external users
2023-02-06 22:00:42 +00:00
$thirdpartystatic = new Societe($this->db);
$thirdpartystatic->fetch($this->socid);
2020-10-28 23:34:41 +00:00
if (empty($hidethirdpartylogo)) {
2024-07-30 09:52:40 +00:00
$companylink = ' '.$thirdpartystatic->getNomUrl(2, 'nolink', 0, 1); // picto only of company
2020-10-28 23:34:41 +00:00
}
}
2023-02-06 22:00:42 +00:00
2020-10-28 23:34:41 +00:00
if ($infologin < 0) {
$label = '';
}
2017-03-23 09:59:13 +00:00
add dolBuildUrl with examples of use (#35549) * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * wip * wip * add more example * add more example * add more example * add more example * add more example * add more example * add more example * add example * add example * add example * add example * add example * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * clean code * clean code * clean code * clean code * clean code * clean code * clean code * add example * add example * add example * add example * add example * add example add example add example add example add example * add example * add example add example add example add example * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * fix * wip * wip * clean code
2025-10-06 16:17:02 +00:00
$baseurl = DOL_URL_ROOT . '/user/card.php';
2020-10-28 23:34:41 +00:00
if ($option == 'leave') {
add dolBuildUrl with examples of use (#35549) * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * wip * wip * add more example * add more example * add more example * add more example * add more example * add more example * add more example * add example * add example * add example * add example * add example * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * clean code * clean code * clean code * clean code * clean code * clean code * clean code * add example * add example * add example * add example * add example * add example add example add example add example add example * add example * add example add example add example add example * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * fix * wip * wip * clean code
2025-10-06 16:17:02 +00:00
$baseurl = DOL_URL_ROOT . '/holiday/list.php';
2020-10-28 23:34:41 +00:00
}
add dolBuildUrl with examples of use (#35549) * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * wip * wip * add more example * add more example * add more example * add more example * add more example * add more example * add more example * add example * add example * add example * add example * add example * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * clean code * clean code * clean code * clean code * clean code * clean code * clean code * add example * add example * add example * add example * add example * add example add example add example add example add example * add example * add example add example add example add example * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * fix * wip * wip * clean code
2025-10-06 16:17:02 +00:00
$query = ['id' => $this->id];
2020-10-28 23:34:41 +00:00
if ($option != 'nolink') {
// Add param to save lastsearch_values or not
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2023-09-10 15:41:22 +00:00
if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2020-10-28 23:34:41 +00:00
$add_save_lastsearch_values = 1;
}
if ($add_save_lastsearch_values) {
add dolBuildUrl with examples of use (#35549) * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * wip * wip * add more example * add more example * add more example * add more example * add more example * add more example * add more example * add example * add example * add example * add example * add example * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * clean code * clean code * clean code * clean code * clean code * clean code * clean code * add example * add example * add example * add example * add example * add example add example add example add example add example * add example * add example add example add example add example * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * fix * wip * wip * clean code
2025-10-06 16:17:02 +00:00
$query = array_merge($query, ['save_lastsearch_values' => 1]);
2020-10-28 23:34:41 +00:00
}
}
add dolBuildUrl with examples of use (#35549) * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * add dol_buildurl with examples of use * wip * wip * add more example * add more example * add more example * add more example * add more example * add more example * add more example * add example * add example * add example * add example * add example * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * stay in the same area even we are on other area in other tab * clean code * clean code * clean code * clean code * clean code * clean code * clean code * add example * add example * add example * add example * add example * add example add example add example add example add example * add example * add example add example add example add example * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * clean code * fix * wip * wip * clean code
2025-10-06 16:17:02 +00:00
$url = dolBuildUrl($baseurl, $query);
2017-03-23 09:59:13 +00:00
$linkstart = '<a href="'.$url.'"';
$linkclose = "";
2020-10-28 23:34:41 +00:00
if (empty($notooltip)) {
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2017-03-23 09:59:13 +00:00
$langs->load("users");
$label = $langs->trans("ShowUser");
2025-01-09 01:01:49 +00:00
$linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
2017-03-23 09:59:13 +00:00
}
2025-01-09 01:01:49 +00:00
$linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
2023-02-04 20:22:30 +00:00
$linkclose .= $dataparams . ' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
2023-04-03 17:51:40 +00:00
} else {
$linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
2017-03-23 09:59:13 +00:00
}
2016-07-16 16:05:58 +00:00
$linkstart .= $linkclose.'>';
$linkend = '</a>';
//if ($withpictoimg == -1) $result.='<div class="nowrap">';
$result .= (($option == 'nolink') ? '' : $linkstart);
2020-10-28 23:34:41 +00:00
if ($withpictoimg) {
$paddafterimage = '';
2025-11-21 00:02:28 +00:00
if (abs((int) $withpictoimg) == 1 || abs((int) $withpictoimg) == 4) {
2020-10-28 23:34:41 +00:00
$paddafterimage = 'style="margin-'.($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right').': 3px;"';
}
// Only picto
2020-10-28 23:34:41 +00:00
if ($withpictoimg > 0) {
2023-10-17 10:36:12 +00:00
$picto = '<!-- picto user --><span class="nopadding userimg'.($morecss ? ' '.$morecss : '').'"><div class="valignmiddle userphoto inline-block center marginrightonlyshort"'.($paddafterimage ? ' '.$paddafterimage : '').'>'.img_object('', 'user', 'class=""', 0, 0, $notooltip ? 0 : 1).'</div></span>';
2021-03-01 19:37:16 +00:00
} else {
// Picto must be a photo
2026-03-03 19:13:58 +00:00
$picto = '<!-- picto photo user --><span class="nopadding userimg'.($morecss ? ' '.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
$picto .= Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.(($withpictoimg == -3 || $withpictoimg == -4) ? 'small' : ''), 'mini', 0, 1);
$picto .= '</span>';
2020-10-28 23:34:41 +00:00
}
$result .= $picto;
}
2026-03-03 19:13:58 +00:00
2025-11-21 00:02:28 +00:00
if ($withpictoimg == -4 || ($withpictoimg > -2 && $withpictoimg != 2)) {
2023-11-27 11:08:48 +00:00
if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2023-07-27 15:45:40 +00:00
$result .= '<span class="nopadding usertext'.((!isset($this->status) || $this->status) ? '' : ' strikefordisabled').($morecss ? ' '.$morecss : '').'">';
2020-10-28 23:34:41 +00:00
}
if ($mode == 'login') {
2021-01-25 21:46:09 +00:00
$result .= dol_string_nohtmltag(dol_trunc($this->login, $maxlen));
2020-10-28 23:34:41 +00:00
} else {
$result .= dol_string_nohtmltag($this->getFullName($langs, 0, ($mode == 'firstelselast' ? 3 : ($mode == 'firstname' ? 2 : -1)), $maxlen));
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2020-10-28 23:34:41 +00:00
$result .= '</span>';
}
}
$result .= (($option == 'nolink') ? '' : $linkend);
2015-10-24 17:45:41 +00:00
//if ($withpictoimg == -1) $result.='</div>';
$result .= $companylink;
global $action;
$hookmanager->initHooks(array('userdao'));
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
$parameters = array('id' => $this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2020-10-28 23:34:41 +00:00
if ($reshook > 0) {
$result = $hookmanager->resPrint;
} else {
$result .= $hookmanager->resPrint;
}
return $result;
}
/**
* Return clickable link of login (optionally with picto)
2011-09-04 18:41:19 +00:00
*
2021-10-05 11:34:25 +00:00
* @param int $withpictoimg Include picto into link (1=picto, -1=photo)
2021-05-18 16:18:00 +00:00
* @param string $option On what the link point to ('leave', 'accountancy', 'nolink', )
* @param integer $notooltip 1=Disable tooltip on picto and name
* @param string $morecss Add more css on link
* @return string String with URL
*/
2021-05-18 16:18:00 +00:00
public function getLoginUrl($withpictoimg = 0, $option = '', $notooltip = 0, $morecss = '')
{
2018-07-05 09:52:41 +00:00
global $langs, $user;
$result = '';
$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
$linkend = '</a>';
2019-11-28 15:16:55 +00:00
//Check user's rights to see an other user
2023-10-15 16:41:39 +00:00
if ((!$user->hasRight('user', 'user', 'lire') && $this->id != $user->id)) {
2020-10-28 23:34:41 +00:00
$option = 'nolink';
}
2018-08-13 15:26:32 +00:00
2020-10-28 23:34:41 +00:00
if ($option == 'xxx') {
$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2024-05-30 11:37:17 +00:00
$linkend = '</a>';
}
2018-08-13 15:26:32 +00:00
2020-10-28 23:34:41 +00:00
if ($option == 'nolink') {
2018-07-05 09:52:41 +00:00
$linkstart = '';
$linkend = '';
2018-07-05 09:52:41 +00:00
}
$result .= $linkstart;
2021-05-18 16:18:00 +00:00
if ($withpictoimg) {
$paddafterimage = '';
if (abs($withpictoimg) == 1) {
$paddafterimage = 'style="margin-'.($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right').': 3px;"';
}
// Only picto
if ($withpictoimg > 0) {
$picto = '<!-- picto user --><span class="nopadding userimg'.($morecss ? ' '.$morecss : '').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : 'class="paddingright classfortooltip"'), 0, 0, $notooltip ? 0 : 1).'</span>';
} else {
// Picto must be a photo
$picto = '<!-- picto photo user --><span class="nopadding userimg'.($morecss ? ' '.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>'.Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1).'</span>';
}
$result .= $picto;
2020-10-28 23:34:41 +00:00
}
$result .= $this->login;
$result .= $linkend;
2021-05-18 16:18:00 +00:00
return $result;
2006-09-02 01:17:50 +00:00
}
2006-09-02 01:17:50 +00:00
/**
2020-09-15 12:45:51 +00:00
* Return the label of the status of user (active, inactive)
2011-09-04 18:41:19 +00:00
*
2020-09-15 12:45:51 +00:00
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2011-09-20 17:34:15 +00:00
* @return string Label of status
2006-09-02 01:17:50 +00:00
*/
2019-02-25 19:35:59 +00:00
public function getLibStatut($mode = 0)
2006-09-02 01:17:50 +00:00
{
2022-06-08 18:07:16 +00:00
return $this->LibStatut(isset($this->statut) ? (int) $this->statut : (int) $this->status, $mode);
2006-09-02 01:17:50 +00:00
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2020-09-15 12:45:51 +00:00
* Return the label of a status of user (active, inactive)
*
* @param int $status Id status
2019-10-31 22:29:17 +00:00
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
* @return string Label of status
*/
public function LibStatut($status, $mode = 0)
{
// phpcs:enable
2006-09-02 01:17:50 +00:00
global $langs;
2020-10-28 23:34:41 +00:00
if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2019-10-31 22:29:17 +00:00
global $langs;
//$langs->load("mymodule");
2021-10-16 17:37:57 +00:00
$this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
$this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
$this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
$this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
2006-09-02 01:17:50 +00:00
}
2019-10-31 22:29:17 +00:00
$statusType = 'status5';
2020-10-28 23:34:41 +00:00
if ($status == self::STATUS_ENABLED) {
$statusType = 'status4';
}
2019-10-31 22:29:17 +00:00
$label = $this->labelStatus[$status];
$labelshort = $this->labelStatusShort[$status];
$now = dol_now();
if (!empty($this->datestartvalidity) && $now < $this->datestartvalidity) {
$statusType = 'status3';
$label .= ' ('.$langs->trans("UserNotYetValid").')';
}
if (!empty($this->dateendvalidity) && $now > ($this->dateendvalidity + 24 * 3600 - 1)) {
$statusType = 'status2';
$label .= ' ('.$langs->trans("UserExpired").')';
}
return dolGetStatus($label, $labelshort, '', $statusType, $mode);
}
2022-05-18 14:55:03 +00:00
/**
* Return clickable link of object (optionally with picto)
2022-05-18 14:55:03 +00:00
*
* @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
* @param ?array<string,mixed> $arraydata Array of data
* @return string HTML Code for Kanban thumb.
2022-05-18 14:55:03 +00:00
*/
2023-01-18 21:27:52 +00:00
public function getKanbanView($option = '', $arraydata = null)
2022-05-18 14:55:03 +00:00
{
2023-06-22 18:53:09 +00:00
global $langs;
2023-03-07 21:04:40 +00:00
$selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2022-05-18 14:55:03 +00:00
$return = '<div class="box-flex-item box-flex-grow-zero">';
$return .= '<div class="info-box info-box-sm">';
$return .= '<span class="info-box-icon bg-infobox-action">';
2022-06-14 09:47:56 +00:00
$label = '';
if (!empty($this->photo)) {
//$label .= '<div class="photointooltip floatright">';
$label .= Form::showphoto('userphoto', $this, 0, 60, 0, 'photokanban photoref photowithmargin photologintooltip', 'small', 0, 1); // Force height to 60 so we total height of tooltip can be calculated and collision can be managed
//$label .= '</div>';
//$label .= '<div style="clear: both;"></div>';
$return .= $label;
} else {
$return .= img_picto('', $this->picto);
}
2022-05-18 14:55:03 +00:00
//$return .= '<i class="fa fa-dol-action"></i>'; // Can be image
$return .= '</span>';
$return .= '<div class="info-box-content">';
2023-06-22 18:53:09 +00:00
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(0, '', 0, 0, 24, 0, '', 'valignmiddle') : $this->ref);
if (isModEnabled('multicompany') && $this->admin && !$this->entity) {
2025-11-21 18:11:32 +00:00
$return .= img_picto($langs->trans("SuperAdministratorDesc"), 'superadmin', 'class="valignmiddle paddingright paddingleft"');
2023-06-22 18:53:09 +00:00
} elseif ($this->admin) {
2025-11-21 18:11:32 +00:00
$return .= img_picto($langs->trans("AdministratorDesc"), 'admin', 'class="valignmiddle paddingright paddingleft"');
2023-06-22 18:53:09 +00:00
}
$return .= '</span>';
2023-10-17 13:43:56 +00:00
if ($selected >= 0) {
$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
2022-05-18 14:55:03 +00:00
if (property_exists($this, 'label')) {
$return .= '<br><span class="info-box-label opacitymedium">'.$this->label.'</span>';
2022-06-14 09:47:56 +00:00
}
if ($this->email) {
$return .= '<br><span class="info-box-label opacitymedium small">'.img_picto('', 'email').' '.$this->email.'</span>';
2022-05-18 14:55:03 +00:00
}
if (method_exists($this, 'getLibStatut')) {
2023-12-19 10:51:48 +00:00
$return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2022-05-18 14:55:03 +00:00
}
$return .= '</div>';
$return .= '</div>';
$return .= '</div>';
return $return;
}
2019-05-10 14:12:16 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2019-05-10 14:37:03 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Returns the complete DN (Distinguished Name) string in the LDAP directory for the object
2011-09-04 18:41:19 +00:00
*
* @param array<string,mixed> $info Info array loaded by _load_ldap_info
* @param int<0,2> $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
* 1=Return parent (ou=xxx,dc=aaa,dc=bbb)
* 2=Return key only (RDN) (uid=qqq)
* @return string DN
*/
public function _load_ldap_dn($info, $mode = 0)
{
// phpcs:enable
global $conf;
$dn = '';
2020-10-28 23:34:41 +00:00
if ($mode == 0) {
2023-10-15 16:41:39 +00:00
$dn = getDolGlobalString('LDAP_KEY_USERS') . "=".$info[getDolGlobalString('LDAP_KEY_USERS')]."," . getDolGlobalString('LDAP_USER_DN');
2020-10-28 23:34:41 +00:00
} elseif ($mode == 1) {
2024-01-05 03:18:53 +00:00
$dn = getDolGlobalString('LDAP_USER_DN');
2020-10-28 23:34:41 +00:00
} elseif ($mode == 2) {
2023-10-15 16:41:39 +00:00
$dn = getDolGlobalString('LDAP_KEY_USERS') . "=".$info[getDolGlobalString('LDAP_KEY_USERS')];
2020-10-28 23:34:41 +00:00
}
return $dn;
}
2019-05-10 14:12:16 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2019-05-10 14:37:03 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-08-11 20:16:58 +00:00
/**
* Initialize the info array (array of LDAP values) that will be used to call LDAP functions
2011-09-04 18:41:19 +00:00
*
* @return array<string,mixed> Table with attribute information
*/
public function _load_ldap_info()
{
// phpcs:enable
global $conf, $langs;
$info = array();
2020-11-11 06:31:10 +00:00
$socialnetworks = getArrayOfSocialNetworks();
$keymodified = false;
// Object classes
2023-12-13 14:20:53 +00:00
$info["objectclass"] = explode(',', getDolGlobalString('LDAP_USER_OBJECT_CLASS'));
$this->fullname = $this->getFullName($langs);
// Possible LDAP KEY (constname => varname)
$ldapkey = array(
'LDAP_FIELD_FULLNAME' => 'fullname',
'LDAP_FIELD_NAME' => 'lastname',
2017-10-02 06:43:53 +00:00
'LDAP_FIELD_FIRSTNAME' => 'firstname',
'LDAP_FIELD_LOGIN' => 'login',
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
'LDAP_FIELD_LOGIN_SAMBA' => 'login',
2017-10-02 06:43:53 +00:00
'LDAP_FIELD_PHONE' => 'office_phone',
'LDAP_FIELD_MOBILE' => 'user_mobile',
2018-10-12 09:29:47 +00:00
'LDAP_FIELD_FAX' => 'office_fax',
'LDAP_FIELD_MAIL' => 'email',
2018-10-12 09:29:47 +00:00
'LDAP_FIELD_SID' => 'ldap_sid',
);
// Champs
2020-10-28 23:34:41 +00:00
foreach ($ldapkey as $constname => $varname) {
2023-08-05 13:44:28 +00:00
if (!empty($this->$varname) && getDolGlobalString($constname)) {
$info[getDolGlobalString($constname)] = $this->$varname;
// Check if it is the LDAP key and if its value has been changed
if (getDolGlobalString('LDAP_KEY_USERS') && getDolGlobalString('LDAP_KEY_USERS') == getDolGlobalString($constname)) {
if (is_object($this->oldcopy) && !$this->oldcopy->isEmpty() && $this->$varname != $this->oldcopy->$varname) {
2020-10-28 23:34:41 +00:00
$keymodified = true; // For check if LDAP key has been modified
}
}
}
}
2020-11-11 06:31:10 +00:00
foreach ($socialnetworks as $key => $value) {
2023-08-05 13:44:28 +00:00
if (!empty($this->socialnetworks[$value['label']]) && getDolGlobalString('LDAP_FIELD_'.strtoupper($value['label']))) {
$info[getDolGlobalString('LDAP_FIELD_'.strtoupper($value['label']))] = $this->socialnetworks[$value['label']];
2020-11-11 06:31:10 +00:00
}
}
2023-11-27 11:08:48 +00:00
if ($this->address && getDolGlobalString('LDAP_FIELD_ADDRESS')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_ADDRESS')] = $this->address;
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if ($this->zip && getDolGlobalString('LDAP_FIELD_ZIP')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_ZIP')] = $this->zip;
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if ($this->town && getDolGlobalString('LDAP_FIELD_TOWN')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_TOWN')] = $this->town;
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if ($this->note_public && getDolGlobalString('LDAP_FIELD_DESCRIPTION')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_DESCRIPTION')] = dol_string_nohtmltag($this->note_public, 2);
2020-10-28 23:34:41 +00:00
}
if ($this->socid > 0 && getDolGlobalString('LDAP_FIELD_COMPANY')) {
$soc = new Societe($this->db);
$soc->fetch($this->socid);
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_COMPANY')] = $soc->name;
2020-10-28 23:34:41 +00:00
if ($soc->client == 1) {
$info["businessCategory"] = "Customers";
}
if ($soc->client == 2) {
$info["businessCategory"] = "Prospects";
}
if ($soc->fournisseur == 1) {
$info["businessCategory"] = "Suppliers";
}
}
// When password is modified
2020-10-28 23:34:41 +00:00
if (!empty($this->pass)) {
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_PASSWORD')) {
$info[getDolGlobalString('LDAP_FIELD_PASSWORD')] = $this->pass; // this->pass = unencrypted password
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')] = dol_hash($this->pass, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2020-10-28 23:34:41 +00:00
}
2023-12-13 14:20:53 +00:00
} elseif (getDolGlobalString('LDAP_SERVER_PROTOCOLVERSION') !== '3') {
2021-03-01 19:37:16 +00:00
// Set LDAP password if possible
// If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('DATABASE_PWD_ENCRYPTED')) {
// Just for the default MD5 !
2023-11-27 11:08:48 +00:00
if (!getDolGlobalString('MAIN_SECURITY_HASH_ALGO')) {
if ($this->pass_indatabase_crypted && getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')] = dolGetLdapPasswordHash($this->pass_indatabase_crypted, 'md5frommd5'); // Create OpenLDAP MD5 password from Dolibarr MD5 password
}
}
2021-03-01 19:37:16 +00:00
} elseif (!empty($this->pass_indatabase)) {
// Use $this->pass_indatabase value if exists
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_PASSWORD')) {
$info[getDolGlobalString('LDAP_FIELD_PASSWORD')] = $this->pass_indatabase; // $this->pass_indatabase = unencrypted password
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED')] = dol_hash($this->pass_indatabase, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2020-10-28 23:34:41 +00:00
}
}
}
2023-07-27 15:45:40 +00:00
if (getDolGlobalString('LDAP_SERVER_TYPE') == 'egroupware') {
$info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
$info['uidnumber'] = $this->id;
$info['phpgwTz'] = 0;
$info['phpgwMailType'] = 'INTERNET';
$info['phpgwMailHomeType'] = 'INTERNET';
$info["phpgwContactTypeId"] = 'n';
$info["phpgwContactCatId"] = 0;
$info["phpgwContactAccess"] = "public";
$info["phpgwContactOwner"] = 1;
2020-10-28 23:34:41 +00:00
if ($this->email) {
$info["rfc822Mailbox"] = $this->email;
}
2023-08-05 12:59:31 +00:00
if ($this->user_mobile) {
$info["phpgwCellTelephoneNumber"] = $this->user_mobile;
2020-10-28 23:34:41 +00:00
}
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_USERID')) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_USERID')] = $this->id;
2020-10-28 23:34:41 +00:00
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_GROUPID')) {
$usergroup = new UserGroup($this->db);
$groupslist = $usergroup->listGroupsForUser($this->id);
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_GROUPID')] = '65534';
if (!empty($groupslist)) {
foreach ($groupslist as $groupforuser) {
2023-10-15 16:41:39 +00:00
$info[getDolGlobalString('LDAP_FIELD_GROUPID')] = $groupforuser->id; //Select first group in list
break;
}
}
}
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('LDAP_FIELD_HOMEDIRECTORY') && getDolGlobalString('LDAP_FIELD_HOMEDIRECTORYPREFIX')) {
2025-09-18 14:26:38 +00:00
$info[getDolGlobalString('LDAP_FIELD_HOMEDIRECTORY')] = getDolGlobalString('LDAP_FIELD_HOMEDIRECTORYPREFIX')."/".$this->login;
2020-10-28 23:34:41 +00:00
}
return $info;
}
/**
2011-09-23 23:46:14 +00:00
* Initialise an instance with random values.
* Used to build previews or test instances.
* id must be 0 if object instance is a specimen.
*
2020-10-28 23:34:41 +00:00
* @return int
*/
2019-02-25 19:35:59 +00:00
public function initAsSpecimen()
{
2025-09-18 14:26:38 +00:00
global $user;
$now = dol_now();
// Initialise parameters
$this->id = 0;
$this->ref = 'SPECIMEN';
$this->specimen = 1;
$this->user_creation_id = $user->id;
$this->lastname = 'DOLIBARR';
$this->firstname = 'SPECIMEN';
$this->gender = 'man';
$this->note_public = 'This is a note public';
$this->note_private = 'This is a note private';
$this->email = 'email@specimen.com';
$this->personal_email = 'personalemail@specimen.com';
2019-09-12 16:12:28 +00:00
$this->socialnetworks = array(
'skype' => 'skypepseudo',
'twitter' => 'twitterpseudo',
'facebook' => 'facebookpseudo',
'linkedin' => 'linkedinpseudo',
);
$this->office_phone = '0999999999';
$this->office_fax = '0999999998';
$this->user_mobile = '0999999997';
$this->personal_mobile = '0999999996';
$this->admin = 0;
$this->login = 'dolibspec';
2022-01-24 11:43:42 +00:00
$this->pass = 'dolibSpec+@123';
2013-04-01 12:49:33 +00:00
//$this->pass_indatabase='dolibspec'; Set after a fetch
//$this->pass_indatabase_crypted='e80ca5a88c892b0aaaf7e154853bccab'; Set after a fetch
$this->datec = $now;
$this->datem = $now;
$this->datelastlogin = $now;
$this->iplastlogin = '127.0.0.1';
$this->datepreviouslogin = $now;
$this->ippreviouslogin = '127.0.0.1';
2023-01-03 10:32:33 +00:00
$this->status = 1;
2013-04-01 12:49:33 +00:00
$this->entity = 1;
2020-10-28 23:34:41 +00:00
return 1;
}
2006-12-03 19:29:41 +00:00
/**
2011-09-20 17:34:15 +00:00
* Load info of user object
2011-09-04 18:41:19 +00:00
*
2011-09-20 17:34:15 +00:00
* @param int $id Id of user to load
* @return void
*/
2019-02-25 19:35:59 +00:00
public function info($id)
{
$sql = "SELECT u.rowid, u.login as ref, u.datec, fk_user_creat as user_creation_id, fk_user_modif as user_modification_id,";
$sql .= " GREATEST(u.tms, uef.tms) as date_modification, u.entity";
$sql .= " FROM ".$this->db->prefix()."user as u";
$sql .= " LEFT JOIN ".$this->db->prefix()."user_extrafields as uef ON uef.fk_object = u.rowid";
2021-03-14 10:48:39 +00:00
$sql .= " WHERE u.rowid = ".((int) $id);
$result = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($result) {
if ($this->db->num_rows($result)) {
$obj = $this->db->fetch_object($result);
$this->id = $obj->rowid;
$this->user_creation_id = $obj->user_creation_id;
$this->user_modification_id = $obj->user_modification_id;
$this->ref = (!$obj->ref) ? $obj->rowid : $obj->ref;
2019-02-25 19:35:59 +00:00
$this->date_creation = $this->db->jdate($obj->datec);
2010-01-13 18:51:19 +00:00
$this->date_modification = $this->db->jdate($obj->date_modification);
2019-02-25 19:35:59 +00:00
$this->entity = $obj->entity;
}
$this->db->free($result);
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
}
}
/**
* Return number of mass Emailing received by this contacts with its email
2011-09-04 18:41:19 +00:00
*
* @return int Number of EMailings
*/
2019-02-25 19:35:59 +00:00
public function getNbOfEMailings()
{
$sql = "SELECT count(mc.email) as nb";
$sql .= " FROM ".$this->db->prefix()."mailing_cibles as mc";
$sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with success
2018-06-06 16:18:50 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$obj = $this->db->fetch_object($resql);
$nb = (int) $obj->nb;
$this->db->free($resql);
return $nb;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->error();
return -1;
}
}
2010-06-17 16:53:26 +00:00
2010-06-07 05:11:45 +00:00
/**
2011-09-20 17:34:15 +00:00
* Return number of existing users
2011-09-04 18:41:19 +00:00
*
* @param string $limitTo Limit to '' or 'active'
* @param string $option 'superadmin' = return for entity 0 only
* @param int $admin Filter on admin tag
2011-09-20 17:34:15 +00:00
* @return int Number of users
2010-06-07 05:11:45 +00:00
*/
2019-02-25 19:35:59 +00:00
public function getNbOfUsers($limitTo, $option = '', $admin = -1)
2010-06-07 05:11:45 +00:00
{
$sql = "SELECT count(rowid) as nb";
$sql .= " FROM ".$this->db->prefix()."user";
2020-10-28 23:34:41 +00:00
if ($option == 'superadmin') {
$sql .= " WHERE entity = 0";
2020-05-21 13:05:19 +00:00
} else {
$sql .= " WHERE entity IN (".getEntity('user', 0).")";
2020-11-10 20:46:51 +00:00
if ($limitTo == 'active') {
$sql .= " AND statut = 1";
}
2020-11-10 20:43:45 +00:00
}
if ($admin >= 0) {
$sql .= " AND admin = ".(int) $admin;
}
2010-06-17 16:53:26 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
2010-06-07 05:11:45 +00:00
$obj = $this->db->fetch_object($resql);
2020-11-10 20:43:45 +00:00
$nb = (int) $obj->nb;
2010-06-07 05:11:45 +00:00
$this->db->free($resql);
return $nb;
2020-05-21 13:05:19 +00:00
} else {
$this->error = $this->db->lasterror();
2010-06-07 05:11:45 +00:00
return -1;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Update user using data from the LDAP
*
2019-04-04 16:33:12 +00:00
* @param Object $ldapuser Ladp User
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2019-02-25 19:35:59 +00:00
public function update_ldap2dolibarr(&$ldapuser)
{
// phpcs:enable
// TODO: See why the update sets all values to empty (does global $user overwrite?)
2025-09-18 14:26:38 +00:00
global $user;
2020-11-11 06:31:10 +00:00
$socialnetworks = getArrayOfSocialNetworks();
2022-12-30 17:43:43 +00:00
$tmpvar = getDolGlobalString('LDAP_FIELD_FIRSTNAME');
$this->firstname = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_NAME');
$this->lastname = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_LOGIN');
$this->login = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_PASSWORD');
$this->pass = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED');
$this->pass_indatabase_crypted = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_PHONE');
$this->office_phone = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_MOBILE');
$this->user_mobile = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_FAX');
$this->office_fax = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_MAIL');
$this->email = $ldapuser->$tmpvar;
2020-11-11 06:31:10 +00:00
foreach ($socialnetworks as $key => $value) {
2022-12-30 17:43:43 +00:00
$tmpvar = getDolGlobalString('LDAP_FIELD_'.strtoupper($value['label']));
$this->socialnetworks[$value['label']] = $ldapuser->$tmpvar;
2020-11-11 06:31:10 +00:00
}
2022-12-30 17:43:43 +00:00
$tmpvar = getDolGlobalString('LDAP_FIELD_SID');
$this->ldap_sid = $ldapuser->$tmpvar;
2022-12-30 17:43:43 +00:00
$tmpvar = getDolGlobalString('LDAP_FIELD_TITLE');
$this->job = $ldapuser->$tmpvar;
$tmpvar = getDolGlobalString('LDAP_FIELD_DESCRIPTION');
$this->note_public = $ldapuser->$tmpvar;
$result = $this->update($user);
dol_syslog(get_class($this)."::update_ldap2dolibarr result=".$result, LOG_DEBUG);
return $result;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Return and array with all instantiated first level children users of current user
*
2024-03-15 22:14:21 +00:00
* @return User[]|int<-1,-1>
2019-04-04 16:33:12 +00:00
* @see getAllChildIds()
*/
2019-02-25 19:35:59 +00:00
public function get_children()
{
// phpcs:enable
$sql = "SELECT rowid FROM ".$this->db->prefix()."user";
2021-08-23 17:33:24 +00:00
$sql .= " WHERE fk_user = ".((int) $this->id);
2021-08-27 20:42:04 +00:00
dol_syslog(get_class($this)."::get_children", LOG_DEBUG);
$res = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($res) {
$users = array();
2020-10-28 23:34:41 +00:00
while ($rec = $this->db->fetch_array($res)) {
$user = new User($this->db);
$user->fetch($rec['rowid']);
$users[] = $user;
}
return $users;
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
return -1;
}
}
/**
2019-02-25 19:35:59 +00:00
* Load this->parentof that is array(id_son=>id_parent, ...)
*
2024-03-15 22:14:21 +00:00
* @return int<-1,1> Return integer <0 if KO, >0 if OK
*/
2018-09-02 07:57:19 +00:00
private function loadParentOf()
{
$this->parentof = array();
// Load array[child]=parent
$sql = "SELECT fk_user as id_parent, rowid as id_son";
$sql .= " FROM ".$this->db->prefix()."user";
$sql .= " WHERE fk_user <> 0";
$sql .= " AND entity IN (".getEntity('user').")";
2018-09-02 07:57:19 +00:00
dol_syslog(get_class($this)."::loadParentOf", LOG_DEBUG);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
$this->parentof[$obj->id_son] = $obj->id_parent;
}
return 1;
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
return -1;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2019-11-02 14:20:35 +00:00
* Build the hierarchy/tree of users into an array.
2014-10-30 10:16:45 +00:00
* Set and return this->users that is an array sorted according to tree with arrays of:
* id = id user
* lastname
* firstname
* fullname = Name with full path to user
* fullpath = Full path composed of the ids: "_grandparentid_parentid_id"
*
2014-08-11 08:50:08 +00:00
* @param int $deleteafterid Removed all users including the leaf $deleteafterid (and all its child) in user tree.
2026-04-14 16:40:54 +00:00
* @param string $filter SQL filter on users. This parameter must NOT come from user input. Must use USF syntax.
2024-03-26 13:40:42 +00:00
* @return int<-1,-1>|array<int,array{rowid:int,id:int,fk_user:int,fk_soc:int,firstname:string,lastname:string,login:string,statut:int,entity:int,email:string,gender:string|int<-1,-1>,admin:int<0,1>,photo:string,fullpath:string,fullname:string,level:int}> Array of user information (also: $this->users). Note: $this->parentof is also set.
*/
public function get_full_tree($deleteafterid = 0, $filter = '')
{
// phpcs:enable
2018-03-23 09:42:36 +00:00
global $hookmanager;
// Actions hooked (by external module)
$hookmanager->initHooks(array('userdao'));
2014-05-30 10:55:00 +00:00
$this->users = array();
// Init this->parentof that is array(id_son=>id_parent, ...)
2018-09-02 07:57:19 +00:00
$this->loadParentOf();
// Init $this->users array
$sql = "SELECT DISTINCT u.rowid, u.firstname, u.lastname, u.fk_user, u.fk_soc, u.login, u.email, u.gender, u.admin, u.statut, u.photo, u.entity"; // Distinct reduce pb with old tables with duplicates
$sql .= " FROM ".$this->db->prefix()."user as u";
2018-03-23 09:42:36 +00:00
// Add fields from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printUserListWhere', $parameters); // Note that $action and $object may have been modified by hook
2018-03-23 09:52:10 +00:00
if ($reshook > 0) {
$sql .= $hookmanager->resPrint;
2018-03-06 18:22:59 +00:00
} else {
$sql .= " WHERE u.entity IN (".getEntity('user').")";
}
2020-10-28 23:34:41 +00:00
if ($filter) {
2026-04-14 16:40:54 +00:00
$sql .= forgeSQLFromUniversalSearchCriteria($filter);
2020-10-28 23:34:41 +00:00
}
2014-06-12 09:31:53 +00:00
dol_syslog(get_class($this)."::get_full_tree get user list", LOG_DEBUG);
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$i = 0;
2020-10-28 23:34:41 +00:00
while ($obj = $this->db->fetch_object($resql)) {
$this->users[(int) $obj->rowid]
= array(
'rowid' => (int) $obj->rowid,
'id' => (int) $obj->rowid,
'fk_user' => (int) $obj->fk_user,
'fk_soc' => (int) $obj->fk_soc,
'firstname' => (string) $obj->firstname,
'lastname' => (string) $obj->lastname,
'login' => (string) $obj->login,
'statut' => (int) $obj->statut,
'entity' => (int) $obj->entity,
'email' => (string) $obj->email,
'gender' => (string) $obj->gender,
'admin' => (int) $obj->admin,
'photo' => (string) $obj->photo,
// fields are filled with build_path_from_id_user
'fullpath' => '',
'fullname' => '',
'level' => 0,
);
$i++;
}
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
return -1;
}
2024-03-15 22:14:21 +00:00
// We add the fullpath property to each element of the first level (no parent exists)
dol_syslog(get_class($this)."::get_full_tree call to build_path_from_id_user", LOG_DEBUG);
2020-10-28 23:34:41 +00:00
foreach ($this->users as $key => $val) {
$result = $this->build_path_from_id_user($key, 0); // Process a branch from the root user key (this user has no parent)
2020-10-28 23:34:41 +00:00
if ($result < 0) {
$this->error = 'ErrorLoopInHierarchy';
return -1;
}
}
2014-08-11 08:50:08 +00:00
// Exclude leaf including $deleteafterid from tree
2020-10-28 23:34:41 +00:00
if ($deleteafterid) {
2014-08-11 08:50:08 +00:00
//print "Look to discard user ".$deleteafterid."\n";
$keyfilter1 = '^'.$deleteafterid.'$';
$keyfilter2 = '_'.$deleteafterid.'$';
$keyfilter3 = '^'.$deleteafterid.'_';
$keyfilter4 = '_'.$deleteafterid.'_';
2024-03-15 22:14:21 +00:00
foreach (array_keys($this->users) as $key) {
$fullpath = (string) $this->users[$key]['fullpath'];
2024-03-15 22:14:21 +00:00
if (preg_match('/'.$keyfilter1.'/', $fullpath) || preg_match('/'.$keyfilter2.'/', $fullpath)
|| preg_match('/'.$keyfilter3.'/', $fullpath) || preg_match('/'.$keyfilter4.'/', $fullpath)) {
2023-12-04 12:53:48 +00:00
unset($this->users[$key]);
2021-07-06 17:02:03 +00:00
}
}
}
dol_syslog(get_class($this)."::get_full_tree dol_sort_array", LOG_DEBUG);
$this->users = dol_sort_array($this->users, 'fullname', 'asc', 1, 0, 1);
return $this->users;
}
/**
* Return list of all child user ids in hierarchy (all sublevels).
* Note: Calling this function also reset full list of users into $this->users.
*
* @param int<0,1> $addcurrentuser 1=Add also current user id to the list.
* @return array<int,int> Array of user id lower than user (all levels under user). This overwrites this->users.
2019-04-08 14:04:15 +00:00
* @see get_children()
*/
public function getAllChildIds($addcurrentuser = 0)
{
$childids = array();
2020-10-28 23:34:41 +00:00
if (isset($this->cache_childids[$this->id])) {
$childids = $this->cache_childids[$this->id];
2020-05-21 13:05:19 +00:00
} else {
// Init this->users
$this->get_full_tree();
$idtoscan = $this->id;
dol_syslog("Build childid for id = ".$idtoscan);
2020-10-28 23:34:41 +00:00
foreach ($this->users as $id => $val) {
if (preg_match('/_'.$idtoscan.'_/', $val['fullpath'])) {
$childids[$val['id']] = $val['id'];
}
}
}
$this->cache_childids[$this->id] = $childids;
2017-03-13 14:00:44 +00:00
2020-10-28 23:34:41 +00:00
if ($addcurrentuser) {
$childids[$this->id] = $this->id;
}
2017-03-13 14:00:44 +00:00
return $childids;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* For user id_user and its children available in this->users, define property fullpath and fullname.
* Function called by get_full_tree().
*
* @param int $id_user id_user entry to update
* @param int $protection Deep counter to avoid infinite loop (no more required, a protection is added with array useridfound)
2024-03-15 22:14:21 +00:00
* @return int<-1,1> Return integer < 0 if KO (infinite loop), >= 0 if OK
*/
public function build_path_from_id_user($id_user, $protection = 0)
{
// phpcs:enable
2020-08-17 15:40:08 +00:00
//dol_syslog(get_class($this)."::build_path_from_id_user id_user=".$id_user." protection=".$protection, LOG_DEBUG);
2020-10-28 23:34:41 +00:00
if (!empty($this->users[$id_user]['fullpath'])) {
// Already defined
dol_syslog(get_class($this)."::build_path_from_id_user fullpath and fullname already defined", LOG_WARNING);
return 0;
}
// Define fullpath and fullname
$this->users[$id_user]['fullpath'] = '_'.$id_user;
$this->users[$id_user]['fullname'] = $this->users[$id_user]['lastname'];
2023-12-04 12:53:48 +00:00
$i = 0;
$cursor_user = $id_user;
$useridfound = array($id_user);
while (!empty($this->parentof[$cursor_user]) && !empty($this->users[$this->parentof[$cursor_user]])) { // @phan-suppress-current-line PhanTypeMismatchProperty
2020-10-28 23:34:41 +00:00
if (in_array($this->parentof[$cursor_user], $useridfound)) {
dol_syslog("The hierarchy of user has a recursive loop", LOG_WARNING);
return -1; // Should not happen. Protection against looping hierarchy
}
$useridfound[] = $this->parentof[$cursor_user];
$this->users[$id_user]['fullpath'] = '_'.$this->parentof[$cursor_user].$this->users[$id_user]['fullpath'];
$this->users[$id_user]['fullname'] = $this->users[$this->parentof[$cursor_user]]['lastname'].' >> '.$this->users[$id_user]['fullname'];
2023-12-04 12:53:48 +00:00
$i++;
$cursor_user = $this->parentof[$cursor_user];
}
// We count number of _ to have level
$this->users[$id_user]['level'] = dol_strlen(preg_replace('/[^_]/i', '', $this->users[$id_user]['fullpath']));
return 1;
}
/**
* Function used to replace a thirdparty id with another one.
*
2022-12-28 12:27:13 +00:00
* @param DoliDB $dbs Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
* @param int $origin_id Old thirdparty id
* @param int $dest_id New thirdparty id
* @return bool
*/
2022-12-28 12:27:13 +00:00
public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
{
$tables = array(
2018-09-16 11:49:22 +00:00
'user',
);
2022-12-28 12:27:13 +00:00
return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
}
2016-03-17 08:22:12 +00:00
CLOSE #29244 Feature to merge contacts (#39512) Add the ability to merge two contacts, the same way third parties and members can already be merged. The merged contact is absorbed by the current one, all its satellite data is moved, then it is deleted. Contact::mergeContact() orchestrates everything in a single transaction, using the new CommonObject::commonReplaceContact() helper and the replaceContact() static methods of Contact, ActionComm and User. A replaceContact hook lets the external modules move their own data. No schema change, no migration. Three specific traps of this table are handled: - llx_element_contact.fk_socpeople references llx_socpeople only when c_type_contact.source is 'external', and llx_user when it is 'internal', so both queries filter on it. Without that filter the internal assignments of the users would silently be moved to the merged contact. - Contact::updateRoles(), called by update(), deletes then reinserts every societe_contacts row of the contact from $this->roles. It is neutralised by setting roles to null, and update() is called before the links are moved. - Every table having a unique index on the contact id is deduplicated before its update, so the update cannot violate it. $ignoreerrors is never used: the FIXME of commonReplaceThirdparty() documents the links it loses. The files are moved after the commit and not before, unlike mergeCompany() and mergeMembers(): a failure after the move leaves them with the database rolled back but the files already gone. A name collision renames the file instead of losing it, and a failure is reported to the user instead of being ignored. Access guards live in the class and not in the page, so the REST API, the scheduled jobs and the modules benefit from them too. They cover both contacts, fetch() by rowid applying neither an entity nor a permission filter: entity, private contact of another user, external user, sales representative perimeter, absorbing a shared contact into a private one, and a contact linked to a user account (moving llx_user.fk_socpeople would let the email of that user be rewritten from the contact card, so it requires the permission to create users). Form::select_contact() gets a one line fix on the way: it accepts a $filter parameter, documents it, forwards it to the ajax branch, but dropped it when building the combo, so the merge popup could not exclude the current contact. Known limitations, out of the scope of this pull request: merging contacts of different entities is refused, Contact::update() neither writes url, no_email, fk_parent nor import_key while its $nosyncuser parameter is declared but never read, and with CONTACT_USE_SEARCH_TO_SELECT set the current contact is still offered in the popup, contact/ajax/contact.php overwriting the filter it gets.
2026-08-19 00:26:34 +00:00
/**
* Function used to replace a contact id with another one when merging two contacts.
* llx_user.fk_socpeople has a unique key, so the case where both contacts are linked to a user
* is refused by Contact::mergeContact() before this method is called.
*
* @param DoliDB $dbs Database handler
* @param int $origin_id Old contact id (the contact to delete)
* @param int $dest_id New contact id (the contact that will receive elements of the other)
* @return bool True if success, False if error
*/
public static function replaceContact(DoliDB $dbs, $origin_id, $dest_id)
{
if (!CommonObject::commonReplaceContact($dbs, $origin_id, $dest_id, array('user'))) {
return false;
}
return CommonObject::commonReplaceContact($dbs, $origin_id, $dest_id, array('user_alert'), 'fk_contact');
}
2016-03-17 08:22:12 +00:00
/**
* Load metrics this->nb for dashboard
*
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
*/
2024-01-18 17:55:53 +00:00
public function loadStateBoard()
{
$this->nb = array();
2021-09-09 07:21:30 +00:00
$sql = "SELECT COUNT(DISTINCT u.rowid) as nb";
$sql .= " FROM ".$this->db->prefix()."user as u";
2023-11-27 11:08:48 +00:00
if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
$sql .= ", ".$this->db->prefix()."usergroup_user as ug";
2021-09-09 14:06:16 +00:00
$sql .= " WHERE ug.entity IN (".getEntity('usergroup').")";
$sql .= " AND ug.fk_user = u.rowid";
} else {
2021-09-09 14:06:16 +00:00
$sql .= " WHERE u.entity IN (".getEntity('user').")";
}
$sql .= " AND u.statut > 0";
//$sql.= " AND employee != 0";
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
$this->nb["users"] = $obj->nb;
}
$this->db->free($resql);
return 1;
2020-05-21 13:05:19 +00:00
} else {
dol_print_error($this->db);
$this->error = $this->db->error();
return -1;
}
}
2016-03-17 08:22:12 +00:00
2017-03-02 14:13:42 +00:00
/**
* Create a document onto disk according to template module.
*
* @param string $modele Force model to use ('' to not force)
* @param Translate $outputlangs Object langs to use for output
* @param int<0,1> $hidedetails Hide details of lines
* @param int<0,1> $hidedesc Hide description
* @param int<0,1> $hideref Hide ref
* @param ?array<string,mixed> $moreparams Array to provide more information
2017-03-02 14:13:42 +00:00
* @return int 0 if KO, 1 if OK
*/
public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2017-03-02 14:13:42 +00:00
{
2025-09-18 14:26:38 +00:00
global $langs;
2017-03-02 14:13:42 +00:00
$langs->load("user");
// Set the '$modele' to the name of the document template (model) to use
2020-10-28 23:34:41 +00:00
if (!dol_strlen($modele)) {
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('USER_ADDON_PDF')) {
2024-01-05 03:18:53 +00:00
$modele = getDolGlobalString('USER_ADDON_PDF');
2020-05-21 13:05:19 +00:00
} else {
2017-03-02 14:13:42 +00:00
$modele = 'bluesky';
}
}
$modelpath = "core/modules/user/doc/";
return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2017-03-02 14:13:42 +00:00
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2018-03-21 10:48:30 +00:00
/**
2018-03-21 22:03:22 +00:00
* Return property of user from its id
2018-03-21 10:48:30 +00:00
*
* @param int $rowid id of contact
* @param string $mode 'email', 'mobile', or 'name'
2018-03-21 22:03:22 +00:00
* @return string Email of user with format: "Full name <email>"
2018-03-21 10:48:30 +00:00
*/
2019-02-25 19:35:59 +00:00
public function user_get_property($rowid, $mode)
2018-03-21 10:48:30 +00:00
{
// phpcs:enable
$user_property = '';
2018-03-21 10:48:30 +00:00
2020-10-28 23:34:41 +00:00
if (empty($rowid)) {
return '';
}
2018-03-21 10:48:30 +00:00
$sql = "SELECT rowid, email, user_mobile, civility, lastname, firstname";
$sql .= " FROM ".$this->db->prefix()."user";
2020-09-20 01:36:02 +00:00
$sql .= " WHERE rowid = ".((int) $rowid);
2018-03-21 10:48:30 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
2018-03-21 10:48:30 +00:00
$nump = $this->db->num_rows($resql);
2020-10-28 23:34:41 +00:00
if ($nump) {
2018-03-21 10:48:30 +00:00
$obj = $this->db->fetch_object($resql);
2020-10-28 23:34:41 +00:00
if ($mode == 'email') {
$user_property = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
} elseif ($mode == 'mobile') {
$user_property = $obj->user_mobile;
} elseif ($mode == 'name') {
$user_property = dolGetFirstLastname($obj->firstname, $obj->lastname);
2020-10-28 23:34:41 +00:00
}
2018-03-21 10:48:30 +00:00
}
return $user_property;
2020-05-21 13:05:19 +00:00
} else {
2018-03-21 10:48:30 +00:00
dol_print_error($this->db);
}
2023-05-01 15:21:00 +00:00
return '';
2018-03-21 10:48:30 +00:00
}
2023-01-07 03:05:59 +00:00
/**
* Return string with full Url to virtual card
*
2023-01-07 11:36:53 +00:00
* @param string $mode Mode for link
2023-03-13 15:28:58 +00:00
* @param string $typeofurl 'external' or 'internal'
2023-01-07 11:36:53 +00:00
* @return string Url string link
2023-01-07 03:05:59 +00:00
*/
2023-03-13 15:28:58 +00:00
public function getOnlineVirtualCardUrl($mode = '', $typeofurl = 'external')
2023-01-07 03:05:59 +00:00
{
2023-05-03 10:01:36 +00:00
global $dolibarr_main_url_root;
2023-01-07 03:05:59 +00:00
global $conf;
2026-08-15 16:17:19 +00:00
$instanceuniqueid = empty($conf->file->instance_unique_id) ? '' : $conf->file->instance_unique_id;
$encodedsecurekey = dol_hash($instanceuniqueid.'uservirtualcard'.$this->id.'-'.$this->login, 'md5');
2023-01-07 03:05:59 +00:00
if (isModEnabled('multicompany')) {
$entity_qr = '&entity='.((int) $conf->entity);
} else {
$entity_qr = '';
}
// Define $urlwithroot
$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
2023-03-13 15:28:58 +00:00
if ($typeofurl == 'internal') {
$urlwithroot = DOL_URL_ROOT;
}
2023-01-07 11:36:53 +00:00
return $urlwithroot.'/public/users/view.php?id='.$this->id.'&securekey='.$encodedsecurekey.$entity_qr.($mode ? '&mode='.urlencode($mode) : '');
2023-01-07 03:05:59 +00:00
}
2018-03-21 10:48:30 +00:00
/**
2018-03-21 22:03:22 +00:00
* Load all objects into $this->users
2018-03-21 10:48:30 +00:00
*
2018-11-27 15:39:08 +00:00
* @param string $sortorder sort order
* @param string $sortfield sort field
* @param int $limit limit page
* @param int $offset page
* @param string $filter Filter as an Universal Search string.
* Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
* @param string $filtermode No more used
* @param bool $entityfilter Activate entity filter
2023-12-01 18:51:32 +00:00
* @return int Return integer <0 if KO, >0 if OK
2018-03-21 10:48:30 +00:00
*/
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND', $entityfilter = false)
{
global $conf, $user;
2018-03-21 10:48:30 +00:00
$sql = "SELECT t.rowid";
$sql .= ' FROM '.$this->db->prefix().$this->table_element.' as t ';
2020-10-28 23:34:41 +00:00
if ($entityfilter) {
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
if (!empty($user->admin) && empty($user->entity) && $conf->entity == 1) {
$sql .= " WHERE t.entity IS NOT NULL"; // Show all users
} else {
$sql .= " WHERE t.entity = 0 OR EXISTS (";
$sql .= " SELECT ug.rowid FROM " . $this->db->prefix() . "usergroup_user as ug";
$sql .= " WHERE ug.fk_user = t.rowid AND ug.entity IN (" . getEntity('usergroup') . "))";
}
2020-05-21 13:05:19 +00:00
} else {
$sql .= " WHERE t.entity IN (".getEntity('user').")";
}
2020-05-21 13:05:19 +00:00
} else {
2021-05-05 09:49:11 +00:00
$sql .= " WHERE 1 = 1";
}
2018-03-21 10:48:30 +00:00
2018-11-27 15:39:08 +00:00
// Manage filter
$errormessage = '';
$sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
if ($errormessage) {
$this->errors[] = $errormessage;
Qual: Fix and enable alias deprecation detection (#28716) * Qual: Ignore some false positives for deprecated functions # Qual: Ignore some false positives for deprecated functions The Phan Deprecation Plugin for internal functions has mixed up some mail functions and lists them as deprecated, this ignores that * Qual: Enable detection and fixing of internal deprecations * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Replace 'join' with 'implode' * Qual: Update codespell lines ignore list after format # Qual: Update codespell lines ignore list after forma Done using latest library, so also adds some exceptions that are needed in the future; --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2024-03-08 20:34:18 +00:00
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
return -1;
2018-11-27 15:39:08 +00:00
}
$sql .= $this->db->order($sortfield, $sortorder);
2020-10-28 23:34:41 +00:00
if ($limit) {
$sql .= $this->db->plimit($limit + 1, $offset);
}
2018-03-21 10:48:30 +00:00
dol_syslog(__METHOD__, LOG_DEBUG);
2018-03-21 10:48:30 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if ($resql) {
$this->users = array();
2018-03-21 10:48:30 +00:00
$num = $this->db->num_rows($resql);
2020-10-28 23:34:41 +00:00
if ($num) {
while ($obj = $this->db->fetch_object($resql)) {
2018-03-21 10:48:30 +00:00
$line = new self($this->db);
$result = $line->fetch($obj->rowid);
if ($result > 0 && !empty($line->id)) {
2018-03-21 10:48:30 +00:00
$this->users[$obj->rowid] = clone $line;
}
}
$this->db->free($resql);
}
return $num;
2020-05-21 13:05:19 +00:00
} else {
$this->errors[] = $this->db->lasterror();
return -1;
}
2020-08-21 06:18:26 +00:00
}
/**
* Cache the SQL results of the function "findUserIdByEmail($email)"
2020-08-25 10:20:48 +00:00
*
2020-08-25 10:16:44 +00:00
* NOTE: findUserIdByEmailCache[...] === -1 means not found in database
2020-08-25 10:20:48 +00:00
*
* @var array<string,int<-1,max>>
2020-08-21 06:18:26 +00:00
*/
private $findUserIdByEmailCache;
/**
2020-08-25 10:16:44 +00:00
* Find a user by the given e-mail and return it's user id when found
*
* NOTE:
* Use AGENDA_DISABLE_EXACT_USER_EMAIL_COMPARE_FOR_EXTERNAL_CALENDAR
* to disable exact e-mail search
2020-08-21 06:18:26 +00:00
*
2020-08-25 10:16:44 +00:00
* @param string $email The full e-mail (or a part of a e-mail)
2023-12-06 14:46:39 +00:00
* @return int Return integer <0 = user was not found, >0 = The id of the user
2020-08-21 06:18:26 +00:00
*/
public function findUserIdByEmail($email)
{
2022-04-30 18:41:18 +00:00
if (isset($this->findUserIdByEmailCache[$email])) {
2020-08-21 06:18:26 +00:00
return $this->findUserIdByEmailCache[$email];
}
2020-08-25 10:16:44 +00:00
$this->findUserIdByEmailCache[$email] = -1;
2020-08-21 06:18:26 +00:00
$sql = 'SELECT rowid';
$sql .= ' FROM '.$this->db->prefix().'user';
2023-11-27 11:08:48 +00:00
if (getDolGlobalString('AGENDA_DISABLE_EXACT_USER_EMAIL_COMPARE_FOR_EXTERNAL_CALENDAR')) {
2024-02-16 00:19:53 +00:00
$sql .= " WHERE email LIKE '%".$this->db->escape($this->db->escapeforlike($email))."%'";
2020-10-28 23:34:41 +00:00
} else {
2021-08-28 01:09:18 +00:00
$sql .= " WHERE email = '".$this->db->escape($email)."'";
2020-08-25 10:16:44 +00:00
}
$sql .= ' LIMIT 1';
2020-08-21 06:18:26 +00:00
$resql = $this->db->query($sql);
2020-10-28 23:34:41 +00:00
if (!$resql) {
2020-08-25 10:16:44 +00:00
return -1;
2020-08-21 06:18:26 +00:00
}
$obj = $this->db->fetch_object($resql);
2020-10-28 23:34:41 +00:00
if (!$obj) {
2020-08-25 10:16:44 +00:00
return -1;
2018-03-21 10:48:30 +00:00
}
2020-08-21 06:18:26 +00:00
2020-08-25 10:16:44 +00:00
$this->findUserIdByEmailCache[$email] = (int) $obj->rowid;
2020-08-21 06:18:26 +00:00
2020-08-25 10:16:44 +00:00
return $this->findUserIdByEmailCache[$email];
2020-08-21 06:18:26 +00:00
}
/**
* Clone permissions of user
* @param int $fromId User ID from whom to clone rights
* @param int $toId User ID
* @return int Return integer<0 if KO, >0 if OK
*/
public function cloneRights($fromId, $toId)
{
if (empty($fromId) || empty($toId)) {
return -1;
}
$this->db->begin();
// delete default rights for UserTo
$sqlDelete = "DELETE FROM ".$this->db->prefix()."user_rights";
$sqlDelete .= " WHERE fk_user = ".((int) $toId);
dol_syslog(get_class($this)."::clone_rights (delete default permissions)", LOG_DEBUG);
if (!$this->db->query($sqlDelete)) {
$this->db->rollback();
return -1;
}
// Construction of the insertion request
$sql = "INSERT INTO ".$this->db->prefix()."user_rights (entity, fk_user, fk_id)";
$sql .= " SELECT entity, ".((int) $toId).", fk_id";
$sql .= " FROM ".$this->db->prefix()."user_rights src";
$sql .= " WHERE fk_user = ".((int) $fromId);
$sql .= " AND NOT EXISTS (";
$sql .= " SELECT 1";
$sql .= " FROM ".$this->db->prefix()."user_rights dest";
$sql .= " WHERE dest.entity = src.entity";
$sql .= " AND dest.fk_user = ".((int) $toId);
$sql .= " AND dest.fk_id = src.fk_id";
$sql .= " )";
dol_syslog(get_class($this)."::clone_rights", LOG_DEBUG);
// Execute request
if (!$this->db->query($sql)) {
$this->db->rollback();
return -1;
}
$this->db->commit();
return 1;
}
/**
* Copy related categories to another object
*
* @param int $fromId Id user source
* @param int $toId Id user cible
* @param string $type Type of category ('user', ...)
* @return int Return integer < 0 if error, > 0 if ok
*/
public function cloneCategories($fromId, $toId, $type = 'user')
{
$this->db->begin();
if (empty($type)) {
$type = $this->table_element;
}
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
$categorystatic = new Categorie($this->db);
$sql = "INSERT INTO ".$this->db->prefix()."categorie_".(empty($categorystatic->MAP_CAT_TABLE[$type]) ? $type : $categorystatic->MAP_CAT_TABLE[$type])." (fk_categorie, fk_user)";
$sql .= " SELECT fk_categorie, ".((int) $toId)." FROM ".$this->db->prefix()."categorie_".(empty($categorystatic->MAP_CAT_TABLE[$type]) ? $type : $categorystatic->MAP_CAT_TABLE[$type]);
$sql .= " WHERE fk_user = ".((int) $fromId);
if (!$this->db->query($sql)) {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
$this->db->commit();
return 1;
}
2002-04-30 10:51:35 +00:00
}