2
0
forked from Wavyzz/dolibarr

Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur
2025-04-24 17:17:32 +02:00
25 changed files with 472 additions and 177 deletions

View File

@@ -7182,18 +7182,6 @@ parameters:
count: 1
path: ../../../htdocs/core/boxes/box_customers_outstanding_bill_reached.php
-
message: '#^Call to function is_array\(\) with array\<''contacts''\|''contracts''\|''customers''\|''dolresource''\|''donations''\|''expensereports''\|''holidays''\|''interventions''\|''invoices''\|''members''\|''orders''\|''products''\|''projects''\|''proposals''\|''prospects''\|''services''\|''supplier_invoices''\|''supplier_orders''\|''supplier_proposals''\|''suppliers''\|''ticket''\|''users'', non\-falsy\-string\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/core/boxes/box_dolibarr_state_board.php
-
message: '#^Call to function method_exists\(\) with Adherent\|Client\|Commande\|CommandeFournisseur\|Contact\|Contrat\|Dolresource\|Don\|ExpenseReport\|Facture\|FactureFournisseur\|Fichinter\|Fournisseur\|Holiday\|Product\|Project\|Propal\|SupplierProposal\|Ticket\|User and ''loadStateBoard'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/core/boxes/box_dolibarr_state_board.php
-
message: '#^Constructor of class box_dolibarr_state_board has an unused parameter \$param\.$#'
identifier: constructor.unusedParameter

View File

