Merge remote-tracking branch 'upstream/develop' into develop_hotfix19760

# Conflicts:
#	htdocs/install/mysql/migration/15.0.0-16.0.0.sql
This commit is contained in:
Juanjo Menent 2022-01-25 16:25:44 +01:00
commit 56cb81287e
269 changed files with 4030 additions and 2463 deletions

View File

@ -15,7 +15,7 @@ NEW: Add option to disable globaly some notifications emails.
NEW: #18326 Workflow: Close order on shipment closing.
NEW: #18401 Add __NEWREF__ subtitute to get new object reference.
NEW: #18403 Add __URL_SHIPMENT__ substitute to get the URL of a shipment
NEW: #18689 REST API module: add api key generate / modify right.
NEW: #18689 REST API module: add api key generate / modify pemrission.
NEW: #18663 Make "L'Annuaire des Entreprises" the default provider for SIREN verification for French thirdparties.
NEW: #18046 Add tags on ticket/categories
NEW: #18326 Workflow: Close order on shipment closing.
@ -109,6 +109,13 @@ NEW: External backups can be downloaded from the "About info page".
NEW: Add massaction to switch status on sale / on purchase of a product.
Modules
NEW: Stable module Knowledge Management
NEW: Experimental module Event Organization Management
NEW: Experimental module Workstations Management
NEW: Development of module Partnership Management
For developers:
---------------
@ -116,6 +123,7 @@ NEW: Introduce method hasRight
NEW: Can use textarea field into a confirm popup.
NEW: Can use the result_mode of mysqli driver. Save memory for list count
NEW: #18319 REST API - Shipment: Add 'close' action / endpoint / POST method.
NEW: Add API /approve and /makeOrder for purchase orders.
NEW: add action trigger for member excluded
NEW: add option MAIN_IBAN_IS_NEVER_MANDATORY, MAIN_IBAN_NOT_MANDATORY, PROPAL_NOT_BILLABLE, PROPAL_REOPEN_UNSIGNED_ONLY, PROPOSAL_ARE_NOT_BILLABLE, TICKETS_MESSAGE_FORCE_MAIL
NEW: Add code codebar column on serial/lot structure

View File

@ -39,15 +39,13 @@ RUN chmod +x /usr/local/bin/docker-run.sh
RUN pecl install xdebug && docker-php-ext-enable xdebug
RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so"' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.remote_autostart=1' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.remote_enable=1' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.default_enable=1' >> ${PHP_INI_DIR}/php.ini
#RUN echo 'xdebug.remote_host=docker.host' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.remote_port=9000' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.remote_connect_back=1' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.profiler_enable=0' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.remote_log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
#RUN echo 'localhost docker.host' >> /etc/hosts
RUN echo 'xdebug.mode=debug' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.start_with_request=yes' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.client_host=host.docker.internal' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.client_port=9003' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.discover_client_host=true' >> ${PHP_INI_DIR}/php.ini
#RUN echo 'xdebug.log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
RUN echo 'xdebug.idekey="netbeans-xdebug"' >> ${PHP_INI_DIR}/php.ini
# set up sendmail config, to use maildev
RUN echo "account default" > /etc/msmtprc

View File

@ -48,6 +48,7 @@ services:
- external-pod
extra_hosts:
- "localhost.localdomain:127.0.0.1"
- "host.docker.internal:host-gateway"
mail:
image: maildev/maildev

View File

