FIX Avoid infinite loop when a fetch is inside a compute field.

This commit is contained in:
Laurent Destailleur 2020-04-28 14:25:07 +02:00
parent 2b00ae9e92
commit dd3a5949c0
3 changed files with 27 additions and 3 deletions

View File

@ -5243,6 +5243,25 @@ abstract class CommonObject
/* Functions for extrafields */
/**
* Function to make a fetch but set environment to avoid to load computed values before.
*
* @param int $id ID of object
* @return int >0 if OK, 0 if not found, <0 if KO
*/
public function fetchNoCompute($id)
{
global $conf;
$savDisableCompute = $conf->disable_compute;
$conf->disable_compute = 1;
$ret = $this->fetch($id);
$conf->disable_compute = $savDisableCompute;
return $ret;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
@ -5257,7 +5276,7 @@ abstract class CommonObject
public function fetch_optionals($rowid = null, $optionsArray = null)
{
// phpcs:enable
global $extrafields;
global $conf, $extrafields;
if (empty($rowid)) $rowid = $this->id;
if (empty($rowid)) $rowid = $this->rowid;
@ -5341,7 +5360,10 @@ abstract class CommonObject
foreach ($tab as $key => $value) {
if (!empty($extrafields) && !empty($extrafields->attributes[$this->table_element]['computed'][$key]))
{
$this->array_options["options_".$key] = dol_eval($extrafields->attributes[$this->table_element]['computed'][$key], 1, 0);
//var_dump($conf->disable_compute);
if (empty($conf->disable_compute)) {
$this->array_options["options_".$key] = dol_eval($extrafields->attributes[$this->table_element]['computed'][$key], 1, 0);
}
}
}
}

View File

@ -48,6 +48,8 @@ class Conf
//! To store if javascript/ajax is enabked
public $use_javascript_ajax;
//! To store if javascript/ajax is enabked
public $disable_compute;
//! Used to store current currency (ISO code like 'USD', 'EUR', ...)
public $currency;
//! Used to store current css (from theme)

View File

@ -427,7 +427,7 @@ ExtrafieldCheckBox=Checkboxes
ExtrafieldCheckBoxFromList=Checkboxes from table
ExtrafieldLink=Link to an object
ComputedFormula=Computed field
ComputedFormulaDesc=You can enter here a formula using other properties of object or any PHP coding to get a dynamic computed value. You can use any PHP compatible formulas including the "?" condition operator, and following global object: <strong>$db, $conf, $langs, $mysoc, $user, $object</strong>.<br><strong>WARNING</strong>: Only some properties of $object may be available. If you need a properties not loaded, just fetch yourself the object into your formula like in the second example.<br>Using a computed field means you can't enter yourself any value from interface. Also, if there is a syntax error, the formula may return nothing.<br><br>Example of formula:<br>$object->id < 10 ? round($object->id / 2, 2): ($object->id + 2 * $user->id) * (int) substr($mysoc->zip, 1, 2)<br><br>Example to reload object<br>(($reloadedobj = new Societe($db)) && ($reloadedobj->fetch($obj->id ? $obj->id: ($obj->rowid ? $obj->rowid: $object->id)) > 0)) ? $reloadedobj->array_options['options_extrafieldkey'] * $reloadedobj->capital / 5: '-1'<br><br>Other example of formula to force load of object and its parent object:<br>(($reloadedobj = new Task($db)) && ($reloadedobj->fetch($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetch($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref: 'Parent project not found'
ComputedFormulaDesc=You can enter here a formula using other properties of object or any PHP coding to get a dynamic computed value. You can use any PHP compatible formulas including the "?" condition operator, and following global object: <strong>$db, $conf, $langs, $mysoc, $user, $object</strong>.<br><strong>WARNING</strong>: Only some properties of $object may be available. If you need a properties not loaded, just fetch yourself the object into your formula like in the second example.<br>Using a computed field means you can't enter yourself any value from interface. Also, if there is a syntax error, the formula may return nothing.<br><br>Example of formula:<br>$object->id < 10 ? round($object->id / 2, 2): ($object->id + 2 * $user->id) * (int) substr($mysoc->zip, 1, 2)<br><br>Example to reload object<br>(($reloadedobj = new Societe($db)) && ($reloadedobj->fetchNoCompute($obj->id ? $obj->id: ($obj->rowid ? $obj->rowid: $object->id)) > 0)) ? $reloadedobj->array_options['options_extrafieldkey'] * $reloadedobj->capital / 5: '-1'<br><br>Other example of formula to force load of object and its parent object:<br>(($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref: 'Parent project not found'
Computedpersistent=Store computed field
ComputedpersistentDesc=Computed extra fields will be stored in the database, however, the value will only be recalculated when the object of this field is changed. If the computed field depends on other objects or global data this value might be wrong!!
ExtrafieldParamHelpPassword=Leaving this field blank means this value will be stored without encryption (field must be only hidden with star on screen).<br>Set 'auto' to use the default encryption rule to save password into database (then value read will be the hash only, no way to retrieve original value)