diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 8046f932357..117b91b9565 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -44,7 +44,8 @@ jobs: # Restore old cache - name: Restore phpstan cache - uses: actions/cache/restore@v3 + id: cache + uses: actions/cache/restore@v4 with: path: ./.github/tmp key: "phpstan-cache-${{ matrix.php-version }}-${{ github.run_id }}" @@ -55,13 +56,14 @@ jobs: # Run PHPStan - name: Run PHPStan + id: phpstan run: phpstan -vvv analyse --error-format=checkstyle --memory-limit 4G -a build/phpstan/bootstrap_action.php -c phpstan.neon | cs2pr --graceful-warnings # continue-on-error: true # Save cache - name: "Save phpstan cache" - uses: actions/cache/save@v3 - if: always() + uses: actions/cache/save@v4 + if: ${{ success() || ( ! cancelled() && steps.cache.outputs.cache-hit != 'true' ) }} with: path: ./.github/tmp key: "phpstan-cache-${{ matrix.php-version }}-${{ github.run_id }}" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index cffcb6ffcd9..7836dd5a487 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -27,7 +27,7 @@ jobs: python-version: '3.11' - run: python -m pip install pre-commit regex # Restore previous cache of precommit - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ~/.cache/pre-commit/ key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} @@ -54,8 +54,8 @@ jobs: notices-as-warnings: true # optional prepend-filename: true # optional # Save the precommit cache - - uses: actions/cache/save@v3 - if: ${{ always() }} + - uses: actions/cache/save@v4 + if: ${{ ! cancelled() }} with: path: ~/.cache/pre-commit/ key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') @@ -63,7 +63,7 @@ jobs: # Upload result log files of precommit into the Artifact shared store - name: Provide log as artifact uses: actions/upload-artifact@v4 - if: ${{ always() }} + if: ${{ ! cancelled() }} with: name: precommit-logs path: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6fefa14ed25..490373ea632 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,6 +34,15 @@ repos: args: [--tab] # Run local script + # + # For instance to update the license in edited files, you could add to local.sh: + # + # ```shell + # #!/bin/bash + # MYDIR=$(dirname "$0") + # CHANGED_INTERNALS=$(git diff --name-only | grep -v includes) + # "$MYDIR/dev/tools/updatelicense.php" $CHANGED_INTERNALS + # ``` - repo: local hooks: - id: local-precommit-script diff --git a/dev/setup/codesniffer/README b/dev/setup/codesniffer/README index 2fdc66b9d1f..940b8db182a 100644 --- a/dev/setup/codesniffer/README +++ b/dev/setup/codesniffer/README @@ -1,7 +1,7 @@ README (English) -------------------------------- -This directory contains ruleset files to use to develop Dolibarr EPR & CRM. +This directory contains ruleset files to use to develop Dolibarr ERP & CRM. To install/upgrade phpcs: > sudo pear upgrade PHP_CodeSniffer @@ -17,5 +17,4 @@ To fix with phpcbf: Note with Eclipse: You must setup the PTI plugin of Eclipse into PHPCodeSniffer menu with: * tab value to 4 -* path of code sniffer standard to dev/codesniffer - +* path of code sniffer standard to dev/codesniffer diff --git a/dev/tools/codespell/addCodespellIgnores.sh b/dev/tools/codespell/addCodespellIgnores.sh index 0b73c4c16b2..00a93e1a03b 100755 --- a/dev/tools/codespell/addCodespellIgnores.sh +++ b/dev/tools/codespell/addCodespellIgnores.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Copyright (C) 2024 MDW + # # Script to add codespell exceptions to the ignores lines file. # @@ -18,7 +20,7 @@ # # :warning: # -# This script only works properly if codespell is install for your CLI. +# This script only works properly if codespell is installed for your CLI. # As the configuration is in pyproject.toml, you also need tomli. # # ```shell @@ -50,11 +52,17 @@ fi [ -r "${codespell_ignore_file}" ] || { echo "${codespell_ignore_file} not found" ; exit 1 ; } # Then: # - Run codespell; +# - Identify files that have fixes; +# - Limit to files under git control; +# - Run codespell on selected files; # - For each line, create a grep command to find the lines; # - Execute that command by evaluation -codespell . | sed -n -E 's@^([^:]+):[[:digit:]]+:[[:space:]](\S+)[[:space:]].*@grep -P '\''\\b\2\\b'\'' "\1" >> '"${codespell_ignore_file}"'@p' | \ - while read -r line ; do eval "$line" ; done +codespell . \ + | sed -n -E 's@^([^:]+)@\1@p' \ + | xargs -r git ls-files -- \ + | xargs -r codespell -- \ + | sed -n -E 's@^([^:]+):[[:digit:]]+:[[:space:]](\S+)[[:space:]].*@grep -P '\''\\b\2\\b'\'' -- "\1" >> '"${codespell_ignore_file}"'@p' \ + | while read -r line ; do eval "$line" ; done # Finally, sort and remove duplicates to make merges easier. sort -u -o "${codespell_ignore_file}"{,} - diff --git a/dev/tools/codespell/codespell-dict.txt b/dev/tools/codespell/codespell-dict.txt index fbab9df6c3c..e5f9ed51f86 100644 --- a/dev/tools/codespell/codespell-dict.txt +++ b/dev/tools/codespell/codespell-dict.txt @@ -1,9 +1,10 @@ +# Please add in alphabetical order->(`sort -u` like). +EPR->ERP +alpahnohtml->alphanohtml +choosed->chosen dolibar->dolibarr dollibar->dolibarr dollibarr->dolibarr -not de passe->password mot de passe->password -choosed->chosen +not de passe->password tableau de bord->state board -#DoliDB->DoliDB -alpahnohtml->alphanohtml diff --git a/dev/tools/updatelicense.php b/dev/tools/updatelicense.php new file mode 100755 index 00000000000..6c69785e7e0 --- /dev/null +++ b/dev/tools/updatelicense.php @@ -0,0 +1,154 @@ +#!/usr/bin/env php + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Script to update year periods and user/email in headers. + */ + +/** + * Retrieve Git user information + * + * @return array{name:string,email:string} + */ +function getGitUserInfo() +{ + $name = trim(shell_exec('git config user.name')); + $email = trim(shell_exec('git config user.email')); + return ['name' => $name, 'email' => $email]; +} + +const PREFIXES = [ + 'sh' => ['# ', '# ', '', '#!'], + 'php' => ['/* ', ' * ', ' */', '\d{4}))\s+{$r_name}\s*\<{$r_email}>~"; + + // Check if the lines match the pattern + if (preg_match($pattern, $lines, $matches)) { + $existingYear = $matches['year']; + + // Check if the existing year is different from the current year + if ($existingYear !== date('Y')) { + // Update the year range to include or be up to the current year + $updatedNotice = preg_replace('/(\d{4})(-\d{4})?\s+/', $existingYear . '-' . date('Y') . "\t", $matches[0]); + + // Replace the old notice with the updated one in the file + file_put_contents($filename, preg_replace($pattern, $updatedNotice, file_get_contents($filename))); + return true; // Change detected + } + // If the existing year is the same, no need to update + } else { + // Adjust tabs for proper alignment + $emailTabs = str_repeat("\t", (int) (max(0, (31 - mb_strlen($name)) / 4))); + + // No match found, add a new line to the header + $newNotice = "Copyright (C) " . date('Y') . "\t\t" . $name . $emailTabs . "<" . $email . ">"; + + // Read the file content + $fileContent = file_get_contents($filename); + + // Check if there are existing copyright notices + $pos = max(strrpos($fileContent, "{$prefix0}Copyright"), strrpos($fileContent, "{$prefix1}Copyright")); + + if ($pos !== false) { + // Add the new notice behind the last preceding copyright notices + $pos = strpos($fileContent, "\n", $pos) + 1; + $fileContent = substr_replace($fileContent, $prefix1 . $newNotice . "\n", $pos, 0); + } elseif (strpos($fileContent, $prefix3) !== false) { + // Add the new notice after the shebang or ' [ ...]" . PHP_EOL; + exit(1); +} + +// Process each filename provided +$changesDetected = false; +for ($i = 1; $i < $argc; $i++) { + $filename = $argv[$i]; + + // Determine file type based on extension + $fileType = pathinfo($filename, PATHINFO_EXTENSION); + + // Retrieve Git user information + $gitUserInfo = getGitUserInfo(); + $name = $gitUserInfo['name']; + $email = $gitUserInfo['email']; + + // Update or add copyright notice based on file type + $changeDetected = updateCopyrightNotice($filename, $fileType, $name, $email); + $changesDetected |= $changeDetected; + if ($changeDetected) { + echo "Copyright notice updated in '$filename'" . PHP_EOL; + } +} + +if (!$changesDetected) { + echo "No changes needed in any file" . PHP_EOL; +} diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 00adc0bffae..67f5bf220e7 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1372,6 +1372,7 @@ function dol_sanitizeFileName($str, $newstr = '_', $unaccent = 1) return $tmp; } + /** * Clean a string to use it as a path name. Similare to dol_sanitizeFileName but accept / and \ chars. * Replace also '--' and ' -' strings, they are used for parameters separation (Note: ' - ' is allowed). @@ -2795,15 +2796,15 @@ function dol_format_address($object, $withcountry = 0, $sep = "\n", $outputlangs * * @param string $fmt Format of strftime function (http://php.net/manual/fr/function.strftime.php) * @param int $ts Timestamp (If is_gmt is true, timestamp is already includes timezone and daylight saving offset, if is_gmt is false, timestamp is a GMT timestamp and we must compensate with server PHP TZ) - * @param int $is_gmt See comment of timestamp parameter + * @param bool $is_gmt See comment of timestamp parameter * @return string A formatted string */ function dol_strftime($fmt, $ts = false, $is_gmt = false) { if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - return ($is_gmt) ? @gmstrftime($fmt, $ts) : @dol_print_date($ts, $fmt); + return dol_print_date($ts, $fmt, $is_gmt); } else { - return 'Error date into a not supported range'; + return 'Error date outside supported range'; } } @@ -2818,7 +2819,7 @@ function dol_strftime($fmt, $ts = false, $is_gmt = false) * "%d/%m/%Y %H:%M:%S", * "%B"=Long text of month, "%A"=Long text of day, "%b"=Short text of month, "%a"=Short text of day * "day", "daytext", "dayhour", "dayhourldap", "dayhourtext", "dayrfc", "dayhourrfc", "...inputnoreduce", "...reduceformat" - * @param string $tzoutput true or 'gmt' => string is for Greenwich location + * @param string|bool $tzoutput true or 'gmt' => string is for Greenwich location * false or 'tzserver' => output string is for local PHP server TZ usage * 'tzuser' => output string is for user TZ (current browser TZ with current dst) => In a future, we should have same behaviour than 'tzuserrel' * 'tzuserrel' => output string is for user TZ (current browser TZ with dst or not, depending on date position) diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index 70732b5ebde..ff917cc2634 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -559,6 +559,7 @@ class Cronjob extends CommonObject $sql .= " t.fk_user_mod,"; $sql .= " t.note as note_private,"; $sql .= " t.nbrun,"; + $sql .= " t.maxrun,"; $sql .= " t.libname,"; $sql .= " t.test"; $sql .= " FROM ".MAIN_DB_PREFIX."cronjob as t"; @@ -595,45 +596,46 @@ class Cronjob extends CommonObject if ($num) { while ($i < $num) { - $line = new Cronjobline(); - $obj = $this->db->fetch_object($resql); + $cronjob_obj = new Cronjob($this->db); - $line->id = $obj->rowid; - $line->ref = $obj->rowid; - $line->entity = $obj->entity; - $line->tms = $this->db->jdate($obj->tms); - $line->datec = $this->db->jdate($obj->datec); - $line->label = $obj->label; - $line->jobtype = $obj->jobtype; - $line->command = $obj->command; - $line->classesname = $obj->classesname; - $line->objectname = $obj->objectname; - $line->methodename = $obj->methodename; - $line->params = $obj->params; - $line->md5params = $obj->md5params; - $line->module_name = $obj->module_name; - $line->priority = $obj->priority; - $line->datelastrun = $this->db->jdate($obj->datelastrun); - $line->datenextrun = $this->db->jdate($obj->datenextrun); - $line->dateend = $this->db->jdate($obj->dateend); - $line->datestart = $this->db->jdate($obj->datestart); - $line->lastresult = $obj->lastresult; - $line->datelastresult = $this->db->jdate($obj->datelastresult); - $line->lastoutput = $obj->lastoutput; - $line->unitfrequency = $obj->unitfrequency; - $line->frequency = $obj->frequency; - $line->status = $obj->status; - $line->processing = $obj->processing; - $line->pid = $obj->pid; - $line->email_alert = $obj->email_alert; - $line->fk_user_author = $obj->fk_user_author; - $line->fk_user_mod = $obj->fk_user_mod; - $line->note_private = $obj->note_private; - $line->nbrun = $obj->nbrun; - $line->libname = $obj->libname; - $line->test = $obj->test; - $this->lines[] = $line; + $cronjob_obj->id = $obj->rowid; + $cronjob_obj->ref = $obj->rowid; + $cronjob_obj->entity = $obj->entity; + $cronjob_obj->tms = $this->db->jdate($obj->tms); + $cronjob_obj->datec = $this->db->jdate($obj->datec); + $cronjob_obj->label = $obj->label; + $cronjob_obj->jobtype = $obj->jobtype; + $cronjob_obj->command = $obj->command; + $cronjob_obj->classesname = $obj->classesname; + $cronjob_obj->objectname = $obj->objectname; + $cronjob_obj->methodename = $obj->methodename; + $cronjob_obj->params = $obj->params; + $cronjob_obj->md5params = $obj->md5params; + $cronjob_obj->module_name = $obj->module_name; + $cronjob_obj->priority = $obj->priority; + $cronjob_obj->datelastrun = $this->db->jdate($obj->datelastrun); + $cronjob_obj->datenextrun = $this->db->jdate($obj->datenextrun); + $cronjob_obj->dateend = $this->db->jdate($obj->dateend); + $cronjob_obj->datestart = $this->db->jdate($obj->datestart); + $cronjob_obj->lastresult = $obj->lastresult; + $cronjob_obj->lastoutput = $obj->lastoutput; + $cronjob_obj->datelastresult = $this->db->jdate($obj->datelastresult); + $cronjob_obj->unitfrequency = $obj->unitfrequency; + $cronjob_obj->frequency = $obj->frequency; + $cronjob_obj->status = $obj->status; + $cronjob_obj->processing = $obj->processing; + $cronjob_obj->pid = $obj->pid; + $cronjob_obj->email_alert = $obj->email_alert; + $cronjob_obj->fk_user_author = $obj->fk_user_author; + $cronjob_obj->fk_user_mod = $obj->fk_user_mod; + $cronjob_obj->note_private = $obj->note_private; + $cronjob_obj->nbrun = $obj->nbrun; + $cronjob_obj->maxrun = $obj->maxrun; + $cronjob_obj->libname = $obj->libname; + $cronjob_obj->test = $obj->test; + + $this->lines[] = $cronjob_obj; $i++; } @@ -1572,76 +1574,9 @@ class Cronjob extends CommonObject /** - * Crob Job line class + * Crob Job line class + * @TODO Deprecated, to delete very soon */ -class Cronjobline +class Cronjobline extends Cronjob { - /** - * @var int ID - */ - public $id; - - public $entity; - - /** - * @var string Ref - */ - public $ref; - - public $tms = ''; - public $datec = ''; - - /** - * @var string Cron Job Line label - */ - public $label; - - public $jobtype; - public $command; - public $classesname; - public $objectname; - public $methodename; - public $params; - public $md5params; - public $module_name; - public $priority; - public $datelastrun = ''; - public $datenextrun = ''; - public $dateend = ''; - public $datestart = ''; - public $datelastresult = ''; - public $lastresult = ''; - public $lastoutput; - public $unitfrequency; - public $frequency; - public $processing; - - /** - * @var int Status - */ - public $status; - - /** - * @var int ID - */ - public $fk_user_author; - - /** - * @var int ID - */ - public $fk_user_mod; - - public $note; - public $note_private; - public $nbrun; - public $libname; - public $test; - - /** - * Constructor - * - */ - public function __construct() - { - } } diff --git a/htdocs/fourn/facture/card-rec.php b/htdocs/fourn/facture/card-rec.php index d196d562ba6..3c505e20bc5 100644 --- a/htdocs/fourn/facture/card-rec.php +++ b/htdocs/fourn/facture/card-rec.php @@ -62,7 +62,7 @@ $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("pa // Security check $id = (GETPOST('facid', 'int') ? GETPOST('facid', 'int') : GETPOST('id', 'int')); -$lineid = GETPOST('lineid', 'int'); +$lineid = GETPOSTINT('lineid'); $title = GETPOST('title', 'alpha'); $libelle = GETPOST('libelle', 'alpha'); $ref_supplier = GETPOST('ref_supplier', 'alpha'); @@ -194,7 +194,7 @@ if (empty($reshook)) { $object->title = GETPOST('title', 'alphanohtml'); $object->libelle = GETPOST('libelle', 'alpha'); // deprecated $object->label = GETPOST('libelle', 'alpha'); - $object->fk_project = GETPOST('projectid', 'int'); + $object->fk_project = GETPOSTINT('projectid'); $object->ref_supplier = GETPOST('ref_supplier', 'alphanohtml'); $object->note_private = GETPOST('note_private', 'restricthtml'); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 72f4b19f4f2..b0fd9dfe7d6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -760,7 +760,7 @@ if (empty($reshook)) { } elseif ($action == 'add' && $usercancreate) { // Insert new invoice in database if ($socid > 0) { - $object->socid = GETPOST('socid', 'int'); + $object->socid = GETPOSTINT('socid'); } $selectedLines = GETPOST('toselect', 'array'); diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 9c7bc6bbeeb..e7ce2fd79d2 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -183,7 +183,7 @@ if (empty($reshook)) { $halfday = 1; } - $approverid = GETPOST('valideur', 'int'); + $approverid = GETPOSTINT('valideur'); $description = trim(GETPOST('description', 'restricthtml')); // Check that leave is for a user inside the hierarchy or advanced permission for all is set diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 1fd9a75f1b3..2de7dbbbdc3 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -185,4 +185,4 @@ EvenUnsubscribe=Include opt-out emails EvenUnsubscribeDesc=Include opt-out emails when you select emails as targets. Useful for mandatory service emails for example. XEmailsDoneYActionsDone=%s emails pre-qualified, %s emails successfully processed (for %s record/actions done) helpWithAi=Add instructions -YouCanMakeSomeInstructionForEmail=You Can Make Some Instruction For your Email (Exemple: generate image in email template...) \ No newline at end of file +YouCanMakeSomeInstructionForEmail=You can add some instructions for your email (Example: generate image in email template...) diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 3a19d530054..b9f5f672bc2 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -132,7 +132,7 @@ if (empty($reshook)) { if (!$error) { $object->label = GETPOST('label'); - $object->fk_bank = GETPOST('accountid'); + $object->fk_bank = GETPOSTINT('accountid'); $object->capital = $capital; $object->datestart = $datestart; $object->dateend = $dateend; @@ -140,7 +140,7 @@ if (empty($reshook)) { $object->rate = $rate; $object->note_private = GETPOST('note_private', 'restricthtml'); $object->note_public = GETPOST('note_public', 'restricthtml'); - $object->fk_project = GETPOST('projectid', 'int'); + $object->fk_project = GETPOSTINT('projectid'); $object->insurance_amount = GETPOST('insurance_amount', 'int'); $accountancy_account_capital = GETPOST('accountancy_account_capital'); diff --git a/htdocs/mrp/class/api_mos.class.php b/htdocs/mrp/class/api_mos.class.php index 4b185f4b304..1c8435d65cf 100644 --- a/htdocs/mrp/class/api_mos.class.php +++ b/htdocs/mrp/class/api_mos.class.php @@ -736,7 +736,7 @@ class Mos extends DolibarrApi * * @return void */ - private function checkRefNumbering(): void + private function checkRefNumbering() { $ref = substr($this->mo->ref, 1, 4); if ($this->mo->status > 0 && $ref == 'PROV') { diff --git a/htdocs/product/card.php b/htdocs/product/card.php index a3c487bff35..6e9d0b6ed82 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -575,7 +575,7 @@ if (empty($reshook)) { // Set barcode_type_xxx from barcode_type id $stdobject = new GenericObject($db); $stdobject->element = 'product'; - $stdobject->barcode_type = GETPOST('fk_barcode_type'); + $stdobject->barcode_type = GETPOSTINT('fk_barcode_type'); $result = $stdobject->fetch_barcode(); if ($result < 0) { $error++; @@ -817,7 +817,7 @@ if (empty($reshook)) { // Set barcode_type_xxx from barcode_type id $stdobject = new GenericObject($db); $stdobject->element = 'product'; - $stdobject->barcode_type = GETPOST('fk_barcode_type'); + $stdobject->barcode_type = GETPOSTINT('fk_barcode_type'); $result = $stdobject->fetch_barcode(); if ($result < 0) { $error++; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 26890169fb8..5225a0ec57a 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -663,10 +663,10 @@ class Product extends CommonObject $this->ref = dol_sanitizeFileName(dol_string_nospecial(trim($this->ref))); } $this->label = trim($this->label); - $this->price_ttc = price2num($this->price_ttc); - $this->price = price2num($this->price); - $this->price_min_ttc = price2num($this->price_min_ttc); - $this->price_min = price2num($this->price_min); + $this->price_ttc = (float) price2num($this->price_ttc); + $this->price = (float) price2num($this->price); + $this->price_min_ttc = (float) price2num($this->price_min_ttc); + $this->price_min = (float) price2num($this->price_min); if (empty($this->tva_tx)) { $this->tva_tx = 0; } @@ -4542,7 +4542,7 @@ class Product extends CommonObject * * @param int $fk_parent Id of parent kit product * @param int $fk_child Id of child product - * @return int Return integer <0 if KO, >0 if OK + * @return int Return 1 or 0; -1 if error */ public function is_sousproduit($fk_parent, $fk_child) { @@ -4562,9 +4562,9 @@ class Product extends CommonObject $this->is_sousproduit_qty = $obj->qty; $this->is_sousproduit_incdec = $obj->incdec; - return true; + return 1; } else { - return false; + return 0; } } else { dol_print_error($this->db);