@@ -396,7 +396,7 @@ if ($action == 'create') {
print '<td><input type="text" class="minwidth300" name="picto" value="'.dol_escape_htmltag(GETPOST("picto", 'alphanohtml')).'"></td><td>'.$langs->trans('Example').': fa-globe-americas';
print '<span class="opacitymedium small">';
print ' &nbsp; &nbsp; ';
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?displayMode=icon-only#img-picto-section-list', '', '');
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only#img-picto-section-list', '', '');
print '</span>';
print '</td></tr>';
@@ -529,7 +529,7 @@ if ($action == 'create') {
print '<td><input type="text" class="minwidth300" name="picto" value="'.dol_escape_htmltag($menu->prefix).'"></td><td>'.$langs->trans('Example').': fa-globe-americas';
print '<span class="opacitymedium small">';
print ' &nbsp; &nbsp; ';
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?displayMode=icon-only#img-picto-section-list', '', '');
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only#img-picto-section-list', '', '');
print '</span>';
print '</td></tr>';

View File

@@ -297,7 +297,7 @@ class Documentation
/**
* Output sidebar
*
* @return void
* @return void
*/
public function showSidebar()
{

View File

@@ -57,11 +57,18 @@ $switchDisplayLink = dol_buildpath($documentation->baseUrl . '/components/icons.
$switchDisplayLinkIcon = $displayMode == 'kanban' ? 'fa fa-th' : 'fa fa-th-list';
// Output sidebar
$documentation->showSidebar(); ?>
if (!GETPOST('hidenavmenu')) {
$documentation->showSidebar();
}
?>
<div class="doc-wrapper">
<?php $documentation->showBreadCrumb(); ?>
<?php
if (!GETPOST('hidenavmenu')) {
$documentation->showBreadCrumb();
}
?>
<div class="doc-content-wrapper">

View File

@@ -1482,7 +1482,7 @@ class Setup extends DolibarrApi
}
$alwayseditable = $request_data['alwayseditable'];
$default_value = $request_data['default_value'];
$default_value = $request_data['default'];
$totalizable = $request_data['totalizable'];
$printable = $request_data['printable'];
$required = $request_data['required'];
@@ -1567,7 +1567,7 @@ class Setup extends DolibarrApi
}
$alwayseditable = $request_data['alwayseditable'];
$default_value = $request_data['default_value'];
$default_value = $request_data['default'];
$totalizable = $request_data['totalizable'];
$printable = $request_data['printable'];
$required = $request_data['required'];

View File

@@ -615,6 +615,8 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$object->error .= '<br> - ' . $langs->trans('ErrorResourceUseInEvent', $obj->r_ref, $obj->ac_label . ' [' . $obj->ac_id . ']');
}
$object->errors[] = $object->error;
setEventMessages($object->error, null, 'errors');
}
$db->free($resql);
}
@@ -628,9 +630,12 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
unset($_SESSION['assignedtoresource']);
// Category association
$categories = GETPOST('categories', 'array');
$object->setCategories($categories);
if (!$error) {
$categories = GETPOST('categories', 'array');
$object->setCategories($categories);
}
unset($_SESSION['assignedtouser']);
@@ -639,7 +644,7 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
}
// Create reminders
if ($addreminder == 'on') {
if (!$error && $addreminder == 'on') {
$actionCommReminder = new ActionCommReminder($db);
$dateremind = dol_time_plus_duree($datep, -1 * $offsetvalue, $offsetunit);
@@ -685,6 +690,7 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$db->commit();
}
// if (!empty($backtopage)) {
// dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
// header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
@@ -710,7 +716,7 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$donotclearsession = 1;
}
if ($eventisrecurring) {
if (!$error && $eventisrecurring) {
$dayoffset = 0;
$monthoffset = 0;
// We set first date of recurrence and offsets
@@ -1906,7 +1912,7 @@ if ($action == 'create') {
}
// View or edit
if ($id > 0) {
if ($id > 0 && $action != 'create') {
$result1 = $object->fetch($id);
if ($result1 <= 0) {
$langs->load("errors");
@@ -1952,18 +1958,6 @@ if ($id > 0) {
exit;
}
/*
if ($object->authorid > 0) {
$tmpuser = new User($db);
$res = $tmpuser->fetch($object->authorid);
$object->author = $tmpuser;
}
if ($object->usermodid > 0) {
$tmpuser = new User($db);
$res = $tmpuser->fetch($object->usermodid);
$object->usermod = $tmpuser;
}
*/
/*
* Show tabs

View File

@@ -1293,7 +1293,7 @@ if ($action == 'create') {
* Invoice lines
*/
print '<div class="div-table-responsive-no-min">';
print '<table id="tablelines" class="noborder noshadow centpercent">';
print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
// Show object lines
if (!empty($sourceInvoice->lines)) {
@@ -1743,7 +1743,7 @@ if ($action == 'create') {
}
print '<div class="div-table-responsive-no-min">';
print '<table id="tablelines" class="noborder noshadow centpercent">';
print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
// Show object lines
if (!empty($object->lines)) {
$canchangeproduct = 1;

View File

@@ -5848,7 +5848,7 @@ if ($action == 'create') {
print '</div>';
print '</div>';
print '<div class="clearboth"></div><br><br>';
print '<div class="clearboth"></div><br>';
if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
$blocname = 'contacts';
@@ -5928,7 +5928,7 @@ if ($action == 'create') {
}
print '<div class="div-table-responsive-no-min">';
print '<table id="tablelines" class="noborder noshadow centpercent">';
print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
// Show object lines
if (!empty($object->lines)) {

View File

@@ -744,7 +744,7 @@ while ($i < $imaxinloop) {
// Payment type
if (!empty($arrayfields['c.libelle']['checked'])) {
print '<td>'.$langs->trans("PaymentTypeShort".$objp->paiement_code).'</td>';
print '<td class="tdoverflowmax100" title="'.dolPrintHTMLForAttribute($langs->trans("PaymentTypeShort".$objp->paiement_code)).'">'.dolPrintHTML($langs->trans("PaymentTypeShort".$objp->paiement_code)).'</td>';
if (!$i) {
$totalarray['nbfield']++;
}

View File

@@ -3,6 +3,7 @@
* Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2015-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Charlene Benke <charlene@patas-monkey.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -99,6 +100,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'contracts',
'interventions',
'ticket',
'knowledgebase',
'dolresource'
);
$conditions = array(
@@ -128,6 +130,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'),
'holidays' => isModEnabled('holiday') && $user->hasRight('holiday', 'read'),
'ticket' => isModEnabled('ticket') && $user->hasRight('ticket', 'read'),
'knowledgebase' => isModEnabled('knowledgemanagement') && $user->hasRight('knowledgemanagement', 'knowledgerecord', 'read'),
'dolresource' => isModEnabled('resource') && $user->hasRight('resource', 'read')
);
$classes = array(
@@ -152,6 +155,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => 'ExpenseReport',
'holidays' => 'Holiday',
'ticket' => 'Ticket',
'knowledgebase' => 'KnowledgeRecord',
'dolresource' => 'Dolresource'
);
$includes = array(
@@ -176,6 +180,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => DOL_DOCUMENT_ROOT . "/expensereport/class/expensereport.class.php",
'holidays' => DOL_DOCUMENT_ROOT . "/holiday/class/holiday.class.php",
'ticket' => DOL_DOCUMENT_ROOT . "/ticket/class/ticket.class.php",
'knowledgebase' => DOL_DOCUMENT_ROOT . "/knowledgemanagement/class/knowledgerecord.class.php",
'dolresource' => DOL_DOCUMENT_ROOT . "/resource/class/dolresource.class.php"
);
$links = array(
@@ -200,6 +205,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => DOL_URL_ROOT . '/expensereport/list.php?mainmenu=hrm&leftmenu=expensereport',
'holidays' => DOL_URL_ROOT . '/holiday/list.php?mainmenu=hrm&leftmenu=holiday',
'ticket' => DOL_URL_ROOT . '/ticket/list.php?leftmenu=ticket',
'knowledgebase' => DOL_URL_ROOT . '/knowledgemanagement/knowledgerecord_list.php?leftmenu=knowledgebase',
'dolresource' => DOL_URL_ROOT . '/resource/list.php?mainmenu=agenda',
);
$titres = array(
@@ -224,6 +230,7 @@ class box_dolibarr_state_board extends ModeleBoxes
'expensereports' => "ExpenseReports",
'holidays' => "Holidays",
'ticket' => "Ticket",
'knowledgebase' => "KnowledgeRecord",
'dolresource' => "Resources",
);
$langfile = array(

View File

@@ -9417,6 +9417,16 @@ abstract class CommonObject
}
}
// Expected behavior : if THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_XXX is set, when we change company,
// Then we use the extrafields of the object (they are filled in the card when constant THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_XXX is set)
$force_values_on_change_company = (
($this->element == 'facture' && getDolGlobalInt('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE'))
|| ($this->element == 'commande' && getDolGlobalInt('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER'))
);
if ($force_values_on_change_company && GETPOSTINT('changecompany')) {
$value = $this->array_options['options_'.$key] ?? $value;
}
// Convert date into timestamp format (value in memory must be a timestamp)
if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('date'))) {
$datenotinstring = null;

View File

@@ -69,6 +69,118 @@ class EventAttendees extends DolibarrApi
}
/**
* List Event attendees
*
* Get a list of Event attendees
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.status:=:1) and (t.email:=:'bad@example.com')"
* @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
* @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*
* @return array Array of order objects
* @phan-return ConferenceOrBoothAttendee[]|array{data:ConferenceOrBoothAttendee[],pagination:array{total:int,page:int,page_count:int,limit:int}}
* @phpstan-return ConferenceOrBoothAttendee[]|array{data:ConferenceOrBoothAttendee[],pagination:array{total:int,page:int,page_count:int,limit:int}}
*
* @url GET
*
* @throws RestException 403 Access denied
* @throws RestException 503 Error
*/
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '', $pagination_data = false)
{
// $allowaccess = $this->_checkAccessRights('read', 0);
// if (!$allowaccess) {
// throw new RestException(403, 'denied read access to Event attendees');
// }
// access check delayed until we can do it for each row checking each fk_project
// entity stolen from api_setup.class.php
$entity = (int) DolibarrApiAccess::$user->entity;
$obj_ret = array();
$sql = "SELECT t.rowid";
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." AS t";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet AS p ON t.fk_project = p.rowid";
if (isModEnabled('multicompany')) {
$sql .= ' WHERE p.entity = '.((int) $entity);
} else {
$sql .= ' WHERE 1 = 1';
}
// Add sql filters
if ($sqlfilters) {
$errormessage = '';
$sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
if ($errormessage) {
throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
}
}
//this query will return total orders with the filters given
$sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
$sql .= $this->db->order($sortfield, $sortorder);
if ($limit) {
if ($page < 0) {
$page = 0;
}
$offset = $limit * $page;
$sql .= $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this)."::index", LOG_DEBUG);
$result = $this->db->query($sql);
if ($result) {
$num = $this->db->num_rows($result);
$min = min($num, ($limit <= 0 ? $num : $limit));
$i = 0;
$onerowaccessgranted = false;
while ($i < $min) {
$obj = $this->db->fetch_object($result);
$event_attendees_static = new ConferenceOrBoothAttendee($this->db);
if ($event_attendees_static->fetch($obj->rowid, '') > 0) {
$rowallowaccess = $this->_checkAccessRights('read', $event_attendees_static->fk_project);
if ($rowallowaccess) {
$obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($event_attendees_static), $properties);
$onerowaccessgranted = $rowallowaccess;
}
}
$i++;
}
if (($num > 0) && !$onerowaccessgranted) {
throw new RestException(403, 'No access granted for even a single of the rows found');
}
} else {
throw new RestException(503, 'Error when retrieve event attendee list : '.$this->db->lasterror());
}
//if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
if ($pagination_data) {
$totalsResult = $this->db->query($sqlTotals);
$total = $this->db->fetch_object($totalsResult)->total;
$tmp = $obj_ret;
$obj_ret = [];
$obj_ret['data'] = $tmp;
$obj_ret['pagination'] = [
'total' => (int) $total,
'page' => $page, //count starts from 0
'page_count' => ceil((int) $total / $limit),
'limit' => $limit
];
}
return $obj_ret;
}
/**
* Create an event attendee
*
* Example: {"module":"adherent","type_template":"member","active": 1,"ref":"(SendingEmailOnAutoSubscription)","fk_user":0,"joinfiles": "0", ... }
@@ -113,6 +225,91 @@ class EventAttendees extends DolibarrApi
return ((int) $this->event_attendees->id);
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Clean sensible object datas
*
* @param Object $object Object to clean
* @phan-param ConferenceOrBoothAttendee $object
* @phpstan-param ConferenceOrBoothAttendee $object
*
* @return Object Object with cleaned properties
* @phan-return ConferenceOrBoothAttendee
* @phpstan-return ConferenceOrBoothAttendee
*/
protected function _cleanObjectDatas($object)
{
// phpcs:enable
$object = parent::_cleanObjectDatas($object);
unset($object->array_languages);
unset($object->contacts_ids);
unset($object->canvas);
unset($object->contact_id);
unset($object->user);
unset($object->origin_type);
unset($object->origin_id);
unset($object->ref_ext);
unset($object->statut);
unset($object->civility_code);
unset($object->country_id);
unset($object->country_code);
unset($object->state_id);
unset($object->region_id);
unset($object->barcode_type);
unset($object->barcode_type_coder);
unset($object->mode_reglement_id);
unset($object->cond_reglement_id);
unset($object->demand_reason_id);
unset($object->transport_mode_id);
unset($object->shipping_method_id);
unset($object->shipping_method);
unset($object->fk_multicurrency);
unset($object->multicurrency_code);
unset($object->multicurrency_tx);
unset($object->multicurrency_total_ht);
unset($object->multicurrency_total_tva);
unset($object->multicurrency_total_ttc);
unset($object->multicurrency_total_localtax1);
unset($object->multicurrency_total_localtax2);
unset($object->fk_account);
unset($object->total_ht);
unset($object->total_tva);
unset($object->total_localtax1);
unset($object->total_localtax2);
unset($object->total_ttc);
unset($object->lines);
unset($object->actiontypecode);
unset($object->name);
unset($object->civility_id);
unset($object->user_author);
unset($object->user_creation);
unset($object->user_creation_id);
unset($object->user_valid);
unset($object->user_validation);
unset($object->user_validation_id);
unset($object->user_closing_id);
unset($object->user_modification);
unset($object->user_modification_id);
unset($object->totalpaid);
unset($object->product);
unset($object->cond_reglement_supplier_id);
unset($object->deposit_percent);
unset($object->retained_warranty_fk_cond_reglement);
unset($object->warehouse_id);
unset($object->target);
unset($object->extraparams);
unset($object->specimen);
unset($object->date_validation);
unset($object->date_modification);
unset($object->date_cloture);
unset($object->rowid);
unset($object->module);
unset($object->entity);
return $object;
}
/**
* Validate fields before create or update object
*

View File

@@ -1490,7 +1490,7 @@ class Expedition extends CommonObject
// Add a protection to refuse deleting if shipment has at least one delivery
$this->fetchObjectLinked($this->id, 'shipping', 0, 'delivery'); // Get deliveries linked to this shipment
if (count($this->linkedObjectsIds) > 0) {
if (isset($this->linkedObjectsIds['delivery']) && count($this->linkedObjectsIds['delivery']) > 0) {
$this->error = 'ErrorThereIsSomeDeliveries';
$error++;
}
@@ -1700,7 +1700,7 @@ class Expedition extends CommonObject
// Add a protection to refuse deleting if shipment has at least one delivery
$this->fetchObjectLinked($this->id, 'shipping', 0, 'delivery'); // Get deliveries linked to this shipment
if (count($this->linkedObjectsIds) > 0) {
if (isset($this->linkedObjectsIds['delivery']) && count($this->linkedObjectsIds['delivery']) > 0) {
$this->error = 'ErrorThereIsSomeDeliveries';
$error++;
}

View File

@@ -1911,6 +1911,15 @@ if ($action == 'create') {
print $hookmanager->resPrint;
if (empty($reshook)) {
if (getDolGlobalString('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_SUPPLIER_ORDER') && !empty($societe->id)) {
// copy from thirdparty
$tpExtrafields = new ExtraFields($db);
$tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($societe->table_element);
if ($societe->fetch_optionals() > 0) {
$object->array_options = array_merge($object->array_options, $societe->array_options);
}
}
print $object->showOptionals($extrafields, 'create');
}

View File

@@ -1,7 +1,8 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
* Copyright (C) 2021 SuperAdmin <test@dolibarr.com>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2021 SuperAdmin <test@dolibarr.com>
* Copyright (C) 2025 Charlene Benke <charlent@patas-monkey.com>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* 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
@@ -438,6 +439,79 @@ class KnowledgeManagement extends DolibarrApi
return $object;
}
/**
* Validate a knowledge
*
* If you get a bad value for param notrigger check, provide this in body
* {
* "notrigger": 0
* }
*
* @param int $id knowledge ID
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
*
* @url POST {id}/validate
*
* @return Object
*/
public function validate($id, $notrigger = 0)
{
if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'write')) {
throw new RestException(403, "Insuffisant rights");
}
$result = $this->knowledgerecord->fetch($id);
if (!$result) {
throw new RestException(404, 'knowledgerecord not found');
}
$result = $this->knowledgerecord->validate(DolibarrApiAccess::$user, $notrigger);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already validated');
}
if ($result < 0) {
throw new RestException(500, 'Error when validating knowledgerecord: '.$this->knowledgerecord->error);
}
return $this->_cleanObjectDatas($this->knowledgerecord);
}
/**
* Cancel a knowledge
*
* If you get a bad value for param notrigger check, provide this in body
* {
* "notrigger": 0
* }
*
* @param int $id knowledge ID
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
*
* @url POST {id}/cancel
*
* @return Object
*/
public function cancel($id, $notrigger = 0)
{
if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'write')) {
throw new RestException(403, "Insuffisant rights");
}
$result = $this->knowledgerecord->fetch($id);
if (!$result) {
throw new RestException(404, 'knowledgerecord not found');
}
$result = $this->knowledgerecord->cancel(DolibarrApiAccess::$user, $notrigger);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already validated');
}
if ($result < 0) {
throw new RestException(500, 'Error when validating knowledgerecord: '.$this->knowledgerecord->error);
}
return $this->_cleanObjectDatas($this->knowledgerecord);
}
/**
* Validate fields before create or update object
@@ -454,7 +528,7 @@ class KnowledgeManagement extends DolibarrApi
}
$knowledgerecord = array();
foreach ($this->knowledgerecord->fields as $field => $propfield) {
if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || empty($propfield['notnull']) || $propfield['notnull'] != 1) {
if (in_array($field, array('rowid', 'entity', 'ref', 'date_creation', 'tms', 'fk_user_creat')) || empty($propfield['notnull']) || $propfield['notnull'] != 1) {
continue; // Not a mandatory field
}
if (!isset($data[$field])) {

View File

@@ -1201,6 +1201,36 @@ class KnowledgeRecord extends CommonObject
$return .= '</div>';
return $return;
}
/**
* Load indicators into this->nb for board
*
* @return int Return integer <0 if KO, >0 if OK
*/
public function loadStateBoard()
{
global $user;
$this->nb = array();
$clause = "WHERE";
$sql = "SELECT count(t.rowid) as nb";
$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
$resql = $this->db->query($sql);
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
$this->nb["knowledgebase"] = $obj->nb;
}
$this->db->free($resql);
return 1;
} else {
dol_print_error($this->db);
$this->error = $this->db->error();
return -1;
}
}
}

