mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-05 17:18:13 +01:00
* NEW webportal member authentication only * FIX missing translation * FIX php-stan errors * FIX php-stan : cryptType is always "auto" ! * FIX remove CrypType * FIX php-stan error * FIX phan error * FIX CI versions * FIX remove wrong fix * FIX pre-commit error * FIX phan error * FIX php-stan error * FIX avoid php warning * FIXME this check is not valid
1312 lines
49 KiB
PHP
1312 lines
49 KiB
PHP
<?php
|
|
/* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
|
* Copyright (C) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
|
|
* Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
|
|
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
|
|
* Copyright (C) 2009-2012 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
|
|
* Copyright (C) 2013 Florian Henry <forian.henry@open-concept.pro>
|
|
* Copyright (C) 2015 Charles-Fr BENKE <charles.fr@benke.fr>
|
|
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
|
* Copyright (C) 2017 Nicolas ZABOURI <info@inovea-conseil.com>
|
|
* Copyright (C) 2018-2022 Frédéric France <frederic.france@netlogic.fr>
|
|
* Copyright (C) 2022 Antonin MARCHAL <antonin@letempledujeu.fr>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \file htdocs/core/class/fieldsmanager.class.php
|
|
* \ingroup core
|
|
* \brief File of class to manage fields
|
|
*/
|
|
|
|
require_once DOL_DOCUMENT_ROOT . '/core/class/fieldinfos.class.php';
|
|
require_once DOL_DOCUMENT_ROOT . '/core/class/fields/commonfield.class.php';
|
|
|
|
|
|
/**
|
|
* Class to manage fields
|
|
*/
|
|
class FieldsManager
|
|
{
|
|
/**
|
|
* @var DoliDB Database handler.
|
|
*/
|
|
public $db;
|
|
|
|
/**
|
|
* @var string Error code (or message)
|
|
*/
|
|
public $error = '';
|
|
|
|
/**
|
|
* @var string[] Array of Error code (or message)
|
|
*/
|
|
public $errors = array();
|
|
|
|
/**
|
|
* @var array<string,string> To store error results of ->validateField()
|
|
*/
|
|
public $validateFieldsErrors = array();
|
|
|
|
/**
|
|
* @var string Path to fields classes
|
|
*/
|
|
public $fieldsPath = '/core/class/fields/';
|
|
|
|
/**
|
|
* @var array<string,CommonField> Field classes cached
|
|
*/
|
|
public static $fieldClasses = array();
|
|
|
|
/**
|
|
* @var array<string,array<string,array{object:array<string,FieldInfos>,extraField:array<string,FieldInfos>}>> Field infos cached (array<element,array<mode,{object:array<fieldKey,fieldInfos>,extraField:array<fieldKey,fieldInfos>}>>)
|
|
*/
|
|
public static $fieldInfos = array();
|
|
|
|
/**
|
|
* @var array<string,bool|int<0,1>>|null Array with boolean of status of groups
|
|
*/
|
|
public $expand_display = array();
|
|
|
|
///**
|
|
// * @var array<string,string> Array of type to label
|
|
// */
|
|
//public static $type2label = array(
|
|
// 'varchar' => 'String1Line',
|
|
// 'text' => 'TextLongNLines',
|
|
// 'html' => 'HtmlText',
|
|
// 'int' => 'Int',
|
|
// 'double' => 'Float',
|
|
// 'date' => 'Date',
|
|
// 'datetime' => 'DateAndTime',
|
|
// 'duration' => 'Duration',
|
|
// //'datetimegmt'=>'DateAndTimeUTC',
|
|
// 'boolean' => 'Boolean',
|
|
// 'price' => 'ExtrafieldPrice',
|
|
// 'pricecy' => 'ExtrafieldPriceWithCurrency',
|
|
// 'phone' => 'ExtrafieldPhone',
|
|
// 'email' => 'ExtrafieldMail',
|
|
// 'url' => 'ExtrafieldUrl',
|
|
// 'ip' => 'ExtrafieldIP',
|
|
// 'icon' => 'Icon',
|
|
// 'password' => 'ExtrafieldPassword',
|
|
// 'radio' => 'ExtrafieldRadio',
|
|
// 'select' => 'ExtrafieldSelect',
|
|
// 'sellist' => 'ExtrafieldSelectList',
|
|
// 'checkbox' => 'ExtrafieldCheckBox',
|
|
// 'chkbxlst' => 'ExtrafieldCheckBoxFromList',
|
|
// 'link' => 'ExtrafieldLink',
|
|
// 'point' => 'ExtrafieldPointGeo',
|
|
// 'multipts' => 'ExtrafieldMultiPointGeo',
|
|
// 'linestrg' => 'ExtrafieldLinestringGeo',
|
|
// 'polygon' => 'ExtrafieldPolygonGeo',
|
|
// 'separate' => 'ExtrafieldSeparator',
|
|
// 'stars' => 'ExtrafieldStars',
|
|
// //'real' => 'ExtrafieldReal',
|
|
//);
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param DoliDB $db Database handler
|
|
* @param Form|null $form Specific form handler
|
|
*/
|
|
public function __construct($db, $form = null)
|
|
{
|
|
$this->db = $db;
|
|
$this->error = '';
|
|
$this->errors = array();
|
|
|
|
if (isset($form)) {
|
|
CommonField::setForm($form);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get field handler for the provided type
|
|
*
|
|
* @param string $type Field type
|
|
* @return CommonField|null
|
|
*/
|
|
public function getFieldClass($type)
|
|
{
|
|
global $hookmanager, $langs;
|
|
|
|
$type = trim($type);
|
|
|
|
if (!isset(self::$fieldClasses[$type])) {
|
|
$field = null;
|
|
$parameters = array(
|
|
'type' => $type,
|
|
// @phan-suppress-next-line PhanPluginConstantVariableNull
|
|
'field' => &$field,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getFieldClass', $parameters, $this); // Note that $object may have been modified by hook
|
|
// @phpstan-ignore-next-line @phan-suppress-next-line PhanPluginConstantVariableNull
|
|
if (isset($field) && is_object($field)) {
|
|
self::$fieldClasses[$type] = $field;
|
|
} else {
|
|
$filename = strtolower($type) . 'field.class.php';
|
|
$classname = ucfirst($type) . 'Field';
|
|
|
|
// Load class file
|
|
dol_include_once(rtrim($this->fieldsPath, '/') . '/' . $filename);
|
|
if (!class_exists($classname)) {
|
|
@include_once DOL_DOCUMENT_ROOT . '/core/class/fields/' . $filename;
|
|
}
|
|
|
|
if (class_exists($classname)) {
|
|
self::$fieldClasses[$type] = new $classname($this->db);
|
|
} else {
|
|
$langs->load("errors");
|
|
$this->errors[] = $langs->trans('ErrorFieldClassNotFoundForClassName', $classname, $type);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
$field = self::$fieldClasses[$type];
|
|
$field->clearErrors();
|
|
|
|
return $field;
|
|
}
|
|
|
|
/**
|
|
* Get all fields handler available
|
|
*
|
|
* @return array<string,CommonField>
|
|
*/
|
|
public function getAllFields()
|
|
{
|
|
// Todo to make
|
|
return self::$fieldClasses;
|
|
}
|
|
|
|
/**
|
|
* clear errors
|
|
*
|
|
* @return void
|
|
*/
|
|
public function clearErrors()
|
|
{
|
|
$this->error = '';
|
|
$this->errors = array();
|
|
}
|
|
|
|
/**
|
|
* Method to output saved errors
|
|
*
|
|
* @param string $separator Separator between each error
|
|
* @return string String with errors
|
|
*/
|
|
public function errorsToString($separator = ', ')
|
|
{
|
|
return $this->error . (is_array($this->errors) ? (!empty($this->error) ? $separator : '') . implode($separator, $this->errors) : '');
|
|
}
|
|
|
|
/**
|
|
* clear validation message result for a field
|
|
*
|
|
* @param string $fieldKey Key of attribute to clear
|
|
* @return void
|
|
*/
|
|
public function clearFieldError($fieldKey)
|
|
{
|
|
$this->error = '';
|
|
unset($this->validateFieldsErrors[$fieldKey]);
|
|
}
|
|
|
|
/**
|
|
* set validation error message a field
|
|
*
|
|
* @param string $fieldKey Key of attribute
|
|
* @param string $msg the field error message
|
|
* @return void
|
|
*/
|
|
public function setFieldError($fieldKey, $msg = '')
|
|
{
|
|
global $langs;
|
|
if (empty($msg)) {
|
|
$msg = $langs->trans("UnknownError");
|
|
}
|
|
|
|
$this->error = $this->validateFieldsErrors[$fieldKey] = $msg;
|
|
}
|
|
|
|
/**
|
|
* get field error message
|
|
*
|
|
* @param string $fieldKey Key of attribute
|
|
* @return string Error message of validation ('' if no error)
|
|
*/
|
|
public function getFieldError($fieldKey)
|
|
{
|
|
if (!empty($this->validateFieldsErrors[$fieldKey])) {
|
|
return $this->validateFieldsErrors[$fieldKey];
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* get field error icon
|
|
*
|
|
* @param string $fieldValidationErrorMsg message to add in tooltip
|
|
* @return string html output
|
|
*/
|
|
public function getFieldErrorIcon($fieldValidationErrorMsg)
|
|
{
|
|
$out = '';
|
|
|
|
if (!empty($fieldValidationErrorMsg) && function_exists('getFieldErrorIcon')) {
|
|
$out .= ' ' . getFieldErrorIcon($fieldValidationErrorMsg);
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Get list of fields infos for the provided mode into X columns
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields ExtraFields handler
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param int $nbColumn Split fields infos into X columns
|
|
* @param array<int,string> $breakKeys Key used for break on each column (ex: array(1 => 'total_ht', ...))
|
|
* @param array<string,mixed> $params Other params
|
|
* @return array{columns:array<int,array<string,FieldInfos>>,hiddenFields:array<string,FieldInfos>} List of fields info by column and hidden
|
|
*/
|
|
public function getAllFieldsInfos(&$object, &$extrafields = null, $mode = 'view', $nbColumn = 2, $breakKeys = array(), $params = array())
|
|
{
|
|
global $hookmanager, $langs;
|
|
|
|
// Get object fields
|
|
$fields = $this->getAllObjectFieldsInfos($object, $mode, $params);
|
|
|
|
// Old sort
|
|
if (!getDolGlobalInt('MAIN_FIELDS_SORT_WITH_EXTRA_FIELDS')) {
|
|
$fields = dol_sort_array($fields, 'position');
|
|
}
|
|
|
|
// Get extra fields
|
|
$fields2 = $this->getAllExtraFieldsInfos($object, $extrafields, $mode, $params);
|
|
$fields = array_merge($fields, $fields2);
|
|
|
|
// New sort
|
|
if (getDolGlobalInt('MAIN_FIELDS_SORT_WITH_EXTRA_FIELDS')) {
|
|
$fields = dol_sort_array($fields, 'position');
|
|
}
|
|
|
|
// Split in columns
|
|
$idxColumn = 1;
|
|
$columns = array();
|
|
$hiddenFields = array();
|
|
$columns[$idxColumn] = array();
|
|
$nbVisibleFields = 0;
|
|
foreach ($fields as $field) {
|
|
if ($field->visible) {
|
|
$nbVisibleFields++;
|
|
}
|
|
}
|
|
$nbFieldsByColumn = ceil($nbVisibleFields / $nbColumn);
|
|
$breakKey = $breakKeys[$idxColumn] ?? '';
|
|
$idxField = 0;
|
|
foreach ($fields as $key => $field) {
|
|
if ($idxColumn < $nbColumn && ((!empty($breakKey) && $key == $breakKey) || (empty($breakKey) && $idxField == $nbFieldsByColumn))) {
|
|
$idxColumn++;
|
|
$idxField = 0;
|
|
$columns[$idxColumn] = array();
|
|
}
|
|
|
|
if ($field->visible) {
|
|
if ($field->type != 'separate') {
|
|
$idxField++;
|
|
}
|
|
|
|
// Add field into column
|
|
$columns[$idxColumn][$key] = $field;
|
|
} else {
|
|
$hiddenFields[$key] = $field;
|
|
}
|
|
}
|
|
|
|
// Add column not created
|
|
for ($idxColumn = 1; $idxColumn <= $nbColumn; $idxColumn++) {
|
|
if (!isset($columns[$idxColumn])) {
|
|
$columns[$idxColumn] = array();
|
|
}
|
|
}
|
|
|
|
$parameters = array(
|
|
'object' => &$object,
|
|
'extrafields' => &$extrafields,
|
|
'mode' => $mode,
|
|
'nbColumn' => $nbColumn,
|
|
'breakKeys' => $breakKeys,
|
|
'params' => $params,
|
|
'columns' => &$columns,
|
|
'hiddenFields' => &$hiddenFields,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getFieldInfosFromObjectField', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
return array(
|
|
'columns' => $columns,
|
|
'hiddenFields' => $hiddenFields,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get list of object fields infos
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return array<string,FieldInfos> List of fields infos
|
|
*/
|
|
public function getAllObjectFieldsInfos(&$object, $mode = 'view', $params = array())
|
|
{
|
|
global $hookmanager;
|
|
|
|
// Get object fields
|
|
$fields = array();
|
|
// @phpstan-ignore-next-line
|
|
if (isset($object->fields) && is_array($object->fields)) {
|
|
$keyPrefix = getDolGlobalInt('MAIN_FIELDS_NEW_OBJECT_KEY_PREFIX') ? 'object_' : '';
|
|
foreach ($object->fields as $key => $field) {
|
|
$fieldInfos = $this->getFieldInfosFromObjectField($object, $key, $mode, $params);
|
|
$fields[$keyPrefix . $key] = $fieldInfos;
|
|
}
|
|
}
|
|
|
|
$parameters = array(
|
|
'object' => &$object,
|
|
'mode' => $mode,
|
|
'params' => $params,
|
|
'fields' => &$fields,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getAllObjectFieldsInfos', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
return $fields;
|
|
}
|
|
|
|
/**
|
|
* Get list of extra fields infos
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields ExtraFields handler
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return array<string,FieldInfos> List of fields infos
|
|
*/
|
|
public function getAllExtraFieldsInfos(&$object, &$extrafields = null, $mode = 'view', $params = array())
|
|
{
|
|
global $hookmanager;
|
|
|
|
// Get extra fields
|
|
$fields = array();
|
|
if (isset($extrafields->attributes[$object->table_element]) && is_array($extrafields->attributes[$object->table_element])) {
|
|
if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label'])) {
|
|
$keyPrefix = 'options_';
|
|
foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) {
|
|
$fieldInfos = $this->getFieldInfosFromExtraField($object, $extrafields, $key, $mode, $params);
|
|
$fields[$keyPrefix . $key] = $fieldInfos;
|
|
}
|
|
}
|
|
}
|
|
|
|
$parameters = array(
|
|
'object' => &$object,
|
|
'extrafields' => &$extrafields,
|
|
'mode' => $mode,
|
|
'params' => $params,
|
|
'fields' => &$fields,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getAllExtraFieldsInfos', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
return $fields;
|
|
}
|
|
|
|
/**
|
|
* Get list of fields infos for the provided mode into X columns
|
|
*
|
|
* @param string $key Field key (begin by object_ for object or options_ for extrafields)
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields ExtraFields handler
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return FieldInfos|null Get field info or null if not found
|
|
*/
|
|
public function getFieldsInfos($key, &$object, &$extrafields = null, $mode = 'view', $params = array())
|
|
{
|
|
global $langs;
|
|
|
|
$fieldInfos = null;
|
|
|
|
$patternObjectPrefix = getDolGlobalInt('MAIN_FIELDS_NEW_OBJECT_KEY_PREFIX') ? 'object_' : '';
|
|
if (preg_match('/^options_(.*)/i', $key, $matches)) {
|
|
$fieldKey = $matches[1];
|
|
$fieldInfos = $this->getFieldInfosFromExtraField($object, $extrafields, $fieldKey, $mode, $params);
|
|
} elseif (preg_match('/^' . $patternObjectPrefix . '(.*)/i', $key, $matches)) {
|
|
$fieldKey = $matches[2];
|
|
$fieldInfos = $this->getFieldInfosFromObjectField($object, $fieldKey, $mode, $params);
|
|
}
|
|
|
|
return $fieldInfos;
|
|
}
|
|
|
|
/**
|
|
* Get field infos from object field infos
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param string $key Field key
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return FieldInfos|null Properties of the field or null if field not found
|
|
*/
|
|
public function getFieldInfosFromObjectField(&$object, $key, $mode = 'view', $params = array())
|
|
{
|
|
global $hookmanager;
|
|
|
|
if (!isset($object->fields[$key])) {
|
|
return null;
|
|
}
|
|
|
|
if (isset(self::$fieldInfos[$object->element][$mode]['object'][$key])) {
|
|
return self::$fieldInfos[$object->element][$mode]['object'][$key];
|
|
}
|
|
|
|
$attributes = $object->fields[$key];
|
|
|
|
$fieldInfos = new FieldInfos();
|
|
$fieldInfos->fieldType = FieldInfos::FIELD_TYPE_OBJECT;
|
|
$fieldInfos->originType = $attributes['type'] ?? '';
|
|
$fieldInfos->size = $attributes['length'] ?? '';
|
|
$fieldInfos->label = $attributes['label'] ?? '';
|
|
$fieldInfos->langFile = $attributes['langfile'] ?? '';
|
|
$fieldInfos->sqlAlias = $attributes['alias'] ?? null;
|
|
$fieldInfos->picto = $attributes['picto'] ?? '';
|
|
$fieldInfos->position = $attributes['position'] ?? 0;
|
|
$fieldInfos->required = ($attributes['notnull'] ?? 0) > 0;
|
|
$fieldInfos->alwaysEditable = !empty($attributes['alwayseditable']);
|
|
$fieldInfos->defaultValue = $attributes['default'] ?? '';
|
|
$fieldInfos->css = $attributes['css'] ?? '';
|
|
$fieldInfos->viewCss = $attributes['cssview'] ?? '';
|
|
$fieldInfos->listCss = $attributes['csslist'] ?? '';
|
|
$fieldInfos->inputPlaceholder = $attributes['placeholder'] ?? '';
|
|
$fieldInfos->help = $attributes['help'] ?? '';
|
|
$fieldInfos->listHelp = $attributes['helplist'] ?? '';
|
|
$fieldInfos->showOnComboBox = !empty($attributes['showoncombobox']);
|
|
$fieldInfos->inputDisabled = !empty($attributes['disabled']);
|
|
$fieldInfos->inputAutofocus = !empty($attributes['autofocusoncreate']) && $mode == 'create';
|
|
$fieldInfos->comment = $attributes['comment'] ?? '';
|
|
$fieldInfos->listTotalizable = !empty($attributes['isameasure']) && $attributes['isameasure'] == 1;
|
|
$fieldInfos->validateField = !empty($attributes['validate']);
|
|
$fieldInfos->copyToClipboard = $attributes['copytoclipboard'] ?? 0;
|
|
$fieldInfos->tdCss = $attributes['tdcss'] ?? '';
|
|
$fieldInfos->multiInput = !empty($attributes['multiinput']);
|
|
$fieldInfos->nameInClass = $attributes['nameinclass'] ?? $key;
|
|
$fieldInfos->nameInTable = $attributes['nameintable'] ?? $key;
|
|
$fieldInfos->getNameUrlParams = $attributes['get_name_url_params'] ?? null;
|
|
$fieldInfos->showOnHeader = !empty($attributes['showonheader']);
|
|
|
|
// TODO set nameinclass = "id" in fields "rowid"
|
|
if ($fieldInfos->nameInClass == 'rowid') {
|
|
$fieldInfos->nameInClass = 'id';
|
|
}
|
|
|
|
$enabled = $attributes['enabled'] ?? '1';
|
|
$visibility = $attributes['visible'] ?? '1';
|
|
$perms = empty($attributes['noteditable']) ? '1' : '0';
|
|
|
|
$this->setCommonFieldInfos($fieldInfos, $object, $extrafields, $key, $mode, $enabled, $visibility, $perms, $params);
|
|
|
|
// Special case that force options and type ($type can be integer, varchar, ...)
|
|
if (!empty($attributes['arrayofkeyval']) && is_array($attributes['arrayofkeyval'])) {
|
|
$fieldInfos->options = $attributes['arrayofkeyval'];
|
|
// Special case that prevent to force $type to have multiple input @phan-suppress-next-line PhanTypeMismatchProperty
|
|
if (!$fieldInfos->multiInput) {
|
|
$fieldInfos->type = (($fieldInfos->type == 'checkbox') ? $fieldInfos->type : 'select');
|
|
}
|
|
}
|
|
|
|
$parameters = array(
|
|
'object' => &$object,
|
|
'key' => $key,
|
|
'mode' => $mode,
|
|
'fieldInfos' => &$fieldInfos,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getFieldInfosFromObjectField', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
self::$fieldInfos[$object->element][$mode]['object'][$key] = $fieldInfos;
|
|
return $fieldInfos;
|
|
}
|
|
|
|
/**
|
|
* Get field infos from extra field infos
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields Extrafields handler
|
|
* @param string $key Field key
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return FieldInfos|null Properties of the field or null if not found
|
|
*/
|
|
public function getFieldInfosFromExtraField(&$object, &$extrafields, $key, $mode = 'view', $params = array())
|
|
{
|
|
global $hookmanager;
|
|
|
|
if (!isset($extrafields->attributes[$object->table_element]['label'][$key])) {
|
|
return null;
|
|
}
|
|
|
|
if (isset(self::$fieldInfos[$object->element][$mode]['extraField'][$key])) {
|
|
return self::$fieldInfos[$object->element][$mode]['extraField'][$key];
|
|
}
|
|
|
|
$attributes = $extrafields->attributes[$object->table_element];
|
|
|
|
$fieldInfos = new FieldInfos();
|
|
$fieldInfos->fieldType = FieldInfos::FIELD_TYPE_EXTRA_FIELD;
|
|
$fieldInfos->originType = $attributes['type'][$key] ?? '';
|
|
$fieldInfos->label = $attributes['label'][$key] ?? '';
|
|
$fieldInfos->position = $attributes['pos'][$key] ?? 0;
|
|
$fieldInfos->required = !empty($attributes['required'][$key]);
|
|
$fieldInfos->defaultValue = $attributes['default'][$key] ?? '';
|
|
$fieldInfos->css = $attributes['css'][$key] ?? '';
|
|
$fieldInfos->help = $attributes['help'][$key] ?? '';
|
|
$fieldInfos->size = $attributes['size'][$key] ?? '';
|
|
$fieldInfos->computed = $attributes['computed'][$key] ?? '';
|
|
$fieldInfos->unique = !empty($attributes['unique'][$key]);
|
|
$fieldInfos->alwaysEditable = !empty($attributes['alwayseditable'][$key]);
|
|
$fieldInfos->emptyOnClone = !empty($attributes['emptyonclone'][$key]);
|
|
$fieldInfos->langFile = $attributes['langfile'][$key] ?? '';
|
|
$fieldInfos->printable = !empty($attributes['printable'][$key]);
|
|
$fieldInfos->aiPrompt = $attributes['aiprompt'][$key] ?? '';
|
|
$fieldInfos->viewCss = $attributes['cssview'][$key] ?? '';
|
|
$fieldInfos->listCss = $attributes['csslist'][$key] ?? '';
|
|
$fieldInfos->listTotalizable = !empty($attributes['totalizable'][$key]);
|
|
$fieldInfos->options = array_diff_assoc($attributes['param'][$key]['options'] ?? array(), array('' => null)); // For remove case when not defined
|
|
$fieldInfos->nameInClass = $key;
|
|
$fieldInfos->nameInTable = $key;
|
|
|
|
$enabled = $attributes['enabled'][$key] ?? '1';
|
|
$visibility = $attributes['list'][$key] ?? '1';
|
|
$perms = $attributes['perms'][$key] ?? null;
|
|
|
|
$this->setCommonFieldInfos($fieldInfos, $object, $extrafields, $key, $mode, $enabled, $visibility, $perms, $params);
|
|
|
|
$parameters = array(
|
|
'object' => &$object,
|
|
'extraFields' => &$extrafields,
|
|
'key' => $key,
|
|
'mode' => $mode,
|
|
'fieldInfos' => &$fieldInfos,
|
|
);
|
|
|
|
$hookmanager->executeHooks('getFieldInfosFromExtraField', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
self::$fieldInfos[$object->element][$mode]['extraField'][$key] = $fieldInfos;
|
|
return $fieldInfos;
|
|
}
|
|
|
|
/**
|
|
* Set common field infos
|
|
*
|
|
* @param FieldInfos $fieldInfos Field infos to set with common infos
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields Extrafields handler
|
|
* @param string $key Field key
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param string $enabled Condition when the field must be managed (Example: 1 or 'getDolGlobalInt("MY_SETUP_PARAM")' or 'isModEnabled("multicurrency")' ...)
|
|
* @param string $visibility Condition when the field must be visible (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form (not create). 5=Visible on list and view form (not create/not update). 6=visible on list and update/view form (not create). Using a negative value means field is not shown by default on list but can be selected for viewing)
|
|
* @param string $perms Condition when the field must be editable
|
|
* @param array<string,mixed> $params Other params
|
|
* @return void
|
|
*/
|
|
public function setCommonFieldInfos(&$fieldInfos, &$object, &$extrafields, $key, $mode = 'view', $enabled = '1', $visibility = '', $perms = null, $params = array())
|
|
{
|
|
global $user;
|
|
|
|
$fieldInfos->object = &$object;
|
|
$fieldInfos->mode = preg_replace('/[^a-z0-9_]/i', '', $mode);
|
|
$fieldInfos->type = $fieldInfos->originType;
|
|
$fieldInfos->key = $key;
|
|
$fieldInfos->otherParams = $params;
|
|
|
|
if (preg_match('/^(integer|link):(.*):(.*):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] . ':' . $reg[5] => 'N');
|
|
$fieldInfos->type = 'link';
|
|
} elseif (preg_match('/^(integer|link):(.*):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] => 'N');
|
|
$fieldInfos->type = 'link';
|
|
} elseif (preg_match('/^(integer|link):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] . ($reg[1] == 'User' ? ':#getnomurlparam1=-1' : '') => 'N');
|
|
$fieldInfos->type = 'link';
|
|
} elseif (preg_match('/^(sellist):(.*):(.*):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] . ':' . $reg[5] => 'N');
|
|
$fieldInfos->type = 'sellist';
|
|
} elseif (preg_match('/^(sellist):(.*):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] => 'N');
|
|
$fieldInfos->type = 'sellist';
|
|
} elseif (preg_match('/^(sellist):(.*):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[2] . ':' . $reg[3] => 'N');
|
|
$fieldInfos->type = 'sellist';
|
|
} elseif (preg_match('/^chkbxlst:(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array($reg[1] => 'N');
|
|
$fieldInfos->type = 'chkbxlst';
|
|
} elseif (preg_match('/varchar\((\d+)\)/', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array();
|
|
$fieldInfos->type = 'varchar';
|
|
$fieldInfos->size = $reg[1];
|
|
$fieldInfos->maxLength = (int) $reg[1];
|
|
} elseif (preg_match('/varchar/', $fieldInfos->originType)) {
|
|
$fieldInfos->options = array();
|
|
$fieldInfos->type = 'varchar';
|
|
} elseif (preg_match('/stars\((\d+)\)/', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->options = array();
|
|
$fieldInfos->type = 'stars';
|
|
$fieldInfos->size = $reg[1];
|
|
} elseif (preg_match('/integer/', $fieldInfos->originType)) {
|
|
$fieldInfos->type = 'int';
|
|
} elseif ($fieldInfos->originType == 'mail') {
|
|
$fieldInfos->type = 'email';
|
|
} elseif (preg_match('/^(text):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->type = 'text';
|
|
$fieldInfos->getPostCheck = $reg[2];
|
|
} elseif (preg_match('/^(html):(.*)/i', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->type = 'html';
|
|
$fieldInfos->getPostCheck = $reg[2];
|
|
} elseif (preg_match('/^double\(([0-9]+,[0-9]+)\)/', $fieldInfos->originType, $reg)) {
|
|
$fieldInfos->type = 'double';
|
|
$fieldInfos->size = $reg[1];
|
|
}
|
|
|
|
// Set visibility
|
|
$visibility = (int) dol_eval((string) $visibility, 1, 1, '2');
|
|
$absVisibility = abs($visibility);
|
|
$enabled = (int) dol_eval((string) $enabled, 1, 1, '2');
|
|
$fieldInfos->visible = true;
|
|
if (empty($visibility) ||
|
|
empty($enabled) ||
|
|
($mode == 'create' && !in_array($absVisibility, array(1, 3, 6))) ||
|
|
($mode == 'edit' && !in_array($absVisibility, array(1, 3, 4))) ||
|
|
($mode == 'view' && (!in_array($absVisibility, array(1, 3, 4, 5)) || $fieldInfos->showOnHeader)) ||
|
|
($mode == 'list' && $absVisibility == 3)
|
|
) {
|
|
$fieldInfos->visible = false;
|
|
}
|
|
|
|
// Set edit perms
|
|
if (isset($perms)) {
|
|
$perms = (int) dol_eval((string) $perms, 1, 1, '2');
|
|
} else {
|
|
//TODO Improve element and rights detection
|
|
$mappingKeyForPerm = array(
|
|
'fichinter' => 'ficheinter',
|
|
'product' => 'produit',
|
|
'project' => 'projet',
|
|
'order_supplier' => 'supplier_order',
|
|
'invoice_supplier' => 'supplier_invoice',
|
|
'shipping' => 'expedition',
|
|
'productlot' => 'stock',
|
|
'facturerec' => 'facture',
|
|
'mo' => 'mrp',
|
|
'salary' => 'salaries',
|
|
'member' => 'adherent',
|
|
);
|
|
$keyForPerm = $mappingKeyForPerm[$object->element] ?? $object->element;
|
|
|
|
$perms = false;
|
|
if (isset($user->rights->$keyForPerm)) {
|
|
$perms = $user->hasRight($keyForPerm, 'creer') || $user->hasRight($keyForPerm, 'create') || $user->hasRight($keyForPerm, 'write');
|
|
}
|
|
if ($object->element == 'order_supplier' && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) {
|
|
$perms = $user->hasRight('fournisseur', 'commande', 'creer');
|
|
} elseif ($object->element == 'invoice_supplier' && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) {
|
|
$perms = $user->hasRight('fournisseur', 'facture', 'creer');
|
|
} elseif ($object->element == 'delivery') {
|
|
$perms = $user->hasRight('expedition', 'delivery', 'creer');
|
|
} elseif ($object->element == 'contact') {
|
|
$perms = $user->hasRight('societe', 'contact', 'creer');
|
|
}
|
|
}
|
|
// Manage always editable of extra field
|
|
$isDraft = ((isset($object->statut) && $object->statut == 0) || (isset($object->status) && $object->status == 0));
|
|
if ($mode == 'view' && !$isDraft && !$fieldInfos->alwaysEditable) {
|
|
$perms = false;
|
|
}
|
|
// Case visible only in view so not editable
|
|
if ($mode == 'view' && $absVisibility == 5) {
|
|
$perms = false;
|
|
}
|
|
// Case field computed
|
|
if (!empty($fieldInfos->computed)) {
|
|
$perms = false;
|
|
}
|
|
$fieldInfos->editable = !empty($perms);
|
|
|
|
// Set list info 'checked'
|
|
$fieldInfos->listChecked = $mode == 'list' && $visibility > 0;
|
|
}
|
|
|
|
/**
|
|
* Set all values of the object (with extra field) from POST
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields Extrafields handler
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return int Result <0 if KO, >0 if OK
|
|
*/
|
|
public function setFieldValuesFromPost(&$object, &$extrafields, $keyPrefix = '', $keySuffix = '', $mode = 'view', $params = array())
|
|
{
|
|
$result = $this->setObjectFieldValuesFromPost($object, $keyPrefix, $keySuffix, $mode, $params);
|
|
$result2 = $this->setExtraFieldValuesFromPost($object, $extrafields, $keyPrefix, $keySuffix, $mode, $params);
|
|
|
|
return $result > 0 && $result2 > 0 ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Set all object values of the object from POST
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return int Result <0 if KO, >0 if OK
|
|
*/
|
|
public function setObjectFieldValuesFromPost(&$object, $keyPrefix = '', $keySuffix = '', $mode = 'view', $params = array())
|
|
{
|
|
$fields = $this->getAllObjectFieldsInfos($object, $mode, $params);
|
|
|
|
$error = 0;
|
|
foreach ($fields as $fieldKey => $fieldInfos) {
|
|
$check = true;
|
|
$key = $fieldInfos->nameInClass ?? $fieldInfos->key;
|
|
if ($fieldInfos->visible) {
|
|
$check = $this->verifyPostFieldValue($fieldInfos, $fieldKey, $keyPrefix, $keySuffix);
|
|
}
|
|
if ($check) {
|
|
$object->$key = $this->getPostFieldValue($fieldInfos, $fieldKey, $object->$key, $keyPrefix, $keySuffix);
|
|
}
|
|
if (!$fieldInfos->visible) {
|
|
$check = $this->verifyFieldValue($fieldInfos, $fieldKey, $object->$key);
|
|
}
|
|
if (!$check) {
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
return $error ? -1 : 1;
|
|
}
|
|
|
|
/**
|
|
* Set all extra field values of the object from POST
|
|
*
|
|
* @param CommonObject $object Object handler
|
|
* @param ExtraFields $extrafields Extrafields handler
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $mode Get the fields infos for the provided mode ('create', 'edit', 'view', 'list')
|
|
* @param array<string,mixed> $params Other params
|
|
* @return int Result <0 if KO, >0 if OK
|
|
*/
|
|
public function setExtraFieldValuesFromPost(&$object, &$extrafields, $keyPrefix = '', $keySuffix = '', $mode = 'view', $params = array())
|
|
{
|
|
$fields = $this->getAllExtraFieldsInfos($object, $extrafields, $mode, $params);
|
|
|
|
$error = 0;
|
|
foreach ($fields as $fieldKey => $fieldInfos) {
|
|
$check = true;
|
|
$key = 'options_' . ($fieldInfos->nameInClass ?? $fieldInfos->key);
|
|
if ($fieldInfos->visible) {
|
|
$check = $this->verifyPostFieldValue($fieldInfos, $fieldKey, $keyPrefix, $keySuffix);
|
|
}
|
|
if ($check) {
|
|
$object->array_options[$key] = $this->getPostFieldValue($fieldInfos, $fieldKey, $object->array_options[$key], $keyPrefix, $keySuffix);
|
|
}
|
|
if (!$fieldInfos->visible) {
|
|
$check = $this->verifyFieldValue($fieldInfos, $fieldKey, $object->array_options[$key]);
|
|
}
|
|
if (!$check) {
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
return $error ? -1 : 1;
|
|
}
|
|
|
|
/**
|
|
* Verify if the field value is valid
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of attribute
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @return bool
|
|
*/
|
|
public function verifyPostFieldValue($fieldInfos, $key, $keyPrefix = '', $keySuffix = '')
|
|
{
|
|
global $hookmanager;
|
|
|
|
$result = true;
|
|
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 1 || getDolGlobalString('MAIN_ACTIVATE_VALIDATION_RESULT')) {
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
);
|
|
|
|
$reshook = $hookmanager->executeHooks('verifyPostFieldValue', $parameters, $this); // Note that $object may have been modified by hook
|
|
if ($reshook > 0) {
|
|
return (bool) $hookmanager->resPrint;
|
|
}
|
|
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$this->clearFieldError($key);
|
|
$result = $field->verifyPostFieldValue($fieldInfos, $key, $keyPrefix, $keySuffix);
|
|
if (!$result) {
|
|
$this->setFieldError($key, CommonField::$validator->error);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Verify if the field value is valid
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of field
|
|
* @param mixed $value Value to check (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @return bool
|
|
*/
|
|
public function verifyFieldValue($fieldInfos, $key, $value)
|
|
{
|
|
global $hookmanager;
|
|
|
|
$result = true;
|
|
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 1 || getDolGlobalString('MAIN_ACTIVATE_VALIDATION_RESULT')) {
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => $value,
|
|
);
|
|
|
|
$reshook = $hookmanager->executeHooks('verifyFieldValue', $parameters, $this); // Note that $object may have been modified by hook
|
|
if ($reshook > 0) {
|
|
return (bool) $hookmanager->resPrint;
|
|
}
|
|
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$this->clearFieldError($key);
|
|
$result = $field->verifyFieldValue($fieldInfos, $key, $value);
|
|
if (!$result) {
|
|
$this->setFieldError($key, CommonField::$validator->error);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get field value from GET/POST
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of field
|
|
* @param mixed $defaultValue Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @return mixed
|
|
*/
|
|
public function getPostFieldValue($fieldInfos, $key, $defaultValue = null, $keyPrefix = '', $keySuffix = '')
|
|
{
|
|
global $hookmanager;
|
|
|
|
$value = '';
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => &$value,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
);
|
|
|
|
$reshook = $hookmanager->executeHooks('getPostFieldValue', $parameters, $this); // Note that $object may have been modified by hook
|
|
if ($reshook > 0) {
|
|
return $value;
|
|
}
|
|
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$value = $field->getPostFieldValue($fieldInfos, $key, $defaultValue, $keyPrefix, $keySuffix);
|
|
} else {
|
|
$value = $defaultValue;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Get search field value from GET/POST
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of field
|
|
* @param mixed $defaultValue Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @return mixed
|
|
*/
|
|
public function getPostSearchFieldValue($fieldInfos, $key, $defaultValue = null, $keyPrefix = '', $keySuffix = '')
|
|
{
|
|
global $hookmanager;
|
|
|
|
$value = '';
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => &$value,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
);
|
|
|
|
$reshook = $hookmanager->executeHooks('getPostSearchFieldValue', $parameters, $this); // Note that $object may have been modified by hook
|
|
if ($reshook > 0) {
|
|
return $value;
|
|
}
|
|
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$value = $field->getPostSearchFieldValue($fieldInfos, $key, $defaultValue, $keyPrefix, $keySuffix);
|
|
} else {
|
|
$value = $defaultValue;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Return HTML string to put an input search field into a page
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of attribute
|
|
* @param mixed $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $moreCss Value for css to define style/length of field.
|
|
* @param string $moreAttrib To add more attributes on html input tag
|
|
* @param int<0,1> $noNewButton Force to not show the new button on field that are links to object
|
|
* @return string
|
|
*/
|
|
public function printInputSearchField($fieldInfos, $key, $value, $keyPrefix = '', $keySuffix = '', $moreCss = '', $moreAttrib = '', $noNewButton = 0)
|
|
{
|
|
global $hookmanager;
|
|
|
|
$overwrite_before = '';
|
|
$overwrite_content = '';
|
|
$overwrite_after = '';
|
|
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => &$value,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
'moreCss' => $moreCss,
|
|
'moreAttrib' => $moreAttrib,
|
|
'noNewButton' => $noNewButton,
|
|
'overwrite_before' => &$overwrite_before,
|
|
'overwrite_content' => &$overwrite_content,
|
|
'overwrite_after' => &$overwrite_after,
|
|
);
|
|
|
|
$hookmanager->executeHooks('printInputSearchField', $parameters, $this); // Note that $this may have been modified by hook
|
|
|
|
if (!empty($fieldInfos->computed)) {
|
|
return '';
|
|
}
|
|
|
|
$out = $overwrite_before;
|
|
if (empty($overwrite_content)) {
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$moreCss = $field->getInputCss($fieldInfos, $moreCss);
|
|
|
|
$out .= $field->printInputSearchField($fieldInfos, $key, $value, $keyPrefix, $keySuffix, $moreCss, $moreAttrib);
|
|
} else {
|
|
$out .= $this->errorsToString();
|
|
}
|
|
} else {
|
|
$out .= $overwrite_content;
|
|
}
|
|
$out .= $overwrite_after;
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Return HTML string to put an input field into a page
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of attribute
|
|
* @param mixed $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $moreCss Value for css to define style/length of field.
|
|
* @param string $moreAttrib To add more attributes on html input tag
|
|
* @param int<0,1> $noNewButton Force to not show the new button on field that are links to object
|
|
* @return string
|
|
*/
|
|
public function printInputField($fieldInfos, $key, $value, $keyPrefix = '', $keySuffix = '', $moreCss = '', $moreAttrib = '', $noNewButton = 0)
|
|
{
|
|
global $hookmanager, $langs;
|
|
|
|
$overwrite_before = '';
|
|
$overwrite_content = '';
|
|
$overwrite_after = '';
|
|
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => &$value,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
'moreCss' => $moreCss,
|
|
'moreAttrib' => $moreAttrib,
|
|
'noNewButton' => $noNewButton,
|
|
'overwrite_before' => &$overwrite_before,
|
|
'overwrite_content' => &$overwrite_content,
|
|
'overwrite_after' => &$overwrite_after,
|
|
);
|
|
|
|
$hookmanager->executeHooks('printInputField', $parameters, $this); // Note that $this may have been modified by hook
|
|
|
|
if (!empty($fieldInfos->computed)) {
|
|
return '<span class="opacitymedium">' . $langs->trans("AutomaticallyCalculated") . '</span>';
|
|
}
|
|
|
|
if (!$fieldInfos->editable) {
|
|
return $this->printOutputField($fieldInfos, $key, $value, $keyPrefix, $keySuffix, $moreCss, $moreAttrib);
|
|
}
|
|
|
|
// Get validation error
|
|
$fieldValidationErrorMsg = $this->getFieldError($key);
|
|
|
|
$out = $overwrite_before;
|
|
if (empty($overwrite_content)) {
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$moreCss = $field->getInputCss($fieldInfos, $moreCss);
|
|
|
|
// Add validation state class
|
|
if (!empty($fieldValidationErrorMsg)) {
|
|
$moreCss .= ' --error'; // the -- is use as class state in css : .--error can't be be defined alone it must be define with another class like .my-class.--error or input.--error
|
|
} else {
|
|
$moreCss .= ' --success'; // the -- is use as class state in css : .--success can't be be defined alone it must be define with another class like .my-class.--success or input.--success
|
|
}
|
|
|
|
$out .= $field->printInputField($fieldInfos, $key, $value, $keyPrefix, $keySuffix, $moreCss, $moreAttrib);
|
|
} else {
|
|
$out .= $this->errorsToString();
|
|
}
|
|
} else {
|
|
$out .= $overwrite_content;
|
|
}
|
|
if (empty($overwrite_after)) {
|
|
// Display error message for field
|
|
$out .= $this->getFieldErrorIcon($fieldValidationErrorMsg);
|
|
} else {
|
|
$out .= $overwrite_after;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Return HTML string to show a field into a page
|
|
*
|
|
* @param FieldInfos $fieldInfos Properties of the field
|
|
* @param string $key Key of attribute
|
|
* @param mixed $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
|
|
* @param string $keyPrefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $keySuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
|
|
* @param string $moreCss Value for css to define style/length of field.
|
|
* @param string $moreAttrib To add more attributes on html input tag
|
|
* @return string
|
|
*/
|
|
public function printOutputField($fieldInfos, $key, $value, $keyPrefix = '', $keySuffix = '', $moreCss = '', $moreAttrib = '')
|
|
{
|
|
global $hookmanager;
|
|
|
|
$overwrite_before = '';
|
|
$overwrite_content = '';
|
|
$overwrite_after = '';
|
|
|
|
$parameters = array(
|
|
'fieldInfos' => &$fieldInfos,
|
|
'key' => $key,
|
|
'value' => &$value,
|
|
'keyPrefix' => $keyPrefix,
|
|
'keySuffix' => $keySuffix,
|
|
'moreCss' => $moreCss,
|
|
'moreAttrib' => $moreAttrib,
|
|
'overwrite_before' => &$overwrite_before,
|
|
'overwrite_content' => &$overwrite_content,
|
|
'overwrite_after' => &$overwrite_after,
|
|
);
|
|
|
|
$hookmanager->executeHooks('printOutputField', $parameters, $this); // Note that $object may have been modified by hook
|
|
|
|
$out = $overwrite_before;
|
|
if (empty($overwrite_content)) {
|
|
$this->clearErrors();
|
|
$field = $this->getFieldClass($fieldInfos->type);
|
|
if (isset($field)) {
|
|
$moreCss = $field->getInputCss($fieldInfos, $moreCss);
|
|
|
|
$out .= $field->printOutputField($fieldInfos, $key, $value, $keyPrefix, $keySuffix, $moreCss, $moreAttrib);
|
|
} else {
|
|
$out .= $this->errorsToString();
|
|
}
|
|
} else {
|
|
$out .= $overwrite_content;
|
|
}
|
|
$out .= $overwrite_after;
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Return HTML string to print separator field
|
|
*
|
|
* @param string $key Key of attribute
|
|
* @param object $object Object
|
|
* @param int $colspan Value of colspan to use (it must include the first column with title)
|
|
* @param string $display_type "card" for form display, "line" for document line display
|
|
* @param string $mode Show output ('view') or input ('create' or 'edit') for field
|
|
* @return string HTML code with line for separator
|
|
*/
|
|
public function printSeparator($key, &$object, $colspan = 2, $display_type = 'card', $mode = 'view')
|
|
{
|
|
global $conf, $langs;
|
|
|
|
// TODO to adapt for field and not extra fields only
|
|
$out = '';
|
|
|
|
/*$tagtype = 'tr';
|
|
$tagtype_dyn = 'td';
|
|
|
|
if ($display_type == 'line') {
|
|
$tagtype = 'div';
|
|
$tagtype_dyn = 'span';
|
|
$colspan = 0;
|
|
}
|
|
|
|
$extrafield_param = $this->attributes[$object->table_element]['param'][$key];
|
|
$extrafield_param_list = array();
|
|
if (!empty($extrafield_param) && is_array($extrafield_param)) {
|
|
$extrafield_param_list = array_keys($extrafield_param['options']);
|
|
}
|
|
|
|
// Set $extrafield_collapse_display_value (do we have to collapse/expand the group after the separator)
|
|
$extrafield_collapse_display_value = -1;
|
|
$expand_display = false;
|
|
if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) {
|
|
$extrafield_collapse_display_value = intval($extrafield_param_list[0]);
|
|
$expand_display = ((isset($_COOKIE['DOLUSER_COLLAPSE_' . $object->table_element . '_extrafields_' . $key]) || GETPOSTINT('ignorecollapsesetup')) ? (!empty($_COOKIE['DOLUSER_COLLAPSE_' . $object->table_element . '_extrafields_' . $key])) : !($extrafield_collapse_display_value == 2));
|
|
}
|
|
$disabledcookiewrite = 0;
|
|
if ($mode == 'create') {
|
|
// On create mode, force separator group to not be collapsible
|
|
$extrafield_collapse_display_value = 1;
|
|
$expand_display = true; // We force group to be shown expanded
|
|
$disabledcookiewrite = 1; // We keep status of group unchanged into the cookie
|
|
}
|
|
|
|
$out = '<' . $tagtype . ' id="trextrafieldseparator' . $key . (!empty($object->id) ? '_' . $object->id : '') . '" class="trextrafieldseparator trextrafieldseparator' . $key . (!empty($object->id) ? '_' . $object->id : '') . '">';
|
|
$out .= '<' . $tagtype_dyn . ' ' . (!empty($colspan) ? 'colspan="' . $colspan . '"' : '') . '>';
|
|
// Some js code will be injected here to manage the collapsing of fields
|
|
// Output the picto
|
|
$out .= '<span class="' . ($extrafield_collapse_display_value ? 'cursorpointer ' : '') . ($extrafield_collapse_display_value == 0 ? 'fas fa-square opacitymedium' : 'far fa-' . (($expand_display ? 'minus' : 'plus') . '-square')) . '"></span>';
|
|
$out .= ' ';
|
|
$out .= '<strong>';
|
|
$out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
|
|
$out .= '</strong>';
|
|
$out .= '</' . $tagtype_dyn . '>';
|
|
$out .= '</' . $tagtype . '>';
|
|
|
|
$collapse_group = $key . (!empty($object->id) ? '_' . $object->id : '');
|
|
//$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:'');
|
|
|
|
if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
|
|
// Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
|
|
$this->expand_display[$collapse_group] = $expand_display;
|
|
|
|
if (!empty($conf->use_javascript_ajax)) {
|
|
$out .= '<!-- Add js script to manage the collapse/uncollapse of extrafields separators ' . $key . ' -->' . "\n";
|
|
$out .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
|
|
$out .= 'jQuery(document).ready(function(){' . "\n";
|
|
if (empty($disabledcookiewrite)) {
|
|
if (!$expand_display) {
|
|
$out .= ' console.log("Inject js for the collapsing of extrafield ' . $key . ' - hide");' . "\n";
|
|
$out .= ' jQuery(".trextrafields_collapse' . $collapse_group . '").hide();' . "\n";
|
|
} else {
|
|
$out .= ' console.log("Inject js for collapsing of extrafield ' . $key . ' - keep visible and set cookie");' . "\n";
|
|
$out .= ' document.cookie = "DOLUSER_COLLAPSE_' . $object->table_element . '_extrafields_' . $key . '=1; path=' . $_SERVER["PHP_SELF"] . '"' . "\n";
|
|
}
|
|
}
|
|
$out .= ' jQuery("#trextrafieldseparator' . $key . (!empty($object->id) ? '_' . $object->id : '') . '").click(function(){' . "\n";
|
|
$out .= ' console.log("We click on collapse/uncollapse to hide/show .trextrafields_collapse' . $collapse_group . '");' . "\n";
|
|
$out .= ' jQuery(".trextrafields_collapse' . $collapse_group . '").toggle(100, function(){' . "\n";
|
|
$out .= ' if (jQuery(".trextrafields_collapse' . $collapse_group . '").is(":hidden")) {' . "\n";
|
|
$out .= ' jQuery("#trextrafieldseparator' . $key . (!empty($object->id) ? '_' . $object->id : '') . ' ' . $tagtype_dyn . ' span").addClass("fa-plus-square").removeClass("fa-minus-square");' . "\n";
|
|
$out .= ' document.cookie = "DOLUSER_COLLAPSE_' . $object->table_element . '_extrafields_' . $key . '=0; path=' . $_SERVER["PHP_SELF"] . '"' . "\n";
|
|
$out .= ' } else {' . "\n";
|
|
$out .= ' jQuery("#trextrafieldseparator' . $key . (!empty($object->id) ? '_' . $object->id : '') . ' ' . $tagtype_dyn . ' span").addClass("fa-minus-square").removeClass("fa-plus-square");' . "\n";
|
|
$out .= ' document.cookie = "DOLUSER_COLLAPSE_' . $object->table_element . '_extrafields_' . $key . '=1; path=' . $_SERVER["PHP_SELF"] . '"' . "\n";
|
|
$out .= ' }' . "\n";
|
|
$out .= ' });' . "\n";
|
|
$out .= ' });' . "\n";
|
|
$out .= '});' . "\n";
|
|
$out .= '</script>' . "\n";
|
|
}
|
|
} else {
|
|
$this->expand_display[$collapse_group] = 1;
|
|
}*/
|
|
|
|
return $out;
|
|
}
|
|
}
|