@ -94,9 +94,15 @@ class AdherentType extends CommonObject
*/
public $amount;
/** @var string Public note */
/**
* @var string Public note
* @deprecated
*/
public $note;
/** @var string Public note */
public $note_public;
/** @var integer Can vote */
public $vote;
@ -358,6 +364,10 @@ class AdherentType extends CommonObject
$this->label = trim($this->label);
if (empty($this->note_public) && !empty($this->note)) { // For backward compatibility
$this->note_public = $this->note;
}
$this->db->begin();
$sql = "UPDATE ".MAIN_DB_PREFIX."adherent_type ";
@ -368,14 +378,14 @@ class AdherentType extends CommonObject
$sql .= "subscription = '".$this->db->escape($this->subscription)."',";
$sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? 'null' : ((float) $this->amount)).",";
$sql .= "duration = '".$this->db->escape($this->duration_value.$this->duration_unit)."',";
$sql .= "note = '".$this->db->escape($this->note)."',";
$sql .= "note = '".$this->db->escape($this->note_public)."',";
$sql .= "vote = ".(integer) $this->db->escape($this->vote).",";
$sql .= "mail_valid = '".$this->db->escape($this->mail_valid)."'";
$sql .= " WHERE rowid =".((int) $this->id);
$result = $this->db->query($sql);
if ($result) {
$this->description = $this->db->escape($this->note);
$this->description = $this->db->escape($this->note_public);
// Multilangs
if (!empty($conf->global->MAIN_MULTILANGS)) {
@ -461,7 +471,7 @@ class AdherentType extends CommonObject
{
global $langs, $conf;
$sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.mail_valid, d.note, d.vote";
$sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.mail_valid, d.note as note_public, d.vote";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d";
$sql .= " WHERE d.rowid = ".(int) $rowid;
@ -483,7 +493,8 @@ class AdherentType extends CommonObject
$this->subscription = $obj->subscription;
$this->amount = $obj->amount;
$this->mail_valid = $obj->mail_valid;
$this->note = $obj->note;
$this->note = $obj->note_public; // deprecated
$this->note_public = $obj->note_public;
$this->vote = $obj->vote;
// multilangs
@ -792,12 +803,16 @@ class AdherentType extends CommonObject
// Object classes
$info["objectclass"] = explode(',', $conf->global->LDAP_MEMBER_TYPE_OBJECT_CLASS);
if (empty($this->note_public) && !empty($this->note)) { // For backward compatibility
$this->note_public = $this->note;
}
// Champs
if ($this->label && !empty($conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME)) {
$info[$conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME] = $this->label;
}
if ($this->note && !empty($conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION)) {
$info[$conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note, 0, 'UTF-8', 1);
if ($this->note_public && !empty($conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION)) {
$info[$conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_public, 0, 'UTF-8', 1);
}
if (!empty($conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS)) {
$valueofldapfield = array();
@ -829,7 +844,7 @@ class AdherentType extends CommonObject
$this->specimen = 1;
$this->label = 'MEMBERS TYPE SPECIMEN';
$this->note = 'This is a note';
$this->note_public = 'This is a public note';
$this->mail_valid = 'This is welcome email';
$this->subscription = 1;
$this->vote = 0;

View File

@ -215,7 +215,7 @@ class Subscription extends CommonObject
$sql .= " tms,";
$sql .= " dateadh as dateh,";
$sql .= " datef,";
$sql .= " subscription, note, fk_bank";
$sql .= " subscription, note as note_public, fk_bank";
$sql .= " FROM ".MAIN_DB_PREFIX."subscription";
$sql .= " WHERE rowid=".((int) $rowid);
@ -235,7 +235,8 @@ class Subscription extends CommonObject
$this->dateh = $this->db->jdate($obj->dateh);
$this->datef = $this->db->jdate($obj->datef);
$this->amount = $obj->subscription;
$this->note = $obj->note;
$this->note = $obj->note_public; // deprecated
$this->note_public = $obj->note_public;
$this->fk_bank = $obj->fk_bank;
return 1;
} else {
@ -266,10 +267,14 @@ class Subscription extends CommonObject
return -1;
}
if (empty($this->note_public) && !empty($this->note)) { // For backward compatibility
$this->note_public = $this->note;
}
$sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET ";
$sql .= " fk_type = ".((int) $this->fk_type).",";
$sql .= " fk_adherent = ".((int) $this->fk_adherent).",";
$sql .= " note=".($this->note ? "'".$this->db->escape($this->note)."'" : 'null').",";
$sql .= " note=".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : 'null').",";
$sql .= " subscription = ".price2num($this->amount).",";
$sql .= " dateadh='".$this->db->idate($this->dateh)."',";
$sql .= " datef='".$this->db->idate($this->datef)."',";

View File

@ -1163,9 +1163,13 @@ if ($rowid > 0) {
print dol_get_fiche_end();
print '<div class="center">';
print '<input type="submit" class="button" name="add" value="'.$langs->trans("AddSubscription").'">';
print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
$parameters = array();
$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
if (empty($reshook)) {
print '<input type="submit" class="button" name="add" value="'.$langs->trans("AddSubscription").'">';
print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
}
print '</div>';
print '</form>';

View File

@ -158,18 +158,6 @@ if ($action == 'updateMask') {
$error++;
}
if (!$error) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
} elseif ($action == "setshippableiconinlist") {
// Activate Set Shippable Icon In List
$setshippableiconinlist = GETPOST('value', 'int');
$res = dolibarr_set_const($db, "SHIPPABLE_ORDER_ICON_IN_LIST", $setshippableiconinlist, 'yesno', 0, '', $conf->entity);
if (!($res > 0)) {
$error++;
}
if (!$error) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
@ -646,25 +634,6 @@ print '<input type="submit" class="button button-edit" value="'.$langs->trans("M
print "</td></tr>\n";
print '</form>';
// Shippable Icon in List
/* Kept as hidden feature for the moment, result seems bugged.
Where is definition of "shippable" according to all different STOCK_CALCULATE_... options ?
print '<tr class="oddeven">';
print '<td>'.$langs->trans("ShippableOrderIconInList").'</td>';
print '<td>&nbsp;</td>';
print '<td class="center">';
if (!empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=setshippableiconinlist&token='.newToken().'&value=0">';
print img_picto($langs->trans("Activated"),'switch_on');
} else {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=setshippableiconinlist&token='.newToken().'&value=1">';
print img_picto($langs->trans("Disabled"),'switch_off');
}
print '</a></td>';
print '</tr>';
*/
/*
// Seems to be not so used. So kept hidden for the moment to avoid dangerous options inflation.
// Ask for payment bank during order

View File

@ -1,6 +1,5 @@
div.divsearchfield {
float: left;
margin: 4px 12px 4px 2px;
padding-left: 2px;
}

View File

@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/eventorganization.lib.php';
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
// Translations
$langs->loadLangs(array("admin", "eventorganization"));
$langs->loadLangs(array("admin", "eventorganization", "categories"));
// Parameters
$action = GETPOST('action', 'aZ09');
@ -54,11 +54,11 @@ $arrayofparameters = array(
'EVENTORGANIZATION_TEMPLATE_EMAIL_ASK_BOOTH'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'EVENTORGANIZATION_TEMPLATE_EMAIL_AFT_SUBS_BOOTH'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'EVENTORGANIZATION_TEMPLATE_EMAIL_AFT_SUBS_EVENT'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_SPEAKER'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'EVENTORGANIZATION_SECUREKEY'=>array('type'=>'securekey', 'enabled'=>1),
//'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_SPEAKER'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
//'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1),
'SERVICE_BOOTH_LOCATION'=>array('type'=>'product', 'enabled'=>1),
'SERVICE_CONFERENCE_ATTENDEE_SUBSCRIPTION'=>array('type'=>'product', 'enabled'=>1),
'EVENTORGANIZATION_SECUREKEY'=>array('type'=>'securekey', 'enabled'=>1),
);
$error = 0;

View File

@ -28,24 +28,91 @@
*/
require '../main.inc.php';
// Libraries
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
// Load translation files required by the page
$langs->loadLangs(array('admin', 'errors', 'other', 'bills'));
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$hookmanager->initHooks(array('situationinvoicesetup', 'globalsetup'));
// Access control
if (!$user->admin) {
accessforbidden();
}
$action = GETPOST('action', 'aZ09');
$backtopage = GETPOST('backtopage', 'alpha');
$value = GETPOST('value', 'alpha');
$label = GETPOST('label', 'alpha');
$scandir = GETPOST('scan_dir', 'alpha');
$type = 'invoice';
$form = new Form($db);
$formSetup = new FormSetup($db);
// Setup conf MYMODULE_MYPARAM4 : exemple of quick define write style
$formSetup->newItem('INVOICE_USE_SITUATION')
->setAsYesNo()
->nameText = $langs->trans('UseSituationInvoices');
$item = $formSetup->newItem('INVOICE_USE_SITUATION_CREDIT_NOTE')
->setAsYesNo()
->nameText = $langs->trans('UseSituationInvoicesCreditNote');
//$item = $formSetup->newItem('INVOICE_USE_RETAINED_WARRANTY')
// ->setAsYesNo()
// ->nameText = $langs->trans('Retainedwarranty');
$item = $formSetup->newItem('INVOICE_USE_RETAINED_WARRANTY');
$item->nameText = $langs->trans('AllowedInvoiceForRetainedWarranty');
$arrayAvailableType = array(
Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation"),
Facture::TYPE_STANDARD.'+'.Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation").' + '.$langs->trans("InvoiceStandard"),
);
if ($action == 'edit') {
$item->fieldInputOverride = $form->selectarray('INVOICE_USE_RETAINED_WARRANTY', $arrayAvailableType, $conf->global->INVOICE_USE_RETAINED_WARRANTY, 1);
} else {
$item->fieldOutputOverride= isset($arrayAvailableType[$conf->global->INVOICE_USE_RETAINED_WARRANTY])?$arrayAvailableType[$conf->global->INVOICE_USE_RETAINED_WARRANTY]:'';
}
//$item = $formSetup->newItem('INVOICE_RETAINED_WARRANTY_LIMITED_TO_SITUATION')->setAsYesNo();
//$item->nameText = $langs->trans('RetainedwarrantyOnlyForSituation');
$formSetup->newItem('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION')
->setAsYesNo()
->nameText = $langs->trans('RetainedwarrantyOnlyForSituationFinal');
$item = $formSetup->newItem('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT');
$item->nameText = $langs->trans('RetainedwarrantyDefaultPercent');
$item->fieldAttr = array(
'type' => 'number',
'step' => '0.01',
'min' => 0,
'max' => 100
);
// Conditions paiements
$item = $formSetup->newItem('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID');
$item->nameText = $langs->trans('PaymentConditionsShortRetainedWarranty');
$form->load_cache_conditions_paiements();
if (!empty($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID) && isset($form->cache_conditions_paiements[$conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID]['label'])) {
$item->fieldOutputOverride = $form->cache_conditions_paiements[$conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID]['label'];
}
$item->fieldInputOverride = $form->getSelectConditionsPaiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID', -1, 1);
/*
* Actions
@ -67,7 +134,6 @@ llxHeader(
'EN:Invoice_Configuration|FR:Configuration_module_facture|ES:ConfiguracionFactura'
);
$form = new Form($db);
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
@ -84,170 +150,25 @@ print '<span class="opacitymedium">'.$langs->trans("InvoiceFirstSituationDesc").
* Numbering module
*/
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
if ($action == 'edit') {
print $formSetup->generateOutput(true);
} else {
print $formSetup->generateOutput();
}
if (count($formSetup->items) > 0) {
if ($action != 'edit') {
print '<div class="tabsAction">';
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&token='.newToken().'">'.$langs->trans("Modify").'</a>';
print '</div>';
}
} else {
print '<br>'.$langs->trans("NothingToSetup");
}
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Parameter").'</td>';
print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
print '<td width="80">&nbsp;</td>';
print "</tr>\n";
_printOnOff('INVOICE_USE_SITUATION', $langs->trans('UseSituationInvoices'));
_printOnOff('INVOICE_USE_SITUATION_CREDIT_NOTE', $langs->trans('UseSituationInvoicesCreditNote'));
//_printOnOff('INVOICE_USE_RETAINED_WARRANTY', $langs->trans('Retainedwarranty'));
$confkey = 'INVOICE_USE_RETAINED_WARRANTY';
$arrayAvailableType = array(
Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation"),
Facture::TYPE_STANDARD.'+'.Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation").' + '.$langs->trans("InvoiceStandard"),
);
$selected = $conf->global->$confkey;
$curentInput = (empty($inputCount) ? 1 : ($inputCount + 1));
$formSelectInvoiceType = $form->selectarray('value'.$curentInput, $arrayAvailableType, $selected, 1);
_printInputFormPart($confkey, $langs->trans('AllowedInvoiceForRetainedWarranty'), '', array(), $formSelectInvoiceType);
//_printOnOff('INVOICE_RETAINED_WARRANTY_LIMITED_TO_SITUATION', $langs->trans('RetainedwarrantyOnlyForSituation'));
_printOnOff('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION', $langs->trans('RetainedwarrantyOnlyForSituationFinal'));
$metas = array(
'type' => 'number',
'step' => '0.01',
'min' => 0,
'max' => 100
);
_printInputFormPart('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT', $langs->trans('RetainedwarrantyDefaultPercent'), '', $metas);
// Conditions paiements
$inputCount = empty($inputCount) ? 1 : ($inputCount + 1);
print '<tr class="oddeven">';
print '<td>'.$langs->trans('PaymentConditionsShortRetainedWarranty').'</td>';
print '<td class="center" width="20">&nbsp;</td>';
print '<td class="right" width="300">';
print '<input type="hidden" name="param'.$inputCount.'" value="INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID">';
$form->select_conditions_paiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'value'.$inputCount, -1, 1);
print '</td></tr>';
print '</table>';
print '</div>';
print '<br>';
_updateBtn();
print '</form>';
print dol_get_fiche_end();
// End of page
llxFooter();
$db->close();
/**
* Print an update button
*
* @return void
*/
function _updateBtn()
{
global $langs;
print '<div class="center">';
print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
print '</div>';
}
/**
* Print a On/Off button
*
* @param string $confkey the conf key
* @param bool $title Title of conf
* @param string $desc Description
*
* @return void
*/
function _printOnOff($confkey, $title = false, $desc = '')
{
global $langs;
print '<tr class="oddeven">';
print '<td>'.($title ? $title : $langs->trans($confkey));
if (!empty($desc)) {
print '<br><small>'.$langs->trans($desc).'</small>';
}
print '</td>';
print '<td class="center" width="20">&nbsp;</td>';
print '<td class="right" width="300">';
print ajax_constantonoff($confkey);
print '</td></tr>';
}
/**
* Print a form part
*
* @param string $confkey the conf key
* @param bool $title Title of conf
* @param string $desc Description of
* @param array $metas html meta
* @param string $type type of input textarea or input
* @param bool $help help description
*
* @return void
*/
function _printInputFormPart($confkey, $title = false, $desc = '', $metas = array(), $type = 'input', $help = false)
{
global $langs, $conf, $db, $inputCount;
$inputCount = empty($inputCount) ? 1 : ($inputCount + 1);
$form = new Form($db);
$defaultMetas = array(
'name' => 'value'.$inputCount
);
if ($type != 'textarea') {
$defaultMetas['type'] = 'text';
$defaultMetas['value'] = $conf->global->{$confkey};
}
$metas = array_merge($defaultMetas, $metas);
$metascompil = '';
foreach ($metas as $key => $values) {
$metascompil .= ' '.$key.'="'.$values.'" ';
}
print '<tr class="oddeven">';
print '<td>';
if (!empty($help)) {
print $form->textwithtooltip(($title ? $title : $langs->trans($confkey)), $langs->trans($help), 2, 1, img_help(1, ''));
} else {
print $title ? $title : $langs->trans($confkey);
}
if (!empty($desc)) {
print '<br><small>'.$langs->trans($desc).'</small>';
}
print '</td>';
print '<td class="center" width="20">&nbsp;</td>';
print '<td class="right" width="300">';
print '<input type="hidden" name="param'.$inputCount.'" value="'.$confkey.'">';
print '<input type="hidden" name="action" value="setModuleOptions">';
if ($type == 'textarea') {
print '<textarea '.$metascompil.' >'.dol_htmlentities($conf->global->{$confkey}).'</textarea>';
} elseif ($type == 'input') {
print '<input '.$metascompil.' />';
} else {
// custom
print $type;
}
print '</td></tr>';
}

View File

@ -535,11 +535,11 @@ if ($mode == 'common' || $mode == 'commonkanban') {
//$moreforfilter .= '<div class="floatright center marginrightonly hideonsmartphone" style="padding-top: 3px"><span class="paddingright">'.$moreinfo.'</span> '.$moreinfo2.'</div>';
$moreforfilter .= '<div class="colorbacktimesheet float valignmiddle">';
$moreforfilter .= '<div class="divsearchfield paddingtop">';
$moreforfilter .= '<div class="divfilteralone colorbacktimesheet float valignmiddle">';
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
$moreforfilter .= img_picto($langs->trans("Filter"), 'filter', 'class="paddingright opacityhigh hideonsmartphone"').'<input type="text" id="search_keyword" name="search_keyword" class="maxwidth125" value="'.dol_escape_htmltag($search_keyword).'" placeholder="'.dol_escape_htmltag($langs->trans('Keyword')).'">';
$moreforfilter .= '</div>';
$moreforfilter .= '<div class="divsearchfield paddingtop">';
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
$moreforfilter .= $form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), $langs->trans('Origin'), 0, 0, '', 0, 0, 0, '', 'maxwidth250', 1);
$moreforfilter .= '</div>';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) {
@ -553,16 +553,16 @@ if ($mode == 'common' || $mode == 'commonkanban') {
if ($conf->global->MAIN_FEATURES_LEVEL > 1) {
$array_version['development'] = $langs->trans("Development");
}
$moreforfilter .= '<div class="divsearchfield paddingtop">';
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
$moreforfilter .= $form->selectarray('search_version', $array_version, $search_version, $langs->trans('Version'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1);
$moreforfilter .= '</div>';
}
$moreforfilter .= '<div class="divsearchfield paddingtop">';
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
$moreforfilter .= $form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, $langs->trans('Status'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1);
$moreforfilter .= '</div>';
$moreforfilter .= ' ';
$moreforfilter .= '<div class="divsearchfield">';
$moreforfilter .= '<input type="submit" name="buttonsubmit" class="button" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
$moreforfilter .= '<div class="divsearchfield valignmiddle inline-block">';
$moreforfilter .= '<input type="submit" name="buttonsubmit" class="button small" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
if ($search_keyword || ($search_nature && $search_nature != '-1') || ($search_version && $search_version != '-1') || ($search_status && $search_status != '-1')) {
$moreforfilter .= ' ';
$moreforfilter .= '<input type="submit" name="buttonreset" class="buttonreset noborderbottom" value="'.dol_escape_htmltag($langs->trans("Reset")).'">';
@ -1139,7 +1139,7 @@ if ($mode == 'deploy') {
}
if ($allowfromweb == 1) {
print $langs->trans("UnpackPackageInModulesRoot", $dirins).'<br>';
print '<span class="opacitymedium">'.$langs->trans("UnpackPackageInModulesRoot", $dirins).'</span><br>';
print '<br>';

View File

@ -400,8 +400,6 @@ print '</td>';
print '</tr>';
print '</table>';
print '</td></tr>';
print '</table>';
@ -538,6 +536,8 @@ if (!empty($_SESSION["commandbackuptorun"])) {
print "</div> <!-- end div center button -->\n";
print '</td></tr>';
print '</table>';
print "</div> <!-- end div fichehalfleft -->\n";

View File

@ -137,7 +137,7 @@ $dirtocompress = basename($fulldirtocompress);
if ($compression == 'zip') {
$file .= '.zip';
$excludefiles = '/(\.back|\.old|\.log|[\/\\\]temp[\/\\\]|documents[\/\\\]admin[\/\\\]documents[\/\\\])/i';
$excludefiles = '/(\.back|\.old|\.log|\.pdf_preview-.*\.png|[\/\\\]temp[\/\\\]|documents[\/\\\]admin[\/\\\]documents[\/\\\])/i';
//var_dump($fulldirtocompress);
//var_dump($outputdir."/".$file);exit;
@ -173,7 +173,7 @@ if ($compression == 'zip') {
// We also exclude '/temp/' dir and 'documents/admin/documents'
// We make escapement here and call executeCLI without escapement because we don't want to have the '*.log' escaped.
$cmd = "tar -cf ".escapeshellcmd($outputdir."/".$file)." --exclude-vcs --exclude-caches-all --exclude='temp' --exclude='*.log' --exclude='documents/admin/documents' -C '".escapeshellcmd(dol_sanitizePathName($dirtoswitch))."' '".escapeshellcmd(dol_sanitizeFileName($dirtocompress))."'";
$cmd = "tar -cf ".escapeshellcmd($outputdir."/".$file)." --exclude-vcs --exclude-caches-all --exclude='temp' --exclude='*.log' --exclude='*.pdf_preview-*.png' --exclude='documents/admin/documents' -C '".escapeshellcmd(dol_sanitizePathName($dirtoswitch))."' '".escapeshellcmd(dol_sanitizeFileName($dirtocompress))."'";
$result = $utils->executeCLI($cmd, $outputfile, 0, null, 1);

View File

@ -624,6 +624,9 @@ class Documents extends DolibarrApi
} elseif ($modulepart == 'expensereport') {
require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
$object = new ExpenseReport($this->db);
} elseif ($modulepart == 'fichinter') {
require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
$object = new Fichinter($this->db);
} elseif ($modulepart == 'adherent' || $modulepart == 'member') {
$modulepart = 'adherent';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';

View File

@ -261,6 +261,11 @@ class Commande extends CommonOrder
//! key of pos source ('0', '1', ...)
public $pos_source;
/**
* @var array Array with line of all shipments
*/
public $expeditions;
/**
* 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
@ -490,7 +495,8 @@ class Commande extends CommonOrder
$sql .= " SET ref = '".$this->db->escape($num)."',";
$sql .= " fk_statut = ".self::STATUS_VALIDATED.",";
$sql .= " date_valid='".$this->db->idate($now)."',";
$sql .= " fk_user_valid = ".((int) $user->id);
$sql .= " fk_user_valid = ".((int) $user->id).",";
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id);
dol_syslog(get_class($this)."::valid", LOG_DEBUG);
@ -620,7 +626,8 @@ class Commande extends CommonOrder
$this->db->begin();
$sql = "UPDATE ".MAIN_DB_PREFIX."commande";
$sql .= " SET fk_statut = ".self::STATUS_DRAFT;
$sql .= " SET fk_statut = ".self::STATUS_DRAFT."',";
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id);
if ($this->db->query($sql)) {
@ -694,7 +701,8 @@ class Commande extends CommonOrder
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'commande';
$sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0';
$sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0,';
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id);
dol_syslog(get_class($this)."::set_reopen", LOG_DEBUG);
@ -755,7 +763,8 @@ class Commande extends CommonOrder
$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
$sql .= ' SET fk_statut = '.self::STATUS_CLOSED.',';
$sql .= ' fk_user_cloture = '.((int) $user->id).',';
$sql .= " date_cloture = '".$this->db->idate($now)."'";
$sql .= " date_cloture = '".$this->db->idate($now)."',";
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > '.self::STATUS_DRAFT;
if ($this->db->query($sql)) {
@ -803,7 +812,8 @@ class Commande extends CommonOrder
$this->db->begin();
$sql = "UPDATE ".MAIN_DB_PREFIX."commande";
$sql .= " SET fk_statut = ".self::STATUS_CANCELED;
$sql .= " SET fk_statut = ".self::STATUS_CANCELED.",";
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id);
$sql .= " AND fk_statut = ".self::STATUS_VALIDATED;
@ -1779,7 +1789,7 @@ class Commande extends CommonOrder
return -1;
}
$sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_statut';
$sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_user_modif, c.fk_statut';
$sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason';
$sql .= ', c.fk_account';
$sql .= ', c.date_commande, c.date_valid, c.tms';
@ -1844,6 +1854,7 @@ class Commande extends CommonOrder
$this->user_author_id = $obj->fk_user_author;
$this->user_valid = $obj->fk_user_valid;
$this->user_modification = $obj->fk_user_modif;
$this->total_ht = $obj->total_ht;
$this->total_tva = $obj->total_tva;
$this->total_localtax1 = $obj->total_localtax1;
@ -2004,9 +2015,9 @@ class Commande extends CommonOrder
/**
* Load array lines
*
* @param int $only_product Return only physical products, not services
* @param int $only_product Return only physical products, not services
* @param int $loadalsotranslation Return translation for products
* @return int <0 if KO, >0 if OK
* @return int <0 if KO, >0 if OK
*/
public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
{
@ -2201,9 +2212,10 @@ class Commande extends CommonOrder
* Note: For a dedicated shipment, the fetch_lines can be used to load the qty_asked and qty_shipped. This function is use to return qty_shipped cumulated for the order
*
* @param int $filtre_statut Filter on shipment status
* @param int $fk_product Add a filter on a product
* @return int <0 if KO, Nb of lines found if OK
*/
public function loadExpeditions($filtre_statut = -1)
public function loadExpeditions($filtre_statut = -1, $fk_product = 0)
{
$this->expeditions = array();

View File

@ -1854,10 +1854,13 @@ if ($resql) {
print '<td class="center">';
if (!empty($show_shippable_command) && !empty($conf->stock->enabled)) {
if (($obj->fk_statut > $generic_commande::STATUS_DRAFT) && ($obj->fk_statut < $generic_commande::STATUS_CLOSED)) {
$generic_commande->getLinesArray(); // This set ->lines
$generic_commande->getLinesArray(); // Load array ->lines
$generic_commande->loadExpeditions(); // Load array ->expeditions
$numlines = count($generic_commande->lines); // Loop on each line of order
for ($lig = 0; $lig < $numlines; $lig++) {
$reliquat = $generic_commande->lines[$lig]->qty - $generic_commande->expeditions[$generic_commande->lines[$lig]->id];
if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0) { // If line is a product and not a service
$nbprod++; // order contains real products
$generic_product->id = $generic_commande->lines[$lig]->fk_product;
@ -1872,15 +1875,15 @@ if ($resql) {
$generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
}
if ($reliquat > $generic_product->stock_reel) {
$notshippable++;
}
if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) { // Default code. Default should be this case.
$text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->product_ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
$text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->product_ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 20);
$text_info .= ' - '.$langs->trans("Stock").': <span class="'.($generic_product->stock_reel > 0 ? 'ok' : 'error').'">'.$generic_product->stock_reel.'</span>';
$text_info .= ' - '.$langs->trans("VirtualStock").': <span class="'.($generic_product->stock_theorique > 0 ? 'ok' : 'error').'">'.$generic_product->stock_theorique.'</span>';
$text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' <span class="opacitymedium">('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')</span>' : '');
$text_info .= '<br>';
if ($generic_commande->lines[$lig]->qty > $generic_product->stock_reel) {
$notshippable++;
}
} else { // BUGGED CODE.
// DOES NOT TAKE INTO ACCOUNT MANUFACTURING. THIS CODE SHOULD BE USELESS. PREVIOUS CODE SEEMS COMPLETE.
// COUNT STOCK WHEN WE SHOULD ALREADY HAVE VALUE
@ -1908,32 +1911,31 @@ if ($resql) {
$stock_order_supplier = $generic_product->stats_commande_fournisseur['qty'];
}
}
$text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
$text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 20);
$text_stock_reel = $generic_product->stock_reel.'/'.$stock_order;
if ($stock_order > $generic_product->stock_reel && !($generic_product->stock_reel < $generic_commande->lines[$lig]->qty)) {
$warning++;
$text_warning .= '<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
}
if ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty) {
$notshippable++;
if ($reliquat > $generic_product->stock_reel) {
$text_info .= '<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
} else {
$text_info .= '<span class="ok">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
}
if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) {
$text_info .= '&nbsp;'.$langs->trans('SupplierOrder').'&nbsp;:&nbsp;'.$stock_order_supplier.'<br>';
} else {
$text_info .= '<br>';
$text_info .= '&nbsp;'.$langs->trans('SupplierOrder').'&nbsp;:&nbsp;'.$stock_order_supplier;
}
$text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' <span class="opacitymedium">('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')</span>' : '');
$text_info .= '<br>';
}
}
}
if ($notshippable == 0) {
$text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'green paddingleft');
$text_info = $langs->trans('Shippable').'<br>'.$text_info;
$text_info = $text_icon.' '.$langs->trans('Shippable').'<br>'.$text_info;
} else {
$text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'error paddingleft');
$text_info = $langs->trans('NonShippable').'<br>'.$text_info;
$text_info = $text_icon.' '.$langs->trans('NonShippable').'<br>'.$text_info;
}
}

View File

@ -1339,14 +1339,15 @@ if ($resql) {
$labeltoshow = $langs->trans($reg[1]);
} else {
if ($objp->label == '(payment_salary)') {
$labeltoshow = dol_trunc($langs->trans("SalaryPayment", 40));
$labeltoshow = $langs->trans("SalaryPayment");
} else {
$labeltoshow = dol_escape_htmltag($objp->label);
$titletoshow = $objp->label;
}
}
print '<td class="tdoverflowmax300"'.($titletoshow ? ' title="'.dol_escape_htmltag($titletoshow).'"' : '').'>';
print $labeltoshow; // Already escaped
print '<td class="tdoverflowmax250"'.($titletoshow ? ' title="'.dol_escape_htmltag($titletoshow).'"' : '').'>';
// Add info about links after description
$cachebankaccount = array();
@ -1355,70 +1356,70 @@ if ($resql) {
if ($links[$key]['type'] == 'withdraw') {
$banktransferstatic->id = $links[$key]['url_id'];
$banktransferstatic->ref = $links[$key]['label'];
print ' '.$banktransferstatic->getNomUrl(0);
print $banktransferstatic->getNomUrl(0).' ';
} elseif ($links[$key]['type'] == 'payment') {
$paymentstatic->id = $links[$key]['url_id'];
$paymentstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment
$paymentstatic->date = $db->jdate($objp->do);
print ' '.$paymentstatic->getNomUrl(2);
print $paymentstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_supplier') {
$paymentsupplierstatic->id = $links[$key]['url_id'];
$paymentsupplierstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment
print ' '.$paymentsupplierstatic->getNomUrl(2);
print $paymentsupplierstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_sc') {
$paymentscstatic->id = $links[$key]['url_id'];
$paymentscstatic->ref = $links[$key]['url_id'];
$paymentscstatic->label = $links[$key]['label'];
print ' '.$paymentscstatic->getNomUrl(2);
print $paymentscstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_vat') {
$paymentvatstatic->id = $links[$key]['url_id'];
$paymentvatstatic->ref = $links[$key]['url_id'];
print ' '.$paymentvatstatic->getNomUrl(2);
print $paymentvatstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_salary') {
$paymentsalstatic->id = $links[$key]['url_id'];
$paymentsalstatic->ref = $links[$key]['url_id'];
$paymentsalstatic->label = $links[$key]['label'];
print ' '.$paymentsalstatic->getNomUrl(2);
print $paymentsalstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_loan') {
print '<a href="'.DOL_URL_ROOT.'/loan/payment/card.php?id='.$links[$key]['url_id'].'">';
print ' '.img_object($langs->trans('ShowPayment'), 'payment').' ';
print '</a>';
print '</a> ';
} elseif ($links[$key]['type'] == 'payment_donation') {
$paymentdonationstatic->id = $links[$key]['url_id'];
$paymentdonationstatic->ref = $links[$key]['url_id'];
print ' '.$paymentdonationstatic->getNomUrl(2);
print $paymentdonationstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_expensereport') {
$paymentexpensereportstatic->id = $links[$key]['url_id'];
$paymentexpensereportstatic->ref = $links[$key]['url_id'];
print ' '.$paymentexpensereportstatic->getNomUrl(2);
print $paymentexpensereportstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'payment_various') {
$paymentvariousstatic->id = $links[$key]['url_id'];
$paymentvariousstatic->ref = $links[$key]['url_id'];
print ' '.$paymentvariousstatic->getNomUrl(2);
print $paymentvariousstatic->getNomUrl(2).' ';
} elseif ($links[$key]['type'] == 'banktransfert') {
// Do not show link to transfer since there is no transfer card (avoid confusion). Can already be accessed from transaction detail.
if ($objp->amount > 0) {
$banklinestatic->fetch($links[$key]['url_id']);
$bankstatic->id = $banklinestatic->fk_account;
$bankstatic->label = $banklinestatic->bank_account_ref;
print ' ('.$langs->trans("TransferFrom").' ';
print $langs->trans("TransferFrom").' ';
print $bankstatic->getNomUrl(1, 'transactions');
print ' '.$langs->trans("toward").' ';
$bankstatic->id = $objp->bankid;
$bankstatic->label = $objp->bankref;
print $bankstatic->getNomUrl(1, '');
print ')';
print ' - ';
} else {
$bankstatic->id = $objp->bankid;
$bankstatic->label = $objp->bankref;
print ' ('.$langs->trans("TransferFrom").' ';
print $langs->trans("TransferFrom").' ';
print $bankstatic->getNomUrl(1, '');
print ' '.$langs->trans("toward").' ';
$banklinestatic->fetch($links[$key]['url_id']);
$bankstatic->id = $banklinestatic->fk_account;
$bankstatic->label = $banklinestatic->bank_account_ref;
print $bankstatic->getNomUrl(1, 'transactions');
print ')';
print ' - ';
}
//var_dump($links);
} elseif ($links[$key]['type'] == 'company') {
@ -1430,22 +1431,22 @@ if ($resql) {
// Information is already shown using the payment_salary link. No need of this link.
} else {
// Show link with label $links[$key]['label']
if (!empty($objp->label) && !empty($links[$key]['label'])) {
print ' - ';
}
print '<a href="'.$links[$key]['url'].$links[$key]['url_id'].'">';
if (preg_match('/^\((.*)\)$/i', $links[$key]['label'], $reg)) {
// Label generique car entre parentheses. On l'affiche en le traduisant
if ($reg[1] == 'paiement') {
$reg[1] = 'Payment';
}
print ' '.$langs->trans($reg[1]);
print $langs->trans($reg[1]);
} else {
print ' '.$links[$key]['label'];
print $links[$key]['label'];
}
print '</a>';
print '</a>'.($labeltoshow ? ' - ' : '');
}
}
print $labeltoshow; // Already escaped
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
@ -1488,7 +1489,7 @@ if ($resql) {
// Payment type
if (!empty($arrayfields['type']['checked'])) {
print '<td align="center" class="nowrap">';
print '<td class="tdoverflowmax100 center">';
$labeltype = ($langs->trans("PaymentTypeShort".$objp->fk_type) != "PaymentTypeShort".$objp->fk_type) ? $langs->trans("PaymentTypeShort".$objp->fk_type) : $langs->getLabelFromKey($db, $objp->fk_type, 'c_paiement', 'code', 'libelle', '', 1);
if ($labeltype == 'SOLD') {
print '&nbsp;'; //$langs->trans("InitialBankBalance");
@ -1514,9 +1515,9 @@ if ($resql) {
print '<td class="tdoverflowmax150">';
$companylinked_id = 0;
$userlinked_id = 0;
$userlinked_id = 0;
//payment line type to define user display and user or company linked
//payment line type to define user display and user or company linked
foreach ($links as $key => $value) {
if ($links[$key]['type'] == 'payment_sc') {
$type_link = 'payment_sc';

View File

@ -130,6 +130,7 @@ $usercanread = $user->rights->facture->lire;
$usercancreate = $user->rights->facture->creer;
$usercanissuepayment = $user->rights->facture->paiement;
$usercandelete = $user->rights->facture->supprimer;
$usercancreatecontract = $user->rights->contrat->creer;
$usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->validate)));
$usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->send)));
$usercanreopen = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->reopen)));
@ -609,7 +610,7 @@ if (empty($reshook)) {
// Check parameters
// Check for mandatory fields in thirdparty (defined into setup)
$array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL');
$array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL', 'ACCOUNTANCY_CODE_CUSTOMER');
foreach ($array_to_check as $key) {
$keymin = strtolower($key);
$i = (int) preg_replace('/[^0-9]/', '', $key);
@ -637,6 +638,14 @@ if (empty($reshook)) {
setEventMessages($langs->trans("ErrorBadEMail", $object->thirdparty->email).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
}
}
if ($key == 'ACCOUNTANCY_CODE_CUSTOMER') {
// Check for mandatory
if (!empty($conf->global->SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY) && empty($object->thirdparty->code_compta)) {
$langs->load("errors");
$error++;
setEventMessages($langs->trans("ErrorAccountancyCodeCustomerIsMandatory", $object->thirdparty->name).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
}
}
}
}
@ -3417,6 +3426,10 @@ if ($action == 'create') {
$optionsav .= '<option value="'.$key.'"';
if ($key == GETPOST('fac_avoir')) {
$optionsav .= ' selected';
// pre-filled extra fields with selected credit note
$newinvoice_static->fetch_optionals($key);
$object->array_options = $newinvoice_static->array_options;
}
$optionsav .= '>';
$optionsav .= $newinvoice_static->ref;
@ -5378,6 +5391,17 @@ if ($action == 'create') {
}
}
// Create contract
if (!empty($conf->global->CONTRACT_CREATE_FROM_INVOICE)) {
if ($conf->contrat->enabled && $object->statut == Facture::STATUS_VALIDATED) {
$langs->load("contracts");
if ($usercancreatecontract) {
print '<a class="butAction" href="' . DOL_URL_ROOT . '/contrat/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans('AddContract') . '</a>';
}
}
}
// Validate
if ($object->statut == Facture::STATUS_DRAFT && count($object->lines) > 0 && ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA || $object->type == Facture::TYPE_SITUATION) && (!empty($conf->global->FACTURE_ENABLE_NEGATIVE) || $object->total_ttc >= 0)) || ($object->type == Facture::TYPE_CREDIT_NOTE && $object->total_ttc <= 0))) {
if ($usercanvalidate) {

View File

@ -1622,7 +1622,7 @@ class Facture extends CommonInvoice
if ($rowid) {
$sql .= " WHERE f.rowid=".((int) $rowid);
} else {
$sql .= ' WHERE f.entity IN ('.getEntity('invoice').')'; // Dont't use entity if you use rowid
$sql .= ' WHERE f.entity IN ('.getEntity('invoice').')'; // Don't use entity if you use rowid
if ($ref) {
$sql .= " AND f.ref='".$this->db->escape($ref)."'";
}

117
htdocs/contact/project.php Normal file
View File

@ -0,0 +1,117 @@
<?php
/*
* Copyright (C) 2021 VIAL--GOUTEYRON Quentin <quentin.vial-gouteyron@atm-consulting.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/contact/project.php
* \ingroup contact
* \brief Page of third party projects
*/
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
$langs->loadLangs(array("contacts", "companies", "projects"));
// Security check
$id = GETPOST('id', 'int');
$result = restrictedArea($user, 'contact', $id, 'socpeople&societe');
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$hookmanager->initHooks(array('projectcontact'));
/*
* Actions
*/
$parameters = array('id' => $id);
$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');
}
/*
* View
*/
$form = new Form($db);
if ($id) {
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/contact.lib.php';
$object = new Contact($db);
$result = $object->fetch($id);
if (empty($object->thirdparty)) {
$object->fetch_thirdparty();
}
$socid = $object->thirdparty->id;
$title = $langs->trans("Projects");
if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) {
$title = $object->name." - ".$title;
}
llxHeader('', $title);
if (! empty($conf->notification->enabled)) {
$langs->load("mails");
}
$head = contact_prepare_head($object);
print dol_get_fiche_head($head, 'project', $langs->trans("Contact"), -1, 'contact');
$linkback = '<a href="'.DOL_URL_ROOT.'/contact/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<div class="refidno">';
if (empty($conf->global->SOCIETE_DISABLE_CONTACTS) && !empty($socid)) {
$object->thirdparty->fetch($socid);
// Thirdparty
$morehtmlref .= $langs->trans('ThirdParty').' : ';
if ($object->thirdparty->id > 0) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'contact');
} else {
$morehtmlref .= $langs->trans("ContactNotLinkedToCompany");
}
}
$morehtmlref .= '</div>';
dol_banner_tab($object, 'id', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom', $morehtmlref);
print '<div class="fichecenter">';
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">';
// Civility
print '<tr><td class="titlefield">'.$langs->trans("UserTitle").'</td><td>';
print $object->getCivilityLabel();
print '</td></tr>';
print '</table>';
print '</div>';
print dol_get_fiche_end();
print '<br>';
// Projects list
$result = show_contacts_projects($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?id='.$object->id, 1);
}
// End of page
llxFooter();
$db->close();

View File

@ -245,6 +245,8 @@ if ($id > 0) {
$newcardbutton = '';
if (!empty($conf->agenda->enabled)) {
if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) {
$backtopage = $_SERVER['PHP_SELF'].'?id='.$object->id;
$out = '&origin='.$object->element.'&originid='.$object->id.'&backtopage='.urlencode($backtopage);
$newcardbutton .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create'.$out);
}
}

View File

@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
if (!empty($conf->propal->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
}
@ -248,6 +249,10 @@ if (empty($reshook)) {
if ($element == 'propal') {
$element = 'comm/propal'; $subelement = 'propal';
}
if ($element == 'invoice' || $element == 'facture') {
$element = 'compta/facture';
$subelement = 'facture';
}
$object->origin = $origin;
$object->origin_id = $originid;
@ -1040,6 +1045,10 @@ if ($action == 'create') {
if ($element == 'propal') {
$element = 'comm/propal'; $subelement = 'propal';
}
if ($element == 'invoice' || $element == 'facture') {
$element = 'compta/facture';
$subelement = 'facture';
}
dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');

View File

@ -81,7 +81,7 @@ if (!$error && $massaction == 'confirm_presend') {
$listofobjectref = array();
$contactidtosend = array();
$attachedfilesThirdpartyObj = array();
$oneemailperrecipient = (GETPOST('oneemailperrecipient') == 'on' ? 1 : 0);
$oneemailperrecipient = (GETPOST('oneemailperrecipient', 'int') ? 1 : 0);
if (!$error) {
$thirdparty = new Societe($db);

View File

@ -29,13 +29,13 @@
// $formSetup may be defined
if ($action == 'update' && !empty($formSetup) && is_object($formSetup)) {
if ($action == 'update' && !empty($formSetup) && is_object($formSetup) && !empty($user->admin)) {
$formSetup->saveConfFromPost();
return;
}
if ($action == 'update' && is_array($arrayofparameters)) {
if ($action == 'update' && is_array($arrayofparameters) && !empty($user->admin)) {
$db->begin();
foreach ($arrayofparameters as $key => $val) {
@ -72,8 +72,37 @@ if ($action == 'update' && is_array($arrayofparameters)) {
}
}
if ($action == 'deletefile' && $modulepart == 'doctemplates' && !empty($user->admin)) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09');
$listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir))));
foreach ($listofdir as $key => $tmpdir) {
$tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT
if (!$tmpdir) {
unset($listofdir[$key]);
continue;
}
$tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set
if (!is_dir($tmpdir)) {
if (empty($nomessageinsetmoduleoptions)) {
setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings');
}
} else {
$upload_dir = $tmpdir;
break; // So we take the first directory found into setup $conf->global->$keyforuploaddir
}
}
$filetodelete = $tmpdir.'/'.GETPOST('file');
$result = dol_delete_file($filetodelete);
if ($result > 0) {
setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
}
}
// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
if ($action == 'setModuleOptions') {
if ($action == 'setModuleOptions' && !empty($user->admin)) {
$db->begin();
// Process common param fields
@ -97,20 +126,22 @@ if ($action == 'setModuleOptions') {
if (GETPOST('upload', 'alpha') && GETPOST('keyforuploaddir', 'aZ09')) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09');
$listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->$keyforuploaddir)));
$listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir))));
foreach ($listofdir as $key => $tmpdir) {
$tmpdir = trim($tmpdir);
$tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
$tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT
if (!$tmpdir) {
unset($listofdir[$key]);
continue;
}
$tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set
if (!is_dir($tmpdir)) {
if (empty($nomessageinsetmoduleoptions)) {
setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings');
}
} else {
$upload_dir = $tmpdir;
break; // So we take the first directory found into setup $conf->global->$keyforuploaddir
}
}
if ($upload_dir) {

View File

@ -163,7 +163,7 @@ class box_produits_alerte_stock extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"',
'td' => 'class="tdoverflowmax100 maxwidth150onsmartphone"',
'text' => $objp->label,
);
@ -186,18 +186,13 @@ class box_produits_alerte_stock extends ModeleBoxes
}
}
$this->info_box_contents[$line][] = array(
/*$this->info_box_contents[$line][] = array(
'td' => 'class="nowraponall right amount"',
'text' => $price,
);
'text' => $price.' '.$price_base_type,
);*/
$this->info_box_contents[$line][] = array(
'td' => 'class="right"',
'text' => $price_base_type,
);
$this->info_box_contents[$line][] = array(
'td' => 'class="center"',
'td' => 'class="center nowraponall"',
'text' => price2num($objp->total_stock, 'MS').' / '.$objp->seuil_stock_alerte,
'text2'=>img_warning($langs->transnoentitiesnoconv("StockLowerThanLimit", $objp->seuil_stock_alerte)),
);

View File

@ -26,6 +26,7 @@
*/
include_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php";
/**
* Class to manage the box to show last projet
*/
@ -63,7 +64,7 @@ class box_validated_projects extends ModeleBoxes
$langs->loadLangs(array('boxes', 'projects'));
$this->db = $db;
$this->boxlabel = "ProjectsWithTask";
$this->boxlabel = "ProjectTasksWithoutTimeSpent";
$this->hidden = !($user->rights->projet->lire);
@ -116,7 +117,7 @@ class box_validated_projects extends ModeleBoxes
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_contact as ec ON ec.element_id = t.rowid AND fk_c_type_contact IN (-1, -2, -3)";
$sql .= " WHERE p.fk_statut = 1"; // Only open projects
if ($projectsListId) {
$sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only project are allowed
$sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only projects that are allowed
}
$sql .= " AND t.rowid NOT IN (SELECT fk_task FROM ".MAIN_DB_PREFIX."projet_task_time WHERE fk_user = ".((int) $user->id).")";
$sql .= " GROUP BY p.rowid, p.ref, p.fk_soc, p.dateo";

View File

@ -1215,17 +1215,20 @@ abstract class CommonObject
public function delete_linked_contact($source = '', $code = '')
{
// phpcs:enable
$listId = '';
$temp = array();
$typeContact = $this->liste_type_contact($source, '', 0, 0, $code);
foreach ($typeContact as $key => $value) {
array_push($temp, $key);
if (!empty($typeContact)) {
foreach ($typeContact as $key => $value) {
array_push($temp, $key);
}
$listId = implode(",", $temp);
}
$listId = implode(",", $temp);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact";
$sql .= " WHERE element_id = ".((int) $this->id);
if ($listId) {
if (!empty($listId)) {
$sql .= " AND fk_c_type_contact IN (".$this->db->sanitize($listId).")";
}
@ -7595,7 +7598,7 @@ abstract class CommonObject
} else { return true; }
} elseif (in_array($type, array('double', 'real', 'price'))) {
// is numeric
if (!$validate->isDuration($fieldValue)) {
if (!$validate->isNumeric($fieldValue)) {
$this->setFieldError($fieldKey, $validate->error);
return false;
} else { return true; }

View File

@ -258,7 +258,7 @@ class Conf
// Define all global constants into $this->global->key=value
$sql = "SELECT ".$db->decrypt('name')." as name,";
$sql .= " ".$db->decrypt('value')." as value, entity";
$sql .= " FROM ".MAIN_DB_PREFIX."const";
$sql .= " FROM ".$db->prefix()."const";
$sql .= " WHERE entity IN (0,".$this->entity.")";
$sql .= " ORDER BY entity"; // This is to have entity 0 first, then entity 1 that overwrite.

View File

@ -1690,11 +1690,17 @@ class Form
$out .= '<select class="flat'.($moreclass ? ' '.$moreclass : '').'" id="'.$htmlid.'" name="'.$htmlname.(($num || empty($disableifempty)) ? '' : ' disabled').($multiple ? '[]' : '').'" '.($multiple ? 'multiple' : '').' '.(!empty($moreparam) ? $moreparam : '').'>';
}
if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
$out .= '<option value="0"'.(in_array(0, $selected) ? ' selected' : '').'>&nbsp;</option>';
if ($showempty && ! is_numeric($showempty)) {
$textforempty = $showempty;
$out .= '<option class="optiongrey" value="-1"'.(in_array(-1, $selected) ? ' selected' : '').'>'.$textforempty.'</option>';
}
if ($showempty == 2) {
$out .= '<option value="0"'.(in_array(0, $selected) ? ' selected' : '').'>-- '.$langs->trans("Internal").' --</option>';
else {
if (($showempty == 1 || ($showempty == 3 && $num > 1)) && ! $multiple) {
$out .= '<option value="0"'.(in_array(0, $selected) ? ' selected' : '').'>&nbsp;</option>';
}
if ($showempty == 2) {
$out .= '<option value="0"'.(in_array(0, $selected) ? ' selected' : '').'>-- '.$langs->trans("Internal").' --</option>';
}
}
$i = 0;
@ -3896,7 +3902,7 @@ class Form
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Return list of payment modes.
* print list of payment modes.
* Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want.
* See instead to force the default value by the caller.
*
@ -3911,8 +3917,28 @@ class Form
public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '')
{
// phpcs:enable
global $langs, $user, $conf;
print $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss);
}
/**
* Return list of payment modes.
* Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want.
* See instead to force the default value by the caller.
*
* @param int $selected Id of payment term to preselect by default
* @param string $htmlname Nom de la zone select
* @param int $filtertype Not used
* @param int $addempty Add an empty entry
* @param int $noinfoadmin 0=Add admin info, 1=Disable admin info
* @param string $morecss Add more CSS on select tag
* @return void
*/
public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '')
{
global $langs, $user, $conf;
$out = '';
dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
$this->load_cache_conditions_paiements();
@ -3922,24 +3948,25 @@ class Form
$selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
}
print '<select id="'.$htmlname.'" class="flat selectpaymentterms'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
$out.= '<select id="'.$htmlname.'" class="flat selectpaymentterms'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
if ($addempty) {
print '<option value="0">&nbsp;</option>';
$out.= '<option value="0">&nbsp;</option>';
}
foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
if ($selected == $id) {
print '<option value="'.$id.'" selected>';
$out.= '<option value="'.$id.'" selected>';
} else {
print '<option value="'.$id.'">';
$out.= '<option value="'.$id.'">';
}
print $arrayconditions['label'];
print '</option>';
$out.= $arrayconditions['label'];
$out.= '</option>';
}
print '</select>';
$out.= '</select>';
if ($user->admin && empty($noinfoadmin)) {
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
$out.= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
}
print ajax_combobox($htmlname);
$out.= ajax_combobox($htmlname);
return $out;
}

