diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index ef974d9e76329..1eae1b063b040 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,20 +1,21 @@
How to contribute to Dolibarr
=============================
-Send a Bug reports or a Feature request
+Submit a Bug report or a Feature request
---------------------------------------
-*Note*: **GitHub Issues is not a support forum.** If you have questions about Dolibarr / need help on using the software, please use [the forums](https://www.dolibarr.org/forum.php). Forums exist in different languages.
+*Note*: **GitHub Issues is not a support forum.**
+If you have questions about Dolibarr or need help on using the software, please use [the forums](https://www.dolibarr.org/forum.php). Forums exist in different languages.
-Issues to inform about a bug or a development trouble, like requests for a new feature, are managed on [GitHub](https://github.com/Dolibarr/dolibarr/issues).
-Default **language here is English**. So please prepare your contributions in English (we recommand using an online translation service if you don't know English).
+Issues to inform about a bug or a development trouble and requests for a new feature, are managed on [GitHub](https://github.com/Dolibarr/dolibarr/issues).
+Default **language here is English**. So please prepare your contributions in English (we recommend using an online translation service if you don't speak English).
-1. Please [use the search engine](https://help.github.com/articles/searching-issues) to check if nobody's already reported your problem.
+1. Please [use the search engine](https://help.github.com/articles/searching-issues) to check if anyone else has already reported your issue.
2. [Create an issue](https://help.github.com/articles/creating-an-issue). Choose an appropriate title. Prepend appropriately with Bug or Feature Request.
3. Tell us the version you are using! (look at /htdocs/admin/system/dolibarr.php? and check if you are using the latest version)
4. Write a report with as much detail as possible (Use [screenshots](https://help.github.com/articles/issue-attachments) or even screencasts and provide logging and debugging information whenever possible).
5. Delete unnecessary submissions.
-6. **Check your Message at Preview before sending.**
+6. **Check your Message at Preview before submitting.**
@@ -23,12 +24,12 @@ Default **language here is English**. So please prepare your contributions in En
Submit code
---------------------
-This process describes how a Developer can submit code to the project so it can be analysezd and validated by the Merger (we call this a Pull Request).
+This process describes how a Developer can submit code to the project so it can be analyzed and validated by the PR Maintainer (we call this a Pull Request).
Definition:
-- The Developer: is the human knowing the development language of the application that want to change some part of the code by making changement on the sources of the project.
-- The Merger: is the human knowing the development and check that the code submitted for approbation is correct to validate it, in other word, the Merger is the approbator of commits.
-- The Releaser: is the human that validates that there a freeze/beta version is ok to be released officialy as a stable version.
+- Developer: is the human knowing the development language of the application that wants to change some part of the code by modifying the sources of the project.
+- PR Maintainer: is the human knowing the development language and code who checks that the code submitted for approbation is correct to validate it, in other words, the PR Maintainer is the approbator of commits.
+- Release Maintainer: is the human that validates that a freeze/beta version is ok to be released officially as a stable version.
### Basic workflow
@@ -42,15 +43,16 @@ As the Developer:
5. Commit and push your changes.
6. [Make a pull request](https://help.github.com/articles/creating-a-pull-request).
-As the Merger:
+As the PR Maintainer:
-7. The Merger will check and say if he approves or not the commits. During this step, the Merger can modify your own code to make it valid for appobation or ask you to make the change yourself. For this the Merger may add commits himself. Depending on the tools used (can be done from github directly orfrom an IDE), such commits may be done directly after having validating your PR (for example to complete it).
+7. The PR Maintainer will check and decide if he approves or not the commits. During this step, the PR Maintainer can modify your own code to make it valid for approbation or ask you to make the change yourself. For this the PR Maintainer may add commits to a PR. Depending on the tools used (can be done from github directly or from an IDE), such commits may be done directly after validating your PR (for example to complete it).
-Note: Of course, the Merger, does not need to ask to himself if he is ok to validate a commit he did himself. This is a reason why the Merger can validate commits he did directly without passing by the approbation process described for the Developer.
+As the Release Maintainer:
-As the Releaser:
+8. A tag will be added to take a snapshot of the code with all the changes approved by PR Maintainers, when ready to do a release.
-8. A tag will be added to take a photo of the code will all the changes approved by the Merger, when he decide to do a release.
+
+Note: Project leader(Master Yoda and BDFL) retains all above roles and can directly commit to the project without a PR. Of course anyone can check commit history and comment!
@@ -59,21 +61,23 @@ As the Releaser:
Unless you're fixing a bug, all pull requests should be made against the *develop* branch.
-If you're fixing a bug, it is preferred that you cook your fix and pull request it against an oldest version affected.
+If you're fixing a bug, it is preferred that you make a pull request against the oldest version affected.
-We recommend to push it into N - 2 for N the latest version available, if not possible into version N - 1, and finally into develop.
-This is just a recommendation, currently, if you push a bug fix on a very old version, it is still merged and propagated into higher versions.
+We recommend to push it into N - 2 where N is the latest version available, if not possible into version N - 1, and finally into develop.
The rule N - 2 is just a tip if you don't know which version to choose to get the best compromise between ease of correction and number of potential beneficiaries of the correction.
+If you push a bug fix on a very old version it is still going to be merged and propagated into newer versions(choose wisely because old versions depend on old deprecated/unsupported versions of PHP and external libraries).
+
+
### General rules
- As the Developer, please don't edit the ChangeLog file. This file is generated from all commit messages during the release process by the Project releaser.
-- As the Developer: Do not submit changes into files xx_XX/afile.lang. They are language files and are updated automatically by sync from Transifex. If you need to add a new language file, just add it for the en_US language.
+- As the Developer: Do not submit changes into files xx_XX/afile.lang. They are language files and are updated/synced automatically from Transifex. If you need to add a new language file, just add it for the en_US language.
-- As the Releaser: The releaser will decide to make a new release as soon as the planning of the release is reached and the code in the branch to release reach the status "No more known serious bug known".
+- As the Release Maintainer: The Release Maintainer will decide to make a new release as soon as the planning of the release is reached and the code in the branch to release reach the status of "No more known serious bugs".
@@ -135,9 +139,9 @@ FIX|Fix #456 Short description (where #456 is number of bug fix, if it exists. I
or
CLOSE|Close #456 Short description (where #456 is number of feature request, if it exists. In upper case to appear into ChangeLog)
or
-NEW|New|QUAL|Qual|PERF|Perf Short description (In upper case to appear into ChangeLog, use this if you add a feature not tracked, otherwise use CLOSE #456)
+NEW|New|QUAL|Qual|PERF|Perf Short description (In upper case to appear into ChangeLog, use this if you add a feature not tracked, otherwise use CLOSE #xxx)
or
-Short description (when the commit is not introducing feature nor closing a bug)
+Short description (when the commit is not introducing a feature nor closing a bug)
Long description (Can span across multiple lines).
@@ -154,11 +158,11 @@ a process to follow to optimize the chance to have PRs merged efficiently...
* When submitting a pull request, use same rule as [Commits](#commits) for the message. If your pull request only contains 1 commit, GitHub will be smart enough to fill it for you. Otherwise, please be a bit verbose about what you're providing.
-* A screenshot will be always required for any PR of change/addition of a GUI behaviour.
+* A screenshot will be always required for any PR of change/addition of a GUI behavior.
Also, some code changes need a prior approbation:
-* if you want to include a new external library (into htdocs/includes directory), please ask before to the core project manager (mention @dolibarr-jedi in your issue) to see if such a library can be accepted.
+* if you want to include a new external library (into htdocs/includes directory), please contact the core project manager first (mention @dolibarr-jedi in your issue) to see if such a library can be accepted.
* if you add new tables or fields, you MUST first submit a standalone PR with the data structure changes you plan to add/modify (and only data structure changes). Start development only once this data structure has been accepted.
@@ -166,12 +170,12 @@ Once a PR has been submitted, you may need to wait for its integration. It is co
If the label of PR start with "Draft" or "WIP" (Work In Progress), it will not be analyzed for merging until you change the label of the PR (but it can be analyzed for discussion).
-If your PR has errors reported by the Continuous Integration Platform, it means your PR is not valid and nothing will be done with it. It will be kept open to allow developers to fix this, or it may be closed several month later. Don't expect anything on your PR if you have such errors, you MUST first fix the Continuous Integration error to have it taken into consideration.
+If your PR has errors reported by the Continuous Integration Platform, it means your PR is not valid and nothing will be done with it. It will be kept open to allow developers to fix this, or it may be closed several months later. Don't expect anything on your PR if you have such errors, you MUST first fix the Continuous Integration error to have it taken into consideration.
-If the PR is valid, and is kept open for a long time, a tag will also be added on the PR to describe the status of your PR and why the PR is kept open. By putting your mouse on the tag, you will get a full explanation of the tag/status that explain why your PR has not been integrated yet.
-In most cases, it gives you information of things you have to do to have the PR taken into consideration (for example a change is requested, a conflict is expected to be solved, some questions were asked). If you have a yellow, red flag of purple flag, don't expect to have your PR validated. You must first provide the answer the tag ask you. The majority of open PR are waiting an action of the author of the PR.
+If the PR is valid, and is kept open for a long time, a tag will also be added on the PR to describe the status of your PR and why the PR is kept open. By putting your mouse on the tag, you will get a full explanation of the tag/status that explains why your PR has not been integrated yet.
+In most cases, it gives you information of things you have to do to have the PR taken into consideration (for example a change is requested, a conflict is expected to be solved, some questions were asked). If you have a yellow, red flag of purple flag, don't expect to have your PR validated. You must first provide the answer the tag asks you. The majority of open PRs are waiting an action of the author of the PR.
-Statistics on Dolibarr project shows that 95% of submitted PR are reviewed and tagged. Average answer delay is also one of the best among Open source projects (just few days before having the Answer Tag set). This is one of the most important ratio of answered PR in Open Source world for a major project. Don't expect the core team to reach the 100%.
+Statistics on Dolibarr project shows that 95% of submitted PRs are reviewed and tagged. Average answer delay is also one of the best among Open source projects (just few days before having the Answer Tag set). This is one of the most important ratio of answered PRs in Open Source world for a major project. Don't expect the core team to reach 100%.
A so high ratio is very rare on a so popular project and with the increasing popularity of Dolibarr, this ratio will probably decrease in future to a more common level.
@@ -186,9 +190,9 @@ All other translations are managed online at [Transifex](https://www.transifex.c
Translations done on transifex are available in the next major release.
-Note: Sometimes, the source text (English) is modified. In such a case, the translation is reset. Transifex assume that if the original source
+Note: Sometimes, the source text (English) is modified. In such a case, the translation is reset. Transifex assumes that if the original source
has changed, the translation is surely no more correct so must be done again. But old translation is not lost and you can use the tab "History"
-to retrieve all old translation of a source text, and restore the translation in one click with no need to retranslate it if there is no need to.
+to retrieve all old translations of a source text and restore the translation in one click with no need to retranslate it if there is no need to.
### Resources
diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml
index 7f55003741613..9dbdf1b5ee4e8 100644
--- a/.github/workflows/windows-ci.yml
+++ b/.github/workflows/windows-ci.yml
@@ -61,19 +61,22 @@ jobs:
- name: Restore cache
id: cache
uses: actions/cache/restore@v4
+ env:
+ HASH: ${{ hashFiles('htdocs/install/**') }}
+ KEY_ROOT: ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}
with:
# See https://github.com/actions/cache/issues/1275#issuecomment-1925217178
enableCrossOsArchive: true
path: |
- db_init.sql
- db_init.sql.md5
- key: ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}-${{ env.CACHE_KEY_PART
- }}-${{ github.run_id }}
+ ./db_init.sql
+ ./db_init.sql.md5
+ key: ${{ env.KEY_ROOT }}-${{ env.HASH }}-${{ env.CACHE_KEY_PART }}-${{ github.run_id }}
restore-keys: |
- ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}-${{ env.CACHE_KEY_PART }}-
- ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}-${{ github.head_ref }}-
- ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}-${{ github.base_ref }}-
- ${{ matrix.os }}-${{ env.ckey }}-${{ matrix.php_version }}-
+ ${{ env.KEY_ROOT }}-${{ env.HASH }}-${{ env.CACHE_KEY_PART }}-
+ ${{ env.KEY_ROOT }}-${{ env.HASH }}-${{ github.head_ref }}-
+ ${{ env.KEY_ROOT }}-${{ env.HASH }}-${{ github.base_ref }}-
+ ${{ env.KEY_ROOT }}-${{ env.HASH }}-
+ ${{ env.KEY_ROOT }}-
- name: Create local php.ini with open_basedir restrictions
shell: cmd
@@ -183,4 +186,6 @@ jobs:
# See https://github.com/actions/cache/issues/1275#issuecomment-1925217178
enableCrossOsArchive: true
key: ${{ steps.cache.outputs.cache-primary-key }}
- path: db_init.*
+ path: |
+ ./db_init.sql
+ ./db_init.sql.md5
diff --git a/.gitignore b/.gitignore
index 2964b1ead0f0a..830429de679d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@ htdocs/includes/php-parallel-lint/
htdocs/includes/sebastian/
htdocs/includes/squizlabs/
htdocs/includes/webmozart/
+htdocs/install/install.forced.php
htdocs/.well-known/apple-developer-merchantid-domain-association
/factory/
/output/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 328005d7a4d9c..45eb0d85dc76c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,7 +3,7 @@ exclude: (?x)^( htdocs/includes/ckeditor/.*|(\.[^/]*/.*))$
repos:
# Several miscellaneous checks and fix (on yaml files, end of files fix)
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v4.6.0
hooks:
# This hook tests the name of the branch and return an error if the name is
# 'develop' or an official version 'x.y'
@@ -177,7 +177,7 @@ repos:
# Check format of yaml files
- repo: https://github.com/adrienverge/yamllint.git
- rev: v1.33.0
+ rev: v1.35.1
hooks:
- id: yamllint
args:
@@ -187,7 +187,7 @@ repos:
# Execute codespell to fix typo errors (setup of codespell into dev/tools/codespell/)
- repo: https://github.com/codespell-project/codespell
- rev: v2.2.6
+ rev: v2.3.0
hooks:
- id: codespell
# Due to a current limitation of configuration files,
@@ -230,14 +230,14 @@ repos:
# Check some shell scripts
- repo: https://github.com/shellcheck-py/shellcheck-py
- rev: v0.9.0.6
+ rev: v0.10.0.1
hooks:
- id: shellcheck
args: [-W, "100"]
# Check sql file syntax
- repo: https://github.com/sqlfluff/sqlfluff
- rev: 3.0.4
+ rev: 3.1.0
hooks:
- id: sqlfluff-lint
stages: [pre-commit, manual] # manual needed for ci
diff --git a/ChangeLog b/ChangeLog
index 5c321be8fb197..fbe7c1522bf2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -316,6 +316,77 @@ The following changes may create regressions for some external modules, but were
* The signature of method fetch() of class CompanyBankAccount has been modified to match the signature of method Account->fetch()
+***** ChangeLog for 19.0.3 compared to 19.0.2 *****
+FIX: #29403 HRM - Unable to delete a skill in a job Profile (#29779)
+FIX: #29439 incomplete API return (#29796)
+FIX: #29756 Sql error on comment search (#29761)
+FIX: #29780 Restore filtes when using "back to list"
+FIX: #30010 : Use conf TICKET_MESSAGE_MAIL_INTRO instead of translation key (#30081)
+FIX: #30274 : Add the include before executing dolibarr_set_const (#30320)
+FIX: #30467
+FIX: #30576 - Salary payment - Date of the payment is not displayed (#30592)
+FIX: Accountancy - Avoid space on FEC name file (#29716)
+FIX: Accountancy - Generate entries of expense report with localtax (#30411)
+FIX: ASSET: annual depreciation starting year (Again ;-)) #26084 (#30040)
+FIX: Backport page inventory.php from v18 to fix pagination bugs causing data loss (#29688)
+FIX: back to page on error in contact card (#29627)
+FIX: Bad calculation of $nbtotalofrecord (#30183)
+FIX: Bad count of total of supplie rinvoice into the list
+FIX: Better compatibility when objectdesc is not valid, and warnings
+FIX: broken pdf preview when multicompany sharing (#30188)
+FIX: compatibility with MULTICOMPANY_TRANSVERSE_MODE (#30599)
+FIX: Conflict with autoload (#30399)
+FIX: Display the real_PMP on inventory when its value is equal to 0 (#22291)
+FIX: Error mesg show untranslated extrafield name (#30227)
+FIX: executeHooks $object default value (#29647)
+FIX: expedition PDF models using units labels (#30358)
+FIX: Extrafield intshowzero in list (#29789)
+FIX: Extrafields always been delete and re insert for categories (#29781)
+FIX: extrafields on Organized events was broken
+FIX: fatal error on loading pictures in attached documents of an event (#30553)
+FIX: for country type (#29745)
+FIX: group by qty in product margin tab (#29853)
+FIX: init total amounts in margin module (#29854)
+FIX: issue to get the right files exported in Quadratrus export.php (#30004)
+FIX: lang output for sales representative on PDF (#30469)
+FIX: langs in common docgenerator (#29774)
+FIX: langs overwrite (#29630)
+FIX: lettering (auto) for invoice deposit with company discount (#29633)
+FIX: missing $object and $action for hook parameters (#30484)
+FIX: Missing $param in hook call for list
+FIX: Missing expense report picto in list (#29917)
+FIX: Missing expense report picto in menu (#29908)
+FIX: Missing the description in tooltip when option show in tooltip on
+FIX: mo cloning (#29686)
+FIX: modification date from label in accounting bookkeeping list (#30038)
+FIX: move porpale ref pdf cornas (#29989)
+FIX: Not qualified lines for reception (#29473)
+FIX: on change ref for bank account attachment are lost (#30529)
+FIX: orders to bill menu (#30179)
+FIX: Page expands when ticket messages are too long (#29785)
+FIX: parameter name (#29666)
+FIX: PHP8 warning if $conf->reception is checked the old fashion way (#29697)
+FIX: PHP 8 warning on output of successful cronjob (#29922)
+FIX: PHP exception on getSpecialCode (#29646)
+FIX: php warning if cookie doesn’t exist (#29723)
+FIX: pos: invoice date incorrectly set because of timezome mismatches (reverts #36e91da) (#30184)
+FIX: public project form return an error if SOCIETE_EMAIL_UNIQUE (#29942)
+FIX: REPLENISH MANY FOURN WHEN ORDER ALREADY CREATE (#29710)
+FIX: Supplier Order search on date valid (#30448)
+FIX: Ternary operator condition is always true/false (#29649)
+FIX: to avoid error during upgrade with pgsql (#30443)
+FIX: transfer in accountancy for expense reports.
+FIX: uninitialised var (#29728)
+FIX: - Unknown Character on HTML (#30257)
+FIX: Unsigned propal having signing date (#29825)
+FIX: Update asset.class.php
+FIX: update date_echeance of supplier invoices when we update invoice date in the past (#29886)
+FIX: User List - Function is show in wrong column when module HRM enabled (#30186)
+FIX: var name error and remove useless code (#30601)
+FIX: Warning: Undefined property: PropaleLigne::$situation_percent in /home/httpd/vhosts/aflac.fr/domains/dol190.aflac.fr/httpdocs/core/lib/pdf.lib.php on line 2442 (#30033)
+FIX: wrong value for duration unit (#30261)
+FIX: The ZAR currency must show the R before the amount
+
***** ChangeLog for 19.0.2 compared to 19.0.1 *****
FIX: $object->oldcopy may be a stdClass and not original object
FIX: 16.0 - parent company gets emptied when updating a third party from the card in edit mode (#28269)
@@ -1643,7 +1714,7 @@ NEW: Add link to create an element from the category page
NEW: add margin infos to takepos invoice lines
NEW: Add max size send for "backup and link to mail" option
NEW: Add method httponly_accessforbidden()
-NEW: Add more advices into the Setup security page
+NEW: Add more advice into the Setup security page
NEW: Add new global variable for keeping the previous signature information on proposal (case of reopening a proposal)
NEW: Add objectLink on shipment
NEW: Add option --force on CLI cron_run_jobs.php
@@ -3061,8 +3132,8 @@ NEW: add option in Workflow module to set a shipment as closed
for Admins
-NEW: Add a security center page with all information and advices related to the security of your instance
-NEW: Add a performance center page with all information and advices related to the performance of your instance
+NEW: Add a security center page with all information and advice related to the security of your instance
+NEW: Add a performance center page with all information and advice related to the performance of your instance
Modules
NEW: Module Recruitment is now stable
@@ -7080,7 +7151,7 @@ NEW: Add index and constraints keys on supplier proposal detail table
NEW: Add phpunit to check the engine is defined into sql create files.
NEW: Add project and Hook to Loan
NEW: Add REST API to push a file.
-NEW: Allow extrafields list select to be dependands on other standard list and not only other extrafields list
+NEW: Allow extrafields list select to be dependent on other standard list and not only other extrafields list
NEW: Architecture to manage search criteria persistence (using save_lastsearch_values=1 on exit links and restore_lastsearch_values=1 in entry links)
NEW: data files are now also parsed by phpunit for sql syntax
NEW: Hook to allow inserting custom product head #6001
@@ -8104,7 +8175,7 @@ NEW: The clicktodial module is now able to provide link "tel:" on phone numbers.
NEW: The conditional IF into ODT templates works also on not defined var so we can show data only if defined. Close #3819
NEW: The free text in PDF footers can now be a HTML content. So the WYSIWYG editor is on by default to edit it into module setup.
NEW: The thirdparties tabs, the contacts tabs and the members tabs are now presented using a new "top banner", saving space and using a same way to show address, status and navigation arrows.
-NEW: Thumbs for statistics on main page are fully clicable (not only link inside the thumb)
+NEW: Thumbs for statistics on main page are fully clickable (not only link inside the thumb)
NEW: Translate extrafield's labels.
NEW: Use new select2 component for juridical status, country and state selection.
NEW: When creating order, proposal or invoice from thirdparty card, the project is asked during creation. A link to create project if it does not exists is also available.
@@ -8703,7 +8774,7 @@ NEW: [ task #851 ] Add a new field: Commercial name
NEW: [ task #977 ] New option to manage product unit Migrated code from GPCSolutions/dolibarr:3.2-units branch and adapted for 3.8 with some improvements
NEW: The line where mouse is over can be highlight with option THEME_ELDY_USE_HOVER (on by default)
NEW: The notification module accept keyword __SUPERVISOR__ to send notification to supervisor of user.
-NEW: Thumbs for statistics on main page are fully clicable (not only link inside the thumb)
+NEW: Thumbs for statistics on main page are fully clickable (not only link inside the thumb)
NEW: Title of page project contains project ref and label
NEW: update skeleton and class builder
NEW: Use new select2 component for juridical status, country and state selection.
@@ -9854,7 +9925,7 @@ For users:
prices, radio).
- New: [ task #798 ] Add range limit date on product/services as it is done on order
and invoice.
-- New: [ task #814 ] Add extrafield feature for projects ands tasks.
+- New: [ task #814 ] Add extrafield feature for projects and tasks.
- New: [ task #770 ] Add ODT document generation for Projects module.
- New: [ task #741 ] Add intervention box.
- New: [ task #826 ] Optional increase stock when deleting an invoice already validated.
diff --git a/README.md b/README.md
index 0012573bd0868..b81d632a7283d 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![GitHub release](https://img.shields.io/github/v/release/Dolibarr/dolibarr)](https://github.com/Dolibarr/dolibarr)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5521/badge)](https://bestpractices.coreinfrastructure.org/projects/5521)
-Dolibarr ERP & CRM is a modern software package that helps manage your organization's activities (contacts, suppliers, invoices, orders, stocks, agenda…).
+Dolibarr ERP & CRM is a modern software package that helps manage your organization's activities (contacts, quotes, invoices, orders, stocks, agenda, human resources, ecm, manufacturing…).
It's an Open-Source Software suite (written in PHP with JavaScript enhancements) designed for small, medium or large companies, foundations and freelancers.
@@ -29,7 +29,9 @@ Other licenses apply for some included dependencies. See [COPYRIGHT](https://git
## INSTALLING
-### Simple setup
+There is a lot of different solutions to install Dolibarr.
+
+### Using packages
If you have low technical skills and you're looking to install Dolibarr ERP/CRM with just a few clicks, you can use one of the packaged versions:
@@ -39,7 +41,7 @@ If you have low technical skills and you're looking to install Dolibarr ERP/CRM
Releases can be downloaded from [official website](https://www.dolibarr.org/).
-### Recommended and generic setup
+### Using the generic step by step setup (recommended)
You can use any web server supporting PHP (Apache, Nginx, ...) and a supported database (MariaDB, MySQL or PostgreSQL) to install the standard version:
@@ -69,7 +71,11 @@ You can use any web server supporting PHP (Apache, Nginx, ...) and a supported d
- Follow the installer instructions;;;
-### SaaS/Cloud Setup
+### Using Docker images
+
+Dolibarr is also available as a [Docker image](https://hub.docker.com/r/dolibarr/dolibarr). Installation instructions are available [here](https://github.com/Dolibarr/dolibarr-docker).
+
+### Using ready to use SaaS/Cloud offers
If you lack the time to install it yourself, consider exploring commercial 'ready-to-use' Cloud offerings (refer to https://saas.dolibarr.org). Keep in mind that this third option comes with associated costs.
diff --git a/build/docker-dev/README.md b/build/docker-dev/README.md
index 6daf6d6bd5c13..66358bf2bbe47 100644
--- a/build/docker-dev/README.md
+++ b/build/docker-dev/README.md
@@ -2,7 +2,7 @@
The docker-compose.yml file is a sample of a config file to use to build and run Dolibarr in the current workspace with Docker.
This docker image is intended for development usage.
-For production usage you should consider other contributor reference like https://hub.docker.com/r/tuxgasy/dolibarr
+For production usage you should consider other contributor reference like https://hub.docker.com/r/dolibarr/dolibarr
Before build/run, define the variable HOST_USER_ID as following:
diff --git a/build/docker/README.md b/build/docker/README.md
index 03932387ee9d9..dc6147ef85533 100644
--- a/build/docker/README.md
+++ b/build/docker/README.md
@@ -1,7 +1,17 @@
# How to use it ?
+This directory is experimental. Scope of its used is not clear and not documented.
+If you are looking for a process to run Dolibarr as an official Docker image, you can find it on https://hub.docker.com/r/dolibarr/dolibarr
+
+
+# For experimental dev - TO REMOVE.
+
+But if you want to execute the version of Dolibarr that is into this current directory as a docker process, you can do it with this commands.
+
export HOST_USER_ID=$(id -u)
export HOST_GROUP_ID=$(id -g)
export MYSQL_ROOT_PWD=$(tr -dc A-Za-z0-9 accessType);
+ $url = 'https://accounts.google.com/o/oauth2/auth?'.($this->approvalPrompt?'approval_prompt='.$this->approvalPrompt.'&':'').'access_type='.$this->accessType;
+ return new Uri($url);
+ }
+
+
JS JSGANTT:
-----------
diff --git a/dev/resources/iso-normes/Accountancy-format_Ebp_txt.pdf b/dev/resources/iso-normes/accountancy/Accountancy-format_Ebp_txt.pdf
similarity index 100%
rename from dev/resources/iso-normes/Accountancy-format_Ebp_txt.pdf
rename to dev/resources/iso-normes/accountancy/Accountancy-format_Ebp_txt.pdf
diff --git a/dev/resources/iso-normes/Accountancy-format_Winfic-eWinfic-WinSisCompta.pdf b/dev/resources/iso-normes/accountancy/Accountancy-format_Winfic-eWinfic-WinSisCompta.pdf
similarity index 100%
rename from dev/resources/iso-normes/Accountancy-format_Winfic-eWinfic-WinSisCompta.pdf
rename to dev/resources/iso-normes/accountancy/Accountancy-format_Winfic-eWinfic-WinSisCompta.pdf
diff --git "a/dev/resources/iso-normes/format_FEC - Lien_outil_de_test_agr\303\251\303\251.pdf" "b/dev/resources/iso-normes/accountancy/format_FEC - Lien_outil_de_test_agr\303\251\303\251.pdf"
similarity index 100%
rename from "dev/resources/iso-normes/format_FEC - Lien_outil_de_test_agr\303\251\303\251.pdf"
rename to "dev/resources/iso-normes/accountancy/format_FEC - Lien_outil_de_test_agr\303\251\303\251.pdf"
diff --git a/dev/resources/iso-normes/format_FEC - fie example.txt b/dev/resources/iso-normes/accountancy/format_FEC - fie example.txt
similarity index 88%
rename from dev/resources/iso-normes/format_FEC - fie example.txt
rename to dev/resources/iso-normes/accountancy/format_FEC - fie example.txt
index 4285a9403a524..d7d3f1abecf51 100644
--- a/dev/resources/iso-normes/format_FEC - fie example.txt
+++ b/dev/resources/iso-normes/accountancy/format_FEC - fie example.txt
@@ -1,16 +1,16 @@
JOURNALCODE JOURNALLIB ECRITURENUM ECRITUREDATE COMPTENUM COMPTELIB COMPAUXNUM COMPAUXLIB PIECEREF PIECEDATE ECRITURELIB DEBIT CREDIT ECRITURELET DATELET VALIDDATE MONTANTDEVISE IDEVISE
-Banque Banque 17293 20170109 401PPRO PUBLI-PROV L08 20170109 PPRO domiciliation 1TR 187,20 0,00 20170109
-Banque Banque 17293 20170109 5121CRA CR AGRICOLE L08 20170109 PPRO domiciliation 1TR 0,00 187,20 20170109
-Banque Banque 17295 20170109 401ORPA ORANGE PARIS Report 20170109 ORPA adsl par 12 96,00 0,00 20170109
-Banque Banque 17295 20170109 5121CRA CR AGRICOLE Report 20170109 ORPA adsl par 12 0,00 96,00 20170109
-Banque Banque 17302 20170105 401ORVI ORANGE VEBRON INTERNET Report 20170105 ORVI adsl veb 12 26,00 0,00 20170109
-Banque Banque 17302 20170105 5121CRA CR AGRICOLE Report 20170105 ORVI adsl veb 12 0,00 26,00 20170109
-Fournisseurs Fournisseurs 17305 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170119
-Fournisseurs Fournisseurs 17305 20170119 622200 Courtages s/ ventes A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170119
-Banque Banque 17306 20170119 5121CRA CR AGRICOLE A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170119
-Banque Banque 17306 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170119
-Banque Banque 17307 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170131
-Banque Banque 17307 20170119 5121CRA CR AGRICOLE A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170131
+Banque Banque 17293 20170109 401PPRO PUBLI-PROV L08 20170109 PPRO domiciliation 1TR 187,20 0,00 20170109
+Banque Banque 17293 20170109 5121CRA CR AGRICOLE L08 20170109 PPRO domiciliation 1TR 0,00 187,20 20170109
+Banque Banque 17295 20170109 401ORPA ORANGE PARIS Report 20170109 ORPA adsl par 12 96,00 0,00 20170109
+Banque Banque 17295 20170109 5121CRA CR AGRICOLE Report 20170109 ORPA adsl par 12 0,00 96,00 20170109
+Banque Banque 17302 20170105 401ORVI ORANGE VEBRON INTERNET Report 20170105 ORVI adsl veb 12 26,00 0,00 20170109
+Banque Banque 17302 20170105 5121CRA CR AGRICOLE Report 20170105 ORVI adsl veb 12 0,00 26,00 20170109
+Fournisseurs Fournisseurs 17305 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170119
+Fournisseurs Fournisseurs 17305 20170119 622200 Courtages s/ ventes A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170119
+Banque Banque 17306 20170119 5121CRA CR AGRICOLE A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170119
+Banque Banque 17306 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170119
+Banque Banque 17307 20170119 401ZDAV SANDRA DAVILA A01 20170119 ZDAV courtage s/ ventes 508,00 0,00 20170131
+Banque Banque 17307 20170119 5121CRA CR AGRICOLE A01 20170119 ZDAV courtage s/ ventes 0,00 508,00 20170131
diff --git a/dev/resources/iso-normes/format_FEC.pdf b/dev/resources/iso-normes/accountancy/format_FEC.pdf
similarity index 100%
rename from dev/resources/iso-normes/format_FEC.pdf
rename to dev/resources/iso-normes/accountancy/format_FEC.pdf
diff --git a/dev/resources/iso-normes/accountancy/import-ofx-format.txt b/dev/resources/iso-normes/accountancy/import-ofx-format.txt
new file mode 100644
index 0000000000000..8ba29403a46a2
--- /dev/null
+++ b/dev/resources/iso-normes/accountancy/import-ofx-format.txt
@@ -0,0 +1,2 @@
+OFX is an old Financial format:
+See https://stackoverflow.com/questions/15735330/how-to-parse-a-ofx-version-1-0-2-file-in-php
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 a749aa293308f..d84486d27e90e 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
@@ -11,6 +11,7 @@ List of QR Code format we found on some invoices
------------------------------------------
https://en.wikipedia.org/wiki/EPC_QR_code#Generators
+Experimental support can be enabled in Dolibarr by setting INVOICE_ADD_EPC_QR_CODE = 1
* For ZATCA QR Code format (Saudi Arabia). Used when INVOICE_ADD_ZATCA_QR_CODE is set
@@ -19,10 +20,14 @@ 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
+Method to encode/decode ZATCA string is available in test/phpunit/BarcodeTest.php
-* FOR QR-Bill in switzerland - Facture-QR
-Syntax of QR Code - See file ig-qr-bill-v2.2-fr.pdf (more doc on https://www.swiss-qr-invoice.org/downloads/)
-Syntax of complentary field named "structured information of invoice S1": https://www.swiss-qr-invoice.org/downloads/qr-bill-s1-syntax-fr.pdf
+* FOR QR-Bill in switzerland - Facture-QR or QR-Facture
+-------------------------------------------------------
+- Syntax of QR Code - See file ig-qr-bill-v2.2-fr.pdf (more doc on https://www.swiss-qr-invoice.org/downloads/)
+- Syntax of complementary 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/
+
+Experimental support to show the QR code can be enabled in dolibarr by setting INVOICE_ADD_SWISS_QR_CODE = 1.
+If setting value to "bottom", the complete top banner can be added at bottom of invoice PDF. Note: an external PHP library may be requested at first PDF generation.
diff --git a/dev/resources/iso-normes/qr-bar-codes/ig-qr-bill-v2.2-fr.pdf b/dev/resources/iso-normes/qr-bar-codes/ig-qr-bill-v2.2-fr.pdf
index 92e071f99dbdd..f7fe64b79b557 100644
Binary files a/dev/resources/iso-normes/qr-bar-codes/ig-qr-bill-v2.2-fr.pdf and b/dev/resources/iso-normes/qr-bar-codes/ig-qr-bill-v2.2-fr.pdf differ
diff --git a/dev/resources/iso-normes/fichier_norme_AFB-CFONB.pdf b/dev/resources/iso-normes/transfer-bank-afb-confb/fichier_norme_AFB-CFONB.pdf
similarity index 100%
rename from dev/resources/iso-normes/fichier_norme_AFB-CFONB.pdf
rename to dev/resources/iso-normes/transfer-bank-afb-confb/fichier_norme_AFB-CFONB.pdf
diff --git a/dev/resources/iso-normes/sepa/pain.001.001.03.xsd b/dev/resources/iso-normes/transfer-bank-sepa/pain.001.001.03.xsd
similarity index 100%
rename from dev/resources/iso-normes/sepa/pain.001.001.03.xsd
rename to dev/resources/iso-normes/transfer-bank-sepa/pain.001.001.03.xsd
diff --git a/dev/resources/iso-normes/sepa/pain.008.001.02.xsd b/dev/resources/iso-normes/transfer-bank-sepa/pain.008.001.02.xsd
similarity index 100%
rename from dev/resources/iso-normes/sepa/pain.008.001.02.xsd
rename to dev/resources/iso-normes/transfer-bank-sepa/pain.008.001.02.xsd
diff --git a/dev/resources/iso-normes/sepa/sample-credit-transfer.xml b/dev/resources/iso-normes/transfer-bank-sepa/sample-credit-transfer.xml
similarity index 100%
rename from dev/resources/iso-normes/sepa/sample-credit-transfer.xml
rename to dev/resources/iso-normes/transfer-bank-sepa/sample-credit-transfer.xml
diff --git a/dev/resources/iso-normes/sepa/sample-direct-debit.xml b/dev/resources/iso-normes/transfer-bank-sepa/sample-direct-debit.xml
similarity index 100%
rename from dev/resources/iso-normes/sepa/sample-direct-debit.xml
rename to dev/resources/iso-normes/transfer-bank-sepa/sample-direct-debit.xml
diff --git a/dev/resources/iso-normes/sepa/text.txt b/dev/resources/iso-normes/transfer-bank-sepa/text.txt
similarity index 76%
rename from dev/resources/iso-normes/sepa/text.txt
rename to dev/resources/iso-normes/transfer-bank-sepa/text.txt
index dfa55834e580b..edf4820b42db4 100644
--- a/dev/resources/iso-normes/sepa/text.txt
+++ b/dev/resources/iso-normes/transfer-bank-sepa/text.txt
@@ -2,11 +2,11 @@ https://en.wikipedia.org/wiki/Single_Euro_Payments_Area
https://www.ecb.europa.eu/paym/integration/retail/sepa/html/index.en.html
https://www.europeanpaymentscouncil.eu/about-sepa
-Spec for credit transfer:
+Spec for credit transfer:
https://docs.oracle.com/cd/E39124_01/doc.91/e60210/fields_sepa_pay_file_appx.htm#EOAEL00515
To validate a SEPA file:
xmllint --schema pain.001.001.03.xsd T200801.xml --noout
-To test a SEPA file:
-https://www.mesfluxdepaiement.fr/testez-vos-fichiers-sepa
+To test a SEPA file:
+https://www.mesfluxdepaiement.fr/testez-vos-fichiers-sepa
diff --git a/dev/resources/iso-normes/xmlexport.txt b/dev/resources/iso-normes/xmlexport.txt
deleted file mode 100644
index 370c6a638f80d..0000000000000
--- a/dev/resources/iso-normes/xmlexport.txt
+++ /dev/null
@@ -1 +0,0 @@
-See specification at http://www.ofx.net
\ No newline at end of file
diff --git a/dev/setup/pre-commit/README.md b/dev/setup/pre-commit/README.md
index e610a55c4114f..9ebe65c8a58ae 100644
--- a/dev/setup/pre-commit/README.md
+++ b/dev/setup/pre-commit/README.md
@@ -94,4 +94,4 @@ CI also runs pre-commit to help maintain code quality.
Note:
Code for precommits are saved into:
-.cache/pre-commit/repoyXXXXX/py_env-python3/lib/pythonX.Y/site-packages/pre_commit_hooks/no_commit_to_branch.py
+.cache/pre-commit/repo*/py_env-python3/lib/python*/site-packages/pre_commit_hooks/no_commit_to_branch.py
diff --git a/dev/tools/apstats.php b/dev/tools/apstats.php
index 6f71492b32d79..bb768d9da1781 100755
--- a/dev/tools/apstats.php
+++ b/dev/tools/apstats.php
@@ -98,7 +98,7 @@
}
// PHPSTAN setup
-$PHPSTANLEVEL = 4;
+$PHPSTANLEVEL = 6;
// PHAN setup. Configuration is required, otherwise phan is disabled.
$PHAN_CONFIG = "{$path}phan/config_extended.php";
@@ -745,7 +745,7 @@
$html .= << Thumbs of most active contributors
-
+
END;
diff --git a/dev/tools/codespell/codespell-ignore.txt b/dev/tools/codespell/codespell-ignore.txt
index ddc0936a3abf4..e0450f0c643b0 100644
--- a/dev/tools/codespell/codespell-ignore.txt
+++ b/dev/tools/codespell/codespell-ignore.txt
@@ -1,5 +1,5 @@
# List of words codespell will ignore
-# one per line, case-sensitive (when not lowercase)
+# one per line, must be in lower case.
# PROVid
provid
@@ -7,11 +7,16 @@ provid
# PostgreSQL
postgresql
+# ZAR currency
+zar
+
# Name of contributores
noe
udo
tim
+ConfirmActionXxx
+
# Inside email
ba
blacklist
@@ -83,3 +88,4 @@ datee
# other
blacklists
+confirmactionxxx
diff --git a/dev/tools/codespell/codespell-lines-ignore.txt b/dev/tools/codespell/codespell-lines-ignore.txt
index c04c6d0446d19..e2acab0de5389 100644
--- a/dev/tools/codespell/codespell-lines-ignore.txt
+++ b/dev/tools/codespell/codespell-lines-ignore.txt
@@ -1,12 +1,6 @@
- || !empty($dates) && empty($datee) && $loanSchedule->datep >= $dates && $loanSchedule->datep <= dol_now()
- || empty($dates) && !empty($datee) && $loanSchedule->datep <= $datee
$objMod->dictionaries = $objMod->{"dictionnaries"}; // For backward compatibility
- if (($loanSchedule->datep >= $dates && $loanSchedule->datep <= $datee) // dates filter is defined
- $datee = $langs->trans("Unknown");
- $datee = dol_print_date($objectligne->date_end, 'day', false, $outputlangs, true);
- $txt .= $outputlangs->transnoentities("DateStartPlannedShort")." : ".$datei." - ".$outputlangs->transnoentities("DateEndPlanned")." : ".$datee.'';
if (empty($objMod->dictionaries) && !empty($objMod->{"dictionnaries"})) {
- print 'id.'&id_entrepot='.$entrepotstatic->id.'&action=transfert&pdluoid='.$pdluo->id.'">';
+ print 'id.'&id_entrepot='.$entrepotstatic->id.'&action=transfert&pdluoid='.$pdluo->id.'&token='.newToken().'">';
$object->date_ech = $object->periode;
$object->periode = $object->date_ech;
$reponsesadd = str_split($obj->reponses);
@@ -16,182 +10,97 @@
// $object->periode = dol_get_last_day(year of $object->date_ech - 1m, month or $object->date_ech -1m)
//$pice = '';
//$typea = ($objp->typea == 'birth') ? $picb : $pice;
- print '
';
@@ -389,6 +393,7 @@
require_once $dir.'/'.$file;
$module = new $classname($db);
+ '@phan-var-force doc_generic_member_odt|pdf_standard_member $module';
$modulequalified = 1;
if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php
index 2ccb20f51bb2d..c4937a8a8a877 100644
--- a/htdocs/adherents/admin/website.php
+++ b/htdocs/adherents/admin/website.php
@@ -1,9 +1,10 @@
- * Copyright (C) 2006-2015 Laurent Destailleur
- * Copyright (C) 2006-2012 Regis Houssin
- * Copyright (C) 2011 Juanjo Menent
- * Copyright (C) 2024 Alexandre Spangaro
+/* Copyright (C) 2001-2002 Rodolphe Quiedeville
+ * Copyright (C) 2006-2015 Laurent Destailleur
+ * Copyright (C) 2006-2012 Regis Houssin
+ * Copyright (C) 2011 Juanjo Menent
+ * Copyright (C) 2024 Alexandre Spangaro
+ * Copyright (C) 2024 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
@@ -75,8 +76,8 @@
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_AMOUNT", $amount, 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "MEMBER_MIN_AMOUNT", $minamount, 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "MEMBER_COUNTERS_ARE_PUBLIC", $publiccounters, 'chaine', 0, '', $conf->entity);
- $res = dolibarr_set_const($db, "MEMBER_SKIP_TABLE", !$showtable, 'chaine', 0, '', $conf->entity); // Logic is reversed for retrocompatibility: "skip -> show"
- $res = dolibarr_set_const($db, "MEMBER_HIDE_VOTE_ALLOWED", !$showvoteallowed, 'chaine', 0, '', $conf->entity); // Logic is reversed for retrocompatibility: "hide -> show"
+ $res = dolibarr_set_const($db, "MEMBER_SKIP_TABLE", (string) !$showtable, 'chaine', 0, '', $conf->entity); // Logic is reversed for retrocompatibility: "skip -> show"
+ $res = dolibarr_set_const($db, "MEMBER_HIDE_VOTE_ALLOWED", (string) !$showvoteallowed, 'chaine', 0, '', $conf->entity); // Logic is reversed for retrocompatibility: "hide -> show"
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_PAYONLINE", $payonline, 'chaine', 0, '', $conf->entity);
if ($forcetype < 0) {
$res = dolibarr_del_const($db, "MEMBER_NEWFORM_FORCETYPE", $conf->entity);
diff --git a/htdocs/adherents/canvas/actions_adherentcard_common.class.php b/htdocs/adherents/canvas/actions_adherentcard_common.class.php
index d4b06aa2b1fd5..58a9c4d7b2a5c 100644
--- a/htdocs/adherents/canvas/actions_adherentcard_common.class.php
+++ b/htdocs/adherents/canvas/actions_adherentcard_common.class.php
@@ -1,6 +1,7 @@
* Copyright (C) 2012 Philippe Grand
+ * Copyright (C) 2024 MDW
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,14 +33,29 @@ abstract class ActionsAdherentCardCommon
*/
public $db;
+ /**
+ * @var string
+ */
public $dirmodule;
+ /**
+ * @var string
+ */
public $targetmodule;
+ /**
+ * @var string
+ */
public $canvas;
+ /**
+ * @var string
+ */
public $card;
-
- //! Template container
+ /**
+ * @var array Template container
+ */
public $tpl = array();
- //! Object container
+ /**
+ * @var Object container
+ */
public $object;
/**
@@ -57,7 +73,7 @@ abstract class ActionsAdherentCardCommon
* Get object
*
* @param int $id Object id
- * @return object Object loaded
+ * @return Adherent Object loaded
*/
public function getObject($id)
{
diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php
index 451cd8cd81c1a..e9a5b94e0e9b4 100644
--- a/htdocs/adherents/card.php
+++ b/htdocs/adherents/card.php
@@ -471,7 +471,7 @@
$pass = GETPOST("password", 'password'); // For password, we use 'none'
$photo = GETPOST("photo", 'alphanohtml');
$morphy = GETPOST("morphy", 'alphanohtml');
- $public = GETPOST("public", 'alphanohtml');
+ $public = GETPOSTINT("public");
$userid = GETPOSTINT("userid");
$socid = GETPOSTINT("socid");
@@ -1419,7 +1419,7 @@ function initfieldrequired() {
print '
';
// Other attributes. Fields from hook formObjectOptions and Extrafields.
- include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
+ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php';
print '';
print dol_get_fiche_end();
@@ -2085,7 +2085,7 @@ function initfieldrequired() {
print '
';
- $MAX = 10;
+ $MAXEVENT = 10;
$morehtmlcenter = '';
$messagingUrl = DOL_URL_ROOT.'/adherents/messaging.php?rowid='.$object->id;
@@ -2095,7 +2095,7 @@ function initfieldrequired() {
// 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, $socid, 1, 'listactions', $MAX, '', $morehtmlcenter);
+ $somethingshown = $formactions->showactions($object, $object->element, $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
print '
';
}
diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php
index 7eb943244d427..9acc5a1fe7868 100644
--- a/htdocs/adherents/class/adherent.class.php
+++ b/htdocs/adherents/class/adherent.class.php
@@ -96,7 +96,7 @@ class Adherent extends CommonObject
/**
* @var string
- * @deprecated
+ * @deprecated Use $civility_code
* @see $civility_code
*/
public $civility_id;
@@ -106,11 +106,14 @@ class Adherent extends CommonObject
*/
public $civility_code;
+ /**
+ * @var int
+ */
public $civility;
/**
* @var string company name
- * @deprecated
+ * @deprecated Use $company
* @see $company
*/
public $societe;
@@ -122,7 +125,7 @@ class Adherent extends CommonObject
/**
* @var int Thirdparty ID
- * @deprecated
+ * @deprecated Use $socid
* @see $socid
*/
public $fk_soc;
@@ -133,7 +136,7 @@ class Adherent extends CommonObject
public $socid;
/**
- * @var array array of socialnetworks
+ * @var array array of socialnetworks
*/
public $socialnetworks;
@@ -202,6 +205,9 @@ class Adherent extends CommonObject
*/
public $datem;
+ /**
+ * @var string|int
+ */
public $datevalid;
/**
@@ -239,6 +245,9 @@ class Adherent extends CommonObject
*/
public $user_login;
+ /**
+ * @var string|int
+ */
public $datefin;
@@ -299,13 +308,13 @@ class Adherent extends CommonObject
public $partnerships = array();
/**
- * @var Facture|null To store the created invoice into subscriptionComplementaryActions()
+ * @var ?Facture To store the created invoice into subscriptionComplementaryActions()
*/
public $invoice;
/**
- * @var array|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
+ * @var array|string,position:int,notnull?:int,visible:int<-2,5>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,2>,disabled?:int<0,1>,arrayofkeyval?:array,comment?:string,validate?:int<0,1>}> 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, 'visible' => -1, 'notnull' => 1, 'position' => 10),
@@ -795,7 +804,7 @@ public function update($user, $notrigger = 0, $nosyncuser = 0, $nosyncuserpass =
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
$sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
$sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
- $sql .= ", public = '".$this->db->escape($this->public)."'";
+ $sql .= ", public = ".(int) $this->public;
$sql .= ", statut = ".(int) $this->statut;
$sql .= ", default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null");
$sql .= ", fk_adherent_type = ".(int) $this->typeid;
@@ -2291,7 +2300,7 @@ public function getTooltipContentArray($params)
}
/**
- * Return clicable name (with picto eventually)
+ * Return clickable name (with picto eventually)
*
* @param int $withpictoimg 0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small, -4=???)
* @param int $maxlen length max label
@@ -2679,6 +2688,7 @@ public function initAsSpecimen()
$this->photo = '';
$this->public = 1;
$this->statut = self::STATUS_DRAFT;
+ $this->status = self::STATUS_DRAFT;
$this->datefin = $now;
$this->datevalid = $now;
@@ -3044,7 +3054,7 @@ public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
}
$tmp = dol_getdate($now);
- $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), $daysbeforeend, 'd');
+ $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), (int) $daysbeforeend, 'd');
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
$sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
@@ -3251,11 +3261,11 @@ public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
}
/**
- * Return clicable link of object (with eventually picto)
+ * Return clickable link of object (with eventually picto)
*
- * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
- * @param array $arraydata Array of data
- * @return string HTML Code for Kanban thumb.
+ * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
+ * @param array{string,mixed} $arraydata Array of data
+ * @return string HTML Code for Kanban thumb.
*/
public function getKanbanView($option = '', $arraydata = null)
{
diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php
index 605c9b248e66d..497d4e4d8dcb4 100644
--- a/htdocs/adherents/class/adherent_type.class.php
+++ b/htdocs/adherents/class/adherent_type.class.php
@@ -6,6 +6,7 @@
* Copyright (C) 2018-2019 Thibault Foucart
* Copyright (C) 2021 Waël Almoman
* Copyright (C) 2024 Frédéric France
+ * Copyright (C) 2024 MDW
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -67,20 +68,23 @@ class AdherentType extends CommonObject
*/
public $morphy;
+ /**
+ * @var string
+ */
public $duration;
/**
- * type expiration
+ * @var int type expiration
*/
public $duration_value;
/**
- * Expiration unit
+ * @var string Expiration unit
*/
public $duration_unit;
/**
- * @var int Subscription required (0 or 1)
+ * @var int<0,1> Subscription required (0 or 1)
*/
public $subscription;
@@ -118,7 +122,7 @@ class AdherentType extends CommonObject
/** @var string Email sent after exclude */
public $mail_exclude = '';
- /** @var array Array of members */
+ /** @var Adherent[] Array of members */
public $members = array();
/**
@@ -501,7 +505,7 @@ public function fetch($rowid)
$this->morphy = $obj->morphy;
$this->status = $obj->status;
$this->duration = $obj->duration;
- $this->duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1);
+ $this->duration_value = (int) substr($obj->duration, 0, dol_strlen($obj->duration) - 1);
$this->duration_unit = substr($obj->duration, -1);
$this->subscription = $obj->subscription;
$this->amount = $obj->amount;
@@ -533,7 +537,7 @@ public function fetch($rowid)
* Return list of members' type
*
* @param int $status Filter on status of type
- * @return array List of types of members
+ * @return array List of types of members
*/
public function liste_array($status = -1)
{
@@ -572,7 +576,7 @@ public function liste_array($status = -1)
* Return the array of all amounts per membership type id
*
* @param int $status Filter on status of type
- * @return array Array of membership type
+ * @return array Array of membership type
*/
public function amountByType($status = null)
{
@@ -608,11 +612,11 @@ public function amountByType($status = null)
/**
* Return array of Member objects for member type this->id (or all if this->id not defined)
*
- * @param string $excludefilter Filter to exclude. This value must not come from a user input.
- * @param int $mode 0=Return array of member instance
+ * @param string $excludefilter Filter to exclude. This value must not come from a user input.
+ * @param int<0,2> $mode 0=Return array of member instance
* 1=Return array of member instance without extra data
* 2=Return array of members id only
- * @return mixed Array of members or -1 on error
+ * @return Adherent[]|int<-1,-1> Array of members or -1 on error
*/
public function listMembersForMemberType($excludefilter = '', $mode = 0)
{
@@ -699,9 +703,9 @@ public function getTooltipContentArray($params)
if (isset($this->duration)) {
$datas['duration'] = ' '.$langs->trans("Duration").': '.$this->duration_value;
if ($this->duration_value > 1) {
- $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years"));
+ $dur = array("i" => $langs->trans("Minutes"), "h" => $langs->trans("Hours"), "d" => $langs->trans("Days"), "w" => $langs->trans("Weeks"), "m" => $langs->trans("Months"), "y" => $langs->trans("Years"));
} elseif ($this->duration_value > 0) {
- $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year"));
+ $dur = array("i" => $langs->trans("Minute"), "h" => $langs->trans("Hour"), "d" => $langs->trans("Day"), "w" => $langs->trans("Week"), "m" => $langs->trans("Month"), "y" => $langs->trans("Year"));
}
$datas['duration'] .= " " . (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ? $langs->trans($dur[$this->duration_unit]) : '');
}
@@ -710,14 +714,14 @@ public function getTooltipContentArray($params)
}
/**
- * Return clicable name (with picto eventually)
+ * Return clickable name (with picto eventually)
*
- * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
- * @param int $maxlen length max label
- * @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
+ * @param int<0,2> $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
+ * @param int $maxlen length max label
+ * @param int<0,1> $notooltip 1=Disable tooltip
+ * @param string $morecss Add more css on link
+ * @param int<-1,1> $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+ * @return string String with URL
*/
public function getNomUrl($withpicto = 0, $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
{
@@ -772,8 +776,8 @@ public function getNomUrl($withpicto = 0, $maxlen = 0, $notooltip = 0, $morecss
/**
* Return label of status (activity, closed)
*
- * @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
+ * @param int<0,6> $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)
{
@@ -784,9 +788,9 @@ public function getLibStatut($mode = 0)
/**
* Return the label of a given status
*
- * @param int $status Status id
- * @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 Status label
+ * @param int $status Status id
+ * @param int<0,6> $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 Status label
*/
public function LibStatut($status, $mode = 0)
{
@@ -814,11 +818,11 @@ public function LibStatut($status, $mode = 0)
/**
* Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
*
- * @param array $info Info array loaded by _load_ldap_info
- * @param int $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
- * 1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
- * 2=Return key only (uid=qqq)
- * @return string DN
+ * @param array $info Info array loaded by _load_ldap_info
+ * @param int<0,2> $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
+ * 1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
+ * 2=Return key only (uid=qqq)
+ * @return string DN
*/
public function _load_ldap_dn($info, $mode = 0)
{
@@ -970,11 +974,11 @@ public function getMailOnExclude()
/**
- * Return clicable link of object (with eventually picto)
+ * Return clickable link of object (with eventually picto)
*
- * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
- * @param array $arraydata Array of data
- * @return string HTML Code for Kanban thumb.
+ * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
+ * @param array{string,mixed} $arraydata Array of data
+ * @return string HTML Code for Kanban thumb.
*/
public function getKanbanView($option = '', $arraydata = null)
{
diff --git a/htdocs/adherents/class/adherentstats.class.php b/htdocs/adherents/class/adherentstats.class.php
index 78c531785a77e..c515188aa2014 100644
--- a/htdocs/adherents/class/adherentstats.class.php
+++ b/htdocs/adherents/class/adherentstats.class.php
@@ -40,12 +40,30 @@ class AdherentStats extends Stats
*/
public $table_element;
+ /**
+ * @var int
+ */
public $memberid;
+ /**
+ * @var int
+ */
public $socid;
+ /**
+ * @var int
+ */
public $userid;
+ /**
+ * @var string
+ */
public $from;
+ /**
+ * @var string
+ */
public $field;
+ /**
+ * @var string
+ */
public $where;
diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php
index 2012f7c839d6e..5f56609fd0d68 100644
--- a/htdocs/adherents/class/subscription.class.php
+++ b/htdocs/adherents/class/subscription.class.php
@@ -98,7 +98,7 @@ class Subscription extends CommonObject
public $fk_bank;
/**
- * @var array|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
+ * @var array|string,position:int,notnull?:int,visible:int<-2,5>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,2>,disabled?:int<0,1>,arrayofkeyval?:array,comment?:string,validate?:int<0,1>}> 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, 'visible' => -1, 'notnull' => 1, 'position' => 10),
@@ -420,7 +420,7 @@ public function delete($user, $notrigger = 0)
/**
- * Return clicable name (with picto eventually)
+ * Return clickable name (with picto eventually)
*
* @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
* @param int $notooltip 1=Disable tooltip
@@ -536,10 +536,10 @@ public function info($id)
}
/**
- * Return clicable link of object (with eventually picto)
+ * Return clickable link of object (with eventually picto)
*
* @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
- * @param array $arraydata Array of data
+ * @param array{selected:?int,member:?Adherent,bank:?Account} $arraydata Array of data
* @return string HTML Code for Kanban thumb.
*/
public function getKanbanView($option = '', $arraydata = null)
diff --git a/htdocs/adherents/messaging.php b/htdocs/adherents/messaging.php
index 9222b072f5cfe..2ea8397391919 100644
--- a/htdocs/adherents/messaging.php
+++ b/htdocs/adherents/messaging.php
@@ -196,7 +196,7 @@
$cachekey = 'count_events_user_'.$object->id;
$nbEvent = dol_getcache($cachekey); // TODO Add nb into badge in menu so we can get it from cache also here
- $titlelist = $langs->trans("ActionsOnCompany").(is_numeric($nbEvent) ? '('.$nbEvent.')' : '');
+ $titlelist = $langs->trans("ActionsOnMember").(is_numeric($nbEvent) ? '('.$nbEvent.')' : '');
if (!empty($conf->dol_optimize_smallscreen)) {
$titlelist = $langs->trans("Actions").(is_numeric($nbEvent) ? '('.$nbEvent.')' : '');
}
diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php
index 1caa87e4a948c..1cf4c41a04daf 100644
--- a/htdocs/adherents/subscription.php
+++ b/htdocs/adherents/subscription.php
@@ -986,9 +986,9 @@
}
// Now do a correction of the suggested date
if (getDolGlobalString('MEMBER_SUBSCRIPTION_START_FIRST_DAY_OF') === "m") {
- $datefrom = dol_get_first_day(dol_print_date($datefrom, "%Y"), dol_print_date($datefrom, "%m"));
+ $datefrom = dol_get_first_day((int) dol_print_date($datefrom, "%Y"), (int) dol_print_date($datefrom, "%m"));
} elseif (getDolGlobalString('MEMBER_SUBSCRIPTION_START_FIRST_DAY_OF') === "Y") {
- $datefrom = dol_get_first_day(dol_print_date($datefrom, "%Y"));
+ $datefrom = dol_get_first_day((int) dol_print_date($datefrom, "%Y"));
}
}
print $form->selectDate($datefrom, '', 0, 0, 0, "subscription", 1, 1);
@@ -1000,9 +1000,9 @@
}
if (!$dateto) {
if (getDolGlobalInt('MEMBER_SUBSCRIPTION_SUGGEST_END_OF_MONTH')) {
- $dateto = dol_get_last_day(dol_print_date($datefrom, "%Y"), dol_print_date($datefrom, "%m"));
+ $dateto = dol_get_last_day((int) dol_print_date($datefrom, "%Y"), (int) dol_print_date($datefrom, "%m"));
} elseif (getDolGlobalInt('MEMBER_SUBSCRIPTION_SUGGEST_END_OF_YEAR')) {
- $dateto = dol_get_last_day(dol_print_date($datefrom, "%Y"));
+ $dateto = dol_get_last_day((int) dol_print_date($datefrom, "%Y"));
} else {
$dateto = -1; // By default, no date is suggested
}
diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php
index e01630fefd36f..17e8b2f75c37e 100644
--- a/htdocs/adherents/subscription/card.php
+++ b/htdocs/adherents/subscription/card.php
@@ -409,7 +409,7 @@
/*
include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
$formactions = new FormActions($db);
- $somethingshown = $formactions->showactions($object, $object->element, $socid, 1);
+ $somethingshown = $formactions->showactions($object, $object->element, $socid, 1, '', $MAXEVENT);
*/
print '';
diff --git a/htdocs/adherents/tpl/linkedobjectblock.tpl.php b/htdocs/adherents/tpl/linkedobjectblock.tpl.php
index 62a3a08aa49d8..21db449c9e9a4 100644
--- a/htdocs/adherents/tpl/linkedobjectblock.tpl.php
+++ b/htdocs/adherents/tpl/linkedobjectblock.tpl.php
@@ -29,7 +29,9 @@
global $user;
$langs = $GLOBALS['langs'];
+'@phan-var-force Translate $langs';
$linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
+'@phan-var-force Subscription[] $linkedObjectBlock';
$langs->load("members");
$total = 0;
diff --git a/htdocs/adherents/type_ldap.php b/htdocs/adherents/type_ldap.php
index e85d39c1d3602..e7bb1edb40d4a 100644
--- a/htdocs/adherents/type_ldap.php
+++ b/htdocs/adherents/type_ldap.php
@@ -36,15 +36,15 @@
$id = GETPOSTINT('rowid');
$action = GETPOST('action', 'aZ09');
+// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
+$hookmanager->initHooks(array('membertypeldapcard', 'globalcard'));
+
// Security check
$result = restrictedArea($user, 'adherent', $id, 'adherent_type');
$object = new AdherentType($db);
$object->fetch($id);
-// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
-$hookmanager->initHooks(array('membertypeldapcard', 'globalcard'));
-
/*
* Actions
*/
diff --git a/htdocs/admin/agenda_extsites.php b/htdocs/admin/agenda_extsites.php
index 12c91161e9281..99ae2a7d68ad4 100644
--- a/htdocs/admin/agenda_extsites.php
+++ b/htdocs/admin/agenda_extsites.php
@@ -53,6 +53,8 @@
// List of available colors
$colorlist = array('BECEDD', 'DDBECE', 'BFDDBE', 'F598B4', 'F68654', 'CBF654', 'A4A4A5');
+$reg = array();
+
/*
* Actions
diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php
index 994537b515d02..4585a6be6fdab 100644
--- a/htdocs/admin/agenda_other.php
+++ b/htdocs/admin/agenda_other.php
@@ -256,6 +256,8 @@
require_once $dir.'/'.$file;
$module = new $classname($db, new ActionComm($db));
+ '@phan-var-force ModeleAction $module';
+
print '
\n";
}
}
@@ -401,7 +436,7 @@ public function get_next_url()
{
// phpcs:enable
$param_array = array();
- if (count($this->products) < $this->per_page) {
+ if ($this->products !== null && count($this->products) < $this->per_page) {
$add = 0;
} else {
$add = $this->per_page;
diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php
index 02bc1f00c8112..925a0eb4d75f9 100644
--- a/htdocs/admin/emailcollector_card.php
+++ b/htdocs/admin/emailcollector_card.php
@@ -439,15 +439,16 @@
$credentials = new Credentials(
getDolGlobalString('OAUTH_'.$object->oauth_service.'_ID'),
getDolGlobalString('OAUTH_'.$object->oauth_service.'_SECRET'),
- getDolGlobalString('OAUTH_'.$object->oauth_service.'_URLAUTHORIZE')
+ getDolGlobalString('OAUTH_'.$object->oauth_service.'_URLCALLBACK')
);
$serviceFactory = new \OAuth\ServiceFactory();
$oauthname = explode('-', $OAUTH_SERVICENAME);
// ex service is Google-Emails we need only the first part Google
$apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array());
+ '@phan-var-force OAuth\OAuth2\Service\AbstractService|OAuth\OAuth1\Service\AbstractService $apiService'; // createService is only ServiceInterface
- // We have to save the token because Google give it only once
+ // We need to save the token because Google provides it only once
$refreshtoken = $tokenobj->getRefreshToken();
//var_dump($tokenobj);
@@ -457,6 +458,7 @@
throw new Exception("Failed to refresh access token: ".$e->getMessage());
}
+ // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
$tokenobj->setRefreshToken($refreshtoken);
$storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);
}
diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php
index 71e457920742e..940c016b07fd8 100644
--- a/htdocs/admin/expedition.php
+++ b/htdocs/admin/expedition.php
@@ -203,6 +203,7 @@
require_once $dir.$file.'.php';
$module = new $file();
+ '@phan-var-force ModelNumRefExpedition $module';
if ($module->isEnabled()) {
// Show modules according to features level
@@ -340,6 +341,8 @@
require_once $dir.'/'.$file;
$module = new $classname($db);
+ '@phan-var-force ModelePdfExpedition $module';
+
$modulequalified = 1;
if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
$modulequalified = 0;
@@ -353,7 +356,7 @@
print(empty($module->name) ? $name : $module->name);
print "
\n";
if (method_exists($module, 'info')) {
- print $module->info($langs);
+ print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod
} else {
print $module->description;
}
diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php
index 6eee65a50a804..c8b57520e24f0 100644
--- a/htdocs/admin/expensereport.php
+++ b/htdocs/admin/expensereport.php
@@ -228,6 +228,8 @@
$module = new $file($db);
+ '@phan-var-force ModeleNumRefExpenseReport $module';
+
// Show modules according to features level
if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
continue;
@@ -237,7 +239,7 @@
}
if ($module->isEnabled()) {
- print '
\n";
if (method_exists($module, 'info')) {
- print $module->info($langs);
+ print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod
} else {
print $module->description;
}
diff --git a/htdocs/admin/expensereport_rules.php b/htdocs/admin/expensereport_rules.php
index 4e4ef01d9f042..8440bee8e74d0 100644
--- a/htdocs/admin/expensereport_rules.php
+++ b/htdocs/admin/expensereport_rules.php
@@ -3,6 +3,7 @@
* Copyright (C) 2017 ATM Consulting
* Copyright (C) 2017 Pierre-Henry Favre
* Copyright (C) 2018-2019 Frédéric France
+ * Copyright (C) 2024 MDW
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -355,7 +356,7 @@
echo '
\n";
}
diff --git a/htdocs/asset/tpl/linkedobjectblock.tpl.php b/htdocs/asset/tpl/linkedobjectblock.tpl.php
index 0e8d62a692185..bb6034c6f70b6 100644
--- a/htdocs/asset/tpl/linkedobjectblock.tpl.php
+++ b/htdocs/asset/tpl/linkedobjectblock.tpl.php
@@ -2,6 +2,7 @@
/* Copyright (C) 2010-2011 Regis Houssin
* Copyright (C) 2013 Juanjo Menent
* Copyright (C) 2014 Marcos García
+ * Copyright (C) 2024 MDW
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +30,9 @@
global $noMoreLinkedObjectBlockAfter;
$langs = $GLOBALS['langs'];
+'@phan-var-force Translate $langs';
$linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
+'@phan-var-force CommonObject[] $linkedObjectBlock';
// Load translation files required by the page
$langs->load("assets");
@@ -56,7 +59,7 @@
echo '
';
// Status
diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php
index bc0e4a3bec464..6bb7aacb13135 100644
--- a/htdocs/blockedlog/class/blockedlog.class.php
+++ b/htdocs/blockedlog/class/blockedlog.class.php
@@ -65,6 +65,9 @@ class BlockedLog
*/
public $signature_line = '';
+ /**
+ * @var float|string|null
+ */
public $amounts = null;
/**
@@ -98,22 +101,38 @@ class BlockedLog
public $fk_user = 0;
/**
- * @var integer|string date_creation
+ * @var int|string date_creation
*/
public $date_creation;
/**
- * @var integer|string $date_modification;
+ * @var int|string $date_modification;
*/
public $date_modification;
+ /**
+ * @var int
+ */
public $date_object = 0;
+ /**
+ * @var string
+ */
public $ref_object = '';
+ /**
+ * @var ?stdClass
+ */
public $object_data = null;
+
+ /**
+ * @var string
+ */
public $object_version = '';
+ /**
+ * @var string
+ */
public $user_fullname = '';
/**
@@ -138,7 +157,7 @@ public function __construct(DoliDB $db)
/**
* Load list of tracked events into $this->trackedevents.
*
- * @return int Always 1
+ * @return int<1,1> Always 1
*/
public function loadTrackedEvents()
{
@@ -237,7 +256,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
}
if ($this->element === 'invoice_supplier') {
@@ -247,7 +266,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'payment') {
require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
@@ -256,7 +275,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'payment_supplier') {
require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
@@ -265,7 +284,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'payment_donation') {
require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php';
@@ -274,7 +293,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'payment_various') {
require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
@@ -283,7 +302,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'don' || $this->element === 'donation') {
require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
@@ -292,7 +311,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'subscription') {
require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
@@ -301,7 +320,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'cashcontrol') {
require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
@@ -310,7 +329,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'stockmouvement') {
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
@@ -319,7 +338,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->element === 'project') {
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
@@ -328,7 +347,7 @@ public function getObjectLink()
if ($object->fetch($this->fk_object) > 0) {
return $object->getNomUrl(1);
} else {
- $this->error++;
+ $this->error = (string) (((int) $this->error) + 1);
}
} elseif ($this->action == 'MODULE_SET') {
return ''.$langs->trans("BlockedLogEnabled").'';
@@ -344,7 +363,8 @@ public function getObjectLink()
}
/**
- * try to retrieve user author
+ * Try to retrieve user author
+ *
* @return string
*/
public function getUser()
@@ -374,9 +394,9 @@ public function getUser()
*
* @param CommonObject $object object to store
* @param string $action action
- * @param string $amounts amounts
+ * @param float|int $amounts amounts
* @param ?User $fuser User object (forced)
- * @return int >0 if OK, <0 if KO
+ * @return int<-1,-1>|int<1,1> >0 if OK, <0 if KO
*/
public function setObjectData(&$object, $action, $amounts, $fuser = null)
{
@@ -394,21 +414,26 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
$this->amounts = $amounts;
// date
if ($object->element == 'payment' || $object->element == 'payment_supplier') {
+ '@phan-var-force Paiement|PaiementFourn $object';
$this->date_object = empty($object->datepaye) ? $object->date : $object->datepaye;
} elseif ($object->element == 'payment_salary') {
+ '@phan-var-force PaymentSalary $object';
$this->date_object = $object->datev;
} elseif ($object->element == 'payment_donation' || $object->element == 'payment_various') {
+ '@phan-var-force PaymentDonation $object';
$this->date_object = empty($object->datepaid) ? $object->datep : $object->datepaid;
} elseif ($object->element == 'subscription') {
+ '@phan-var-force Subscription $object';
$this->date_object = $object->dateh;
} elseif ($object->element == 'cashcontrol') {
+ '@phan-var-force CashControl $object';
$this->date_object = $object->date_creation;
} elseif (property_exists($object, 'date')) {
// Generic case
- $this->date_object = $object->date;
+ $this->date_object = $object->date; // @phan-suppress-current-line PhanUndeclaredProperty
} elseif (property_exists($object, 'datem')) {
// Generic case (second chance, for example for stock movement)
- $this->date_object = $object->datem;
+ $this->date_object = $object->datem; // @phan-suppress-current-line PhanUndeclaredProperty
}
// ref
@@ -498,6 +523,7 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
// Field specific to object
if ($this->element == 'facture') {
+ '@phan-var-force Facture $object';
foreach ($object as $key => $value) {
if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties
@@ -536,6 +562,7 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
$this->object_data->ref = $object->newref;
}
} elseif ($this->element == 'invoice_supplier') {
+ '@phan-var-force FactureFournisseur $object';
foreach ($object as $key => $value) {
if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties
@@ -554,6 +581,7 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
$this->object_data->ref = $object->newref;
}
} elseif ($this->element == 'payment' || $this->element == 'payment_supplier' || $this->element == 'payment_donation' || $this->element == 'payment_various') {
+ '@phan-var-force Paiement|PaiementFourn|PaymentDonation|PaymentVarious $object';
$datepayment = $object->datepaye ? $object->datepaye : ($object->datepaid ? $object->datepaid : $object->datep);
$paymenttypeid = $object->paiementid ? $object->paiementid : ($object->paymenttype ? $object->paymenttype : $object->type_payment);
@@ -685,12 +713,14 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
$this->object_data->ref = $object->newref;
}
} elseif ($this->element == 'payment_salary') {
+ '@phan-var-force PaymentSalary $object';
$this->object_data->amounts = array($object->amount);
if (!empty($object->newref)) {
$this->object_data->ref = $object->newref;
}
} elseif ($this->element == 'subscription') {
+ '@phan-var-force Subscription $object';
foreach ($object as $key => $value) {
if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties
@@ -709,6 +739,7 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
$this->object_data->ref = $object->newref;
}
} elseif ($this->element == 'stockmouvement') {
+ '@phan-var-force StockTransfer $object';
foreach ($object as $key => $value) {
if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties
@@ -744,7 +775,7 @@ public function setObjectData(&$object, $action, $amounts, $fuser = null)
* Get object from database
*
* @param int $id Id of object to load
- * @return int >0 if OK, <0 if KO, 0 if not found
+ * @return int<-1,1> >0 if OK, <0 if KO, 0 if not found
*/
public function fetch($id)
{
@@ -806,9 +837,9 @@ public function fetch($id)
/**
* Encode data
*
- * @param string $data Data to serialize
- * @param int $mode 0=serialize, 1=json_encode
- * @return string Value serialized, an object (stdClass)
+ * @param ?stdClass $data Data to serialize
+ * @param int<0,1> $mode 0=serialize, 1=json_encode
+ * @return string Value serialized, an object (stdClass)
*/
public function dolEncodeBlockedData($data, $mode = 0)
{
@@ -828,7 +859,7 @@ public function dolEncodeBlockedData($data, $mode = 0)
*
* @param string $data Data to unserialize
* @param int $mode 0=unserialize, 1=json_decode
- * @return object Value unserialized, an object (stdClass)
+ * @return Object Value unserialized, an object (stdClass)
*/
public function dolDecodeBlockedData($data, $mode = 0)
{
@@ -862,8 +893,8 @@ public function setCertified()
* Create blocked log in database.
*
* @param User $user Object user that create
- * @param string $forcesignature Force signature (for example '0000000000' when we disabled the module)
- * @return int Return integer <0 if KO, >0 if OK
+ * @param string $forcesignature Force signature (for example '0000000000' when we disabled the module)
+ * @return int<-3,-1>|int<1,1> Return integer <0 if KO, >0 if OK
*/
public function create($user, $forcesignature = '')
{
@@ -902,7 +933,7 @@ public function create($user, $forcesignature = '')
$this->date_creation = dol_now();
- $this->object_version = ((float) DOL_VERSION);
+ $this->object_version = DOL_VERSION;
$this->db->begin();
@@ -989,8 +1020,8 @@ public function create($user, $forcesignature = '')
* Check if current signature still correct compared to the value in chain
*
* @param string $previoushash If previous signature hash is known, we can provide it to avoid to make a search of it in database.
- * @param int $returnarray 1=Return array of details, 2=Return array of details including keyforsignature, 0=Boolean
- * @return boolean|array True if OK, False if KO
+ * @param int<0,2> $returnarray 1=Return array of details, 2=Return array of details including keyforsignature, 0=Boolean
+ * @return boolean|array{checkresult:bool,calculatedsignature:string,previoushash:string,keyforsignature?:string} True if OK, False if KO
*/
public function checkSignature($previoushash = '', $returnarray = 0)
{
@@ -1044,9 +1075,9 @@ private function buildKeyForSignature()
/**
* Get previous signature/hash in chain
*
- * @param int $withlock 1=With a lock
- * @param int $beforeid ID of a record
- * @return string Hash of previous record (if beforeid is defined) or hash of last record (if beforeid is 0)
+ * @param int<0,1> $withlock 1=With a lock
+ * @param int $beforeid ID of a record
+ * @return string Hash of previous record (if beforeid is defined) or hash of last record (if beforeid is 0)
*/
public function getPreviousHash($withlock = 0, $beforeid = 0)
{
@@ -1084,18 +1115,18 @@ public function getPreviousHash($withlock = 0, $beforeid = 0)
/**
* Return array of log objects (with criteria)
*
- * @param string $element element to search
- * @param int $fk_object id of object to search
- * @param int $limit max number of element, 0 for all
- * @param string $sortfield sort field
- * @param string $sortorder sort order
- * @param int $search_fk_user id of user(s)
- * @param int $search_start start time limit
- * @param int $search_end end time limit
- * @param string $search_ref search ref
- * @param string $search_amount search amount
- * @param string $search_code search code
- * @return BlockedLog[]|int<-2,-1> Array of object log or <0 if error
+ * @param string $element element to search
+ * @param int $fk_object id of object to search
+ * @param int<0,max> $limit max number of element, 0 for all
+ * @param string $sortfield sort field
+ * @param string $sortorder sort order
+ * @param int $search_fk_user id of user(s)
+ * @param int $search_start start time limit
+ * @param int $search_end end time limit
+ * @param string $search_ref search ref
+ * @param string $search_amount search amount
+ * @param string $search_code search code
+ * @return BlockedLog[]|int<-2,-1> Array of object log or <0 if error
*/
public function getLog($element, $fk_object, $limit = 0, $sortfield = '', $sortorder = '', $search_fk_user = -1, $search_start = -1, $search_end = -1, $search_ref = '', $search_amount = '', $search_code = '')
{
@@ -1202,7 +1233,7 @@ public function getSignature()
/**
* Check if module was already used or not for at least one recording.
*
- * @param int $ignoresystem Ignore system events for the test
+ * @param int<0,1> $ignoresystem Ignore system events for the test
* @return bool
*/
public function alreadyUsed($ignoresystem = 0)
diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php
index b7eaba7420955..0450717e0bd20 100644
--- a/htdocs/bom/class/bom.class.php
+++ b/htdocs/bom/class/bom.class.php
@@ -101,7 +101,7 @@ class BOM extends CommonObject
// BEGIN MODULEBUILDER PROPERTIES
/**
- * @var array|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
+ * @var array|string,position:int,notnull?:int,visible:int<-2,5>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,2>,disabled?:int<0,1>,arrayofkeyval?:array,comment?:string,validate?:int<0,1>}> 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, 'visible' => -2, 'position' => 1, 'notnull' => 1, 'index' => 1, 'comment' => "Id",),
@@ -155,7 +155,7 @@ class BOM extends CommonObject
public $description;
/**
- * @var integer|string date_valid
+ * @var int|string date_valid
*/
public $date_valid;
@@ -193,8 +193,17 @@ class BOM extends CommonObject
* @var int product Id
*/
public $fk_product;
+ /**
+ * @var float
+ */
public $qty;
+ /**
+ * @var float
+ */
public $duration;
+ /**
+ * @var float
+ */
public $efficiency;
// END MODULEBUILDER PROPERTIES
@@ -301,7 +310,7 @@ public function create(User $user, $notrigger = 1)
*
* @param User $user User that creates
* @param int $fromid Id of object to clone
- * @return mixed New object created, <0 if KO
+ * @return BOM|int<-1,-1> New object created, <0 if KO
*/
public function createFromClone(User $user, $fromid)
{
@@ -330,7 +339,8 @@ public function createFromClone(User $user, $fromid)
unset($object->import_key);
// Clear fields
- $object->ref = empty($this->fields['ref']['default']) ? $langs->trans("copy_of_").$object->ref : $this->fields['ref']['default'];
+ $default_ref = $this->fields['ref']['default'] ?? null;
+ $object->ref = empty($default_ref) ? $langs->trans("copy_of_").$object->ref : $default_ref;
$object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
$object->status = self::STATUS_DRAFT;
// ...
@@ -364,6 +374,7 @@ public function createFromClone(User $user, $fromid)
if (!$error) {
// copy external contacts if same company
+ // @phan-suppress-next-line PhanUndeclaredProperty
if (property_exists($this, 'socid') && $this->socid == $object->socid) {
if ($this->copy_linked_contact($object, 'external') < 0) {
$error++;
@@ -390,9 +401,9 @@ public function createFromClone(User $user, $fromid)
/**
* Load object in memory from the database
*
- * @param int $id Id object
- * @param string $ref Ref
- * @return int Return integer <0 if KO, 0 if not found, >0 if OK
+ * @param int $id Id object
+ * @param string $ref Ref
+ * @return int<-1,1> Return integer <0 if KO, 0 if not found, >0 if OK
*/
public function fetch($id, $ref = null)
{
@@ -422,9 +433,9 @@ public function fetchLines()
/**
* Load object lines in memory from the database by type of product
*
- * @param int $typeproduct 0 type product, 1 type service
+ * @param int<0,1> $typeproduct 0 type product, 1 type service
- * @return int Return integer <0 if KO, 0 if not found, >0 if OK
+ * @return int<-1,1> Return integer <0 if KO, 0 if not found, >0 if OK
*/
public function fetchLinesbytypeproduct($typeproduct = 0)
{
@@ -438,6 +449,8 @@ public function fetchLinesbytypeproduct($typeproduct = 0)
$objectline = new $objectlineclassname($this->db);
+ '@phan-var-force BOMLine $objectline';
+
$sql = "SELECT ".$objectline->getFieldList('l');
$sql .= " FROM ".$this->db->prefix().$objectline->table_element." as l";
$sql .= " LEFT JOIN ".$this->db->prefix()."product as p ON p.rowid = l.fk_product";
@@ -455,6 +468,7 @@ public function fetchLinesbytypeproduct($typeproduct = 0)
$obj = $this->db->fetch_object($resql);
if ($obj) {
$newline = new $objectlineclassname($this->db);
+ '@phan-var-force BOMLine $newline';
$newline->setVarsFromFetchObj($obj);
$this->lines[] = $newline;
@@ -476,11 +490,11 @@ public function fetchLinesbytypeproduct($typeproduct = 0)
*
* @param string $sortorder Sort Order
* @param string $sortfield Sort field
- * @param int $limit Limit
- * @param int $offset Offset
+ * @param int<0,max> $limit Limit
+ * @param int<0,max> $offset Offset
* @param string $filter Filter USF
* @param string $filtermode Filter mode (AND or OR)
- * @return array|int int <0 if KO, array of pages if OK
+ * @return BOM[]|int<-1,-1> int <0 if KO, array of pages if OK
*/
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
{
@@ -537,9 +551,9 @@ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset =
/**
* Update object into database
*
- * @param User $user User that modifies
- * @param int $notrigger 0=launch triggers after, 1=disable triggers
- * @return int Return integer <0 if KO, >0 if OK
+ * @param User $user User that modifies
+ * @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
+ * @return int<-1,-1>|int<1,1> Return integer <0 if KO, >0 if OK
*/
public function update(User $user, $notrigger = 1)
{
@@ -553,9 +567,9 @@ public function update(User $user, $notrigger = 1)
/**
* Delete object in database
*
- * @param User $user User that deletes
- * @param int $notrigger 0=launch triggers after, 1=disable triggers
- * @return int Return integer <0 if KO, >0 if OK
+ * @param User $user User that deletes
+ * @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
+ * @return int<-1,-1>|int<1,1> Return integer <0 if KO, >0 if OK
*/
public function delete(User $user, $notrigger = 1)
{
@@ -566,18 +580,18 @@ public function delete(User $user, $notrigger = 1)
/**
* Add an BOM line into database (linked to BOM)
*
- * @param int $fk_product Id of product
- * @param float $qty Quantity
- * @param int<0,1> $qty_frozen If the qty is Frozen
- * @param int $disable_stock_change Disable stock change on using in MO
- * @param float $efficiency Efficiency in MO
- * @param int $position Position of BOM-Line in BOM-Lines
- * @param int $fk_bom_child Id of BOM Child
- * @param string $import_key Import Key
- * @param int $fk_unit Unit
- * @param array $array_options extrafields array
- * @param int $fk_default_workstation Default workstation
- * @return int Return integer <0 if KO, Id of created object if OK
+ * @param int $fk_product Id of product
+ * @param float $qty Quantity
+ * @param int<0,1> $qty_frozen If the qty is Frozen
+ * @param int $disable_stock_change Disable stock change on using in MO
+ * @param float $efficiency Efficiency in MO
+ * @param int<-1,max> $position Position of BOM-Line in BOM-Lines
+ * @param ?int $fk_bom_child Id of BOM Child
+ * @param ?string $import_key Import Key
+ * @param int $fk_unit Unit
+ * @param array $array_options extrafields array
+ * @param ?int $fk_default_workstation Default workstation
+ * @return int<-3,max> Return integer <0 if KO, Id of created object if OK
*/
public function addLine($fk_product, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $fk_bom_child = null, $import_key = null, $fk_unit = 0, $array_options = array(), $fk_default_workstation = null)
{
@@ -607,7 +621,7 @@ public function addLine($fk_product, $qty, $qty_frozen = 0, $disable_stock_chang
$fk_bom_child = null;
}
if (empty($import_key)) {
- $import_key = null;
+ $import_key = '';
}
if (empty($position)) {
$position = -1;
@@ -675,17 +689,17 @@ public function addLine($fk_product, $qty, $qty_frozen = 0, $disable_stock_chang
/**
* Update an BOM line into database
*
- * @param int $rowid Id of line to update
- * @param float $qty Quantity
- * @param float $qty_frozen Frozen quantity
- * @param int $disable_stock_change Disable stock change on using in MO
- * @param float $efficiency Efficiency in MO
- * @param int $position Position of BOM-Line in BOM-Lines
- * @param string $import_key Import Key
- * @param int $fk_unit Unit of line
- * @param array $array_options extrafields array
- * @param int $fk_default_workstation Default workstation
- * @return int Return integer <0 if KO, Id of updated BOM-Line if OK
+ * @param int $rowid Id of line to update
+ * @param float $qty Quantity
+ * @param float $qty_frozen Frozen quantity
+ * @param int $disable_stock_change Disable stock change on using in MO
+ * @param float $efficiency Efficiency in MO
+ * @param int<-1,max> $position Position of BOM-Line in BOM-Lines
+ * @param ?string $import_key Import Key
+ * @param int $fk_unit Unit of line
+ * @param array $array_options extrafields array
+ * @param ?int $fk_default_workstation Default workstation
+ * @return int<-3,max> Return integer <0 if KO, Id of updated BOM-Line if OK
*/
public function updateLine($rowid, $qty, $qty_frozen = 0, $disable_stock_change = 0, $efficiency = 1.0, $position = -1, $import_key = null, $fk_unit = 0, $array_options = array(), $fk_default_workstation = null)
{
@@ -712,7 +726,7 @@ public function updateLine($rowid, $qty, $qty_frozen = 0, $disable_stock_change
$efficiency = 1.0;
}
if (empty($import_key)) {
- $import_key = null;
+ $import_key = '';
}
if (empty($position)) {
$position = -1;
@@ -794,10 +808,10 @@ public function updateLine($rowid, $qty, $qty_frozen = 0, $disable_stock_change
/**
* Delete a line of object in database
*
- * @param User $user User that delete
- * @param int $idline Id of line to delete
- * @param int $notrigger 0=launch triggers after, 1=disable triggers
- * @return int >0 if OK, <0 if KO
+ * @param User $user User that delete
+ * @param int $idline Id of line to delete
+ * @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
+ * @return int<-2,-1>|int<1,1> >0 if OK, <0 if KO
*/
public function deleteLine(User $user, $idline, $notrigger = 0)
{
@@ -866,12 +880,13 @@ public function getNextNumRef($prod)
$mybool = ((bool) @include_once $dir.$file) || $mybool;
}
- if ($mybool === false) {
+ if (!$mybool) {
dol_print_error(null, "Failed to include file ".$file);
return '';
}
$obj = new $classname();
+ '@phan-var-force ModeleNumRefBoms $obj';
$numref = $obj->getNextValue($prod, $this);
if ($numref != "") {
@@ -890,9 +905,9 @@ public function getNextNumRef($prod)
/**
* Validate bom
*
- * @param User $user User making status change
- * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
- * @return int Return integer <=0 if OK, 0=Nothing done, >0 if KO
+ * @param User $user User making status change
+ * @param int<0,1> $notrigger 1=Does not execute triggers, 0= execute triggers
+ * @return int<-1,1> Return integer <=0 if OK, 0=Nothing done, >0 if KO
*/
public function validate($user, $notrigger = 0)
{
@@ -1009,9 +1024,9 @@ public function validate($user, $notrigger = 0)
/**
* Set draft status
*
- * @param User $user Object user that modify
- * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
- * @return int Return integer <0 if KO, >0 if OK
+ * @param User $user Object user that modify
+ * @param int<0,1> $notrigger 1=Does not execute triggers, 0=Execute triggers
+ * @return int<-1,1> Return integer <0 if KO, 0=Nothing done, >0 if OK
*/
public function setDraft($user, $notrigger = 0)
{
@@ -1026,9 +1041,9 @@ public function setDraft($user, $notrigger = 0)
/**
* Set cancel status
*
- * @param User $user Object user that modify
- * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
- * @return int Return integer <0 if KO, 0=Nothing done, >0 if OK
+ * @param User $user Object user that modify
+ * @param int<0,1> $notrigger 1=Does not execute triggers, 0=Execute triggers
+ * @return int<-1,1> Return integer <0 if KO, 0=Nothing done, >0 if OK
*/
public function cancel($user, $notrigger = 0)
{
@@ -1041,11 +1056,11 @@ public function cancel($user, $notrigger = 0)
}
/**
- * Set cancel status
+ * Reopen if canceled
*
- * @param User $user Object user that modify
- * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
- * @return int Return integer <0 if KO, 0=Nothing done, >0 if OK
+ * @param User $user Object user that modify
+ * @param int<0,1> $notrigger 1=Does not execute triggers, 0=Execute triggers
+ * @return int<-1,1> Return integer <0 if KO, 0=Nothing done, >0 if OK
*/
public function reopen($user, $notrigger = 0)
{
@@ -1061,7 +1076,7 @@ public function reopen($user, $notrigger = 0)
* getTooltipContentArray
* @param array $params params to construct tooltip data
* @since v18
- * @return array
+ * @return array{picto:string,ref?:string,refsupplier?:string,label?:string,date?:string,date_echeance?:string,amountht?:string,total_ht?:string,totaltva?:string,amountlt1?:string,amountlt2?:string,amountrevenustamp?:string,totalttc?:string}|array{optimize:string}
*/
public function getTooltipContentArray($params)
{
@@ -1098,11 +1113,11 @@ public function getTooltipContentArray($params)
/**
* Return a link to the object card (with optionally 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
+ * @param int<0,2> $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<0,1> $notooltip 1=Disable tooltip
+ * @param string $morecss Add more css on link
+ * @param int<-1,1> $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string String with URL
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
@@ -1196,8 +1211,8 @@ public function getLibStatut($mode = 0)
/**
* 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
+ * @param int $status Id status
+ * @param int<0,6> $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)
@@ -1256,7 +1271,7 @@ public function info($id)
/**
* Create an array of lines
*
- * @return array|int array of lines if OK, <0 if KO
+ * @return BOMLine[]|int array of lines if OK, <0 if KO
*/
public function getLinesArray()
{
@@ -1280,11 +1295,11 @@ public function getLinesArray()
*
* @param string $modele Force template to use ('' to not force)
* @param Translate $outputlangs object lang a utiliser pour traduction
- * @param int $hidedetails Hide details of lines
- * @param int $hidedesc Hide description
- * @param int $hideref Hide ref
+ * @param int<0,1> $hidedetails Hide details of lines
+ * @param int<0,1> $hidedesc Hide description
+ * @param int<0,1> $hideref Hide ref
* @param null|array $moreparams Array to provide more information
- * @return int 0 if KO, 1 if OK
+ * @return int<0,1> 0 if KO, 1 if OK
*/
public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
{
@@ -1347,7 +1362,7 @@ public function is_photo_available($sdir)
* Initialise object with example values
* Id must be 0 if object instance is a specimen
*
- * @return int
+ * @return int<1,1>
*/
public function initAsSpecimen()
{
@@ -1502,9 +1517,9 @@ public function calculateCosts()
/**
* Function used to replace a product id with another one.
*
- * @param DoliDB $db Database handler
- * @param int $origin_id Old product id
- * @param int $dest_id New product id
+ * @param DoliDB $db Database handler
+ * @param int $origin_id Old product id
+ * @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
@@ -1548,8 +1563,8 @@ public function getNetNeeds(&$TNetNeeds = array(), $qty = 0)
* Get/add Net needs Tree by product or bom
*
* @param array $TNetNeeds Array of ChildBom and infos linked to
- * @param float $qty qty needed (used as a factor to produce 1 unit)
- * @param int $level level of recursivity
+ * @param float $qty qty needed (used as a factor to produce 1 unit)
+ * @param int<0,1000> $level level of recursivity
* @return void
*/
public function getNetNeedsTree(&$TNetNeeds = array(), $qty = 0, $level = 0)
@@ -1590,9 +1605,9 @@ public function getNetNeedsTree(&$TNetNeeds = array(), $qty = 0, $level = 0)
/**
* Recursively retrieves all parent bom in the tree that leads to the $bom_id bom
*
- * @param array $TParentBom We put all found parent bom in $TParentBom
- * @param int $bom_id ID of bom from which we want to get parent bom ids
- * @param int $level Protection against infinite loop
+ * @param BOM[] $TParentBom We put all found parent bom in $TParentBom
+ * @param int $bom_id ID of bom from which we want to get parent bom ids
+ * @param int<0,1000> $level Protection against infinite loop
* @return void
*/
public function getParentBomTreeRecursive(&$TParentBom, $bom_id = 0, $level = 1)
@@ -1622,11 +1637,11 @@ public function getParentBomTreeRecursive(&$TParentBom, $bom_id = 0, $level = 1)
}
/**
- * Return clicable link of object (with eventually picto)
+ * Return clickable link of object (with eventually picto)
*
- * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
- * @param array $arraydata Array of data
- * @return string HTML Code for Kanban thumb.
+ * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
+ * @param array{prod:?Product,selected:int<-1,1>} $arraydata Array of data
+ * @return string HTML Code for Kanban thumb.
*/
public function getKanbanView($option = '', $arraydata = null)
{
@@ -1644,12 +1659,13 @@ public function getKanbanView($option = '', $arraydata = null)
if ($selected >= 0) {
$return .= '';
}
- if (property_exists($this, 'fields') && !empty($this->fields['bomtype']['arrayofkeyval'])) {
+ $arrayofkeyval = $this->fields['bomtype']['arrayofkeyval'] ?? null;
+ if (!empty($arrayofkeyval)) {
$return .= ' '.$langs->trans("Type").' : ';
if ($this->bomtype == 0) {
- $return .= ''.$this->fields['bomtype']['arrayofkeyval'][0].'';
+ $return .= ''.$arrayofkeyval[0].'';
} else {
- $return .= ''.$this->fields['bomtype']['arrayofkeyval'][1].'';
+ $return .= ''.$arrayofkeyval[1].'';
}
}
if (!empty($arraydata['prod'])) {
@@ -1720,7 +1736,7 @@ class BOMLine extends CommonObjectLine
// BEGIN MODULEBUILDER PROPERTIES
/**
- * @var array|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
+ * @var array|string,position:int,notnull?:int,visible:int<-2,5>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,2>,disabled?:int<0,1>,arrayofkeyval?:array,comment?:string,validate?:int<0,1>}> 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' => 'LineID', 'enabled' => 1, 'visible' => -1, 'position' => 1, 'notnull' => 1, 'index' => 1, 'comment' => "Id",),
@@ -1754,7 +1770,7 @@ class BOMLine extends CommonObjectLine
public $fk_product;
/**
- * @var int Id of parent bom
+ * @var ?int Id of parent bom
*/
public $fk_bom_child;
@@ -1791,7 +1807,7 @@ class BOMLine extends CommonObjectLine
public $fk_unit;
/**
- * @var int Service Workstation
+ * @var ?int Service Workstation
*/
public $fk_default_workstation;
@@ -1807,17 +1823,17 @@ class BOMLine extends CommonObjectLine
// END MODULEBUILDER PROPERTIES
/**
- * @var float Calculated cost for the BOM line
+ * @var int|float Calculated cost for the BOM line
*/
public $total_cost = 0;
/**
- * @var float Line unit cost based on product cost price or pmp
+ * @var int|float Line unit cost based on product cost price or pmp
*/
public $unit_cost = 0;
/**
- * @var array array of Bom in line
+ * @var BOM[] array of Bom in line
*/
public $childBom = array();
@@ -1902,7 +1918,7 @@ public function fetch($id, $ref = null)
* @param string $filter Filter as an Universal Search string.
* Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
* @param string $filtermode No more used
- * @return array|int int <0 if KO, array of pages if OK
+ * @return BOMLine[]|int<-1,-1> int <0 if KO, array of pages if OK
*/
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
{
@@ -1989,11 +2005,11 @@ public function delete(User $user, $notrigger = 0)
/**
* Return a link to the object card (with optionally 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
+ * @param int<0,2> $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<0,1> $notooltip 1=Disable tooltip
+ * @param string $morecss Add more css on link
+ * @param int<-1,1> $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string String with URL
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
@@ -2077,9 +2093,9 @@ public function getLibStatut($mode = 0)
/**
* 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
+ * @param int $status Id status
+ * @param int<0,6> $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)
{
diff --git a/htdocs/bom/tpl/linkedobjectblock.tpl.php b/htdocs/bom/tpl/linkedobjectblock.tpl.php
index 3ededc6bffa1b..aa429b2d65c8b 100644
--- a/htdocs/bom/tpl/linkedobjectblock.tpl.php
+++ b/htdocs/bom/tpl/linkedobjectblock.tpl.php
@@ -3,6 +3,7 @@
* Copyright (C) 2013 Juanjo Menent
* Copyright (C) 2014 Marcos García
* Copyright (C) 2013-2020 Charlene BENKE
+ * Copyright (C) 2024 MDW
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,12 +31,15 @@
global $noMoreLinkedObjectBlockAfter;
$langs = $GLOBALS['langs'];
+'@phan-var-force Translate $langs';
$linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
// Load translation files required by the page
$langs->load("bom");
+'@phan-var-force array $linkedObjectBlock'; // Type before use
$linkedObjectBlock = dol_sort_array($linkedObjectBlock, 'date', 'desc', 0, 0, 1);
+'@phan-var-force array $linkedObjectBlock'; // Type after dol_sort_array which looses typing
$total = 0;
$ilink = 0;
@@ -65,7 +69,7 @@
echo '