diff --git a/ChangeLog b/ChangeLog index c301ac59b58..48002248c4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -165,6 +165,7 @@ NEW: Update ActionComm type_code on email message ticket NEW: VAT - Admin - Add information on deadline day for submission of VAT declaration NEW: expand/collapse permissions on user permission page NEW: Show delivery mode on PDF for proposals +NEW: Add the target to select attendees of event for emailings For developers or integrators: diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 59890c36988..d3eae385ee0 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -741,7 +741,7 @@ class Adherent extends CommonObject $sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null"); $sql .= ", email = '".$this->db->escape($this->email)."'"; $sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null"); - $sql .= ", socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'"; + $sql .= ", socialnetworks = ".($this->socialnetworks ? "'".$this->db->escape(json_encode($this->socialnetworks))."'" : "null"); $sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null"); $sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null"); $sql .= ", phone_mobile = ".($this->phone_mobile ? "'".$this->db->escape($this->phone_mobile)."'" : "null"); @@ -2958,17 +2958,18 @@ class Adherent extends CommonObject dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG); if (!is_numeric($daysbeforeend)) { - $blockingerrormsg = "Value for delta is not a positive or negative numeric"; + $blockingerrormsg = "Value for delta is not a numeric value"; $nbko++; break; } $tmp = dol_getdate($now); - $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year']), $daysbeforeend, 'd'); + $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), $daysbeforeend, 'd'); $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent'; - $sql .= " WHERE entity = ".$conf->entity; // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only; + $sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only; $sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'"; + //$sql .= " LIMIT 10000"; $resql = $this->db->query($sql); if ($resql) { @@ -3001,7 +3002,7 @@ class Adherent extends CommonObject dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang); $arraydefaultmessage = null; - $labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION; + $labeltouse = getDolGlobalString('ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION'); if (!empty($labeltouse)) { $arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse); @@ -3025,7 +3026,7 @@ class Adherent extends CommonObject $result = $cmail->sendfile(); if (!$result) { $error++; - $this->error = $cmail->error; + $this->error .= $cmail->error.' '; if (!is_null($cmail->errors)) { $this->errors += $cmail->errors; } @@ -3043,8 +3044,7 @@ class Adherent extends CommonObject $extraparams = ''; $actionmsg = ''; - $actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '. - CMailFile::getValidAddress($sendto, 4, 0, 1); + $actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($sendto, 4, 0, 1); if ($message) { $actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from); $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto)); @@ -3091,7 +3091,10 @@ class Adherent extends CommonObject $actioncomm->create($user); } } else { - $blockingerrormsg = "Can't find email template, defined into member module setup, to use for reminding"; + //$blockingerrormsg = "Can't find email template with label=".$labeltouse.", to use for the reminding email"; + + $error++; + $this->error .= "Can't find email template with label=".$labeltouse.", to use for the reminding email "; $nbko++; $listofmembersko[$adherent->id] = $adherent->id; @@ -3133,7 +3136,7 @@ class Adherent extends CommonObject if ($listofids) { $listofids .= ']'; } - $this->output .= $listofids; + $this->output .= ' ids='.$listofids; } if ($nbko) { $this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)'; @@ -3161,6 +3164,6 @@ class Adherent extends CommonObject } } - return 0; + return $nbko; } } diff --git a/htdocs/admin/mailing.php b/htdocs/admin/mailing.php index 6a166078bfc..c88bb1bc4d5 100644 --- a/htdocs/admin/mailing.php +++ b/htdocs/admin/mailing.php @@ -123,32 +123,35 @@ print ''; print ''; print ''; print ''; -print ''; +print ''; print "\n"; print ''; +print ''; +print ''; print ''; print ''; +print ''; +print ''; print ''; print ''; +print ''; +print ''; print ''; @@ -157,11 +160,12 @@ print ''; print ''; +print ''; +print ''; print ''; // default blacklist from mailing @@ -171,7 +175,7 @@ print ''; -print ''; +print ''; print ''; @@ -179,7 +183,8 @@ if (!empty($conf->use_javascript_ajax) && $conf->global->MAIN_FEATURES_LEVEL >= print ''; + print ''; + print ''; print ''; } diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 58ab4503dc5..d3d90067bf3 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1646,8 +1646,10 @@ class ActionComm extends CommonObject } if (!empty($this->note_private)) { $tooltip .= '