View File

@@ -1153,8 +1153,8 @@ VATManagement=Sales Tax Management
VATIsUsedStandard=When creating documents (proposals, invoices, orders...), the default Sales Tax rate is set according to the standard rules (depending on seller and buyer countries)
VATIsUsedDesc=By default when creating proposals, invoices, orders etc. the Sales Tax rate follows the active standard rule:<br>If the seller is not subject to Sales tax, then Sales tax defaults to 0. End of rule.<br>If buyer state or province has a VAT rule from vat rates dictionary then it's the default VAT rate. End of rule.<br>If the (seller's country = buyer's country), then the Sales tax by default equals the Sales tax of the product in the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and goods are transport-related products (haulage, shipping, airline), the default VAT is 0. This rule is dependent on the seller's country - please consult with your accountant. The VAT should be paid by the buyer to the customs office in their country and not to the seller. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is not a company (with a registered intra-Community VAT number) then the VAT defaults to the VAT rate of the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is a company (with a registered intra-Community VAT number), then the VAT is 0 by default. End of rule.<br>In any other case the proposed default is Sales tax=0. End of rule.
VATIsNotUsedDesc=By default the proposed Sales tax is 0 which can be used for cases like associations, individuals or small companies.
VATIsUsedExampleFR=In France, it means companies or organizations having a real fiscal system (Simplified real or normal real). A system in which VAT is declared.
VATIsNotUsedExampleFR=In France, it means associations that are non Sales tax declared or companies, organizations or liberal professions that have chosen the micro enterprise fiscal system (Sales tax in franchise) and paid a franchise Sales tax without any Sales tax declaration. This choice will display the reference "Non applicable Sales tax - art-293B of CGI" on invoices.
VATIsUsedExampleFR=In France, it concerns companies or organizations having a real fiscal system (Simplified real or normal real). A system in which VAT is declared.
VATIsNotUsedExampleFR=In France, it concerns associations that are non Sales tax declared or companies, organizations or liberal professions that have chosen the micro enterprise fiscal system (Sales tax in franchise) and paid a franchise Sales tax without any Sales tax declaration. This choice will display the mention "Non applicable Sales tax - art-293B of CGI" on invoices.
VATType=Tax usage
##### Local Taxes #####
TypeOfSaleTaxes=Type of sales tax