View File

@ -379,9 +379,10 @@ class FormFile
* @param Object $object Object when method is called from an object card.
* @param int $hideifempty Hide section of generated files if there is no file
* @param string $removeaction (optional) The action to remove a file
* @param string $tooltipontemplatecombo Text to show on a tooltip after the combo list of templates
* @return string Output string with HTML array of documents (might be empty string)
*/
public function showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file')
public function showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file', $tooltipontemplatecombo = '')
{
global $dolibarr_main_url_root;
@ -769,6 +770,7 @@ class FormFile
if ($conf->use_javascript_ajax) {
$out .= ajax_combobox('model');
}
$out .= $form->textwithpicto('', $tooltipontemplatecombo, 1, 'help', 'marginrightonly', 0, 3, '', 0);
} else {
$out .= '<div class="float">'.$langs->trans("Files").'</div>';
}

View File

@ -157,6 +157,7 @@ class FormMail extends Form
public $lines_model;
// -1 suggest the checkbox 'one email per recipient' not checked, 0 = no suggestion, 1 = suggest and checked
public $withoptiononeemailperrecipient;
@ -357,7 +358,7 @@ class FormMail extends Form
// phpcs:enable
global $conf, $langs, $user, $hookmanager, $form;
// Required to show preview of mail attachments
// Required to show preview wof mail attachments
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
$formfile = new Formfile($this->db);
@ -366,7 +367,7 @@ class FormMail extends Form
}
// Load translation files required by the page
$langs->loadLangs(array('other', 'mails'));
$langs->loadLangs(array('other', 'mails', 'members'));
// Clear temp files. Must be done before call of triggers, at beginning (mode = init), or when we select a new template
if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
@ -464,11 +465,10 @@ class FormMail extends Form
$modelmail_array = array();
if ($this->param['models'] != 'none') {
$result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
if ($result < 0) {
setEventMessages($this->error, $this->errors, 'errors');
}
$langs->trans("members");
foreach ($this->lines_model as $line) {
$reg = array();
if (preg_match('/\((.*)\)/', $line->label, $reg)) {
@ -503,7 +503,7 @@ class FormMail extends Form
}
$out .= ' &nbsp; ';
$out .= '<input type="submit" class="button" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
$out .= '<input type="submit" class="button reposition" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
$out .= ' &nbsp; ';
$out .= '</div>';
} elseif (!empty($this->param['models']) && in_array($this->param['models'], array(
@ -526,7 +526,7 @@ class FormMail extends Form
}
$out .= '<table class="tableforemailform boxtablenotop" width="100%">'."\n";
$out .= '<table class="tableforemailform boxtablenotop centpercent">'."\n";
// Substitution array/string
$helpforsubstitution = '';
@ -688,16 +688,20 @@ class FormMail extends Form
// With option one email per recipient
if (!empty($this->withoptiononeemailperrecipient)) {
$out .= '<tr><td class="minwidth200">';
$out .= $langs->trans("GroupEmails");
$out .= '</td><td>';
$out .= ' <input type="checkbox" id="oneemailperrecipient" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> ';
$out .= '<label for="oneemailperrecipient">'.$langs->trans("OneEmailPerRecipient").'</label>';
$out .= '<span class="hideonsmartphone opacitymedium">';
$out .= ' - ';
$out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
$out .= '</span>';
$out .= '</td></tr>';
if (abs($this->withoptiononeemailperrecipient) == 1) {
$out .= '<tr><td class="minwidth200">';
$out .= $langs->trans("GroupEmails");
$out .= '</td><td>';
$out .= ' <input type="checkbox" id="oneemailperrecipient" value="1" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> ';
$out .= '<label for="oneemailperrecipient">'.$langs->trans("OneEmailPerRecipient").'</label>';
$out .= '<span class="hideonsmartphone opacitymedium">';
$out .= ' - ';
$out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
$out .= '</span>';
$out .= '</td></tr>';
} else {
$out .= '<tr><td><input type="hidden" name="oneemailperrecipient" value="1"></td><td></td></tr>';
}
}
// CC
@ -813,8 +817,7 @@ class FormMail extends Form
$out .= '<br></div>';
}
} elseif (empty($this->withmaindocfile)) {
// Do not show message if we asked to show the checkbox
$out .= $langs->trans("NoAttachedFiles").'<br>';
$out .= '<span class="opacitymedium">'.$langs->trans("NoAttachedFiles").'</span><br>';
}
if ($this->withfile == 2) {
// Can add other files
@ -1217,6 +1220,7 @@ class FormMail extends Form
global $conf, $langs, $form;
$defaulttopic = GETPOST('subject', 'restricthtml');
if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
if ($arraydefaultmessage && $arraydefaultmessage->topic) {
$defaulttopic = $arraydefaultmessage->topic;

View File

@ -1261,7 +1261,7 @@ class FormTicket
// Zone to select its email template
if (count($modelmail_array) > 0) {
print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1);
print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, "", "", 0, 0, 0, '', 'minwidth200');
if ($user->admin) {
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
}

View File

@ -55,18 +55,17 @@ class Validate
{
global $langs;
if ($outputLang) {
if (empty($outputLang)) {
$this->outputLang = $langs;
} else {
$this->outputLang = $outputLang;
}
if (!is_object($this->outputLang) || !method_exists($outputLang, 'load')) {
if (!is_object($this->outputLang) || !method_exists($this->outputLang, 'load')) {
return false;
}
/** @var Translate $outputLang */
$outputLang->load('validate');
$this->outputLang->loadLangs(array('validate', 'errors'));
$this->db = $db;
}
@ -229,6 +228,21 @@ class Validate
return true;
}
/**
* Check numeric validity
*
* @param mixed $string to validate
* @return boolean Validity is ok or not
*/
public function isNumeric($string)
{
if (!is_numeric($string)) {
$this->error = $this->outputLang->trans('RequireValidNumeric');
return false;
}
return true;
}
/**
* Check for boolean validity
*

View File

@ -57,6 +57,40 @@ function contact_prepare_head(Contact $object)
$head[$tab][2] = 'perso';
$tab++;
if (!empty($conf->projet->enabled) && (!empty($user->rights->projet->lire))) {
$nbProject = 0;
// Enable caching of thirdrparty count projects
require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
$cachekey = 'count_projects_contact_'.$object->id;
$dataretrieved = dol_getcache($cachekey);
if (!is_null($dataretrieved)) {
$nbProject = $dataretrieved;
} else {
$sql = 'SELECT COUNT(n.rowid) as nb';
$sql .= ' FROM '.MAIN_DB_PREFIX.'projet as n';
$sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'element_contact as cc ON (n.rowid = cc.element_id)';
$sql .= ' WHERE cc.fk_socpeople = '.((int) $object->id);
$sql .= ' AND cc.fk_c_type_contact IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'c_type_contact WHERE element="project" AND source="external")';
$sql .= ' AND n.entity IN ('.getEntity('project').')';
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
$nbProject = $obj->nb;
} else {
dol_print_error($db);
}
dol_setcache($cachekey, $nbProject, 120); // If setting cache fails, this is not a problem, so we do not test result.
}
$head[$tab][0] = DOL_URL_ROOT.'/contact/project.php?id='.$object->id;
$head[$tab][1] = $langs->trans("Projects");
if ($nbProject > 0) {
$head[$tab][1] .= '<span class="badge marginleftonlyshort">'.$nbProject.'</span>';
}
$head[$tab][2] = 'project';
$tab++;
}
// Related items
if (!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || !empty($conf->facture->enabled) || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) {
$head[$tab][0] = DOL_URL_ROOT.'/contact/consumption.php?id='.$object->id;
@ -117,3 +151,131 @@ function contact_prepare_head(Contact $object)
return $head;
}
/**
* Show html area for list of projects
*
* @param Conf $conf Object conf
* @param Translate $langs Object langs
* @param DoliDB $db Database handler
* @param Object $object Third party object
* @param string $backtopage Url to go once contact is created
* @param int $nocreatelink 1=Hide create project link
* @param string $morehtmlright More html on right of title
* @return int
*/
function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatelink = 0, $morehtmlright = '')
{
global $user;
$i = -1;
if (!empty($conf->projet->enabled) && $user->rights->projet->lire) {
$langs->load("projects");
$newcardbutton = '';
if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) {
$newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&amp;action=create&amp;backtopage='.urlencode($backtopage));
}
print "\n";
print load_fiche_titre($langs->trans("ProjectsHavingThisContact"), $newcardbutton.$morehtmlright, '');
print '<div class="div-table-responsive">';
print "\n".'<table class="noborder" width=100%>';
$sql = 'SELECT p.rowid as id, p.entity, p.title, p.ref, p.public, p.dateo as do, p.datee as de, p.fk_statut as status, p.fk_opp_status, p.opp_amount, p.opp_percent, p.tms as date_update, p.budget_amount';
$sql .= ', cls.code as opp_status_code, ctc.libelle';
$sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p';
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_lead_status as cls on p.fk_opp_status = cls.rowid';
$sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'element_contact as cc ON (p.rowid = cc.element_id)';
$sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_contact as ctc ON (ctc.rowid = cc.fk_c_type_contact)';
$sql .= ' WHERE cc.fk_socpeople = '.((int) $object->id);
$sql .= ' AND ctc.element="project" AND ctc.source="external"';
$sql .= ' AND p.entity IN ('.getEntity('project').')';
$sql .= ' ORDER BY p.dateo DESC';
$result = $db->query($sql);
if ($result) {
$num = $db->num_rows($result);
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Ref").'</td>';
print '<td>'.$langs->trans("Name").'</td>';
print '<td>'.$langs->trans("ContactType").'</td>';
print '<td class="center">'.$langs->trans("DateStart").'</td>';
print '<td class="center">'.$langs->trans("DateEnd").'</td>';
print '<td class="right">'.$langs->trans("OpportunityAmountShort").'</td>';
print '<td class="center">'.$langs->trans("OpportunityStatusShort").'</td>';
print '<td class="right">'.$langs->trans("OpportunityProbabilityShort").'</td>';
print '<td class="right">'.$langs->trans("Status").'</td>';
print '</tr>';
if ($num > 0) {
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
$projecttmp = new Project($db);
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($result);
$projecttmp->fetch($obj->id);
// To verify role of users
$userAccess = $projecttmp->restrictedProjectArea($user);
if ($user->rights->projet->lire && $userAccess > 0) {
print '<tr class="oddeven">';
// Ref
print '<td>';
print $projecttmp->getNomUrl(1);
print '</td>';
// Label
print '<td>'.$obj->title.'</td>';
print '<td>'.$obj->libelle.'</td>';
// Date start
print '<td class="center">'.dol_print_date($db->jdate($obj->do), "day").'</td>';
// Date end
print '<td class="center">'.dol_print_date($db->jdate($obj->de), "day").'</td>';
// Opp amount
print '<td class="right">';
if ($obj->opp_status_code) {
print price($obj->opp_amount, 1, '', 1, -1, -1, '');
}
print '</td>';
// Opp status
print '<td class="center">';
if ($obj->opp_status_code) {
print $langs->trans("OppStatus".$obj->opp_status_code);
}
print '</td>';
// Opp percent
print '<td class="right">';
if ($obj->opp_percent) {
print price($obj->opp_percent, 1, '', 1, 0).'%';
}
print '</td>';
// Status
print '<td class="right">'.$projecttmp->getLibStatut(5).'</td>';
print '</tr>';
}
$i++;
}
} else {
print '<tr class="oddeven"><td colspan="8"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
}
$db->free($result);
} else {
dol_print_error($db);
}
print "</table>";
print '</div>';
print "<br>\n";
}
return $i;
}

