From 5152a060ccdb8bdc27be3d831a20fa0de3f05136 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 14 Feb 2022 04:06:25 +0100 Subject: [PATCH 001/421] NEW Asset module - New structure --- .../install/mysql/migration/15.0.0-16.0.0.sql | 215 ++++++++++++++++++ .../mysql/tables/llx_asset-asset.key.sql | 17 +- .../install/mysql/tables/llx_asset-asset.sql | 61 +++-- ...t_accountancy_codes_economic-asset.key.sql | 24 ++ ...asset_accountancy_codes_economic-asset.sql | 33 +++ ...set_accountancy_codes_fiscal-asset.key.sql | 24 ++ ...x_asset_accountancy_codes_fiscal-asset.sql | 29 +++ .../llx_asset_depreciation-asset.key.sql | 25 ++ .../tables/llx_asset_depreciation-asset.sql | 34 +++ ...epreciation_options_economic-asset.key.sql | 24 ++ ...et_depreciation_options_economic-asset.sql | 35 +++ ..._depreciation_options_fiscal-asset.key.sql | 24 ++ ...sset_depreciation_options_fiscal-asset.sql | 34 +++ .../llx_asset_extrafields-asset.key.sql | 1 - .../tables/llx_asset_extrafields-asset.sql | 3 +- .../tables/llx_asset_model-asset.key.sql | 25 ++ .../mysql/tables/llx_asset_model-asset.sql | 33 +++ ... llx_asset_model_extrafield-asset.key.sql} | 6 +- ...l => llx_asset_model_extrafield-asset.sql} | 15 +- .../mysql/tables/llx_asset_type-asset.sql | 26 --- .../llx_asset_type_extrafields-asset.key.sql | 17 -- .../llx_c_asset_disposal_type-asset.key.sql | 18 ++ .../llx_c_asset_disposal_type-asset.sql | 25 ++ 23 files changed, 668 insertions(+), 80 deletions(-) create mode 100644 htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_model-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_asset_model-asset.sql rename htdocs/install/mysql/tables/{llx_asset_type-asset.key.sql => llx_asset_model_extrafield-asset.key.sql} (67%) rename htdocs/install/mysql/tables/{llx_asset_type_extrafields-asset.sql => llx_asset_model_extrafield-asset.sql} (54%) delete mode 100644 htdocs/install/mysql/tables/llx_asset_type-asset.sql delete mode 100644 htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.key.sql create mode 100644 htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index b78e53bd287..40ecda6c3fe 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -237,4 +237,219 @@ ALTER TABLE llx_advtargetemailing RENAME TO llx_mailing_advtarget; ALTER TABLE llx_mailing ADD UNIQUE uk_mailing(titre, entity); +-- Assets - New module +ALTER TABLE llx_asset DROP FOREIGN KEY fk_asset_asset_type; +ALTER TABLE llx_asset DROP INDEX idx_asset_fk_asset_type; + +ALTER TABLE llx_asset CHANGE COLUMN amount_ht acquisition_value_ht double(24,8) NOT NULL; +ALTER TABLE llx_asset CHANGE COLUMN amount_vat recovered_vat double(24,8); + +DELETE FROM llx_asset WHERE fk_asset_type IS NOT NULL; + +ALTER TABLE llx_asset DROP COLUMN fk_asset_type; +ALTER TABLE llx_asset DROP COLUMN description; + +ALTER TABLE llx_asset ADD COLUMN fk_asset_model integer AFTER label; +ALTER TABLE llx_asset ADD COLUMN reversal_amount_ht double(24,8) AFTER fk_asset_model; +ALTER TABLE llx_asset ADD COLUMN reversal_date date AFTER recovered_vat; +ALTER TABLE llx_asset ADD COLUMN date_acquisition date NOT NULL AFTER reversal_date; +ALTER TABLE llx_asset ADD COLUMN date_start date NOT NULL AFTER date_acquisition; +ALTER TABLE llx_asset ADD COLUMN qty real DEFAULT 1 NOT NULL AFTER date_start; +ALTER TABLE llx_asset ADD COLUMN acquisition_type smallint DEFAULT 0 NOT NULL AFTER qty; +ALTER TABLE llx_asset ADD COLUMN asset_type smallint DEFAULT 0 NOT NULL AFTER acquisition_type; +ALTER TABLE llx_asset ADD COLUMN not_depreciated integer(1) DEFAULT 0 AFTER asset_type; +ALTER TABLE llx_asset ADD COLUMN disposal_date date AFTER not_depreciated; +ALTER TABLE llx_asset ADD COLUMN disposal_amount_ht double(24,8) AFTER disposal_date; +ALTER TABLE llx_asset ADD COLUMN fk_disposal_type integer AFTER disposal_amount_ht; +ALTER TABLE llx_asset ADD COLUMN disposal_depreciated integer(1) DEFAULT 0 AFTER fk_disposal_type; +ALTER TABLE llx_asset ADD COLUMN disposal_subject_to_vat integer(1) DEFAULT 0 AFTER disposal_depreciated; +ALTER TABLE llx_asset ADD COLUMN last_main_doc varchar(255) AFTER fk_user_modif; +ALTER TABLE llx_asset ADD COLUMN model_pdf varchar(255) AFTER import_key; + +DROP TABLE llx_asset_type; + +CREATE TABLE llx_c_asset_disposal_type +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer NOT NULL DEFAULT 1, + code varchar(16) NOT NULL, + label varchar(50) NOT NULL, + active integer DEFAULT 1 NOT NULL +)ENGINE=innodb; + +CREATE TABLE llx_asset_accountancy_codes_economic( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + asset varchar(32), + depreciation_asset varchar(32), + depreciation_expense varchar(32), + value_asset_sold varchar(32), + receivable_on_assignment varchar(32), + proceeds_from_sales varchar(32), + vat_collected varchar(32), + vat_deductible varchar(32), + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; + +CREATE TABLE llx_asset_accountancy_codes_fiscal( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + accelerated_depreciation varchar(32), + endowment_accelerated_depreciation varchar(32), + provision_accelerated_depreciation varchar(32), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; + +CREATE TABLE llx_asset_depreciation_options_economic( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional + accelerated_depreciation_option integer(1), -- activate accelerated depreciation mode (fiscal) + + degressive_coefficient double(24,8), + duration smallint NOT NULL, + duration_type smallint DEFAULT 0 NOT NULL, -- 0:annual, 1:monthly, 2:daily + + amount_base_depreciation_ht double(24,8), + amount_base_deductible_ht double(24,8), + total_amount_last_depreciation_ht double(24,8), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; + +CREATE TABLE llx_asset_depreciation_options_fiscal( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional + + degressive_coefficient double(24,8), + duration smallint NOT NULL, + duration_type smallint DEFAULT 0 NOT NULL, -- 0:annual, 1:monthly, 2:daily + + amount_base_depreciation_ht double(24,8), + amount_base_deductible_ht double(24,8), + total_amount_last_depreciation_ht double(24,8), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; + +CREATE TABLE llx_asset_depreciation( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + + fk_asset integer NOT NULL, + depreciation_mode varchar(255) NOT NULL, -- (economic, fiscal or other) + + ref varchar(255) NOT NULL, + depreciation_date datetime NOT NULL, + depreciation_ht double(24,8) NOT NULL, + cumulative_depreciation_ht double(24,8) NOT NULL, + + accountancy_code_debit varchar(32), + accountancy_code_credit varchar(32), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; + +CREATE TABLE llx_asset_model( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + ref varchar(128) NOT NULL, + label varchar(255) NOT NULL, + + asset_type smallint NOT NULL, + fk_pays integer DEFAULT 0, + + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status smallint NOT NULL +) ENGINE=innodb; + +CREATE TABLE llx_asset_model_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + +ALTER TABLE llx_c_asset_disposal_type ADD UNIQUE INDEX uk_c_asset_disposal_type(code, entity); + +ALTER TABLE llx_asset ADD INDEX idx_asset_fk_asset_model (fk_asset_model); +ALTER TABLE llx_asset ADD INDEX idx_asset_fk_disposal_type (fk_disposal_type); + +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_disposal_type FOREIGN KEY (fk_disposal_type) REFERENCES llx_c_asset_disposal_type (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_accountancy_codes_economic ADD INDEX idx_asset_ace_rowid (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD UNIQUE uk_asset_ace_fk_asset (fk_asset); +ALTER TABLE llx_asset_accountancy_codes_economic ADD UNIQUE uk_asset_ace_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD INDEX idx_asset_acf_rowid (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD UNIQUE uk_asset_acf_fk_asset (fk_asset); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD UNIQUE uk_asset_acf_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_depreciation_options_economic ADD INDEX idx_asset_doe_rowid (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD UNIQUE uk_asset_doe_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation_options_economic ADD UNIQUE uk_asset_doe_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_depreciation_options_fiscal ADD INDEX idx_asset_dof_rowid (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD UNIQUE uk_asset_dof_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD UNIQUE uk_asset_dof_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_rowid (rowid); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_depreciation_mode (depreciation_mode); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_ref (ref); +ALTER TABLE llx_asset_depreciation ADD UNIQUE uk_asset_depreciation_fk_asset (fk_asset, depreciation_mode, ref); + +ALTER TABLE llx_asset_depreciation ADD CONSTRAINT fk_asset_depreciation_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation ADD CONSTRAINT fk_asset_depreciation_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_rowid (rowid); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_ref (ref); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_pays (fk_pays); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_entity (entity); +ALTER TABLE llx_asset_model ADD UNIQUE INDEX uk_asset_model (entity, ref); + +ALTER TABLE llx_asset_model ADD CONSTRAINT fk_asset_model_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid); +ALTER TABLE llx_asset_model ADD CONSTRAINT fk_asset_model_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); + +ALTER TABLE llx_asset_model_extrafields ADD INDEX idx_asset_model_extrafields (fk_object); diff --git a/htdocs/install/mysql/tables/llx_asset-asset.key.sql b/htdocs/install/mysql/tables/llx_asset-asset.key.sql index a82f29ee58b..6175ed8a2b7 100644 --- a/htdocs/install/mysql/tables/llx_asset-asset.key.sql +++ b/htdocs/install/mysql/tables/llx_asset-asset.key.sql @@ -1,4 +1,5 @@ --- Copyright (C) 2018 Alexandre Spangaro +-- ======================================================================== +-- Copyright (C) 2018-2022 OpenDSI -- -- 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 @@ -12,12 +13,12 @@ -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== +ALTER TABLE llx_asset ADD INDEX idx_asset_fk_asset_model (fk_asset_model); +ALTER TABLE llx_asset ADD INDEX idx_asset_fk_disposal_type (fk_disposal_type); -ALTER TABLE llx_asset ADD INDEX idx_asset_rowid (rowid); -ALTER TABLE llx_asset ADD INDEX idx_asset_ref (ref); -ALTER TABLE llx_asset ADD INDEX idx_asset_entity (entity); - -ALTER TABLE llx_asset ADD INDEX idx_asset_fk_asset_type (fk_asset_type); -ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_asset_type FOREIGN KEY (fk_asset_type) REFERENCES llx_asset_type (rowid); - +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_disposal_type FOREIGN KEY (fk_disposal_type) REFERENCES llx_c_asset_disposal_type (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid); +ALTER TABLE llx_asset ADD CONSTRAINT fk_asset_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset-asset.sql b/htdocs/install/mysql/tables/llx_asset-asset.sql index 52eeda3ba58..0366c306ac8 100644 --- a/htdocs/install/mysql/tables/llx_asset-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset-asset.sql @@ -1,4 +1,5 @@ --- Copyright (C) 2018 Alexandre Spangaro +-- ======================================================================== +-- Copyright (C) 2018-2022 OpenDSI -- -- 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 @@ -12,23 +13,47 @@ -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see https://www.gnu.org/licenses/. - +-- ======================================================================== CREATE TABLE llx_asset( - rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, - ref varchar(128) NOT NULL, - entity integer DEFAULT 1 NOT NULL, - label varchar(255), - amount_ht double(24,8) DEFAULT NULL, - amount_vat double(24,8) DEFAULT NULL, - fk_asset_type integer NOT NULL, - description text, - note_public text, - note_private text, - date_creation datetime NOT NULL, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_user_creat integer NOT NULL, - fk_user_modif integer, - import_key varchar(14), - status integer NOT NULL + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) NOT NULL, + entity integer DEFAULT 1 NOT NULL, + label varchar(255), + + fk_asset_model integer, + + reversal_amount_ht double(24,8), + acquisition_value_ht double(24,8) DEFAULT NULL, + recovered_vat double(24,8), + + reversal_date date, + + date_acquisition date NOT NULL, + date_start date NOT NULL, + + qty real DEFAULT 1 NOT NULL, + + acquisition_type smallint DEFAULT 0 NOT NULL, + asset_type smallint DEFAULT 0 NOT NULL, + + not_depreciated integer DEFAULT 0, + + disposal_date date, + disposal_amount_ht double(24,8), + fk_disposal_type integer, + disposal_depreciated integer DEFAULT 0, + disposal_subject_to_vat integer DEFAULT 0, + + note_public text, + note_private text, + + date_creation datetime NOT NULL, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + last_main_doc varchar(255), + import_key varchar(14), + model_pdf varchar(255), + status integer NOT NULL ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.key.sql new file mode 100644 index 00000000000..69bc6754f65 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.key.sql @@ -0,0 +1,24 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_asset_accountancy_codes_economic ADD INDEX idx_asset_ace_rowid (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD UNIQUE uk_asset_ace_fk_asset (fk_asset); +ALTER TABLE llx_asset_accountancy_codes_economic ADD UNIQUE uk_asset_ace_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_accountancy_codes_economic ADD CONSTRAINT fk_asset_ace_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql new file mode 100644 index 00000000000..013b70ef1e9 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql @@ -0,0 +1,33 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_asset_accountancy_codes_economic( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + asset varchar(32), + depreciation_asset varchar(32), + depreciation_expense varchar(32), + value_asset_sold varchar(32), + receivable_on_assignment varchar(32), + proceeds_from_sales varchar(32), + vat_collected varchar(32), + vat_deductible varchar(32), + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.key.sql new file mode 100644 index 00000000000..f7a4109b9fa --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.key.sql @@ -0,0 +1,24 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD INDEX idx_asset_acf_rowid (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD UNIQUE uk_asset_acf_fk_asset (fk_asset); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD UNIQUE uk_asset_acf_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_accountancy_codes_fiscal ADD CONSTRAINT fk_asset_acf_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql new file mode 100644 index 00000000000..9ab80facab0 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql @@ -0,0 +1,29 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_asset_accountancy_codes_fiscal( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + accelerated_depreciation varchar(32), + endowment_accelerated_depreciation varchar(32), + provision_accelerated_depreciation varchar(32), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.key.sql new file mode 100644 index 00000000000..531f88d72ba --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.key.sql @@ -0,0 +1,25 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_rowid (rowid); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_depreciation_mode (depreciation_mode); +ALTER TABLE llx_asset_depreciation ADD INDEX idx_asset_depreciation_ref (ref); +ALTER TABLE llx_asset_depreciation ADD UNIQUE uk_asset_depreciation_fk_asset (fk_asset, depreciation_mode, ref); + +ALTER TABLE llx_asset_depreciation ADD CONSTRAINT fk_asset_depreciation_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation ADD CONSTRAINT fk_asset_depreciation_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql new file mode 100644 index 00000000000..5171f3ca6f2 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql @@ -0,0 +1,34 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_asset_depreciation( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + + fk_asset integer NOT NULL, + depreciation_mode varchar(255) NOT NULL, -- (economic, fiscal or other) + + ref varchar(255) NOT NULL, + depreciation_date datetime NOT NULL, + depreciation_ht double(24,8) NOT NULL, + cumulative_depreciation_ht double(24,8) NOT NULL, + + accountancy_code_debit varchar(32), + accountancy_code_credit varchar(32), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.key.sql new file mode 100644 index 00000000000..569e4f286a2 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.key.sql @@ -0,0 +1,24 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_asset_depreciation_options_economic ADD INDEX idx_asset_doe_rowid (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD UNIQUE uk_asset_doe_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation_options_economic ADD UNIQUE uk_asset_doe_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_depreciation_options_economic ADD CONSTRAINT fk_asset_doe_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql new file mode 100644 index 00000000000..1e0028ebaf2 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql @@ -0,0 +1,35 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_asset_depreciation_options_economic( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional + accelerated_depreciation_option integer(1), -- activate accelerated depreciation mode (fiscal) + degressive_coefficient double(24,8), + duration smallint NOT NULL, + duration_type smallint DEFAULT 0 NOT NULL, -- 0:annual, 1:monthly, 2:daily + + amount_base_depreciation_ht double(24,8), + amount_base_deductible_ht double(24,8), + total_amount_last_depreciation_ht double(24,8), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.key.sql new file mode 100644 index 00000000000..1fb678696d1 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.key.sql @@ -0,0 +1,24 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_asset_depreciation_options_fiscal ADD INDEX idx_asset_dof_rowid (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD UNIQUE uk_asset_dof_fk_asset (fk_asset); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD UNIQUE uk_asset_dof_fk_asset_model (fk_asset_model); + +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_asset FOREIGN KEY (fk_asset) REFERENCES llx_asset (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_asset_model FOREIGN KEY (fk_asset_model) REFERENCES llx_asset_model (rowid); +ALTER TABLE llx_asset_depreciation_options_fiscal ADD CONSTRAINT fk_asset_dof_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql new file mode 100644 index 00000000000..ef2346ace5e --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql @@ -0,0 +1,34 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_asset_depreciation_options_fiscal( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_asset integer, + fk_asset_model integer, + + depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional + degressive_coefficient double(24,8), + duration smallint NOT NULL, + duration_type smallint DEFAULT 0 NOT NULL, -- 0:annual, 1:monthly, 2:daily + + amount_base_depreciation_ht double(24,8), + amount_base_deductible_ht double(24,8), + total_amount_last_depreciation_ht double(24,8), + + tms timestamp, + fk_user_modif integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql index fe6bb053ed6..5671e2a5b9f 100644 --- a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql +++ b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.key.sql @@ -16,5 +16,4 @@ -- -- =================================================================== - ALTER TABLE llx_asset_extrafields ADD INDEX idx_asset_extrafields (fk_object); diff --git a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql index c93fac7b20a..1b111d89ca0 100644 --- a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql @@ -1,3 +1,4 @@ +-- =================================================================== -- Copyright (C) 2018 Alexandre Spangaro -- -- This program is free software; you can redistribute it and/or modify @@ -12,6 +13,7 @@ -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see https://www.gnu.org/licenses/. +-- =================================================================== create table llx_asset_extrafields ( @@ -20,4 +22,3 @@ create table llx_asset_extrafields fk_object integer NOT NULL, import_key varchar(14) -- import key ) ENGINE=innodb; - diff --git a/htdocs/install/mysql/tables/llx_asset_model-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_model-asset.key.sql new file mode 100644 index 00000000000..5c301e5c147 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_model-asset.key.sql @@ -0,0 +1,25 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see . +-- ======================================================================== + +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_rowid (rowid); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_entity (entity); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_ref (ref); +ALTER TABLE llx_asset_model ADD INDEX idx_asset_model_pays (fk_pays); +ALTER TABLE llx_asset_model ADD UNIQUE INDEX uk_asset_model (entity, ref); + +ALTER TABLE llx_asset_model ADD CONSTRAINT fk_asset_model_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user (rowid); +ALTER TABLE llx_asset_model ADD CONSTRAINT fk_asset_model_user_modif FOREIGN KEY (fk_user_modif) REFERENCES llx_user (rowid); diff --git a/htdocs/install/mysql/tables/llx_asset_model-asset.sql b/htdocs/install/mysql/tables/llx_asset_model-asset.sql new file mode 100644 index 00000000000..576d794f54a --- /dev/null +++ b/htdocs/install/mysql/tables/llx_asset_model-asset.sql @@ -0,0 +1,33 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see . +-- ======================================================================== + +CREATE TABLE llx_asset_model( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + ref varchar(128) NOT NULL, + label varchar(255) NOT NULL, + asset_type smallint NOT NULL, + fk_pays integer DEFAULT 0, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status smallint NOT NULL +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_type-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.key.sql similarity index 67% rename from htdocs/install/mysql/tables/llx_asset_type-asset.key.sql rename to htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.key.sql index 4a7c4cb1145..22a6ee89196 100644 --- a/htdocs/install/mysql/tables/llx_asset_type-asset.key.sql +++ b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.key.sql @@ -1,4 +1,5 @@ --- Copyright (C) 2018 Alexandre Spangaro +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI -- -- 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 @@ -12,5 +13,6 @@ -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- ======================================================================== -ALTER TABLE llx_asset_type ADD UNIQUE INDEX uk_asset_type_label (label, entity); +ALTER TABLE llx_asset_model_extrafields ADD INDEX idx_asset_model_extrafields (fk_object); diff --git a/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.sql b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql similarity index 54% rename from htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.sql rename to htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql index 7ff09176216..007f4fa76ec 100644 --- a/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql @@ -1,4 +1,5 @@ --- Copyright (C) 2018 Alexandre Spangaro +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI -- -- 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 @@ -12,12 +13,12 @@ -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- ======================================================================== -create table llx_asset_type_extrafields +CREATE TABLE llx_asset_model_extrafields ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, - import_key varchar(14) -- import key + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_object integer NOT NULL, + import_key varchar(14) -- import key ) ENGINE=innodb; - diff --git a/htdocs/install/mysql/tables/llx_asset_type-asset.sql b/htdocs/install/mysql/tables/llx_asset_type-asset.sql deleted file mode 100644 index 1205acb959b..00000000000 --- a/htdocs/install/mysql/tables/llx_asset_type-asset.sql +++ /dev/null @@ -1,26 +0,0 @@ --- Copyright (C) 2018 Alexandre Spangaro --- --- 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 --- (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 --- along with this program. If not, see . - -create table llx_asset_type -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - entity integer DEFAULT 1 NOT NULL, -- multi company id - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - label varchar(50) NOT NULL, - accountancy_code_asset varchar(32), - accountancy_code_depreciation_asset varchar(32), - accountancy_code_depreciation_expense varchar(32), - note text -)ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql b/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql deleted file mode 100644 index ec0b4b28619..00000000000 --- a/htdocs/install/mysql/tables/llx_asset_type_extrafields-asset.key.sql +++ /dev/null @@ -1,17 +0,0 @@ --- Copyright (C) 2018 Alexandre Spangaro --- --- 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 --- (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 --- along with this program. If not, see . - - -ALTER TABLE llx_asset_type_extrafields ADD INDEX idx_asset_type_extrafields (fk_object); diff --git a/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.key.sql b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.key.sql new file mode 100644 index 00000000000..3f588dc506d --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.key.sql @@ -0,0 +1,18 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +ALTER TABLE llx_c_asset_disposal_type ADD UNIQUE INDEX uk_c_asset_disposal_type(code, entity); diff --git a/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql new file mode 100644 index 00000000000..c3c103850b3 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql @@ -0,0 +1,25 @@ +-- ======================================================================== +-- Copyright (C) 2022 OpenDSI +-- +-- 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 +-- (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 +-- along with this program. If not, see https://www.gnu.org/licenses/. +-- ======================================================================== + +CREATE TABLE llx_c_asset_disposal_type +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer NOT NULL DEFAULT 1, + code varchar(16) NOT NULL, + label varchar(50) NOT NULL, + active integer DEFAULT 1 NOT NULL +)ENGINE=innodb; From 636a01725ee9feff5ac2286671087c19ee955ed1 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 14 Feb 2022 04:11:11 +0100 Subject: [PATCH 002/421] Remove integer(1) --- htdocs/install/mysql/migration/15.0.0-16.0.0.sql | 8 ++++---- .../llx_asset_depreciation_options_economic-asset.sql | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 40ecda6c3fe..8182cc44d39 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -257,12 +257,12 @@ ALTER TABLE llx_asset ADD COLUMN date_start date NOT NULL AFTER date_acquisition ALTER TABLE llx_asset ADD COLUMN qty real DEFAULT 1 NOT NULL AFTER date_start; ALTER TABLE llx_asset ADD COLUMN acquisition_type smallint DEFAULT 0 NOT NULL AFTER qty; ALTER TABLE llx_asset ADD COLUMN asset_type smallint DEFAULT 0 NOT NULL AFTER acquisition_type; -ALTER TABLE llx_asset ADD COLUMN not_depreciated integer(1) DEFAULT 0 AFTER asset_type; +ALTER TABLE llx_asset ADD COLUMN not_depreciated integer DEFAULT 0 AFTER asset_type; ALTER TABLE llx_asset ADD COLUMN disposal_date date AFTER not_depreciated; ALTER TABLE llx_asset ADD COLUMN disposal_amount_ht double(24,8) AFTER disposal_date; ALTER TABLE llx_asset ADD COLUMN fk_disposal_type integer AFTER disposal_amount_ht; -ALTER TABLE llx_asset ADD COLUMN disposal_depreciated integer(1) DEFAULT 0 AFTER fk_disposal_type; -ALTER TABLE llx_asset ADD COLUMN disposal_subject_to_vat integer(1) DEFAULT 0 AFTER disposal_depreciated; +ALTER TABLE llx_asset ADD COLUMN disposal_depreciated integer DEFAULT 0 AFTER fk_disposal_type; +ALTER TABLE llx_asset ADD COLUMN disposal_subject_to_vat integer DEFAULT 0 AFTER disposal_depreciated; ALTER TABLE llx_asset ADD COLUMN last_main_doc varchar(255) AFTER fk_user_modif; ALTER TABLE llx_asset ADD COLUMN model_pdf varchar(255) AFTER import_key; @@ -313,7 +313,7 @@ CREATE TABLE llx_asset_depreciation_options_economic( fk_asset_model integer, depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional - accelerated_depreciation_option integer(1), -- activate accelerated depreciation mode (fiscal) + accelerated_depreciation_option integer, -- activate accelerated depreciation mode (fiscal) degressive_coefficient double(24,8), duration smallint NOT NULL, diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql index 1e0028ebaf2..37dd9c24402 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql @@ -21,7 +21,7 @@ CREATE TABLE llx_asset_depreciation_options_economic( fk_asset_model integer, depreciation_type smallint DEFAULT 0 NOT NULL, -- 0:linear, 1:degressive, 2:exceptional - accelerated_depreciation_option integer(1), -- activate accelerated depreciation mode (fiscal) + accelerated_depreciation_option integer, -- activate accelerated depreciation mode (fiscal) degressive_coefficient double(24,8), duration smallint NOT NULL, duration_type smallint DEFAULT 0 NOT NULL, -- 0:annual, 1:monthly, 2:daily From b7b3a25abacf54c20435b1b7da7d6422fd88cde7 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 14 Feb 2022 11:23:03 +0100 Subject: [PATCH 003/421] Fix tms --- .../tables/llx_asset_accountancy_codes_economic-asset.sql | 2 +- .../tables/llx_asset_accountancy_codes_fiscal-asset.sql | 2 +- .../install/mysql/tables/llx_asset_depreciation-asset.sql | 2 +- .../llx_asset_depreciation_options_economic-asset.sql | 2 +- .../llx_asset_depreciation_options_fiscal-asset.sql | 2 +- .../install/mysql/tables/llx_asset_extrafields-asset.sql | 8 ++++---- htdocs/install/mysql/tables/llx_asset_model-asset.sql | 2 +- .../mysql/tables/llx_asset_model_extrafield-asset.sql | 8 ++++---- .../mysql/tables/llx_c_asset_disposal_type-asset.sql | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql index 013b70ef1e9..3cbb8eb175b 100644 --- a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql @@ -28,6 +28,6 @@ CREATE TABLE llx_asset_accountancy_codes_economic( proceeds_from_sales varchar(32), vat_collected varchar(32), vat_deductible varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql index 9ab80facab0..db87b2fac3e 100644 --- a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql @@ -24,6 +24,6 @@ CREATE TABLE llx_asset_accountancy_codes_fiscal( endowment_accelerated_depreciation varchar(32), provision_accelerated_depreciation varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql index 5171f3ca6f2..bb994f883fb 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql @@ -29,6 +29,6 @@ CREATE TABLE llx_asset_depreciation( accountancy_code_debit varchar(32), accountancy_code_credit varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql index 37dd9c24402..88e90fa097f 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql @@ -30,6 +30,6 @@ CREATE TABLE llx_asset_depreciation_options_economic( amount_base_deductible_ht double(24,8), total_amount_last_depreciation_ht double(24,8), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql index ef2346ace5e..7463e448db4 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql @@ -29,6 +29,6 @@ CREATE TABLE llx_asset_depreciation_options_fiscal( amount_base_deductible_ht double(24,8), total_amount_last_depreciation_ht double(24,8), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql index 1b111d89ca0..57406ca5a6c 100644 --- a/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_extrafields-asset.sql @@ -17,8 +17,8 @@ create table llx_asset_extrafields ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, - import_key varchar(14) -- import key + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_object integer NOT NULL, + import_key varchar(14) -- import key ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_asset_model-asset.sql b/htdocs/install/mysql/tables/llx_asset_model-asset.sql index 576d794f54a..5ddee8a0dc6 100644 --- a/htdocs/install/mysql/tables/llx_asset_model-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_model-asset.sql @@ -25,7 +25,7 @@ CREATE TABLE llx_asset_model( note_public text, note_private text, date_creation datetime NOT NULL, - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_creat integer NOT NULL, fk_user_modif integer, import_key varchar(14), diff --git a/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql index 007f4fa76ec..18d13b89f72 100644 --- a/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_model_extrafield-asset.sql @@ -17,8 +17,8 @@ CREATE TABLE llx_asset_model_extrafields ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, - import_key varchar(14) -- import key + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_object integer NOT NULL, + import_key varchar(14) -- import key ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql index c3c103850b3..ebcaef02ac9 100644 --- a/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql +++ b/htdocs/install/mysql/tables/llx_c_asset_disposal_type-asset.sql @@ -18,8 +18,8 @@ CREATE TABLE llx_c_asset_disposal_type ( rowid integer AUTO_INCREMENT PRIMARY KEY, - entity integer NOT NULL DEFAULT 1, + entity integer NOT NULL DEFAULT 1, code varchar(16) NOT NULL, label varchar(50) NOT NULL, - active integer DEFAULT 1 NOT NULL + active integer DEFAULT 1 NOT NULL )ENGINE=innodb; From 4985b98bd52dc1b98b0d8632f29b0f703976659a Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 14 Feb 2022 12:02:50 +0100 Subject: [PATCH 004/421] Fix tms --- .../install/mysql/migration/15.0.0-16.0.0.sql | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 8182cc44d39..1574281908d 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -290,7 +290,7 @@ CREATE TABLE llx_asset_accountancy_codes_economic( proceeds_from_sales varchar(32), vat_collected varchar(32), vat_deductible varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; @@ -303,7 +303,7 @@ CREATE TABLE llx_asset_accountancy_codes_fiscal( endowment_accelerated_depreciation varchar(32), provision_accelerated_depreciation varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; @@ -323,7 +323,7 @@ CREATE TABLE llx_asset_depreciation_options_economic( amount_base_deductible_ht double(24,8), total_amount_last_depreciation_ht double(24,8), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; @@ -342,7 +342,7 @@ CREATE TABLE llx_asset_depreciation_options_fiscal( amount_base_deductible_ht double(24,8), total_amount_last_depreciation_ht double(24,8), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; @@ -360,7 +360,7 @@ CREATE TABLE llx_asset_depreciation( accountancy_code_debit varchar(32), accountancy_code_credit varchar(32), - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; @@ -376,7 +376,7 @@ CREATE TABLE llx_asset_model( note_public text, note_private text, date_creation datetime NOT NULL, - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_creat integer NOT NULL, fk_user_modif integer, import_key varchar(14), @@ -385,9 +385,9 @@ CREATE TABLE llx_asset_model( CREATE TABLE llx_asset_model_extrafields ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_object integer NOT NULL, import_key varchar(14) -- import key ) ENGINE=innodb; From 8152a728a866c568baf769db56ff09ef36b8a9e3 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 22 Mar 2022 11:42:15 +0100 Subject: [PATCH 005/421] Fix : filemanagement in ecm and medias --- htdocs/core/class/html.formfile.class.php | 8 ++++---- htdocs/core/tpl/filemanager.tpl.php | 18 ++++++++++++++++-- htdocs/ecm/class/htmlecm.form.class.php | 4 ++-- htdocs/ecm/dir_add_card.php | 2 +- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 6c4ff6e30f1..7117b2b8a2a 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -1328,7 +1328,7 @@ class FormFile if ($file['name'] != '.' && $file['name'] != '..' && !preg_match('/\.meta$/i', $file['name'])) { - if ($filearray[$key]['rowid'] > 0) { + if (!empty($filearray[$key]['rowid']) && $filearray[$key]['rowid'] > 0) { $lastrowid = $filearray[$key]['rowid']; } $filepath = $relativepath.$file['name']; @@ -1337,8 +1337,8 @@ class FormFile $nboflines++; print ''."\n"; // Do we have entry into database ? - print ''."\n"; - print ''; + print ''."\n"; + print ''; // File name print ''; @@ -1481,7 +1481,7 @@ class FormFile if ($permtoeditline) { // Link to resize $moreparaminurl = ''; - if ($object->id > 0) { + if (!empty($object->id) && $object->id > 0) { $moreparaminurl = '&id='.$object->id; } elseif (GETPOST('website', 'alpha')) { $moreparaminurl = '&website='.GETPOST('website', 'alpha'); diff --git a/htdocs/core/tpl/filemanager.tpl.php b/htdocs/core/tpl/filemanager.tpl.php index e776388ac53..5c40e56ff10 100644 --- a/htdocs/core/tpl/filemanager.tpl.php +++ b/htdocs/core/tpl/filemanager.tpl.php @@ -51,7 +51,7 @@ if ($module == 'medias') { $permtoupload = ($user->rights->mailing->creer || $user->rights->website->write); $showroot = 1; } - +$section = 0; // Confirm remove file (for non javascript users) @@ -102,12 +102,26 @@ $('#acreatedir').on('click', function() { try{ section_dir = $('.directory.expanded')[$('.directory.expanded').length-1].children[0].rel; section = $('.directory.expanded')[$('.directory.expanded').length-1].children[0].id.split('_')[2]; + catParent = "; +if ($module == 'ecm') { + print "section;"; +} else { + print "section_dir.substring(0, section_dir.length - 1);"; +} +print " } catch{ section_dir = '/'; section = 0; + catParent = "; +if ($module == 'ecm') { + print "section;"; +} else { + print "section_dir;"; +} +print " } console.log('We click to create a new directory, we set current section_dir='+section_dir+' into href url of button acreatedir'); - $('#acreatedir').attr('href', $('#acreatedir').attr('href')+'§ion_dir='+encodeURI(section_dir)+'§ion='+encodeURI(section)); + $('#acreatedir').attr('href', $('#acreatedir').attr('href')+'%26section_dir%3D'+encodeURI(section_dir)+'%26section%3D'+encodeURI(section)+'§ion_dir='+encodeURI(section_dir)+'§ion='+encodeURI(section)+'&catParent='+encodeURI(catParent)); console.log($('#acreatedir').attr('href')); }); $('#agenerateimgwebp').on('click', function() { diff --git a/htdocs/ecm/class/htmlecm.form.class.php b/htdocs/ecm/class/htmlecm.form.class.php index 623d626935d..b93d3d563fb 100644 --- a/htdocs/ecm/class/htmlecm.form.class.php +++ b/htdocs/ecm/class/htmlecm.form.class.php @@ -80,7 +80,7 @@ class FormEcm $cate_arbo = dol_dir_list($path, 'directories', 1, '', array('(\.meta|_preview.*\.png)$', '^\.'), 'relativename', SORT_ASC); } - $output = ''; if (is_array($cate_arbo)) { if (!count($cate_arbo)) { $output .= ''; @@ -100,7 +100,7 @@ class FormEcm } } $output .= ''; - $output .= ajax_combobox($select_name); + //$output .= ajax_combobox($select_name); $output .= "\n"; return $output; } diff --git a/htdocs/ecm/dir_add_card.php b/htdocs/ecm/dir_add_card.php index d7de6acc727..a6c980e5908 100644 --- a/htdocs/ecm/dir_add_card.php +++ b/htdocs/ecm/dir_add_card.php @@ -230,7 +230,7 @@ if ($action == 'create') { print ''; // Label - print ''."\n"; + print ''."\n"; print ''; print ''; - //auto APPROVAL ON CREATE + //auto validation ON CREATE print ''."\n"; From bf10e8f68771f9e125b76d09a248bd6a6244b98f Mon Sep 17 00:00:00 2001 From: jpb Date: Wed, 8 Jun 2022 17:08:05 +0200 Subject: [PATCH 028/421] add js behaviour on auvalidation and automail remove todo --- htdocs/holiday/card_group.php | 95 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 8ffe0f3e1fc..898d9f53be8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -318,8 +318,8 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; } else { - // AUTO APPROUVAL /VALIDATED - //@TODO changer le nom si approuved / validated + + //@TODO changer le nom si validated if ($autoValidation) { $htemp = new Holiday($db); $htemp->fetch($result); @@ -332,10 +332,11 @@ if (empty($reshook)) { $error++; } // we can auto send mail if we are in auto validation behavior - //@todo jquery disable if checkbox autovalidation unchecked + if ($AutoSendMail && !$error) { // send a mail to the user - sendMail($result, $cancreate, $now, $autoValidation); + $returnSendMail = sendMail($result, $cancreate, $now, $autoValidation); + if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg,$returnSendMail->style); } } } @@ -413,6 +414,13 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''."\n"; @@ -448,12 +465,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''."\n"; print ''."\n"; - - print dol_get_fiche_head(); - //print ''.$langs->trans('DelayToRequestCP',$object->getConfCP('delayForRequest')).'

'; - print '
'.$langs->trans("Label").'
'.$langs->trans("Label").'
'.$langs->trans("AddIn").''; print $formecm->selectAllSections((GETPOST("catParent", 'alpha') ? GETPOST("catParent", 'alpha') : $ecmdir->fk_parent), 'catParent', $module); From b18eac6c75708e6d1e2869cd3c99936440225932 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 22 Mar 2022 14:44:11 +0100 Subject: [PATCH 006/421] remove tests lines --- htdocs/ecm/class/htmlecm.form.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/ecm/class/htmlecm.form.class.php b/htdocs/ecm/class/htmlecm.form.class.php index b93d3d563fb..623d626935d 100644 --- a/htdocs/ecm/class/htmlecm.form.class.php +++ b/htdocs/ecm/class/htmlecm.form.class.php @@ -80,7 +80,7 @@ class FormEcm $cate_arbo = dol_dir_list($path, 'directories', 1, '', array('(\.meta|_preview.*\.png)$', '^\.'), 'relativename', SORT_ASC); } - $output = ''; if (is_array($cate_arbo)) { if (!count($cate_arbo)) { $output .= ''; @@ -100,7 +100,7 @@ class FormEcm } } $output .= ''; - //$output .= ajax_combobox($select_name); + $output .= ajax_combobox($select_name); $output .= "\n"; return $output; } From 9c8cb32de3e52d710486225367dd1f2710d41006 Mon Sep 17 00:00:00 2001 From: BB2A Anthony Berton Date: Fri, 8 Apr 2022 10:25:19 +0200 Subject: [PATCH 007/421] FIX --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index b6e16a22a9e..3e2158ff2ae 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2628,7 +2628,7 @@ if ($action == 'create' && $usercancreate) { } // Cancel order - if ($object->statut == Commande::STATUS_VALIDATED && (!empty($usercanclose) || !empty($usercancancel))) { + if ($object->statut == Commande::STATUS_VALIDATED && !empty($usercancancel)) { print ''.$langs->trans("Cancel").''; } From f17d09743ff2e9d5d88492671f091f56e49b515e Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 16:40:59 +0200 Subject: [PATCH 008/421] NEW product categories filter on inventory list --- htdocs/product/inventory/list.php | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index c4548b3aa66..a2b9fdfa194 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -27,6 +27,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} // Load translation files required by the page $langs->loadLangs(array("stocks", "other")); @@ -88,6 +91,13 @@ foreach ($object->fields as $key => $val) { $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); } } +$searchCategoryProductOperator = 0; +if (GETPOSTISSET('formfilteraction')) { + $searchCategoryProductOperator = GETPOST('search_category_product_operator', 'int'); +} elseif (!empty($conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT)) { + $searchCategoryProductOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT; +} +$searchCategoryProductList = GETPOST('search_category_product_list', 'array'); // List of fields to search into when doing a "search in all" $fieldstosearchall = array(); @@ -166,6 +176,7 @@ if (empty($reshook)) { $search[$key.'_dtend'] = ''; } } + $searchCategoryProductList = array(); $toselect = array(); $search_array_options = array(); } @@ -259,6 +270,50 @@ foreach ($search as $key => $val) { if ($search_all) { $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } +$searchCategoryProductSqlList = array(); +if ($searchCategoryProductOperator == 1) { + $existsCategoryProductList = array(); + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $sqlCategoryProductNotExists = " NOT EXISTS ("; + $sqlCategoryProductNotExists .= " SELECT cp.fk_product"; + $sqlCategoryProductNotExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductNotExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductNotExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductNotExists; + } elseif (intval($searchCategoryProduct) > 0) { + $existsCategoryProductList[] = $db->escape($searchCategoryProduct); + } + } + if (!empty($existsCategoryProductList)) { + $sqlCategoryProductExists = " EXISTS ("; + $sqlCategoryProductExists .= " SELECT cp.fk_product"; + $sqlCategoryProductExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".implode(",", $existsCategoryProductList).")"; + $sqlCategoryProductExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductExists; + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")"; + } +} else { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $sqlCategoryProductNotExists = " NOT EXISTS ("; + $sqlCategoryProductNotExists .= " SELECT cp.fk_product"; + $sqlCategoryProductNotExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductNotExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductNotExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductNotExists; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "t.fk_product IN (SELECT fk_product FROM ".$db->prefix()."categorie_product WHERE fk_categorie = ".((int) $searchCategoryProduct).")"; + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")"; + } +} //$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -348,6 +403,9 @@ foreach ($search as $key => $val) { if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } +foreach ($searchCategoryProductList as $searchCategoryProduct) { + $param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct); +} // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; // Add $param from hooks @@ -405,6 +463,17 @@ $moreforfilter = ''; $moreforfilter.= $langs->trans('MyFilter') . ': '; $moreforfilter.= '';*/ +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); + $categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1); + $categoriesProductArr[-2] = '- '.$langs->trans('NotCategorized').' -'; + $moreforfilter .= Form::multiselectarray('search_category_product_list', $categoriesProductArr, $searchCategoryProductList, 0, 0, 'minwidth300'); + $moreforfilter .= ' '; + $moreforfilter .= '
'; +} + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook if (empty($reshook)) { From 4510af67478628bd7b36ac69a5a91ac785944596 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 16:59:46 +0200 Subject: [PATCH 009/421] FIX travis SQL syntax --- htdocs/product/inventory/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index a2b9fdfa194..7e795d821bf 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -290,7 +290,7 @@ if ($searchCategoryProductOperator == 1) { $sqlCategoryProductExists .= " SELECT cp.fk_product"; $sqlCategoryProductExists .= " FROM ".$db->prefix()."categorie_product AS cp"; $sqlCategoryProductExists .= " WHERE cp.fk_product = t.fk_product"; - $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".implode(",", $existsCategoryProductList).")"; + $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".$db->sanitize(implode(',', $existsCategoryProductList)).")"; $sqlCategoryProductExists .= " )"; $searchCategoryProductSqlList[] = $sqlCategoryProductExists; } From 1435e2666e8d698b9b7f1cbabc75306e2b62bea8 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 17:18:39 +0200 Subject: [PATCH 010/421] FIX reload travis From 86296516591397cdb681543643e630972313abb1 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Thu, 28 Apr 2022 11:13:21 +0200 Subject: [PATCH 011/421] NEW : module webhook --- htdocs/admin/target_extrafields.php | 143 +++ htdocs/admin/webhook.php | 733 +++++++++++ htdocs/core/modules/modWebhook.class.php | 542 ++++++++ ...ce_99_modWebhook_WebhookTriggers.class.php | 119 ++ htdocs/langs/en_US/webhook.lang | 49 + htdocs/webhook/README.md | 86 ++ htdocs/webhook/class/target.class.php | 1091 +++++++++++++++++ .../modules/webhook/mod_target_advanced.php | 146 +++ .../modules/webhook/mod_target_standard.php | 161 +++ .../core/modules/webhook/modules_target.php | 158 +++ htdocs/webhook/lib/webhook.lib.php | 70 ++ htdocs/webhook/lib/webhook_target.lib.php | 91 ++ htdocs/webhook/modulebuilder.txt | 3 + htdocs/webhook/target_agenda.php | 315 +++++ htdocs/webhook/target_card.php | 618 ++++++++++ htdocs/webhook/target_contact.php | 226 ++++ htdocs/webhook/target_document.php | 261 ++++ htdocs/webhook/target_list.php | 813 ++++++++++++ htdocs/webhook/target_note.php | 221 ++++ htdocs/webhook/webhookindex.php | 241 ++++ test/phpunit/WebhookFunctionalTest.php | 304 +++++ 21 files changed, 6391 insertions(+) create mode 100644 htdocs/admin/target_extrafields.php create mode 100644 htdocs/admin/webhook.php create mode 100644 htdocs/core/modules/modWebhook.class.php create mode 100644 htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php create mode 100644 htdocs/langs/en_US/webhook.lang create mode 100644 htdocs/webhook/README.md create mode 100644 htdocs/webhook/class/target.class.php create mode 100644 htdocs/webhook/core/modules/webhook/mod_target_advanced.php create mode 100644 htdocs/webhook/core/modules/webhook/mod_target_standard.php create mode 100644 htdocs/webhook/core/modules/webhook/modules_target.php create mode 100644 htdocs/webhook/lib/webhook.lib.php create mode 100644 htdocs/webhook/lib/webhook_target.lib.php create mode 100644 htdocs/webhook/modulebuilder.txt create mode 100644 htdocs/webhook/target_agenda.php create mode 100644 htdocs/webhook/target_card.php create mode 100644 htdocs/webhook/target_contact.php create mode 100644 htdocs/webhook/target_document.php create mode 100644 htdocs/webhook/target_list.php create mode 100644 htdocs/webhook/target_note.php create mode 100644 htdocs/webhook/webhookindex.php create mode 100644 test/phpunit/WebhookFunctionalTest.php diff --git a/htdocs/admin/target_extrafields.php b/htdocs/admin/target_extrafields.php new file mode 100644 index 00000000000..8ab40dc0d90 --- /dev/null +++ b/htdocs/admin/target_extrafields.php @@ -0,0 +1,143 @@ + + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2012 Regis Houssin + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2015 Jean-François Ferry + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file admin/target_extrafields.php + * \ingroup webhook + * \brief Page to setup extra fields of target + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +require_once '../lib/webhook.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array('webhook@webhook', 'admin')); + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label = ExtraFields::$type2label; +$type2label = array(''); +foreach ($tmptype2label as $key => $val) { + $type2label[$key] = $langs->transnoentitiesnoconv($val); +} + +$action = GETPOST('action', 'aZ09'); +$attrname = GETPOST('attrname', 'alpha'); +$elementtype = 'webhook_target'; //Must be the $table_element of the class that manage extrafield + +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; + + + +/* + * View + */ + +$help_url = ''; +$page_name = "WebhookSetup"; + +llxHeader('', $langs->trans("WebhookSetup"), $help_url); + + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + + +$head = webhookAdminPrepareHead(); + +print dol_get_fiche_head($head, 'target_extrafields', $langs->trans($page_name), -1, 'webhook@webhook'); + +require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; + +print dol_get_fiche_end(); + + +// Buttons +if ($action != 'create' && $action != 'edit') { + print '
'; + print "".$langs->trans("NewAttribute").""; + print "
"; +} + + +/* + * Creation of an optional field + */ +if ($action == 'create') { + print '
'; + print load_fiche_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; +} + +/* + * Edition of an optional field + */ +if ($action == 'edit' && !empty($attrname)) { + print "
"; + print load_fiche_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/admin/webhook.php b/htdocs/admin/webhook.php new file mode 100644 index 00000000000..963b76c238a --- /dev/null +++ b/htdocs/admin/webhook.php @@ -0,0 +1,733 @@ + + * Copyright (C) 2022 SuperAdmin + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file webhook/admin/webhook.php + * \ingroup webhook + * \brief Webhook setup page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +global $langs, $user; + +// Libraries +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; +require_once DOL_DOCUMENT_ROOT.'/webhook/lib/webhook.lib.php'; + +// Translations +$langs->loadLangs(array("admin", "webhook")); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('webhooksetup', 'globalsetup')); + +// Access control +if (!$user->admin) { + accessforbidden(); +} + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type = 'myobject'; + +$arrayofparameters = array( + 'WEBHOOK_MYPARAM1'=>array('type'=>'string', 'css'=>'minwidth500' ,'enabled'=>0), + //'WEBHOOK_MYPARAM2'=>array('type'=>'textarea','enabled'=>1), + //'WEBHOOK_MYPARAM3'=>array('type'=>'category:'.Categorie::TYPE_CUSTOMER, 'enabled'=>1), + //'WEBHOOK_MYPARAM4'=>array('type'=>'emailtemplate:thirdparty', 'enabled'=>1), + //'WEBHOOK_MYPARAM5'=>array('type'=>'yesno', 'enabled'=>1), + //'WEBHOOK_MYPARAM5'=>array('type'=>'thirdparty_type', 'enabled'=>1), + //'WEBHOOK_MYPARAM6'=>array('type'=>'securekey', 'enabled'=>1), + //'WEBHOOK_MYPARAM7'=>array('type'=>'product', 'enabled'=>1), +); + +$error = 0; +$setupnotempty = 0; + +// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only +$useFormSetup = 0; +// Convert arrayofparameter into a formSetup object +if ($useFormSetup && (float) DOL_VERSION >= 15) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; + $formSetup = new FormSetup($db); + + // you can use the param convertor + $formSetup->addItemsFromParamsArray($arrayofparameters); + + // or use the new system see exemple as follow (or use both because you can ;-) ) + + /* + // Hôte + $item = $formSetup->newItem('NO_PARAM_JUST_TEXT'); + $item->fieldOverride = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST']; + $item->cssClass = 'minwidth500'; + + // Setup conf WEBHOOK_MYPARAM1 as a simple string input + $item = $formSetup->newItem('WEBHOOK_MYPARAM1'); + + // Setup conf WEBHOOK_MYPARAM1 as a simple textarea input but we replace the text of field title + $item = $formSetup->newItem('WEBHOOK_MYPARAM2'); + $item->nameText = $item->getNameText().' more html text '; + + // Setup conf WEBHOOK_MYPARAM3 + $item = $formSetup->newItem('WEBHOOK_MYPARAM3'); + $item->setAsThirdpartyType(); + + // Setup conf WEBHOOK_MYPARAM4 : exemple of quick define write style + $formSetup->newItem('WEBHOOK_MYPARAM4')->setAsYesNo(); + + // Setup conf WEBHOOK_MYPARAM5 + $formSetup->newItem('WEBHOOK_MYPARAM5')->setAsEmailTemplate('thirdparty'); + + // Setup conf WEBHOOK_MYPARAM6 + $formSetup->newItem('WEBHOOK_MYPARAM6')->setAsSecureKey()->enabled = 0; // disabled + + // Setup conf WEBHOOK_MYPARAM7 + $formSetup->newItem('WEBHOOK_MYPARAM7')->setAsProduct(); + */ + + $setupnotempty = count($formSetup->items); +} + + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + +if ($action == 'updateMask') { + $maskconst = GETPOST('maskconst', 'alpha'); + $maskvalue = GETPOST('maskvalue', 'alpha'); + + if ($maskconst) { + $res = dolibarr_set_const($db, $maskconst, $maskvalue, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen') { + $modele = GETPOST('module', 'alpha'); + $tmpobjectkey = GETPOST('object'); + + $tmpobject = new $tmpobjectkey($db); + $tmpobject->initAsSpecimen(); + + // Search template files + $file = ''; $classname = ''; $filefound = 0; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $file = dol_buildpath($reldir."core/modules/webhook/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0); + if (file_exists($file)) { + $filefound = 1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($tmpobject, $langs) > 0) { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} elseif ($action == 'setmod') { + // TODO Check if numbering module chosen can be activated by calling method canBeActivated + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'WEBHOOK_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); + } +} elseif ($action == 'set') { + // Activate a model + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') { + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'WEBHOOK_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if ($conf->global->$constforval == "$value") { + dolibarr_del_const($db, $constforval, $conf->entity); + } + } + } +} elseif ($action == 'setdoc') { + // Set or unset default model + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'WEBHOOK_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->$constforval = $value; + } + + // We disable/enable the document template (into llx_document_model table) + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $ret = addDocumentModel($value, $type, $label, $scandir); + } + } +} elseif ($action == 'unsetdoc') { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'WEBHOOK_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + dolibarr_del_const($db, $constforval, $conf->entity); + } +} + + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +$page_name = "WebhookSetup"; + +llxHeader('', $langs->trans($page_name), $help_url); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + +// Configuration header +$head = webhookAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "webhook@webhook"); + +// Setup page goes here +echo ''.$langs->trans("WebhookSetupPage").'

'; + + +if ($action == 'edit') { + if ($useFormSetup && (float) DOL_VERSION >= 15) { + print $formSetup->generateOutput(true); + } else { + print '
'; + print ''; + print ''; + + print ''; + print ''; + + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print ''.$form->textwithpicto($langs->trans($constname), $tooltiphelp, 1, 'info', '', 0, 3, 'tootips'.$constname).''; + print ''; + + if ($val['type'] == 'textarea') { + print '\n"; + } elseif ($val['type']== 'html') { + require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; + $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor->Create(); + } elseif ($val['type'] == 'yesno') { + print $form->selectyesno($constname, $conf->global->{$constname}, 1); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + $nboftemplates = $formmail->fetchAllEMailTemplate($tmp[1], $user, null, 1); // We set lang=null to get in priority record with no lang + //$arraydefaultmessage = $formmail->getEMailTemplate($db, $tmp[1], $user, null, 0, 1, ''); + $arrayofmessagename = array(); + if (is_array($formmail->lines_model)) { + foreach ($formmail->lines_model as $modelmail) { + //var_dump($modelmail); + $moreonlabel = ''; + if (!empty($arrayofmessagename[$modelmail->label])) { + $moreonlabel = ' (' . $langs->trans("SeveralLangugeVariatFound") . ')'; + } + // The 'label' is the key that is unique if we exclude the language + $arrayofmessagename[$modelmail->id] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)) . $moreonlabel; + } + } + print $form->selectarray($constname, $arrayofmessagename, $conf->global->{$constname}, 'None', 0, 0, '', 0, 0, 0, '', '', 1); + } elseif (preg_match('/category:/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + $formother = new FormOther($db); + + $tmp = explode(':', $val['type']); + print img_picto('', 'category', 'class="pictofixedwidth"'); + print $formother->select_categories($tmp[1], $conf->global->{$constname}, $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + $formcompany = new FormCompany($db); + print $formcompany->selectProspectCustomerType($conf->global->{$constname}, $constname); + } elseif ($val['type'] == 'securekey') { + print ''; + if (!empty($conf->use_javascript_ajax)) { + print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); + } + if (!empty($conf->use_javascript_ajax)) { + print "\n".''; + } + } elseif ($val['type'] == 'product') { + if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $form->select_produits($selected, $constname, '', 0); + } + } else { + print ''; + } + print '
'; + + print '
'; + print ''; + print '
'; + + print '
'; + } + + print '
'; +} else { + if ($useFormSetup && (float) DOL_VERSION >= 15) { + if (!empty($formSetup->items)) { + print $formSetup->generateOutput(); + } + } else { + if (!empty($arrayofparameters)) { + print ''; + print ''; + + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print $form->textwithpicto($langs->trans($constname), $tooltiphelp); + print ''; + + if ($val['type'] == 'textarea') { + print dol_nl2br($conf->global->{$constname}); + } elseif ($val['type']== 'html') { + print $conf->global->{$constname}; + } elseif ($val['type'] == 'yesno') { + print ajax_constantonoff($constname); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + + $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, $conf->global->{$constname}); + if ($template<0) { + setEventMessages(null, $formmail->errors, 'errors'); + } + print $langs->trans($template->label); + } elseif (preg_match('/category:/', $val['type'])) { + $c = new Categorie($db); + $result = $c->fetch($conf->global->{$constname}); + if ($result < 0) { + setEventMessages(null, $c->errors, 'errors'); + } elseif ($result > 0 ) { + $ways = $c->print_all_ways(' >> ', 'none', 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text + $toprint = array(); + foreach ($ways as $way) { + $toprint[] = '
  • color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '
  • '; + } + print '
      ' . implode(' ', $toprint) . '
    '; + } + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + if ($conf->global->{$constname}==2) { + print $langs->trans("Prospect"); + } elseif ($conf->global->{$constname}==3) { + print $langs->trans("ProspectCustomer"); + } elseif ($conf->global->{$constname}==1) { + print $langs->trans("Customer"); + } elseif ($conf->global->{$constname}==0) { + print $langs->trans("NorProspectNorCustomer"); + } + } elseif ($val['type'] == 'product') { + $product = new Product($db); + $resprod = $product->fetch($conf->global->{$constname}); + if ($resprod > 0) { + print $product->ref; + } elseif ($resprod < 0) { + setEventMessages(null, $object->errors, "errors"); + } + } else { + print $conf->global->{$constname}; + } + print '
    '; + } + } + + if ($setupnotempty) { + print '
    '; + print ''.$langs->trans("Modify").''; + print '
    '; + } else { + //print '
    '.$langs->trans("NothingToSetup"); + } +} + + +$moduledir = 'webhook'; +$myTmpObjects['MyObject'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); + + +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'MyObject') { + continue; + } + if ($myTmpObjectArray['includerefgeneration']) { + /* + * Orders Numbering model + */ + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectKey), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { + continue; + } + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { + continue; + } + + if ($module->isEnabled()) { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $mytmpinstance = new $myTmpObjectKey($db); + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
    '; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') { + $nextval = $langs->trans($nextval); + } + $htmltooltip .= $nextval.'
    '; + } else { + $htmltooltip .= $langs->trans($module->error).'
    '; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
    '.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
    '.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
    '.$langs->trans($tmp).'
    '; + } elseif ($tmp == 'NotConfigured') { + print $langs->trans($tmp); + } else { + print $tmp; + } + print '
    '; + $constforvar = 'WEBHOOK_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $file) { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

    \n"; + } + + if ($myTmpObjectArray['includedocgeneration']) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } + } else { + dol_print_error($db); + } + + print "\n"; + print "\n"; + print ''; + print ''; + print '\n"; + print '\n"; + print ''; + print ''; + print "\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + foreach (array('', '/doc') as $valdir) { + $realpath = $reldir."core/modules/".$moduledir.$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) { + if (file_exists($dir.'/'.$file)) { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified = 1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { + $modulequalified = 0; + } + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { + $modulequalified = 0; + } + + if ($modulequalified) { + print ''; + + // Active + if (in_array($name, $def)) { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
    '.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') { + $htmltooltip .= '
    '.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
    '.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

    '.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
    '.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
    '.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } + } + + print '
    '.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
    '; + print (empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) { + print $module->info($langs); + } else { + print $module->description; + } + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + $constforvar = 'WEBHOOK_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $name) { + //print img_picto($langs->trans("Default"), 'on'); + // Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset + print 'scandir).'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').''; + } else { + print 'scandir).'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print ''; + if ($module->type == 'pdf') { + print ''.img_object($langs->trans("Preview"), 'pdf').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
    '; + } +} + +if (empty($setupnotempty)) { + print '
    '.$langs->trans("NothingToSetup"); +} + +// Page end +print dol_get_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/htdocs/core/modules/modWebhook.class.php b/htdocs/core/modules/modWebhook.class.php new file mode 100644 index 00000000000..4a4467d205f --- /dev/null +++ b/htdocs/core/modules/modWebhook.class.php @@ -0,0 +1,542 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2022 SuperAdmin + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \defgroup webhook Module Webhook + * \brief Webhook module descriptor. + * + * \file htdocs/webhook/core/modules/modWebhook.class.php + * \ingroup webhook + * \brief Description and activation file for module Webhook + */ +include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + +/** + * Description and activation class for module Webhook + */ +class modWebhook extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs, $conf; + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 68305; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'webhook'; + + // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' + // It is used to group modules by family in module setup page + $this->family = "interface"; + + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '90'; + + // Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); + // Module label (no space allowed), used if translation string 'ModuleWebhookName' not found (Webhook is name of module). + $this->name = preg_replace('/^mod/i', '', get_class($this)); + + // Module description, used if translation string 'ModuleWebhookDesc' not found (Webhook is name of module). + $this->description = "WebhookDescription"; + // Used only if file README.md and README-LL.md not found. + $this->descriptionlong = "WebhookDescription"; + + // Author + $this->editor_name = 'Editor name'; + $this->editor_url = 'https://www.example.com'; + + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' + $this->version = 'dolibarr'; + // Url to the file with your last numberversion of this module + //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; + + // Key used in llx_const table to save module status enabled/disabled (where WEBHOOK is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' + $this->picto = 'webhook'; + + // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + // Set this to 1 if module has its own trigger directory (core/triggers) + 'triggers' => 1, + // Set this to 1 if module has its own login method file (core/login) + 'login' => 0, + // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 0, + // Set this to 1 if module has its own menus handler directory (core/menus) + 'menus' => 0, + // Set this to 1 if module overwrite template dir (core/tpl) + 'tpl' => 0, + // Set this to 1 if module has its own barcode directory (core/modules/barcode) + 'barcode' => 0, + // Set this to 1 if module has its own models directory (core/modules/xxx) + 'models' => 1, + // Set this to 1 if module has its own printing directory (core/modules/printing) + 'printing' => 0, + // Set this to 1 if module has its own theme directory (theme) + 'theme' => 0, + // Set this to relative path of css file if module has its own css file + 'css' => array( + // '/webhook/css/webhook.css.php', + ), + // Set this to relative path of js file if module must load a js on all pages + 'js' => array( + // '/webhook/js/webhook.js.php', + ), + // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all' + 'hooks' => array( + // 'data' => array( + // 'hookcontext1', + // 'hookcontext2', + // ), + // 'entity' => '0', + ), + // Set this to 1 if features of module are opened to external users + 'moduleforexternal' => 0, + ); + + // Data directories to create when module is enabled. + // Example: this->dirs = array("/webhook/temp","/webhook/subdir"); + $this->dirs = array("/webhook/temp"); + + // Config pages. Put here list of php page, stored into webhook/admin directory, to use to setup module. + $this->config_page_url = array("webhook.php"); + + // Dependencies + // A condition to hide module + $this->hidden = false; + // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) + $this->depends = array(); + $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) + + // The language file dedicated to your module + $this->langfiles = array("webhook"); + + // Prerequisites + $this->phpmin = array(5, 6); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(11, -3); // Minimum version of Dolibarr required by module + + // Messages at activation + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','MX'='textmx'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','MX'='textmx'...) + //$this->automatic_activation = array('FR'=>'WebhookWasAutomaticallyActivatedBecauseOfYourCountryChoice'); + //$this->always_enabled = true; // If true, can't be disabled + + // Constants + // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) + // Example: $this->const=array(1 => array('WEBHOOK_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1), + // 2 => array('WEBHOOK_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1) + // ); + $this->const = array(); + + // Some keys to add into the overwriting translation tables + /*$this->overwrite_translation = array( + 'en_US:ParentCompany'=>'Parent company or reseller', + 'fr_FR:ParentCompany'=>'Maison mère ou revendeur' + )*/ + + if (!isset($conf->webhook) || !isset($conf->webhook->enabled)) { + $conf->webhook = new stdClass(); + $conf->webhook->enabled = 0; + } + + // Array to add new pages in new tabs + $this->tabs = array(); + // Example: + // $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@webhook:$user->rights->webhook->read:/webhook/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1 + // $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@webhook:$user->rights->othermodule->read:/webhook/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // $this->tabs[] = array('data'=>'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // + // Where objecttype can be + // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) + // 'contact' to add a tab in contact view + // 'contract' to add a tab in contract view + // 'group' to add a tab in group view + // 'intervention' to add a tab in intervention view + // 'invoice' to add a tab in customer invoice view + // 'invoice_supplier' to add a tab in supplier invoice view + // 'member' to add a tab in fundation member view + // 'opensurveypoll' to add a tab in opensurvey poll view + // 'order' to add a tab in customer order view + // 'order_supplier' to add a tab in supplier order view + // 'payment' to add a tab in payment view + // 'payment_supplier' to add a tab in supplier payment view + // 'product' to add a tab in product view + // 'propal' to add a tab in propal view + // 'project' to add a tab in project view + // 'stock' to add a tab in stock view + // 'thirdparty' to add a tab in third party view + // 'user' to add a tab in user view + + // Dictionaries + $this->dictionaries = array(); + /* Example: + $this->dictionaries=array( + 'langs'=>'webhook@webhook', + // List of tables we want to see into dictonnary editor + 'tabname'=>array(MAIN_DB_PREFIX."table1", MAIN_DB_PREFIX."table2", MAIN_DB_PREFIX."table3"), + // Label of tables + 'tablib'=>array("Table1", "Table2", "Table3"), + // Request to select fields + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), + // Sort order + 'tabsqlsort'=>array("label ASC", "label ASC", "label ASC"), + // List of fields (result of select to show dictionary) + 'tabfield'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields to edit a record) + 'tabfieldvalue'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields for insert) + 'tabfieldinsert'=>array("code,label", "code,label", "code,label"), + // Name of columns with primary key (try to always name it 'rowid') + 'tabrowid'=>array("rowid", "rowid", "rowid"), + // Condition to show each dictionary + 'tabcond'=>array($conf->webhook->enabled, $conf->webhook->enabled, $conf->webhook->enabled) + ); + */ + + // Boxes/Widgets + // Add here list of php file(s) stored in webhook/core/boxes that contains a class to show a widget. + $this->boxes = array( + // 0 => array( + // 'file' => 'webhookwidget1.php@webhook', + // 'note' => 'Widget provided by Webhook', + // 'enabledbydefaulton' => 'Home', + // ), + // ... + ); + + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week + $this->cronjobs = array( + // 0 => array( + // 'label' => 'MyJob label', + // 'jobtype' => 'method', + // 'class' => '/webhook/class/webhook_target.class.php', + // 'objectname' => 'Webhook_target', + // 'method' => 'doScheduledJob', + // 'parameters' => '', + // 'comment' => 'Comment', + // 'frequency' => 2, + // 'unitfrequency' => 3600, + // 'status' => 0, + // 'test' => '$conf->webhook->enabled', + // 'priority' => 50, + // ), + ); + // Example: $this->cronjobs=array( + // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->webhook->enabled', 'priority'=>50), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->webhook->enabled', 'priority'=>50) + // ); + + // Permissions provided by this module + $this->rights = array(); + $r = 0; + // Add here entries to declare new permissions + /* BEGIN MODULEBUILDER PERMISSIONS */ + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); // Permission id (must not be already used) + $this->rights[$r][1] = 'Read objects of Webhook'; // Permission label + $this->rights[$r][4] = 'webhook_target'; + $this->rights[$r][5] = 'read'; // In php code, permission will be checked by test if ($user->rights->webhook->webhook_target->read) + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); // Permission id (must not be already used) + $this->rights[$r][1] = 'Create/Update objects of Webhook'; // Permission label + $this->rights[$r][4] = 'webhook_target'; + $this->rights[$r][5] = 'write'; // In php code, permission will be checked by test if ($user->rights->webhook->webhook_target->write) + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); // Permission id (must not be already used) + $this->rights[$r][1] = 'Delete objects of Webhook'; // Permission label + $this->rights[$r][4] = 'webhook_target'; + $this->rights[$r][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->webhook->webhook_target->delete) + $r++; + /* END MODULEBUILDER PERMISSIONS */ + + // Main menu entries to add + $this->menu = array(); + $r = 0; + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + /*$this->menu[$r++] = array( + 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'top', // This is a Top menu entry + 'titre'=>'ModuleWebhookName', + 'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth valignmiddle"'), + 'mainmenu'=>'webhook', + 'leftmenu'=>'', + 'url'=>'/webhook/webhookindex.php', + 'langs'=>'webhook@webhook', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000 + $r, + 'enabled'=>'$conf->webhook->enabled', // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->webhook->webhook_target->read' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + );*/ + /* END MODULEBUILDER TOPMENU */ + /* BEGIN MODULEBUILDER LEFTMENU WEBHOOK_TARGET + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=webhook', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'Webhook_target', + 'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth valignmiddle"'), + 'mainmenu'=>'webhook', + 'leftmenu'=>'webhook_target', + 'url'=>'/webhook/webhookindex.php', + 'langs'=>'webhook@webhook', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->webhook->enabled', // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->webhook->webhook_target->read', // Use 'perms'=>'$user->rights->webhook->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=webhook,fk_leftmenu=webhook_target', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List_Webhook_target', + 'mainmenu'=>'webhook', + 'leftmenu'=>'webhook_webhook_target_list', + 'url'=>'/webhook/webhook_target_list.php', + 'langs'=>'webhook@webhook', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->webhook->enabled', // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->webhook->webhook_target->read', // Use 'perms'=>'$user->rights->webhook->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=webhook,fk_leftmenu=webhook_target', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New_Webhook_target', + 'mainmenu'=>'webhook', + 'leftmenu'=>'webhook_webhook_target_new', + 'url'=>'/webhook/webhook_target_card.php?action=create', + 'langs'=>'webhook@webhook', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->webhook->enabled', // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->webhook->webhook_target->write', // Use 'perms'=>'$user->rights->webhook->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + */ + + /*$this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=webhook', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'List Webhook_target', + 'mainmenu'=>'webhook', + 'leftmenu'=>'webhook_webhook_target', + 'url'=>'/webhook/webhook_target_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'webhook@webhook', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->webhook->enabled', + // Use 'perms'=>'$user->rights->webhook->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=webhook,fk_leftmenu=webhook_webhook_target', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'New Webhook_target', + 'mainmenu'=>'webhook', + 'leftmenu'=>'webhook_webhook_target', + 'url'=>'/webhook/webhook_target_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'webhook@webhook', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->webhook->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->webhook->enabled', + // Use 'perms'=>'$user->rights->webhook->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + );*/ + + /* END MODULEBUILDER LEFTMENU WEBHOOK_TARGET */ + // Exports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER EXPORT WEBHOOK_TARGET */ + /* + $langs->load("webhook@webhook"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='Webhook_targetLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='webhook_target@webhook'; + // Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array + $keyforclass = 'Webhook_target'; $keyforclassfile='/webhook/class/webhook_target.class.php'; $keyforelement='webhook_target@webhook'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; + //unset($this->export_fields_array[$r]['t.fieldtoremove']); + //$keyforclass = 'Webhook_targetLine'; $keyforclassfile='/webhook/class/webhook_target.class.php'; $keyforelement='webhook_targetline@webhook'; $keyforalias='tl'; + //include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='webhook_target'; $keyforaliasextra='extra'; $keyforelement='webhook_target@webhook'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$keyforselect='webhook_targetline'; $keyforaliasextra='extraline'; $keyforelement='webhook_targetline@webhook'; + //include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r] = array('webhook_targetline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + //$this->export_special_array[$r] = array('t.field'=>'...'); + //$this->export_examplevalues_array[$r] = array('t.field'=>'Example'); + //$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp'); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'webhook_target as t'; + //$this->export_sql_end[$r] =' LEFT JOIN '.MAIN_DB_PREFIX.'webhook_target_line as tl ON tl.fk_webhook_target = t.rowid'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('webhook_target').')'; + $r++; */ + /* END MODULEBUILDER EXPORT WEBHOOK_TARGET */ + + // Imports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER IMPORT WEBHOOK_TARGET */ + /* + $langs->load("webhook@webhook"); + $this->import_code[$r]=$this->rights_class.'_'.$r; + $this->import_label[$r]='Webhook_targetLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->import_icon[$r]='webhook_target@webhook'; + $this->import_tables_array[$r] = array('t' => MAIN_DB_PREFIX.'webhook_webhook_target', 'extra' => MAIN_DB_PREFIX.'webhook_webhook_target_extrafields'); + $this->import_tables_creator_array[$r] = array('t' => 'fk_user_author'); // Fields to store import user id + $import_sample = array(); + $keyforclass = 'Webhook_target'; $keyforclassfile='/webhook/class/webhook_target.class.php'; $keyforelement='webhook_target@webhook'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinimport.inc.php'; + $import_extrafield_sample = array(); + $keyforselect='webhook_target'; $keyforaliasextra='extra'; $keyforelement='webhook_target@webhook'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinimport.inc.php'; + $this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'webhook_webhook_target'); + $this->import_regex_array[$r] = array(); + $this->import_examplevalues_array[$r] = array_merge($import_sample, $import_extrafield_sample); + $this->import_updatekeys_array[$r] = array('t.ref' => 'Ref'); + $this->import_convertvalue_array[$r] = array( + 't.ref' => array( + 'rule'=>'getrefifauto', + 'class'=>(empty($conf->global->WEBHOOK_WEBHOOK_TARGET_ADDON) ? 'mod_webhook_target_standard' : $conf->global->WEBHOOK_WEBHOOK_TARGET_ADDON), + 'path'=>"/core/modules/commande/".(empty($conf->global->WEBHOOK_WEBHOOK_TARGET_ADDON) ? 'mod_webhook_target_standard' : $conf->global->WEBHOOK_WEBHOOK_TARGET_ADDON).'.php' + 'classobject'=>'Webhook_target', + 'pathobject'=>'/webhook/class/webhook_target.class.php', + ), + 't.fk_soc' => array('rule' => 'fetchidfromref', 'file' => '/societe/class/societe.class.php', 'class' => 'Societe', 'method' => 'fetch', 'element' => 'ThirdParty'), + 't.fk_user_valid' => array('rule' => 'fetchidfromref', 'file' => '/user/class/user.class.php', 'class' => 'User', 'method' => 'fetch', 'element' => 'user'), + 't.fk_mode_reglement' => array('rule' => 'fetchidfromcodeorlabel', 'file' => '/compta/paiement/class/cpaiement.class.php', 'class' => 'Cpaiement', 'method' => 'fetch', 'element' => 'cpayment'), + ); + $r++; */ + /* END MODULEBUILDER IMPORT WEBHOOK_TARGET */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + global $conf, $langs; + + //$result = $this->_load_tables('/install/mysql/tables/', 'webhook'); + $result = $this->_load_tables('/webhook/sql/'); + if ($result < 0) { + return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + } + + // Create extrafields during init + //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + //$extrafields = new ExtraFields($this->db); + //$result1=$extrafields->addExtraField('webhook_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'webhook@webhook', '$conf->webhook->enabled'); + //$result2=$extrafields->addExtraField('webhook_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'webhook@webhook', '$conf->webhook->enabled'); + //$result3=$extrafields->addExtraField('webhook_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'webhook@webhook', '$conf->webhook->enabled'); + //$result4=$extrafields->addExtraField('webhook_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'webhook@webhook', '$conf->webhook->enabled'); + //$result5=$extrafields->addExtraField('webhook_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'webhook@webhook', '$conf->webhook->enabled'); + + // Permissions + $this->remove($options); + + $sql = array(); + + // Document templates + $moduledir = dol_sanitizeFileName('webhook'); + $myTmpObjects = array(); + $myTmpObjects['Webhook_target'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); + + foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'Webhook_target') { + continue; + } + if ($myTmpObjectArray['includerefgeneration']) { + $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_webhook_targets.odt'; + $dirodt = DOL_DATA_ROOT.'/doctemplates/'.$moduledir; + $dest = $dirodt.'/template_webhook_targets.odt'; + + if (file_exists($src) && !file_exists($dest)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + dol_mkdir($dirodt); + $result = dol_copy($src, $dest, 0, 0); + if ($result < 0) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest); + return 0; + } + } + + $sql = array_merge($sql, array( + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")" + )); + } + } + + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php new file mode 100644 index 00000000000..f49e0ef4499 --- /dev/null +++ b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php @@ -0,0 +1,119 @@ + + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file core/triggers/interface_99_modWebhook_WebhookTriggers.class.php + * \ingroup webhook + * \brief Example trigger. + * + * Put detailed description here. + * + * \remarks You can create other triggers by copying this one. + * - File name should be either: + * - interface_99_modWebhook_MyTrigger.class.php + * - interface_99_all_MyTrigger.class.php + * - The file must stay in core/triggers + * - The class name must be InterfaceMytrigger + */ + +require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; +require_once dol_buildpath("webhook/class/target.class.php"); + +/** + * Class of triggers for Webhook module + */ +class InterfaceWebhookTriggers extends DolibarrTriggers +{ + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + $this->db = $db; + + $this->name = preg_replace('/^Interface/i', '', get_class($this)); + $this->family = "demo"; + $this->description = "Webhook triggers."; + // 'development', 'experimental', 'dolibarr' or version + $this->version = 'development'; + $this->picto = 'webhook@webhook'; + } + + /** + * Trigger name + * + * @return string Name of trigger file + */ + public function getName() + { + return $this->name; + } + + /** + * Trigger description + * + * @return string Description of trigger file + */ + public function getDesc() + { + return $this->description; + } + + + /** + * Function called when a Dolibarrr business event is done. + * All functions "runTrigger" are triggered if file + * is inside directory core/triggers + * + * @param string $action Event action code + * @param CommonObject $object Object + * @param User $user Object user + * @param Translate $langs Object langs + * @param Conf $conf Object conf + * @return int <0 if KO, 0 if no triggered ran, >0 if OK + */ + public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) + { + if (empty($conf->webhook) || empty($conf->webhook->enabled)) { + return 0; // If module is not enabled, we do nothing + } + + // Or you can execute some code here + $nbPosts = 0; + $errors = 0; + $static_object = new Target($this->db); + $target_url = $static_object->fetchAll(); + foreach ($target_url as $key => $tmpobject) { + $actionarray = explode(",", $tmpobject->trigger_codes); + if (is_array($actionarray) && in_array($action, $actionarray)) { + $jsonstr = '{"triggercode":'.json_encode($action).',"object":'.json_encode($object).'}'; + $response = getURLContent($tmpobject->url, 'POST', $jsonstr); + if (empty($response['curl_error_no'])) { + $nbPosts ++; + } else { + $errors ++; + } + } + } + if (!empty($errors)) { + return $errors * -1; + } + return $nbPosts; + } +} diff --git a/htdocs/langs/en_US/webhook.lang b/htdocs/langs/en_US/webhook.lang new file mode 100644 index 00000000000..1c09e925559 --- /dev/null +++ b/htdocs/langs/en_US/webhook.lang @@ -0,0 +1,49 @@ +# Copyright (C) 2022 SuperAdmin +# +# 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 +# (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 +# along with this program. If not, see . + +# +# Generic +# + +# Module label 'ModuleWebhookName' +ModuleWebhookName = Webhook +# Module description 'ModuleWebhookDesc' +ModuleWebhookDesc = Interface to catch dolibarr triggers and send it to an URL + +# +# Admin page +# +WebhookSetup = Webhook setup +Settings = Settings +WebhookSetupPage = Webhook setup page +WEBHOOK_AUTOVALIDATE = Allow targets automatic validation + + +# +# About page +# +About = About +WebhookAbout = About Webhook +WebhookAboutPage = Webhook about page + +# +# Sample page +# + +# +# Sample widget +# +MyWidget = My widget +MyWidgetDescription = My widget description diff --git a/htdocs/webhook/README.md b/htdocs/webhook/README.md new file mode 100644 index 00000000000..74fe79e76fd --- /dev/null +++ b/htdocs/webhook/README.md @@ -0,0 +1,86 @@ +# WEBHOOK FOR [DOLIBARR ERP CRM](https://www.dolibarr.org) + +## Features + +Description of the module... + + + +Other external modules are available on [Dolistore.com](https://www.dolistore.com). + +## Translations + +Translations can be completed manually by editing files into directories *langs*. + + + + + +## Licenses + +### Main code + +GPLv3 or (at your option) any later version. See file COPYING for more information. + +### Documentation + +All texts and readmes are licensed under GFDL. diff --git a/htdocs/webhook/class/target.class.php b/htdocs/webhook/class/target.class.php new file mode 100644 index 00000000000..e977842ad79 --- /dev/null +++ b/htdocs/webhook/class/target.class.php @@ -0,0 +1,1091 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file class/target.class.php + * \ingroup webhook + * \brief This file is a CRUD class file for Target (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Target + */ +class Target extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'webhook'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'target'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'webhook_target'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for target. Must be the part after the 'object_' into object_target.png + */ + public $picto = 'webhook'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_CANCELED = 9; + + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or '!empty($conf->multicurrency->enabled)' ...) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'validate'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'help'=>"Help text", 'showoncombobox'=>'2', 'validate'=>'1',), + 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3, 'validate'=>'1',), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>0,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>2000, 'notnull'=>1, 'visible'=>3, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validé', '9'=>'Annulé'), 'validate'=>'1',), + 'url' => array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1,), + 'trigger_codes' => array('type'=>'text', 'label'=>'TriggerCodes', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1, 'help'=>"TriggerCodeInfo",), + ); + public $rowid; + public $ref; + public $label; + public $description; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $last_main_doc; + public $import_key; + public $model_pdf; + public $status; + public $url; + public $trigger_codes; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + // /** + // * @var string Name of subtable line + // */ + // public $table_element_line = 'webhook_targetline'; + + // /** + // * @var string Field with ID of parent key if this object has a parent + // */ + // public $fk_element = 'fk_target'; + + // /** + // * @var string Name of subtable class that manage subtable lines + // */ + // public $class_element_line = 'Targetline'; + + // /** + // * @var array List of child tables. To test if we can delete object. + // */ + // protected $childtables = array(); + + // /** + // * @var array List of child tables. To know object to delete on cascade. + // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + // */ + // protected $childtablesoncascade = array('webhook_targetdet'); + + // /** + // * @var TargetLine[] Array of subtable lines + // */ + // public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { + $this->fields['rowid']['visible'] = 0; + } + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) { + $this->fields['entity']['enabled'] = 0; + } + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->webhook->target->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + $resultcreate = $this->createCommon($user, $notrigger); + + if ($resultcreate <= 0) { + return $resultcreate; + } + $resultvalidate = $this->validate($user, $notrigger); + + return $resultvalidate; + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && !empty($object->table_element_line)) { + $object->fetchLines(); + } + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) { + $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + } + if (property_exists($object, 'label')) { + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + } + if (property_exists($object, 'status')) { + $object->status = self::STATUS_DRAFT; + } + if (property_exists($object, 'date_creation')) { + $object->date_creation = dol_now(); + } + if (property_exists($object, 'date_modification')) { + $object->date_modification = null; + } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) { + $error++; + } + } + + if (!$error) { + // copy external contacts if same company + if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) { + if ($this->copy_linked_contact($object, 'external') < 0) { + $error++; + } + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) { + $this->fetchLines(); + } + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = "SELECT "; + $sql .= $this->getFieldList('t'); + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + } else { + $sql .= " WHERE 1 = 1"; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->target->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->target->target_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) { + $sql .= ", date_validation = '".$this->db->idate($now)."'"; + } + if (!empty($this->fields['fk_user_valid'])) { + $sql .= ", fk_user_valid = ".((int) $user->id); + } + $sql .= " WHERE rowid = ".((int) $this->id); + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('TARGET_VALIDATE', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + } + + if (!$error) { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'target/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'target/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { + $error++; $this->error = $this->db->lasterror(); + } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->webhook->dir_output.'/target/'.$oldref; + $dirdest = $conf->webhook->dir_output.'/target/'.$newref; + if (!$error && file_exists($dirsource)) { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->webhook->dir_output.'/target/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'TARGET_UNVALIDATE'); + } + + /** + * Set cancel status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function cancel($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_VALIDATED) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'TARGET_CANCEL'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'TARGET_REOPEN'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) { + $notooltip = 1; // Force disable tooltips + } + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("Target").''; + if (isset($this->status)) { + $label .= ' '.$this->getLibStatut(5); + } + $label .= '
    '; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + + $url = dol_buildpath('/webhook/target_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { + $add_save_lastsearch_values = 1; + } + if ($url && $add_save_lastsearch_values) { + $url .= '&save_lastsearch_values=1'; + } + } + + $linkclose = ''; + if (empty($notooltip)) { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + $label = $langs->trans("ShowTarget"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else { + $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + } + + if ($option == 'nolink' || empty($url)) { + $linkstart = ''; + if ($option == 'nolink' || empty($url)) { + $linkend = ''; + } else { + $linkend = ''; + } + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
    No photo
    '; + } else { + $result .= '
    No photo
    '; + } + + $result .= ''; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) { + $result .= $this->ref; + } + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('targetdao')); + $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 + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } + + return $result; + } + + /** + * Return the label of the status + * + * @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 getLabelStatus($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the label of the status + * + * @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 getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @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 + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + //$langs->load("webhook@webhook"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + if ($status == self::STATUS_CANCELED) { + $statusType = 'status6'; + } + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = "SELECT rowid, date_creation as datec, tms as datem,"; + $sql .= " fk_user_creat, fk_user_modif"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".((int) $id); + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if (!empty($obj->fk_user_author)) { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if (!empty($obj->fk_user_valid)) { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if (!empty($obj->fk_user_cloture)) { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + // Set here init that are not commonf fields + // $this->property1 = ... + // $this->property2 = ... + + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new TargetLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_target = '.((int) $this->id))); + + if (is_numeric($result)) { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("webhook@webhook"); + + if (empty($conf->global->WEBHOOK_TARGET_ADDON)) { + $conf->global->WEBHOOK_TARGET_ADDON = 'mod_target_standard'; + } + + if (!empty($conf->global->WEBHOOK_TARGET_ADDON)) { + $mybool = false; + + $file = $conf->global->WEBHOOK_TARGET_ADDON.".php"; + $classname = $conf->global->WEBHOOK_TARGET_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/webhook/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 0; + + $langs->load("webhook@webhook"); + + if (!dol_strlen($modele)) { + $modele = 'standard_target'; + + if (!empty($this->model_pdf)) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->TARGET_ADDON_PDF)) { + $modele = $conf->global->TARGET_ADDON_PDF; + } + } + + $modelpath = "core/modules/webhook/doc/"; + + if ($includedocgeneration && !empty($modele)) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} + + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + +/** + * Class TargetLine. You can also remove this and generate a CRUD class for lines objects. + */ +class TargetLine extends CommonObjectLine +{ + // To complete with content of an object TargetLine + // We should have a field rowid, fk_target and position + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } +} diff --git a/htdocs/webhook/core/modules/webhook/mod_target_advanced.php b/htdocs/webhook/core/modules/webhook/mod_target_advanced.php new file mode 100644 index 00000000000..52dade35b89 --- /dev/null +++ b/htdocs/webhook/core/modules/webhook/mod_target_advanced.php @@ -0,0 +1,146 @@ + + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France + * + * 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 + * (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 + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/webhook/mod_target_advanced.php + * \ingroup webhook + * \brief File containing class for advanced numbering model of Target + */ + +dol_include_once('/webhook/core/modules/webhook/modules_target.php'); + + +/** + * Class to manage customer Bom numbering rules advanced + */ +class mod_target_advanced extends ModeleNumRefTarget +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string Error message + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'advanced'; + + + /** + * Returns the description of the numbering model + * + * @return string Texte descripif + */ + public function info() + { + global $conf, $langs, $db; + + $langs->load("bills"); + + $form = new Form($db); + + $texte = $langs->trans('GenericNumRefModelDesc')."
    \n"; + $texte .= '
    '; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("Target"), $langs->transnoentities("Target")); + $tooltip .= $langs->trans("GenericMaskCodes2"); + $tooltip .= $langs->trans("GenericMaskCodes3"); + $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("Target"), $langs->transnoentities("Target")); + $tooltip .= $langs->trans("GenericMaskCodes5"); + + // Parametrage du prefix + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $texte .= '
    '.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
    '; + $texte .= '
    '; + + return $texte; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $conf, $db, $langs, $mysoc; + + $object = new Target($db); + $object->initAsSpecimen(); + + /*$old_code_client = $mysoc->code_client; + $old_code_type = $mysoc->typent_code; + $mysoc->code_client = 'CCCCCCCCCC'; + $mysoc->typent_code = 'TTTTTTTTTT';*/ + + $numExample = $this->getNextValue($object); + + /*$mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type;*/ + + if (!$numExample) { + $numExample = $langs->trans('NotConfigured'); + } + return $numExample; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + // We get cursor rule + $mask = $conf->global->WEBHOOK_TARGET_ADVANCED_MASK; + + if (!$mask) { + $this->error = 'NotConfigured'; + return 0; + } + + $date = $object->date; + + $numFinal = get_next_value($db, $mask, 'webhook_target', 'ref', '', null, $date); + + return $numFinal; + } +} diff --git a/htdocs/webhook/core/modules/webhook/mod_target_standard.php b/htdocs/webhook/core/modules/webhook/mod_target_standard.php new file mode 100644 index 00000000000..f3202e9e895 --- /dev/null +++ b/htdocs/webhook/core/modules/webhook/mod_target_standard.php @@ -0,0 +1,161 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * + * 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 + * (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 + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/webhook/mod_target_standard.php + * \ingroup webhook + * \brief File of class to manage Target numbering rules standard + */ +dol_include_once('/webhook/core/modules/webhook/modules_target.php'); + + +/** + * Class to manage customer order numbering rules standard + */ +class mod_target_standard extends ModeleNumRefTarget +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + public $prefix = 'TARGET'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'standard'; + + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info() + { + global $langs; + return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + } + + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + return $this->prefix."0501-0001"; + } + + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."webhook_target"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $row = $db->fetch_row($resql); + if ($row) { + $coyymm = substr($row[0], 0, 6); $max = $row[0]; + } + } + if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + // first we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."webhook_target"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $max = intval($obj->max); + } else { + $max = 0; + } + } else { + dol_syslog("mod_target_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) { + $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + } else { + $num = sprintf("%04s", $max + 1); + } + + dol_syslog("mod_target_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } +} diff --git a/htdocs/webhook/core/modules/webhook/modules_target.php b/htdocs/webhook/core/modules/webhook/modules_target.php new file mode 100644 index 00000000000..9f1f253f9a5 --- /dev/null +++ b/htdocs/webhook/core/modules/webhook/modules_target.php @@ -0,0 +1,158 @@ + + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2014 Marcos García + * + * 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 + * (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 + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/webhook/modules_target.php + * \ingroup webhook + * \brief File that contains parent class for targets document models and parent class for targets numbering models + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // required for use by classes that inherit + + +/** + * Parent class for documents models + */ +abstract class ModelePDFTarget extends CommonDocGenerator +{ + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + public static function liste_modeles($db, $maxfilenamelength = 0) + { + // phpcs:enable + global $conf; + + $type = 'target'; + $list = array(); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $list = getListOfModels($db, $type, $maxfilenamelength); + + return $list; + } +} + + + +/** + * Parent class to manage numbering of Target + */ +abstract class ModeleNumRefTarget +{ + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled() + { + return true; + } + + /** + * Returns the default description of the numbering template + * + * @return string Texte descripif + */ + public function info() + { + global $langs; + $langs->load("webhook@webhook"); + return $langs->trans("NoDescription"); + } + + /** + * Returns an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $langs; + $langs->load("webhook@webhook"); + return $langs->trans("NoExample"); + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + return true; + } + + /** + * Returns next assigned value + * + * @param Object $object Object we need next value for + * @return string Valeur + */ + public function getNextValue($object) + { + global $langs; + return $langs->trans("NotAvailable"); + } + + /** + * Returns version of numbering module + * + * @return string Valeur + */ + public function getVersion() + { + global $langs; + $langs->load("admin"); + + if ($this->version == 'development') { + return $langs->trans("VersionDevelopment"); + } + if ($this->version == 'experimental') { + return $langs->trans("VersionExperimental"); + } + if ($this->version == 'dolibarr') { + return DOL_VERSION; + } + if ($this->version) { + return $this->version; + } + return $langs->trans("NotAvailable"); + } +} diff --git a/htdocs/webhook/lib/webhook.lib.php b/htdocs/webhook/lib/webhook.lib.php new file mode 100644 index 00000000000..6c511180b6e --- /dev/null +++ b/htdocs/webhook/lib/webhook.lib.php @@ -0,0 +1,70 @@ + + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file webhook/lib/webhook.lib.php + * \ingroup webhook + * \brief Library files with common functions for Webhook + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function webhookAdminPrepareHead() +{ + global $langs, $conf; + + $langs->load("webhook@webhook"); + + $h = 0; + $head = array(); + $head[$h][0] = dol_buildpath("/admin/webhook.php", 1); + $head[$h][1] = $langs->trans("Miscellaneous"); + $head[$h][2] = 'settings'; + $h++; + + $head[$h][0] = dol_buildpath("/webhook/target_list.php?mode=modulesetup", 1); + $head[$h][1] = $langs->trans("Targets"); + $head[$h][2] = 'targets'; + $h++; + + + /* + $head[$h][0] = dol_buildpath("/webhook/admin/myobject_extrafields.php", 1); + $head[$h][1] = $langs->trans("ExtraFields"); + $head[$h][2] = 'myobject_extrafields'; + $h++; + */ + + + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@webhook:/webhook/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@webhook:/webhook/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'webhook@webhook'); + + complete_head_from_modules($conf, $langs, null, $head, $h, 'webhook@webhook', 'remove'); + + return $head; +} diff --git a/htdocs/webhook/lib/webhook_target.lib.php b/htdocs/webhook/lib/webhook_target.lib.php new file mode 100644 index 00000000000..e5c0d09bb85 --- /dev/null +++ b/htdocs/webhook/lib/webhook_target.lib.php @@ -0,0 +1,91 @@ +. + */ + +/** + * \file lib/webhook_target.lib.php + * \ingroup webhook + * \brief Library files with common functions for Target + */ +/** + * Prepare array of tabs for Target + * + * @param Target $object Target + * @return array Array of tabs + */ +function targetPrepareHead($object) +{ + global $db, $langs, $conf; + + $langs->load("webhook@webhook"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/webhook/target_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) { + $nbNote = 0; + if (!empty($object->note_private)) { + $nbNote++; + } + if (!empty($object->note_public)) { + $nbNote++; + } + $head[$h][0] = dol_buildpath('/webhook/target_note.php', 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) { + $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); + } + $head[$h][2] = 'note'; + $h++; + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; + $upload_dir = $conf->webhook->dir_output."/target/".dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); + $nbLinks = Link::count($db, $object->element, $object->id); + $head[$h][0] = dol_buildpath("/webhook/target_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles + $nbLinks) > 0) { + $head[$h][1] .= ''.($nbFiles + $nbLinks).''; + } + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = dol_buildpath("/webhook/target_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@webhook:/webhook/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@webhook:/webhook/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'target@webhook'); + + complete_head_from_modules($conf, $langs, $object, $head, $h, 'target@webhook', 'remove'); + + return $head; +} diff --git a/htdocs/webhook/modulebuilder.txt b/htdocs/webhook/modulebuilder.txt new file mode 100644 index 00000000000..670a1774929 --- /dev/null +++ b/htdocs/webhook/modulebuilder.txt @@ -0,0 +1,3 @@ +# DO NOT DELETE THIS FILE MANUALLY +# File to flag module built using official module template. +# When this file is present into a module directory, you can edit it with the module builder tool. \ No newline at end of file diff --git a/htdocs/webhook/target_agenda.php b/htdocs/webhook/target_agenda.php new file mode 100644 index 00000000000..12b6e67c57b --- /dev/null +++ b/htdocs/webhook/target_agenda.php @@ -0,0 +1,315 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_agenda.php + * \ingroup webhook + * \brief Tab of events on Target + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/webhook/class/target.class.php'); +dol_include_once('/webhook/lib/webhook_target.lib.php'); + + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) { + $actioncode = '0'; + } +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) { + $sortfield = 'a.datep,a.id'; +} +if (!$sortorder) { + $sortorder = 'DESC,DESC'; +} + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->webhook->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity]."/".$object->id; +} + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permissiontoadd = $user->rights->webhook->target->write; +} else { + $permissiontoread = 1; + $permissiontoadd = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array('id'=>$id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $actioncode = ''; + $search_agenda_label = ''; + } +} + + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) { + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = 'EN:Module_Agenda_En'; + llxHeader('', $title, $help_url); + + if (!empty($conf->notification->enabled)) { + $langs->load("mails"); + } + $head = targetPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("Target"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) { + if ($action != 'classify') { + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + } + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
    '; + + print dol_get_fiche_end(); + + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin='.urlencode($object->element.'@'.$object->module).'&originid='.urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'].'?id='.$object->id; + $out .= '&backtopage='.urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
    '; + + if (!empty($conf->agenda->enabled)) { + if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) { + print ''.$langs->trans("AddAction").''; + } else { + print ''.$langs->trans("AddAction").''; + } + } + + print '
    '; + + if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { + $param = '&id='.$object->id.'&socid='.$socid; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); + } + + + //print load_fiche_titre($langs->trans("ActionsOnTarget"), '', ''); + + // List of all actions + $filters = array(); + $filters['search_agenda_label'] = $search_agenda_label; + + // TODO Replace this with same code than into list.php + show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/target_card.php b/htdocs/webhook/target_card.php new file mode 100644 index 00000000000..dd0d5e171e8 --- /dev/null +++ b/htdocs/webhook/target_card.php @@ -0,0 +1,618 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_card.php + * \ingroup webhook + * \brief Page to create/edit/view target + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification +//if (! defined('NOSESSION')) define('NOSESSION', '1'); // Disable session + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +dol_include_once('/webhook/class/target.class.php'); +dol_include_once('/webhook/lib/webhook_target.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'targetcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$lineid = GETPOST('lineid', 'int'); + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetcard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha')) { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } +} + +if (empty($action) && empty($id) && empty($ref)) { + $action = 'view'; +} + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permissiontoadd = $user->rights->webhook->target->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php + $permissiontodelete = $user->rights->webhook->target->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); + $permissionnote = $user->rights->webhook->target->write; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $user->rights->webhook->target->write; // Used by the include of actions_dellink.inc.php +} else { + $permissiontoread = 1; + $permissiontoadd = 1; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php + $permissiontodelete = 1; + $permissionnote = 1; + $permissiondellink = 1; +} + +$upload_dir = $conf->webhook->multidir_output[isset($object->entity) ? $object->entity : 1].'/target'; + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (isset($object->status) && ($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $error = 0; + + $backurlforlist = dol_buildpath('/webhook/target_list.php?mode=modulesetup', 1); + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = dol_buildpath('/webhook/target_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + $triggermodname = 'WEBHOOK_TARGET_MODIFY'; // Name of trigger action code to execute when we modify record + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Actions when linking object each other + include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + + // Action to move up and down lines of object + //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + if ($action == 'set_thirdparty' && $permissiontoadd) { + $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, $triggermodname); + } + if ($action == 'classin' && $permissiontoadd) { + $object->setProject(GETPOST('projectid', 'int')); + } + + // Actions to send emails + $triggersendname = 'WEBHOOK_TARGET_SENTBYMAIL'; + $autocopy = 'MAIN_MAIL_AUTOCOPY_TARGET_TO'; + $trackid = 'target'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; +} + + + + +/* + * View + * + * Put here all code to build page + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$formproject = new FormProjets($db); + +$title = $langs->trans("Target"); +$help_url = ''; +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +// print ''; + + +// Part to create +if ($action == 'create') { + if (empty($permissiontoadd)) { + accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1); + exit; + } + + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Target")), '', 'object_'.$object->picto); + + print '
    '; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print '
    '."\n"; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel("Create"); + + print '
    '; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') { + print load_fiche_titre($langs->trans("Target"), '', 'object_'.$object->picto); + + print '
    '; + print ''; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
    '; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + $res = $object->fetch_optionals(); + + $head = targetPrepareHead($object); + print dol_get_fiche_head($head, 'card', $langs->trans("Target"), -1, $object->picto); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteTarget'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } + // Confirmation to delete line + if ($action == 'deleteline') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); + } + + // Clone confirmation + if ($action == 'clone') { + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + } + + // Confirmation of action xxxx (You can use it for xxx = 'close', xxx = 'reopen', ...) + if ($action == 'xxx') { + $text = $langs->trans('ConfirmActionTarget', $object->ref); + /*if (! empty($conf->notification->enabled)) + { + require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; + $notify = new Notify($db); + $text .= '
    '; + $text .= $notify->confirmMessage('TARGET_CLOSE', $object->socid, $object); + }*/ + + $formquestion = array(); + /* + $forcecombo=0; + if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy + $formquestion = array( + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo)) + ); + */ + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) { + //if ($action != 'classify') $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' '; + $morehtmlref .= ' : '; + if ($action == 'classify') { + //$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
    '; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + print '
    '; + print ''."\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field + //unset($object->fields['fk_project']); // Hide field already shown in banner + //unset($object->fields['fk_soc']); // Hide field already shown in banner + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
    '; + print '
    '; + print '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + + /* + * Lines + */ + + if (!empty($object->table_element_line)) { + // Show object lines + $result = $object->getLinesArray(); + + print '
    + + + + + + '; + + if (!empty($conf->use_javascript_ajax) && $object->status == 0) { + include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; + } + + print '
    '; + if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) { + print ''; + } + + if (!empty($object->lines)) { + $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1); + } + + // Form to add new line + if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') { + if ($action != 'editline') { + // Add products/services form + + $parameters = array(); + $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + if (empty($reshook)) + $object->formAddObjectLine(1, $mysoc, $soc); + } + } + + if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) { + print '
    '; + } + print '
    '; + + print "
    \n"; + } + + + // Buttons for actions + + if ($action != 'presend' && $action != 'editline') { + print '
    '."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + // Send + if (empty($user->socid)) { + print dolGetButtonAction($langs->trans('SendMail'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init&token='.newToken().'#formmailbeforetitle'); + } + + // Back to draft + if ($object->status == $object::STATUS_VALIDATED) { + print dolGetButtonAction($langs->trans('SetToDraft'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_setdraft&confirm=yes&token='.newToken(), '', $permissiontoadd); + } + + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoadd); + + // Validate + if ($object->status == $object::STATUS_DRAFT) { + if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) { + print dolGetButtonAction($langs->trans('Validate'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=confirm_validate&confirm=yes&token='.newToken(), '', $permissiontoadd); + } else { + $langs->load("errors"); + print dolGetButtonAction($langs->trans("ErrorAddAtLeastOneLineFirst"), $langs->trans("Validate"), 'default', '#', '', 0); + } + } + + // Clone + print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid)?'&socid='.$object->socid:'').'&action=clone&token='.newToken(), '', $permissiontoadd); + + /* + if ($permissiontoadd) { + if ($object->status == $object::STATUS_ENABLED) { + print dolGetButtonAction($langs->trans('Disable'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=disable&token='.newToken(), '', $permissiontoadd); + } else { + print dolGetButtonAction($langs->trans('Enable'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=enable&token='.newToken(), '', $permissiontoadd); + } + } + if ($permissiontoadd) { + if ($object->status == $object::STATUS_VALIDATED) { + print dolGetButtonAction($langs->trans('Cancel'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=close&token='.newToken(), '', $permissiontoadd); + } else { + print dolGetButtonAction($langs->trans('Re-Open'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen&token='.newToken(), '', $permissiontoadd); + } + } + */ + + // Delete (need delete permission, or if draft, just need create/modify permission) + print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=delete&token='.newToken(), '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); + } + print '
    '."\n"; + } + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') { + print '
    '; + print ''; // ancre + + $includedocgeneration = 0; + + // Documents + if ($includedocgeneration) { + $objref = dol_sanitizeFileName($object->ref); + $relativepath = $objref.'/'.$objref.'.pdf'; + $filedir = $conf->webhook->dir_output.'/'.$object->element.'/'.$objref; + $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; + $genallowed = $permissiontoread; // If you can read, you can build the PDF to read content + $delallowed = $permissiontoadd; // If you can create/edit, you can remove a file on card + print $formfile->showdocuments('webhook:Target', $object->element.'/'.$objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); + } + + // Show links to link elements + $linktoelem = $form->showLinkToObjectBlock($object, null, array('target')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + + + print '
    '; + + $MAXEVENT = 10; + + $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', dol_buildpath('/webhook/target_agenda.php', 1).'?id='.$object->id); + + // List of actions on element + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, $object->element.'@'.$object->module, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter); + + print '
    '; + } + + //Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + // Presend form + $modelmail = 'target'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->webhook->dir_output; + $trackid = 'target'.$object->id; + + include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/target_contact.php b/htdocs/webhook/target_contact.php new file mode 100644 index 00000000000..94c906969aa --- /dev/null +++ b/htdocs/webhook/target_contact.php @@ -0,0 +1,226 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_contact.php + * \ingroup webhook + * \brief Tab for contacts linked to Target + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +dol_include_once('/webhook/class/target.class.php'); +dol_include_once('/webhook/lib/webhook_target.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "companies", "other", "mails")); + +$id = (GETPOST('id') ?GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility +$ref = GETPOST('ref', 'alpha'); +$lineid = GETPOST('lineid', 'int'); +$socid = GETPOST('socid', 'int'); +$action = GETPOST('action', 'aZ09'); + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetcontact', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permission = $user->rights->webhook->target->write; +} else { + $permissiontoread = 1; + $permission = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Add a new contact + */ + +if ($action == 'addcontact' && $permission) { + $contactid = (GETPOST('userid') ? GETPOST('userid', 'int') : GETPOST('contactid', 'int')); + $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); + $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09')); + + if ($result >= 0) { + header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); + exit; + } else { + if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $langs->load("errors"); + setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors'); + } else { + setEventMessages($object->error, $object->errors, 'errors'); + } + } +} elseif ($action == 'swapstatut' && $permission) { + // Toggle the status of a contact + $result = $object->swapContactStatus(GETPOST('ligne', 'int')); +} elseif ($action == 'deletecontact' && $permission) { + // Deletes a contact + $result = $object->delete_contact($lineid); + + if ($result >= 0) { + header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); + exit; + } else { + dol_print_error($db); + } +} + + +/* + * View + */ + +$title = $langs->trans('Target')." - ".$langs->trans('ContactsAddresses'); +$help_url = ''; +//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +llxHeader('', $title, $help_url); + +$form = new Form($db); +$formcompany = new FormCompany($db); +$contactstatic = new Contact($db); +$userstatic = new User($db); + + +/* *************************************************************************** */ +/* */ +/* View and edit mode */ +/* */ +/* *************************************************************************** */ + +if ($object->id) { + /* + * Show tabs + */ + $head = targetPrepareHead($object); + + print dol_get_fiche_head($head, 'contact', $langs->trans("Target"), -1, $object->picto); + + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); + + print dol_get_fiche_end(); + + print '
    '; + + // Contacts lines (modules that overwrite templates must declare this into descriptor) + $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl')); + foreach ($dirtpls as $reldir) { + $res = @include dol_buildpath($reldir.'/contacts.tpl.php'); + if ($res) { + break; + } + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/target_document.php b/htdocs/webhook/target_document.php new file mode 100644 index 00000000000..92ceca277c2 --- /dev/null +++ b/htdocs/webhook/target_document.php @@ -0,0 +1,261 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_document.php + * \ingroup webhook + * \brief Tab for documents linked to Target + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +dol_include_once('/webhook/class/target.class.php'); +dol_include_once('/webhook/lib/webhook_target.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "companies", "other", "mails")); + + +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm'); +$id = (GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int')); +$ref = GETPOST('ref', 'alpha'); + +// Get parameters +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortorder) { + $sortorder = "ASC"; +} +if (!$sortfield) { + $sortfield = "name"; +} +//if (! $sortfield) $sortfield="position_name"; + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetdocument', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->webhook->multidir_output[$object->entity ? $object->entity : $conf->entity]."/target/".get_exdir(0, 0, 0, 1, $object); +} + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permissiontoadd = $user->rights->webhook->target->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php +} else { + $permissiontoread = 1; + $permissiontoadd = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; + + +/* + * View + */ + +$form = new Form($db); + +$title = $langs->trans("Target").' - '.$langs->trans("Files"); +$help_url = ''; +//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +llxHeader('', $title, $help_url); + +if ($object->id) { + /* + * Show tabs + */ + $head = targetPrepareHead($object); + + print dol_get_fiche_head($head, 'document', $langs->trans("Target"), -1, $object->picto); + + + // Build file list + $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ?SORT_DESC:SORT_ASC), 1); + $totalsize = 0; + foreach ($filearray as $key => $file) { + $totalsize += $file['size']; + } + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + + print '
    '; + print ''; + + // Number of files + print ''; + + // Total size + print ''; + + print '
    '.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
    '.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
    '; + + print '
    '; + + print dol_get_fiche_end(); + + $modulepart = 'webhook'; + //$permissiontoadd = $user->rights->webhook->target->write; + $permissiontoadd = 1; + //$permtoedit = $user->rights->webhook->target->write; + $permtoedit = 1; + $param = '&id='.$object->id; + + //$relativepathwithnofile='target/' . dol_sanitizeFileName($object->id).'/'; + $relativepathwithnofile = 'target/'.dol_sanitizeFileName($object->ref).'/'; + + include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; +} else { + accessforbidden('', 0, 1); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/target_list.php b/htdocs/webhook/target_list.php new file mode 100644 index 00000000000..e62969e62ea --- /dev/null +++ b/htdocs/webhook/target_list.php @@ -0,0 +1,813 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_list.php + * \ingroup webhook + * \brief List page for target + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification +//if (! defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; + +// load webhook libraries +require_once __DIR__.'/class/target.class.php'; + +// for other modules +//dol_include_once('/othermodule/class/otherobject.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "other")); + +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'targetlist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$mode = GETPOST('mode', 'aZ'); + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters + $page = 0; +} +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetlist')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +//$extrafields->fetch_name_optionals_label($object->table_element_line); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) { + reset($object->fields); // Reset is required to avoid key() to return null. + $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. +} +if (!$sortorder) { + $sortorder = "ASC"; +} + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha') !== '') { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int')); + $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); + } +} + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) { + if (!empty($val['searchall'])) { + $fieldstosearchall['t.'.$key] = $val['label']; + } +} + +// Definition of array of fields for columns +$arrayfields = array(); +foreach ($object->fields as $key => $val) { + // If $val['visible']==0, then we never show the field + if (!empty($val['visible'])) { + $visible = (int) dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=> isset($val['help']) ? $val['help'] : '' + ); + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +//$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permissiontoadd = $user->rights->webhook->target->write; + $permissiontodelete = $user->rights->webhook->target->delete; +} else { + $permissiontoread = 1; + $permissiontoadd = 1; + $permissiontodelete = 1; +} + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) accessforbidden(); +//$socid = 0; if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, 0, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden('Module not enabled'); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + foreach ($object->fields as $key => $val) { + $search[$key] = ''; + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = ''; + $search[$key.'_dtend'] = ''; + } + } + $toselect = array(); + $search_array_options = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'Target'; + $objectlabel = 'Target'; + $uploaddir = $conf->webhook->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * View + */ + +$form = new Form($db); + +$now = dol_now(); +//$help_url = "EN:Module_Target|FR:Module_Target_FR|ES:Módulo_Target"; +$help_url = ''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Targets")); +$morejs = array(); +$morecss = array(); + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +$sql .= $object->getFieldList('t'); +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); + } +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +//$sql .= ", COUNT(rc.rowid) as anotherfield"; +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; +//$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."anothertable as rc ON rc.parent = t.rowid"; +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +} +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; +} else { + $sql .= " WHERE 1 = 1"; +} +foreach ($search as $key => $val) { + if (array_key_exists($key, $object->fields)) { + if ($key == 'status' && $search[$key] == -1) { + continue; + } + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) { + if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) { + $search[$key] = ''; + } + $mode_search = 2; + } + if ($search[$key] != '') { + $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search)); + } + } else { + if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { + $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key); + if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { + if (preg_match('/_dtstart$/', $key)) { + $sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'"; + } + if (preg_match('/_dtend$/', $key)) { + $sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'"; + } + } + } + } +} +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} +//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); +// Add where from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +/* If a group by is required +$sql .= " GROUP BY "; +foreach($object->fields as $key => $val) { + $sql .= "t.".$db->escape($key).", "; +} +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); + } +} +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql = preg_replace('/,\s*$/', '', $sql); +*/ + +// Add HAVING from hooks +/* +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint; +*/ + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); + */ + /* The slow method does not consume memory on mysql (not tested on pgsql) */ + /*$resql = $db->query($sql, 0, 'auto', 1); + while ($db->fetch_object($resql)) { + if (empty($nbtotalofrecords)) { + $nbtotalofrecords = 1; // We can't make +1 because init value is '' + } else { + $nbtotalofrecords++; + } + }*/ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + + +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".dol_buildpath('/webhook/target_card.php', 1).'?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- +$title = $langs->trans("Targets"); +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); + +if ($mode == 'modulesetup') { + require_once 'lib/webhook.lib.php'; + + $help_url = ''; + $page_name = "WebhookSetup"; + // Subheader + $linkback = ''.$langs->trans("BackToModuleList").''; + print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + + $head = webhookAdminPrepareHead(); + print dol_get_fiche_head($head, 'targets', $langs->trans($page_name), -1, "webhook@webhook"); +} + +// Example : Adding jquery code +// print ''; + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); +} +foreach ($search as $key => $val) { + if (is_array($search[$key]) && count($search[$key])) { + foreach ($search[$key] as $skey) { + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } + } + } elseif ($search[$key] != '') { + $param .= '&search_'.$key.'='.urlencode($search[$key]); + } +} +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); +} +// Add $param from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), + //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), +); +if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
    '."\n"; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + + +$newcardbutton = ''; +//$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/^&mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); +//$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/^&mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition')); +//$newcardbutton .= dolGetButtonTitleSeparator(); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/webhook/target_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']).'?mode=modulesetup', '', $permissiontoadd); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, "", 0, $newcardbutton, '', $limit, 0, 0, 1); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendTargetRef"; +$modelmail = "target"; +$objecttmp = new Target($db); +$trackid = 'xxxx'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) { + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + } + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; +} + +$moreforfilter = ''; +/*$moreforfilter.='
    '; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
    ';*/ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; +} + +if (!empty($moreforfilter)) { + print '
    '; + print $moreforfilter; + print '
    '; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +/*if (!empty($arrayfields['anotherfield']['checked'])) { + print ''; +}*/ +// Action column +print ''; +print ''."\n"; + +$totalarray = array(); +$totalarray['nbfield'] = 0; + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + $totalarray['nbfield']++; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +/*if (!empty($arrayfields['anotherfield']['checked'])) { + print ''; + $totalarray['nbfield']++; +}*/ +// Action column +print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +$totalarray['nbfield']++; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { + if (preg_match('/\$object/', $val)) { + $needToFetchEachLine++; // There is at least one compute field that use $object + } + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$savnbfield = $totalarray['nbfield']; +$totalarray['nbfield'] = 0; +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } + + // Store properties in $object + $object->setVarsFromFetchObj($obj); + + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + } + } else { + // Show here line of result + $j = 0; + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + /*if (!empty($arrayfields['anotherfield']['checked'])) { + print ''; + }*/ + // Action column + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + + print ''."\n"; + } + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
    '; + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); + } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + print '
    '; + print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
    '; + print '
    '; + print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
    '; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; + } + print '
    '; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
    '.$langs->trans("AnotherField").'
    '; + print '
    '; + } + // Output Kanban + print $object->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + print '
    '; + print '
    '.$obj->anotherfield.''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    '."\n"; +print '
    '."\n"; + +print '
    '."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) { + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) { + $hidegeneratedfilelistifempty = 0; + } + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_webhook', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/target_note.php b/htdocs/webhook/target_note.php new file mode 100644 index 00000000000..bb12d0947e8 --- /dev/null +++ b/htdocs/webhook/target_note.php @@ -0,0 +1,221 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file target_note.php + * \ingroup webhook + * \brief Tab for notes on Target + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +dol_include_once('/webhook/class/target.class.php'); +dol_include_once('/webhook/lib/webhook_target.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Target($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('targetnote', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->webhook->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity]."/".$object->id; +} + + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->webhook->target->read; + $permissiontoadd = $user->rights->webhook->target->write; + $permissionnote = $user->rights->webhook->target->write; // Used by the include of actions_setnotes.inc.php +} else { + $permissiontoread = 1; + $permissiontoadd = 1; + $permissionnote = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->webhook->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once +} + + +/* + * View + */ + +$form = new Form($db); + +//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; +$help_url = ''; +$title = $langs->trans('Target').' - '.$langs->trans("Notes"); +llxHeader('', $title, $help_url); + +if ($id > 0 || !empty($ref)) { + $object->fetch_thirdparty(); + + $head = targetPrepareHead($object); + + print dol_get_fiche_head($head, 'note', $langs->trans("Target"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + + + $cssclass = "titlefield"; + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/webhook/webhookindex.php b/htdocs/webhook/webhookindex.php new file mode 100644 index 00000000000..e62c5e3ddae --- /dev/null +++ b/htdocs/webhook/webhookindex.php @@ -0,0 +1,241 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2015 Jean-François Ferry + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file webhook/webhookindex.php + * \ingroup webhook + * \brief Home page of webhook top menu + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("webhook@webhook")); + +$action = GETPOST('action', 'aZ09'); + + +// Security check +// if (! $user->rights->webhook->myobject->read) { +// accessforbidden(); +// } +$socid = GETPOST('socid', 'int'); +if (isset($user->socid) && $user->socid > 0) { + $action = ''; + $socid = $user->socid; +} + +$max = 5; +$now = dol_now(); + + +/* + * Actions + */ + +// None + + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); + +llxHeader("", $langs->trans("WebhookArea")); + +print load_fiche_titre($langs->trans("WebhookArea"), '', 'webhook.png@webhook'); + +print '
    '; + + +/* BEGIN MODULEBUILDER DRAFT MYOBJECT +// Draft MyObject +if (! empty($conf->webhook->enabled) && $user->rights->webhook->read) +{ + $langs->load("orders"); + + $sql = "SELECT c.rowid, c.ref, c.ref_client, c.total_ht, c.tva as total_tva, c.total_ttc, s.rowid as socid, s.nom as name, s.client, s.canvas"; + $sql.= ", s.code_client"; + $sql.= " FROM ".MAIN_DB_PREFIX."commande as c"; + $sql.= ", ".MAIN_DB_PREFIX."societe as s"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.fk_soc = s.rowid"; + $sql.= " AND c.fk_statut = 0"; + $sql.= " AND c.entity IN (".getEntity('commande').")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); + if ($socid) $sql.= " AND c.fk_soc = ".((int) $socid); + + $resql = $db->query($sql); + if ($resql) + { + $total = 0; + $num = $db->num_rows($resql); + + print ''; + print ''; + print ''; + + $var = true; + if ($num > 0) + { + $i = 0; + while ($i < $num) + { + + $obj = $db->fetch_object($resql); + print ''; + print ''; + print ''; + $i++; + $total += $obj->total_ttc; + } + if ($total>0) + { + + print '"; + } + } + else + { + + print ''; + } + print "
    '.$langs->trans("DraftMyObjects").($num?''.$num.'':'').'
    '; + + $myobjectstatic->id=$obj->rowid; + $myobjectstatic->ref=$obj->ref; + $myobjectstatic->ref_client=$obj->ref_client; + $myobjectstatic->total_ht = $obj->total_ht; + $myobjectstatic->total_tva = $obj->total_tva; + $myobjectstatic->total_ttc = $obj->total_ttc; + + print $myobjectstatic->getNomUrl(1); + print ''; + print ''.price($obj->total_ttc).'
    '.$langs->trans("Total").''.price($total)."
    '.$langs->trans("NoOrder").'

    "; + + $db->free($resql); + } + else + { + dol_print_error($db); + } +} +END MODULEBUILDER DRAFT MYOBJECT */ + + +print '
    '; + + +$NBMAX = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; +$max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; + +/* BEGIN MODULEBUILDER LASTMODIFIED MYOBJECT +// Last modified myobject +if (! empty($conf->webhook->enabled) && $user->rights->webhook->read) +{ + $sql = "SELECT s.rowid, s.ref, s.label, s.date_creation, s.tms"; + $sql.= " FROM ".MAIN_DB_PREFIX."webhook_myobject as s"; + //if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE s.entity IN (".getEntity($myobjectstatic->element).")"; + //if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); + //if ($socid) $sql.= " AND s.rowid = $socid"; + $sql .= " ORDER BY s.tms DESC"; + $sql .= $db->plimit($max, 0); + + $resql = $db->query($sql); + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + + print ''; + print ''; + print ''; + print ''; + print ''; + if ($num) + { + while ($i < $num) + { + $objp = $db->fetch_object($resql); + + $myobjectstatic->id=$objp->rowid; + $myobjectstatic->ref=$objp->ref; + $myobjectstatic->label=$objp->label; + $myobjectstatic->status = $objp->status; + + print ''; + print ''; + print '"; + print '"; + print ''; + $i++; + } + + $db->free($resql); + } else { + print ''; + } + print "
    '; + print $langs->trans("BoxTitleLatestModifiedMyObjects", $max); + print ''.$langs->trans("DateModificationShort").'
    '.$myobjectstatic->getNomUrl(1).''; + print "'.dol_print_date($db->jdate($objp->tms), 'day')."
    '.$langs->trans("None").'

    "; + } +} +*/ + +print '
    '; + +// End of page +llxFooter(); +$db->close(); diff --git a/test/phpunit/WebhookFunctionalTest.php b/test/phpunit/WebhookFunctionalTest.php new file mode 100644 index 00000000000..9012e7b7105 --- /dev/null +++ b/test/phpunit/WebhookFunctionalTest.php @@ -0,0 +1,304 @@ + + * Copyright (C) 2022 SuperAdmin + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file test/phpunit/WebhookFunctionalTest.php + * \ingroup webhook + * \brief Example Selenium test. + * + * Put detailed description here. + */ + +namespace test\functional; + +use PHPUnit_Extensions_Selenium2TestCase_WebDriverException; + +/** + * Class WebhookFunctionalTest + * + * Requires chromedriver for Google Chrome + * Requires geckodriver for Mozilla Firefox + * + * @fixme Firefox (Geckodriver/Marionette) support + * @todo Opera linux support + * @todo Windows support (IE, Google Chrome, Mozilla Firefox, Safari) + * @todo OSX support (Safari, Google Chrome, Mozilla Firefox) + * + * @package Testwebhook + */ +class WebhookFunctionalTest extends \PHPUnit_Extensions_Selenium2TestCase +{ + // TODO: move to a global configuration file? + /** @var string Base URL of the webserver under test */ + protected static $base_url = 'http://dev.zenfusion.fr'; + /** + * @var string Dolibarr admin username + * @see authenticate + */ + protected static $dol_admin_user = 'admin'; + /** + * @var string Dolibarr admin password + * @see authenticate + */ + protected static $dol_admin_pass = 'admin'; + /** @var int Dolibarr module ID */ + private static $module_id = 500000; // TODO: autodetect? + + /** @var array Browsers to test with */ + public static $browsers = array( + array( + 'browser' => 'Google Chrome on Linux', + 'browserName' => 'chrome', + 'sessionStrategy' => 'shared', + 'desiredCapabilities' => array() + ), + // Geckodriver does not keep the session at the moment?! + // XPath selectors also don't seem to work + //array( + // 'browser' => 'Mozilla Firefox on Linux', + // 'browserName' => 'firefox', + // 'sessionStrategy' => 'shared', + // 'desiredCapabilities' => array( + // 'marionette' => true, + // ), + //) + ); + + /** + * Helper function to select links by href + * + * @param string $value Href + * @return mixed Helper string + */ + protected function byHref($value) + { + $anchor = null; + $anchors = $this->elements($this->using('tag name')->value('a')); + foreach ($anchors as $anchor) { + if (strstr($anchor->attribute('href'), $value)) { + break; + } + } + return $anchor; + } + + /** + * Global test setup + * @return void + */ + public static function setUpBeforeClass() + { + } + + /** + * Unit test setup + * @return void + */ + public function setUp() + { + $this->setSeleniumServerRequestsTimeout(3600); + $this->setBrowserUrl(self::$base_url); + } + + /** + * Verify pre conditions + * @return void + */ + protected function assertPreConditions() + { + } + + /** + * Handle Dolibarr authentication + * @return void + */ + private function authenticate() + { + try { + if ($this->byId('login')) { + $login = $this->byId('username'); + $login->clear(); + $login->value('admin'); + $password = $this->byId('password'); + $password->clear(); + $password->value('admin'); + $this->byId('login')->submit(); + } + } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + // Login does not exist. Assume we are already authenticated + } + } + + /** + * Test enabling developer mode + * @return bool + */ + public function testEnableDeveloperMode() + { + $this->url('/admin/const.php'); + $this->authenticate(); + $main_features_level_path = '//input[@value="MAIN_FEATURES_LEVEL"]/following::input[@type="text"]'; + $main_features_level = $this->byXPath($main_features_level_path); + $main_features_level->clear(); + $main_features_level->value('2'); + $this->byName('update')->click(); + // Page reloaded, we need a new XPath + $main_features_level = $this->byXPath($main_features_level_path); + return $this->assertEquals('2', $main_features_level->value(), "MAIN_FEATURES_LEVEL value is 2"); + } + + /** + * Test enabling the module + * + * @depends testEnableDeveloperMode + * @return bool + */ + public function testModuleEnabled() + { + $this->url('/admin/modules.php'); + $this->authenticate(); + $module_status_image_path = '//a[contains(@href, "'.self::$module_id.'")]/img'; + $module_status_image = $this->byXPath($module_status_image_path); + if (strstr($module_status_image->attribute('src'), 'switch_off.png')) { + // Enable the module + $this->byHref('modWebhook')->click(); + } else { + // Disable the module + $this->byHref('modWebhook')->click(); + // Reenable the module + $this->byHref('modWebhook')->click(); + } + // Page reloaded, we need a new Xpath + $module_status_image = $this->byXPath($module_status_image_path); + return $this->assertContains('switch_on.png', $module_status_image->attribute('src'), "Module enabled"); + } + + /** + * Test access to the configuration page + * + * @depends testModuleEnabled + * @return bool + */ + public function testConfigurationPage() + { + $this->url('/custom/webhook/admin/setup.php'); + $this->authenticate(); + return $this->assertContains('webhook/admin/setup.php', $this->url(), 'Configuration page'); + } + + /** + * Test access to the about page + * + * @depends testConfigurationPage + * @return bool + */ + public function testAboutPage() + { + $this->url('/custom/webhook/admin/about.php'); + $this->authenticate(); + return $this->assertContains('webhook/admin/about.php', $this->url(), 'About page'); + } + + /** + * Test about page is rendering Markdown + * + * @depends testAboutPage + * @return bool + */ + public function testAboutPageRendersMarkdownReadme() + { + $this->url('/custom/webhook/admin/about.php'); + $this->authenticate(); + return $this->assertEquals( + 'Dolibarr Module Template (aka My Module)', + $this->byTag('h1')->text(), + "Readme title" + ); + } + + /** + * Test box is properly declared + * + * @depends testModuleEnabled + * @return bool + */ + public function testBoxDeclared() + { + $this->url('/admin/boxes.php'); + $this->authenticate(); + return $this->assertContains('webhookwidget1', $this->source(), "Box enabled"); + } + + /** + * Test trigger is properly enabled + * + * @depends testModuleEnabled + * @return bool + */ + public function testTriggerDeclared() + { + $this->url('/admin/triggers.php'); + $this->authenticate(); + return $this->assertContains( + 'interface_99_modWebhook_WebhookTriggers.class.php', + $this->byTag('body')->text(), + "Trigger declared" + ); + } + + /** + * Test trigger is properly declared + * + * @depends testTriggerDeclared + * @return bool + */ + public function testTriggerEnabled() + { + $this->url('/admin/triggers.php'); + $this->authenticate(); + return $this->assertContains( + 'tick.png', + $this->byXPath('//td[text()="interface_99_modWebhook_MyTrigger.class.php"]/following::img')->attribute('src'), + "Trigger enabled" + ); + } + + /** + * Verify post conditions + * @return void + */ + protected function assertPostConditions() + { + } + + /** + * Unit test teardown + * @return void + */ + public function tearDown() + { + } + + /** + * Global test teardown + * @return void + */ + public static function tearDownAfterClass() + { + } +} From 13e05b875de3120db7b6c682e27d8dd36ca092eb Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Mon, 2 May 2022 15:07:41 +0200 Subject: [PATCH 012/421] remove unused files --- htdocs/core/modules/modWebhook.class.php | 2 +- htdocs/langs/en_US/admin.lang | 5 + htdocs/langs/en_US/webhook.lang | 49 - htdocs/webhook/class/target.class.php | 9 +- htdocs/webhook/class/target.class.php.back | 1090 +++++++++++++++++ .../modules/webhook/mod_target_advanced.php | 146 --- .../modules/webhook/mod_target_standard.php | 161 --- .../core/modules/webhook/modules_target.php | 158 --- htdocs/webhook/lib/webhook_target.lib.php | 8 +- htdocs/webhook/target_document.php | 261 ---- test/phpunit/WebhookFunctionalTest.php | 304 ----- 11 files changed, 1103 insertions(+), 1090 deletions(-) delete mode 100644 htdocs/langs/en_US/webhook.lang create mode 100644 htdocs/webhook/class/target.class.php.back delete mode 100644 htdocs/webhook/core/modules/webhook/mod_target_advanced.php delete mode 100644 htdocs/webhook/core/modules/webhook/mod_target_standard.php delete mode 100644 htdocs/webhook/core/modules/webhook/modules_target.php delete mode 100644 htdocs/webhook/target_document.php delete mode 100644 test/phpunit/WebhookFunctionalTest.php diff --git a/htdocs/core/modules/modWebhook.class.php b/htdocs/core/modules/modWebhook.class.php index 4a4467d205f..92fdfca6d28 100644 --- a/htdocs/core/modules/modWebhook.class.php +++ b/htdocs/core/modules/modWebhook.class.php @@ -72,7 +72,7 @@ class modWebhook extends DolibarrModules $this->editor_url = 'https://www.example.com'; // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' - $this->version = 'dolibarr'; + $this->version = 'development'; // Url to the file with your last numberversion of this module //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 1dc7d4e2092..50e803bb1aa 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2234,3 +2234,8 @@ TemplateforBusinessCards=Template for a business card in different size InventorySetup= Inventory Setup ExportUseLowMemoryMode=Use a low memory mode ExportUseLowMemoryModeHelp=Use the low memory mode to execute the exec of the dump (compression is done through a pipe instead of into the PHP memory). This method does not allow to check that file is completed and error message can't be reported if it fails. +ModuleWebhookName = Webhook +ModuleWebhookDesc = Interface to catch dolibarr triggers and send it to an URL +WebhookSetup = Webhook setup +Settings = Settings +WebhookSetupPage = Webhook setup page \ No newline at end of file diff --git a/htdocs/langs/en_US/webhook.lang b/htdocs/langs/en_US/webhook.lang deleted file mode 100644 index 1c09e925559..00000000000 --- a/htdocs/langs/en_US/webhook.lang +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2022 SuperAdmin -# -# 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 -# (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 -# along with this program. If not, see . - -# -# Generic -# - -# Module label 'ModuleWebhookName' -ModuleWebhookName = Webhook -# Module description 'ModuleWebhookDesc' -ModuleWebhookDesc = Interface to catch dolibarr triggers and send it to an URL - -# -# Admin page -# -WebhookSetup = Webhook setup -Settings = Settings -WebhookSetupPage = Webhook setup page -WEBHOOK_AUTOVALIDATE = Allow targets automatic validation - - -# -# About page -# -About = About -WebhookAbout = About Webhook -WebhookAboutPage = Webhook about page - -# -# Sample page -# - -# -# Sample widget -# -MyWidget = My widget -MyWidgetDescription = My widget description diff --git a/htdocs/webhook/class/target.class.php b/htdocs/webhook/class/target.class.php index e977842ad79..d768f7c5c36 100644 --- a/htdocs/webhook/class/target.class.php +++ b/htdocs/webhook/class/target.class.php @@ -56,7 +56,7 @@ class Target extends CommonObject /** * @var int Does object support extrafields ? 0=No, 1=Yes */ - public $isextrafieldmanaged = 1; + public $isextrafieldmanaged = 0; /** * @var string String with name of icon for target. Must be the part after the 'object_' into object_target.png @@ -103,7 +103,7 @@ class Target extends CommonObject */ public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), - 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'validate'=>'1', 'comment'=>"Reference of object"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'index'=>1, 'searchall'=>1, 'validate'=>'1', 'comment'=>"Reference of object"), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'help'=>"Help text", 'showoncombobox'=>'2', 'validate'=>'1',), 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3, 'validate'=>'1',), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), @@ -112,9 +112,7 @@ class Target extends CommonObject 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), - 'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>0,), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), - 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>2000, 'notnull'=>1, 'visible'=>3, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validé', '9'=>'Annulé'), 'validate'=>'1',), 'url' => array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1,), 'trigger_codes' => array('type'=>'text', 'label'=>'TriggerCodes', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1, 'help'=>"TriggerCodeInfo",), @@ -129,9 +127,7 @@ class Target extends CommonObject public $tms; public $fk_user_creat; public $fk_user_modif; - public $last_main_doc; public $import_key; - public $model_pdf; public $status; public $url; public $trigger_codes; @@ -227,6 +223,7 @@ class Target extends CommonObject public function create(User $user, $notrigger = false) { $resultcreate = $this->createCommon($user, $notrigger); + $this->ref = $this->id; if ($resultcreate <= 0) { return $resultcreate; diff --git a/htdocs/webhook/class/target.class.php.back b/htdocs/webhook/class/target.class.php.back new file mode 100644 index 00000000000..acb40530bc1 --- /dev/null +++ b/htdocs/webhook/class/target.class.php.back @@ -0,0 +1,1090 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * (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 + * along with this program. If not, see . + */ + +/** + * \file class/target.class.php + * \ingroup webhook + * \brief This file is a CRUD class file for Target (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Target + */ +class Target extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'webhook'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'target'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'webhook_target'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * @var string String with name of icon for target. Must be the part after the 'object_' into object_target.png + */ + public $picto = 'webhook'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_CANCELED = 9; + + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or '!empty($conf->multicurrency->enabled)' ...) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'index'=>1, 'searchall'=>1, 'validate'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'help'=>"Help text", 'showoncombobox'=>'2', 'validate'=>'1',), + 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3, 'validate'=>'1',), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>0,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>2000, 'notnull'=>1, 'visible'=>3, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validé', '9'=>'Annulé'), 'validate'=>'1',), + 'url' => array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1,), + 'trigger_codes' => array('type'=>'text', 'label'=>'TriggerCodes', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>1, 'help'=>"TriggerCodeInfo",), + ); + public $rowid; + public $ref; + public $label; + public $description; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $last_main_doc; + public $import_key; + public $status; + public $url; + public $trigger_codes; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + // /** + // * @var string Name of subtable line + // */ + // public $table_element_line = 'webhook_targetline'; + + // /** + // * @var string Field with ID of parent key if this object has a parent + // */ + // public $fk_element = 'fk_target'; + + // /** + // * @var string Name of subtable class that manage subtable lines + // */ + // public $class_element_line = 'Targetline'; + + // /** + // * @var array List of child tables. To test if we can delete object. + // */ + // protected $childtables = array(); + + // /** + // * @var array List of child tables. To know object to delete on cascade. + // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + // */ + // protected $childtablesoncascade = array('webhook_targetdet'); + + // /** + // * @var TargetLine[] Array of subtable lines + // */ + // public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { + $this->fields['rowid']['visible'] = 0; + } + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) { + $this->fields['entity']['enabled'] = 0; + } + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->webhook->target->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + $resultcreate = $this->createCommon($user, $notrigger); + $this->ref = $this->id; + + if ($resultcreate <= 0) { + return $resultcreate; + } + $resultvalidate = $this->validate($user, $notrigger); + + return $resultvalidate; + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && !empty($object->table_element_line)) { + $object->fetchLines(); + } + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) { + $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + } + if (property_exists($object, 'label')) { + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + } + if (property_exists($object, 'status')) { + $object->status = self::STATUS_DRAFT; + } + if (property_exists($object, 'date_creation')) { + $object->date_creation = dol_now(); + } + if (property_exists($object, 'date_modification')) { + $object->date_modification = null; + } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) { + $error++; + } + } + + if (!$error) { + // copy external contacts if same company + if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) { + if ($this->copy_linked_contact($object, 'external') < 0) { + $error++; + } + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) { + $this->fetchLines(); + } + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = "SELECT "; + $sql .= $this->getFieldList('t'); + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + } else { + $sql .= " WHERE 1 = 1"; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->target->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->target->target_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) { + $sql .= ", date_validation = '".$this->db->idate($now)."'"; + } + if (!empty($this->fields['fk_user_valid'])) { + $sql .= ", fk_user_valid = ".((int) $user->id); + } + $sql .= " WHERE rowid = ".((int) $this->id); + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('TARGET_VALIDATE', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + } + + if (!$error) { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'target/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'target/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { + $error++; $this->error = $this->db->lasterror(); + } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->webhook->dir_output.'/target/'.$oldref; + $dirdest = $conf->webhook->dir_output.'/target/'.$newref; + if (!$error && file_exists($dirsource)) { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->webhook->dir_output.'/target/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'TARGET_UNVALIDATE'); + } + + /** + * Set cancel status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function cancel($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_VALIDATED) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'TARGET_CANCEL'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->webhook->webhook_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'TARGET_REOPEN'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) { + $notooltip = 1; // Force disable tooltips + } + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("Target").''; + if (isset($this->status)) { + $label .= ' '.$this->getLibStatut(5); + } + $label .= '
    '; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + + $url = dol_buildpath('/webhook/target_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { + $add_save_lastsearch_values = 1; + } + if ($url && $add_save_lastsearch_values) { + $url .= '&save_lastsearch_values=1'; + } + } + + $linkclose = ''; + if (empty($notooltip)) { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + $label = $langs->trans("ShowTarget"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else { + $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + } + + if ($option == 'nolink' || empty($url)) { + $linkstart = ''; + if ($option == 'nolink' || empty($url)) { + $linkend = ''; + } else { + $linkend = ''; + } + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
    No photo
    '; + } else { + $result .= '
    No photo
    '; + } + + $result .= ''; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) { + $result .= $this->ref; + } + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('targetdao')); + $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 + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } + + return $result; + } + + /** + * Return the label of the status + * + * @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 getLabelStatus($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the label of the status + * + * @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 getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @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 + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + //$langs->load("webhook@webhook"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + if ($status == self::STATUS_CANCELED) { + $statusType = 'status6'; + } + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = "SELECT rowid, date_creation as datec, tms as datem,"; + $sql .= " fk_user_creat, fk_user_modif"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".((int) $id); + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if (!empty($obj->fk_user_author)) { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if (!empty($obj->fk_user_valid)) { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if (!empty($obj->fk_user_cloture)) { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + // Set here init that are not commonf fields + // $this->property1 = ... + // $this->property2 = ... + + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new TargetLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_target = '.((int) $this->id))); + + if (is_numeric($result)) { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("webhook@webhook"); + + if (empty($conf->global->WEBHOOK_TARGET_ADDON)) { + $conf->global->WEBHOOK_TARGET_ADDON = 'mod_target_standard'; + } + + if (!empty($conf->global->WEBHOOK_TARGET_ADDON)) { + $mybool = false; + + $file = $conf->global->WEBHOOK_TARGET_ADDON.".php"; + $classname = $conf->global->WEBHOOK_TARGET_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/webhook/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 0; + + $langs->load("webhook@webhook"); + + if (!dol_strlen($modele)) { + $modele = 'standard_target'; + + if (!empty($this->model_pdf)) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->TARGET_ADDON_PDF)) { + $modele = $conf->global->TARGET_ADDON_PDF; + } + } + + $modelpath = "core/modules/webhook/doc/"; + + if ($includedocgeneration && !empty($modele)) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} + + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + +/** + * Class TargetLine. You can also remove this and generate a CRUD class for lines objects. + */ +class TargetLine extends CommonObjectLine +{ + // To complete with content of an object TargetLine + // We should have a field rowid, fk_target and position + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } +} diff --git a/htdocs/webhook/core/modules/webhook/mod_target_advanced.php b/htdocs/webhook/core/modules/webhook/mod_target_advanced.php deleted file mode 100644 index 52dade35b89..00000000000 --- a/htdocs/webhook/core/modules/webhook/mod_target_advanced.php +++ /dev/null @@ -1,146 +0,0 @@ - - * Copyright (C) 2004-2007 Laurent Destailleur - * Copyright (C) 2005-2009 Regis Houssin - * Copyright (C) 2008 Raphael Bertrand (Resultic) - * Copyright (C) 2019 Frédéric France - * - * 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 - * (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 - * along with this program. If not, see . - * or see https://www.gnu.org/ - */ - -/** - * \file htdocs/core/modules/webhook/mod_target_advanced.php - * \ingroup webhook - * \brief File containing class for advanced numbering model of Target - */ - -dol_include_once('/webhook/core/modules/webhook/modules_target.php'); - - -/** - * Class to manage customer Bom numbering rules advanced - */ -class mod_target_advanced extends ModeleNumRefTarget -{ - /** - * Dolibarr version of the loaded document - * @var string - */ - public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' - - /** - * @var string Error message - */ - public $error = ''; - - /** - * @var string name - */ - public $name = 'advanced'; - - - /** - * Returns the description of the numbering model - * - * @return string Texte descripif - */ - public function info() - { - global $conf, $langs, $db; - - $langs->load("bills"); - - $form = new Form($db); - - $texte = $langs->trans('GenericNumRefModelDesc')."
    \n"; - $texte .= '
    '; - $texte .= ''; - $texte .= ''; - $texte .= ''; - $texte .= ''; - - $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("Target"), $langs->transnoentities("Target")); - $tooltip .= $langs->trans("GenericMaskCodes2"); - $tooltip .= $langs->trans("GenericMaskCodes3"); - $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("Target"), $langs->transnoentities("Target")); - $tooltip .= $langs->trans("GenericMaskCodes5"); - - // Parametrage du prefix - $texte .= ''; - $texte .= ''; - $texte .= ''; - $texte .= ''; - - $texte .= '
    '.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
    '; - $texte .= '
    '; - - return $texte; - } - - /** - * Return an example of numbering - * - * @return string Example - */ - public function getExample() - { - global $conf, $db, $langs, $mysoc; - - $object = new Target($db); - $object->initAsSpecimen(); - - /*$old_code_client = $mysoc->code_client; - $old_code_type = $mysoc->typent_code; - $mysoc->code_client = 'CCCCCCCCCC'; - $mysoc->typent_code = 'TTTTTTTTTT';*/ - - $numExample = $this->getNextValue($object); - - /*$mysoc->code_client = $old_code_client; - $mysoc->typent_code = $old_code_type;*/ - - if (!$numExample) { - $numExample = $langs->trans('NotConfigured'); - } - return $numExample; - } - - /** - * Return next free value - * - * @param Object $object Object we need next value for - * @return string Value if KO, <0 if KO - */ - public function getNextValue($object) - { - global $db, $conf; - - require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; - - // We get cursor rule - $mask = $conf->global->WEBHOOK_TARGET_ADVANCED_MASK; - - if (!$mask) { - $this->error = 'NotConfigured'; - return 0; - } - - $date = $object->date; - - $numFinal = get_next_value($db, $mask, 'webhook_target', 'ref', '', null, $date); - - return $numFinal; - } -} diff --git a/htdocs/webhook/core/modules/webhook/mod_target_standard.php b/htdocs/webhook/core/modules/webhook/mod_target_standard.php deleted file mode 100644 index f3202e9e895..00000000000 --- a/htdocs/webhook/core/modules/webhook/mod_target_standard.php +++ /dev/null @@ -1,161 +0,0 @@ - - * Copyright (C) 2005-2009 Regis Houssin - * - * 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 - * (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 - * along with this program. If not, see . - * or see https://www.gnu.org/ - */ - -/** - * \file htdocs/core/modules/webhook/mod_target_standard.php - * \ingroup webhook - * \brief File of class to manage Target numbering rules standard - */ -dol_include_once('/webhook/core/modules/webhook/modules_target.php'); - - -/** - * Class to manage customer order numbering rules standard - */ -class mod_target_standard extends ModeleNumRefTarget -{ - /** - * Dolibarr version of the loaded document - * @var string - */ - public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' - - public $prefix = 'TARGET'; - - /** - * @var string Error code (or message) - */ - public $error = ''; - - /** - * @var string name - */ - public $name = 'standard'; - - - /** - * Return description of numbering module - * - * @return string Text with description - */ - public function info() - { - global $langs; - return $langs->trans("SimpleNumRefModelDesc", $this->prefix); - } - - - /** - * Return an example of numbering - * - * @return string Example - */ - public function getExample() - { - return $this->prefix."0501-0001"; - } - - - /** - * Checks if the numbers already in the database do not - * cause conflicts that would prevent this numbering working. - * - * @param Object $object Object we need next value for - * @return boolean false if conflict, true if ok - */ - public function canBeActivated($object) - { - global $conf, $langs, $db; - - $coyymm = ''; $max = ''; - - $posindice = strlen($this->prefix) + 6; - $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; - $sql .= " FROM ".MAIN_DB_PREFIX."webhook_target"; - $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - if ($object->ismultientitymanaged == 1) { - $sql .= " AND entity = ".$conf->entity; - } elseif ($object->ismultientitymanaged == 2) { - // TODO - } - - $resql = $db->query($sql); - if ($resql) { - $row = $db->fetch_row($resql); - if ($row) { - $coyymm = substr($row[0], 0, 6); $max = $row[0]; - } - } - if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { - $langs->load("errors"); - $this->error = $langs->trans('ErrorNumRefModel', $max); - return false; - } - - return true; - } - - /** - * Return next free value - * - * @param Object $object Object we need next value for - * @return string Value if KO, <0 if KO - */ - public function getNextValue($object) - { - global $db, $conf; - - // first we get the max value - $posindice = strlen($this->prefix) + 6; - $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; - $sql .= " FROM ".MAIN_DB_PREFIX."webhook_target"; - $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - if ($object->ismultientitymanaged == 1) { - $sql .= " AND entity = ".$conf->entity; - } elseif ($object->ismultientitymanaged == 2) { - // TODO - } - - $resql = $db->query($sql); - if ($resql) { - $obj = $db->fetch_object($resql); - if ($obj) { - $max = intval($obj->max); - } else { - $max = 0; - } - } else { - dol_syslog("mod_target_standard::getNextValue", LOG_DEBUG); - return -1; - } - - //$date=time(); - $date = $object->date_creation; - $yymm = strftime("%y%m", $date); - - if ($max >= (pow(10, 4) - 1)) { - $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is - } else { - $num = sprintf("%04s", $max + 1); - } - - dol_syslog("mod_target_standard::getNextValue return ".$this->prefix.$yymm."-".$num); - return $this->prefix.$yymm."-".$num; - } -} diff --git a/htdocs/webhook/core/modules/webhook/modules_target.php b/htdocs/webhook/core/modules/webhook/modules_target.php deleted file mode 100644 index 9f1f253f9a5..00000000000 --- a/htdocs/webhook/core/modules/webhook/modules_target.php +++ /dev/null @@ -1,158 +0,0 @@ - - * Copyright (C) 2004-2011 Laurent Destailleur - * Copyright (C) 2004 Eric Seigne - * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2006 Andre Cianfarani - * Copyright (C) 2012 Juanjo Menent - * Copyright (C) 2014 Marcos García - * - * 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 - * (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 - * along with this program. If not, see . - * or see https://www.gnu.org/ - */ - -/** - * \file htdocs/core/modules/webhook/modules_target.php - * \ingroup webhook - * \brief File that contains parent class for targets document models and parent class for targets numbering models - */ - -require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; -require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // required for use by classes that inherit - - -/** - * Parent class for documents models - */ -abstract class ModelePDFTarget extends CommonDocGenerator -{ - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Return list of active generation modules - * - * @param DoliDB $db Database handler - * @param integer $maxfilenamelength Max length of value to show - * @return array List of templates - */ - public static function liste_modeles($db, $maxfilenamelength = 0) - { - // phpcs:enable - global $conf; - - $type = 'target'; - $list = array(); - - include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; - $list = getListOfModels($db, $type, $maxfilenamelength); - - return $list; - } -} - - - -/** - * Parent class to manage numbering of Target - */ -abstract class ModeleNumRefTarget -{ - /** - * @var string Error code (or message) - */ - public $error = ''; - - /** - * Return if a module can be used or not - * - * @return boolean true if module can be used - */ - public function isEnabled() - { - return true; - } - - /** - * Returns the default description of the numbering template - * - * @return string Texte descripif - */ - public function info() - { - global $langs; - $langs->load("webhook@webhook"); - return $langs->trans("NoDescription"); - } - - /** - * Returns an example of numbering - * - * @return string Example - */ - public function getExample() - { - global $langs; - $langs->load("webhook@webhook"); - return $langs->trans("NoExample"); - } - - /** - * Checks if the numbers already in the database do not - * cause conflicts that would prevent this numbering working. - * - * @param Object $object Object we need next value for - * @return boolean false if conflict, true if ok - */ - public function canBeActivated($object) - { - return true; - } - - /** - * Returns next assigned value - * - * @param Object $object Object we need next value for - * @return string Valeur - */ - public function getNextValue($object) - { - global $langs; - return $langs->trans("NotAvailable"); - } - - /** - * Returns version of numbering module - * - * @return string Valeur - */ - public function getVersion() - { - global $langs; - $langs->load("admin"); - - if ($this->version == 'development') { - return $langs->trans("VersionDevelopment"); - } - if ($this->version == 'experimental') { - return $langs->trans("VersionExperimental"); - } - if ($this->version == 'dolibarr') { - return DOL_VERSION; - } - if ($this->version) { - return $this->version; - } - return $langs->trans("NotAvailable"); - } -} diff --git a/htdocs/webhook/lib/webhook_target.lib.php b/htdocs/webhook/lib/webhook_target.lib.php index e5c0d09bb85..fb01a8f95aa 100644 --- a/htdocs/webhook/lib/webhook_target.lib.php +++ b/htdocs/webhook/lib/webhook_target.lib.php @@ -57,7 +57,7 @@ function targetPrepareHead($object) $h++; } - require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + /*require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $upload_dir = $conf->webhook->dir_output."/target/".dol_sanitizeFileName($object->ref); $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); @@ -68,12 +68,12 @@ function targetPrepareHead($object) $head[$h][1] .= ''.($nbFiles + $nbLinks).''; } $head[$h][2] = 'document'; - $h++; + $h++;*/ - $head[$h][0] = dol_buildpath("/webhook/target_agenda.php", 1).'?id='.$object->id; + /*$head[$h][0] = dol_buildpath("/webhook/target_agenda.php", 1).'?id='.$object->id; $head[$h][1] = $langs->trans("Events"); $head[$h][2] = 'agenda'; - $h++; + $h++;*/ // Show more tabs from modules // Entries must be declared in modules descriptor with line diff --git a/htdocs/webhook/target_document.php b/htdocs/webhook/target_document.php deleted file mode 100644 index 92ceca277c2..00000000000 --- a/htdocs/webhook/target_document.php +++ /dev/null @@ -1,261 +0,0 @@ - - * Copyright (C) ---Put here your own copyright and developer email--- - * - * 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 - * (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 - * along with this program. If not, see . - */ - -/** - * \file target_document.php - * \ingroup webhook - * \brief Tab for documents linked to Target - */ - -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user -//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs -//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). -//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) -//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data -//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu -//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php -//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library -//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. -//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip -//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value -//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler -//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message -//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies -//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET -//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification - -// Load Dolibarr environment -$res = 0; -// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) -if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { - $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; -} -// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME -$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; -while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { - $i--; $j--; -} -if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { - $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; -} -if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { - $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; -} -// Try main.inc.php using relative path -if (!$res && file_exists("../main.inc.php")) { - $res = @include "../main.inc.php"; -} -if (!$res && file_exists("../../main.inc.php")) { - $res = @include "../../main.inc.php"; -} -if (!$res && file_exists("../../../main.inc.php")) { - $res = @include "../../../main.inc.php"; -} -if (!$res) { - die("Include of main fails"); -} - -require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -dol_include_once('/webhook/class/target.class.php'); -dol_include_once('/webhook/lib/webhook_target.lib.php'); - -// Load translation files required by the page -$langs->loadLangs(array("webhook@webhook", "companies", "other", "mails")); - - -$action = GETPOST('action', 'aZ09'); -$confirm = GETPOST('confirm'); -$id = (GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int')); -$ref = GETPOST('ref', 'alpha'); - -// Get parameters -$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST('sortorder', 'aZ09comma'); -$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -if (empty($page) || $page == -1) { - $page = 0; -} // If $page is not defined, or '' or -1 -$offset = $limit * $page; -$pageprev = $page - 1; -$pagenext = $page + 1; -if (!$sortorder) { - $sortorder = "ASC"; -} -if (!$sortfield) { - $sortfield = "name"; -} -//if (! $sortfield) $sortfield="position_name"; - -// Initialize technical objects -$object = new Target($db); -$extrafields = new ExtraFields($db); -$diroutputmassaction = $conf->webhook->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('targetdocument', 'globalcard')); // Note that conf->hooks_modules contains array -// Fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label($object->table_element); - -// Load object -include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals - -if ($id > 0 || !empty($ref)) { - $upload_dir = $conf->webhook->multidir_output[$object->entity ? $object->entity : $conf->entity]."/target/".get_exdir(0, 0, 0, 1, $object); -} - -// There is several ways to check permission. -// Set $enablepermissioncheck to 1 to enable a minimum low level of checks -$enablepermissioncheck = 0; -if ($enablepermissioncheck) { - $permissiontoread = $user->rights->webhook->target->read; - $permissiontoadd = $user->rights->webhook->target->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php -} else { - $permissiontoread = 1; - $permissiontoadd = 1; -} - -// Security check (enable the most restrictive one) -//if ($user->socid > 0) accessforbidden(); -//if ($user->socid > 0) $socid = $user->socid; -//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); -if (empty($conf->webhook->enabled)) accessforbidden(); -if (!$permissiontoread) accessforbidden(); - - -/* - * Actions - */ - -include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; - - -/* - * View - */ - -$form = new Form($db); - -$title = $langs->trans("Target").' - '.$langs->trans("Files"); -$help_url = ''; -//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; -llxHeader('', $title, $help_url); - -if ($object->id) { - /* - * Show tabs - */ - $head = targetPrepareHead($object); - - print dol_get_fiche_head($head, 'document', $langs->trans("Target"), -1, $object->picto); - - - // Build file list - $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ?SORT_DESC:SORT_ASC), 1); - $totalsize = 0; - foreach ($filearray as $key => $file) { - $totalsize += $file['size']; - } - - // Object card - // ------------------------------------------------------------ - $linkback = ''.$langs->trans("BackToList").''; - - $morehtmlref = '
    '; - /* - // Ref customer - $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); - $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); - // Thirdparty - $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; - if ($permissiontoadd) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref .= ': '.$proj->getNomUrl(); - } else { - $morehtmlref .= ''; - } - } - }*/ - $morehtmlref .= '
    '; - - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); - - print '
    '; - - print '
    '; - print ''; - - // Number of files - print ''; - - // Total size - print ''; - - print '
    '.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
    '.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
    '; - - print '
    '; - - print dol_get_fiche_end(); - - $modulepart = 'webhook'; - //$permissiontoadd = $user->rights->webhook->target->write; - $permissiontoadd = 1; - //$permtoedit = $user->rights->webhook->target->write; - $permtoedit = 1; - $param = '&id='.$object->id; - - //$relativepathwithnofile='target/' . dol_sanitizeFileName($object->id).'/'; - $relativepathwithnofile = 'target/'.dol_sanitizeFileName($object->ref).'/'; - - include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; -} else { - accessforbidden('', 0, 1); -} - -// End of page -llxFooter(); -$db->close(); diff --git a/test/phpunit/WebhookFunctionalTest.php b/test/phpunit/WebhookFunctionalTest.php deleted file mode 100644 index 9012e7b7105..00000000000 --- a/test/phpunit/WebhookFunctionalTest.php +++ /dev/null @@ -1,304 +0,0 @@ - - * Copyright (C) 2022 SuperAdmin - * - * 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 - * (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 - * along with this program. If not, see . - */ - -/** - * \file test/phpunit/WebhookFunctionalTest.php - * \ingroup webhook - * \brief Example Selenium test. - * - * Put detailed description here. - */ - -namespace test\functional; - -use PHPUnit_Extensions_Selenium2TestCase_WebDriverException; - -/** - * Class WebhookFunctionalTest - * - * Requires chromedriver for Google Chrome - * Requires geckodriver for Mozilla Firefox - * - * @fixme Firefox (Geckodriver/Marionette) support - * @todo Opera linux support - * @todo Windows support (IE, Google Chrome, Mozilla Firefox, Safari) - * @todo OSX support (Safari, Google Chrome, Mozilla Firefox) - * - * @package Testwebhook - */ -class WebhookFunctionalTest extends \PHPUnit_Extensions_Selenium2TestCase -{ - // TODO: move to a global configuration file? - /** @var string Base URL of the webserver under test */ - protected static $base_url = 'http://dev.zenfusion.fr'; - /** - * @var string Dolibarr admin username - * @see authenticate - */ - protected static $dol_admin_user = 'admin'; - /** - * @var string Dolibarr admin password - * @see authenticate - */ - protected static $dol_admin_pass = 'admin'; - /** @var int Dolibarr module ID */ - private static $module_id = 500000; // TODO: autodetect? - - /** @var array Browsers to test with */ - public static $browsers = array( - array( - 'browser' => 'Google Chrome on Linux', - 'browserName' => 'chrome', - 'sessionStrategy' => 'shared', - 'desiredCapabilities' => array() - ), - // Geckodriver does not keep the session at the moment?! - // XPath selectors also don't seem to work - //array( - // 'browser' => 'Mozilla Firefox on Linux', - // 'browserName' => 'firefox', - // 'sessionStrategy' => 'shared', - // 'desiredCapabilities' => array( - // 'marionette' => true, - // ), - //) - ); - - /** - * Helper function to select links by href - * - * @param string $value Href - * @return mixed Helper string - */ - protected function byHref($value) - { - $anchor = null; - $anchors = $this->elements($this->using('tag name')->value('a')); - foreach ($anchors as $anchor) { - if (strstr($anchor->attribute('href'), $value)) { - break; - } - } - return $anchor; - } - - /** - * Global test setup - * @return void - */ - public static function setUpBeforeClass() - { - } - - /** - * Unit test setup - * @return void - */ - public function setUp() - { - $this->setSeleniumServerRequestsTimeout(3600); - $this->setBrowserUrl(self::$base_url); - } - - /** - * Verify pre conditions - * @return void - */ - protected function assertPreConditions() - { - } - - /** - * Handle Dolibarr authentication - * @return void - */ - private function authenticate() - { - try { - if ($this->byId('login')) { - $login = $this->byId('username'); - $login->clear(); - $login->value('admin'); - $password = $this->byId('password'); - $password->clear(); - $password->value('admin'); - $this->byId('login')->submit(); - } - } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { - // Login does not exist. Assume we are already authenticated - } - } - - /** - * Test enabling developer mode - * @return bool - */ - public function testEnableDeveloperMode() - { - $this->url('/admin/const.php'); - $this->authenticate(); - $main_features_level_path = '//input[@value="MAIN_FEATURES_LEVEL"]/following::input[@type="text"]'; - $main_features_level = $this->byXPath($main_features_level_path); - $main_features_level->clear(); - $main_features_level->value('2'); - $this->byName('update')->click(); - // Page reloaded, we need a new XPath - $main_features_level = $this->byXPath($main_features_level_path); - return $this->assertEquals('2', $main_features_level->value(), "MAIN_FEATURES_LEVEL value is 2"); - } - - /** - * Test enabling the module - * - * @depends testEnableDeveloperMode - * @return bool - */ - public function testModuleEnabled() - { - $this->url('/admin/modules.php'); - $this->authenticate(); - $module_status_image_path = '//a[contains(@href, "'.self::$module_id.'")]/img'; - $module_status_image = $this->byXPath($module_status_image_path); - if (strstr($module_status_image->attribute('src'), 'switch_off.png')) { - // Enable the module - $this->byHref('modWebhook')->click(); - } else { - // Disable the module - $this->byHref('modWebhook')->click(); - // Reenable the module - $this->byHref('modWebhook')->click(); - } - // Page reloaded, we need a new Xpath - $module_status_image = $this->byXPath($module_status_image_path); - return $this->assertContains('switch_on.png', $module_status_image->attribute('src'), "Module enabled"); - } - - /** - * Test access to the configuration page - * - * @depends testModuleEnabled - * @return bool - */ - public function testConfigurationPage() - { - $this->url('/custom/webhook/admin/setup.php'); - $this->authenticate(); - return $this->assertContains('webhook/admin/setup.php', $this->url(), 'Configuration page'); - } - - /** - * Test access to the about page - * - * @depends testConfigurationPage - * @return bool - */ - public function testAboutPage() - { - $this->url('/custom/webhook/admin/about.php'); - $this->authenticate(); - return $this->assertContains('webhook/admin/about.php', $this->url(), 'About page'); - } - - /** - * Test about page is rendering Markdown - * - * @depends testAboutPage - * @return bool - */ - public function testAboutPageRendersMarkdownReadme() - { - $this->url('/custom/webhook/admin/about.php'); - $this->authenticate(); - return $this->assertEquals( - 'Dolibarr Module Template (aka My Module)', - $this->byTag('h1')->text(), - "Readme title" - ); - } - - /** - * Test box is properly declared - * - * @depends testModuleEnabled - * @return bool - */ - public function testBoxDeclared() - { - $this->url('/admin/boxes.php'); - $this->authenticate(); - return $this->assertContains('webhookwidget1', $this->source(), "Box enabled"); - } - - /** - * Test trigger is properly enabled - * - * @depends testModuleEnabled - * @return bool - */ - public function testTriggerDeclared() - { - $this->url('/admin/triggers.php'); - $this->authenticate(); - return $this->assertContains( - 'interface_99_modWebhook_WebhookTriggers.class.php', - $this->byTag('body')->text(), - "Trigger declared" - ); - } - - /** - * Test trigger is properly declared - * - * @depends testTriggerDeclared - * @return bool - */ - public function testTriggerEnabled() - { - $this->url('/admin/triggers.php'); - $this->authenticate(); - return $this->assertContains( - 'tick.png', - $this->byXPath('//td[text()="interface_99_modWebhook_MyTrigger.class.php"]/following::img')->attribute('src'), - "Trigger enabled" - ); - } - - /** - * Verify post conditions - * @return void - */ - protected function assertPostConditions() - { - } - - /** - * Unit test teardown - * @return void - */ - public function tearDown() - { - } - - /** - * Global test teardown - * @return void - */ - public static function tearDownAfterClass() - { - } -} From ce41d3ed09dcf5b13d2f481dcc425fcbb9f2ff95 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Mon, 2 May 2022 15:42:26 +0200 Subject: [PATCH 013/421] remove target extrafields --- htdocs/admin/target_extrafields.php | 143 ---------------------------- 1 file changed, 143 deletions(-) delete mode 100644 htdocs/admin/target_extrafields.php diff --git a/htdocs/admin/target_extrafields.php b/htdocs/admin/target_extrafields.php deleted file mode 100644 index 8ab40dc0d90..00000000000 --- a/htdocs/admin/target_extrafields.php +++ /dev/null @@ -1,143 +0,0 @@ - - * Copyright (C) 2003 Jean-Louis Bergamo - * Copyright (C) 2004-2011 Laurent Destailleur - * Copyright (C) 2012 Regis Houssin - * Copyright (C) 2014 Florian Henry - * Copyright (C) 2015 Jean-François Ferry - * - * 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 - * (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 - * along with this program. If not, see . - */ - -/** - * \file admin/target_extrafields.php - * \ingroup webhook - * \brief Page to setup extra fields of target - */ - -// Load Dolibarr environment -$res = 0; -// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) -if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { - $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; -} -// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME -$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; -while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { - $i--; $j--; -} -if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { - $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; -} -if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { - $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; -} -// Try main.inc.php using relative path -if (!$res && file_exists("../../main.inc.php")) { - $res = @include "../../main.inc.php"; -} -if (!$res && file_exists("../../../main.inc.php")) { - $res = @include "../../../main.inc.php"; -} -if (!$res) { - die("Include of main fails"); -} - -require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; -require_once '../lib/webhook.lib.php'; - -// Load translation files required by the page -$langs->loadLangs(array('webhook@webhook', 'admin')); - -$extrafields = new ExtraFields($db); -$form = new Form($db); - -// List of supported format -$tmptype2label = ExtraFields::$type2label; -$type2label = array(''); -foreach ($tmptype2label as $key => $val) { - $type2label[$key] = $langs->transnoentitiesnoconv($val); -} - -$action = GETPOST('action', 'aZ09'); -$attrname = GETPOST('attrname', 'alpha'); -$elementtype = 'webhook_target'; //Must be the $table_element of the class that manage extrafield - -if (!$user->admin) { - accessforbidden(); -} - - -/* - * Actions - */ - -require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; - - - -/* - * View - */ - -$help_url = ''; -$page_name = "WebhookSetup"; - -llxHeader('', $langs->trans("WebhookSetup"), $help_url); - - -$linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); - - -$head = webhookAdminPrepareHead(); - -print dol_get_fiche_head($head, 'target_extrafields', $langs->trans($page_name), -1, 'webhook@webhook'); - -require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; - -print dol_get_fiche_end(); - - -// Buttons -if ($action != 'create' && $action != 'edit') { - print '
    '; - print "".$langs->trans("NewAttribute").""; - print "
    "; -} - - -/* - * Creation of an optional field - */ -if ($action == 'create') { - print '
    '; - print load_fiche_titre($langs->trans('NewAttribute')); - - require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; -} - -/* - * Edition of an optional field - */ -if ($action == 'edit' && !empty($attrname)) { - print "
    "; - print load_fiche_titre($langs->trans("FieldEdition", $attrname)); - - require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; -} - -// End of page -llxFooter(); -$db->close(); From af28c050f6692ff199d37809e1f459ca0bf2c90f Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Wed, 4 May 2022 10:20:31 +0200 Subject: [PATCH 014/421] remove of dol build path in Triggers --- .../triggers/interface_99_modWebhook_WebhookTriggers.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php index f49e0ef4499..d5d95c59ef3 100644 --- a/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php +++ b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php @@ -31,7 +31,7 @@ */ require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; -require_once dol_buildpath("webhook/class/target.class.php"); +require_once DOL_DOCUMENT_ROOT.'/webhook/class/target.class.php'; /** * Class of triggers for Webhook module From 2b84dc39de6042ef7a50798af19e5d986899620b Mon Sep 17 00:00:00 2001 From: Lucas Marcouiller Date: Fri, 20 May 2022 17:03:36 +0200 Subject: [PATCH 015/421] fix error management --- htdocs/core/lib/functions.lib.php | 4 ++-- htdocs/core/modules/modWebhook.class.php | 4 ++-- .../interface_99_modWebhook_WebhookTriggers.class.php | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 34d4120db24..b45bcc6040d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3754,7 +3754,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'recent', 'reception', 'recruitmentcandidature', 'recruitmentjobposition', 'resource', 'recurring', 'shapes', 'square', 'stop-circle', 'supplier', 'supplier_proposal', 'supplier_order', 'supplier_invoice', 'timespent', 'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda', - 'uncheck', 'user-cog', 'user-injured', 'user-md', 'vat', 'website', 'workstation', + 'uncheck', 'user-cog', 'user-injured', 'user-md', 'vat', 'website', 'workstation', 'webhook', 'conferenceorbooth', 'eventorganization' ))) { $fakey = $pictowithouttext; @@ -3805,7 +3805,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'title_agenda'=>'calendar-alt', 'uncheck'=>'times', 'uparrow'=>'share', 'vat'=>'money-check-alt', 'vcard'=>'address-card', 'jabber'=>'comment-o', - 'website'=>'globe-americas', 'workstation'=>'pallet', + 'website'=>'globe-americas', 'workstation'=>'pallet', 'webhook'=>'bullseye', 'conferenceorbooth'=>'chalkboard-teacher', 'eventorganization'=>'project-diagram' ); if ($pictowithouttext == 'off') { diff --git a/htdocs/core/modules/modWebhook.class.php b/htdocs/core/modules/modWebhook.class.php index 92fdfca6d28..fbcb5f81003 100644 --- a/htdocs/core/modules/modWebhook.class.php +++ b/htdocs/core/modules/modWebhook.class.php @@ -469,8 +469,8 @@ class modWebhook extends DolibarrModules { global $conf, $langs; - //$result = $this->_load_tables('/install/mysql/tables/', 'webhook'); - $result = $this->_load_tables('/webhook/sql/'); + $result = $this->_load_tables('/install/mysql/tables/', 'webhook'); + //$result = $this->_load_tables('/webhook/sql/'); if ($result < 0) { return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') } diff --git a/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php index d5d95c59ef3..335024554fc 100644 --- a/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php +++ b/htdocs/core/triggers/interface_99_modWebhook_WebhookTriggers.class.php @@ -93,6 +93,7 @@ class InterfaceWebhookTriggers extends DolibarrTriggers if (empty($conf->webhook) || empty($conf->webhook->enabled)) { return 0; // If module is not enabled, we do nothing } + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; // Or you can execute some code here $nbPosts = 0; @@ -104,10 +105,11 @@ class InterfaceWebhookTriggers extends DolibarrTriggers if (is_array($actionarray) && in_array($action, $actionarray)) { $jsonstr = '{"triggercode":'.json_encode($action).',"object":'.json_encode($object).'}'; $response = getURLContent($tmpobject->url, 'POST', $jsonstr); - if (empty($response['curl_error_no'])) { + if (empty($response['curl_error_no']) && $response['http_code'] >= 200 && $response['http_code'] < 300) { $nbPosts ++; } else { $errors ++; + dol_syslog("Failed to get url with httpcode=".(!empty($response['http_code']) ? $response['http_code'] : "")." curl_error_no=".(!empty($response['curl_error_no']) ? $response['curl_error_no'] : ""), LOG_DEBUG); } } } From e77bf4a320acc9e6bb6294681437b30eccce1a5b Mon Sep 17 00:00:00 2001 From: Norbert Penel Date: Fri, 20 May 2022 21:53:42 +0200 Subject: [PATCH 016/421] dangerous overwritting --- htdocs/core/class/commonobject.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index bf33cbe224e..da435f550d1 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6843,13 +6843,13 @@ abstract class CommonObject if ((!isset($this->fields[$key]['default'])) || ($this->fields[$key]['notnull'] != 1)) { $out .= ''; } - foreach ($param['options'] as $key => $val) { - if ((string) $key == '') { + foreach ($param['options'] as $index => $val) { + if ((string) $index == '') { continue; } if (strpos($val, "|") !== false) list($val, $parent) = explode('|', $val); - $out .= '
    '.$langs->trans("AutoApprovalOnCreate").''; - print ''; + print ''; print '
    '; print ''; @@ -485,13 +498,6 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { $sql .= ' WHERE 1=1 '; $sql .= !empty($morefilter) ? $morefilter : ''; - - if ($cancreate && !$cancreateall) { - } else { - //$sql .= ' AND u.fk_user = '.$user->id; - //$sql .= ' OR u.rowid ='.$user->id; - } - $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { @@ -586,13 +592,13 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { //auto validation ON CREATE print ''."\n"; //no auto SEND MAIL print ''."\n"; // Description @@ -641,6 +647,11 @@ if (is_object($db)) { */ function sendMail($id, $cancreate, $now, $autoValidation) { + $objStd = new stdClass(); + $objStd->msg = ''; + $objStd->status = 'success'; + $objStd->error = 0; + $objStd->style = ''; global $db, $user, $conf, $langs; @@ -657,19 +668,21 @@ function sendMail($id, $cancreate, $now, $autoValidation) $verif = $object->validate($user); - // If no SQL error, we redirect to the request form if ($verif > 0) { // To $destinataire = new User($db); $destinataire->fetch($object->fk_validator); $emailTo = $destinataire->email; - //@todo make object return errors - //@todo remove redisrection here ! + if (!$emailTo) { dol_syslog("Expected validator has no email, so we redirect directly to finished page without sending email"); - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroremailTo'); + $objStd->status = 'error'; + $objStd->style="warnings"; + return $objStd; } // From @@ -729,26 +742,34 @@ function sendMail($id, $cancreate, $now, $autoValidation) $result = $mail->sendfile(); if (!$result) { - setEventMessages($mail->error, $mail->errors, 'warnings'); - $action = ''; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroreSendmail'); + $objStd->style="warnings"; + $objStd->status = 'error'; } else { - //@todo make object return errors - //@todo remove redisrection here ! - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + + $objStd->msg = $langs->trans('mailSended'); } + + return $objStd; } else { - //@todo make object return errors - //@todo remove redisrection here ! - setEventMessages($object->error, $object->errors, 'errors'); - $action = ''; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroreVerif'); + $objStd->status = 'error'; + $objStd->style="errors"; + return $objStd; } } } else { - //@todo make object return errors - //@todo remove redisrection here ! - setEventMessage($langs->trans('ErrorloadUserOnSendingMail'), 'warning'); + + $objStd->error++; + $objStd->msg = $langs->trans('ErrorloadUserOnSendingMail'); + $objStd->status = 'error'; + $objStd->style="warnings"; + return $objStd; } - return 'objerrors'; + return $objStd; } From 189d918181f906e0caf7083d287481079f9b8e94 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 8 Jun 2022 15:14:18 +0000 Subject: [PATCH 029/421] Fixing style errors. --- htdocs/holiday/card_group.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 898d9f53be8..19f5e1a5fd8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -318,7 +318,6 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; } else { - //@TODO changer le nom si validated if ($autoValidation) { $htemp = new Holiday($db); @@ -336,7 +335,7 @@ if (empty($reshook)) { if ($AutoSendMail && !$error) { // send a mail to the user $returnSendMail = sendMail($result, $cancreate, $now, $autoValidation); - if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg,$returnSendMail->style); + if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg, $returnSendMail->style); } } } @@ -742,19 +741,16 @@ function sendMail($id, $cancreate, $now, $autoValidation) $result = $mail->sendfile(); if (!$result) { - $objStd->error++; $objStd->msg = $langs->trans('ErroreSendmail'); $objStd->style="warnings"; $objStd->status = 'error'; } else { - $objStd->msg = $langs->trans('mailSended'); } return $objStd; } else { - $objStd->error++; $objStd->msg = $langs->trans('ErroreVerif'); $objStd->status = 'error'; @@ -763,7 +759,6 @@ function sendMail($id, $cancreate, $now, $autoValidation) } } } else { - $objStd->error++; $objStd->msg = $langs->trans('ErrorloadUserOnSendingMail'); $objStd->status = 'error'; From 1dcc701251aae5acba82b39dd82b53eb7372b497 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Thu, 9 Jun 2022 13:10:46 +0200 Subject: [PATCH 030/421] Fixing bug 20500 --- htdocs/user/class/user.class.php | 68 ++++++++++++++++++-------------- test/phpunit/UserTest.php | 40 +++++++++++++++++-- 2 files changed, 75 insertions(+), 33 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 0a88e17eb02..143546fbe06 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -682,7 +682,7 @@ class User extends CommonObject 'member' => 'adherent', // We must check $user->rights->adherent... 'mo' => 'mrp', 'order' => 'commande', - 'product' => 'produit', // We must check $user->rights->produit... + //'product' => 'produit', // We must check $user->rights->produit... 'project' => 'projet', 'shipping' => 'expedition', 'task' => 'task@projet', @@ -695,14 +695,24 @@ class User extends CommonObject '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" ); + if (!empty($moduletomoduletouse[$module])) { $module = $moduletomoduletouse[$module]; } + $moduleRightsMapping = array( + 'product' => 'produit', // We must check $user->rights->produit... + ); + + $rightsPath = $module; + if (!empty($moduleRightsMapping[$rightsPath])) { + $rightsPath = $moduleRightsMapping[$rightsPath]; + } + // If module is abc@module, we check permission user->rights->module->abc->permlevel1 - $tmp = explode('@', $module, 2); + $tmp = explode('@', $rightsPath, 2); if (! empty($tmp[1])) { - $module = $tmp[1]; + $rightsPath = $tmp[1]; $permlevel2 = $permlevel1; $permlevel1 = $tmp[0]; } @@ -722,50 +732,50 @@ class User extends CommonObject } if ($permlevel1 == 'recruitmentcandidature') { $permlevel1 = 'recruitmentjobposition'; - } - - //var_dump($module.' '.$permlevel1.' '.$permlevel2); - if (empty($module) || empty($this->rights) || empty($this->rights->$module) || empty($permlevel1)) { + } + //var_dump($module.' '.$permlevel1.' '.$permlevel2. ' '. $rightsPath); + //var_dump($this->rights); + if (empty($rightsPath) || empty($this->rights) || empty($this->rights->$rightsPath) || empty($permlevel1)) { return 0; } - + if ($permlevel2) { - if (!empty($this->rights->$module->$permlevel1)) { - if (!empty($this->rights->$module->$permlevel1->$permlevel2)) { - return $this->rights->$module->$permlevel1->$permlevel2; + 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" - if ($permlevel2 == 'read' && !empty($this->rights->$module->$permlevel1->lire)) { - return $this->rights->$module->lire; + if ($permlevel2 == 'read' && !empty($this->rights->$rightsPath->$permlevel1->lire)) { + return $this->rights->$rightsPath->lire; } - if ($permlevel2 == 'write' && !empty($this->rights->$module->$permlevel1->creer)) { - return $this->rights->$module->create; + if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->creer)) { + return $this->rights->$rightsPath->create; } - if ($permlevel2 == 'write' && !empty($this->rights->$module->$permlevel1->create)) { - return $this->rights->$module->create; + if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->create)) { + return $this->rights->$rightsPath->create; } - if ($permlevel2 == 'delete' && !empty($this->rights->$module->$permlevel1->supprimer)) { - return $this->rights->$module->supprimer; + if ($permlevel2 == 'delete' && !empty($this->rights->$rightsPath->$permlevel1->supprimer)) { + return $this->rights->$rightsPath->supprimer; } } } else { - if (!empty($this->rights->$module->$permlevel1)) { - return $this->rights->$module->$permlevel1; + if (!empty($this->rights->$rightsPath->$permlevel1)) { + return $this->rights->$rightsPath->$permlevel1; } // For backward compatibility with old permissions called "lire", "creer", "create", "supprimer" // instead of "read", "write", "delete" - if ($permlevel1 == 'read' && !empty($this->rights->$module->lire)) { - return $this->rights->$module->lire; + if ($permlevel1 == 'read' && !empty($this->rights->$rightsPath->lire)) { + return $this->rights->$rightsPath->lire; } - if ($permlevel1 == 'write' && !empty($this->rights->$module->creer)) { - return $this->rights->$module->create; + if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->creer)) { + return $this->rights->$rightsPath->create; } - if ($permlevel1 == 'write' && !empty($this->rights->$module->create)) { - return $this->rights->$module->create; + if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->create)) { + return $this->rights->$rightsPath->create; } - if ($permlevel1 == 'delete' && !empty($this->rights->$module->supprimer)) { - return $this->rights->$module->supprimer; + if ($permlevel1 == 'delete' && !empty($this->rights->$rightsPath->supprimer)) { + return $this->rights->$rightsPath->supprimer; } } diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 699e9fd89f0..2b4ab4ea4f3 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -78,7 +78,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - public static function setUpBeforeClass() + public static function setUpBeforeClass() : void { global $conf,$user,$langs,$db; @@ -96,7 +96,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass() : void { global $conf,$user,$langs,$db; $db->rollback(); @@ -109,7 +109,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - protected function setUp() + protected function setUp() : void { global $conf,$user,$langs,$db; $conf=$this->savconf; @@ -125,7 +125,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - protected function tearDown() + protected function tearDown() : void { print __METHOD__."\n"; } @@ -261,6 +261,38 @@ class UserTest extends PHPUnit\Framework\TestCase return $localobject; } + /** + * testUserHasRight + * + * @param User $localobject User + * @return void + */ + + public function testUserHasRight() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + /*$result=$localobject->setstatus(0); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0); + */ + + print __METHOD__." id=". $user->id ."\n"; + //$this->assertNotEquals($user->date_creation, ''); + $user->addrights(0, 'supplier_proposal'); + + $this->assertEquals($user->hasRight('member', ''), 0); + $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); + $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); + $user->clearrights(); + //print __METHOD__. $user->hasRight('module', 'level11'); + return $user; + } + /** * testUserSetPassword * From 7f86c53b3e1173cf6a3518d3416fc7eeecc121ed Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Thu, 9 Jun 2022 13:15:40 +0200 Subject: [PATCH 031/421] fixing bug 20500 --- htdocs/user/class/user.class.php | 68 ++++++++++++++++++-------------- test/phpunit/UserTest.php | 36 ++++++++++++++++- 2 files changed, 73 insertions(+), 31 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 0a88e17eb02..143546fbe06 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -682,7 +682,7 @@ class User extends CommonObject 'member' => 'adherent', // We must check $user->rights->adherent... 'mo' => 'mrp', 'order' => 'commande', - 'product' => 'produit', // We must check $user->rights->produit... + //'product' => 'produit', // We must check $user->rights->produit... 'project' => 'projet', 'shipping' => 'expedition', 'task' => 'task@projet', @@ -695,14 +695,24 @@ class User extends CommonObject '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" ); + if (!empty($moduletomoduletouse[$module])) { $module = $moduletomoduletouse[$module]; } + $moduleRightsMapping = array( + 'product' => 'produit', // We must check $user->rights->produit... + ); + + $rightsPath = $module; + if (!empty($moduleRightsMapping[$rightsPath])) { + $rightsPath = $moduleRightsMapping[$rightsPath]; + } + // If module is abc@module, we check permission user->rights->module->abc->permlevel1 - $tmp = explode('@', $module, 2); + $tmp = explode('@', $rightsPath, 2); if (! empty($tmp[1])) { - $module = $tmp[1]; + $rightsPath = $tmp[1]; $permlevel2 = $permlevel1; $permlevel1 = $tmp[0]; } @@ -722,50 +732,50 @@ class User extends CommonObject } if ($permlevel1 == 'recruitmentcandidature') { $permlevel1 = 'recruitmentjobposition'; - } - - //var_dump($module.' '.$permlevel1.' '.$permlevel2); - if (empty($module) || empty($this->rights) || empty($this->rights->$module) || empty($permlevel1)) { + } + //var_dump($module.' '.$permlevel1.' '.$permlevel2. ' '. $rightsPath); + //var_dump($this->rights); + if (empty($rightsPath) || empty($this->rights) || empty($this->rights->$rightsPath) || empty($permlevel1)) { return 0; } - + if ($permlevel2) { - if (!empty($this->rights->$module->$permlevel1)) { - if (!empty($this->rights->$module->$permlevel1->$permlevel2)) { - return $this->rights->$module->$permlevel1->$permlevel2; + 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" - if ($permlevel2 == 'read' && !empty($this->rights->$module->$permlevel1->lire)) { - return $this->rights->$module->lire; + if ($permlevel2 == 'read' && !empty($this->rights->$rightsPath->$permlevel1->lire)) { + return $this->rights->$rightsPath->lire; } - if ($permlevel2 == 'write' && !empty($this->rights->$module->$permlevel1->creer)) { - return $this->rights->$module->create; + if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->creer)) { + return $this->rights->$rightsPath->create; } - if ($permlevel2 == 'write' && !empty($this->rights->$module->$permlevel1->create)) { - return $this->rights->$module->create; + if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->create)) { + return $this->rights->$rightsPath->create; } - if ($permlevel2 == 'delete' && !empty($this->rights->$module->$permlevel1->supprimer)) { - return $this->rights->$module->supprimer; + if ($permlevel2 == 'delete' && !empty($this->rights->$rightsPath->$permlevel1->supprimer)) { + return $this->rights->$rightsPath->supprimer; } } } else { - if (!empty($this->rights->$module->$permlevel1)) { - return $this->rights->$module->$permlevel1; + if (!empty($this->rights->$rightsPath->$permlevel1)) { + return $this->rights->$rightsPath->$permlevel1; } // For backward compatibility with old permissions called "lire", "creer", "create", "supprimer" // instead of "read", "write", "delete" - if ($permlevel1 == 'read' && !empty($this->rights->$module->lire)) { - return $this->rights->$module->lire; + if ($permlevel1 == 'read' && !empty($this->rights->$rightsPath->lire)) { + return $this->rights->$rightsPath->lire; } - if ($permlevel1 == 'write' && !empty($this->rights->$module->creer)) { - return $this->rights->$module->create; + if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->creer)) { + return $this->rights->$rightsPath->create; } - if ($permlevel1 == 'write' && !empty($this->rights->$module->create)) { - return $this->rights->$module->create; + if ($permlevel1 == 'write' && !empty($this->rights->$rightsPath->create)) { + return $this->rights->$rightsPath->create; } - if ($permlevel1 == 'delete' && !empty($this->rights->$module->supprimer)) { - return $this->rights->$module->supprimer; + if ($permlevel1 == 'delete' && !empty($this->rights->$rightsPath->supprimer)) { + return $this->rights->$rightsPath->supprimer; } } diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 699e9fd89f0..9f106e6e207 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -78,7 +78,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - public static function setUpBeforeClass() + public static function setUpBeforeClass() { global $conf,$user,$langs,$db; @@ -125,7 +125,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - protected function tearDown() + protected function tearDown() { print __METHOD__."\n"; } @@ -261,6 +261,38 @@ class UserTest extends PHPUnit\Framework\TestCase return $localobject; } + /** + * testUserHasRight + * + * @param User $localobject User + * @return void + */ + + public function testUserHasRight() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + /*$result=$localobject->setstatus(0); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0); + */ + + print __METHOD__." id=". $user->id ."\n"; + //$this->assertNotEquals($user->date_creation, ''); + $user->addrights(0, 'supplier_proposal'); + + $this->assertEquals($user->hasRight('member', ''), 0); + $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); + $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); + $user->clearrights(); + //print __METHOD__. $user->hasRight('module', 'level11'); + return $user; + } + /** * testUserSetPassword * From e729d76833b08d827486640c9e5a6211540717e9 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Thu, 9 Jun 2022 13:19:26 +0200 Subject: [PATCH 032/421] removing some spaces --- test/phpunit/UserTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 9f106e6e207..d25f7471fc8 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -78,7 +78,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - public static function setUpBeforeClass() + public static function setUpBeforeClass() { global $conf,$user,$langs,$db; @@ -125,7 +125,7 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - protected function tearDown() + protected function tearDown() { print __METHOD__."\n"; } From 7b3fe948a01dc645ccaefb73457eca5ad55f66ac Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 9 Jun 2022 11:20:59 +0000 Subject: [PATCH 033/421] Fixing style errors. --- htdocs/user/class/user.class.php | 6 +++--- test/phpunit/UserTest.php | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 143546fbe06..1e6a116686f 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -703,7 +703,7 @@ class User extends CommonObject $moduleRightsMapping = array( 'product' => 'produit', // We must check $user->rights->produit... ); - + $rightsPath = $module; if (!empty($moduleRightsMapping[$rightsPath])) { $rightsPath = $moduleRightsMapping[$rightsPath]; @@ -732,13 +732,13 @@ class User extends CommonObject } if ($permlevel1 == 'recruitmentcandidature') { $permlevel1 = 'recruitmentjobposition'; - } + } //var_dump($module.' '.$permlevel1.' '.$permlevel2. ' '. $rightsPath); //var_dump($this->rights); if (empty($rightsPath) || empty($this->rights) || empty($this->rights->$rightsPath) || empty($permlevel1)) { return 0; } - + if ($permlevel2) { if (!empty($this->rights->$rightsPath->$permlevel1)) { if (!empty($this->rights->$rightsPath->$permlevel1->$permlevel2)) { diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index d25f7471fc8..c67d610c931 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -263,11 +263,11 @@ class UserTest extends PHPUnit\Framework\TestCase /** * testUserHasRight - * + * * @param User $localobject User * @return void */ - + public function testUserHasRight() { global $conf,$user,$langs,$db; @@ -282,17 +282,17 @@ class UserTest extends PHPUnit\Framework\TestCase */ print __METHOD__." id=". $user->id ."\n"; - //$this->assertNotEquals($user->date_creation, ''); - $user->addrights(0, 'supplier_proposal'); - - $this->assertEquals($user->hasRight('member', ''), 0); + //$this->assertNotEquals($user->date_creation, ''); + $user->addrights(0, 'supplier_proposal'); + + $this->assertEquals($user->hasRight('member', ''), 0); $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); $user->clearrights(); //print __METHOD__. $user->hasRight('module', 'level11'); return $user; } - + /** * testUserSetPassword * From ef8b041ac6b5aafccff18792c02b8004acf980a9 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Thu, 9 Jun 2022 13:29:02 +0200 Subject: [PATCH 034/421] resolving phpcs errors --- test/phpunit/UserTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index c67d610c931..0a7431c171f 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -264,10 +264,8 @@ class UserTest extends PHPUnit\Framework\TestCase /** * testUserHasRight * - * @param User $localobject User - * @return void - */ - + * @return void + */ public function testUserHasRight() { global $conf,$user,$langs,$db; @@ -275,7 +273,6 @@ class UserTest extends PHPUnit\Framework\TestCase $user=$this->savuser; $langs=$this->savlangs; $db=$this->savdb; - /*$result=$localobject->setstatus(0); print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertLessThan($result, 0); From 3d0a8dd5959650c83999e76e2e522fe5bb60e45c Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Thu, 9 Jun 2022 13:29:49 +0200 Subject: [PATCH 035/421] running phpcs one last time --- htdocs/user/class/user.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 1e6a116686f..96a614857ba 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -675,7 +675,6 @@ class User extends CommonObject public function hasRight($module, $permlevel1, $permlevel2 = '') { global $conf; - // For compatibility with bad naming permissions on module $moduletomoduletouse = array( 'contract' => 'contrat', From b63b7b242d7dec94d74915b2ca5f7b3cb31307cd Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami <73450837+Quatadah@users.noreply.github.com> Date: Thu, 9 Jun 2022 19:32:38 +0200 Subject: [PATCH 036/421] Delete .phpunit.result.cache --- test/phpunit/.phpunit.result.cache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/phpunit/.phpunit.result.cache diff --git a/test/phpunit/.phpunit.result.cache b/test/phpunit/.phpunit.result.cache deleted file mode 100644 index f2f8f46386b..00000000000 --- a/test/phpunit/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -C:37:"PHPUnit\Runner\DefaultTestResultCache":455:{a:2:{s:7:"defects";a:1:{s:26:"UserTest::testUserHasRight";i:4;}s:5:"times";a:9:{s:24:"UserTest::testUserCreate";d:0.123;s:23:"UserTest::testUserFetch";d:0.002;s:24:"UserTest::testUserUpdate";d:0.048;s:25:"UserTest::testUserDisable";d:0.005;s:23:"UserTest::testUserOther";d:0.002;s:29:"UserTest::testUserSetPassword";d:0.378;s:24:"UserTest::testUserDelete";d:0.006;s:31:"UserTest::testUserAddPermission";d:0.005;s:26:"UserTest::testUserHasRight";d:0.007;}}} \ No newline at end of file From 19cb81e3ea3247ded71b35c58bbab6e4e35d1070 Mon Sep 17 00:00:00 2001 From: jpb Date: Sat, 11 Jun 2022 10:16:04 +0200 Subject: [PATCH 037/421] change filter array method on users selection from groups --- htdocs/holiday/card_group.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 898d9f53be8..07beaeeb678 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -259,7 +259,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); - + // usergroup select /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; @@ -268,15 +268,13 @@ if (empty($reshook)) { if ($resql) { while ($obj = $db->fetch_object($resql)) { - if (!array_key_exists($obj->rowid, $TusersToProcess)) - $TusersToProcess[] = $obj->rowid; + $TusersToProcess[$obj->rowid] = $obj->rowid; } } /** USERS */ if (is_array($users) && count($users) > 0) { foreach ($users as $u) { - if (!array_key_exists($u, $TusersToProcess)) - $TusersToProcess[] = $u; + $TusersToProcess[$u] = $u; } } foreach ($TusersToProcess as $u) { From 1af3b6ccbddd6ba5fdc3c12ba36babb281ebcc94 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 11 Jun 2022 08:23:08 +0000 Subject: [PATCH 038/421] Fixing style errors. --- htdocs/holiday/card_group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 93560b9bb7c..c52ea39681d 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -259,7 +259,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); - // usergroup select + // usergroup select /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; From 74d23cccd8c6e84efb87d4be862c82bd8e8b91ec Mon Sep 17 00:00:00 2001 From: jpb Date: Sat, 11 Jun 2022 14:01:54 +0200 Subject: [PATCH 039/421] remove seteventMessage * precheck automail on selected auto validation --- htdocs/holiday/card_group.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 93560b9bb7c..57fe16ea23e 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -281,7 +281,7 @@ if (empty($reshook)) { // Check if there is already holiday for this period pour chaque user $verifCP = $object->verifDateHolidayCP($u, $date_debut, $date_fin, $halfday); if (!$verifCP) { - setEventMessages($langs->trans("alreadyCPexist"), null, 'errors'); + //setEventMessages($langs->trans("alreadyCPexist"), null, 'errors'); $userError = new User($db); $result = $userError->fetch($u); @@ -342,7 +342,7 @@ if (empty($reshook)) { // If no SQL error we redirect to the request card if (!$error) { $db->commit(); - header('Location: '.DOL_URL_ROOT.'/holiday/list.php?restore_lastsearch_values=1'); + header('Location: '.DOL_URL_ROOT.'/holiday/list.php'); exit; } else { $db->rollback(); @@ -414,10 +414,27 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { if( $("input[name=autoValidation]").is(":checked") ){ $("#AutoSendMail").prop("disabled", false); + $("#AutoSendMail").prop("checked", true); + } else { $("#AutoSendMail").prop("disabled", true); + $("#AutoSendMail").prop("checked", false); } + $("input[name=autoValidation]").click( function(e) { + console.log("chang") + + if( $("input[name=autoValidation]").is(":checked") ){ + $("#AutoSendMail").prop("disabled", false); + $("#AutoSendMail").prop("checked", true); + } else { + $("#AutoSendMail").prop("disabled", true); + $("#AutoSendMail").prop("checked", false); + } + }); + + + $("input.button-save").click("submit", function(e) { console.log("Call valider()"); if (document.demandeCP.date_debut_.value != "") @@ -588,7 +605,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''; //auto validation ON CREATE - print ''."\n"; @@ -658,10 +675,10 @@ function sendMail($id, $cancreate, $now, $autoValidation) if ($result) { // If draft and owner of leave - if ($object->statut == Holiday::STATUS_DRAFT && $cancreate) { + if ($object->statut == Holiday::STATUS_VALIDATED && $cancreate) { $object->oldcopy = dol_clone($object); - if ($autoValidation) $object->statut = Holiday::STATUS_VALIDATED; + //if ($autoValidation) $object->statut = Holiday::STATUS_VALIDATED; $verif = $object->validate($user); From 4620224b650d56a0a5020548caa6c78932baf66f Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:01:17 +0200 Subject: [PATCH 040/421] Fix PHP 8.1.7 --- htdocs/debugbar/class/DebugBar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/debugbar/class/DebugBar.php b/htdocs/debugbar/class/DebugBar.php index 15bb2360ed8..93a27666101 100644 --- a/htdocs/debugbar/class/DebugBar.php +++ b/htdocs/debugbar/class/DebugBar.php @@ -40,7 +40,7 @@ class DolibarrDebugBar extends DebugBar //$this->addCollector(new DolExceptionsCollector()); $this->addCollector(new DolQueryCollector()); $this->addCollector(new DolibarrCollector()); - if ($conf->syslog->enabled) { + if (!empty($conf->syslog->enabled)) { $this->addCollector(new DolLogsCollector()); } } From 7967ab402a5fa0233897cd4b6cf91398d381fffa Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:19:08 +0200 Subject: [PATCH 041/421] Fix PHP 8.1.7 --- htdocs/accountancy/admin/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 309dc094e82..543d32dedcc 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -409,7 +409,7 @@ foreach ($list_binding as $key) { // Value print ''; // Value print ''; print ''; } From 7e3a6116bf4f41bce18ce1667147bd3df457231b Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 21:30:12 +0200 Subject: [PATCH 046/421] Remove patch - Error --- htdocs/accountancy/admin/defaultaccounts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 725f7bbe47f..583b12368dc 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -195,7 +195,7 @@ foreach ($list_account_main as $key) { print ''; // Value print ''; print ''; } From 917574aa619e1215ff21f4f40460869fbc8dc21c Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 21:34:47 +0200 Subject: [PATCH 047/421] Fix PHP 8.1.7 --- htdocs/debugbar/class/DebugBar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/debugbar/class/DebugBar.php b/htdocs/debugbar/class/DebugBar.php index 93a27666101..af824a64392 100644 --- a/htdocs/debugbar/class/DebugBar.php +++ b/htdocs/debugbar/class/DebugBar.php @@ -40,7 +40,7 @@ class DolibarrDebugBar extends DebugBar //$this->addCollector(new DolExceptionsCollector()); $this->addCollector(new DolQueryCollector()); $this->addCollector(new DolibarrCollector()); - if (!empty($conf->syslog->enabled)) { + if (isModEnabled('syslog')) { $this->addCollector(new DolLogsCollector()); } } From ae55ff6a43a0ab0bc2522b65c4a6156802a2cd26 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 21:50:09 +0200 Subject: [PATCH 048/421] Fix PHP 8.1.7 --- htdocs/accountancy/admin/export.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/htdocs/accountancy/admin/export.php b/htdocs/accountancy/admin/export.php index 430c7b6abae..acc4bcc23db 100644 --- a/htdocs/accountancy/admin/export.php +++ b/htdocs/accountancy/admin/export.php @@ -1,11 +1,11 @@ - * Copyright (C) 2013-2017 Alexandre Spangaro - * Copyright (C) 2014 Florian Henry - * Copyright (C) 2014 Marcos García - * Copyright (C) 2014 Juanjo Menent - * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2017-2018 Frédéric France +/* Copyright (C) 2013-2014 Olivier Geffroy + * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2014 Marcos García + * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2017-2018 Frédéric France * * 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 @@ -211,7 +211,8 @@ if ($num) { // Value print ''; } } From 2865b72b65c7abac5387f31f8dedf3f00a558ee1 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 21:56:15 +0200 Subject: [PATCH 049/421] Fix PHP 8.1.7 --- htdocs/accountancy/admin/defaultaccounts.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 583b12368dc..3329e743399 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -195,7 +195,8 @@ foreach ($list_account_main as $key) { print ''; // Value print ''; print ''; } From 274dd343f7d7b432fdca605aaabd9d4d7e9ae573 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:26:12 +0200 Subject: [PATCH 050/421] Fix PHP 8.1.7 --- htdocs/accountancy/customer/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index b9ea4fc0e54..8dbba002b98 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -158,8 +158,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'AccountingAccount'; - $permissiontoread = $user->rights->accounting->read; - $permissiontodelete = $user->rights->accounting->delete; + $permissiontoread = $user->hasRight('accounting','read'); + $permissiontodelete = $user->hasRight('accounting','delete'); $uploaddir = $conf->accounting->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } @@ -469,7 +469,7 @@ if ($result) { print ''.$langs->trans("DescVentilTodoCustomer").'

    '; - if ($msg) { + if (!empty($msg)) { print $msg.'
    '; } From 4f27d7e760d8e138c7c069a8687a39b730981965 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:26:16 +0200 Subject: [PATCH 051/421] Fix PHP 8.1.7 --- htdocs/accountancy/supplier/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 32e939f7bee..2d1e5b94b54 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -161,8 +161,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'AccountingAccount'; - $permissiontoread = $user->rights->accounting->read; - $permissiontodelete = $user->rights->accounting->delete; + $permissiontoread = $user->hasRight('accounting','read'); + $permissiontodelete = $user->hasRight('accounting','delete'); $uploaddir = $conf->accounting->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } @@ -477,7 +477,7 @@ if ($result) { print ''.$langs->trans("DescVentilTodoCustomer").'

    '; - if ($msg) { + if (!empty($msg)) { print $msg.'
    '; } From c96b6b0bc763450f5ee6401107f38d977a6233a3 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:30:24 +0200 Subject: [PATCH 052/421] Fix PHP 8.1.7 --- htdocs/accountancy/supplier/lines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/supplier/lines.php b/htdocs/accountancy/supplier/lines.php index 914c355c838..c142361155d 100644 --- a/htdocs/accountancy/supplier/lines.php +++ b/htdocs/accountancy/supplier/lines.php @@ -384,7 +384,7 @@ if ($result) { print ''; print ''; - print_barre_liste($langs->trans("InvoiceLinesDone"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit); + print_barre_liste($langs->trans("InvoiceLinesDone"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit); print ''.$langs->trans("DescVentilDoneSupplier").'
    '; print '
    '.$langs->trans("ChangeAccount").' '; From 70e8210339ca59ddf5d3d8a88f2934a8879a30ec Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:33:58 +0200 Subject: [PATCH 053/421] Fix PHP 8.1.7 --- htdocs/accountancy/expensereport/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 033f1164dc7..35a726363cf 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -150,8 +150,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'ExpenseReport'; $objectlabel = 'ExpenseReport'; - $permissiontoread = $user->rights->expensereport->read; - $permissiontodelete = $user->rights->expensereport->delete; + $permissiontoread = $user->hasRight('accounting','read'); + $permissiontodelete = $user->hasRight('accounting','delete'); $uploaddir = $conf->expensereport->dir_output; include DOL_DOCUMENT_ROOT . '/core/actions_massactions.inc.php'; } @@ -370,7 +370,7 @@ if ($result) { print ''.$langs->trans("DescVentilTodoExpenseReport").'

    '; - if ($msg) { + if (!empty($msg)) { print $msg.'
    '; } From 5f298f7f69541d601de18d5948e2c7d49ef953ee Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 12 Jun 2022 20:39:25 +0000 Subject: [PATCH 054/421] Fixing style errors. --- htdocs/accountancy/customer/list.php | 4 ++-- htdocs/accountancy/expensereport/list.php | 4 ++-- htdocs/accountancy/supplier/list.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 8dbba002b98..b2a127e86a4 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -158,8 +158,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'AccountingAccount'; - $permissiontoread = $user->hasRight('accounting','read'); - $permissiontodelete = $user->hasRight('accounting','delete'); + $permissiontoread = $user->hasRight('accounting', 'read'); + $permissiontodelete = $user->hasRight('accounting', 'delete'); $uploaddir = $conf->accounting->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 35a726363cf..880af769183 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -150,8 +150,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'ExpenseReport'; $objectlabel = 'ExpenseReport'; - $permissiontoread = $user->hasRight('accounting','read'); - $permissiontodelete = $user->hasRight('accounting','delete'); + $permissiontoread = $user->hasRight('accounting', 'read'); + $permissiontodelete = $user->hasRight('accounting', 'delete'); $uploaddir = $conf->expensereport->dir_output; include DOL_DOCUMENT_ROOT . '/core/actions_massactions.inc.php'; } diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 2d1e5b94b54..f274a5432dc 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -161,8 +161,8 @@ if (empty($reshook)) { // Mass actions $objectclass = 'AccountingAccount'; - $permissiontoread = $user->hasRight('accounting','read'); - $permissiontodelete = $user->hasRight('accounting','delete'); + $permissiontoread = $user->hasRight('accounting', 'read'); + $permissiontodelete = $user->hasRight('accounting', 'delete'); $uploaddir = $conf->accounting->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } From 7cd6df4745912d6060b015a69ecdb34065a37b9e Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:49:05 +0200 Subject: [PATCH 055/421] Fix PHP 8.1.7 --- htdocs/accountancy/bookkeeping/listbyaccount.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 80b2efe7050..d638a7c0c84 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -2,7 +2,7 @@ /* Copyright (C) 2016 Neil Orley * Copyright (C) 2013-2016 Olivier Geffroy * Copyright (C) 2013-2020 Florian Henry - * Copyright (C) 2013-2021 Alexandre Spangaro + * Copyright (C) 2013-2022 Alexandre Spangaro * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $langs->loadLangs(array("accountancy", "compta")); $action = GETPOST('action', 'aZ09'); +$socid = GETPOST('socid', 'int'); $massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); @@ -104,6 +105,7 @@ if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_ $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); +$optioncss = GETPOST('optioncss', 'alpha'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page < 0) { $page = 0; @@ -571,6 +573,7 @@ $num = count($object->lines); //} // Print form confirm +$formconfirm = ''; print $formconfirm; // List of mass actions available From 448027f8ed32879f2643d56eabbe743d2272004a Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:54:15 +0200 Subject: [PATCH 056/421] Fix PHP 8.1.7 --- htdocs/core/class/html.formaccounting.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/class/html.formaccounting.class.php b/htdocs/core/class/html.formaccounting.class.php index 63b21e7fa0d..10e23f3d2e4 100644 --- a/htdocs/core/class/html.formaccounting.class.php +++ b/htdocs/core/class/html.formaccounting.class.php @@ -505,6 +505,7 @@ class FormAccounting extends Form } // Build select + $out = ''; $out .= Form::selectarray($htmlname, $aux_account, $selectid, ($showempty ? (is_numeric($showempty) ? 1 : $showempty): 0), 0, 0, '', 0, 0, 0, '', $morecss, 1); //automatic filling if we give the name of the subledger_label input if (!empty($conf->use_javascript_ajax) && !empty($labelhtmlname)) { From e2c9f6279620b2b39858229580aaa4896b9df052 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 22:58:20 +0200 Subject: [PATCH 057/421] Fix PHP 8.1.7 --- htdocs/accountancy/bookkeeping/list.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 2ee947bf720..8dd004fcc35 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -132,6 +132,7 @@ $search_not_reconciled = GETPOST('search_not_reconciled', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); +$optioncss = GETPOST('optioncss', 'alpha'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page < 0) { $page = 0; @@ -913,6 +914,8 @@ if ($massactionbutton && $contextpage != 'poslist') { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } +$moreforfilter = ''; + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook if (empty($reshook)) { From 909bb1469d9e28a9f99cc803d02d0f540a05783f Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 13 Jun 2022 03:42:12 +0200 Subject: [PATCH 058/421] Fix PHP 8.1.7 --- htdocs/core/boxes/box_scheduled_jobs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_scheduled_jobs.php b/htdocs/core/boxes/box_scheduled_jobs.php index f2195659654..cd610543e47 100644 --- a/htdocs/core/boxes/box_scheduled_jobs.php +++ b/htdocs/core/boxes/box_scheduled_jobs.php @@ -63,7 +63,7 @@ class box_scheduled_jobs extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->service->lire && $user->rights->contrat->lire); + $this->hidden = !($user->hasRight('service', 'lire') && $user->hasRight('contrat', 'lire')); } /** From 0e72085be681eaf485080490fddea2cc76973007 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 08:36:17 +0200 Subject: [PATCH 059/421] add trads on form fields --- htdocs/holiday/card_group.php | 11 +++++++---- htdocs/langs/en_US/holiday.lang | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 9655bb24320..5dee6e54f6c 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -209,8 +209,9 @@ if (empty($reshook)) { } // If no groups and no users if (empty($groups) && empty($users)) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors'); - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Group")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequiredUserOrGroup"), null, 'errors'); + //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UserOrGroup")), null, 'errors'); + //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Group")), null, 'errors'); $error++; $action = 'create'; } @@ -486,7 +487,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { // groupe print '
    '; - print ''; @@ -505,7 +507,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { // users print ''; - print ''; + print '\n"; $total = 0; + $total_ttc = 0; $totalrecu = 0; while ($i < $num) { From cfed286e63d698fe71b1ebde4972e0c5ceefab40 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:14:00 +0200 Subject: [PATCH 067/421] PHP 8 in social contribution --- htdocs/compta/payment_sc/card.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/compta/payment_sc/card.php b/htdocs/compta/payment_sc/card.php index b1ec9800aa5..f5ff5a101f2 100644 --- a/htdocs/compta/payment_sc/card.php +++ b/htdocs/compta/payment_sc/card.php @@ -1,8 +1,9 @@ - * Copyright (C) 2004-2014 Laurent Destailleur - * Copyright (C) 2005 Marc Barilley / Ocebo - * Copyright (C) 2005-2009 Regis Houssin +/* Copyright (C) 2004 Rodolphe Quiedeville + * Copyright (C) 2004-2014 Laurent Destailleur + * Copyright (C) 2005 Marc Barilley / Ocebo + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2022 Alexandre Spangaro * * 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 @@ -134,7 +135,7 @@ print ''; // Amount -print ''; +print ''; // Note print ''; From 489ed743be4c48de8f74f98b32e9e58a11ebb8c4 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:14:08 +0200 Subject: [PATCH 068/421] PHP 8 in social contribution --- htdocs/compta/sociales/card.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index 900f1a179e9..b6c69c0182c 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -1,9 +1,9 @@ - * Copyright (C) 2005-2013 Regis Houssin - * Copyright (C) 2016-2018 Frédéric France - * Copyright (C) 2017 Alexandre Spangaro - * Copyright (C) 2021 Gauthier VERDOL +/* Copyright (C) 2004-2020 Laurent Destailleur + * Copyright (C) 2005-2013 Regis Houssin + * Copyright (C) 2016-2018 Frédéric France + * Copyright (C) 2017-2022 Alexandre Spangaro + * Copyright (C) 2021 Gauthier VERDOL * * 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 @@ -53,6 +53,7 @@ $cancel = GETPOST('cancel', 'aZ09'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'myobjectcard'; // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$lineid = GETPOST('lineid', 'int'); $fk_project = (GETPOST('fk_project') ? GETPOST('fk_project', 'int') : 0); From 4cbe6fb48d005b0a474221eca5878100f1b8d1d9 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:14:14 +0200 Subject: [PATCH 069/421] PHP 8 in social contribution --- .../sociales/class/paymentsocialcontribution.class.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php index 1b83915714d..318e7fcd96b 100644 --- a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php +++ b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php @@ -1,6 +1,7 @@ - * Copyright (C) 2004-2007 Laurent Destailleur +/* Copyright (C) 2002 Rodolphe Quiedeville + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2022 Alexandre Spangaro * * 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 @@ -544,7 +545,7 @@ class PaymentSocialContribution extends CommonObject */ public function addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque) { - global $conf; + global $conf, $langs; // Clean data $this->num_payment = trim($this->num_payment); From bba32869a3552ed892ed99c1fff067802389f31b Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:14:30 +0200 Subject: [PATCH 070/421] PHP 8 in social contribution --- htdocs/compta/sociales/list.php | 43 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 082a485f817..785d00d9468 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -1,12 +1,12 @@ - * Copyright (C) 2004-2017 Laurent Destailleur - * Copyright (C) 2005-2009 Regis Houssin - * Copyright (C) 2016 Frédéric France - * Copyright (C) 2020 Pierre Ardoin - * Copyright (C) 2020 Tobias Sekan - * Copyright (C) 2021 Gauthier VERDOL - * Copyright (C) 2021 Alexandre Spangaro +/* Copyright (C) 2001-2003 Rodolphe Quiedeville + * Copyright (C) 2004-2017 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2016 Frédéric France + * Copyright (C) 2020 Pierre Ardoin + * Copyright (C) 2020 Tobias Sekan + * Copyright (C) 2021 Gauthier VERDOL + * Copyright (C) 2021-2022 Alexandre Spangaro * * 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 @@ -41,16 +41,16 @@ if (!empty($conf->projet->enabled)) { // Load translation files required by the page $langs->loadLangs(array('compta', 'banks', 'bills', 'hrm', 'projects')); -$action = GETPOST('action', 'aZ09'); -$massaction = GETPOST('massaction', 'alpha'); -$confirm = GETPOST('confirm', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); -$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sclist'; +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sclist'; -$search_ref = GETPOST('search_ref', 'int'); +$search_ref = GETPOST('search_ref', 'int'); $search_label = GETPOST('search_label', 'alpha'); -$search_amount = GETPOST('search_amount', 'alpha'); -$search_status = GETPOST('search_status', 'int'); +$search_amount = GETPOST('search_amount', 'alpha'); +$search_status = GETPOST('search_status', 'int'); $search_date_startday = GETPOST('search_date_startday', 'int'); $search_date_startmonth = GETPOST('search_date_startmonth', 'int'); $search_date_startyear = GETPOST('search_date_startyear', 'int'); @@ -70,11 +70,11 @@ $search_date_limit_end = dol_mktime(23, 59, 59, $search_date_limit_endmonth, $se $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_users = GETPOST('search_users'); $search_type = GETPOST('search_type', 'int'); -$search_account = GETPOST('search_account', 'int'); +$search_account = GETPOST('search_account', 'int'); $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST("sortorder", 'aZ09comma'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST("sortorder", 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { @@ -388,6 +388,9 @@ if (empty($mysoc->country_id) && empty($mysoc->country_code)) { $db->close(); } +$moreforfilter = ''; +$massactionbutton = ''; + $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields if ($massactionbutton) { @@ -551,7 +554,9 @@ print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], '', '', '', '', $ print ''; $i = 0; - $totalarray = $TLoadedUsers = array(); +$totalarray = $TLoadedUsers = array(); +$totalarray['nbfield'] = 0; +$totalarray['val']['totalttcfield'] = 0; while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); From f94b25c8372d62cec808580aa89f33d904779887 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:14:56 +0200 Subject: [PATCH 071/421] PHP 8 in social contribution --- htdocs/compta/sociales/payments.php | 41 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/htdocs/compta/sociales/payments.php b/htdocs/compta/sociales/payments.php index d2646d241ea..99d4b760d40 100644 --- a/htdocs/compta/sociales/payments.php +++ b/htdocs/compta/sociales/payments.php @@ -1,12 +1,12 @@ - * Copyright (C) 2004-2016 Laurent Destailleur - * Copyright (C) 2005-2010 Regis Houssin - * Copyright (C) 2011-2016 Alexandre Spangaro - * Copyright (C) 2011-2014 Juanjo Menent - * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2019 Nicolas ZABOURI - * Copyright (C) 2021 Gauthier VERDOL +/* Copyright (C) 2001-2003 Rodolphe Quiedeville + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2011-2022 Alexandre Spangaro + * Copyright (C) 2011-2014 Juanjo Menent + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2019 Nicolas ZABOURI + * Copyright (C) 2021 Gauthier VERDOL * * 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 @@ -37,6 +37,9 @@ require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsocialcontrib.class.php'; +if (!empty($conf->accounting->enabled)) { + include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; +} $hookmanager = new HookManager($db); @@ -48,6 +51,7 @@ $langs->loadLangs(array('compta', 'bills', 'hrm')); $year = GETPOST("year", 'int'); $search_sc_type = GETPOST('search_sc_type', 'int'); +$optioncss = GETPOST('optioncss', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -123,6 +127,9 @@ if ($year) { if ($search_sc_type) { $param .= '&search_sc_type='.urlencode($search_sc_type); } +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); +} $num = 0; print ''; @@ -139,7 +146,7 @@ $sql = "SELECT c.id, c.libelle as type_label,"; $sql .= " cs.rowid, cs.libelle as label_sc, cs.fk_type as type, cs.periode, cs.date_ech, cs.amount as total, cs.paye,"; $sql .= " pc.rowid as pid, pc.datep, pc.amount as totalpaid, pc.num_paiement as num_payment, pc.fk_bank,"; $sql .= " pct.code as payment_code,"; -$sql .= " u.rowid uid, u.lastname, u.firstname, u.email, u.login, u.admin,"; +$sql .= " u.rowid as uid, u.lastname, u.firstname, u.email, u.login, u.admin, u.statut,"; $sql .= " ba.rowid as bid, ba.ref as bref, ba.number as bnumber, ba.account_number, ba.fk_accountancy_journal, ba.label as blabel, ba.iban_prefix as iban, ba.bic, ba.currency_code, ba.clos"; $sql .= " FROM ".MAIN_DB_PREFIX."c_chargesociales as c,"; $sql .= " ".MAIN_DB_PREFIX."chargesociales as cs"; @@ -278,7 +285,7 @@ while ($i < min($num, $limit)) { print $socialcontrib->getNomUrl(1, ''); print ''; // Type - print ''; + print ''; // Date $date = $obj->periode; if (empty($date)) { @@ -297,8 +304,7 @@ while ($i < min($num, $limit)) { $userstatic->admin = $obj->admin; $userstatic->login = $obj->login; $userstatic->email = $obj->email; - $userstatic->socid = $obj->fk_soc; - $userstatic->statut = $obj->status; + $userstatic->statut = $obj->statut; print $userstatic->getNomUrl(1); print "\n"; } @@ -327,13 +333,19 @@ while ($i < min($num, $limit)) { $accountstatic->id = $obj->bid; $accountstatic->ref = $obj->bref; $accountstatic->number = $obj->bnumber; - $accountstatic->accountancy_number = $obj->account_number; - $accountstatic->accountancy_journal = $obj->accountancy_journal; $accountstatic->label = $obj->blabel; $accountstatic->iban = $obj->iban; $accountstatic->bic = $obj->bic; $accountstatic->currency_code = $langs->trans("Currency".$obj->currency_code); $accountstatic->clos = $obj->clos; + + if (!empty($conf->accounting->enabled)) { + $accountstatic->account_number = $obj->account_number; + + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($obj->fk_accountancy_journal); + $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } print $accountstatic->getNomUrl(1); } else { print ' '; @@ -356,7 +368,6 @@ while ($i < min($num, $limit)) { print ''; $total = $total + $obj->total; - $totalnb = $totalnb + $obj->nb; $totalpaid = $totalpaid + $obj->totalpaid; $i++; } From 56e03b9a113bd2704c8208de3ab13aea33cfb1d0 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:22:53 +0200 Subject: [PATCH 072/421] PHP 8 in social contribution --- htdocs/compta/sociales/list.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 785d00d9468..1590ddc83f2 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -49,6 +49,7 @@ $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sc $search_ref = GETPOST('search_ref', 'int'); $search_label = GETPOST('search_label', 'alpha'); +$search_typeid = GETPOST('search_typeid', 'int'); $search_amount = GETPOST('search_amount', 'alpha'); $search_status = GETPOST('search_status', 'int'); $search_date_startday = GETPOST('search_date_startday', 'int'); @@ -93,19 +94,6 @@ if (!$sortorder) { $filtre = GETPOST("filtre", 'int'); -if (!GETPOSTISSET('search_typeid')) { - $newfiltre = str_replace('filtre=', '', $filtre); - $filterarray = explode('-', $newfiltre); - foreach ($filterarray as $val) { - $part = explode(':', $val); - if ($part[0] == 'cs.fk_type') { - $search_typeid = $part[1]; - } - } -} else { - $search_typeid = GETPOST('search_typeid', 'int'); -} - $arrayfields = array( 'cs.rowid' =>array('label'=>"Ref", 'checked'=>1, 'position'=>10), 'cs.libelle' =>array('label'=>"Label", 'checked'=>1, 'position'=>20), From 2c6e4227910f2687e0dc5eeaeb95ca752d1d92b1 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Tue, 14 Jun 2022 11:06:10 +0200 Subject: [PATCH 073/421] changing function name to existing one --- htdocs/core/class/stats.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/stats.class.php b/htdocs/core/class/stats.class.php index ae9a8e56e58..91d3d729c2f 100644 --- a/htdocs/core/class/stats.class.php +++ b/htdocs/core/class/stats.class.php @@ -236,7 +236,7 @@ abstract class Stats $year = $startyear; while ($year <= $endyear) { - $datay[$year] = $this->getAverageByMonth($year); + $datay[$year] = $this->_getAverageByMonth($year); $year++; } From fc4f5d9af214e0e8af36ca2b48a2beb58b352d54 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Wed, 15 Jun 2022 12:25:00 +0200 Subject: [PATCH 074/421] adding abstract function in Stats class --- htdocs/core/class/stats.class.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/stats.class.php b/htdocs/core/class/stats.class.php index 91d3d729c2f..38effddb586 100644 --- a/htdocs/core/class/stats.class.php +++ b/htdocs/core/class/stats.class.php @@ -219,6 +219,13 @@ abstract class Stats return $data; } + /** + * @param int $year year number + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return int value + */ + protected abstract function getAverageByMonth($year, $format = 0); + /** * Return average of entity by month for several years * @@ -236,7 +243,7 @@ abstract class Stats $year = $startyear; while ($year <= $endyear) { - $datay[$year] = $this->_getAverageByMonth($year); + $datay[$year] = $this->getAverageByMonth($year); $year++; } From c2213d6b1d9f12788c7409125a840e18cea311c3 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Wed, 15 Jun 2022 14:51:03 +0200 Subject: [PATCH 075/421] set -e to set +e --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 45be1a9a6ba..7cf0c562a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -434,7 +434,7 @@ script: - | echo "Unit testing" # Ensure we catch errors. Set this to +e if you want to go to the end to see dolibarr.log file. - set -e + set +e phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php phpunitresult=$? echo "Phpunit return code = $phpunitresult" From e00e7e1faa19af6f3d18a5cc36ca7147e93ce1c5 Mon Sep 17 00:00:00 2001 From: Faustin Date: Mon, 13 Jun 2022 14:13:51 +0200 Subject: [PATCH 076/421] replaced projet from old version by project --- htdocs/core/lib/contact.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index b63e7b025c7..884efb16482 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -174,7 +174,7 @@ function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $ $langs->load("projects"); $newcardbutton = ''; - if (!empty($conf->project->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { + if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { $newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&action=create&backtopage='.urlencode($backtopage)); } From 2392d1c59c699c5bcec97a0e507f9bc0aa28c5be Mon Sep 17 00:00:00 2001 From: Faustin Date: Mon, 13 Jun 2022 14:14:06 +0200 Subject: [PATCH 077/421] replaced projet from old version by project --- htdocs/core/lib/contact.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index 884efb16482..b63e7b025c7 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -174,7 +174,7 @@ function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $ $langs->load("projects"); $newcardbutton = ''; - if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { + if (!empty($conf->project->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { $newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&action=create&backtopage='.urlencode($backtopage)); } From 7f73464ecc51b679163cb2f5807c7a468a904c8e Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Mon, 13 Jun 2022 16:17:18 +0200 Subject: [PATCH 078/421] Increasing the scope of the variable --- htdocs/core/boxes/box_project.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/boxes/box_project.php b/htdocs/core/boxes/box_project.php index 909ff32acb9..523f18d6c33 100644 --- a/htdocs/core/boxes/box_project.php +++ b/htdocs/core/boxes/box_project.php @@ -83,8 +83,7 @@ class box_project extends ModeleBoxes $textHead = $langs->trans("OpenedProjects"); $this->info_box_head = array('text' => $textHead, 'limit'=> dol_strlen($textHead)); - - $i = 0; + $num = 0; // list the summary of the orders if ($user->rights->projet->lire) { include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; From 9f4690eedda1118a1af4267b63a22306977558c5 Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 15 Jun 2022 15:02:48 +0200 Subject: [PATCH 079/421] Conflict management --- htdocs/core/lib/contact.lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index b63e7b025c7..d51b3cd02db 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -170,11 +170,11 @@ function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $ $i = -1; - if (!empty($conf->project->enabled) && $user->rights->projet->lire) { + if (!empty($conf->projet->enabled) && $user->rights->projet->lire) { $langs->load("projects"); $newcardbutton = ''; - if (!empty($conf->project->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { + if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { $newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&action=create&backtopage='.urlencode($backtopage)); } From 0f77d945a96eeb597430a0fddd5a683a84bb1c16 Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 15 Jun 2022 15:05:07 +0200 Subject: [PATCH 080/421] Conflict management --- htdocs/core/lib/contact.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index d51b3cd02db..8ade2200724 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -57,7 +57,7 @@ function contact_prepare_head(Contact $object) $head[$tab][2] = 'perso'; $tab++; - if (!empty($conf->project->enabled) && $user->hasRight('project', 'lire')) { + if (!empty($conf->projet->enabled) && (!empty($user->rights->projet->lire))) { $nbProject = 0; // Enable caching of thirdrparty count projects require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; From 4874b8d94a8dafce79614386767efd658c877635 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 14 Jun 2022 17:53:17 +0200 Subject: [PATCH 081/421] Fix conf->projet conf->project --- htdocs/core/lib/contact.lib.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index 8ade2200724..220c088fc11 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -57,7 +57,7 @@ function contact_prepare_head(Contact $object) $head[$tab][2] = 'perso'; $tab++; - if (!empty($conf->projet->enabled) && (!empty($user->rights->projet->lire))) { + if (!empty($conf->project->enabled) && (!empty($user->rights->projet->lire))) { $nbProject = 0; // Enable caching of thirdrparty count projects require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; @@ -170,11 +170,11 @@ function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $ $i = -1; - if (!empty($conf->projet->enabled) && $user->rights->projet->lire) { + if (!empty($conf->project->enabled) && $user->rights->projet->lire) { $langs->load("projects"); $newcardbutton = ''; - if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { + if (!empty($conf->project->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { $newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&action=create&backtopage='.urlencode($backtopage)); } From 0af9fe275df38464e183349e67bb421c854dbec2 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Wed, 15 Jun 2022 15:25:23 +0200 Subject: [PATCH 082/421] test userHasRight temporarily commented --- test/phpunit/UserTest.php | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 0a7431c171f..86b32f45c03 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -266,29 +266,29 @@ class UserTest extends PHPUnit\Framework\TestCase * * @return void */ - public function testUserHasRight() - { - global $conf,$user,$langs,$db; - $conf=$this->savconf; - $user=$this->savuser; - $langs=$this->savlangs; - $db=$this->savdb; - /*$result=$localobject->setstatus(0); - print __METHOD__." id=".$localobject->id." result=".$result."\n"; - $this->assertLessThan($result, 0); - */ + // public function testUserHasRight() + // { + // global $conf,$user,$langs,$db; + // $conf=$this->savconf; + // $user=$this->savuser; + // $langs=$this->savlangs; + // $db=$this->savdb; + // /*$result=$localobject->setstatus(0); + // print __METHOD__." id=".$localobject->id." result=".$result."\n"; + // $this->assertLessThan($result, 0); + // */ - print __METHOD__." id=". $user->id ."\n"; - //$this->assertNotEquals($user->date_creation, ''); - $user->addrights(0, 'supplier_proposal'); + // print __METHOD__." id=". $user->id ."\n"; + // //$this->assertNotEquals($user->date_creation, ''); + // $user->addrights(0, 'supplier_proposal'); - $this->assertEquals($user->hasRight('member', ''), 0); - $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); - $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); - $user->clearrights(); - //print __METHOD__. $user->hasRight('module', 'level11'); - return $user; - } + // $this->assertEquals($user->hasRight('member', ''), 0); + // $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); + // $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); + // $user->clearrights(); + // //print __METHOD__. $user->hasRight('module', 'level11'); + // return $user; + // } /** * testUserSetPassword From 6696d3d4eb173e348776c4c747c81a2e40d1ce6a Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 15 Jun 2022 15:28:31 +0200 Subject: [PATCH 083/421] Conflict --- htdocs/core/lib/contact.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index 220c088fc11..b63e7b025c7 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -57,7 +57,7 @@ function contact_prepare_head(Contact $object) $head[$tab][2] = 'perso'; $tab++; - if (!empty($conf->project->enabled) && (!empty($user->rights->projet->lire))) { + if (!empty($conf->project->enabled) && $user->hasRight('project', 'lire')) { $nbProject = 0; // Enable caching of thirdrparty count projects require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; From baf28abf7a68f61739baa44e3904702e8b6bec77 Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 15 Jun 2022 15:30:35 +0200 Subject: [PATCH 084/421] Conflict --- htdocs/core/boxes/box_project.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_project.php b/htdocs/core/boxes/box_project.php index 523f18d6c33..909ff32acb9 100644 --- a/htdocs/core/boxes/box_project.php +++ b/htdocs/core/boxes/box_project.php @@ -83,7 +83,8 @@ class box_project extends ModeleBoxes $textHead = $langs->trans("OpenedProjects"); $this->info_box_head = array('text' => $textHead, 'limit'=> dol_strlen($textHead)); - $num = 0; + + $i = 0; // list the summary of the orders if ($user->rights->projet->lire) { include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; From e07a94a0512f7385c5f8506b4e4ea84e04ca4049 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Wed, 15 Jun 2022 15:31:23 +0200 Subject: [PATCH 085/421] changing the testUserHasRight --- test/phpunit/UserTest.php | 47 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 86b32f45c03..39fd87b95a5 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -263,39 +263,38 @@ class UserTest extends PHPUnit\Framework\TestCase /** * testUserHasRight - * - * @return void + * @param User $localobject User + * @return User $localobject User + * @depends testUserOther */ - // public function testUserHasRight() - // { - // global $conf,$user,$langs,$db; - // $conf=$this->savconf; - // $user=$this->savuser; - // $langs=$this->savlangs; - // $db=$this->savdb; - // /*$result=$localobject->setstatus(0); - // print __METHOD__." id=".$localobject->id." result=".$result."\n"; - // $this->assertLessThan($result, 0); - // */ + public function testUserHasRight($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + /*$result=$localobject->setstatus(0); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0); + */ - // print __METHOD__." id=". $user->id ."\n"; - // //$this->assertNotEquals($user->date_creation, ''); - // $user->addrights(0, 'supplier_proposal'); + print __METHOD__." id=". $localobject->id ."\n"; + //$this->assertNotEquals($user->date_creation, ''); + $user->addrights(0, 'supplier_proposal'); + $this->assertEquals($localobject->hasRight('member', ''), 0); + $this->assertEquals($localobject->hasRight('member', 'member'), 0);$this->assertEquals($localobject->hasRight('product', 'member', 'read'), 0); + $this->assertEquals($localobject->hasRight('member', 'member'), 0);$this->assertEquals($localobject->hasRight('produit', 'member', 'read'), 0); - // $this->assertEquals($user->hasRight('member', ''), 0); - // $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('product', 'member', 'read'), 0); - // $this->assertEquals($user->hasRight('member', 'member'), 0);$this->assertEquals($user->hasRight('produit', 'member', 'read'), 0); - // $user->clearrights(); - // //print __METHOD__. $user->hasRight('module', 'level11'); - // return $user; - // } + return $localobject; + } /** * testUserSetPassword * * @param User $localobject User * @return void - * @depends testUserOther + * @depends testUserHasRight * The depends says test is run only if previous is ok */ public function testUserSetPassword($localobject) From a11732bb0d12f3ad292155ede13ef45c2aa241cb Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Wed, 15 Jun 2022 15:44:40 +0200 Subject: [PATCH 086/421] done --- .travis.yml | 549 +++++++++++++++++++------------------- test/phpunit/UserTest.php | 2 +- 2 files changed, 273 insertions(+), 278 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7cf0c562a9f..da3856b5254 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,30 +14,30 @@ git: # Start on every boot services: -- memcached -- mysql -- postgresql + - memcached + - mysql + - postgresql addons: # Force postgresql to 9.4 (the oldest availablable on xenial) - postgresql: '9.4' + postgresql: "9.4" apt: sources: - # To use the last version of pgloader, we add repo of postgresql with a name available in http://apt.postgresql.org/pub/repos/apt/ - - pgdg-xenial + # To use the last version of pgloader, we add repo of postgresql with a name available in http://apt.postgresql.org/pub/repos/apt/ + - pgdg-xenial packages: - # We need a webserver to test the webservices - # Let's install Apache with. - - apache2 - # mod_php is not supported by Travis. Add fcgi. We install FPM later on. - - libapache2-mod-fastcgi - # We need pgloader for import mysql database into pgsql - - pgloader + # We need a webserver to test the webservices + # Let's install Apache with. + - apache2 + # mod_php is not supported by Travis. Add fcgi. We install FPM later on. + - libapache2-mod-fastcgi + # We need pgloader for import mysql database into pgsql + - pgloader env: global: - # Set to true for very verbose output - - DEBUG=false + # Set to true for very verbose output + - DEBUG=false jobs: fast_finish: true @@ -46,19 +46,19 @@ jobs: include: - stage: PHP 5.6-7.4 if: type = push - php: '5.6' + php: "5.6" env: DB=postgresql - stage: PHP 5.6-7.4 if: type = pull_request OR type = push - php: '7.4.22' + php: "7.4.22" env: DB=mysql - stage: PHP Dev if: type = push AND branch = develop - php: nightly + php: nightly env: DB=mysql - stage: PHP Dev if: type = push AND branch = 15.0 - php: nightly + php: nightly env: DB=mysql notifications: @@ -67,69 +67,67 @@ notifications: on_failure: never # [always|never|change] default: always irc: channels: - - "chat.freenode.net#dolibarr" + - "chat.freenode.net#dolibarr" on_success: change on_failure: always use_notice: true before_install: -- | - echo "Disabling Xdebug for composer" - export PHP_VERSION_NAME=$(phpenv version-name) - cp ~/.phpenv/versions/$PHP_VERSION_NAME/etc/conf.d/xdebug.ini /tmp/xdebug.ini - phpenv config-rm xdebug.ini - echo + - | + echo "Disabling Xdebug for composer" + export PHP_VERSION_NAME=$(phpenv version-name) + cp ~/.phpenv/versions/$PHP_VERSION_NAME/etc/conf.d/xdebug.ini /tmp/xdebug.ini + phpenv config-rm xdebug.ini + echo install: -- | - echo "Updating Composer" - rm $TRAVIS_BUILD_DIR/composer.json - rm $TRAVIS_BUILD_DIR/composer.lock - composer -V - composer self-update - composer -n init - composer -n config vendor-dir htdocs/includes - composer -n config -g vendor-dir htdocs/includes - echo - -- | - echo "Installing Composer dependencies - PHP Unit, Parallel Lint, PHP CodeSniffer - for $TRAVIS_PHP_VERSION" - if [ "$TRAVIS_PHP_VERSION" = '5.6' ]; then - composer -n require phpunit/phpunit ^5 \ - php-parallel-lint/php-parallel-lint ^1 \ - php-parallel-lint/php-console-highlighter ^0 \ - squizlabs/php_codesniffer ^3 - fi - if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ]; then - composer -n require phpunit/phpunit ^6 \ - php-parallel-lint/php-parallel-lint ^1 \ - php-parallel-lint/php-console-highlighter ^0 \ - squizlabs/php_codesniffer ^3 - fi - if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '7.4.22' ]; then - composer -n require phpunit/phpunit ^7 \ - php-parallel-lint/php-parallel-lint ^1.2 \ - php-parallel-lint/php-console-highlighter ^0 \ - squizlabs/php_codesniffer ^3 - fi - # phpunit 9 is required for php 8 - if [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then - composer -n require --ignore-platform-reqs phpunit/phpunit ^7 \ - php-parallel-lint/php-parallel-lint ^1.2 \ - php-parallel-lint/php-console-highlighter ^0 \ - squizlabs/php_codesniffer ^3 - fi - echo - -- | - echo "Adding path of binaries tools installed by composer to the PATH" - export PATH="$TRAVIS_BUILD_DIR/htdocs/includes/bin:$PATH" - echo $PATH - ls $TRAVIS_BUILD_DIR/vendor - ls $TRAVIS_BUILD_DIR/htdocs/includes/bin - echo + - | + echo "Updating Composer" + rm $TRAVIS_BUILD_DIR/composer.json + rm $TRAVIS_BUILD_DIR/composer.lock + composer -V + composer self-update + composer -n init + composer -n config vendor-dir htdocs/includes + composer -n config -g vendor-dir htdocs/includes + echo + - | + echo "Installing Composer dependencies - PHP Unit, Parallel Lint, PHP CodeSniffer - for $TRAVIS_PHP_VERSION" + if [ "$TRAVIS_PHP_VERSION" = '5.6' ]; then + composer -n require phpunit/phpunit ^5 \ + php-parallel-lint/php-parallel-lint ^1 \ + php-parallel-lint/php-console-highlighter ^0 \ + squizlabs/php_codesniffer ^3 + fi + if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ]; then + composer -n require phpunit/phpunit ^6 \ + php-parallel-lint/php-parallel-lint ^1 \ + php-parallel-lint/php-console-highlighter ^0 \ + squizlabs/php_codesniffer ^3 + fi + if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '7.4.22' ]; then + composer -n require phpunit/phpunit ^7 \ + php-parallel-lint/php-parallel-lint ^1.2 \ + php-parallel-lint/php-console-highlighter ^0 \ + squizlabs/php_codesniffer ^3 + fi + # phpunit 9 is required for php 8 + if [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then + composer -n require --ignore-platform-reqs phpunit/phpunit ^7 \ + php-parallel-lint/php-parallel-lint ^1.2 \ + php-parallel-lint/php-console-highlighter ^0 \ + squizlabs/php_codesniffer ^3 + fi + echo + - | + echo "Adding path of binaries tools installed by composer to the PATH" + export PATH="$TRAVIS_BUILD_DIR/htdocs/includes/bin:$PATH" + echo $PATH + ls $TRAVIS_BUILD_DIR/vendor + ls $TRAVIS_BUILD_DIR/htdocs/includes/bin + echo before_script: - | @@ -236,7 +234,6 @@ before_script: echo "***** First line of dolibarr.log" > $TRAVIS_BUILD_DIR/documents/dolibarr.log echo - - echo "Setting up Apache + FPM" # enable php-fpm - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf @@ -256,221 +253,219 @@ before_script: - sudo cat /etc/apache2/sites-available/000-default.conf - sudo service apache2 restart - - script: -- | - echo "Checking webserver availability by a wget -O - http://127.0.0.1" - # Ensure we stop on error with set -e - set +e - # The wget should return a page with line ' - wget -O - http://127.0.0.1 > test.html - head test.html - sudo cat /var/log/apache2/travis_error_log - set +e - echo + - | + echo "Checking webserver availability by a wget -O - http://127.0.0.1" + # Ensure we stop on error with set -e + set +e + # The wget should return a page with line ' + wget -O - http://127.0.0.1 > test.html + head test.html + sudo cat /var/log/apache2/travis_error_log + set +e + echo -- | - echo "Checking PHP syntax errors (only 1 version to not overload travis and avoid duplicate tests)" - # Ensure we catch errors - set -e - #parallel-lint --exclude htdocs/includes --blame . - # Exclusions are defined in the ruleset.xml file - if [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then - parallel-lint -e php --exclude dev/tools/test/namespacemig --exclude htdocs/includes/composer --exclude htdocs/includes/myclabs --exclude htdocs/includes/phpspec --exclude dev/initdata/dbf/includes \ - --exclude htdocs/includes/sabre --exclude htdocs/includes/phpoffice/PhpSpreadsheet --exclude htdocs/includes/sebastian \ - --exclude htdocs/includes/squizlabs/php_codesniffer --exclude htdocs/includes/jakub-onderka --exclude htdocs/includes/php-parallel-lint --exclude htdocs/includes/symfony \ - --exclude htdocs/includes/mike42/escpos-php/example --exclude htdocs/includes/maximebf \ - --exclude htdocs/includes/phpunit/ --exclude htdocs/includes/tecnickcom/tcpdf/include/barcodes --exclude htdocs/includes/webmozart --blame . - fi - set +e - echo + - | + echo "Checking PHP syntax errors (only 1 version to not overload travis and avoid duplicate tests)" + # Ensure we catch errors + set -e + #parallel-lint --exclude htdocs/includes --blame . + # Exclusions are defined in the ruleset.xml file + if [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then + parallel-lint -e php --exclude dev/tools/test/namespacemig --exclude htdocs/includes/composer --exclude htdocs/includes/myclabs --exclude htdocs/includes/phpspec --exclude dev/initdata/dbf/includes \ + --exclude htdocs/includes/sabre --exclude htdocs/includes/phpoffice/PhpSpreadsheet --exclude htdocs/includes/sebastian \ + --exclude htdocs/includes/squizlabs/php_codesniffer --exclude htdocs/includes/jakub-onderka --exclude htdocs/includes/php-parallel-lint --exclude htdocs/includes/symfony \ + --exclude htdocs/includes/mike42/escpos-php/example --exclude htdocs/includes/maximebf \ + --exclude htdocs/includes/phpunit/ --exclude htdocs/includes/tecnickcom/tcpdf/include/barcodes --exclude htdocs/includes/webmozart --blame . + fi + set +e + echo -- | - echo "Checking coding style (only for Pull Requests builds and 1 version to not overload travis and avoid duplicate tests)" - # Ensure we catch errors - set -e - # Exclusions are defined in the ruleset.xml file - if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then - phpcs -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true .; - fi - set +e - echo + - | + echo "Checking coding style (only for Pull Requests builds and 1 version to not overload travis and avoid duplicate tests)" + # Ensure we catch errors + set -e + # Exclusions are defined in the ruleset.xml file + if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then + phpcs -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true .; + fi + set +e + echo -- | - export INSTALL_FORCED_FILE=htdocs/install/install.forced.php - echo "Setting up Dolibarr $INSTALL_FORCED_FILE to test installation" - # Ensure we catch errors - set +e - echo ' $INSTALL_FORCED_FILE - echo '$'force_install_noedit=2';' >> $INSTALL_FORCED_FILE - if [ "$DB" = 'mysql' ] || [ "$DB" = 'mariadb' ]; then - echo '$'force_install_type=\'mysqli\'';' >> $INSTALL_FORCED_FILE - fi - if [ "$DB" = 'postgresql' ]; then - echo '$'force_install_type=\'pgsql\'';' >> $INSTALL_FORCED_FILE - fi - echo '$'force_install_dbserver=\'127.0.0.1\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_database=\'travis\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_databaselogin=\'travis\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_databasepass=\'\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_port=\'5432\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_prefix=\'llx_\'';' >> $INSTALL_FORCED_FILE - echo '$'force_install_createdatabase=false';' >> $INSTALL_FORCED_FILE - echo '$'force_install_createuser=false';' >> $INSTALL_FORCED_FILE - echo '$'force_install_mainforcehttps=false';' >> $INSTALL_FORCED_FILE - echo '$'force_install_main_data_root=\'$TRAVIS_BUILD_DIR/htdocs\'';' >> $INSTALL_FORCED_FILE - #cat $INSTALL_FORCED_FILE + - | + export INSTALL_FORCED_FILE=htdocs/install/install.forced.php + echo "Setting up Dolibarr $INSTALL_FORCED_FILE to test installation" + # Ensure we catch errors + set +e + echo ' $INSTALL_FORCED_FILE + echo '$'force_install_noedit=2';' >> $INSTALL_FORCED_FILE + if [ "$DB" = 'mysql' ] || [ "$DB" = 'mariadb' ]; then + echo '$'force_install_type=\'mysqli\'';' >> $INSTALL_FORCED_FILE + fi + if [ "$DB" = 'postgresql' ]; then + echo '$'force_install_type=\'pgsql\'';' >> $INSTALL_FORCED_FILE + fi + echo '$'force_install_dbserver=\'127.0.0.1\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_database=\'travis\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_databaselogin=\'travis\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_databasepass=\'\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_port=\'5432\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_prefix=\'llx_\'';' >> $INSTALL_FORCED_FILE + echo '$'force_install_createdatabase=false';' >> $INSTALL_FORCED_FILE + echo '$'force_install_createuser=false';' >> $INSTALL_FORCED_FILE + echo '$'force_install_mainforcehttps=false';' >> $INSTALL_FORCED_FILE + echo '$'force_install_main_data_root=\'$TRAVIS_BUILD_DIR/htdocs\'';' >> $INSTALL_FORCED_FILE + #cat $INSTALL_FORCED_FILE -#- | -# echo "Installing Dolibarr" -# cd htdocs/install -# php step1.php $TRAVIS_BUILD_DIR/htdocs > $TRAVIS_BUILD_DIR/install.log -# php step2.php set >> $TRAVIS_BUILD_DIR/install.log -# if [ "$?" -ne "0" ]; then -# echo "SORRY, AN ERROR OCCURED DURING INSTALLATION PROCESS" -# cat $TRAVIS_BUILD_DIR/install.log -# exit 1 -# fi -# cd ../.. -# rm $INSTALL_FORCED_FILE -# #cat $TRAVIS_BUILD_DIR/install.log -# set +e -# echo + #- | + # echo "Installing Dolibarr" + # cd htdocs/install + # php step1.php $TRAVIS_BUILD_DIR/htdocs > $TRAVIS_BUILD_DIR/install.log + # php step2.php set >> $TRAVIS_BUILD_DIR/install.log + # if [ "$?" -ne "0" ]; then + # echo "SORRY, AN ERROR OCCURED DURING INSTALLATION PROCESS" + # cat $TRAVIS_BUILD_DIR/install.log + # exit 1 + # fi + # cd ../.. + # rm $INSTALL_FORCED_FILE + # #cat $TRAVIS_BUILD_DIR/install.log + # set +e + # echo -- | - echo "Setting up database to test migrations" - if [ "$DB" = 'mysql' ] || [ "$DB" = 'mariadb' ] || [ "$DB" = 'postgresql' ]; then - echo "MySQL" - mysql -e 'DROP DATABASE IF EXISTS travis;' - mysql -e 'CREATE DATABASE IF NOT EXISTS travis;' - mysql -e 'GRANT ALL PRIVILEGES ON travis.* TO travis@127.0.0.1;' - mysql -e 'FLUSH PRIVILEGES;' - mysql -D travis < dev/initdemo/mysqldump_dolibarr_3.5.0.sql - fi - if [ "$DB" = 'postgresql' ]; then - #pgsql travis < dev/initdemo/mysqldump_dolibarr_3.5.0.sql - #pgloader mysql://root:pass@127.0.0.1/base postgresql://dolibarrowner@127.0.0.1/dolibarr - echo pgloader mysql://root@127.0.0.1/travis postgresql:///travis - pgloader mysql://root@127.0.0.1/travis postgresql:///travis - echo 'ALTER SEQUENCE llx_accountingaccount_rowid_seq RENAME TO llx_accounting_account_rowid_seq' | psql travis - echo 'ALTER SEQUENCE llx_accounting_account_rowid_seq RESTART WITH 1000001;' | psql travis - #echo 'select * from INFORMATION_SCHEMA.COLUMNS where table_name = 'llx_accountingaccount' | psql travis - #echo 'select * from information_schema.table_constraints;' | psql travis - #echo 'ALTER TABLE "llx_accounting_account" DROP CONSTRAINT "idx_16390_primary"' | psql travis - fi - echo + - | + echo "Setting up database to test migrations" + if [ "$DB" = 'mysql' ] || [ "$DB" = 'mariadb' ] || [ "$DB" = 'postgresql' ]; then + echo "MySQL" + mysql -e 'DROP DATABASE IF EXISTS travis;' + mysql -e 'CREATE DATABASE IF NOT EXISTS travis;' + mysql -e 'GRANT ALL PRIVILEGES ON travis.* TO travis@127.0.0.1;' + mysql -e 'FLUSH PRIVILEGES;' + mysql -D travis < dev/initdemo/mysqldump_dolibarr_3.5.0.sql + fi + if [ "$DB" = 'postgresql' ]; then + #pgsql travis < dev/initdemo/mysqldump_dolibarr_3.5.0.sql + #pgloader mysql://root:pass@127.0.0.1/base postgresql://dolibarrowner@127.0.0.1/dolibarr + echo pgloader mysql://root@127.0.0.1/travis postgresql:///travis + pgloader mysql://root@127.0.0.1/travis postgresql:///travis + echo 'ALTER SEQUENCE llx_accountingaccount_rowid_seq RENAME TO llx_accounting_account_rowid_seq' | psql travis + echo 'ALTER SEQUENCE llx_accounting_account_rowid_seq RESTART WITH 1000001;' | psql travis + #echo 'select * from INFORMATION_SCHEMA.COLUMNS where table_name = 'llx_accountingaccount' | psql travis + #echo 'select * from information_schema.table_constraints;' | psql travis + #echo 'ALTER TABLE "llx_accounting_account" DROP CONSTRAINT "idx_16390_primary"' | psql travis + fi + echo -- | - echo "Upgrading Dolibarr" - # Ensure we catch errors. Set this to +e if you want to go to the end to see log files. - set +e - cd htdocs/install - php upgrade.php 3.5.0 3.6.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade350360.log - php upgrade2.php 3.5.0 3.6.0 > $TRAVIS_BUILD_DIR/upgrade350360-2.log - php step5.php 3.5.0 3.6.0 > $TRAVIS_BUILD_DIR/upgrade350360-3.log - php upgrade.php 3.6.0 3.7.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade360370.log - php upgrade2.php 3.6.0 3.7.0 > $TRAVIS_BUILD_DIR/upgrade360370-2.log - php step5.php 3.6.0 3.7.0 > $TRAVIS_BUILD_DIR/upgrade360370-3.log - php upgrade.php 3.7.0 3.8.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade370380.log - php upgrade2.php 3.7.0 3.8.0 > $TRAVIS_BUILD_DIR/upgrade370380-2.log - php step5.php 3.7.0 3.8.0 > $TRAVIS_BUILD_DIR/upgrade370380-3.log - php upgrade.php 3.8.0 3.9.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade380390.log - php upgrade2.php 3.8.0 3.9.0 > $TRAVIS_BUILD_DIR/upgrade380390-2.log - php step5.php 3.8.0 3.9.0 > $TRAVIS_BUILD_DIR/upgrade380390-3.log - php upgrade.php 3.9.0 4.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade390400.log - php upgrade2.php 3.9.0 4.0.0 > $TRAVIS_BUILD_DIR/upgrade390400-2.log - php step5.php 3.9.0 4.0.0 > $TRAVIS_BUILD_DIR/upgrade390400-3.log - php upgrade.php 4.0.0 5.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade400500.log - php upgrade2.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-2.log - php step5.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-3.log - php upgrade.php 5.0.0 6.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade500600.log - php upgrade2.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-2.log - php step5.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-3.log - php upgrade.php 6.0.0 7.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade600700.log - php upgrade2.php 6.0.0 7.0.0 > $TRAVIS_BUILD_DIR/upgrade600700-2.log - php step5.php 6.0.0 7.0.0 > $TRAVIS_BUILD_DIR/upgrade600700-3.log - php upgrade.php 7.0.0 8.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade700800.log - php upgrade2.php 7.0.0 8.0.0 > $TRAVIS_BUILD_DIR/upgrade700800-2.log - php step5.php 7.0.0 8.0.0 > $TRAVIS_BUILD_DIR/upgrade700800-3.log - php upgrade.php 8.0.0 9.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade800900.log - php upgrade2.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-2.log - php step5.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-3.log - php upgrade.php 9.0.0 10.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade9001000.log - php upgrade2.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-2.log - php step5.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-3.log - php upgrade.php 10.0.0 11.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade10001100.log - php upgrade2.php 10.0.0 11.0.0 > $TRAVIS_BUILD_DIR/upgrade10001100-2.log - php step5.php 10.0.0 11.0.0 > $TRAVIS_BUILD_DIR/upgrade10001100-3.log - php upgrade.php 11.0.0 12.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade11001200.log - php upgrade2.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-2.log - php step5.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-3.log - php upgrade.php 12.0.0 13.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade12001300.log - php upgrade2.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-2.log - php step5.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-3.log - php upgrade.php 13.0.0 14.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade13001400.log - php upgrade2.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-2.log - php step5.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-3.log - php upgrade.php 14.0.0 15.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade14001500.log - php upgrade2.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-2.log - php step5.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-3.log - ls -alrt $TRAVIS_BUILD_DIR/ + - | + echo "Upgrading Dolibarr" + # Ensure we catch errors. Set this to +e if you want to go to the end to see log files. + set +e + cd htdocs/install + php upgrade.php 3.5.0 3.6.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade350360.log + php upgrade2.php 3.5.0 3.6.0 > $TRAVIS_BUILD_DIR/upgrade350360-2.log + php step5.php 3.5.0 3.6.0 > $TRAVIS_BUILD_DIR/upgrade350360-3.log + php upgrade.php 3.6.0 3.7.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade360370.log + php upgrade2.php 3.6.0 3.7.0 > $TRAVIS_BUILD_DIR/upgrade360370-2.log + php step5.php 3.6.0 3.7.0 > $TRAVIS_BUILD_DIR/upgrade360370-3.log + php upgrade.php 3.7.0 3.8.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade370380.log + php upgrade2.php 3.7.0 3.8.0 > $TRAVIS_BUILD_DIR/upgrade370380-2.log + php step5.php 3.7.0 3.8.0 > $TRAVIS_BUILD_DIR/upgrade370380-3.log + php upgrade.php 3.8.0 3.9.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade380390.log + php upgrade2.php 3.8.0 3.9.0 > $TRAVIS_BUILD_DIR/upgrade380390-2.log + php step5.php 3.8.0 3.9.0 > $TRAVIS_BUILD_DIR/upgrade380390-3.log + php upgrade.php 3.9.0 4.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade390400.log + php upgrade2.php 3.9.0 4.0.0 > $TRAVIS_BUILD_DIR/upgrade390400-2.log + php step5.php 3.9.0 4.0.0 > $TRAVIS_BUILD_DIR/upgrade390400-3.log + php upgrade.php 4.0.0 5.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade400500.log + php upgrade2.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-2.log + php step5.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-3.log + php upgrade.php 5.0.0 6.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade500600.log + php upgrade2.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-2.log + php step5.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-3.log + php upgrade.php 6.0.0 7.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade600700.log + php upgrade2.php 6.0.0 7.0.0 > $TRAVIS_BUILD_DIR/upgrade600700-2.log + php step5.php 6.0.0 7.0.0 > $TRAVIS_BUILD_DIR/upgrade600700-3.log + php upgrade.php 7.0.0 8.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade700800.log + php upgrade2.php 7.0.0 8.0.0 > $TRAVIS_BUILD_DIR/upgrade700800-2.log + php step5.php 7.0.0 8.0.0 > $TRAVIS_BUILD_DIR/upgrade700800-3.log + php upgrade.php 8.0.0 9.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade800900.log + php upgrade2.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-2.log + php step5.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-3.log + php upgrade.php 9.0.0 10.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade9001000.log + php upgrade2.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-2.log + php step5.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-3.log + php upgrade.php 10.0.0 11.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade10001100.log + php upgrade2.php 10.0.0 11.0.0 > $TRAVIS_BUILD_DIR/upgrade10001100-2.log + php step5.php 10.0.0 11.0.0 > $TRAVIS_BUILD_DIR/upgrade10001100-3.log + php upgrade.php 11.0.0 12.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade11001200.log + php upgrade2.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-2.log + php step5.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-3.log + php upgrade.php 12.0.0 13.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade12001300.log + php upgrade2.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-2.log + php step5.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-3.log + php upgrade.php 13.0.0 14.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade13001400.log + php upgrade2.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-2.log + php step5.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-3.log + php upgrade.php 14.0.0 15.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade14001500.log + php upgrade2.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-2.log + php step5.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-3.log + ls -alrt $TRAVIS_BUILD_DIR/ -- | - echo "Enabling new modules" - # Enable modules not enabled into original dump - set -e - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_PRODUCTBATCH,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_STRIPE,MAIN_MODULE_EXPENSEREPORT > $TRAVIS_BUILD_DIR/enablemodule.log - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP >> $TRAVIS_BUILD_DIR/enablemodule.log - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_RECEPTION,MAIN_MODULE_RECRUITMENT >> $TRAVIS_BUILD_DIR/enablemodule.log - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_KNOWLEDGEMANAGEMENT,MAIN_MODULE_EVENTORGANIZATION,MAIN_MODULE_PARTNERSHIP >> $TRAVIS_BUILD_DIR/enablemodule.log - echo $? - cd - - set +e - echo - #cat /tmp/dolibarr_install.log - cat $TRAVIS_BUILD_DIR/enablemodule.log + - | + echo "Enabling new modules" + # Enable modules not enabled into original dump + set -e + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_PRODUCTBATCH,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_STRIPE,MAIN_MODULE_EXPENSEREPORT > $TRAVIS_BUILD_DIR/enablemodule.log + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP >> $TRAVIS_BUILD_DIR/enablemodule.log + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_RECEPTION,MAIN_MODULE_RECRUITMENT >> $TRAVIS_BUILD_DIR/enablemodule.log + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_KNOWLEDGEMANAGEMENT,MAIN_MODULE_EVENTORGANIZATION,MAIN_MODULE_PARTNERSHIP >> $TRAVIS_BUILD_DIR/enablemodule.log + echo $? + cd - + set +e + echo + #cat /tmp/dolibarr_install.log + cat $TRAVIS_BUILD_DIR/enablemodule.log -- | - echo "Unit testing" - # Ensure we catch errors. Set this to +e if you want to go to the end to see dolibarr.log file. - set +e - phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php - phpunitresult=$? - echo "Phpunit return code = $phpunitresult" - set +e + - | + echo "Unit testing" + # Ensure we catch errors. Set this to +e if you want to go to the end to see dolibarr.log file. + set -e + phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php + phpunitresult=$? + echo "Phpunit return code = $phpunitresult" + set +e after_script: -- | - echo "After script - Output last lines of dolibarr.log" - ls $TRAVIS_BUILD_DIR/documents - #cat $TRAVIS_BUILD_DIR/documents/dolibarr.log - sudo tail -n 50 $TRAVIS_BUILD_DIR/documents/dolibarr.log + - | + echo "After script - Output last lines of dolibarr.log" + ls $TRAVIS_BUILD_DIR/documents + #cat $TRAVIS_BUILD_DIR/documents/dolibarr.log + sudo tail -n 50 $TRAVIS_BUILD_DIR/documents/dolibarr.log after_success: -- | - echo Success + - | + echo Success after_failure: -- | - echo Failure detected, so we show samples of log to help diagnose - # This part of code is executed only if previous command that fails are enclosed with set +e - # Upgrade log files - for ficlog in `ls $TRAVIS_BUILD_DIR/*.log` - do - echo "Debugging informations for file $ficlog" - #cat $ficlog - done - # Apache log file - echo "Debugging informations for file apache error.log" - sudo cat /var/log/apache2/travis_error_log - if [ "$DEBUG" = true ]; then - # Dolibarr log file - echo "Debugging informations for file dolibarr.log (latest 50 lines)" - tail -n 50 $TRAVIS_BUILD_DIR/documents/dolibarr.log - # Database log file - echo "Debugging informations for file mysql error.log" - sudo tail -n 50 /var/log/mysql/error.log - # TODO: PostgreSQL log file - echo - fi + - | + echo Failure detected, so we show samples of log to help diagnose + # This part of code is executed only if previous command that fails are enclosed with set +e + # Upgrade log files + for ficlog in `ls $TRAVIS_BUILD_DIR/*.log` + do + echo "Debugging informations for file $ficlog" + #cat $ficlog + done + # Apache log file + echo "Debugging informations for file apache error.log" + sudo cat /var/log/apache2/travis_error_log + if [ "$DEBUG" = true ]; then + # Dolibarr log file + echo "Debugging informations for file dolibarr.log (latest 50 lines)" + tail -n 50 $TRAVIS_BUILD_DIR/documents/dolibarr.log + # Database log file + echo "Debugging informations for file mysql error.log" + sudo tail -n 50 /var/log/mysql/error.log + # TODO: PostgreSQL log file + echo + fi diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 39fd87b95a5..bd5ed8ba7ad 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -281,7 +281,7 @@ class UserTest extends PHPUnit\Framework\TestCase print __METHOD__." id=". $localobject->id ."\n"; //$this->assertNotEquals($user->date_creation, ''); - $user->addrights(0, 'supplier_proposal'); + $localobject->addrights(0, 'supplier_proposal'); $this->assertEquals($localobject->hasRight('member', ''), 0); $this->assertEquals($localobject->hasRight('member', 'member'), 0);$this->assertEquals($localobject->hasRight('product', 'member', 'read'), 0); $this->assertEquals($localobject->hasRight('member', 'member'), 0);$this->assertEquals($localobject->hasRight('produit', 'member', 'read'), 0); From bf801fc11d96ee1d868028ba270d2a166c915769 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Wed, 15 Jun 2022 16:50:34 +0200 Subject: [PATCH 087/421] temporary transformation (from string to array) so it can be traversable --- htdocs/core/class/extrafields.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 4f9b0d06f16..33b36b9dd47 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1268,7 +1268,8 @@ class ExtraFields require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1); $out .= ''; - foreach ($data as $data_key => $data_value) { + $dataArray = str_split($data); // as $data is not traversable as it's a string + foreach ($dataArray as $data_key => $data_value) { $out .= ''; // Value print ''; print ''; From 233d712e397d8a1c22001a3a032c958e0543323b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 13:06:07 +0200 Subject: [PATCH 099/421] NEW Support the Swiss QR-Code --- ChangeLog | 1 + .../QR code for invoices.txt | 6 ++ .../barcode_EAN13.txt | 0 htdocs/admin/pdf_other.php | 16 ++++ htdocs/core/class/commoninvoice.class.php | 88 +++++++++++++++++++ htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/lib/functions.lib.php | 44 ++++++---- .../modules/facture/doc/pdf_crabe.modules.php | 5 ++ .../facture/doc/pdf_sponge.modules.php | 5 ++ htdocs/langs/en_US/admin.lang | 1 + 10 files changed, 148 insertions(+), 20 deletions(-) rename dev/resources/iso-normes/{barcodes => qr-bar-codes}/QR code for invoices.txt (76%) rename dev/resources/iso-normes/{barcodes => qr-bar-codes}/barcode_EAN13.txt (100%) diff --git a/ChangeLog b/ChangeLog index 37957f61c1d..fb83d84bc60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,7 @@ NEW: PHP 8.1 compatibility NEW: Support for recurring purchase invoices. NEW: #20292 Include German public holidays NEW: Can show ZATCA QRCode on PDFs +NEW: Can show Swiss QR Code on PDFs NEW: #17123 added ExtraFields for Stock Mouvement NEW: #20609 : new massaction to assign a sale representatives on a selection of thirdparties NEW: #20653 edit discount pourcentage for all lines in one shot diff --git a/dev/resources/iso-normes/barcodes/QR code for invoices.txt b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt similarity index 76% rename from dev/resources/iso-normes/barcodes/QR code for invoices.txt rename to dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt index 639435238f9..df0be6b6659 100644 --- a/dev/resources/iso-normes/barcodes/QR code for invoices.txt +++ b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt @@ -20,3 +20,9 @@ https://www.pwc.com/m1/en/services/tax/me-tax-legal-news/2021/saudi-arabia-guide https://www.tecklenborgh.com/post/ksa-zatca-publishes-guide-on-how-to-develop-a-fatoora-compliant-qr-code Method to encode/decode ZATCA string is available in test/phpunit/BarcodeTest.php + + +* FOR QR-Bill in switzerland +---------------------------- +Syntax of QR Code https://www.swiss-qr-invoice.org/fr/ +Syntax of complentary field named "structured information of invoice S1": https://www.swiss-qr-invoice.org/downloads/qr-bill-s1-syntax-fr.pdf diff --git a/dev/resources/iso-normes/barcodes/barcode_EAN13.txt b/dev/resources/iso-normes/qr-bar-codes/barcode_EAN13.txt similarity index 100% rename from dev/resources/iso-normes/barcodes/barcode_EAN13.txt rename to dev/resources/iso-normes/qr-bar-codes/barcode_EAN13.txt diff --git a/htdocs/admin/pdf_other.php b/htdocs/admin/pdf_other.php index d8afe43720f..b064cbb8cd8 100644 --- a/htdocs/admin/pdf_other.php +++ b/htdocs/admin/pdf_other.php @@ -62,6 +62,11 @@ if ($action == 'update') { } if (GETPOSTISSET('INVOICE_ADD_ZATCA_QR_CODE')) { dolibarr_set_const($db, "INVOICE_ADD_ZATCA_QR_CODE", GETPOST("INVOICE_ADD_ZATCA_QR_CODE", 'int'), 'chaine', 0, '', $conf->entity); + dolibarr_del_const($db, "INVOICE_ADD_SWISS_QR_CODE", $conf->entity); + } + if (GETPOSTISSET('INVOICE_ADD_SWISS_QR_CODE')) { + dolibarr_set_const($db, "INVOICE_ADD_SWISS_QR_CODE", GETPOST("INVOICE_ADD_SWISS_QR_CODE", 'int'), 'chaine', 0, '', $conf->entity); + dolibarr_del_const($db, "INVOICE_ADD_ZATCA_QR_CODE", $conf->entity); } setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); @@ -138,6 +143,17 @@ if (isModEnabled('facture')) { } print ''; + print ''; + /* print ''; } print ''; - print ''; + print ''; print '
    '.$langs->trans("AutoApprovalOnCreate").''; - print ''; + print ''; print '
    '.$langs->trans("AutoSendMail").''; - print ''; + print ''; print '
    '.$langs->trans("AutoApprovalOnCreate").''; + print '
    '.$langs->trans("AutoValidationOnCreate").''; print ''; print '
    '; if ($key == 'ACCOUNTING_DATE_START_BINDING') { - print $form->selectDate(($conf->global->$key ? $db->idate($conf->global->$key) : -1), $key, 0, 0, 1); + print $form->selectDate((!empty($conf->global->$key) ? $db->idate($conf->global->$key) : -1), $key, 0, 0, 1); } elseif ($key == 'ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER') { $array = array(0=>$langs->trans("PreviousMonth"), 1=>$langs->trans("CurrentMonth"), 2=>$langs->trans("Fiscalyear")); print $form->selectarray($key, $array, (isset($conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER) ? $conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER : 0)); From 590cb20b41de73d2c64ebc43f0d8070858f69a69 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:30:09 +0200 Subject: [PATCH 042/421] Fix PHP 8.1.7 - $search_country_id not defined --- htdocs/accountancy/admin/journals_list.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index de6b8374c2a..39300579d5f 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2022 Alexandre Spangaro * * 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 @@ -76,6 +76,8 @@ if (empty($sortorder)) { $error = 0; +$search_country_id = GETPOST('search_country_id', 'int'); + // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('admin')); From 02f21fae78f444d175dfa551ff82fb28c7f2e98b Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:33:28 +0200 Subject: [PATCH 043/421] Fix PHP 8.1.7 - $newcardbutton not defined --- htdocs/accountancy/admin/account.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 48d8ab23d96..4d74237e2e4 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -350,6 +350,8 @@ if ($resql) { '; } + $newcardbutton = ''; + print ''; if ($optioncss != '') { print ''; From 33ecfddf83422c3c29a660c7812daa6a06bdb591 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:36:12 +0200 Subject: [PATCH 044/421] Fix PHP 8.1.7 - $out not defined --- htdocs/core/class/html.formaccounting.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formaccounting.class.php b/htdocs/core/class/html.formaccounting.class.php index 67d12147a3a..63b21e7fa0d 100644 --- a/htdocs/core/class/html.formaccounting.class.php +++ b/htdocs/core/class/html.formaccounting.class.php @@ -283,7 +283,7 @@ class FormAccounting extends Form $out .= ''; //if ($user->admin && $help) $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1); } else { - $out .= $langs->trans("ErrorNoAccountingCategoryForThisCountry", $mysoc->country_code); + $out = $langs->trans("ErrorNoAccountingCategoryForThisCountry", $mysoc->country_code); } } else { dol_print_error($this->db); From 6309dbe99b2cbf7eb9203d769fddb95f102de2a3 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 12 Jun 2022 07:38:49 +0200 Subject: [PATCH 045/421] Fix PHP 8.1.7 --- htdocs/accountancy/admin/defaultaccounts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 583b12368dc..725f7bbe47f 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -195,7 +195,7 @@ foreach ($list_account_main as $key) { print ''; // Do not force class=right, or it align also the content of the select box - print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); + print $formaccounting->select_account(!empty($conf->global->$key), $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); print '
    '; // Do not force class=right, or it align also the content of the select box - print $formaccounting->select_account(!empty($conf->global->$key), $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); + print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); print '
    '; - print ''; + $key_value = getDolGlobalString($conf->global->$key, $conf->global->$key); + print ''; print '
    '; // Do not force class=right, or it align also the content of the select box - print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); + $key_value = getDolGlobalString($conf->global->$key, $conf->global->$key); + print $formaccounting->select_account($key_value, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); print '
    '.$langs->trans("groups"); + print ''; + print $form->textwithpicto($langs->trans("groups"), $langs->trans("fusionGroupsUsers")); print '
    '.$langs->trans("users").''; + print $form->textwithpicto($langs->trans("users"), $langs->trans("fusionGroupsUsers")); print ''; $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from '.MAIN_DB_PREFIX.'user as u'; diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 2005d7e613c..36f1e839e67 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -80,6 +80,8 @@ MotifCP=Reason UserCP=User ErrorAddEventToUserCP=An error occurred while adding the exceptional leave. AddEventToUserOkCP=The addition of the exceptional leave has been completed. +ErrorFieldRequiredUserOrGroup=The "group" field or the "user" field must be filled in +fusionGroupsUsers=The groups field and the user field will be merged MenuLogCP=View change logs LogCP=Log of all updates made to "Balance of Leave" ActionByCP=Updated by From 2209d31b2c6666cdd7917c48cedf80f5cf7e5819 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 08:51:49 +0200 Subject: [PATCH 060/421] add comment on function --- htdocs/holiday/card_group.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 5dee6e54f6c..f244c6374e5 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -655,11 +655,11 @@ if (is_object($db)) { } /** * send email to validator for current leave represented by (id) - * @param $id - * @param $cancreate - * @param $now - * @param $autoValidation - * @return string|void + * @param $id validator for current leave represented by (id) + * @param $cancreate flag for user right + * @param $now date + * @param $autoValidation boolean flag on autovalidation + * @return stdClass * @throws Exception */ function sendMail($id, $cancreate, $now, $autoValidation) From af0846e2f7b22e129628ee699b9dcb1ab6e00ccc Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 09:09:19 +0200 Subject: [PATCH 061/421] add sanitize to sql --- htdocs/holiday/card_group.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index f244c6374e5..8de636da6c8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -264,7 +264,7 @@ if (empty($reshook)) { /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; - $sql .= ' WHERE fk_usergroup in (' . implode(',', $groups) . ')'; + $sql .= ' WHERE fk_usergroup in (' .$this->db->sanitize(implode(',', $groups)) . ')'; $resql = $db->query($sql); if ($resql) { @@ -423,7 +423,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { } $("input[name=autoValidation]").click( function(e) { - console.log("chang") + if( $("input[name=autoValidation]").is(":checked") ){ $("#AutoSendMail").prop("disabled", false); From d7ca52f4ef996b9711a321823da0e19c11730d0d Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 09:17:19 +0200 Subject: [PATCH 062/421] remove $this on sanitize --- htdocs/holiday/card_group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 8de636da6c8..b63a3ae657b 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -264,7 +264,7 @@ if (empty($reshook)) { /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; - $sql .= ' WHERE fk_usergroup in (' .$this->db->sanitize(implode(',', $groups)) . ')'; + $sql .= ' WHERE fk_usergroup in (' .$db->sanitize(implode(',', $groups)) . ')'; $resql = $db->query($sql); if ($resql) { From 09c5b8be79204817c5fc359df27b7690a6de7f19 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 10:38:49 +0200 Subject: [PATCH 063/421] add comment --- htdocs/holiday/card_group.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index b63a3ae657b..5e571f077c8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -261,6 +261,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); // usergroup select + // better perf on single sql /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; From 8729b9f2dd9fb5d565be342467980f3e5e9d0a18 Mon Sep 17 00:00:00 2001 From: NASDAMI Quatadah Date: Mon, 13 Jun 2022 13:34:18 +0200 Subject: [PATCH 064/421] array instead of string in @param pfx() function --- htdocs/core/class/evalmath.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/evalmath.class.php b/htdocs/core/class/evalmath.class.php index ccd495bb623..2259cfde06f 100644 --- a/htdocs/core/class/evalmath.class.php +++ b/htdocs/core/class/evalmath.class.php @@ -368,7 +368,7 @@ class EvalMath /** * evaluate postfix notation * - * @param string $tokens Expression + * @param array $tokens Expression * @param array $vars Array * @return string Output */ From dddd4186a864b53574b61d65d850c28ccf5c2fb0 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 13 Jun 2022 15:37:43 +0200 Subject: [PATCH 065/421] NEW show product label on inventory --- htdocs/core/class/commonobject.class.php | 11 ++++++++- .../fourn/class/fournisseur.product.class.php | 20 ++++++++++++---- htdocs/product/class/product.class.php | 24 ++++++++++++------- .../inventory/class/inventory.class.php | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1f64741385f..1f258fa2ba4 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7556,11 +7556,20 @@ abstract class CommonObject if ($classname && class_exists($classname)) { $object = new $classname($this->db); if ($object->element === 'product') { // Special cas for product because default valut of fetch are wrong + $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]); + $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]); + $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]); + $getnomurlparam6 = (!isset($InfoFieldList[8]) ? 0 : $InfoFieldList[8]); + + /** + * @var Product $object + */ $object->fetch($value, '', '', '', 0, 1, 1); + $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6); } else { $object->fetch($value); + $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } - $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } } else { dol_syslog('Error bad setup of extrafield', LOG_WARNING); diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index d113eadd8a7..774dd192659 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -1091,12 +1091,15 @@ class ProductFournisseur extends Product * * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) * @param string $option On what the link point to ('nolink', ...) - * @param int $notooltip 1=Disable tooltip - * @param string $morecss Add more css on link + * @param int $maxlength Maxlength of ref * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @param int $notooltip No tooltip + * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string + * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set + * @param string $morecss ''=Add more css on link * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') { global $db, $conf, $langs, $hookmanager; @@ -1107,6 +1110,11 @@ class ProductFournisseur extends Product $result = ''; $label = ''; + $newref = $this->ref; + if ($maxlength) { + $newref = dol_trunc($newref, $maxlength, 'middle'); + } + if (!empty($this->entity)) { $tmpphoto = $this->show_photos('product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80); if ($this->nbphoto > 0) { @@ -1228,10 +1236,12 @@ class ProductFournisseur extends Product $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { - $result .= $this->ref.($this->ref_supplier ? ' ('.$this->ref_supplier.')' : ''); + $result .= $newref.($this->ref_supplier ? ' ('.$this->ref_supplier.')' : ''); } $result .= $linkend; - //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + if ($withpicto != 2) { + $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : ''); + } global $action; $hookmanager->initHooks(array($this->element . 'dao')); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 5a7990cd0a7..c5eb211de2c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4882,14 +4882,17 @@ class Product extends CommonObject /** * Return clicable link of object (with eventually picto) * - * @param int $withpicto Add picto into link - * @param string $option Where point the link ('stock', 'composition', 'category', 'supplier', '') - * @param int $maxlength Maxlength of ref - * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking - * @param int $notooltip No tooltip - * @return string String with URL + * @param int $withpicto Add picto into link + * @param string $option Where point the link ('stock', 'composition', 'category', 'supplier', '') + * @param int $maxlength Maxlength of ref + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @param int $notooltip No tooltip + * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string + * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set + * @param string $morecss ''=Add more css on link + * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0) + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') { global $conf, $langs, $hookmanager; include_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; @@ -4997,9 +5000,9 @@ class Product extends CommonObject } $linkclose .= ' title="'.dol_escape_htmltag($label, 1, 1).'"'; - $linkclose .= ' class="nowraponall classfortooltip"'; + $linkclose .= ' class="nowraponall classfortooltip'.($morecss ? ' '.$morecss : '').'"'; } else { - $linkclose = ' class="nowraponall"'; + $linkclose = ' class="nowraponall'.($morecss ? ' '.$morecss : '').'"'; } if ($option == 'supplier' || $option == 'category') { @@ -5038,6 +5041,9 @@ class Product extends CommonObject } $result .= $newref; $result .= $linkend; + if ($withpicto != 2) { + $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : ''); + } global $action; $hookmanager->initHooks(array('productdao')); diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index 80823c7ba5a..c755b92b3e4 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -101,7 +101,7 @@ class Inventory extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), - 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0:1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), From 37ff10eafc6b2e17016b5426aae8a1b5e0427ddb Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 14 Jun 2022 09:13:53 +0200 Subject: [PATCH 066/421] PHP 8 in social contribution --- htdocs/compta/paiement_charge.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/compta/paiement_charge.php b/htdocs/compta/paiement_charge.php index db48b2767f2..ba62c36b0fa 100644 --- a/htdocs/compta/paiement_charge.php +++ b/htdocs/compta/paiement_charge.php @@ -1,6 +1,7 @@ * Copyright (C) 2016-2018 Frédéric France + * Copyright (C) 2022 Alexandre Spangaro * * 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 @@ -254,6 +255,7 @@ if ($action == 'create') { print "
    '.$langs->trans('Mode').''.$langs->trans("Pa print '
    '.$langs->trans('Numero').''.$object->num_payment.'
    '.$langs->trans('Amount').''.price($object->amount, 0, $outputlangs, 1, -1, -1, $conf->currency).'
    '.$langs->trans('Amount').''.price($object->amount, 0, $langs, 1, -1, -1, $conf->currency).'
    '.$langs->trans('Note').''.nl2br($object->note).'
    '.$obj->label.''.$obj->label_sc.'
    "; if (!empty($conf->global->MULTICOMPANY_ALLOW_EXPORT_ACCOUNTING_DOC_FOR_ALL_ENTITIES)) { + $socid = $mc->id; print $mc->select_entities(GETPOSTISSET('search_entity') ? GETPOST('search_entity', 'int') : $mc->id, 'search_entity', '', false, false, false, false, true); } else { print $mc->label; @@ -576,6 +602,16 @@ if (!empty($conf->multicompany->enabled) && is_object($mc)) { print '
    '; +// Project filter +if (!empty($conf->projet->enabled)) { + $formproject = new FormProjets($db); + $langs->load('projects'); + print ''.$langs->trans('Project').":"; + print img_picto('', 'project').$formproject->select_projects(($socid > 0 ? $socid : -1), $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 1, 0, ''); + print ''; + print '
    '; +} + foreach ($listofchoices as $choice => $val) { if (empty($val['enabled'])) { continue; // list not qualified @@ -614,7 +650,7 @@ if (!empty($date_start) && !empty($date_stop)) { echo dol_print_date($date_start, 'day', 'tzuserrel')." - ".dol_print_date($date_stop, 'day', 'tzuserrel'); - print 'The exported ZIP file will contain the lists of requested items in CSV, as well as their attached files in their original format (PDF, ODT, DOCX...). ExportAccountingSourceDocHelp2=To export your journals, use the menu entry %s - %s. +ExportAccountingProjectHelp=Specify a project if you need an accounting report only for a specific project. Expense reports and loan payments are not included in project reports. VueByAccountAccounting=View by accounting account VueBySubAccountAccounting=View by accounting subaccount diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index e0fa85dd273..b4bd6f75d9a 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -293,4 +293,5 @@ LeadPublicFormDesc=You can enable here a public page to allow your prospects to EnablePublicLeadForm=Enable the public form for contact NewLeadbyWeb=Your message or request has been recorded. We will answer or contact your soon. NewLeadForm=New contact form -LeadFromPublicForm=Online lead from public form \ No newline at end of file +LeadFromPublicForm=Online lead from public form +ExportAccountingReportButtonLabel=Get report \ No newline at end of file diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 0cfe126d69b..f3b60e8593c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1280,6 +1280,17 @@ if ($action == 'create' && $user->rights->projet->creer) { } } + // Accounting Report + $accouting_module_activated = !empty($conf->comptabilite->enabled) || !empty($conf->accounting->enabled); + if ($accouting_module_activated && $object->statut != Project::STATUS_DRAFT) { + $start = dol_getdate((int)$object->date_start); + $end = dol_getdate((int)$object->date_end); + $url = DOL_URL_ROOT.'/compta/accounting-files.php?projectid='.$object->id; + if(!empty($object->date_start)) $url .= '&date_startday='.$start['mday'].'&date_startmonth='.$start['mon'].'&date_startyear='.$start['year']; + if(!empty($object->date_end)) $url .= '&date_stopday='.$end['mday'].'&date_stopmonth='.$end['mon'].'&date_stopyear='.$end['year']; + print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, ''); + } + // Modify if ($object->statut != Project::STATUS_CLOSED && $user->rights->projet->creer) { if ($userWrite > 0) { From 512441bbf4f47452c102a5e393a6d4c6358f053f Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 19 Jun 2022 06:07:03 +0200 Subject: [PATCH 096/421] Review structure data on dictionary c_asset_disposal_type --- htdocs/install/mysql/data/llx_c_asset_disposal_type.sql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/data/llx_c_asset_disposal_type.sql b/htdocs/install/mysql/data/llx_c_asset_disposal_type.sql index 5ca253c476e..4951b9df198 100644 --- a/htdocs/install/mysql/data/llx_c_asset_disposal_type.sql +++ b/htdocs/install/mysql/data/llx_c_asset_disposal_type.sql @@ -19,7 +19,6 @@ -- Do not include comments at end of line, this file is parsed during install and string '--' are removed. -- -INSERT INTO `llx_c_asset_disposal_type` (`rowid`, `entity`, `code`, `label`, `active`) VALUES -(1, 1, 'C', 'Sale', 1), -(2, 1, 'HS', 'Putting out of service', 1), -(3, 1, 'D', 'Destruction', 1); +INSERT INTO llx_c_asset_disposal_type (rowid, entity, code, label, active) VALUES (1, 1, 'C', 'Sale', 1); +INSERT INTO llx_c_asset_disposal_type (rowid, entity, code, label, active) VALUES (2, 1, 'HS', 'Putting out of service', 1); +INSERT INTO llx_c_asset_disposal_type (rowid, entity, code, label, active) VALUES (3, 1, 'D', 'Destruction', 1); From 1e1d78037e149576990572617710bb4c44ebbba5 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 19 Jun 2022 06:10:04 +0200 Subject: [PATCH 097/421] Change comment on llx_asset_accountancy_codes_economic-asset.sql --- .../tables/llx_asset_accountancy_codes_economic-asset.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql index fc799154421..e81b9d60c7f 100644 --- a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql @@ -15,7 +15,8 @@ -- along with this program. If not, see https://www.gnu.org/licenses/. -- ======================================================================== -- --- Table to store the configuration of the accounting accounts of a fixed asset for economic status +-- Table to store the configuration of the accounting accounts of a fixed asset for economic status (fk_asset will be filled and fk_asset_model will be null) +-- or to store the configuration of the accounting accounts for templates of asset (fk_asset_model will be filled and fk_asset will be null) -- -- Data example: -- INSERT INTO `llx_asset_accountancy_codes_economic` (`rowid`, `fk_asset`, `fk_asset_model`, `asset`, `depreciation_asset`, `depreciation_expense`, `value_asset_sold`, `receivable_on_assignment`, `proceeds_from_sales`, `vat_collected`, `vat_deductible`, `tms`, `fk_user_modif`) VALUES From e6a9d48e71c29a61d5e616ca3733c1ff7f863550 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 19 Jun 2022 06:41:05 +0200 Subject: [PATCH 098/421] Fix code error --- htdocs/accountancy/admin/defaultaccounts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index cfbbe8f9cfd..44fbef7429e 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -201,7 +201,7 @@ foreach ($list_account_main as $key) { print '
    '; // Do not force class=right, or it align also the content of the select box - $key_value = getDolGlobalString($conf->global->$key, $conf->global->$key); + $key_value = getDolGlobalString($key); print $formaccounting->select_account($key_value, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); print '
    '; + print $form->textwithpicto($langs->trans("INVOICE_ADD_SWISS_QR_CODE"), ''); + print ''; + if ($conf->use_javascript_ajax) { + print ajax_constantonoff('INVOICE_ADD_SWISS_QR_CODE'); + } else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("INVOICE_ADD_SWISS_QR_CODE", $arrval, $conf->global->INVOICE_ADD_SWISS_QR_CODE); + } + print '
    '.$langs->trans("MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING").''; if ($conf->use_javascript_ajax) { diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 14b19023420..dd30a2e3cab 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -900,6 +900,94 @@ abstract class CommonInvoice extends CommonObject return $s; } + + + /** + * Build string for QR-Bill (Switzerland) + * + * @return string String for Switzerland QR Code if QR-Bill + */ + public function buildSwitzerlandQRString() + { + global $conf, $mysoc; + + $tmplang = new Translate('', $conf); + $tmplang->setDefaultLang('en_US'); + $tmplang->load("main"); + + $pricewithtaxstring = price2num($this->total_ttc, 2, 1); + $pricetaxstring = price2num($this->total_tva, 2, 1); + + $complementaryinfo = ''; + /* + Example: //S1/10/10201409/11/190512/20/1400.000-53/30/106017086/31/180508/32/7.7/40/2:10;0:30 + /10/ Numéro de facture – 10201409 + /11/ Date de facture – 12.05.2019 + /20/ Référence client – 1400.000-53 + /30/ Numéro IDE pour la TVA – CHE-106.017.086 TVA + /31/ Date de la prestation pour la comptabilisation de la TVA – 08.05.2018 + /32/ Taux de TVA sur le montant total de la facture – 7.7% + /40/ Conditions – 2% d’escompte à 10 jours, paiement net à 30 jours + */ + $datestring = dol_print_date($this->date, '%y%m%d'); + //$pricewithtaxstring = price($this->total_ttc, 0, $tmplang, 0, -1, 2); + //$pricetaxstring = price($this->total_tva, 0, $tmplang, 0, -1, 2); + $complementaryinfo = '//S1/10/'.str_replace('/', '', $this->ref).'/11/'.$datestring; + if ($this->ref_client) { + $complementaryinfo .= '/20/'.$this->ref_client; + } + if ($this->thirdparty->vat_number) { + $complementaryinfo .= '/30/'.$this->thirdparty->vat_number; + } + + // Header + $s .= "SPC\n"; + $s .= "0200\n"; + $s .= "1\n"; + if ($this->fk_account > 0) { + // Bank BAN if country is LI or CH + // TODO Add + } else { + $s .= "\n"; + } + // Seller + $s .= "S"; + $s .= dol_trunc($mysoc->name, 70, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($mysoc->address, 70, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($mysoc->zip, 16, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($mysoc->town, 35, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($mysoc->country_code, 2, 'right', 'UTF-8', 1)."\n"; + // Final seller + $s .= "\n"; + $s .= "\n"; + $s .= "\n"; + $s .= "\n"; + $s .= "\n"; + $s .= "\n"; + $s .= "\n"; + // Amount of payment (to do?) + $s .= price($pricewithtaxstring, 0, 'none', 0, 0, 2)."\n"; + $s .= $this->currency_code."\n"; + // Buyer + $s .= "S"; + $s .= dol_trunc($this->thirdparty->name, 70, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($this->thirdparty->address, 70, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($this->thirdparty->zip, 16, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($this->thirdparty->town, 35, 'right', 'UTF-8', 1)."\n"; + $s .= dol_trunc($this->thirdparty->country_code, 2, 'right', 'UTF-8', 1)."\n"; + // ID of payment + $s .= "NON\n"; // NON or QRR + $s .= "\n"; // QR Code if previous field is QRR + if ($complementaryinfo) { + $s .= $complementaryinfo."\n"; + } else { + $s .= "\n"; + } + $s .= "EPD\n"; + $s .= "\n"; + //var_dump($s);exit; + return $s; + } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 71ecd3f75d1..4a95bb7d345 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -278,7 +278,7 @@ abstract class CommonObject public $country_id; /** - * @var string + * @var string The ISO country code on 2 chars. * @see getFullAddress(), isInEEC(), country */ public $country_code; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index e1fe08c7f18..48f0b3f452f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5467,7 +5467,7 @@ function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0) * * @param float $amount Amount to format * @param integer $form Type of format, HTML or not (not by default) - * @param Translate|string $outlangs Object langs for output + * @param Translate|string $outlangs Object langs for output. '' use default lang. 'none' use international separators. * @param int $trunc 1=Truncate if there is more decimals than MAIN_MAX_DECIMALS_SHOWN (default), 0=Does not truncate. Deprecated because amount are rounded (to unit or total amount accurancy) before beeing inserted into database or after a computation, so this parameter should be useless. * @param int $rounding Minimum number of decimal to show. If 0, no change, if -1, we use min($conf->global->MAIN_MAX_DECIMALS_UNIT,$conf->global->MAIN_MAX_DECIMALS_TOT) * @param int $forcerounding Force the number of decimal to forcerounding decimal (-1=do not force) @@ -5490,25 +5490,31 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ } $nbdecimal = $rounding; - // Output separators by default (french) - $dec = ','; - $thousand = ' '; - - // If $outlangs not forced, we use use language - if (!is_object($outlangs)) { - $outlangs = $langs; - } - - if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") { - $dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal"); - } - if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") { - $thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand"); - } - if ($thousand == 'None') { + if ($outlangs === 'none') { + // Use international separators + $dec = '.'; $thousand = ''; - } elseif ($thousand == 'Space') { + } else { + // Output separators by default (french) + $dec = ','; $thousand = ' '; + + // If $outlangs not forced, we use use language + if (!is_object($outlangs)) { + $outlangs = $langs; + } + + if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") { + $dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal"); + } + if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") { + $thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand"); + } + if ($thousand == 'None') { + $thousand = ''; + } elseif ($thousand == 'Space') { + $thousand = ' '; + } } //print "outlangs=".$outlangs->defaultlang." amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'
    "; @@ -5547,7 +5553,7 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ } // Add symbol of currency if requested $cursymbolbefore = $cursymbolafter = ''; - if ($currency_code) { + if ($currency_code && is_object($outlangs)) { if ($currency_code == 'auto') { $currency_code = $conf->currency; } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 09f1a0b27e8..63e9d61c409 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -452,8 +452,13 @@ class pdf_crabe extends ModelePDFFactures // You can add more thing under header here, if you increase $extra_under_address_shift too. $extra_under_address_shift = 0; + $qrcodestring = ''; if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) { $qrcodestring = $object->buildZATCAQRString(); + } elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) { + $qrcodestring = $object->buildSwitzerlandQRString(); + } + if ($qrcodestring) { $qrcodecolor = array('25', '25', '25'); // set style for QR-code $styleQr = array( diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 9210946128e..46ac4ffde37 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -435,8 +435,13 @@ class pdf_sponge extends ModelePDFFactures // You can add more thing under header here, if you increase $extra_under_address_shift too. $extra_under_address_shift = 0; + $qrcodestring = ''; if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) { $qrcodestring = $object->buildZATCAQRString(); + } elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) { + $qrcodestring = $object->buildSwitzerlandQRString(); + } + if ($qrcodestring) { $qrcodecolor = array('25', '25', '25'); // set style for QR-code $styleQr = array( diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 341789af7bf..26c2a959a13 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2266,5 +2266,6 @@ IconOnlyTextOnHover=Icon only - Text of icon appears under icon on mouse hover t IconOnly=Icon only - Text on tooltip only INVOICE_ADD_ZATCA_QR_CODE=Show the ZATCA QR code on invoices INVOICE_ADD_ZATCA_QR_CODEMore=Some Arabic countries need this QR Code on their invoices +INVOICE_ADD_SWISS_QR_CODE=Show the swiss QR-Bill code on invoices UrlSocialNetworksDesc=Url link of social network. Use {socialid} for the variable part that contains the social network ID. IfThisCategoryIsChildOfAnother=If this category is a child of another one \ No newline at end of file From eb22434da1cff4fea349cb6ec730f3e441bc31e3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 13:26:49 +0200 Subject: [PATCH 100/421] NEW Support the Swiss QR-Code --- .../qr-bar-codes/QR code for invoices.txt | 1 + htdocs/core/class/commoninvoice.class.php | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt index df0be6b6659..b388ed0c599 100644 --- a/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt +++ b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt @@ -26,3 +26,4 @@ Method to encode/decode ZATCA string is available in test/phpunit/BarcodeTest.ph ---------------------------- Syntax of QR Code https://www.swiss-qr-invoice.org/fr/ Syntax of complentary field named "structured information of invoice S1": https://www.swiss-qr-invoice.org/downloads/qr-bill-s1-syntax-fr.pdf +To test/validate: https://www.swiss-qr-invoice.org/validator/ diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index dd30a2e3cab..e96eee5c553 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -947,13 +947,18 @@ abstract class CommonInvoice extends CommonObject if ($this->fk_account > 0) { // Bank BAN if country is LI or CH // TODO Add + $bankaccount = new Account($this->db); + $bankaccount->fetch($this->fk_account); + $s .= $bankaccount->iban."\n"; } else { $s .= "\n"; } // Seller - $s .= "S"; + $s .= "S\n"; $s .= dol_trunc($mysoc->name, 70, 'right', 'UTF-8', 1)."\n"; - $s .= dol_trunc($mysoc->address, 70, 'right', 'UTF-8', 1)."\n"; + $addresslinearray = explode("\n", $mysoc->address); + $s .= dol_trunc(empty($addresslinearray[1]) ? '' : $addresslinearray[1], 70, 'right', 'UTF-8', 1)."\n"; // address line 1 + $s .= dol_trunc(empty($addresslinearray[2]) ? '' : $addresslinearray[2], 70, 'right', 'UTF-8', 1)."\n"; // address line 2 $s .= dol_trunc($mysoc->zip, 16, 'right', 'UTF-8', 1)."\n"; $s .= dol_trunc($mysoc->town, 35, 'right', 'UTF-8', 1)."\n"; $s .= dol_trunc($mysoc->country_code, 2, 'right', 'UTF-8', 1)."\n"; @@ -967,11 +972,13 @@ abstract class CommonInvoice extends CommonObject $s .= "\n"; // Amount of payment (to do?) $s .= price($pricewithtaxstring, 0, 'none', 0, 0, 2)."\n"; - $s .= $this->currency_code."\n"; + $s .= ($this->multicurrency_code ? $this->multicurrency_code : $conf->currency)."\n"; // Buyer - $s .= "S"; + $s .= "S\n"; $s .= dol_trunc($this->thirdparty->name, 70, 'right', 'UTF-8', 1)."\n"; - $s .= dol_trunc($this->thirdparty->address, 70, 'right', 'UTF-8', 1)."\n"; + $addresslinearray = explode("\n", $this->thirdparty->address); + $s .= dol_trunc(empty($addresslinearray[1]) ? '' : $addresslinearray[1], 70, 'right', 'UTF-8', 1)."\n"; // address line 1 + $s .= dol_trunc(empty($addresslinearray[2]) ? '' : $addresslinearray[2], 70, 'right', 'UTF-8', 1)."\n"; // address line 2 $s .= dol_trunc($this->thirdparty->zip, 16, 'right', 'UTF-8', 1)."\n"; $s .= dol_trunc($this->thirdparty->town, 35, 'right', 'UTF-8', 1)."\n"; $s .= dol_trunc($this->thirdparty->country_code, 2, 'right', 'UTF-8', 1)."\n"; From 78c4a166c02bb9ba071df1d5cecde92323ecf18c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 15:36:17 +0200 Subject: [PATCH 101/421] Trans --- htdocs/langs/en_US/languages.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/languages.lang b/htdocs/langs/en_US/languages.lang index 349cb42fbab..6de4824ecea 100644 --- a/htdocs/langs/en_US/languages.lang +++ b/htdocs/langs/en_US/languages.lang @@ -13,6 +13,7 @@ Language_az_AZ=Azerbaijani Language_bn_BD=Bengali Language_bn_IN=Bengali (India) Language_bg_BG=Bulgarian +Language_bo_CN=Tibetan Language_bs_BA=Bosnian Language_ca_ES=Catalan Language_cs_CZ=Czech From 3f43ba0bc0e1dc2ca8f34370d1d8a7565ed9a5b0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:17:31 +0200 Subject: [PATCH 102/421] Update llx_asset-asset.sql --- .../install/mysql/tables/llx_asset-asset.sql | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset-asset.sql b/htdocs/install/mysql/tables/llx_asset-asset.sql index 97ceaf2a686..2eed188bc14 100644 --- a/htdocs/install/mysql/tables/llx_asset-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset-asset.sql @@ -18,20 +18,20 @@ -- Table for fixed asset -- -- Data example: --- INSERT INTO `llx_asset` (`rowid`, `ref`, `entity`, `label`, `fk_asset_model`, `reversal_amount_ht`, `acquisition_value_ht`, `recovered_vat`, `reversal_date`, `date_acquisition`, `date_start`, `qty`, `acquisition_type`, `asset_type`, `not_depreciated`, `disposal_date`, `disposal_amount_ht`, `fk_disposal_type`, `disposal_depreciated`, `disposal_subject_to_vat`, `note_public`, `note_private`, `date_creation`, `tms`, `fk_user_creat`, `fk_user_modif`, `last_main_doc`, `import_key`, `model_pdf`, `status`) VALUES --- (1, 'LAPTOP', 1, 'LAPTOP xxx for accountancy department', 1, NULL, 1000.00000000, NULL, NULL, '2022-01-18', '2022-01-20', 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-01-18 14:31:21', '2022-03-09 14:09:46', 1, 1, NULL, NULL, NULL, 0); +-- INSERT INTO llx_asset (ref, entity, label, fk_asset_model, reversal_amount_ht, acquisition_value_ht, recovered_vat, reversal_date, date_acquisition, date_start, qty, acquisition_type, asset_type, not_depreciated, disposal_date, disposal_amount_ht, fk_disposal_type, disposal_depreciated, disposal_subject_to_vat, note_public, note_private, date_creation, tms, fk_user_creat, fk_user_modif, last_main_doc, import_key, model_pdf, status) VALUES +-- ('LAPTOP', 1, 'LAPTOP xxx for accountancy department', 1, NULL, 1000.00000000, NULL, NULL, '2022-01-18', '2022-01-20', 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-01-18 14:31:21', '2022-03-09 14:09:46', 1, 1, NULL, NULL, NULL, 0); CREATE TABLE llx_asset( - rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, - ref varchar(128) NOT NULL, - entity integer DEFAULT 1 NOT NULL, - label varchar(255), + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) NOT NULL, + entity integer DEFAULT 1 NOT NULL, + label varchar(255), fk_asset_model integer, reversal_amount_ht double(24,8), acquisition_value_ht double(24,8) DEFAULT NULL, - recovered_vat double(24,8), + recovered_vat double(24,8), reversal_date date, @@ -51,15 +51,15 @@ CREATE TABLE llx_asset( disposal_depreciated integer DEFAULT 0, disposal_subject_to_vat integer DEFAULT 0, - note_public text, - note_private text, + note_public text, + note_private text, - date_creation datetime NOT NULL, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_user_creat integer NOT NULL, - fk_user_modif integer, - last_main_doc varchar(255), - import_key varchar(14), - model_pdf varchar(255), - status integer NOT NULL + date_creation datetime NOT NULL, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + last_main_doc varchar(255), + import_key varchar(14), + model_pdf varchar(255), + status integer NOT NULL ) ENGINE=innodb; From d9bd1638befa9248e199dbfd81154f28aecb8ea3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:19:43 +0200 Subject: [PATCH 103/421] Update llx_asset_accountancy_codes_economic-asset.sql --- .../tables/llx_asset_accountancy_codes_economic-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql index e81b9d60c7f..30969e59916 100644 --- a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_economic-asset.sql @@ -19,8 +19,8 @@ -- or to store the configuration of the accounting accounts for templates of asset (fk_asset_model will be filled and fk_asset will be null) -- -- Data example: --- INSERT INTO `llx_asset_accountancy_codes_economic` (`rowid`, `fk_asset`, `fk_asset_model`, `asset`, `depreciation_asset`, `depreciation_expense`, `value_asset_sold`, `receivable_on_assignment`, `proceeds_from_sales`, `vat_collected`, `vat_deductible`, `tms`, `fk_user_modif`) VALUES --- (2, 1, NULL, '2183', '2818', '68112', '675', '465', '775', '44571', '44562', '2022-01-18 14:20:20', 1); +-- INSERT INTO llx_asset_accountancy_codes_economic (fk_asset, fk_asset_model, asset, depreciation_asset, depreciation_expense, value_asset_sold, receivable_on_assignment, proceeds_from_sales, vat_collected, vat_deductible, tms, fk_user_modif) VALUES +-- (1, NULL, '2183', '2818', '68112', '675', '465', '775', '44571', '44562', '2022-01-18 14:20:20', 1); CREATE TABLE llx_asset_accountancy_codes_economic( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, From 16c9c7f54a432ad35115792125ecf81e2cb7523d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:20:44 +0200 Subject: [PATCH 104/421] Update llx_asset_accountancy_codes_fiscal-asset.sql --- .../mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql index d8229184077..9c005727f81 100644 --- a/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_accountancy_codes_fiscal-asset.sql @@ -18,8 +18,8 @@ -- Table to store the configuration of the accounting accounts of a fixed asset for fiscal status -- -- Data example: --- INSERT INTO `llx_asset_accountancy_codes_fiscal` (`rowid`, `fk_asset`, `fk_asset_model`, `accelerated_depreciation`, `endowment_accelerated_depreciation`, `provision_accelerated_depreciation`, `tms`, `fk_user_modif`) VALUES --- (2, 1, NULL, NULL, NULL, NULL, '2022-01-18 14:20:20', 1); +-- INSERT INTO llx_asset_accountancy_codes_fiscal (fk_asset, fk_asset_model, accelerated_depreciation, endowment_accelerated_depreciation, provision_accelerated_depreciation, tms, fk_user_modif) VALUES +-- (1, NULL, NULL, NULL, NULL, '2022-01-18 14:20:20', 1); CREATE TABLE llx_asset_accountancy_codes_fiscal( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, From bc9159e3c89037fd7cc64f258a7de1bf1d26be4b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:21:54 +0200 Subject: [PATCH 105/421] Update llx_asset_depreciation-asset.sql --- htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql index f58b2c8cc5c..0347e8d112d 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation-asset.sql @@ -18,7 +18,7 @@ -- Table to store depreciation of a fixed asset -- -- Data example: --- INSERT INTO `llx_asset_depreciation` (`rowid`, `fk_asset`, `depreciation_mode`, `ref`, `depreciation_date`, `depreciation_ht`, `cumulative_depreciation_ht`, `accountancy_code_debit`, `accountancy_code_credit`, `tms`, `fk_user_modif`) VALUES +-- INSERT INTO llx_asset_depreciation (rowid, fk_asset, depreciation_mode, ref, depreciation_date, depreciation_ht, cumulative_depreciation_ht, accountancy_code_debit, accountancy_code_credit, tms, fk_user_modif) VALUES -- (194, 1, 'economic', '2022-01', '2022-01-31 23:59:59', 2.00000000, 2.00000000, '2818', '68112', '2022-03-09 14:10:29', NULL), -- (195, 1, 'economic', '2022-02', '2022-02-28 23:59:59', 5.00000000, 7.00000000, '2818', '68112', '2022-03-09 14:10:29', NULL), -- (314, 1, 'economic', '2022-03', '2022-03-31 23:59:59', 8.33000000, 15.33000000, '2818', '68112', '2022-03-09 14:15:48', NULL), @@ -95,6 +95,6 @@ CREATE TABLE llx_asset_depreciation( accountancy_code_debit varchar(32), accountancy_code_credit varchar(32), - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer ) ENGINE=innodb; From 06023b913963e3f755ce1d509864cab0aa582c77 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:22:59 +0200 Subject: [PATCH 106/421] Update llx_asset_depreciation_options_economic-asset.sql --- .../tables/llx_asset_depreciation_options_economic-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql index c34fca1b043..e23a2ed1414 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_economic-asset.sql @@ -18,8 +18,8 @@ -- Table to store economical depreciation of a fixed asset -- -- Data example: --- INSERT INTO `llx_asset_depreciation_options_economic` (`rowid`, `fk_asset`, `fk_asset_model`, `depreciation_type`, `accelerated_depreciation_option`, `degressive_coefficient`, `duration`, `duration_type`, `amount_base_depreciation_ht`, `amount_base_deductible_ht`, `total_amount_last_depreciation_ht`, `tms`, `fk_user_modif`) VALUES --- (11, 1, NULL, 1, NULL, 1.75000000, 60, 1, 500.00000000, 0.00000000, 7.00000000, '2022-03-09 14:15:48', 1); +-- INSERT INTO llx_asset_depreciation_options_economic (fk_asset, fk_asset_model, depreciation_type, accelerated_depreciation_option, degressive_coefficient, duration, duration_type, amount_base_depreciation_ht, amount_base_deductible_ht, total_amount_last_depreciation_ht, tms, fk_user_modif) VALUES +-- (1, NULL, 1, NULL, 1.75000000, 60, 1, 500.00000000, 0.00000000, 7.00000000, '2022-03-09 14:15:48', 1); CREATE TABLE llx_asset_depreciation_options_economic( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, From e0149f3f033bb0249a4e3eca347d9cc9917edcb0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:24:00 +0200 Subject: [PATCH 107/421] Update llx_asset_depreciation_options_fiscal-asset.sql --- .../tables/llx_asset_depreciation_options_fiscal-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql index 0a52c26eaaa..3d9d5e9d091 100644 --- a/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_depreciation_options_fiscal-asset.sql @@ -18,8 +18,8 @@ -- Table to store fiscal depreciation of a fixed asset -- -- Data example: --- INSERT INTO `llx_asset_depreciation_options_fiscal` (`rowid`, `fk_asset`, `fk_asset_model`, `depreciation_type`, `accelerated_depreciation_option`, `degressive_coefficient`, `duration`, `duration_type`, `amount_base_depreciation_ht`, `amount_base_deductible_ht`, `total_amount_last_depreciation_ht`, `tms`, `fk_user_modif`) VALUES --- (1, 1, NULL, 1, NULL, 1.75000000, 60, 1, 500.00000000, 0.00000000, 7.00000000, '2022-03-09 14:15:48', 1); +-- INSERT INTO llx_asset_depreciation_options_fiscal (fk_asset, fk_asset_model, depreciation_type, accelerated_depreciation_option, degressive_coefficient, duration, duration_type, amount_base_depreciation_ht, amount_base_deductible_ht, total_amount_last_depreciation_ht, tms, fk_user_modif) VALUES +-- (1, NULL, 1, NULL, 1.75000000, 60, 1, 500.00000000, 0.00000000, 7.00000000, '2022-03-09 14:15:48', 1); CREATE TABLE llx_asset_depreciation_options_fiscal( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, From f24099a13f7dae519f71079849113eb48c96d32d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 17:25:16 +0200 Subject: [PATCH 108/421] Update llx_asset_model-asset.sql --- htdocs/install/mysql/tables/llx_asset_model-asset.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_asset_model-asset.sql b/htdocs/install/mysql/tables/llx_asset_model-asset.sql index 059bbb92ace..8c285515986 100644 --- a/htdocs/install/mysql/tables/llx_asset_model-asset.sql +++ b/htdocs/install/mysql/tables/llx_asset_model-asset.sql @@ -18,8 +18,8 @@ -- Table for fixed asset model -- -- Data example: --- INSERT INTO `llx_asset_model` (`rowid`, `entity`, `ref`, `label`, `asset_type`, `note_public`, `note_private`, `date_creation`, `tms`, `fk_user_creat`, `fk_user_modif`, `import_key`, `status`) VALUES --- (1, 1, 'LAPTOP', 'Laptop', 1, NULL, NULL, '2022-01-18 14:27:09', '2022-01-24 09:31:49', 1, 1, NULL, 1); +-- INSERT INTO llx_asset_model (entity, ref, label, asset_type, note_public, note_private, date_creation, tms, fk_user_creat, fk_user_modif, import_key, status) VALUES +-- (1, 'LAPTOP', 'Laptop', 1, NULL, NULL, '2022-01-18 14:27:09', '2022-01-24 09:31:49', 1, 1, NULL, 1); CREATE TABLE llx_asset_model( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, From e97f021380cdcab2100553bd6a09bc7fe9cd0729 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 19 Jun 2022 19:02:16 +0200 Subject: [PATCH 109/421] Fix #yogosha11295 --- htdocs/adherents/card.php | 9 ++- htdocs/admin/company.php | 10 +++ htdocs/admin/ihm.php | 5 ++ htdocs/comm/mailing/card.php | 5 ++ htdocs/contact/card.php | 9 ++- htdocs/contact/perso.php | 9 ++- htdocs/core/class/conf.class.php | 4 +- htdocs/core/class/html.form.class.php | 9 ++- htdocs/core/class/html.formfile.class.php | 61 ++--------------- htdocs/core/class/html.formmail.class.php | 5 ++ htdocs/core/class/html.formticket.class.php | 5 ++ htdocs/core/lib/security.lib.php | 67 +++++++++++++++++++ .../bom/doc/doc_generic_bom_odt.modules.php | 8 ++- .../doc/doc_generic_order_odt.modules.php | 8 ++- .../doc/doc_generic_contract_odt.modules.php | 8 ++- .../doc/doc_generic_shipment_odt.modules.php | 8 ++- .../doc/doc_generic_invoice_odt.modules.php | 8 ++- .../modules/mailings/xinputfile.modules.php | 5 ++ .../doc/doc_generic_member_odt.class.php | 8 ++- .../doc/doc_generic_product_odt.modules.php | 8 ++- .../doc/doc_generic_proposal_odt.modules.php | 8 ++- .../doc/doc_generic_reception_odt.modules.php | 8 ++- .../societe/doc/doc_generic_odt.modules.php | 8 ++- .../doc/doc_generic_stock_odt.modules.php | 8 ++- .../doc/doc_generic_ticket_odt.modules.php | 8 ++- .../user/doc/doc_generic_user_odt.modules.php | 8 ++- htdocs/core/tpl/ajax/fileupload_view.tpl.php | 7 ++ htdocs/imports/import.php | 8 ++- .../doc/doc_generic_myobject_odt.modules.php | 8 ++- htdocs/product/stock/massstockmove.php | 6 +- htdocs/societe/card.php | 9 ++- htdocs/website/index.php | 11 ++- 32 files changed, 275 insertions(+), 81 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index d7e46749de3..6fc4c45574a 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1280,7 +1280,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
    '.$langs->trans("Delete").'

    '.$langs->trans("PhotoFile").'
    '; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file + } + print ''; + print '
    '; } print ''; diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index 86800eea947..4f46a2a32b5 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -477,6 +477,11 @@ if (!empty($conf->barcode->enabled)) { // Logo print ''; print '
    '; +$maxfilesizearray = getMaxFileSizeArray(); +$maxmin = $maxfilesizearray['maxmin']; +if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file +} print ''; print '
    '; if (!empty($mysoc->logo_small)) { @@ -514,6 +519,11 @@ print ''; // Logo (squarred) print ''; print '
    '; +$maxfilesizearray = getMaxFileSizeArray(); +$maxmin = $maxfilesizearray['maxmin']; +if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file +} print ''; print '
    '; if (!empty($mysoc->logo_squarred_small)) { diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index d3afd4035e4..37d1757d783 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -636,6 +636,11 @@ if ($mode == 'login') { if (!empty($conf->global->ADD_UNSPLASH_LOGIN_BACKGROUND)) { $disabled = ' disabled="disabled"'; } + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file + } print ''; if ($disabled) { print '(' . $langs->trans("DisabledByOptionADD_UNSPLASH_LOGIN_BACKGROUND") . ') '; diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index b3d3dd25e90..166aa4292be 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -1249,6 +1249,11 @@ if ($action == 'create') { $out .= ''.$langs->trans("NoAttachedFiles").'
    '; } // Add link to add file + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $out .= ''; // MAX_FILE_SIZE must precede the field type=file + } $out .= ''; $out .= ' '; $out .= ''; diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 09d46d02b13..4762404af9c 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1271,7 +1271,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ' '.$langs->trans("Delete").'

    '; } //print ''.$langs->trans("PhotoFile").''; - print ''; + print ''; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file + } + print ''; + print ''; print ''; print ''; diff --git a/htdocs/contact/perso.php b/htdocs/contact/perso.php index e90f8b46bd0..230a8d148d3 100644 --- a/htdocs/contact/perso.php +++ b/htdocs/contact/perso.php @@ -159,7 +159,14 @@ if ($action == 'edit') { print ' '.$langs->trans("Delete").'

    '; } print ''.$langs->trans("PhotoFile").''; - print ''; + print ''; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file + } + print ''; + print ''; print ''; print ''; diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 602e6b560d0..0a996018e97 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -746,8 +746,8 @@ class Conf $this->global->PDF_ALLOW_HTML_FOR_FREE_TEXT = 1; // allow html content into free footer text } - // Default max file size for upload - $this->maxfilesize = (empty($this->global->MAIN_UPLOAD_DOC) ? 0 : (int) $this->global->MAIN_UPLOAD_DOC * 1024); + // Default max file size for upload (deprecated) + //$this->maxfilesize = (empty($this->global->MAIN_UPLOAD_DOC) ? 0 : (int) $this->global->MAIN_UPLOAD_DOC * 1024); // By default, we propagate contacts if (!isset($this->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN)) { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 56990effeb2..be43b35f895 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -9361,7 +9361,14 @@ class Form if ($object->photo) { $ret .= '

    '; } - $ret .= ''; + $ret .= ''; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $ret .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $ret .= ''; + $ret .= ''; $ret .= ''; } } else { diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 97f5eca5822..73a426323e3 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -148,64 +148,15 @@ class FormFile $out .= ''; - $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb - $maxphp = @ini_get('upload_max_filesize'); // In unknown - if (preg_match('/k$/i', $maxphp)) { - $maxphp = preg_replace('/k$/i', '', $maxphp); - $maxphp = $maxphp * 1; - } - if (preg_match('/m$/i', $maxphp)) { - $maxphp = preg_replace('/m$/i', '', $maxphp); - $maxphp = $maxphp * 1024; - } - if (preg_match('/g$/i', $maxphp)) { - $maxphp = preg_replace('/g$/i', '', $maxphp); - $maxphp = $maxphp * 1024 * 1024; - } - if (preg_match('/t$/i', $maxphp)) { - $maxphp = preg_replace('/t$/i', '', $maxphp); - $maxphp = $maxphp * 1024 * 1024 * 1024; - } - $maxphp2 = @ini_get('post_max_size'); // In unknown - if (preg_match('/k$/i', $maxphp2)) { - $maxphp2 = preg_replace('/k$/i', '', $maxphp2); - $maxphp2 = $maxphp2 * 1; - } - if (preg_match('/m$/i', $maxphp2)) { - $maxphp2 = preg_replace('/m$/i', '', $maxphp2); - $maxphp2 = $maxphp2 * 1024; - } - if (preg_match('/g$/i', $maxphp2)) { - $maxphp2 = preg_replace('/g$/i', '', $maxphp2); - $maxphp2 = $maxphp2 * 1024 * 1024; - } - if (preg_match('/t$/i', $maxphp2)) { - $maxphp2 = preg_replace('/t$/i', '', $maxphp2); - $maxphp2 = $maxphp2 * 1024 * 1024 * 1024; - } - // Now $max and $maxphp and $maxphp2 are in Kb - $maxmin = $max; - $maxphptoshow = $maxphptoshowparam = ''; - if ($maxphp > 0) { - $maxmin = min($max, $maxphp); - $maxphptoshow = $maxphp; - $maxphptoshowparam = 'upload_max_filesize'; - } - if ($maxphp2 > 0) { - $maxmin = min($max, $maxphp2); - if ($maxphp2 < $maxphp) { - $maxphptoshow = $maxphp2; - $maxphptoshowparam = 'post_max_size'; - } - } - + $maxfilesizearray = getMaxFileSizeArray(); + $max = $maxfilesizearray['max']; + $maxmin = $maxfilesizearray['maxmin']; + $maxphptoshow = $maxfilesizearray['maxphptoshow']; + $maxphptoshowparam = $maxfilesizearray['maxphptoshowparam']; if ($maxmin > 0) { - // MAX_FILE_SIZE doit précéder le champ input de type file - $out .= ''; + $out .= ''; // MAX_FILE_SIZE must precede the field type=file } - $out .= 'global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $conf->browser->layout != 'classic') ? ' name="userfile"' : ' name="userfile[]" multiple'); $out .= ((!empty($conf->global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $disablemulti) ? ' name="userfile"' : ' name="userfile[]" multiple'); $out .= (empty($conf->global->MAIN_UPLOAD_DOC) || empty($perm) ? ' disabled' : ''); $out .= (!empty($accept) ? ' accept="'.$accept.'"' : ' accept=""'); diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 27ef700cd09..a345f023161 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -829,6 +829,11 @@ class FormMail extends Form $out .= ''.$langs->trans("NoAttachedFiles").'
    '; } if ($this->withfile == 2) { + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $out .= ''; // MAX_FILE_SIZE must precede the field type=file + } // Can add other files if (!empty($conf->global->FROM_MAIL_USE_INPUT_FILE_MULTIPLE)) { $out .= ''; diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index f1c6e12e925..99a348b0374 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -491,6 +491,11 @@ class FormTicket $out .= $langs->trans("NoAttachedFiles").'
    '; } if ($this->withfile == 2) { // Can add other files + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $out .= ''; // MAX_FILE_SIZE must precede the field type=file + } $out .= ''; $out .= ' '; $out .= ''; diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 056d28ab2cd..1d3f013e9f3 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -977,3 +977,70 @@ function accessforbidden($message = '', $printheader = 1, $printfooter = 1, $sho } exit(0); } + + +/** + * Return the max allowed for file upload. + * Analyze among: upload_max_filesize, post_max_size, MAIN_UPLOAD_DOC + * + * @return array Array with all max size for file upload + */ +function getMaxFileSizeArray() +{ + global $conf; + + $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb + $maxphp = @ini_get('upload_max_filesize'); // In unknown + if (preg_match('/k$/i', $maxphp)) { + $maxphp = preg_replace('/k$/i', '', $maxphp); + $maxphp = $maxphp * 1; + } + if (preg_match('/m$/i', $maxphp)) { + $maxphp = preg_replace('/m$/i', '', $maxphp); + $maxphp = $maxphp * 1024; + } + if (preg_match('/g$/i', $maxphp)) { + $maxphp = preg_replace('/g$/i', '', $maxphp); + $maxphp = $maxphp * 1024 * 1024; + } + if (preg_match('/t$/i', $maxphp)) { + $maxphp = preg_replace('/t$/i', '', $maxphp); + $maxphp = $maxphp * 1024 * 1024 * 1024; + } + $maxphp2 = @ini_get('post_max_size'); // In unknown + if (preg_match('/k$/i', $maxphp2)) { + $maxphp2 = preg_replace('/k$/i', '', $maxphp2); + $maxphp2 = $maxphp2 * 1; + } + if (preg_match('/m$/i', $maxphp2)) { + $maxphp2 = preg_replace('/m$/i', '', $maxphp2); + $maxphp2 = $maxphp2 * 1024; + } + if (preg_match('/g$/i', $maxphp2)) { + $maxphp2 = preg_replace('/g$/i', '', $maxphp2); + $maxphp2 = $maxphp2 * 1024 * 1024; + } + if (preg_match('/t$/i', $maxphp2)) { + $maxphp2 = preg_replace('/t$/i', '', $maxphp2); + $maxphp2 = $maxphp2 * 1024 * 1024 * 1024; + } + // Now $max and $maxphp and $maxphp2 are in Kb + $maxmin = $max; + $maxphptoshow = $maxphptoshowparam = ''; + if ($maxphp > 0) { + $maxmin = min($maxmin, $maxphp); + $maxphptoshow = $maxphp; + $maxphptoshowparam = 'upload_max_filesize'; + } + if ($maxphp2 > 0) { + $maxmin = min($maxmin, $maxphp2); + if ($maxphp2 < $maxphp) { + $maxphptoshow = $maxphp2; + $maxphptoshowparam = 'post_max_size'; + } + } + //var_dump($maxphp.'-'.$maxphp2); + //var_dump($maxmin); + + return array('max'=>$max, 'maxmin'=>$maxmin, 'maxphptoshow'=>$maxphptoshow, 'maxphptoshowparam'=>$maxphptoshowparam); +} diff --git a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php index 23917c4b79c..92b51ce70f4 100644 --- a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php +++ b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php @@ -174,7 +174,13 @@ class doc_generic_bom_odt extends ModelePDFBom $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php index 94e0a634328..36e8b66d788 100644 --- a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php +++ b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php @@ -181,7 +181,13 @@ class doc_generic_order_odt extends ModelePDFCommandes $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index 23ed4bec34a..e36e4a281ad 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -166,7 +166,13 @@ class doc_generic_contract_odt extends ModelePDFContract } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php index 209acf648d6..47a54cc4f5c 100644 --- a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php +++ b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php @@ -180,7 +180,13 @@ class doc_generic_shipment_odt extends ModelePdfExpedition $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php index 07a1e3966a6..8d2be499fd2 100644 --- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php +++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php @@ -179,7 +179,13 @@ class doc_generic_invoice_odt extends ModelePDFFactures $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/mailings/xinputfile.modules.php b/htdocs/core/modules/mailings/xinputfile.modules.php index 9a80484f83b..ddff17ee4ad 100644 --- a/htdocs/core/modules/mailings/xinputfile.modules.php +++ b/htdocs/core/modules/mailings/xinputfile.modules.php @@ -110,6 +110,11 @@ class mailing_xinputfile extends MailingTargets global $langs; $s = ''; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $s .= ''; // MAX_FILE_SIZE must precede the field type=file + } $s .= ''; return $s; } diff --git a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php index fb084f312fe..f1bfe706b41 100644 --- a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php +++ b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php @@ -169,7 +169,13 @@ class doc_generic_member_odt extends ModelePDFMember $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php index 090a45f4b3f..f11dfbe6a2d 100644 --- a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php +++ b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php @@ -177,7 +177,13 @@ class doc_generic_product_odt extends ModelePDFProduct $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 39ffd92ac5e..06bf201f8f6 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -211,7 +211,13 @@ class doc_generic_proposal_odt extends ModelePDFPropales } } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php index 3e48aaf18bc..df015345671 100644 --- a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php +++ b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php @@ -173,7 +173,13 @@ class doc_generic_reception_odt extends ModelePdfReception $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php b/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php index 3a62eb22937..c4ef9135536 100644 --- a/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php +++ b/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php @@ -169,7 +169,13 @@ class doc_generic_odt extends ModeleThirdPartyDoc $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php index f8733a8a8ff..8f7a2bdcd15 100644 --- a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php +++ b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php @@ -177,7 +177,13 @@ class doc_generic_stock_odt extends ModelePDFStock $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php index d69da78aacc..3f0b0042f7f 100644 --- a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php +++ b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php @@ -166,7 +166,13 @@ class doc_generic_ticket_odt extends ModelePDFTicket $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $texte .= ' '; + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php index a46503b6e2a..176dab4c093 100644 --- a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php +++ b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php @@ -197,7 +197,13 @@ class doc_generic_user_odt extends ModelePDFUser $texte .= '
    '; } // Add input to upload a new template file. - $texte .= '
    '.$langs->trans("UploadNewTemplate").' '; + $texte .= '
    '.$langs->trans("UploadNewTemplate"); + $maxfilesizearray = getMaxFileSizeArray(); + $maxmin = $maxfilesizearray['maxmin']; + if ($maxmin > 0) { + $texte .= ''; // MAX_FILE_SIZE must precede the field type=file + } + $texte .= ' '; $texte .= ''; $texte .= ''; $texte .= '
    '; diff --git a/htdocs/core/tpl/ajax/fileupload_view.tpl.php b/htdocs/core/tpl/ajax/fileupload_view.tpl.php index 70182a17dbc..d4ba594ee89 100644 --- a/htdocs/core/tpl/ajax/fileupload_view.tpl.php +++ b/htdocs/core/tpl/ajax/fileupload_view.tpl.php @@ -37,6 +37,13 @@ if (empty($conf) || !is_object($conf)) { trans('AddFiles'); ?> + 0) { + print ''; // MAX_FILE_SIZE must precede the field type=file + } + ?>