View File

@@ -3455,7 +3455,7 @@ if ($module == 'initmodule') {
print '<span class="opacitymedium small">';
print ' &nbsp; &nbsp; ';
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?displayMode=icon-only#img-picto-section-list', '', '');
print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only#img-picto-section-list', '', '');
print '</span>';
print '</div></div>';

View File

@@ -1,8 +1,8 @@
<?php
/* Copyright (C) 2013-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2013-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* 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
@@ -93,6 +93,8 @@ if (!$user->hasRight('opensurvey', 'read')) {
accessforbidden();
}
$fieldstosearchall = array();
// Definition of fields for list
$arrayfields = array();
// Extra fields
@@ -120,7 +122,7 @@ if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massa
$massaction = '';
}
$parameters = array();
$parameters = array('arrayfields' => &$arrayfields);
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
@@ -163,7 +165,8 @@ $now = dol_now();
$help_url = '';
$title = $langs->trans('OpenSurveyArea');
// Build and execute select
// --------------------------------------------------------------------
$sql = "SELECT p.id_sondage as rowid, p.fk_user_creat, p.format, p.date_fin, p.status, p.titre as title, p.nom_admin, p.tms,";
$sql .= " u.login, u.firstname, u.lastname";
$sql .= " FROM ".MAIN_DB_PREFIX."opensurvey_sondage as p";
@@ -219,10 +222,10 @@ if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) {
}
// Direct jump if only one record found
if ($num == 1 && getDolGlobalString('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all) {
if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
$obj = $db->fetch_object($resql);
$id = $obj->rowid;
header("Location: ".dol_buildpath('/opensurvey/card.php', 1).'?id='.$id);
header("Location: ".dol_buildpath('/opensurvey/card.php', 1).'?id='.((int) $id));
exit;
}
@@ -241,11 +244,11 @@ if (/* !empty($contextpage) && */ $contextpage != $_SERVER["PHP_SELF"]) { // $co
if ($limit > 0 && $limit != $conf->liste_limit) {
$param .= '&limit='.((int) $limit);
}
$fieldtosortuser = !getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION') ? 'firstname' : 'lastname';
if ($optioncss != '') {
$param .= '&optioncss='.urlencode($optioncss);
}
$fieldtosortuser = getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION') ? 'lastname' : 'firstname';
// Add $param from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
@@ -254,7 +257,7 @@ $arrayofmassactions = array(
//'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
);
if ($permissiontodelete) {
if (!empty($permissiontodelete)) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
}
if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
@@ -262,10 +265,7 @@ if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predel
}
$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
// List of surveys into database
print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
if ($optioncss != '') {
print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
}
@@ -274,7 +274,10 @@ print '<input type="hidden" name="formfilteraction" id="formfilteraction" value=
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
print '<input type="hidden" name="page_y" value="">';
print '<input type="hidden" name="mode" value="'.$mode.'">';
$newcardbutton = '';
$newcardbutton .= dolGetButtonTitle($langs->trans('NewSurvey'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/opensurvey/wizard/index.php', '', $user->hasRight('opensurvey', 'write'));
@@ -290,11 +293,13 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
if ($search_all) {
$fieldstosearchall = array();
$setupstring = '';
// @phan-suppress-next-line PhanEmptyForeach
foreach ($fieldstosearchall as $key => $val) { // @phpstan-ignore-line
$fieldstosearchall[$key] = $langs->trans($val);
$setupstring .= $key."=".$val.";";
}
print '<!-- Search done like if OPENSURVEY_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>';
}
@@ -310,6 +315,9 @@ if (empty($reshook)) {
} else {
$moreforfilter = $hookmanager->resPrint;
}
$parameters = array(
'arrayfields' => &$arrayfields,
);
if (!empty($moreforfilter)) {
print '<div class="liste_titre liste_titre_bydiv centpercent">';
@@ -318,19 +326,19 @@ if (!empty($moreforfilter)) {
}
$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
//$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
$selectedfields = '';
$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column); // This also change content of $arrayfields with user setup
$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
print '<div class="div-table-responsive">';
print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
// Fields title search
// --------------------------------------------------------------------
print '<tr class="liste_titre_filter">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre maxwidthsearch">';
print '<td class="liste_titre center maxwidthsearch">';
$searchpicto = $form->showFilterButtons('left');
print $searchpicto;
print '</td>';
@@ -343,39 +351,50 @@ print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
$arraystatus = array('-1' => '&nbsp;', '0' => $langs->trans("Draft"), '1' => $langs->trans("Opened"), '2' => $langs->trans("Closed"));
print '<td class="liste_titre" align="center">'.$form->selectarray('search_status', $arraystatus, $search_status, 0, 0, 0, '', 0, 0, 0, '', 'onroghtofpage').'</td>';
print '<td class="liste_titre center parentonrightofpage">'.$form->selectarray('search_status', $arraystatus, $search_status, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth100 onrightofpage').'</td>';
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
// Fields from hook
$parameters = array('arrayfields' => $arrayfields);
$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre maxwidthsearch">';
print '<td class="liste_titre center maxwidthsearch">';
$searchpicto = $form->showFilterButtons();
print $searchpicto;
print '</td>';
}
print '</tr>'."\n";
$totalarray = array();
$totalarray['nbfield'] = 0;
// Fields title label
// --------------------------------------------------------------------
print '<tr class="liste_titre">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ')."\n";
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.id_sondage", $param, "", "", $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("Title", $_SERVER["PHP_SELF"], "p.titre", $param, "", "", $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "p.format", $param, "", "", $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("Author", $_SERVER["PHP_SELF"], "u.".$fieldtosortuser, $param, "", "", $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("NbOfVoters", $_SERVER["PHP_SELF"], "", $param, "", 'align="right"', $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("ExpireDate", $_SERVER["PHP_SELF"], "p.date_fin", $param, "", 'align="center"', $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("DateLastModification", $_SERVER["PHP_SELF"], "p.tms", $param, "", 'align="center"', $sortfield, $sortorder);
$totalarray['nbfield']++;
print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "p.status", $param, "", 'align="center"', $sortfield, $sortorder);
$totalarray['nbfield']++;
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
// Hook fields
@@ -385,6 +404,7 @@ print $hookmanager->resPrint;
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
print '</tr>'."\n";
@@ -393,9 +413,11 @@ print '</tr>'."\n";
// Loop on record
// --------------------------------------------------------------------
$i = 0;
$savnbfield = $totalarray['nbfield'];
$totalarray = array();
$totalarray['nbfield'] = 0;
while ($i < min($num, $limit)) {
$imaxinloop = ($limit ? min($num, $limit) : $num);
while ($i < $imaxinloop) {
$obj = $db->fetch_object($resql);
if (empty($obj)) {
break; // Should not happen
@@ -418,7 +440,7 @@ while ($i < min($num, $limit)) {
$opensurvey_static->date_fin = $db->jdate($obj->date_fin);
// Show here line of result
print '<tr class="oddeven">';
print '<tr data-rowid="'.$opensurvey_static->id.'" class="oddeven">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="nowrap center">';

View File

@@ -139,7 +139,7 @@ $arrayofjs = array();
$arrayofcss = array('/opensurvey/css/style.css');
llxHeader('', $langs->trans("OpenSurvey"), '', "", 0, 0, $arrayofjs, $arrayofcss);
print load_fiche_titre($langs->trans("CreatePoll").' (1 / 2)');
print load_fiche_titre($langs->trans("CreatePoll").' (1 / 2)', '', 'poll');
print '<form name="formulaire" action="" method="POST">'."\n";

View File

@@ -201,7 +201,7 @@ if (isModEnabled('category')) {
if (GETPOSTISARRAY('search_status') || GETPOST('search_status_multiselect')) {
$search_status = implode(',', GETPOST('search_status', 'array:intcomma'));
} else {
$search_status = (GETPOST('search_status', 'intcomma') != '' ? GETPOST('search_status', 'intcomma') : '0,1');
$search_status = (GETPOST('search_status', 'intcomma') != '' ? GETPOST('search_status', 'intcomma') : (GETPOSTISSET('search_all') ? '' : '0,1'));
}
$search_option = GETPOST('search_option', 'alpha');

View File

@@ -411,7 +411,7 @@ input[type=submit], input[type=submit]:hover {
}
input[type=checkbox], input[type=radio] {
margin: 0 5px 0 1px;
transform: scale(1.2);
transform: scale(1.3);
}
.kanban input.checkforselect {
margin-right: 0px;
@@ -471,6 +471,10 @@ section.setupsection {
background-color: var(--colorbackgrey);
border-radius: 5px;
}
section.setupsection:hover {
box-shadow: 0 0 5px #aaa;
}
.field-error-icon { color: #ea1212 !important; }
@@ -833,15 +837,11 @@ table.tableforfield .buttonDelete:not(.bordertransp):not(.buttonpayment) {
cursor: pointer;
text-decoration: none !important;
background-color: #f5f5f5;
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
background-repeat: repeat-x;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border: 1px solid #aaa;
border-radius: 1px;
border-radius: 4px;
font-weight: bold;
text-transform: uppercase;

View File

@@ -681,6 +681,9 @@ section.setupsection {
background-color: var(--colorbacktitle1);
border-radius: 5px;
}
section.setupsection:hover {
box-shadow: 0 0 5px #aaa;
}
.field-error-icon { color: #ea1212 !important; }
@@ -964,7 +967,7 @@ input:-webkit-autofill {
input[type=checkbox], input[type=radio] {
margin: 0 5px 0 1px;
transform: scale(1.2);
transform: scale(1.3);
}
.kanban input.checkforselect {
margin-right: 0px;

View File

@@ -1969,10 +1969,7 @@ if ($action == "updatesecurity" && $usercanedit && GETPOST("btn_WEBSITE_SECURITY
}
$securityspstring = "";
if (isset($sourcetype) && $sourcetype == "data") {
if (empty($forceCSPArr[$directivecsp]["data"])) {
$forceCSPArr[$directivecsp]["data"] = array();
}
$forceCSPArr[$directivecsp]["data"][] = $sourcedatacsp;
$forceCSPArr[$directivecsp][] = "data:".$sourcedatacsp;
} elseif (isset($sourcetype) && $sourcetype == "input") {
if (empty($forceCSPArr[$directivecsp])) {
$forceCSPArr[$directivecsp] = array();
@@ -1993,16 +1990,12 @@ if ($action == "updatesecurity" && $usercanedit && GETPOST("btn_WEBSITE_SECURITY
}
$sourcestring = "";
foreach ($sourcekeys as $key => $source) {
if (is_array($source)) {
$sourcestring .= " data: ". implode(" ", $source);
} else {
$directivetype = $directivesarray[$directive]["data-directivetype"];
$sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
if (isset($sourcetype) && $sourcetype == "quoted") {
$sourcestring .= " '".$source."'";
} elseif ($directivetype != "none") {
$sourcestring .= " ".$source;
}
$directivetype = $directivesarray[$directive]["data-directivetype"];
$sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
if (isset($sourcetype) && $sourcetype == "quoted") {
$sourcestring .= " '".$source."'";
} elseif ($directivetype != "none") {
$sourcestring .= " ".$source;
}
}
$securityspstring .= $directive . $sourcestring;
@@ -3010,17 +3003,7 @@ if ($action == 'removecspsource' && $usercanedit) {
$securityspstring = "";
if (!$error && !empty($forceCSPArr)) {
if (isset($sourcekey) && !empty($forceCSPArr[$directive][$sourcekey])) {
if ($sourcetype == "data" || preg_match('/data/', $sourcekey)) {
$keydata = array_search($sourcedata, $forceCSPArr[$directive][$sourcekey]);
if ($keydata !== false) {
unset($forceCSPArr[$directive][$sourcekey][$keydata]);
}
if (count($forceCSPArr[$directive][$sourcekey]) == 0) {
unset($forceCSPArr[$directive][$sourcekey]);
}
} else {
unset($forceCSPArr[$directive][$sourcekey]);
}
unset($forceCSPArr[$directive][$sourcekey]);
}
if (count($forceCSPArr[$directive]) == 0) {
unset($forceCSPArr[$directive]);
@@ -3031,16 +3014,12 @@ if ($action == 'removecspsource' && $usercanedit) {
}
$sourcestring = "";
foreach ($sourcekeys as $key => $source) {
if (is_array($source)) {
$sourcestring .= " data: ". implode(" ", $source);
$directivetype = $directivesarray[$directive]["data-directivetype"];
$sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
if ($sourcetype == "quoted") {
$sourcestring .= " '".$source."'";
} else {
$directivetype = $directivesarray[$directive]["data-directivetype"];
$sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
if ($sourcetype == "quoted") {
$sourcestring .= " '".$source."'";
} else {
$sourcestring .= " ".$source;
}
$sourcestring .= " ".$source;
}
}
$securityspstring .= $directive . $sourcestring;
@@ -4418,29 +4397,28 @@ if ($action == 'editsecurity') {
print '<input class="minwidth500 quatrevingtpercent" name="WEBSITE_'.$object->id.'_SECURITY_FORCECSP" id="WEBSITE_'.$object->id.'_SECURITY_FORCECSP" value="'.$forceCSP.'"> <a href="#" id="btnaddcontentsecuritypolicy">'.img_picto('', 'add').'</a><br>';
print '<br>';
print '<div id="selectaddcontentsecuritypolicy" class="hidden">';
print $form->selectarray("select_identifier_WEBSITE_SECURITY_FORCECSP", $selectarrayCSPDirectives, "select_identifier_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPDirective"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth350 inline-block');
print ' ';
print '<input type="hidden" id="select_source_WEBSITE_SECURITY_FORCECSP" name="select_source_WEBSITE_SECURITY_FORCECSP">';
foreach ($selectarrayCSPSources as $key => $values) {
print '<div class="div_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth350" id="div_'.$key.'_WEBSITE_SECURITY_FORCECSP">';
print $form->selectarray("select_".$key."_WEBSITE_SECURITY_FORCECSP", $values, "select_".$key."_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPSource"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth300 inline-block select_WEBSITE_SECURITY_FORCECSP');
print '</div>';
}
print ' ';
print '<div class="div_input_data_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth200"><input id="input_data_WEBSITE_SECURITY_FORCECSP" name="input_data_WEBSITE_SECURITY_FORCECSP"></div>';
print ' ';
print '<div class="div_btn_class_WEBSITE_SECURITY_FORCECSP inline-block maxwidth200"><input type="submit" id="btn_WEBSITE_SECURITY_FORCECSP" name="btn_WEBSITE_SECURITY_FORCECSP" class="butAction small smallpaddingimp" value="'.$langs->trans("Add").'" disabled></div>';
print '<br><br>';
print '</div>';
if (!empty($forceCSP)) {
print '<br>';
print '<div class="">';
print img_picto('', 'graph', 'class="pictofixedwidth"').$langs->trans("HierarchicView").'<br>';
print '<div id="selectaddcontentsecuritypolicy" class="hidden">';
print $form->selectarray("select_identifier_WEBSITE_SECURITY_FORCECSP", $selectarrayCSPDirectives, "select_identifier_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPDirective"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth350 inline-block');
print ' ';
print '<input type="hidden" id="select_source_WEBSITE_SECURITY_FORCECSP" name="select_source_WEBSITE_SECURITY_FORCECSP">';
foreach ($selectarrayCSPSources as $key => $values) {
print '<div class="div_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth350" id="div_'.$key.'_WEBSITE_SECURITY_FORCECSP">';
print $form->selectarray("select_".$key."_WEBSITE_SECURITY_FORCECSP", $values, "select_".$key."_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPSource"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth300 inline-block select_WEBSITE_SECURITY_FORCECSP');
print '</div>';
}
print ' ';
print '<div class="div_input_data_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth200"><input id="input_data_WEBSITE_SECURITY_FORCECSP" name="input_data_WEBSITE_SECURITY_FORCECSP"></div>';
print ' ';
print '<div class="div_btn_class_WEBSITE_SECURITY_FORCECSP inline-block maxwidth200"><input type="submit" id="btn_WEBSITE_SECURITY_FORCECSP" name="btn_WEBSITE_SECURITY_FORCECSP" class="butAction small smallpaddingimp" value="'.$langs->trans("Add").'" disabled></div>';
print '</div>';
print '</div>';
// Content Security Policy list of selected rules
print '<div class="div-table-responsive-no-min">';
print img_picto('', 'graph', 'class="pictofixedwidth"').$langs->trans("HierarchicView").'<br>';
print '<ul>';
foreach ($forceCSPArr as $directive => $sources) {
print '<li>';
@@ -4452,17 +4430,7 @@ if ($action == 'editsecurity') {
if (!empty($sources)) {
print '<ul>';
foreach ($sources as $key => $source) {
if (is_array($source)) {
print '<li><span>'.$key.'</span>';
print '<ul>';
foreach ($source as $keysource => $sourcedata) {
print '<li><span>'.$sourcedata.'</span>&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'_'.$key.'_'.$sourcedata.'&token='.newToken().'">'.img_delete().'</a></li>';
}
print '</ul>';
print '</li>';
} else {
print '<li><span>'.$source.'</span>&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'_'.$key.'&token='.newToken().'">'.img_delete().'</a></li>';
}
print '<li><span>'.$source.'</span>&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'_'.$key.'&token='.newToken().'">'.img_delete().'</a></li>';
}
print '</ul>';
} else {
@@ -4531,6 +4499,7 @@ if ($action == 'editsecurity') {
console.log("We hide and show fields");
if (keysource == "data" || keysource == "input") {
$(".div_input_data_WEBSITE_SECURITY_FORCECSP").css("display", "inline-block");
$("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
} else {
$("#input_data_WEBSITE_SECURITY_FORCECSP").val("");
$(".div_input_data_WEBSITE_SECURITY_FORCECSP").hide();
@@ -4542,8 +4511,8 @@ if ($action == 'editsecurity') {
}
});
$("#input_data_WEBSITE_SECURITY_FORCECSP").on("change", function(){
if ($(this).val() != undefined) {
$("#input_data_WEBSITE_SECURITY_FORCECSP").on("change keyup", function(){
if ($(this).val() != "") {
console.log("We show add button");
$("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
} else {

View File

@@ -144,7 +144,7 @@ function websiteGetContentPolicySources()
// Fetch directives
"fetch" => array(
"*" => array("label" => "*", "data-sourcetype" => "select"),
"data" => array("label" => "data", "data-sourcetype" => "data"),
"data" => array("label" => "data:", "data-sourcetype" => "data"),
"self" => array("label" => "self", "data-sourcetype" => "quoted"),
"unsafe-eval" => array("label" => "unsafe-eval", "data-sourcetype" => "quoted"),
"wasm-unsafe-eval" => array("label" => "wasm-unsafe-eval", "data-sourcetype" => "quoted"),
@@ -153,21 +153,21 @@ function websiteGetContentPolicySources()
"inline-speculation-rules" => array("label" => "inline-speculation-rules", "data-sourcetype" => "quoted"),
"strict-dynamic" => array("label" => "strict-dynamic", "data-sourcetype" => "quoted"),
"report-sample" => array("label" => "report-sample", "data-sourcetype" => "quoted"),
"host-source" => array("label" => "host-source", "data-sourcetype" => "input"),
"host-source" => array("label" => "host-source (*.mydomain.com)", "data-sourcetype" => "input"),
"scheme-source" => array("label" => "scheme-source", "data-sourcetype" => "input"),
),
// Document directives
"document" => array(
"none" => array("label" => "self", "data-sourcetype" => "quoted"),
"self" => array("label" => "self", "data-sourcetype" => "quoted"),
"host-source" => array("label" => "host-source", "data-sourcetype" => "input"),
"scheme-source" => array("label" => "scheme-source", "data-sourcetype" => "input"),
"host-source" => array("label" => "host-source (*.mydomain.com)", "data-sourcetype" => "input"),
"scheme-source" => array("label" => "scheme-source (*.mydomain.com)", "data-sourcetype" => "input"),
),
// Navigation directives
"navigation" => array(
"none" => array("label" => "self", "data-sourcetype" => "quoted"),
"self" => array("label" => "self", "data-sourcetype" => "quoted"),
"host-source" => array("label" => "host-source", "data-sourcetype" => "input"),
"host-source" => array("label" => "host-source (*.mydomain.com)", "data-sourcetype" => "input"),
"scheme-source" => array("label" => "scheme-source", "data-sourcetype" => "input"),
),
// Reporting directives
@@ -202,6 +202,8 @@ function websiteGetContentPolicyToArray($forceCSP)
foreach ($sourceCSPArr as $key => $arr) {
$sourceCSPArrflatten = array_merge($sourceCSPArrflatten, array_keys($arr));
}
// Gerer le problème avec data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D qui est split + problème avec button ajouter
$forceCSP = preg_replace('/;base64,/', "__semicolumnbase64__", $forceCSP);
$securitypolicies = explode(";", $forceCSP);
// Loop on each security policy to create an array
@@ -209,6 +211,7 @@ function websiteGetContentPolicyToArray($forceCSP)
if ($securitypolicy == "") {
continue;
}
$securitypolicy = preg_replace('/__semicolumnbase64__/', ";base64,", $securitypolicy);
$securitypolicyarr = explode(" ", $securitypolicy);
$directive = array_shift($securitypolicyarr);
// Remove unwanted spaces
@@ -219,37 +222,19 @@ function websiteGetContentPolicyToArray($forceCSP)
continue;
}
$sources = $securitypolicyarr;
$issourcedata = 0;
if (empty($sources)) {
$forceCSPArr[$directive] = array();
} else {
//Loop on each sources to add to the right directive array key
foreach ($sources as $key2 => $source) {
$source = str_replace(":", "", $source);
$source = str_replace("'", "", $source);
if (empty($source)) {
$forceCSPArr[$directive] = array();
continue;
}
if ($source == "data") {
$issourcedata = 1;
if (empty($forceCSPArr[$directive])) {
$forceCSPArr[$directive] = array($source => array());
} else {
$forceCSPArr[$directive][$source] = array();
}
continue;
}
if ($issourcedata && !in_array($source, $sourceCSPArrflatten)) {
$forceCSPArr[$directive]["data"][] = $source;
if (empty($forceCSPArr[$directive])) {
$forceCSPArr[$directive] = array($source);
} else {
$issourcedata = 0;
if (empty($forceCSPArr[$directive])) {
$forceCSPArr[$directive] = array($source);
} else {
$forceCSPArr[$directive][] = $source;
}
$forceCSPArr[$directive][] = $source;
}
}
}