View File

@ -17,6 +17,7 @@
* Copyright (C) 2019 Thibault Foucart <support@ptibogxiv.net>
* Copyright (C) 2020 Open-Dsi <support@open-dsi.fr>
* Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
* Copyright (C) 2022 Anthony Berton <anthony.berton@bb2a.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1544,6 +1545,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename =
// This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it).
$data['ip'] = '???@'.$_SERVER['LOGNAME'];
}
// Loop on each log handler and send output
foreach ($conf->loghandlers as $loghandlerinstance) {
if ($restricttologhandler && $loghandlerinstance->code != $restricttologhandler) {
@ -6951,10 +6953,15 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
'__USER_ID__' => (string) $user->id,
'__USER_LOGIN__' => (string) $user->login,
'__USER_EMAIL__' => (string) $user->email,
'__USER_PHONE__' => (string) dol_print_phone($user->office_phone),
'__USER_PHONEPRO__' => (string) dol_print_phone($user->user_mobile),
'__USER_PHONEMOBILE__' => (string) dol_print_phone($user->personal_mobile),
'__USER_FAX__' => (string) $user->office_fax,
'__USER_LASTNAME__' => (string) $user->lastname,
'__USER_FIRSTNAME__' => (string) $user->firstname,
'__USER_FULLNAME__' => (string) $user->getFullName($outputlangs),
'__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'),
'__USER_JOB__' => (string) $user->job,
'__USER_REMOTE_IP__' => (string) getUserRemoteIP()
));
}
@ -6963,8 +6970,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray = array_merge($substitutionarray, array(
'__MYCOMPANY_NAME__' => $mysoc->name,
'__MYCOMPANY_EMAIL__' => $mysoc->email,
'__MYCOMPANY_PHONE__' => $mysoc->phone,
'__MYCOMPANY_FAX__' => $mysoc->fax,
'__MYCOMPANY_PHONE__' => dol_print_phone($mysoc->phone),
'__MYCOMPANY_FAX__' => dol_print_phone($mysoc->fax),
'__MYCOMPANY_PROFID1__' => $mysoc->idprof1,
'__MYCOMPANY_PROFID2__' => $mysoc->idprof2,
'__MYCOMPANY_PROFID3__' => $mysoc->idprof3,
@ -7112,9 +7119,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__MEMBER_PHOTO__'] = (isset($object->photo) ? $object->photo : '');
$substitutionarray['__MEMBER_LOGIN__'] = (isset($object->login) ? $object->login : '');
$substitutionarray['__MEMBER_PASSWORD__'] = (isset($object->pass) ? $object->pass : '');
$substitutionarray['__MEMBER_PHONE__'] = (isset($object->phone) ? $object->phone : '');
$substitutionarray['__MEMBER_PHONEPRO__'] = (isset($object->phone_perso) ? $object->phone_perso : '');
$substitutionarray['__MEMBER_PHONEMOBILE__'] = (isset($object->phone_mobile) ? $object->phone_mobile : '');
$substitutionarray['__MEMBER_PHONE__'] = (isset($object->phone) ? dol_print_phone($object->phone) : '');
$substitutionarray['__MEMBER_PHONEPRO__'] = (isset($object->phone_perso) ? dol_print_phone($object->phone_perso) : '');
$substitutionarray['__MEMBER_PHONEMOBILE__'] = (isset($object->phone_mobile) ? dol_print_phone($object->phone_mobile) : '');
$substitutionarray['__MEMBER_TYPE__'] = (isset($object->type) ? $object->type : '');
$substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'dayrfc');
$substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->first_subscription_date_start, 'dayrfc');
@ -7131,8 +7138,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__THIRDPARTY_CODE_CLIENT__'] = (is_object($object) ? $object->code_client : '');
$substitutionarray['__THIRDPARTY_CODE_FOURNISSEUR__'] = (is_object($object) ? $object->code_fournisseur : '');
$substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object) ? $object->email : '');
$substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object) ? $object->phone : '');
$substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object) ? $object->fax : '');
$substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object) ? dol_print_phone($object->phone) : '');
$substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object) ? dol_print_phone($object->fax) : '');
$substitutionarray['__THIRDPARTY_ADDRESS__'] = (is_object($object) ? $object->address : '');
$substitutionarray['__THIRDPARTY_ZIP__'] = (is_object($object) ? $object->zip : '');
$substitutionarray['__THIRDPARTY_TOWN__'] = (is_object($object) ? $object->town : '');
@ -7154,8 +7161,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__THIRDPARTY_CODE_CLIENT__'] = (is_object($object->thirdparty) ? $object->thirdparty->code_client : '');
$substitutionarray['__THIRDPARTY_CODE_FOURNISSEUR__'] = (is_object($object->thirdparty) ? $object->thirdparty->code_fournisseur : '');
$substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object->thirdparty) ? $object->thirdparty->email : '');
$substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object->thirdparty) ? $object->thirdparty->phone : '');
$substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object->thirdparty) ? $object->thirdparty->fax : '');
$substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object->thirdparty) ? dol_print_phone($object->thirdparty->phone) : '');
$substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object->thirdparty) ? dol_print_phone($object->thirdparty->fax) : '');
$substitutionarray['__THIRDPARTY_ADDRESS__'] = (is_object($object->thirdparty) ? $object->thirdparty->address : '');
$substitutionarray['__THIRDPARTY_ZIP__'] = (is_object($object->thirdparty) ? $object->thirdparty->zip : '');
$substitutionarray['__THIRDPARTY_TOWN__'] = (is_object($object->thirdparty) ? $object->thirdparty->town : '');
@ -7236,6 +7243,11 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour', 'tzserver', $outputlangs) : '');
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_DAY_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'day', 'tzserver', $outputlangs) : '');
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_RFC__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhourrfc') : '');
} elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'phone') {
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = dol_print_phone($object->array_options['options_'.$key]);
} elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'price') {
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = $object->array_options['options_'.$key];
$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_FORMATED__'] = price($object->array_options['options_'.$key]);
}
}
}

View File

@ -35,9 +35,10 @@
* @param string[] $addheaders Array of string to add into header. Example: ('Accept: application/xrds+xml', ....)
* @param string[] $allowedschemes List of schemes that are allowed ('http' + 'https' only by default)
* @param int $localurl 0=Only external URL are possible, 1=Only local URL, 2=Both external and local URL are allowed.
* @param int $ssl_verifypeer -1=Auto (no ssl check on dev, check on prod), 0=No ssl check, 1=Always ssl check
* @return array Returns an associative array containing the response from the server array('content'=>response, 'curl_error_no'=>errno, 'curl_error_msg'=>errmsg...)
*/
function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = 1, $addheaders = array(), $allowedschemes = array('http', 'https'), $localurl = 0)
function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = 1, $addheaders = array(), $allowedschemes = array('http', 'https'), $localurl = 0, $ssl_verifypeer = -1)
{
//declaring of global variables
global $conf;
@ -75,8 +76,17 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation =
}
//curl_setopt($ch, CURLOPT_SSLVERSION, 6); for tls 1.2
// Turning on or off the ssl target certificate
if ($ssl_verifypeer < 0) {
global $dolibarr_main_prod;
$ssl_verifypeer = ($dolibarr_main_prod ? true : false);
}
if (!empty($conf->global->MAIN_CURL_DISABLE_VERIFYPEER)) {
$ssl_verifypeer = 0;
}
// Turning off the server and peer verification(TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, ($ssl_verifypeer ? true : false));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// Restrict use to some protocols only

View File

@ -823,7 +823,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
}
}
if (count($arrayfields) > 0 && !empty($arrayfields['c.budget_amount']['checked'])) {
if (count($arrayfields) > 0 && !empty($arrayfields['t.budget_amount']['checked'])) {
print '<td class="center">';
print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
$total_budget_amount += $lines[$i]->budget_amount;

View File

@ -180,7 +180,7 @@ function delivery_prepare_head($object)
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
$upload_dir = $conf->commande->dir_output."/".dol_sanitizeFileName($tmpobject->ref);
$upload_dir = $conf->expedition->dir_output."/sending/".dol_sanitizeFileName($object->ref);
$nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
$nbLinks = Link::count($db, $tmpobject->element, $tmpobject->id);
$head[$h][0] = DOL_URL_ROOT.'/expedition/document.php?id='.$tmpobject->id;

View File

@ -55,7 +55,7 @@ class modEventOrganization extends DolibarrModules
$this->description = "EventOrganizationDescription";
$this->descriptionlong = "EventOrganizationDescriptionLong";
$this->version = 'development';
$this->version = 'experimental';
// Key used in llx_const table to save module status enabled/disabled (where EVENTORGANIZATION is value of property name of module in uppercase)

View File

@ -170,7 +170,10 @@ class doc_generic_product_odt extends ModelePDFProduct
$texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
// Show list of found files
foreach ($listoffiles as $file) {
$texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=products/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a><br>';
$texte .= '- '.$file['name'];
$texte .= ' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=products/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
$texte .= ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?modulepart=doctemplates&keyforuploaddir=PRODUCT_ADDON_PDF_ODT_PATH&action=deletefile&token='.newToken().'&file='.urlencode(basename($file['name'])).'">'.img_picto('', 'delete').'</a>';
$texte .= '<br>';
}
$texte .= '</div>';
}

View File

@ -102,12 +102,13 @@ class doc_generic_odt extends ModeleThirdPartyDoc
$form = new Form($this->db);
$texte = $this->description.".<br>\n";
$texte .= '<!-- form for option of ODT templates -->';
$texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
$texte .= '<input type="hidden" name="token" value="'.newToken().'">';
$texte .= '<input type="hidden" name="page_y" value="">';
$texte .= '<input type="hidden" name="action" value="setModuleOptions">';
$texte .= '<input type="hidden" name="param1" value="COMPANY_ADDON_PDF_ODT_PATH">';
$texte .= '<table class="nobordernopadding" width="100%">';
$texte .= '<table class="nobordernopadding centpercent">';
// List of directories area
$texte .= '<tr><td>';
@ -161,7 +162,9 @@ class doc_generic_odt extends ModeleThirdPartyDoc
$texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
// Show list of found files
foreach ($listoffiles as $file) {
$texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=thirdparties/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a><br>';
$texte .= '- '.$file['name'].' &nbsp; <a class="reposition" href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=thirdparties/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
$texte .= ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?modulepart=doctemplates&keyforuploaddir=COMPANY_ADDON_PDF_ODT_PATH&action=deletefile&token='.newToken().'&file='.urlencode(basename($file['name'])).'">'.img_picto('', 'delete').'</a>';
$texte .= '<br>';
}
$texte .= '</div>';
}