'.$langs->trans('Description').':
'; - $texttoshow = dolGetFirstLineOfText($this->note_private, 10); + $texttoshow = dolGetFirstLineOfText($this->note_private, 10); // Try to limit length of content + $tooltip .= '
'; // Restrict height of content into the tooltip $tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '
', $texttoshow)); + $tooltip .= '
'; } $linkclose = ''; //if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color) diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index bd3d54977f1..0afb5cdd230 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -730,7 +730,7 @@ if ($action == 'create') { // Print mail form print load_fiche_titre($langs->trans("NewMailing"), $availablelink, 'object_email'); - print dol_get_fiche_head(); + print dol_get_fiche_head(array(), '', '', -3); print '
'.$langs->trans("Parameter").''.$langs->trans("Value").''.$langs->trans("Example").''.$langs->trans("Example").'
'; $help = img_help(1, $langs->trans("EMailHelpMsgSPFDKIM")); print $langs->trans("MailingEMailFrom").' '.$help.''; -print ''; +print ''; if (!empty($conf->global->MAILING_EMAIL_FROM) && !isValidEmail($conf->global->MAILING_EMAIL_FROM)) { print ' '.img_warning($langs->trans("BadEMail")); } -print ''.dol_escape_htmltag(($mysoc->name ? $mysoc->name : 'MyName').' ').''.dol_escape_htmltag(($mysoc->name ? $mysoc->name : 'MyName').' ').'
'; print $langs->trans("MailingEMailError").''; -print ''; +print ''; if (!empty($conf->global->MAILING_EMAIL_ERRORSTO) && !isValidEmail($conf->global->MAILING_EMAIL_ERRORSTO)) { print ' '.img_warning($langs->trans("BadEMail")); } -print 'webmaster@example.com>webmaster@example.com>
'; print $langs->trans("MailingDelay").''; print ''; -print '
'; print $langs->trans("ActivateCheckReadKey").''; -print ''; +print ''; if (!empty($conf->use_javascript_ajax)) { print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token" class="linkobject"'); } -print '
'; $blacklist_setting=array(0=>$langs->trans('No'), 1=>$langs->trans('Yes'), 2=>$langs->trans('DefaultStatusEmptyMandatory')); print $form->selectarray("MAILING_CONTACT_DEFAULT_BULK_STATUS", $blacklist_setting, $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS); print '
'; print $langs->trans("MailAdvTargetRecipients").''; print ajax_constantonoff('EMAILING_USE_ADVANCED_SELECTOR'); - print '
'; @@ -768,7 +768,7 @@ if ($action == 'create') { print dol_get_fiche_end(); - print $form->buttonsSaveCancel("CreateMailing", ''); + print $form->buttonsSaveCancel("CreateMailing", 'Cancel'); print ''; } else { @@ -1314,7 +1314,7 @@ if ($action == 'create') { print '
'; print ''; - print '     '; + print '     '; print ''; print '
'; diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index ed3cfce4163..fa2f3a3a83b 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -394,7 +394,7 @@ if ($object->fetch($id) >= 0) { if (empty($obj->picto)) { $obj->picto = 'generic'; } - print img_object($langs->trans("EmailingTargetSelector").': '.get_class($obj), $obj->picto, 'class="valignmiddle pictomodule"'); + print img_object($langs->trans("EmailingTargetSelector").': '.get_class($obj), $obj->picto, 'class="valignmiddle pictomodule pictofixedwidth"'); print ' '; print $obj->getDesc(); print ''; @@ -633,10 +633,12 @@ if ($object->fetch($id) >= 0) { include_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; include_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; + include_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; $objectstaticmember = new Adherent($db); $objectstaticuser = new User($db); $objectstaticcompany = new Societe($db); $objectstaticcontact = new Contact($db); + $objectstaticeventorganization = new ConferenceOrBoothAttendee($db); while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); @@ -662,6 +664,9 @@ if ($object->fetch($id) >= 0) { } elseif ($obj->source_type == 'contact') { $objectstaticcontact->fetch($obj->source_id); print $objectstaticcontact->getNomUrl(1); + } elseif ($obj->source_type == 'eventorganizationattendee') { + $objectstaticeventorganization->fetch($obj->source_id); + print $objectstaticeventorganization->getNomUrl(1); } else { print $obj->source_url; } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 4a4a02e87c4..7cc4be35f70 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -40,7 +40,7 @@ * \brief File of class to manage invoices */ -include_once DOL_DOCUMENT_ROOT.'/core/class/commoninvoice.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commoninvoice.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php'; diff --git a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php index e361941b704..6a16f4fa641 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php @@ -72,13 +72,9 @@ foreach ($linkedObjectBlock as $key => $objectlink) { print ''; print ''; // Ref - print ''; + print ''; // Onwer print ''; diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index aa2ee4b3e6a..c81ccb769ab 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1279,7 +1279,7 @@ class FormMail extends Form * * @param DoliDB $dbs Database handler * @param string $type_template Get message for model/type=$type_template, type='all' also included. - * @param User $user Get template public or limited to this user + * @param User $user Get templates public + limited to this user * @param Translate $outputlangs Output lang object * @param int $id Id of template to get, or -1 for first found with position 0, or 0 for first found whatever is position (priority order depends on lang provided or not) or -2 for exact match with label (no answer if not found) * @param int $active 1=Only active template, 0=Only disabled, -1=All diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 9c8928de718..430c3a708d2 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -66,14 +66,15 @@ class FormProjets * @param int $forcefocus Force focus on field (works with javascript only) * @param int $disabled Disabled * @param int $mode 0 for HTML mode and 1 for JSON mode - * @param string $filterkey Key to filter + * @param string $filterkey Key to filter on ref or title * @param int $nooutput No print output. Return it only. * @param int $forceaddid Force to add project id in list, event if not qualified * @param string $morecss More css * @param int $htmlid Html id to use instead of htmlname + * @param string $morefilter More filters (Must be a sql sanitized string) * @return string Return html content */ - public function select_projects($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 16, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $morecss = '', $htmlid = '') + public function select_projects($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 16, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $morecss = '', $htmlid = '', $morefilter = '') { // phpcs:enable global $langs, $conf, $form; @@ -96,16 +97,14 @@ class FormProjets $selected_input_value = $project->ref; } $urloption = 'socid='.((int) $socid).'&htmlname='.urlencode($htmlname).'&discardclosed='.((int) $discard_closed); - + if ($morefilter == 'usage_organize_event=1') { + $urloption .= '&usage_organize_event=1'; + } $out .= ''; - $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array( - // 'update' => array( - // 'projectid' => 'id' - // ) - )); + $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array()); } else { - $out .= $this->select_projects_list($socid, $selected, $htmlname, $maxlength, $option_only, $show_empty, abs($discard_closed), $forcefocus, $disabled, 0, $filterkey, 1, $forceaddid, $htmlid, $morecss); + $out .= $this->select_projects_list($socid, $selected, $htmlname, $maxlength, $option_only, $show_empty, abs($discard_closed), $forcefocus, $disabled, 0, $filterkey, 1, $forceaddid, $htmlid, $morecss, $morefilter); } if ($discard_closed > 0) { if (!empty($form)) { @@ -135,14 +134,15 @@ class FormProjets * @param int $forcefocus Force focus on field (works with javascript only) * @param int $disabled Disabled * @param int $mode 0 for HTML mode and 1 for array return (to be used by json_encode for example) - * @param string $filterkey Key to filter + * @param string $filterkey Key to filter on title or ref * @param int $nooutput No print output. Return it only. * @param int $forceaddid Force to add project id in list, event if not qualified * @param int $htmlid Html id to use instead of htmlname * @param string $morecss More CSS + * @param string $morefilter More filters (Must be a sql sanitized string) * @return int Nb of project if OK, <0 if KO */ - public function select_projects_list($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 24, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $htmlid = '', $morecss = 'maxwidth500') + public function select_projects_list($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 24, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $htmlid = '', $morecss = 'maxwidth500', $morefilter = '') { // phpcs:enable global $user, $conf, $langs; @@ -187,6 +187,9 @@ class FormProjets if (!empty($filterkey)) { $sql .= natural_search(array('p.title', 'p.ref'), $filterkey); } + if ($morefilter) { + $sql .= ' AND ('.$this->db->sanitize($morefilter, 0, 1).')'; + } $sql .= " ORDER BY p.ref ASC"; $resql = $this->db->query($sql); diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php index 2d2ea33a6c5..16b2fd956fe 100644 --- a/htdocs/core/db/DoliDB.class.php +++ b/htdocs/core/db/DoliDB.class.php @@ -136,15 +136,12 @@ abstract class DoliDB implements Database * * @param string $stringtosanitize String to escape * @param int $allowsimplequote 1=Allow simple quotes in string. When string is used as a list of SQL string ('aa', 'bb', ...) + * @param string $allowsequals 1=Allow equals sign * @return string String escaped */ - public function sanitize($stringtosanitize, $allowsimplequote = 0) + public function sanitize($stringtosanitize, $allowsimplequote = 0, $allowsequals = 0) { - if ($allowsimplequote) { - return preg_replace('/[^a-z0-9_\-\.,\']/i', '', $stringtosanitize); - } else { - return preg_replace('/[^a-z0-9_\-\.,]/i', '', $stringtosanitize); - } + return preg_replace('/[^a-z0-9_\-\.,'.($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').']/i', '', $stringtosanitize); } /** diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 74e3afaa141..b5450f7317f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1813,7 +1813,7 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di * @param array $links Array of tabs (0=>url, 1=>label, 2=>code, 3=>not used, 4=>text after link, 5=>morecssonlink). Currently initialized by calling a function xxx_admin_prepare_head. Note that label into $links[$i][1] must be already HTML escaped. * @param string $active Active tab name (document', 'info', 'ldap', ....) * @param string $title Title - * @param int $notab -1 or 0=Add tab header, 1=no tab header (if you set this to 1, using print dol_get_fiche_end() to close tab is not required), -2=Add tab header with no seaparation under tab (to start a tab just after) + * @param int $notab -1 or 0=Add tab header, 1=no tab header (if you set this to 1, using print dol_get_fiche_end() to close tab is not required), -2=Add tab header with no sepaaration under tab (to start a tab just after), -3=Add tab header but no footer separation * @param string $picto Add a picto on tab title * @param int $pictoisfullpath If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto. * @param string $morehtmlright Add more html content on right of tabs title @@ -8858,7 +8858,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' $forbiddenphpstrings = array('$$'); $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST')); - $forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI", 'verifCond'); + $forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI", "verifCond", "base64_decode"); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask")); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func")); diff --git a/htdocs/core/modules/mailings/eventorganization.modules.php b/htdocs/core/modules/mailings/eventorganization.modules.php new file mode 100644 index 00000000000..84c27c5f673 --- /dev/null +++ b/htdocs/core/modules/mailings/eventorganization.modules.php @@ -0,0 +1,212 @@ + + * Copyright (C) 2005-2010 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * + * This file is an example to follow to add your own email selector inside + * the Dolibarr email tool. + * Follow instructions given in README file to know what to change to build + * your own emailing list selector. + * Code that need to be changed in this file are marked by "CHANGE THIS" tag. + */ + +/** + * \file htdocs/core/modules/mailings/eventorganization.modules.php + * \ingroup mailing + * \brief Example file to provide a list of recipients for mailing module + */ + + +// Load Dolibarr Environment +include_once DOL_DOCUMENT_ROOT.'/core/modules/mailings/modules_mailings.php'; + + +/** + * Class to manage a list of personalised recipients for mailing feature + */ +class mailing_eventorganization extends MailingTargets +{ + // This label is used if no translation is found for key XXX neither MailingModuleDescXXX where XXX=name is found + public $name = 'AttendeesOfOrganizedEvent'; + public $desc = "Attendees of an organized event"; + + public $require_admin = 0; + + public $require_module = array(); // This module allows to select by categories must be also enabled if category module is not activated + + /** + * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png + */ + public $picto = 'conferenceorbooth'; + + /** + * @var DoliDB Database handler. + */ + public $db; + + public $enabled = 'isModEnabled("eventorganization")'; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf, $langs; + $langs->load('companies'); + + $this->db = $db; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * This is the main function that returns the array of emails + * + * @param int $mailing_id Id of mailing. No need to use it. + * @return int <0 if error, number of emails added if ok + */ + public function add_to_target($mailing_id) + { + // phpcs:enable + global $conf, $langs; + + $cibles = array(); + $addDescription = ''; + + $sql = "SELECT p.ref, p.entity, e.rowid as id, e.fk_project, e.email as email, e.email_company as company_name, e.firstname as firstname, e.lastname as lastname,"; + $sql .= " 'eventorganizationattendee' as source"; + $sql .= " FROM ".MAIN_DB_PREFIX."eventorganization_conferenceorboothattendee as e,"; + $sql .= " ".MAIN_DB_PREFIX."projet as p"; + $sql .= " WHERE e.email <> ''"; + $sql .= " AND e.fk_project = p.rowid"; + $sql .= " AND p.entity IN (".getEntity('project').")"; + $sql .= " AND e.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; + $sql .= " AND e.fk_project = ".((int) GETPOST('filter_eventorganization', 'int')); + $sql .= " ORDER BY e.email"; + + // Stock recipients emails into targets table + $result = $this->db->query($sql); + if ($result) { + $num = $this->db->num_rows($result); + $i = 0; + $j = 0; + + dol_syslog(get_class($this)."::add_to_target mailing ".$num." targets found"); + + $old = ''; + while ($i < $num) { + $obj = $this->db->fetch_object($result); + if ($old <> $obj->email) { + $otherTxt = ($obj->ref ? $langs->transnoentities("Project").'='.$obj->ref : ''); + if (strlen($addDescription) > 0 && strlen($otherTxt) > 0) { + $otherTxt .= ";"; + } + $otherTxt .= $addDescription; + $cibles[$j] = array( + 'email' => $obj->email, + 'fk_project' => $obj->fk_project, + 'lastname' => $obj->lastname, + 'firstname' => $obj->firstname, + 'other' => $otherTxt, + 'source_url' => $this->url($obj->id, $obj->source), + 'source_id' => $obj->id, + 'source_type' => $obj->source + ); + $old = $obj->email; + $j++; + } + + $i++; + } + } else { + dol_syslog($this->db->error()); + $this->error = $this->db->error(); + return -1; + } + + return parent::addTargetsToDatabase($mailing_id, $cibles); + } + + + /** + * On the main mailing area, there is a box with statistics. + * If you want to add a line in this report you must provide an + * array of SQL request that returns two field: + * One called "label", One called "nb". + * + * @return array Array with SQL requests + */ + public function getSqlArrayForStats() + { + // CHANGE THIS: Optionnal + + //var $statssql=array(); + //$this->statssql[0]="SELECT field1 as label, count(distinct(email)) as nb FROM mytable WHERE email IS NOT NULL"; + return array(); + } + + + /** + * Return here number of distinct emails returned by your selector. + * For example if this selector is used to extract 500 different + * emails from a text file, this function must return 500. + * + * @param string $sql Requete sql de comptage + * @return int|string Nb of recipient, or <0 if error, or '' if NA + */ + public function getNbOfRecipients($sql = '') + { + global $conf; + + $sql = "SELECT COUNT(DISTINCT(e.email)) as nb"; + $sql .= " FROM ".MAIN_DB_PREFIX."eventorganization_conferenceorboothattendee as e, "; + $sql .= " ".MAIN_DB_PREFIX."projet as p"; + $sql .= " WHERE e.email <> ''"; + $sql .= " AND e.fk_project = p.rowid"; + $sql .= " AND p.entity IN (".getEntity('project').")"; + + //print $sql; + + // La requete doit retourner un champ "nb" pour etre comprise par parent::getNbOfRecipients + return parent::getNbOfRecipients($sql); + } + + /** + * This is to add a form filter to provide variant of selector + * If used, the HTML select must be called "filter" + * + * @return string A html select zone + */ + public function formFilter() + { + global $conf, $langs; + + $langs->load("companies"); + + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; + $formproject = new FormProjets($this->db); + $s .= $formproject->select_projects(-1, 0, "filter_eventorganization", 0, 0, 1, 1, 0, 0, 0, '', 1, 0, '', '', 'usage_organize_event=1'); + + return $s; + } + + + /** + * Can include an URL link on each record provided by selector shown on target page. + * + * @param int $id ID + * @param string $sourcetype Source type + * @return string Url link + */ + public function url($id, $sourcetype = 'thirdparty') + { + if ($sourcetype == 'project') { + return ''.img_object('', "eventorganization").''; + } + + return ''; + } +} diff --git a/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php b/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php index 9083b643900..1f8f3f82f7c 100644 --- a/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php +++ b/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php @@ -219,6 +219,7 @@ class mailing_thirdparties_services_expired extends MailingTargets $s = ''; print ''; if ($backtopage) { @@ -522,7 +524,7 @@ if ($action == 'create') { print ''."\n"; } - print dol_get_fiche_head('', ''); + print dol_get_fiche_head(''); print '
'.dol_print_date($objectlink->date, 'day').''; if (!empty($objectlink) && $objectlink->element == 'facture' && $user->hasRight('facture', 'lire')) { - $sign = 1; - if ($objectlink->type == Facture::TYPE_CREDIT_NOTE) { - $sign = -1; - } if ($objectlink->statut != 3) { // If not abandonned - $total = $total + $sign * $objectlink->total_ht; + $total += $objectlink->total_ht; echo price($objectlink->total_ht); } else { echo ''.price($objectlink->total_ht).''; diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index c5b0dda6cf2..37a2d74c5e3 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -402,6 +402,9 @@ if ($resql) { if (!empty($limit)) { print ''; } + if ($type != '') { + print ''; + } $title = $langs->trans("InvoiceWaitingWithdraw"); if ($type == 'bank-transfer') { diff --git a/htdocs/compta/prelevement/list.php b/htdocs/compta/prelevement/list.php index 571c78358e0..4690fd3bbb2 100644 --- a/htdocs/compta/prelevement/list.php +++ b/htdocs/compta/prelevement/list.php @@ -192,6 +192,9 @@ if ($result) { print ''; print ''; print ''; + if ($type != '') { + print ''; + } $title = $langs->trans("WithdrawalsLines"); if ($type == 'bank-transfer') { diff --git a/htdocs/compta/prelevement/orders_list.php b/htdocs/compta/prelevement/orders_list.php index 4fe9e23a8cd..5aca0730f67 100644 --- a/htdocs/compta/prelevement/orders_list.php +++ b/htdocs/compta/prelevement/orders_list.php @@ -161,7 +161,9 @@ if ($result) { print ''; print ''; print ''; - + if ($type != '') { + print ''; + } $titlekey = "WithdrawalsReceipts"; $title = $langs->trans("WithdrawalsReceipts"); if ($type == 'bank-transfer') { diff --git a/htdocs/compta/resultat/clientfourn.php b/htdocs/compta/resultat/clientfourn.php index 908d0ae4ac2..eb76b7a7af7 100644 --- a/htdocs/compta/resultat/clientfourn.php +++ b/htdocs/compta/resultat/clientfourn.php @@ -302,7 +302,7 @@ if ($modecompta == 'BOOKKEEPING') { if (!empty($date_start) && !empty($date_end)) { $sql .= " AND f.doc_date >= '".$db->idate($date_start)."' AND f.doc_date <= '".$db->idate($date_end)."'"; } - $sql .= " GROUP BY pcg_type DESC"; + $sql .= " GROUP BY pcg_type"; if ($showaccountdetail == 'no') { $sql .= ", name, socid"; // group by "accounting group" (INCOME/EXPENSE), then "customer". } diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index 6342e08a34e..e1731984229 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -271,12 +271,10 @@ class FormActions break; } - $ref = $actioncomm->getNomUrl(1, -1); - print '
'.$ref.''.$actioncomm->getNomUrl(1, -1).''; @@ -310,7 +308,7 @@ class FormActions $labeltype .= ' - '.$arraylist[$actionstatic->code]; // Use code in priority on type_code } } - print ''; + print ''; print $actioncomm->getTypePicto(); print $labeltype; print '
'; @@ -692,13 +694,8 @@ if ($action == 'create') { } -/* ************************************************************************** */ -/* */ -/* View mode */ -/* */ -/* ************************************************************************** */ - -if ($id) { +// View mode +if ($id > 0) { $head = salaries_prepare_head($object); $formconfirm = ''; @@ -794,34 +791,26 @@ if ($id) { $morehtmlref .= ''; } + $usercancreate = $permissiontoadd; + // Project if (isModEnabled('project')) { - $morehtmlref .= '
'.$langs->trans('Project').' '; - if ($user->rights->salaries->write) { + $langs->load("projects"); + $morehtmlref .= '
'; + if ($usercancreate) { + $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); if ($action != 'classify') { - $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' : '; - } - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= $formproject->select_projects(-1, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500'); - $morehtmlref .= ''; - $morehtmlref .= ''; - } else { - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, ''); } else { if (!empty($object->fk_project)) { $proj = new Project($db); $proj->fetch($object->fk_project); - $morehtmlref .= ' : '.$proj->getNomUrl(1); + $morehtmlref .= $proj->getNomUrl(1); if ($proj->title) { - $morehtmlref .= ' - '.$proj->title; + $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; } - } else { - $morehtmlref .= ''; } } } diff --git a/htdocs/salaries/document.php b/htdocs/salaries/document.php index 163042dbeb8..2ce7b2e2745 100644 --- a/htdocs/salaries/document.php +++ b/htdocs/salaries/document.php @@ -78,7 +78,9 @@ $childids = $user->getAllChildIds(1); // fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); -$object = new Salary($db); +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('salarydoc', 'globalcard')); + if ($id > 0 || !empty($ref)) { $object->fetch($id, $ref); @@ -105,7 +107,9 @@ if ($user->socid) { } restrictedArea($user, 'salaries', $object->id, 'salary', ''); +$permissiontoread = $user->rights->salaries->read; $permissiontoadd = $user->rights->salaries->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles +$permissiontodelete = $user->rights->salaries->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); /* @@ -176,34 +180,26 @@ if ($object->id) { $morehtmlref .= '
'.$langs->trans('Employee').' : '.$userstatic->getNomUrl(-1); + $usercancreate = $permissiontoadd; + // Project if (isModEnabled('project')) { - $morehtmlref .= '
'.$langs->trans('Project').' '; - if ($user->rights->salaries->write) { + $langs->load("projects"); + $morehtmlref .= '
'; + if ($usercancreate) { + $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); if ($action != 'classify') { - $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' : '; - } - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= $formproject->select_projects(-1, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500'); - $morehtmlref .= ''; - $morehtmlref .= ''; - } else { - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, -1, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, ''); } else { if (!empty($object->fk_project)) { $proj = new Project($db); $proj->fetch($object->fk_project); - $morehtmlref .= ' : '.$proj->getNomUrl(1); + $morehtmlref .= $proj->getNomUrl(1); if ($proj->title) { - $morehtmlref .= ' - '.$proj->title; + $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; } - } else { - $morehtmlref .= ''; } } } diff --git a/htdocs/salaries/info.php b/htdocs/salaries/info.php index e16493ddc91..1085b1175cf 100644 --- a/htdocs/salaries/info.php +++ b/htdocs/salaries/info.php @@ -58,6 +58,9 @@ $childids = $user->getAllChildIds(1); // fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('salaryinfo', 'globalcard')); + $object = new Salary($db); if ($id > 0 || !empty($ref)) { $object->fetch($id, $ref); @@ -77,6 +80,10 @@ if ($id > 0 || !empty($ref)) { restrictedArea($user, 'salaries', $object->id, 'salary', ''); +$permissiontoread = $user->rights->salaries->read; +$permissiontoadd = $user->rights->salaries->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles +$permissiontodelete = $user->rights->salaries->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); + /* * Actions @@ -107,7 +114,6 @@ $title = $langs->trans('Salary')." - ".$langs->trans('Info'); $help_url = ""; llxHeader("", $title, $help_url); -$object = new Salary($db); $object->fetch($id); $object->info($id); @@ -139,34 +145,26 @@ if ($action != 'editlabel') { $morehtmlref .= '
'.$langs->trans('Employee').' : '.$userstatic->getNomUrl(-1); +$usercancreate = $permissiontoadd; + // Project if (isModEnabled('project')) { - $morehtmlref .= '
'.$langs->trans('Project').' '; - if ($user->rights->salaries->write) { + $langs->load("projects"); + $morehtmlref .= '
'; + if ($usercancreate) { + $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); if ($action != 'classify') { - $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' : '; - } - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= ''; - $morehtmlref .= $formproject->select_projects(-1, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500'); - $morehtmlref .= ''; - $morehtmlref .= ''; - } else { - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, ''); } else { if (!empty($object->fk_project)) { $proj = new Project($db); $proj->fetch($object->fk_project); - $morehtmlref .= ' : '.$proj->getNomUrl(1); + $morehtmlref .= $proj->getNomUrl(1); if ($proj->title) { - $morehtmlref .= ' - '.$proj->title; + $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; } - } else { - $morehtmlref .= ''; } } } @@ -180,7 +178,7 @@ print '
'; print '
'; -print '
'; +print '
'; dol_print_object_info($object); print '
'; diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 3901db79cc4..f68122bdfff 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -1154,7 +1154,7 @@ class Thirdparties extends DolibarrApi */ public function getCompanyBankAccount($id) { - if (!DolibarrApiAccess::$user->rights->facture->lire) { + if (!DolibarrApiAccess::$user->rights->societe->lire) { throw new RestException(401); } if (empty($id)) { diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 6f246a0ce96..ce4c6760aab 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1395,6 +1395,12 @@ select.flat.selectlimit { overflow: hidden; height: auto !important; } +.tenlinesmax { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 10; + overflow: hidden; +} .tablelistofcalendars { margin-top: 25px !important; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 2324da32c43..71c45545961 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1514,6 +1514,12 @@ select.flat.selectlimit { overflow: hidden; height: auto !important; } +.tenlinesmax { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 10; + overflow: hidden; +} .tablelistofcalendars { margin-top: 25px !important;