View File

@ -1252,20 +1252,30 @@ class pdf_cornas extends ModelePDFSuppliersOrders
$pdf->SetXY($this->marge_gauche, $posy);
// Logo
$logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
if ($this->emetteur->logo) {
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) {
if ($this->emetteur->logo) {
$logodir = $conf->mycompany->dir_output;
if (!empty($conf->mycompany->multidir_output[$object->entity])) {
$logodir = $conf->mycompany->multidir_output[$object->entity];
}
if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) {
$logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
} else {
$logo = $logodir.'/logos/'.$this->emetteur->logo;
}
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
}
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToModuleSetup"), 0, 'L');
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
}
} else {
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
}
$pdf->SetFont('', 'B', $default_font_size + 3);

View File

@ -1160,20 +1160,30 @@ class pdf_muscadet extends ModelePDFSuppliersOrders
$pdf->SetXY($this->marge_gauche, $posy);
// Logo
$logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
if ($this->emetteur->logo) {
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) {
if ($this->emetteur->logo) {
$logodir = $conf->mycompany->dir_output;
if (!empty($conf->mycompany->multidir_output[$object->entity])) {
$logodir = $conf->mycompany->multidir_output[$object->entity];
}
if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) {
$logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
} else {
$logo = $logodir.'/logos/'.$this->emetteur->logo;
}
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
}
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToModuleSetup"), 0, 'L');
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
}
} else {
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
}
$pdf->SetFont('', 'B', $default_font_size + 3);

View File

@ -1295,20 +1295,30 @@ class pdf_aurore extends ModelePDFSupplierProposal
$pdf->SetXY($this->marge_gauche, $posy);
// Logo
$logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
if ($this->emetteur->logo) {
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) {
if ($this->emetteur->logo) {
$logodir = $conf->mycompany->dir_output;
if (!empty($conf->mycompany->multidir_output[$object->entity])) {
$logodir = $conf->mycompany->multidir_output[$object->entity];
}
if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) {
$logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
} else {
$logo = $logodir.'/logos/'.$this->emetteur->logo;
}
if (is_readable($logo)) {
$height = pdf_getHeightForLogo($logo);
$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
}
} else {
$pdf->SetTextColor(200, 0, 0);
$pdf->SetFont('', 'B', $default_font_size - 2);
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
}
} else {
$text = $this->emetteur->name;
$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
}
$pdf->SetFont('', 'B', $default_font_size + 3);

View File

@ -124,27 +124,25 @@ if ($action == 'presend') {
if ($object->element === 'facture' && !empty($conf->global->INVOICE_EMAIL_SENDER)) {
$formmail->frommail = $conf->global->INVOICE_EMAIL_SENDER;
$formmail->fromname = '';
$formmail->fromname = (!empty($conf->global->INVOICE_EMAIL_SENDER_NAME) ? $conf->global->INVOICE_EMAIL_SENDER_NAME : '');
$formmail->fromtype = 'special';
}
if ($object->element === 'shipping' && !empty($conf->global->SHIPPING_EMAIL_SENDER)) {
$formmail->frommail = $conf->global->SHIPPING_EMAIL_SENDER;
$formmail->fromname = '';
$formmail->fromname = (!empty($conf->global->SHIPPING_EMAIL_SENDER_NAME) ? $conf->global->SHIPPING_EMAIL_SENDER_NAME : '');
$formmail->fromtype = 'special';
}
if ($object->element === 'commande' && !empty($conf->global->COMMANDE_EMAIL_SENDER)) {
$formmail->frommail = $conf->global->COMMANDE_EMAIL_SENDER;
$formmail->fromname = '';
$formmail->fromname = (!empty($conf->global->COMMANDE_EMAIL_SENDER_NAME) ? $conf->global->COMMANDE_EMAIL_SENDER_NAME : '');
$formmail->fromtype = 'special';
}
if ($object->element === 'order_supplier' && !empty($conf->global->ORDER_SUPPLIER_EMAIL_SENDER)) {
$formmail->frommail = $conf->global->ORDER_SUPPLIER_EMAIL_SENDER;
$formmail->fromname = '';
$formmail->fromname = (!empty($conf->global->ORDER_SUPPLIER_EMAIL_SENDER_NAME) ? $conf->global->ORDER_SUPPLIER_EMAIL_SENDER_NAME : '');
$formmail->fromtype = 'special';
}
$formmail->trackid = $trackid;
$formmail->withfrom = 1;

View File

@ -110,11 +110,9 @@ print '</table>';
// We close div and reopen for second column
print '</div>';
print '<div class="fichehalfright">';
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">';
$rightpart = '';
$alreadyoutput = 1;
foreach ($object->fields as $key => $val) {
if ($alreadyoutput) {
@ -139,38 +137,46 @@ foreach ($object->fields as $key => $val) {
$value = $object->$key;
print '<tr><td';
print ' class="'.(empty($val['tdcss']) ? 'titlefield' : $val['tdcss']).' fieldname_'.$key;
//if ($val['notnull'] > 0) print ' fieldrequired'; // No fieldrequired inthe view output
$rightpart .= '<tr><td';
$rightpart .= ' class="'.(empty($val['tdcss']) ? 'titlefield' : $val['tdcss']).' fieldname_'.$key;
//if ($val['notnull'] > 0) $rightpart .= ' fieldrequired'; // No fieldrequired inthe view output
if ($val['type'] == 'text' || $val['type'] == 'html') {
print ' tdtop';
$rightpart .= ' tdtop';
}
print '">';
$rightpart.= '">';
if (!empty($val['help'])) {
print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help']));
$rightpart .= $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help']));
} else {
print $langs->trans($val['label']);
$rightpart .= $langs->trans($val['label']);
}
print '</td>';
print '<td class="valuefield fieldname_'.$key;
$rightpart .= '</td>';
$rightpart .= '<td class="valuefield fieldname_'.$key;
if ($val['type'] == 'text') {
print ' wordbreak';
$rightpart .= ' wordbreak';
}
if (!empty($val['cssview'])) {
print ' '.$val['cssview'];
$rightpart .= ' '.$val['cssview'];
}
print '">';
$rightpart .= '">';
if (in_array($val['type'], array('text', 'html'))) {
print '<div class="longmessagecut">';
$rightpart .= '<div class="longmessagecut">';
}
print $object->showOutputField($val, $key, $value, '', '', '', 0);
//print dol_escape_htmltag($object->$key, 1, 1);
$rightpart .= $object->showOutputField($val, $key, $value, '', '', '', 0);
//$rightpart .= dol_escape_htmltag($object->$key, 1, 1);
if (in_array($val['type'], array('text', 'html'))) {
print '</div>';
$rightpart .= '</div>';
}
print '</td>';
print '</tr>';
$rightpart .= '</td>';
$rightpart .= '</tr>';
}
print '<div class="fichehalfright">';
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">';
print $rightpart;
?>
<!-- END PHP TEMPLATE commonfields_view.tpl.php -->

View File

@ -19,12 +19,17 @@
*/
// Following var must be set:
// $action
// $arrayofselected = array of id selected
// $object
// $objecttmp=new Propal($db);
// $objecttmp = new MyObject($db);
// $topicmail="SendSupplierProposalRef";
// $modelmail="supplier_proposal_send";
// $trackid='ord'.$object->id;
// $trackid='ord'.$objecttmp->id;
//
// Following var can be set
// $object = Object fetched;
// $sendto
// $withmaindocfilemail
if ($massaction == 'predeletedraft') {
@ -41,6 +46,7 @@ if ($massaction == 'preaffecttag') {
$categ_types = array();
$categ_type_array = $categ->getMapList();
foreach ($categ_type_array as $categdef) {
// Test on $object (should be useless, we already check on $objecttmp just after)
if (isset($object) && $categdef['obj_table'] == $object->table_element) {
if (!array_key_exists($categdef['code'], $categ_types)) {
$categ_types[$categdef['code']] = array('code'=>$categdef['code'], 'label'=>$langs->trans($categdef['obj_class']));
@ -76,7 +82,7 @@ if ($massaction == 'presend') {
$langs->load("mails");
$listofselectedid = array();
$listofselectedthirdparties = array();
$listofselectedrecipientobjid = array();
$listofselectedref = array();
if (!GETPOST('cancel', 'alpha')) {
@ -84,14 +90,19 @@ if ($massaction == 'presend') {
$result = $objecttmp->fetch($toselectid);
if ($result > 0) {
$listofselectedid[$toselectid] = $toselectid;
$thirdpartyid = ($objecttmp->fk_soc ? $objecttmp->fk_soc : $objecttmp->socid);
if ($objecttmp->element == 'societe') {
$thirdpartyid = ($objecttmp->fk_soc ? $objecttmp->fk_soc : $objecttmp->socid); // For proposal, order, invoice, conferenceorbooth, ...
if (in_array($objecttmp->element, array('societe', 'conferenceorboothattendee'))) {
$thirdpartyid = $objecttmp->id;
}
if ($objecttmp->element == 'expensereport') {
$thirdpartyid = $objecttmp->fk_user_author;
}
$listofselectedthirdparties[$thirdpartyid] = $thirdpartyid;
if (empty($thirdpartyid)) {
$thirdpartyid = 0;
}
if ($thirdpartyid) {
$listofselectedrecipientobjid[$thirdpartyid] = $thirdpartyid;
}
$listofselectedref[$thirdpartyid][$toselectid] = $objecttmp->ref;
}
}
@ -113,9 +124,9 @@ if ($massaction == 'presend') {
$formmail->trackid = $trackid;
$formmail->withfrom = 1;
$liste = $langs->trans("AllRecipientSelected", count($arrayofselected));
if (count($listofselectedthirdparties) == 1) { // Only 1 different recipient selected, we can suggest contacts
if (count($listofselectedrecipientobjid) == 1) { // Only 1 different recipient selected, we can suggest contacts
$liste = array();
$thirdpartyid = array_shift($listofselectedthirdparties);
$thirdpartyid = array_shift($listofselectedrecipientobjid);
if ($objecttmp->element == 'expensereport') {
$fuser = new User($db);
$fuser->fetch($thirdpartyid);
@ -136,19 +147,31 @@ if ($massaction == 'presend') {
$formmail->withtoreadonly = 1;
}
$formmail->withoptiononeemailperrecipient = ((count($listofselectedref) == 1 && count(reset($listofselectedref)) == 1) || empty($liste)) ? 0 : ((GETPOST('oneemailperrecipient') == 'on') ? 1 : -1);
$formmail->withoptiononeemailperrecipient = ((count($listofselectedref) == 1 && count(reset($listofselectedref)) == 1) || empty($liste)) ? 0 : (GETPOST('oneemailperrecipient', 'int') ? 1 : -1);
if (in_array($objecttmp->element, array('conferenceorboothattendee'))) {
$formmail->withoptiononeemailperrecipient = 0;
}
$formmail->withto = empty($liste) ? (GETPOST('sendto', 'alpha') ?GETPOST('sendto', 'alpha') : array()) : $liste;
$formmail->withtofree = empty($liste) ? 1 : 0;
$formmail->withtocc = 1;
$formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC;
$formmail->withtopic = $langs->transnoentities($topicmail, '__REF__', '__REF_CLIENT__');
$formmail->withfile = 1;
// $formmail->withfile = 2; Not yet supported in mass action
$formmail->withmaindocfile = 1; // Add a checkbox "Attach also main document"
if ($objecttmp->element != 'societe') {
$formmail->withfile = '<span class="hideonsmartphone opacitymedium">'.$langs->trans("OnlyPDFattachmentSupported").'</span>';
$formmail->withmaindocfile = - 1; // Add a checkbox "Attach also main document" but not checked by default
if (!empty($topicmail)) {
$formmail->withtopic = $langs->transnoentities($topicmail, '__REF__', '__REF_CLIENT__');
} else {
$formmail->withtopic = 1;
}
$formmail->withfile = 1; // $formmail->withfile = 2 to allow to upload files is not yet supported in mass action
// Add a checkbox "Attach also main document"
if (isset($withmaindocfilemail)) {
$formmail->withmaindocfile = $withmaindocfilemail;
} else { // Do an automatic definition of $formmail->withmaindocfile
$formmail->withmaindocfile = 1;
if ($objecttmp->element != 'societe') {
$formmail->withfile = '<span class="hideonsmartphone opacitymedium">'.$langs->trans("OnlyPDFattachmentSupported").'</span>';
$formmail->withmaindocfile = -1; // Add a checkbox "Attach also main document" but not checked by default
}
}
$formmail->withbody = 1;
$formmail->withdeliveryreceipt = 1;
@ -167,16 +190,16 @@ if ($massaction == 'presend') {
);
complete_substitutions_array($substitutionarray, $langs, $object, $parameters);
// Tableau des substitutions
// Array of substitutions
$formmail->substit = $substitutionarray;
// Tableau des parametres complementaires du post
$formmail->param['action'] = $action;
$formmail->param['models'] = $modelmail;
$formmail->param['models_id'] = GETPOST('modelmailselected', 'int');
$formmail->param['models'] = $modelmail; // the filter to know which kind of template emails to show. 'none' means no template suggested.
$formmail->param['models_id'] = GETPOST('modelmailselected', 'int') ? GETPOST('modelmailselected', 'int') : '-1';
$formmail->param['id'] = join(',', $arrayofselected);
// $formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id;
if (!empty($conf->global->MAILING_LIMIT_SENDBYWEB) && count($listofselectedthirdparties) > $conf->global->MAILING_LIMIT_SENDBYWEB) {
if (!empty($conf->global->MAILING_LIMIT_SENDBYWEB) && count($listofselectedrecipientobjid) > $conf->global->MAILING_LIMIT_SENDBYWEB) {
$langs->load("errors");
print img_warning().' '.$langs->trans('WarningNumberOfRecipientIsRestrictedInMassAction', $conf->global->MAILING_LIMIT_SENDBYWEB);
print ' - <a href="javascript: window.history.go(-1)">'.$langs->trans("GoBack").'</a>';

View File

@ -101,7 +101,7 @@ if ($action == 'add') {
$object->fk_incoterms = GETPOST('incoterm_id', 'int');
if (!$conf->expedition_bon->enabled && !empty($conf->stock->enabled)) {
$expedition->entrepot_id = GETPOST('entrepot_id');
$expedition->entrepot_id = GETPOST('entrepot_id', 'int');
}
// We loop on each line of order to complete object delivery with qty to delivery
@ -282,7 +282,7 @@ if ($action == 'create') { // Create. Seems to no be used
print '<input type="hidden" name="id" value="'.$object->id.'">';
print '<input type="hidden" name="ref" value="'.$object->ref.'">';
print dol_get_fiche_head($head, 'delivery', $langs->trans("Shipment"), -1, 'sending');
print dol_get_fiche_head($head, 'delivery', $langs->trans("Shipment"), -1, 'dolly');
/*
* Confirmation de la suppression

View File

@ -2365,8 +2365,9 @@ class EmailCollector extends CommonObject
// this code action is hook..... for support this call
global $hookmanager;
if (is_object($hookmanager)) {
$hookmanager->initHooks(array('emailcollectorcard'));
if (!is_object($hookmanager)) {
include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
$hookmanager = new HookManager($this->db);
}
$parameters = array(

View File

@ -621,8 +621,8 @@ $arrayofmassactions = array(
//'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
//'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' - '.$langs->trans("ConferenceOrBooth"),
'presend_attendees'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' - '.$langs->trans("Attendees"),
'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' ('.$langs->trans("ToSpeakers").')',
//'presend_attendees'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' - '.$langs->trans("Attendees"),
);
if ($permissiontodelete) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
@ -650,12 +650,13 @@ $newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle'
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
// Add code for pre mass action (confirmation or email presend form)
$topicmail = $object->ref;
$topicmail = $projectstatic->title;
$modelmail = "conferenceorbooth";
$objecttmp = new ConferenceOrBooth($db);
$trackid = 'conferenceorbooth_'.$object->id;
include DOL_DOCUMENT_ROOT.'/eventorganization/tpl/massactions_mail_pre.tpl.php';
$withmaindocfilemail = 0;
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
@ -689,6 +690,7 @@ $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";

View File

@ -182,8 +182,8 @@ if (GETPOST('cancel', 'alpha')) {
$massaction = '';
}
if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend'
&& $massaction != 'presend_attendees'
&& $massaction != 'confirm_presend_attendees') {
&& $massaction != 'presend'
&& $massaction != 'confirm_presend') {
$massaction = '';
}
@ -676,8 +676,7 @@ $arrayofmassactions = array(
//'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
//'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
//'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
'presend_attendees'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' - '.$langs->trans("Attendees"),
'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
);
if ($permissiontodelete) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
@ -706,14 +705,16 @@ $newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle'
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
// Add code for pre mass action (confirmation or email presend form)
$topicmail = "SendConferenceOrBoothAttendeeRef";
$modelmail = "conferenceorboothattendee";
$topicmail = $projectstatic->title;
$modelmail = "conferenceorbooth";
$objecttmp = new ConferenceOrBoothAttendee($db);
$trackid = 'xxxx'.$object->id;
include DOL_DOCUMENT_ROOT.'/eventorganization/tpl/massactions_mail_pre.tpl.php';
$trackid = 'conferenceorbooth_'.$object->id;
$withmaindocfilemail = 0;
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
if ($search_all) {
foreach ($fieldstosearchall as $key => $val) {
$fieldstosearchall[$key] = $langs->trans($val);

View File

@ -78,7 +78,7 @@ if (!$error && $massaction == 'confirm_presend_attendees') {
$listofobjectid = array();
$listofobjectref = array();
$oneemailperrecipient = (GETPOST('oneemailperrecipient') == 'on' ? 1 : 0);
$oneemailperrecipient = (GETPOST('oneemailperrecipient', 'int') ? 1 : 0);
if (!$error) {
require_once DOL_DOCUMENT_ROOT . '/eventorganization/class/conferenceorboothattendee.class.php';

View File

@ -1,126 +0,0 @@
<?php
/* Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
* Copyright (C) 2013-2014 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* or see https://www.gnu.org/
*/
// Following var must be set:
// $arrayofselected = array of id selected
// $object
// $objecttmp=new Propal($db);
// $topicmail="SendSupplierProposalRef";
// $modelmail="supplier_proposal_send";
// $trackid='ord'.$object->id;
if ($massaction == 'presend_attendees') {
$langs->load("mails");
require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
$attendee = new ConferenceOrBoothAttendee($db);
$listofselectedid = array();
$listofselectedref = array();
if (!GETPOST('cancel', 'alpha')) {
foreach ($arrayofselected as $toselectid) {
$result = $objecttmp->fetch($toselectid);
if ($result > 0) {
$attendees = $attendee->fetchAll();
if (is_array($attendees) && count($attendees)>0) {
foreach ($attendees as $attmail) {
if (!empty($attmail->email)) {
$listofselectedid[$attmail->email] = $attmail->id;
$listofselectedref[$attmail->id][$toselectid] = $objecttmp->ref;
}
}
}
}
}
}
print '<input type="hidden" name="massaction" value="confirm_presend_attendees">';
print '<input type="hidden" name="projectid" value="'.GETPOST('projectid', 'int').'">';
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
print dol_get_fiche_head(null, '', '');
// Create form for email
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
$formmail->withform = -1;
$formmail->fromtype = (GETPOST('fromtype') ? GETPOST('fromtype') : (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) ? $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE : 'user'));
if ($formmail->fromtype === 'user') {
$formmail->fromid = $user->id;
}
$formmail->trackid = $trackid;
$formmail->withfrom = 1;
$liste = $langs->trans("AllRecipientSelected", count($listofselectedid));
$formmail->withtoreadonly = 1;
$formmail->withoptiononeemailperrecipient = ((count($listofselectedref) == 1 && count(reset($listofselectedref)) == 1) || empty($liste)) ? 0 : ((GETPOST('oneemailperrecipient') == 'on') ? 1 : -1);
$formmail->withto = empty($liste) ? (GETPOST('sendto', 'alpha') ?GETPOST('sendto', 'alpha') : array()) : $liste;
$formmail->withtofree = empty($liste) ? 1 : 0;
$formmail->withtocc = 1;
$formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC;
$formmail->withtopic = $langs->transnoentities($topicmail, '__REF__', '__REF_CLIENT__');
$formmail->withfile = 0;
// $formmail->withfile = 2; Not yet supported in mass action
$formmail->withmaindocfile = 0; // Add a checkbox "Attach also main document"
$formmail->withbody = 1;
$formmail->withdeliveryreceipt = 1;
$formmail->withcancel = 1;
// Make substitution in email content
$substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object);
$substitutionarray['__EMAIL__'] = $sendto;
$substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '<img src="'.DOL_MAIN_URL_ROOT.'/public/emailing/mailing-read.php?tag='.urlencode($object->thirdparty->tag).'&securitykey='.urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY).'" width="1" height="1" style="width:1px;height:1px" border="0"/>' : '';
$substitutionarray['__PERSONALIZED__'] = ''; // deprecated
$substitutionarray['__CONTACTCIVNAME__'] = '';
$parameters = array(
'mode' => 'formemail'
);
complete_substitutions_array($substitutionarray, $langs, $object, $parameters);
// Tableau des substitutions
$formmail->substit = $substitutionarray;
// Tableau des parametres complementaires du post
$formmail->param['action'] = $action;
$formmail->param['models'] = $modelmail;
$formmail->param['models_id'] = empty(GETPOST('modelmailselected', 'int'))?$conf->global->EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES:GETPOST('modelmailselected', 'int');
$formmail->param['id'] = join(',', $arrayofselected);
// $formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id;
if (!empty($conf->global->MAILING_LIMIT_SENDBYWEB) && count($listofselectedid) > $conf->global->MAILING_LIMIT_SENDBYWEB) {
$langs->load("errors");
print img_warning().' '.$langs->trans('WarningNumberOfRecipientIsRestrictedInMassAction', $conf->global->MAILING_LIMIT_SENDBYWEB);
print ' - <a href="javascript: window.history.go(-1)">'.$langs->trans("GoBack").'</a>';
$arrayofmassactions = array();
} else {
print $formmail->get_form();
}
print dol_get_fiche_end();
}
// Allow Pre-Mass-Action hook (eg for confirmation dialog)
$parameters = array(
'toselect' => $toselect,
'uploaddir' => isset($uploaddir) ? $uploaddir : null
);

View File

@ -1126,16 +1126,19 @@ if ($action == 'create') {
$product_static->status_buy = $line->product_tobuy;
$product_static->status_batch = $line->product_tobatch;
$showdescinproductdesc = (getDolGlobalString('PRODUIT_DESC_IN_FORM') == 2 ? 1 : 0);
$text = $product_static->getNomUrl(1);
$text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
$description = ($conf->global->PRODUIT_DESC_IN_FORM ? '' : dol_htmlentitiesbr($line->desc));
$description = ($showdescinproductdesc ? '' : dol_htmlentitiesbr($line->desc));
print $form->textwithtooltip($text, $description, 3, '', '', $i);
// Show range
print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
// Add description in form
if (!empty($conf->global->PRODUIT_DESC_IN_FORM)) {
if ($showdescinproductdesc) {
print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
}

View File

@ -635,7 +635,16 @@ class PaymentExpenseReport extends CommonObject
if (empty($this->ref)) {
$this->ref = $this->label;
}
$label = $langs->trans("ShowPayment").': '.$this->ref;
$label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Payment").'</u>';
if (isset($this->status)) {
$label .= ' '.$this->getLibStatut(5);
}
if (!empty($this->ref)) {
$label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
}
if (!empty($this->datep)) {
$label .= '<br><b>'.$langs->trans('Date').':</b> '.dol_print_date($this->datep, 'dayhour');
}
if (!empty($this->id)) {
$link = '<a href="'.DOL_URL_ROOT.'/expensereport/payment/card.php?id='.$this->id.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';

View File

@ -95,11 +95,39 @@ if ($idprod > 0) {
if (!empty($conf->stock->enabled)) {
// Add price for pmp
$price = $producttmp->pmp;
$prices[] = array("id" => 'pmpprice', "price" => price2num($price), "label" => $langs->trans("PMPValueShort").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency)); // For price field, we must use price2num(), for label or title, price()
if (empty($price) && !empty($conf->global->PRODUCT_USE_SUB_COST_PRICES_IF_COST_PRICE_EMPTY)) {
// get pmp for subproducts if any
$producttmp->get_sousproduits_arbo();
$prods_arbo=$producttmp->get_arbo_each_prod();
if (!empty($prods_arbo)) {
$price = 0;
foreach ($prods_arbo as $child) {
$sousprod = new Product($db);
$sousprod->fetch($child['id']);
$price += $sousprod->pmp;
}
}
}
$prices[] = array("id" => 'pmpprice', "price" => price2num($price), "label" => $langs->trans("PMPValueShort").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency)); // For price field, we must use price2num(), for label or title, price()
}
// Add price for costprice (at end)
$price = $producttmp->cost_price;
if (empty($price) && ! empty($conf->global->PRODUCT_USE_SUB_COST_PRICES_IF_COST_PRICE_EMPTY)) {
// get costprice for subproducts if any
$producttmp->get_sousproduits_arbo();
$prods_arbo=$producttmp->get_arbo_each_prod();
if (!empty($prods_arbo)) {
$price = 0;
foreach ($prods_arbo as $child) {
$sousprod = new Product($db);
$sousprod->fetch($child['id']);
$price += $sousprod->cost_price;
}
}
}
$prices[] = array("id" => 'costprice', "price" => price2num($price), "label" => $langs->trans("CostPrice").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price, 0, $langs, 0, 0, -1, $conf->currency)); // For price field, we must use price2num(), for label or title, price()
}

View File

@ -369,6 +369,189 @@ class SupplierOrders extends DolibarrApi
);
}
/**
* Approve an order
*
* @param int $id Order ID
* @param int $idwarehouse Warehouse ID
* @param int $secondlevel 1=Does not execute triggers, 0= execute triggers
*
* @url POST {id}/approve
*
* @return array
* FIXME An error 403 is returned if the request has an empty body.
* Error message: "Forbidden: Content type `text/plain` is not supported."
* Workaround: send this in the body
* {
* "idwarehouse": 0,
* "secondlevel": 0
* }
*/
public function approve($id, $idwarehouse = 0, $secondlevel = 0)
{
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
throw new RestException(401);
}
$result = $this->order->fetch($id);
if (!$result) {
throw new RestException(404, 'Order not found');
}
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$result = $this->order->approve(DolibarrApiAccess::$user, $idwarehouse, $secondlevel);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already approved');
}
if ($result < 0) {
throw new RestException(500, 'Error when approve Order: '.$this->order->error);
}
return array(
'success' => array(
'code' => 200,
'message' => 'Order approved (Ref='.$this->order->ref.')'
)
);
}
/**
* Sends an order to the vendor
*
* @param int $id Order ID
* @param integer $date Date (unix timestamp in sec)
* @param int $method Method
* @param string $comment Comment
*
* @url POST {id}/makeorder
*
* @return array
* FIXME An error 403 is returned if the request has an empty body.
* Error message: "Forbidden: Content type `text/plain` is not supported."
* Workaround: send this in the body
* {
* "date": 0,
* "method": 0,
* "comment": ""
* }
*/
public function makeOrder($id, $date, $method, $comment = '')
{
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
throw new RestException(401);
}
$result = $this->order->fetch($id);
if (!$result) {
throw new RestException(404, 'Order not found');
}
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$result = $this->order->commande(DolibarrApiAccess::$user, $date, $method, $comment);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already sent');
}
if ($result < 0) {
throw new RestException(500, 'Error when sending Order: '.$this->order->error);
}
return array(
'success' => array(
'code' => 200,
'message' => 'Order sent (Ref='.$this->order->ref.')'
)
);
}
/**
* Receives the order, dispatches products.
*
* Example:
* <code> {
* "closeopenorder": 1,
* "comment": "",
* "lines": [{
* "id": 14,
* "fk_product": 112,
* "qty": 18,
* "warehouse": 1,
* "price": 114,
* "comment": "",
* "eatby": 0,
* "sellby": 0,
* "batch": 0,
* "notrigger": 0
* }]
* }</code>
*
* @param int $id Order ID
* @param integer $closeopenorder Close order if everything is received {@required false}
* @param string $comment Comment {@required false}
* @param array $lines Array of product dispatches
*
* @url POST {id}/receive
*
* @return array
* FIXME An error 403 is returned if the request has an empty body.
* Error message: "Forbidden: Content type `text/plain` is not supported."
*
*/
public function receiveOrder($id, $closeopenorder, $comment, $lines)
{
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
throw new RestException(401);
}
$result = $this->order->fetch($id);
if (!$result) {
throw new RestException(404, 'Order not found');
}
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
foreach ($lines as $line) {
$lineObj =(object) $line;
$result=$this->order->dispatchProduct(DolibarrApiAccess::$user,
$lineObj->fk_product,
$lineObj->qty,
$lineObj->warehouse,
$lineObj->price,
$lineObj->comment,
$lineObj->eatby,
$lineObj->sellby,
$lineObj->batch,
$lineObj->id,
$lineObj->notrigger);
if ($result < 0) {
throw new RestException(500, 'Error dispatch order line '.$line->id.': '.$this->order->error);
}
}
$result = $this->order->calcAndSetStatusDispatch(DolibarrApiAccess::$user, $closeopenorder, $comment);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already dispatched');
}
if ($result < 0) {
throw new RestException(500, 'Error when receivce order: '.$this->order->error);
}
return array(
'success' => array(
'code' => 200,
'message' => 'Order received (Ref='.$this->order->ref.')'
)
);
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Clean sensible object datas

View File

@ -1370,29 +1370,35 @@ class CommandeFournisseur extends CommonOrder
// insert products details into database
for ($i = 0; $i < $num; $i++) {
$this->special_code = $this->lines[$i]->special_code; // TODO : remove this in 9.0 and add special_code param to addline()
$line = $this->lines[$i];
if (!is_object($line)) {
$line = (object) $line;
}
$this->special_code = $line->special_code; // TODO : remove this in 9.0 and add special_code param to addline()
// This include test on qty if option SUPPLIER_ORDER_WITH_NOPRICEDEFINED is not set
$result = $this->addline(
$this->lines[$i]->desc,
$this->lines[$i]->subprice,
$this->lines[$i]->qty,
$this->lines[$i]->tva_tx,
$this->lines[$i]->localtax1_tx,
$this->lines[$i]->localtax2_tx,
$this->lines[$i]->fk_product,
$line->desc,
$line->subprice,
$line->qty,
$line->tva_tx,
$line->localtax1_tx,
$line->localtax2_tx,
$line->fk_product,
0,
$this->lines[$i]->ref_fourn, // $this->lines[$i]->ref_fourn comes from field ref into table of lines. Value may ba a ref that does not exists anymore, so we first try with value of product
$this->lines[$i]->remise_percent,
$line->ref_fourn, // $line->ref_fourn comes from field ref into table of lines. Value may ba a ref that does not exists anymore, so we first try with value of product
$line->remise_percent,
'HT',
0,
$this->lines[$i]->product_type,
$this->lines[$i]->info_bits,
$line->product_type,
$line->info_bits,
false,
$this->lines[$i]->date_start,
$this->lines[$i]->date_end,
$this->lines[$i]->array_options,
$this->lines[$i]->fk_unit
$line->date_start,
$line->date_end,
$line->array_options,
$line->fk_unit
);
if ($result < 0) {
dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING); // do not use dol_print_error here as it may be a functionnal error

View File

@ -101,6 +101,10 @@ $extrafields = new ExtraFields($db);
// fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);
if ($user->socid) {
$socid = $user->socid;
}
// Load object
if ($id > 0 || !empty($ref)) {
$ret = $object->fetch($id, $ref);
@ -124,7 +128,9 @@ if ($id > 0 || !empty($ref)) {
}
}
$result = restrictedArea($user, 'fournisseur', $id, 'commande_fournisseur', 'commande');
// Security check
$isdraft = (isset($object->statut) && ($object->statut == $object::STATUS_DRAFT) ? 1 : 0);
$result = restrictedArea($user, 'fournisseur', $id, 'commande_fournisseur', 'commande', 'fk_soc', 'rowid', $isdraft);
// Common permissions
$usercanread = ($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire);
@ -842,8 +848,7 @@ if (empty($reshook)) {
} else {
$db->rollback();
dol_print_error($db, $object->error);
exit;
setEventMessages($object->error, $object->errors, 'errors');
}
}

View File

@ -11,6 +11,7 @@
* Copyright (C) 2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2018-2020 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2021 Charlene Benke <charlene@patas-monkey.com>
* Copyright (C) 2022 Udo Tamm <dev@dolibit.de>
*
* 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
@ -54,11 +55,11 @@ $day = GETPOST('day', 'int');
$month = GETPOST('month', 'int');
$year = GETPOST('year', 'int');
$search_ref = GETPOST("search_ref", "alpha");
$search_account = GETPOST("search_account", "int");
$search_paymenttype = GETPOST("search_paymenttype");
$search_amount = GETPOST("search_amount", 'alpha'); // alpha because we must be able to search on "< x"
$search_company = GETPOST("search_company", 'alpha');
$search_ref = GETPOST('search_ref', 'alpha');
$search_account = GETPOST('search_account', 'int');
$search_paymenttype = GETPOST('search_paymenttype');
$search_amount = GETPOST('search_amount', 'alpha'); // alpha because we must be able to search on "< x"
$search_company = GETPOST('search_company', 'alpha');
$search_payment_num = GETPOST('search_payment_num', 'alpha');
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
@ -773,10 +774,13 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
}
}
// Save Button
// Save + Cancel Buttons
if ($action != 'add_paiement') {
print '<br><div class="center"><input type="checkbox" checked name="closepaidinvoices"> '.$langs->trans("ClosePaidInvoicesAutomatically");
print '<br><input type="submit" class="button" value="'.$langs->trans('ToMakePayment').'"></div>';
print '<p>&nbsp;</p>';
print '<br><input type="submit" class="button" value="'.$langs->trans('ToMakePayment').'">';
print '<p>&nbsp;</p>';
print '<br><input type="button" class="button button-cancel" value="'.$langs->trans("Cancel").'" onClick="javascript:history.go(-1)"></div>';
}
// Form to confirm payment

View File

@ -109,7 +109,7 @@ class Position extends CommonObject
'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,),
'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,),
'fk_contrat' => array('type'=>'integer:Contrat:contrat/class/contrat.class.php', 'label'=>'fk_contrat', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>0,),
'fk_user' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Employee', 'enabled'=>'1', 'position'=>55, 'notnull'=>1, 'visible'=>1,),
'fk_user' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Employee', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>1,),
'fk_job' => array('type'=>'integer:Job:/hrm/class/job.class.php', 'label'=>'Job', 'enabled'=>'1', 'position'=>56, 'notnull'=>1, 'visible'=>1,),
'date_start' => array('type'=>'date', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>51, 'notnull'=>1, 'visible'=>1,),
'date_end' => array('type'=>'date', 'label'=>'DateEnd', 'enabled'=>'1', 'position'=>52, 'notnull'=>0, 'visible'=>1,),

View File

@ -264,7 +264,7 @@ if (($id || $ref) && $action == 'edit') {
if (is_array($SkilldetRecords) && count($SkilldetRecords) > 0) {
print '<table>';
foreach ($SkilldetRecords as $sk) {
if ($sk->rank > $MaxNumberSkill) {
if ($sk->rankorder > $MaxNumberSkill) {
continue;
}
@ -291,7 +291,7 @@ if (($id || $ref) && $action == 'edit') {
// if (!empty($val['help'])) {
// print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help']));
// } else {
print $langs->trans($val['label']).'&nbsp;'.$langs->trans('rank').'&nbsp;'.$sk->rank;
print $langs->trans($val['label']).'&nbsp;'.$langs->trans('rank').'&nbsp;'.$sk->rankorder;
// }
print '</td>';
print '<td class="valuefieldcreate">';
@ -696,7 +696,7 @@ if ($action != "create" && $action != "edit") {
break; // Should not happen
}
if ($obj->rank > $MaxNumberSkill) {
if ($obj->rankorder > $MaxNumberSkill) {
continue;
}

View File

@ -11,17 +11,28 @@ use OAuth\Common\Http\Exception\TokenResponseException;
use OAuth\OAuth2\Service\Exception\InvalidAccessTypeException;
use OAuth\Common\Http\Uri\Uri;
/**
* Class For WordPress OAuth
*/
class WordPress extends AbstractService
{
/**
* @var string
*/
protected $accessType = 'online';
public function __construct(
CredentialsInterface $credentials,
ClientInterface $httpClient,
TokenStorageInterface $storage,
$scopes = array(),
UriInterface $baseApiUri = null
) {
/**
* Construct
*
* @param CredentialsInterface $credentials credentials
* @param ClientInterface $httpClient httpClient
* @param TokenStorageInterface $storage storage
* @param $scopes scope
* @param UriInterface|null $baseApiUri baseApiUri
* @throws Exception\InvalidScopeException
*/
public function __construct(CredentialsInterface $credentials, ClientInterface $httpClient, TokenStorageInterface $storage, $scopes = array(), UriInterface $baseApiUri = null)
{
parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri, true);
if (null === $baseApiUri) {
@ -41,7 +52,7 @@ class WordPress extends AbstractService
}*/
/**
* {@inheritdoc}
* @return Uri
*/
public function getAuthorizationEndpoint()
{
@ -49,7 +60,7 @@ class WordPress extends AbstractService
}
/**
* {@inheritdoc}
* @return Uri
*/
public function getAccessTokenEndpoint()
{
@ -57,7 +68,7 @@ class WordPress extends AbstractService
}
/**
* {@inheritdoc}
* @return int
*/
protected function getAuthorizationMethod()
{
@ -66,7 +77,9 @@ class WordPress extends AbstractService
}
/**
* {@inheritdoc}
* @param $responseBody responseBody
* @return StdOAuth2Token
* @throws TokenResponseException
*/
protected function parseAccessTokenResponse($responseBody)
{

View File

@ -13,6 +13,8 @@ class EmailLexer extends AbstractLexer
const S_BACKSLASH = 92;
const S_DOT = 46;
const S_DQUOTE = 34;
const S_SQUOTE = 39;
const S_BACKTICK = 96;
const S_OPENPARENTHESIS = 49;
const S_CLOSEPARENTHESIS = 261;
const S_OPENBRACKET = 262;
@ -58,6 +60,8 @@ class EmailLexer extends AbstractLexer
'/' => self::S_SLASH,
',' => self::S_COMMA,
'.' => self::S_DOT,
"'" => self::S_SQUOTE,
"`" => self::S_BACKTICK,
'"' => self::S_DQUOTE,
'-' => self::S_HYPHEN,
'::' => self::S_DOUBLECOLON,
@ -73,25 +77,73 @@ class EmailLexer extends AbstractLexer
'\0' => self::C_NUL,
);
/**
* @var bool
*/
protected $hasInvalidTokens = false;
protected $previous;
/**
* @var array
*
* @psalm-var array{value:string, type:null|int, position:int}|array<empty, empty>
*/
protected $previous = [];
/**
* The last matched/seen token.
*
* @var array
*
* @psalm-var array{value:string, type:null|int, position:int}
*/
public $token;
/**
* The next token in the input.
*
* @var array|null
*/
public $lookahead;
/**
* @psalm-var array{value:'', type:null, position:0}
*/
private static $nullToken = [
'value' => '',
'type' => null,
'position' => 0,
];
public function __construct()
{
$this->previous = $this->token = self::$nullToken;
$this->lookahead = null;
}
/**
* @return void
*/
public function reset()
{
$this->hasInvalidTokens = false;
parent::reset();
$this->previous = $this->token = self::$nullToken;
}
/**
* @return bool
*/
public function hasInvalidTokens()
{
return $this->hasInvalidTokens;
}
/**
* @param $type
* @param int $type
* @throws \UnexpectedValueException
* @return boolean
*
* @psalm-suppress InvalidScalarArgument
*/
public function find($type)
{
@ -107,7 +159,7 @@ class EmailLexer extends AbstractLexer
/**
* getPrevious
*
* @return array token
* @return array
*/
public function getPrevious()
{
@ -122,8 +174,10 @@ class EmailLexer extends AbstractLexer
public function moveNext()
{
$this->previous = $this->token;
$hasNext = parent::moveNext();
$this->token = $this->token ?: self::$nullToken;
return parent::moveNext();
return $hasNext;
}
/**
@ -179,6 +233,11 @@ class EmailLexer extends AbstractLexer
return self::GENERIC;
}
/**
* @param string $value
*
* @return bool
*/
protected function isValid($value)
{
if (isset($this->charValue[$value])) {
@ -189,7 +248,7 @@ class EmailLexer extends AbstractLexer
}
/**
* @param $value
* @param string $value
* @return bool
*/
protected function isNullType($value)
@ -202,7 +261,7 @@ class EmailLexer extends AbstractLexer
}
/**
* @param $value
* @param string $value
* @return bool
*/
protected function isUTF8Invalid($value)
@ -214,6 +273,9 @@ class EmailLexer extends AbstractLexer
return false;
}
/**
* @return string
*/
protected function getModifiers()
{
return 'iu';

View File

@ -17,11 +17,33 @@ class EmailParser
{
const EMAIL_MAX_LENGTH = 254;
protected $warnings;
/**
* @var array
*/
protected $warnings = [];
/**
* @var string
*/
protected $domainPart = '';
/**
* @var string
*/
protected $localPart = '';
/**
* @var EmailLexer
*/
protected $lexer;
/**
* @var LocalPart
*/
protected $localPartParser;
/**
* @var DomainPart
*/
protected $domainPartParser;
public function __construct(EmailLexer $lexer)
@ -29,11 +51,10 @@ class EmailParser
$this->lexer = $lexer;
$this->localPartParser = new LocalPart($this->lexer);
$this->domainPartParser = new DomainPart($this->lexer);
$this->warnings = new \SplObjectStorage();
}
/**
* @param $str
* @param string $str
* @return array
*/
public function parse($str)
@ -57,6 +78,9 @@ class EmailParser
return array('local' => $this->localPart, 'domain' => $this->domainPart);
}
/**
* @return Warning\Warning[]
*/
public function getWarnings()
{
$localPartWarnings = $this->localPartParser->getWarnings();
@ -68,11 +92,17 @@ class EmailParser
return $this->warnings;
}
/**
* @return string
*/
public function getParsedDomainPart()
{
return $this->domainPart;
}
/**
* @param string $email
*/
protected function setParts($email)
{
$parts = explode('@', $email);
@ -80,6 +110,9 @@ class EmailParser
$this->localPart = $parts[0];
}
/**
* @return bool
*/
protected function hasAtToken()
{
$this->lexer->moveNext();

View File

@ -13,12 +13,12 @@ class EmailValidator
private $lexer;
/**
* @var array
* @var Warning\Warning[]
*/
protected $warnings;
protected $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
protected $error;
@ -28,7 +28,7 @@ class EmailValidator
}
/**
* @param $email
* @param string $email
* @param EmailValidation $emailValidation
* @return bool
*/
@ -58,7 +58,7 @@ class EmailValidator
}
/**
* @return InvalidEmail
* @return InvalidEmail|null
*/
public function getError()
{

View File

@ -0,0 +1,9 @@
<?php
namespace Egulias\EmailValidator\Exception;
class DomainAcceptsNoMail extends InvalidEmail
{
const CODE = 154;
const REASON = 'Domain accepts no mail (Null MX, RFC7505)';
}

View File

@ -2,7 +2,7 @@
namespace Egulias\EmailValidator\Exception;
class ExpectedQPair extends InvalidEmail
class ExpectingQPair extends InvalidEmail
{
const CODE = 136;
const REASON = "Expecting QPAIR";

View File

@ -0,0 +1,9 @@
<?php
namespace Egulias\EmailValidator\Exception;
class LocalOrReservedDomain extends InvalidEmail
{
const CODE = 153;
const REASON = 'Local, mDNS or reserved domain (RFC2606, RFC6762)';
}

View File

@ -2,8 +2,6 @@
namespace Egulias\EmailValidator\Exception;
use Egulias\EmailValidator\Exception\InvalidEmail;
class NoDNSRecord extends InvalidEmail
{
const CODE = 5;

View File

@ -5,5 +5,5 @@ namespace Egulias\EmailValidator\Exception;
class UnclosedComment extends InvalidEmail
{
const CODE = 146;
const REASON = "No colosing comment token found";
const REASON = "No closing comment token found";
}

View File

@ -35,27 +35,18 @@ use Egulias\EmailValidator\Warning\TLD;
class DomainPart extends Parser
{
const DOMAIN_MAX_LENGTH = 254;
const LABEL_MAX_LENGTH = 63;
/**
* @var string
*/
protected $domainPart = '';
public function parse($domainPart)
{
$this->lexer->moveNext();
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
throw new NoDomainPart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
$this->performDomainStartChecks();
$domain = $this->doParseDomainPart();
@ -77,11 +68,50 @@ class DomainPart extends Parser
$this->domainPart = $domain;
}
private function performDomainStartChecks()
{
$this->checkInvalidTokensAfterAT();
$this->checkEmptyDomain();
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
}
private function checkEmptyDomain()
{
$thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY ||
($this->lexer->token['type'] === EmailLexer::S_SP &&
!$this->lexer->isNextToken(EmailLexer::GENERIC));
if ($thereIsNoDomain) {
throw new NoDomainPart();
}
}
private function checkInvalidTokensAfterAT()
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
}
/**
* @return string
*/
public function getDomainPart()
{
return $this->domainPart;
}
/**
* @param string $addressLiteral
* @param int $maxGroups
*/
public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
{
$prev = $this->lexer->getPrevious();
@ -125,9 +155,13 @@ class DomainPart extends Parser
}
}
/**
* @return string
*/
protected function doParseDomainPart()
{
$domain = '';
$label = '';
$openedParenthesis = 0;
do {
$prev = $this->lexer->getPrevious();
@ -158,7 +192,12 @@ class DomainPart extends Parser
$this->parseDomainLiteral();
}
$this->checkLabelLength($prev);
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
$this->checkLabelLength($label);
$label = '';
} else {
$label .= $this->lexer->token['value'];
}
if ($this->isFWS()) {
$this->parseFWS();
@ -166,12 +205,17 @@ class DomainPart extends Parser
$domain .= $this->lexer->token['value'];
$this->lexer->moveNext();
} while ($this->lexer->token);
if ($this->lexer->token['type'] === EmailLexer::S_SP) {
throw new CharNotAllowed();
}
} while (null !== $this->lexer->token['type']);
$this->checkLabelLength($label);
return $domain;
}
private function checkNotAllowedChars($token)
private function checkNotAllowedChars(array $token)
{
$notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
if (isset($notAllowed[$token['type']])) {
@ -179,6 +223,9 @@ class DomainPart extends Parser
}
}
/**
* @return string|false
*/
protected function parseDomainLiteral()
{
if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
@ -195,6 +242,9 @@ class DomainPart extends Parser
return $this->doParseDomainLiteral();
}
/**
* @return string|false
*/
protected function doParseDomainLiteral()
{
$IPv6TAG = false;
@ -262,6 +312,11 @@ class DomainPart extends Parser
return $addressLiteral;
}
/**
* @param string $addressLiteral
*
* @return string|false
*/
protected function checkIPV4Tag($addressLiteral)
{
$matchesIP = array();
@ -279,16 +334,18 @@ class DomainPart extends Parser
return false;
}
// Convert IPv4 part to IPv6 format for further testing
$addressLiteral = substr($addressLiteral, 0, $index) . '0:0';
$addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0';
}
return $addressLiteral;
}
protected function checkDomainPartExceptions($prev)
protected function checkDomainPartExceptions(array $prev)
{
$invalidDomainTokens = array(
EmailLexer::S_DQUOTE => true,
EmailLexer::S_SQUOTE => true,
EmailLexer::S_BACKTICK => true,
EmailLexer::S_SEMICOLON => true,
EmailLexer::S_GREATERTHAN => true,
EmailLexer::S_LOWERTHAN => true,
@ -320,6 +377,9 @@ class DomainPart extends Parser
}
}
/**
* @return bool
*/
protected function hasBrackets()
{
if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
@ -335,16 +395,31 @@ class DomainPart extends Parser
return true;
}
protected function checkLabelLength($prev)
/**
* @param string $label
*/
protected function checkLabelLength($label)
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
$prev['type'] === EmailLexer::GENERIC &&
strlen($prev['value']) > 63
) {
if ($this->isLabelTooLong($label)) {
$this->warnings[LabelTooLong::CODE] = new LabelTooLong();
}
}
/**
* @param string $label
* @return bool
*/
private function isLabelTooLong($label)
{
if (preg_match('/[^\x00-\x7F]/', $label)) {
idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG);
}
return strlen($label) > self::LABEL_MAX_LENGTH;
}
protected function parseDomainComments()
{
$this->isUnclosedComment();

View File

@ -5,7 +5,6 @@ namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\Exception\DotAtEnd;
use Egulias\EmailValidator\Exception\DotAtStart;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Exception\ExpectingAT;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\UnclosedQuotedString;
@ -20,9 +19,10 @@ class LocalPart extends Parser
$parseDQuote = true;
$closingQuote = false;
$openedParenthesis = 0;
$totalLength = 0;
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) {
throw new DotAtStart();
}
@ -35,12 +35,13 @@ class LocalPart extends Parser
$this->parseComments();
$openedParenthesis += $this->getOpenedParenthesis();
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
if ($openedParenthesis === 0) {
throw new UnopenedComment();
} else {
$openedParenthesis--;
}
$openedParenthesis--;
}
$this->checkConsecutiveDots();
@ -58,15 +59,18 @@ class LocalPart extends Parser
$this->parseFWS();
}
$totalLength += strlen($this->lexer->token['value']);
$this->lexer->moveNext();
}
$prev = $this->lexer->getPrevious();
if (strlen($prev['value']) > LocalTooLong::LOCAL_PART_LENGTH) {
if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) {
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
}
}
/**
* @return bool
*/
protected function parseDoubleQuote()
{
$parseAgain = true;
@ -86,7 +90,7 @@ class LocalPart extends Parser
$this->lexer->moveNext();
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) {
$parseAgain = false;
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
@ -118,7 +122,10 @@ class LocalPart extends Parser
return $parseAgain;
}
protected function isInvalidToken($token, $closingQuote)
/**
* @param bool $closingQuote
*/
protected function isInvalidToken(array $token, $closingQuote)
{
$forbidden = array(
EmailLexer::S_COMMA,

View File

@ -8,7 +8,7 @@ use Egulias\EmailValidator\Exception\ConsecutiveDot;
use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
use Egulias\EmailValidator\Exception\CRLFX2;
use Egulias\EmailValidator\Exception\CRNoLF;
use Egulias\EmailValidator\Exception\ExpectedQPair;
use Egulias\EmailValidator\Exception\ExpectingQPair;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\ExpectingCTEXT;
use Egulias\EmailValidator\Exception\UnclosedComment;
@ -21,8 +21,19 @@ use Egulias\EmailValidator\Warning\QuotedString;
abstract class Parser
{
/**
* @var array
*/
protected $warnings = [];
/**
* @var EmailLexer
*/
protected $lexer;
/**
* @var int
*/
protected $openedParenthesis = 0;
public function __construct(EmailLexer $lexer)
@ -30,11 +41,17 @@ abstract class Parser
$this->lexer = $lexer;
}
/**
* @return \Egulias\EmailValidator\Warning\Warning[]
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* @param string $str
*/
abstract public function parse($str);
/** @return int */
@ -50,7 +67,7 @@ abstract class Parser
{
if (!($this->lexer->token['type'] === EmailLexer::INVALID
|| $this->lexer->token['type'] === EmailLexer::C_DEL)) {
throw new ExpectedQPair();
throw new ExpectingQPair();
}
$this->warnings[QuotedPart::CODE] =
@ -80,6 +97,9 @@ abstract class Parser
}
}
/**
* @return bool
*/
protected function isUnclosedComment()
{
try {
@ -122,6 +142,9 @@ abstract class Parser
}
}
/**
* @return bool
*/
protected function isFWS()
{
if ($this->escaped()) {
@ -140,11 +163,14 @@ abstract class Parser
return false;
}
/**
* @return bool
*/
protected function escaped()
{
$previous = $this->lexer->getPrevious();
if ($previous['type'] === EmailLexer::S_BACKSLASH
if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH
&&
$this->lexer->token['type'] !== EmailLexer::GENERIC
) {
@ -154,6 +180,9 @@ abstract class Parser
return false;
}
/**
* @return bool
*/
protected function warnEscaping()
{
if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {
@ -174,6 +203,11 @@ abstract class Parser
}
/**
* @param bool $hasClosingQuote
*
* @return bool
*/
protected function checkDQUOTE($hasClosingQuote)
{
if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) {

View File

@ -4,6 +4,8 @@ namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\InvalidEmail;
use Egulias\EmailValidator\Exception\LocalOrReservedDomain;
use Egulias\EmailValidator\Exception\DomainAcceptsNoMail;
use Egulias\EmailValidator\Warning\NoDNSMXRecord;
use Egulias\EmailValidator\Exception\NoDNSRecord;
@ -15,10 +17,23 @@ class DNSCheckValidation implements EmailValidation
private $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
/**
* @var array
*/
private $mxRecords = [];
public function __construct()
{
if (!function_exists('idn_to_ascii')) {
throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
}
}
public function isValid($email, EmailLexer $emailLexer)
{
// use the input to check DNS if we cannot extract something similar to a domain
@ -29,7 +44,40 @@ class DNSCheckValidation implements EmailValidation
$host = substr($email, $lastAtPos + 1);
}
return $this->checkDNS($host);
// Get the domain parts
$hostParts = explode('.', $host);
// Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2),
// mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G)
$reservedTopLevelDnsNames = [
// Reserved Top Level DNS Names
'test',
'example',
'invalid',
'localhost',
// mDNS
'local',
// Private DNS Namespaces
'intranet',
'internal',
'private',
'corp',
'home',
'lan',
];
$isLocalDomain = count($hostParts) <= 1;
$isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true);
// Exclude reserved top level DNS names
if ($isLocalDomain || $isReservedTopLevel) {
$this->error = new LocalOrReservedDomain();
return false;
}
return $this->checkDns($host);
}
public function getError()
@ -42,20 +90,77 @@ class DNSCheckValidation implements EmailValidation
return $this->warnings;
}
protected function checkDNS($host)
/**
* @param string $host
*
* @return bool
*/
protected function checkDns($host)
{
$host = rtrim($host, '.') . '.';
$variant = INTL_IDNA_VARIANT_UTS46;
$Aresult = true;
$MXresult = checkdnsrr($host, 'MX');
$host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.';
if (!$MXresult) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
$Aresult = checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA');
if (!$Aresult) {
$this->error = new NoDNSRecord();
return $this->validateDnsRecords($host);
}
/**
* Validate the DNS records for given host.
*
* @param string $host A set of DNS records in the format returned by dns_get_record.
*
* @return bool True on success.
*/
private function validateDnsRecords($host)
{
// Get all MX, A and AAAA DNS records for host
// Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149
$dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA);
// No MX, A or AAAA DNS records
if (empty($dnsRecords)) {
$this->error = new NoDNSRecord();
return false;
}
// For each DNS record
foreach ($dnsRecords as $dnsRecord) {
if (!$this->validateMXRecord($dnsRecord)) {
return false;
}
}
return $MXresult || $Aresult;
// No MX records (fallback to A or AAAA records)
if (empty($this->mxRecords)) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
}
return true;
}
/**
* Validate an MX record
*
* @param array $dnsRecord Given DNS record.
*
* @return bool True if valid.
*/
private function validateMxRecord($dnsRecord)
{
if ($dnsRecord['type'] !== 'MX') {
return true;
}
// "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505)
if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') {
$this->error = new DomainAcceptsNoMail();
return false;
}
$this->mxRecords[] = $dnsRecord;
return true;
}
}

View File

@ -6,6 +6,9 @@ use Exception;
class EmptyValidationList extends \InvalidArgumentException
{
/**
* @param int $code
*/
public function __construct($code = 0, Exception $previous = null)
{
parent::__construct("Empty validation list is not allowed", $code, $previous);

View File

@ -9,16 +9,22 @@ class MultipleErrors extends InvalidEmail
const CODE = 999;
const REASON = "Accumulated errors for multiple validations";
/**
* @var array
* @var InvalidEmail[]
*/
private $errors = [];
/**
* @param InvalidEmail[] $errors
*/
public function __construct(array $errors)
{
$this->errors = $errors;
parent::__construct();
}
/**
* @return InvalidEmail[]
*/
public function getErrors()
{
return $this->errors;

View File

@ -30,12 +30,12 @@ class MultipleValidationWithAnd implements EmailValidation
private $warnings = [];
/**
* @var MultipleErrors
* @var MultipleErrors|null
*/
private $error;
/**
* @var bool
* @var int
*/
private $mode;
@ -62,7 +62,8 @@ class MultipleValidationWithAnd implements EmailValidation
$errors = [];
foreach ($this->validations as $validation) {
$emailLexer->reset();
$result = $result && $validation->isValid($email, $emailLexer);
$validationResult = $validation->isValid($email, $emailLexer);
$result = $result && $validationResult;
$this->warnings = array_merge($this->warnings, $validation->getWarnings());
$errors = $this->addNewError($validation->getError(), $errors);
@ -78,6 +79,12 @@ class MultipleValidationWithAnd implements EmailValidation
return $result;
}
/**
* @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError
* @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors
*
* @return \Egulias\EmailValidator\Exception\InvalidEmail[]
*/
private function addNewError($possibleError, array $errors)
{
if (null !== $possibleError) {
@ -87,13 +94,20 @@ class MultipleValidationWithAnd implements EmailValidation
return $errors;
}
/**
* @param bool $result
*
* @return bool
*/
private function shouldStop($result)
{
return !$result && $this->mode === self::STOP_ON_ERROR;
}
/**
* {@inheritdoc}
* Returns the validation errors.
*
* @return MultipleErrors|null
*/
public function getError()
{

View File

@ -9,7 +9,7 @@ use Egulias\EmailValidator\Validation\Error\RFCWarnings;
class NoRFCWarningsValidation extends RFCValidation
{
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
@ -22,8 +22,7 @@ class NoRFCWarningsValidation extends RFCValidation
return false;
}
$ret = $this->getWarnings();
if (empty($ret)) {
if (empty($this->getWarnings())) {
return true;
}

View File

@ -9,7 +9,7 @@ use Egulias\EmailValidator\Exception\InvalidEmail;
class RFCValidation implements EmailValidation
{
/**
* @var EmailParser
* @var EmailParser|null
*/
private $parser;
@ -19,7 +19,7 @@ class RFCValidation implements EmailValidation
private $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;

View File

@ -10,7 +10,7 @@ use \Spoofchecker;
class SpoofCheckValidation implements EmailValidation
{
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
@ -21,6 +21,9 @@ class SpoofCheckValidation implements EmailValidation
}
}
/**
* @psalm-suppress InvalidArgument
*/
public function isValid($email, EmailLexer $emailLexer)
{
$checker = new Spoofchecker();
@ -33,6 +36,9 @@ class SpoofCheckValidation implements EmailValidation
return $this->error === null;
}
/**
* @return InvalidEmail|null
*/
public function getError()
{
return $this->error;

View File

@ -6,6 +6,10 @@ class QuotedPart extends Warning
{
const CODE = 36;
/**
* @param scalar $prevToken
* @param scalar $postToken
*/
public function __construct($prevToken, $postToken)
{
$this->message = "Deprecated Quoted String found between $prevToken and $postToken";

View File

@ -6,6 +6,10 @@ class QuotedString extends Warning
{
const CODE = 11;
/**
* @param scalar $prevToken
* @param scalar $postToken
*/
public function __construct($prevToken, $postToken)
{
$this->message = "Quoted String found between $prevToken and $postToken";

View File

@ -5,19 +5,36 @@ namespace Egulias\EmailValidator\Warning;
abstract class Warning
{
const CODE = 0;
protected $message;
protected $rfcNumber;
/**
* @var string
*/
protected $message = '';
/**
* @var int
*/
protected $rfcNumber = 0;
/**
* @return string
*/
public function message()
{
return $this->message;
}
/**
* @return int
*/
public function code()
{
return self::CODE;
return static::CODE;
}
/**
* @return int
*/
public function RFCNumber()
{
return $this->rfcNumber;

View File

@ -258,6 +258,11 @@ abstract class AbstractLexer
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
$matches = preg_split($regex, $input, -1, $flags);
if (false === $matches) {
// Work around https://bugs.php.net/78122
$matches = array(array($input, 0));
}
foreach ($matches as $match) {
// Must remain before 'value' assignment since it can change content
$type = $this->getType($match[0]);

View File

@ -11,15 +11,14 @@
/**
* General utility class in Swift Mailer, not to be instantiated.
*
*
* @author Chris Corbyn
*/
abstract class Swift
{
const VERSION = '6.0.2';
const VERSION = '6.3.0';
public static $initialized = false;
public static $inits = array();
public static $inits = [];
/**
* Registers an initializer callable that will be called the first time
@ -57,7 +56,7 @@ abstract class Swift
if (self::$inits && !self::$initialized) {
self::$initialized = true;
foreach (self::$inits as $init) {
call_user_func($init);
\call_user_func($init);
}
}
}
@ -74,6 +73,6 @@ abstract class Swift
if (null !== $callable) {
self::$inits[] = $callable;
}
spl_autoload_register(array('Swift', 'autoload'));
spl_autoload_register(['Swift', 'autoload']);
}
}

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of SwiftMailer.
* (c) 2018 Christian Schmidt
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Email address encoder.
*
* @author Christian Schmidt
*/
interface Swift_AddressEncoder
{
/**
* Encodes an email address.
*
* @throws Swift_AddressEncoderException if the email cannot be represented in
* the encoding implemented by this class
*/
public function encodeString(string $address): string;
}

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of SwiftMailer.
* (c) 2018 Christian Schmidt
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* An IDN email address encoder.
*
* Encodes the domain part of an address using IDN. This is compatible will all
* SMTP servers.
*
* This encoder does not support email addresses with non-ASCII characters in
* local-part (the substring before @). To send to such addresses, use
* Swift_AddressEncoder_Utf8AddressEncoder together with
* Swift_Transport_Esmtp_SmtpUtf8Handler. Your outbound SMTP server must support
* the SMTPUTF8 extension.
*
* @author Christian Schmidt
*/
class Swift_AddressEncoder_IdnAddressEncoder implements Swift_AddressEncoder
{
/**
* Encodes the domain part of an address using IDN.
*
* @throws Swift_AddressEncoderException If local-part contains non-ASCII characters
*/
public function encodeString(string $address): string
{
$i = strrpos($address, '@');
if (false !== $i) {
$local = substr($address, 0, $i);
$domain = substr($address, $i + 1);
if (preg_match('/[^\x00-\x7F]/', $local)) {
throw new Swift_AddressEncoderException('Non-ASCII characters not supported in local-part', $address);
}
if (preg_match('/[^\x00-\x7F]/', $domain)) {
$address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46));
}
}
return $address;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of SwiftMailer.
* (c) 2018 Christian Schmidt
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* A UTF-8 email address encoder.
*
* Returns the email address verbatimly in UTF-8 as permitted by RFC 6531 and
* RFC 6532. It supports addresses containing non-ASCII characters in both
* local-part and domain (i.e. on both sides of @).
*
* This encoder must be used together with Swift_Transport_Esmtp_SmtpUtf8Handler
* and requires that the outbound SMTP server supports the SMTPUTF8 extension.
*
* If your outbound SMTP server does not support SMTPUTF8, use
* Swift_AddressEncoder_IdnAddressEncoder instead. This allows sending to email
* addresses with non-ASCII characters in the domain, but not in local-part.
*
* @author Christian Schmidt
*/
class Swift_AddressEncoder_Utf8AddressEncoder implements Swift_AddressEncoder
{
/**
* Returns the address verbatimly.
*/
public function encodeString(string $address): string
{
return $address;
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of SwiftMailer.
* (c) 2018 Christian Schmidt
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* AddressEncoderException when the specified email address is in a format that
* cannot be encoded by a given address encoder.
*
* @author Christian Schmidt
*/
class Swift_AddressEncoderException extends Swift_RfcComplianceException
{
protected $address;
public function __construct(string $message, string $address)
{
parent::__construct($message);
$this->address = $address;
}
public function getAddress(): string
{
return $this->address;
}
}

View File

@ -26,17 +26,14 @@ class Swift_Attachment extends Swift_Mime_Attachment
*/
public function __construct($data = null, $filename = null, $contentType = null)
{
call_user_func_array(
array($this, 'Swift_Mime_Attachment::__construct'),
\call_user_func_array(
[$this, 'Swift_Mime_Attachment::__construct'],
Swift_DependencyContainer::getInstance()
->createDependenciesFor('mime.attachment')
);
$this->setBody($data);
$this->setBody($data, $contentType);
$this->setFilename($filename);
if ($contentType) {
$this->setContentType($contentType);
}
}
/**
@ -45,7 +42,7 @@ class Swift_Attachment extends Swift_Mime_Attachment
* @param string $path
* @param string $contentType optional
*
* @return Swift_Mime_Attachment
* @return self
*/
public static function fromPath($path, $contentType = null)
{

View File

@ -25,7 +25,7 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
*
* @var Swift_StreamFilter[]
*/
private $filters = array();
private $filters = [];
/**
* A buffer for writing.
@ -37,7 +37,7 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
*
* @var Swift_InputByteStream[]
*/
private $mirrors = array();
private $mirrors = [];
/**
* Commit the given bytes to the storage medium immediately.
@ -54,8 +54,7 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
/**
* Add a StreamFilter to this InputByteStream.
*
* @param Swift_StreamFilter $filter
* @param string $key
* @param string $key
*/
public function addFilter(Swift_StreamFilter $filter, $key)
{
@ -110,8 +109,6 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
*
* The stream acts as an observer, receiving all data that is written.
* All {@link write()} and {@link flushBuffers()} operations will be mirrored.
*
* @param Swift_InputByteStream $is
*/
public function bind(Swift_InputByteStream $is)
{
@ -124,14 +121,12 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
* If $is is not bound, no errors will be raised.
* If the stream currently has any buffered data it will be written to $is
* before unbinding occurs.
*
* @param Swift_InputByteStream $is
*/
public function unbind(Swift_InputByteStream $is)
{
foreach ($this->mirrors as $k => $stream) {
if ($is === $stream) {
if ($this->writeBuffer !== '') {
if ('' !== $this->writeBuffer) {
$stream->write($this->writeBuffer);
}
unset($this->mirrors[$k]);
@ -147,7 +142,7 @@ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_I
*/
public function flushBuffers()
{
if ($this->writeBuffer !== '') {
if ('' !== $this->writeBuffer) {
$this->doWrite($this->writeBuffer);
}
$this->flush();

View File

@ -20,7 +20,7 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
*
* @var string[]
*/
private $array = array();
private $array = [];
/**
* The size of the stack.
@ -41,7 +41,7 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
*
* @var Swift_InputByteStream[]
*/
private $mirrors = array();
private $mirrors = [];
/**
* Create a new ArrayByteStream.
@ -52,13 +52,13 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
*/
public function __construct($stack = null)
{
if (is_array($stack)) {
if (\is_array($stack)) {
$this->array = $stack;
$this->arraySize = count($stack);
} elseif (is_string($stack)) {
$this->arraySize = \count($stack);
} elseif (\is_string($stack)) {
$this->write($stack);
} else {
$this->array = array();
$this->array = [];
}
}
@ -102,7 +102,7 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
foreach ($to_add as $value) {
$this->array[] = $value;
}
$this->arraySize = count($this->array);
$this->arraySize = \count($this->array);
foreach ($this->mirrors as $stream) {
$stream->write($bytes);
@ -121,8 +121,6 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
*
* The stream acts as an observer, receiving all data that is written.
* All {@link write()} and {@link flushBuffers()} operations will be mirrored.
*
* @param Swift_InputByteStream $is
*/
public function bind(Swift_InputByteStream $is)
{
@ -135,8 +133,6 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
* If $is is not bound, no errors will be raised.
* If the stream currently has any buffered data it will be written to $is
* before unbinding occurs.
*
* @param Swift_InputByteStream $is
*/
public function unbind(Swift_InputByteStream $is)
{
@ -172,7 +168,7 @@ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_O
public function flushBuffers()
{
$this->offset = 0;
$this->array = array();
$this->array = [];
$this->arraySize = 0;
foreach ($this->mirrors as $stream) {

View File

@ -81,7 +81,7 @@ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterabl
// If we read one byte after reaching the end of the file
// feof() will return false and an empty string is returned
if ($bytes === '' && feof($fp)) {
if ((false === $bytes || '' === $bytes) && feof($fp)) {
$this->resetReadHandle();
return false;
@ -131,7 +131,7 @@ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterabl
throw new Swift_IoException('Unable to open file for reading ['.$this->path.']');
}
$this->reader = $pointer;
if ($this->offset != 0) {
if (0 != $this->offset) {
$this->getReadStreamSeekableStatus();
$this->seekReadStreamToPosition($this->offset);
}
@ -145,9 +145,7 @@ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterabl
{
if (!isset($this->writer)) {
if (!$this->writer = fopen($this->path, $this->mode)) {
throw new Swift_IoException(
'Unable to open file for writing ['.$this->path.']'
);
throw new Swift_IoException('Unable to open file for writing ['.$this->path.']');
}
}
@ -173,10 +171,10 @@ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterabl
/** Streams in a readOnly stream ensuring copy if needed */
private function seekReadStreamToPosition($offset)
{
if ($this->seekable === null) {
if (null === $this->seekable) {
$this->getReadStreamSeekableStatus();
}
if ($this->seekable === false) {
if (false === $this->seekable) {
$currentPos = ftell($this->reader);
if ($currentPos < $offset) {
$toDiscard = $offset - $currentPos;
@ -194,7 +192,7 @@ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterabl
{
if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) {
/* We have opened a php:// Stream Should work without problem */
} elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
} elseif (\function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
/* We have opened a tmpfile */
} else {
throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');

View File

@ -17,7 +17,7 @@ class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByte
{
$filePath = tempnam(sys_get_temp_dir(), 'FileByteStream');
if ($filePath === false) {
if (false === $filePath) {
throw new Swift_IoException('Failed to retrieve temporary file name.');
}
@ -26,7 +26,7 @@ class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByte
public function getContent()
{
if (($content = file_get_contents($this->getPath())) === false) {
if (false === ($content = file_get_contents($this->getPath()))) {
throw new Swift_IoException('Failed to get temporary file content.');
}
@ -39,4 +39,14 @@ class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByte
@unlink($this->getPath());
}
}
public function __sleep()
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
public function __wakeup()
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
}

View File

@ -45,7 +45,7 @@ class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterRe
*/
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
{
$strlen = strlen($string);
$strlen = \strlen($string);
// % and / are CPU intensive, so, maybe find a better way
$ignored = $strlen % $this->width;
$ignoredChars = $ignored ? substr($string, -$ignored) : '';

View File

@ -27,7 +27,7 @@ class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader
*/
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
{
$strlen = strlen($string);
$strlen = \strlen($string);
$ignoredChars = '';
for ($i = 0; $i < $strlen; ++$i) {
if ($string[$i] > "\x07F") {
@ -65,7 +65,7 @@ class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader
public function validateByteSequence($bytes, $size)
{
$byte = reset($bytes);
if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) {
if (1 == \count($bytes) && $byte >= 0x00 && $byte <= 0x7F) {
return 0;
}

View File

@ -17,8 +17,8 @@
class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
{
/** Pre-computed for optimization */
private static $length_map = array(
// N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,
private static $length_map = [
// N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N
@ -34,10 +34,10 @@ class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN
);
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN
];
private static $s_length_map = array(
private static $s_length_map = [
"\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1,
"\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1,
"\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1,
@ -70,7 +70,7 @@ class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
"\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3,
"\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4,
"\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0,
);
];
/**
* Returns the complete character map.
@ -85,22 +85,22 @@ class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
{
if (!isset($currentMap['i']) || !isset($currentMap['p'])) {
$currentMap['p'] = $currentMap['i'] = array();
$currentMap['p'] = $currentMap['i'] = [];
}
$strlen = strlen($string);
$charPos = count($currentMap['p']);
$strlen = \strlen($string);
$charPos = \count($currentMap['p']);
$foundChars = 0;
$invalid = false;
for ($i = 0; $i < $strlen; ++$i) {
$char = $string[$i];
$size = self::$s_length_map[$char];
if ($size == 0) {
if (0 == $size) {
/* char is invalid, we must wait for a resync */
$invalid = true;
continue;
} else {
if ($invalid == true) {
if (true === $invalid) {
/* We mark the chars as invalid and start a new char */
$currentMap['p'][$charPos + $foundChars] = $startOffset + $i;
$currentMap['i'][$charPos + $foundChars] = true;

View File

@ -20,14 +20,14 @@ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift
*
* @var array
*/
private static $map = array();
private static $map = [];
/**
* Factories which have already been loaded.
*
* @var Swift_CharacterReaderFactory[]
*/
private static $loaded = array();
private static $loaded = [];
/**
* Creates a new CharacterReaderFactory.
@ -44,32 +44,32 @@ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift
public function init()
{
if (count(self::$map) > 0) {
if (\count(self::$map) > 0) {
return;
}
$prefix = 'Swift_CharacterReader_';
$singleByte = array(
$singleByte = [
'class' => $prefix.'GenericFixedWidthReader',
'constructor' => array(1),
);
'constructor' => [1],
];
$doubleByte = array(
$doubleByte = [
'class' => $prefix.'GenericFixedWidthReader',
'constructor' => array(2),
);
'constructor' => [2],
];
$fourBytes = array(
$fourBytes = [
'class' => $prefix.'GenericFixedWidthReader',
'constructor' => array(4),
);
'constructor' => [4],
];
// Utf-8
self::$map['utf-?8'] = array(
self::$map['utf-?8'] = [
'class' => $prefix.'Utf8Reader',
'constructor' => array(),
);
'constructor' => [],
];
//7-8 bit charsets
self::$map['(us-)?ascii'] = $singleByte;
@ -103,11 +103,11 @@ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift
*/
public function getReaderFor($charset)
{
$charset = strtolower(trim($charset));
$charset = strtolower(trim($charset ?? ''));
foreach (self::$map as $pattern => $spec) {
$re = '/^'.$pattern.'$/D';
if (preg_match($re, $charset)) {
if (!array_key_exists($pattern, self::$loaded)) {
if (!\array_key_exists($pattern, self::$loaded)) {
$reflector = new ReflectionClass($spec['class']);
if ($reflector->getConstructor()) {
$reader = $reflector->newInstanceArgs($spec['constructor']);

View File

@ -28,8 +28,6 @@ interface Swift_CharacterStream
/**
* Set the CharacterReaderFactory for multi charset support.
*
* @param Swift_CharacterReaderFactory $factory
*/
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory);

Some files were not shown because too many files have changed in this diff Show More