diff --git a/.travis.yml b/.travis.yml index 688d706331d..9958556d42d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -404,6 +404,10 @@ script: php upgrade.php 11.0.0 12.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade11001200.log php upgrade2.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-2.log php step5.php 11.0.0 12.0.0 > $TRAVIS_BUILD_DIR/upgrade11001200-3.log + php upgrade.php 12.0.0 13.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade12001300.log + php upgrade2.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-2.log + php step5.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-3.log + # Enable modules not enabled into original dump php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKETSUP,MAIN_MODULE_ACCOUNTING > $TRAVIS_BUILD_DIR/enablemodule.log echo $? diff --git a/ChangeLog b/ChangeLog index dafa90b9632..20a1748af6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -78,7 +78,7 @@ FIX: we must export company mail address on contact vcard only if contact email FIX: when we filter a list on a view status, we want this filter to be on bookmark that we create FIX: Wrong Sql on getListOfTowns api method FIX: wrong user right's name to top menu "commercial" -FIX: XSS Vulnerability +FIX: XSS Vulnerability reported by Mehmet Kelepçe / Gais Cyber Security ***** ChangeLog for 12.0.0 compared to 11.0.0 ***** For Users: diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile index 4b1df7e0876..9264eed5ef2 100644 --- a/build/docker/Dockerfile +++ b/build/docker/Dockerfile @@ -3,7 +3,7 @@ FROM php:7.2-apache ENV HOST_USER_ID 33 ENV PHP_INI_DATE_TIMEZONE 'UTC' -RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev libldap2-dev libzip-dev zlib1g-dev libicu-dev g++\ +RUN apt-get update && apt-get install -y libpng16-16 libpng-dev libjpeg62-turbo libjpeg62-turbo-dev libldap2-dev zlib1g-dev libicu-dev g++\ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ && docker-php-ext-install gd \ @@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev libldap2-dev lib && docker-php-ext-install calendar \ && docker-php-ext-configure intl \ && docker-php-ext-install intl \ - && apt-get autoremove --purge -y libjpeg-dev libldap2-dev zlib1g-dev libicu-dev g++ + && apt-get autoremove --purge -y libpng-dev libjpeg62-turbo-dev libldap2-dev zlib1g-dev libicu-dev g++ RUN mkdir /var/documents RUN chown www-data /var/documents diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml index 3fe6125a874..cc839810e7f 100644 --- a/build/docker/docker-compose.yml +++ b/build/docker/docker-compose.yml @@ -21,5 +21,12 @@ web: - ../../htdocs:/var/www/html links: - mariadb + - mail ports: - "80:80" + +mail: + image: maildev/maildev + ports: + - "8081:80" + - "25:25" \ No newline at end of file diff --git a/dev/setup/codesniffer/ruleset.xml b/dev/setup/codesniffer/ruleset.xml index ad26c7f0bdc..e726df6db7c 100644 --- a/dev/setup/codesniffer/ruleset.xml +++ b/dev/setup/codesniffer/ruleset.xml @@ -272,12 +272,7 @@ - - - - - - + 0 @@ -310,20 +305,21 @@ - - + 0 - + 0 + - 0 + 0 - + + 0 @@ -332,27 +328,25 @@ - + 0 - + + 0 - - 0 - + + + - 0 + 0 - - 0 - - - 0 - + + + @@ -361,26 +355,26 @@ 0 + - 0 + 0 - + 0 + - - 0 - + 0 0 - + 0 @@ -391,16 +385,16 @@ + + 0 + - - - - + 0 @@ -411,7 +405,6 @@ 0 - 0 @@ -421,15 +414,17 @@ - - - - - + + + + + + + diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 86981e5b5de..2ac97ee38ac 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -161,7 +161,7 @@ if (empty($reshook)) if ($action == 'disable') { if ($accounting->fetch($id)) { $mode = GETPOST('mode', 'int'); - $result = $accounting->account_desactivate($id, $mode); + $result = $accounting->accountDeactivate($id, $mode); } $action = 'update'; @@ -267,7 +267,7 @@ if ($resql) { $num = $db->num_rows($resql); - $param = ''; + $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.$limit; if ($search_account) $param .= '&search_account='.urlencode($search_account); diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index b2a25b00ce2..4de2be6fcbb 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -55,7 +55,7 @@ $pagenext = $page + 1; //if (! $sortfield) $sortfield="p.date_fin"; //if (! $sortorder) $sortorder="DESC"; - +$show_subgroup = GETPOST('show_subgroup', 'alpha'); $search_date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); $search_date_end = dol_mktime(23, 59, 59, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); @@ -130,10 +130,11 @@ if (!empty($search_accountancy_code_end)) { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers { - $search_accountancy_code_start = ''; - $search_accountancy_code_end = ''; + $show_subgroup = ''; $search_date_start = ''; $search_date_end = ''; + $search_accountancy_code_start = ''; + $search_accountancy_code_end = ''; $filter = array(); } @@ -223,6 +224,12 @@ if ($action != 'export_csv') $moreforfilter .= $form->selectDate($search_date_start ? $search_date_start : -1, 'date_start', 0, 0, 1, '', 1, 0); $moreforfilter .= $langs->trans('DateEnd').': '; $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0); + + $moreforfilter .= ' - '; + $moreforfilter .= $langs->trans('ShowSubtotalByGroup').': '; + $moreforfilter .= ''; + + $moreforfilter .= ''; if (!empty($moreforfilter)) { @@ -289,26 +296,31 @@ if ($action != 'export_csv') } print ''; - // Permet d'afficher le compte comptable - if (empty($displayed_account) || $root_account_description != $displayed_account) + if (!empty($show_subgroup)) { - // Affiche un Sous-Total par compte comptable - if ($displayed_account != "") { - print ''.$langs->trans("SubTotal").':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_credit - $sous_total_debit)).''; - print " \n"; + // Show accounting account + if (empty($displayed_account) || $root_account_description != $displayed_account) { + // Show subtotal per accounting account + if ($displayed_account != "") { + print ''; + print ''.$langs->trans("SubTotal").':'; + print ''.price($sous_total_debit).''; + print ''.price($sous_total_credit).''; + print ''.price(price2num($sous_total_credit - $sous_total_debit)).''; + print "\n"; + print ''; + } + + // Show first line of a break + print ''; + print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; print ''; + + $displayed_account = $root_account_description; + $sous_total_debit = 0; + $sous_total_credit = 0; } - - // Show first line of a break - print ''; - print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; - print ''; - - $displayed_account = $root_account_description; - $sous_total_debit = 0; - $sous_total_credit = 0; } - // $object->get_compte_racine($line->numero_compte); print ''.length_accountg($line->numero_compte).''; @@ -326,12 +338,15 @@ if ($action != 'export_csv') $sous_total_credit += $line->credit; } - print ''.$langs->trans("SubTotal").':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_debit - $sous_total_credit)).''; - print " \n"; - print ''; + if (!empty($show_subgroup)) + { + print ''.$langs->trans("SubTotal").':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_debit - $sous_total_credit)).''; + print "\n"; + print ''; + } print ''.$langs->trans("AccountBalance").':'.price($total_debit).''.price($total_credit).''.price(price2num($total_debit - $total_credit)).''; - print " \n"; + print "\n"; print ''; print ""; diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 26476119cca..f8fa0774400 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -438,7 +438,7 @@ if ($action == 'create') print $langs->trans('Docdate'); print ''; if ($action != 'editdate') - print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('SetDate'), 1).''; + print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('SetDate'), 1).''; print ''; print ''; if ($action == 'editdate') { @@ -462,7 +462,7 @@ if ($action == 'create') print $langs->trans('Codejournal'); print ''; if ($action != 'editjournal') - print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).''; + print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).''; print ''; print ''; if ($action == 'editjournal') { @@ -486,7 +486,7 @@ if ($action == 'create') print $langs->trans('Piece'); print ''; if ($action != 'editdocref') - print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).''; + print 'piece_num.'&mode='.$mode.'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).''; print ''; print ''; if ($action == 'editdocref') { @@ -650,8 +650,8 @@ if ($action == 'create') print ''.price($line->credit).''; print ''; - print 'id.'&piece_num='.$line->piece_num.'&mode='.$mode.'">'; - print img_edit(); + print 'id.'&piece_num='.$line->piece_num.'&mode='.$mode.'">'; + print img_edit('', 0, 'class="marginrightonly"'); print '  '; $actiontodelete = 'delete'; diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index a32918cc5bf..bcd17793db1 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -553,24 +553,19 @@ class AccountingAccount extends CommonObject } } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Account deactivated + * Deactivate an account (for status active or status reconcilable) * * @param int $id Id - * @param int $mode 0=field active, 1=field active_customer_list, 2=field_active_supplier_list + * @param int $mode 0=field active, 1=field reconcilable * @return int <0 if KO, >0 if OK */ - public function account_desactivate($id, $mode = 0) + public function accountDeactivate($id, $mode = 0) { - // phpcs:enable $result = $this->checkUsage(); - if ($mode == 0) - { - $fieldtouse = 'active'; - } - elseif ($mode == 1) + $fieldtouse = 'active'; + if ($mode == 1) { $fieldtouse = 'reconcilable'; } @@ -582,7 +577,7 @@ class AccountingAccount extends CommonObject $sql .= "SET ".$fieldtouse." = '0'"; $sql .= " WHERE rowid = ".$this->db->escape($id); - dol_syslog(get_class($this)."::account_desactivate ".$fieldtouse." sql=".$sql, LOG_DEBUG); + dol_syslog(get_class($this)."::accountDeactivate ".$fieldtouse." sql=".$sql, LOG_DEBUG); $result = $this->db->query($sql); if ($result) { diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 15cfd9ed9db..cce441c4052 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -644,6 +644,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($value == 'localtax2' && empty($_POST['localtax2_type'])) continue; if ($value == 'color' && empty($_POST['color'])) continue; if ($value == 'formula' && empty($_POST['formula'])) continue; + if ($value == 'dayrule' && empty($_POST['dayrule'])) continue; if ($value == 'sortorder') continue; // For a column name 'sortorder', we use the field name 'position' if ((!isset($_POST[$value]) || $_POST[$value] == '') && (!in_array($listfield[$f], array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking')) // Fields that are not mandatory diff --git a/htdocs/admin/dolistore/ajax/image.php b/htdocs/admin/dolistore/ajax/image.php index 8d1122417b5..7c25e9d33a5 100644 --- a/htdocs/admin/dolistore/ajax/image.php +++ b/htdocs/admin/dolistore/ajax/image.php @@ -1,6 +1,7 @@ . * Copyright (C) 2008-2011 Laurent Destailleur + * Copyright (C) 2020 Frédéric France * * This program is free software; you can redistribute it and/or modifyion 2.0 (the "License"); * it under the terms of the GNU General Public License as published bypliance with the License. @@ -17,6 +18,9 @@ */ if (!defined('REQUIRE_JQUERY_BLOCKUI')) define('REQUIRE_JQUERY_BLOCKUI', 1); +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', 1); +} /** diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index 230c588f7e4..a229f3c985d 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -248,11 +248,8 @@ class Dolistore // phpcs:enable global $langs, $conf; $html = ""; - $parity = "pair"; $last_month = time() - (30 * 24 * 60 * 60); foreach ($this->products as $product) { - $parity = ($parity == "impair") ? 'pair' : 'impair'; - // check new product ? $newapp = ''; if ($last_month < strtotime($product->date_add)) { @@ -267,7 +264,7 @@ class Dolistore // add image or default ? if ($product->id_default_image != '') { $image_url = DOL_URL_ROOT.'/admin/dolistore/ajax/image.php?id_product='.$product->id.'&id_image='.$product->id_default_image; - $images = ''; + $images = ''; $images .= ''; } else { $images = ''; @@ -306,16 +303,16 @@ class Dolistore //.'
'.$langs->trans("SeeInMarkerPlace").' //output template - $html .= ' + $html .= '
'.$newapp.$images.'

'.$product->name->language[$this->lang - 1] .'
'.$version.'

- '.dol_print_date(dol_stringtotime($product->date_upd), 'dayhour').' - '.$langs->trans('Ref').': '.$product->reference.' - '.$langs->trans('Id').': '.$product->id.'

'.$product->description_short->language[$this->lang - 1].' - '.$product->description->language[$this->lang - 1].' - '.$price.' - - '.$download_link.' - '; + '.dol_print_date(dol_stringtotime($product->date_upd), 'dayhour').' - '.$langs->trans('Ref').': '.$product->reference.' - '.$langs->trans('Id').': '.$product->id.'

'.$product->description_short->language[$this->lang - 1].''; + // do not load if display none + //$html .= ''.$product->description->language[$this->lang - 1].''; + $html .= ''.$price.''; + $html .= ''.$download_link.''; + $html .= ''; } return $html; } diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 74592ff777a..80161eaadc6 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -592,7 +592,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; $htmltext = $langs->transnoentitiesnoconv("OperationParamDesc"); //var_dump($htmltext); - print $form->textwithpicto('', $htmltext); + print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'operationparamtt'); print ''; print ''; print ''; @@ -643,7 +643,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; // Delete print ''; - print ''.img_edit().''; + print ''.img_edit().''; print ' '.img_delete().''; print ''; print ''; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 6a0ff450346..c0f1991835b 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -680,7 +680,9 @@ if ($mode == 'common' || $mode == 'commonkanban') if (preg_match('/development/i', $version)) $versiontrans .= img_warning($langs->trans("Development"), 'style="float: left"'); if (preg_match('/experimental/i', $version)) $versiontrans .= img_warning($langs->trans("Experimental"), 'style="float: left"'); if (preg_match('/deprecated/i', $version)) $versiontrans .= img_warning($langs->trans("Deprecated"), 'style="float: left"'); - $versiontrans .= $objMod->getVersion(1); + if ($objMod->isCoreOrExternalModule() == 'external' || preg_match('/development|experimental|deprecated/i', $version)) { + $versiontrans .= $objMod->getVersion(1); + } // Define imginfo $imginfo = "info"; diff --git a/htdocs/admin/payment.php b/htdocs/admin/payment.php index e740150e1d5..a5b494b62e2 100644 --- a/htdocs/admin/payment.php +++ b/htdocs/admin/payment.php @@ -1,5 +1,6 @@ + * Copyright (C) 2020 Maxime DEMAREST * * 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 @@ -70,11 +71,12 @@ if ($action == 'setmod') if ($action == 'setparams') { $freetext = GETPOST('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS', 'none'); // No alpha here, we want exact string - $res = dolibarr_set_const($db, "FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS", $freetext, 'chaine', 0, '', $conf->entity); - if (!$res > 0) $error++; + $res = dolibarr_set_const($db, "PAYMENTS_REPORT_GROUP_BY_MOD", GETPOST('PAYMENTS_REPORT_GROUP_BY_MOD', 'int'), 'chaine', 0, '', $conf->entity); + if (!$res > 0) $error++; + if ($error) { setEventMessages($langs->trans("Error"), null, 'errors'); @@ -253,6 +255,14 @@ print $form->selectyesno("FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS", $co print ''; print "\n"; +// Allow to group payments by mod in rapports +print ''; +print $langs->trans("GroupPaymentsByModOnReports"); +print ''; +print $form->selectyesno("PAYMENTS_REPORT_GROUP_BY_MOD", $conf->global->PAYMENTS_REPORT_GROUP_BY_MOD, 1); +print ''; +print "\n"; + print ''; print ''; diff --git a/htdocs/admin/security.php b/htdocs/admin/security.php index f016c305a15..d9d61673c5e 100644 --- a/htdocs/admin/security.php +++ b/htdocs/admin/security.php @@ -168,9 +168,9 @@ elseif ($action == 'disable_MAIN_SECURITY_DISABLEFORGETPASSLINK') exit; } -if ($action == 'maj_pattern') +if ($action == 'updatepattern') { - $pattern = GETPOST("pattern"); + $pattern = GETPOST("pattern", "alpha"); $explodePattern = explode(';', $pattern); $patternInError = false; @@ -184,6 +184,7 @@ if ($action == 'maj_pattern') if (!$patternInError) { dolibarr_set_const($db, "USER_PASSWORD_PATTERN", $pattern, 'chaine', 0, '', $conf->entity); + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); header("Location: security.php"); exit; } @@ -336,11 +337,9 @@ if ($conf->global->USER_PASSWORD_GENERATED == "Perso") { print ''; print '
'; - print ''; - print ''; - print '
'; + print '
'; print ''.$langs->trans("Save").''; - print '
'; + print ''; print '

'; print ''; - } - } - } - - return $out; - } - - /** - * Fill array_options property of object by extrafields value (using for data sent by forms) - * - * @param array $extralabels Deprecated (old $array of extrafields, now set this to null) - * @param object $object Object - * @param string $onlykey Only the following key is filled. When we make update of only one extrafield ($action = 'update_extras'), calling page must set this to avoid to have other extrafields being reset. - * @return int 1 if array_options set, 0 if no value, -1 if error (field required missing for example) - */ - public function setOptionalsFromPost($extralabels, &$object, $onlykey = '') - { - global $_POST, $langs; - - $nofillrequired = 0; // For error when required field left blank - $error_field_required = array(); - - if (is_array($this->attributes[$object->table_element]['label'])) $extralabels = $this->attributes[$object->table_element]['label']; - - if (is_array($extralabels)) - { - // Get extra fields - foreach ($extralabels as $key => $value) - { - if (!empty($onlykey) && $key != $onlykey) continue; - - $key_type = $this->attributes[$object->table_element]['type'][$key]; - if ($key_type == 'separate') continue; - - $enabled = 1; - if (isset($this->attributes[$object->table_element]['list'][$key])) - { - $enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1); - } - $perms = 1; - if (isset($this->attributes[$object->table_element]['perms'][$key])) - { - $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1); - } - if (empty($enabled)) continue; - if (empty($perms)) continue; - - if ($this->attributes[$object->table_element]['required'][$key]) // Value is required - { - // Check if empty without using GETPOST, value can be alpha, int, array, etc... - if ((!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] != 'select' && $_POST["options_".$key] != '0') - || (!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'select') - || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) - { - //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key]; - $nofillrequired++; - $error_field_required[] = $langs->transnoentitiesnoconv($value); - } - } - - if (in_array($key_type, array('date'))) - { - // Clean parameters - // TODO GMT date in memory must be GMT so we should add gm=true in parameters - $value_key = dol_mktime(0, 0, 0, $_POST["options_".$key."month"], $_POST["options_".$key."day"], $_POST["options_".$key."year"]); - } - elseif (in_array($key_type, array('datetime'))) - { - // Clean parameters - // TODO GMT date in memory must be GMT so we should add gm=true in parameters - $value_key = dol_mktime($_POST["options_".$key."hour"], $_POST["options_".$key."min"], 0, $_POST["options_".$key."month"], $_POST["options_".$key."day"], $_POST["options_".$key."year"]); - } - elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) - { - $value_arr = GETPOST("options_".$key, 'array'); // check if an array - if (!empty($value_arr)) { - $value_key = implode($value_arr, ','); - } else { - $value_key = ''; - } - } - elseif (in_array($key_type, array('price', 'double'))) - { - $value_arr = GETPOST("options_".$key, 'alpha'); - $value_key = price2num($value_arr); - } - else - { - $value_key = GETPOST("options_".$key); - if (in_array($key_type, array('link')) && $value_key == '-1') $value_key = ''; - } - - $object->array_options["options_".$key] = $value_key; - } - - if ($nofillrequired) { - $langs->load('errors'); - setEventMessages($langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required), null, 'errors'); - return -1; - } - else { - return 1; - } - } - else { - return 0; - } - } - - /** - * return array_options array of data of extrafields value of object sent by a search form - * - * @param array|string $extrafieldsobjectkey array of extrafields (old usage) or value of object->table_element (new usage) - * @param string $keyprefix Prefix string to add into name and id of field (can be used to avoid duplicate names) - * @param string $keysuffix Suffix string to add into name and id of field (can be used to avoid duplicate names) - * @return array|int array_options set or 0 if no value - */ - public function getOptionalsFromPost($extrafieldsobjectkey, $keyprefix = '', $keysuffix = '') - { - global $_POST; - - if (is_string($extrafieldsobjectkey) && is_array($this->attributes[$extrafieldsobjectkey]['label'])) - { - $extralabels = $this->attributes[$extrafieldsobjectkey]['label']; - } - else - { - $extralabels = $extrafieldsobjectkey; - } - - if (is_array($extralabels)) - { - $array_options = array(); - - // Get extra fields - foreach ($extralabels as $key => $value) - { - $key_type = ''; - if (is_string($extrafieldsobjectkey)) - { - $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key]; - } - - if (in_array($key_type, array('date', 'datetime'))) - { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it. - // Clean parameters - $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); - } - elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) - { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it. - $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix); - // Make sure we get an array even if there's only one checkbox - $value_arr = (array) $value_arr; - $value_key = implode(',', $value_arr); - } - elseif (in_array($key_type, array('price', 'double', 'int'))) - { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it. - $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix); - $value_key = price2num($value_arr); - } - else - { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it. - $value_key = GETPOST($keysuffix."options_".$key.$keyprefix); - } - - $array_options[$keysuffix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read. - } - - return $array_options; - } - - return 0; - } } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 5fe411c6260..d7e46922f56 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -368,6 +368,8 @@ class Form $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"'); $resultforextrlang .= $s; + + // TODO Use the showInputField() method of ExtraLanguages object if ($typeofdata == 'textarea') { $resultforextrlang .= ' + '; + print '
'; +} +elseif ($action == "publicpayment") { + $langs->loadLangs(array("orders")); + print '

'.$langs->trans('StatusOrderDelivered').'

'; + print ''; + print '
'; +} +elseif ($action == "checkplease") { + print ''; + print ''; + print '
'; +} +elseif ($action == "editline") { + $placeid = GETPOST('placeid', 'int'); + $selectedline = GETPOST('selectedline', 'int'); + $invoice = new Facture($db); + $invoice->fetch($placeid); + foreach ($invoice->lines as $line) { - if ($categorycursor['id'] == $conf->global->TAKEPOS_ROOT_CATEGORY_ID) - { - $levelofrootcategory = $categorycursor['level']; - break; + if ($line->id == $selectedline) + { + $prod = new Product($db); + $prod->fetch($line->fk_product); + print "".$prod->label."
"; + print ''; + print "
".$prod->description; + print "
".price($prod->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).""; + print '
'; + print ''; + print ''; + print ''; } } } -$levelofmaincategories = $levelofrootcategory + 1; +else { + // Title + $title = 'TakePOS - Dolibarr '.DOL_VERSION; + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $title = 'TakePOS - '.$conf->global->MAIN_APPLICATION_TITLE; + $head = ' + + +'; + $arrayofcss = array('/takepos/css/phone.css'); + top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); + ?> + - -global->TAKEPOS_NUM_TERMINALS != "1" && $_SESSION["takeposterminal"] == "") print '
'.$langs->trans('TerminalSelect').'
'; -?> + + global->TAKEPOS_NUM_TERMINALS != "1" && $_SESSION["takeposterminal"] == "") print '
'.$langs->trans('TerminalSelect').'
'; + ?>
'.strtoupper(substr($langs->trans('Floors'), 0, 3)).''; - print ''; - print ''; - print ''; - if ($_SESSION["publicterminal"]) print ''; + if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) { + print ''; + print ''; + print ''; + print ''; + } + else { + print ''; + print ''; + print ''; + } ?>
-
-
-
-
+
+
+
+
-global->TAKEPOS_AUTO_ORDER) accessforbidden(); // If Auto Order is disabled never allow NO LOGIN access + $_SESSION["basiclayout"] = 1; -$_SESSION["publicterminal"] = true; // Is a public customer +$_SESSION["takeposterminal"] = 1; define('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE', 1); -include '../phone.php'; +if (GETPOSTISSET("mobilepage")) require '../invoice.php'; +elseif (GETPOSTISSET("genimg")) require DOL_DOCUMENT_ROOT.'/takepos/genimg/index.php'; +else require '../phone.php'; diff --git a/htdocs/theme/dolibarr_logo.png b/htdocs/theme/dolibarr_logo.png index 77c21461910..c15f03c821b 100644 Binary files a/htdocs/theme/dolibarr_logo.png and b/htdocs/theme/dolibarr_logo.png differ diff --git a/htdocs/theme/eldy/dropdown.inc.php b/htdocs/theme/eldy/dropdown.inc.php index 49f910f50da..479bb3f889b 100644 --- a/htdocs/theme/eldy/dropdown.inc.php +++ b/htdocs/theme/eldy/dropdown.inc.php @@ -9,7 +9,7 @@ button.dropdown-item.global-search-item { outline: none; } -.open>.dropdown-search, .open>.dropdown-bookmark, .open>.dropdown-menu, .dropdown dd ul.open { +.open>.dropdown-search, .open>.dropdown-bookmark, .open>.dropdown-quickadd, .open>.dropdown-menu, .dropdown dd ul.open { display: block; } @@ -59,6 +59,29 @@ button.dropdown-item.global-search-item { -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); box-shadow: 0 6px 12px rgba(0,0,0,.175); } +.dropdown-quickadd { + border-color: #eee; + + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 240px; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0,0,0,.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); + box-shadow: 0 6px 12px rgba(0,0,0,.175); +} .dropdown-menu { border-color: #eee; @@ -163,7 +186,7 @@ button.dropdown-item.global-search-item { max-width: 100%; } -div#topmenu-global-search-dropdown, div#topmenu-bookmark-dropdown { +div#topmenu-global-search-dropdown, div#topmenu-bookmark-dropdown, div#topmenu-quickadd-dropdown { global->THEME_TOPMENU_DISABLE_IMAGE)) { ?> line-height: 46px; @@ -383,6 +406,58 @@ a.top-menu-dropdown-link { display: none !important; } +/* + * QUICK ADD + */ +#topmenu-quickadd-dropdown .dropdown-menu { + width: 300px !important; + color: #444; +} + +.quickadd-header { + color: #444 !important; +} + +div.quickadd { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; +} + +div.quickadd a { + color: #444; +} + +div.quickadd a:hover, div.quickadd a:active { + color: #000000; +} + +div.quickaddblock { + width: 80px; + display: block ruby; +} + +div.quickaddblock:hover, +div.quickaddblock:active, +div.quickaddblock:focus { + background: ; +} + /* smartphone */ @media only screen and (max-width: 767px) { diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b6884b164a1..16618f2592b 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -17,6 +17,7 @@ --colorbacklinepair2: rgb(); --colorbacklinepairhover: rgb(); --colorbacklinepairchecked: rgb(); + --colorbacklinebreak: rgb(); --colorbackbody: rgb(); --colortexttitlenotab: rgb(); --colortexttitle: rgb(); @@ -664,10 +665,10 @@ body[class*="colorblind-"] .text-success{ color : } -.editfielda span.fa-pencil-alt, .editfielda span.fa-trash, .editfieldlang { +.editfielda span.fa-pencil-alt, .editfielda span.fa-pencil-ruler, .editfielda span.fa-trash, .editfieldlang { color: #ccc !important; } -.editfielda span.fa-pencil-alt:hover, .editfielda span.fa-trash:hover, .editfieldlang:hover { +.editfielda span.fa-pencil-alt:hover, .editfielda span.fa-pencil-ruler:hover, .editfielda span.fa-trash:hover, .editfieldlang:hover { color: var(--colortexttitle) !important; } .fawidth30 { @@ -1026,6 +1027,7 @@ table[summary="list_of_modules"] .fa-cog { .clearboth { clear:both; } .hideobject { display: none; } .minwidth50 { min-width: 50px; } +.minwidth75 { min-width: 75px; } /* rule for not too small screen only */ @media only screen and (min-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3) ? round($nbtopmenuentries * 47, 0) + 130 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3; ?>px) { @@ -1187,6 +1189,18 @@ table[summary="list_of_modules"] .fa-cog { text-overflow: ellipsis; white-space: nowrap; } + .tdoverflowmax100onsmartphone { /* For tdoverflow, the max-midth become a minimum ! */ + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .tdoverflowmax150onsmartphone { /* For tdoverflow, the max-midth become a minimum ! */ + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } .border tbody tr, .border tbody tr td, div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { height: 40px !important; } @@ -1325,7 +1339,7 @@ td.showDragHandle { #id-left { padding-top: 20px; padding-bottom: 5px; - global->MAIN_USE_TOP_MENU_SEARCH_DROPDOWN)) { ?> + global->MAIN_USE_TOP_MENU_SEARCH_DROPDOWN) && ! empty($conf->global->MAIN_USE_TOP_MENU_QUICKADD_DROPDOWN)) { ?> padding-top: 8px; } @@ -1610,7 +1624,7 @@ div.nopadding { } td.nobordernopadding.widthpictotitle.col-picto { - color: var(--colortexttitlenotab); + color: #bbb; opacity: 0.85; } .table-list-of-attached-files .col-picto, .table-list-of-links .col-picto { @@ -1622,6 +1636,17 @@ td.nobordernopadding.widthpictotitle.col-picto { width: unset; color: #999; } + +span.widthpictotitle.pictotitle { + /* background: rgba(70, 3, 62, 0.5); */ + background: var(--colortexttitlenotab); + opacity: 0.8; + color: #fff !important; + padding: 7px; + border-radius: 2px; + min-width: 30px; + text-align: center; +} .pictotitle { margin-: 8px; /* margin-bottom: 4px; */ @@ -1706,6 +1731,7 @@ div.statusref { margin-top: 8px; margin-bottom: 10px; clear: both; + text-align: right; } div.statusref img { padding-left: 8px; @@ -1749,7 +1775,7 @@ img.photorefnoborder { border-bottom: px solid rgb(); /* border-bottom: 2px solid var(--colorbackhmenu1); */ } -.trextrafieldseparator td { +.trextrafieldseparator td, .trextrafields_collapse_last td { /* border-bottom: 2px solid var(--colorbackhmenu1) !important; */ border-bottom: 2px solid rgb() !important; } @@ -2721,9 +2747,15 @@ a.tabTitle { text-decoration: none; white-space: nowrap; } +.tabTitleText { + display: none; +} .imgTabTitle { max-height: 14px; } +div.tabs div.tabsElem:first-of-type a.tab { + margin-left: 0px !important; +} a.tabunactive { color: var(--colortextlink) !important; @@ -3287,7 +3319,7 @@ td.evenodd, tr.nohoverpair td, #trlinefordates td { .trforbreak td { font-weight: 500; border-bottom: 1pt solid black !important; - /* background-color: # !important; */ + background-color: var(--colorbacklinebreak) !important; !important; } .trforbreak.nobold td a, .trforbreak.nobold span.secondary { font-weight: normal !important; @@ -3598,8 +3630,19 @@ ul.noborder li:nth-child(even):not(.liste_titre) { margin-right: 8px; } + @media only screen and (max-width: 767px) { + div.tabs { + padding-left: 0 !important; + padding-right: 0!important; + margin-left: 0 !important; + margin-right: 0 !important; + } + + a.tab:link, a.tab:visited, a.tab:hover, a.tab#active { + padding: 12px 12px 13px; + } a.tmenu:link, a.tmenu:visited, a.tmenu:hover, a.tmenu:active { padding: 0px 0px 0px 0px; } @@ -3641,7 +3684,7 @@ ul.noborder li:nth-child(even):not(.liste_titre) { box-shadow: 0px 0px 8px 0px rgba(0,0,0,0.20); } span.boxstatstext { - opacity: 0.7; + opacity: 0.5; line-height: 18px; color: var(--colortext); } @@ -3874,7 +3917,7 @@ div.boximport { .fieldrequired { font-weight: bold; color: var(--fieldrequiredcolor); } -.widthpictotitle { width: 26px; text-align: ; } +td.widthpictotitle { width: 26px; text-align: ; } span.widthpictotitle { font-size: 1.7em; }; .dolgraphtitle { margin-top: 6px; margin-bottom: 4px; } @@ -6366,7 +6409,6 @@ div.tabsElem a.tab { word-break: break-word; } .badge { - line-height: 1.2em; min-width: auto; font-size: 12px; } diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 3138cd8bfd9..ade71d73f39 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -8,7 +8,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> */ .info-box-module-external span.info-box-icon-version { - background: #999; + background: #bbb; } .info-box { @@ -74,10 +74,13 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> height: 80px; width: 80px; font-size: 25px; + line-height: 100px; +} +.opened-dash-board-wrap .info-box-sm .info-box-icon { line-height: 80px; } .info-box-module .info-box-icon { - height: 106px; + height: 107px; } .info-box-icon > img { max-width: 100%; @@ -172,6 +175,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> .info-box-title{ text-transform: uppercase; font-weight: bold; + padding-bottom: 4px; } .info-box-text{ font-size: 0.92em; @@ -200,6 +204,7 @@ if (!empty($conf->global->THEME_INFOBOX_COLOR_ON_BACKGROUND)) $prefix = 'backgro if (!isset($conf->global->THEME_AGRESSIVENESS_RATIO) && $prefix) $conf->global->THEME_AGRESSIVENESS_RATIO = -50; if (GETPOSTISSET('THEME_AGRESSIVENESS_RATIO')) $conf->global->THEME_AGRESSIVENESS_RATIO = GETPOST('THEME_AGRESSIVENESS_RATIO', 'int'); //var_dump($conf->global->THEME_AGRESSIVENESS_RATIO); + ?> .info-box-icon { @@ -309,8 +314,8 @@ if (GETPOSTISSET('THEME_AGRESSIVENESS_RATIO')) $conf->global->THEME_AGRESSIVENES display: flex; /* or inline-flex */ flex-direction: row; flex-wrap: wrap; - width: 100%; - margin: 0 0 0 -8px; + width: calc(100% + 14px); + margin: 0 -8px 0 -8px; /*justify-content: space-between;*/ } @@ -343,7 +348,8 @@ if (GETPOSTISSET('THEME_AGRESSIVENESS_RATIO')) $conf->global->THEME_AGRESSIVENES @media only screen and (max-width: 767px) { .box-flex-container { - margin: 0 0 0 0 !important; + margin: 0 0 0 0px !important; + width: 100% !important; } .info-box-module { diff --git a/htdocs/theme/eldy/main_menu_fa_icons.inc.php b/htdocs/theme/eldy/main_menu_fa_icons.inc.php index 5b9395fbc04..c344838458d 100644 --- a/htdocs/theme/eldy/main_menu_fa_icons.inc.php +++ b/htdocs/theme/eldy/main_menu_fa_icons.inc.php @@ -8,7 +8,7 @@ font-style: normal; font-variant: normal; text-rendering: auto; - line-height: 26px; + line-height: 23px; font-size: ; -webkit-font-smoothing: antialiased; text-align:center; diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 927d29e1919..30a7c8635ac 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -203,7 +203,7 @@ $disableimages = 0; $maxwidthloginblock = 180; if (!empty($conf->global->THEME_TOPMENU_DISABLE_IMAGE)) { $disableimages = 1; $maxwidthloginblock = $maxwidthloginblock + 50; $minwidthtmenu = 0; } - +if (!empty($conf->global->MAIN_USE_TOP_MENU_QUICKADD_DROPDOWN)) { $maxwidthloginblock = $maxwidthloginblock + 55; } if (!empty($conf->global->MAIN_USE_TOP_MENU_SEARCH_DROPDOWN)) { $maxwidthloginblock = $maxwidthloginblock + 55; } if (!empty($conf->bookmark->enabled)) { $maxwidthloginblock = $maxwidthloginblock + 55; } diff --git a/htdocs/theme/eldy/theme_vars.inc.php b/htdocs/theme/eldy/theme_vars.inc.php index 823b8168b4c..d2a11725ecf 100644 --- a/htdocs/theme/eldy/theme_vars.inc.php +++ b/htdocs/theme/eldy/theme_vars.inc.php @@ -65,7 +65,7 @@ $colorbacklinepair1 = '251,251,251'; // line pair $colorbacklinepair2 = '251,251,251'; // line pair $colorbacklinepairhover = '230,237,244'; // line hover $colorbacklinepairchecked = '230,237,244'; // line checked -$colorbacklinebreak = '233,228,230'; // line break +$colorbacklinebreak = '253,251,250'; // line break $colorbackbody = '255,255,255'; $colortexttitlenotab = '0,113,120'; // 150,90,121 140,80,10 or 10,140,80 #875a7b green=0,113,120, violet: 0,50,120 $colortexttitle = '0,0,0'; diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index d866cab96a6..2dec0087a1b 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -2,27 +2,68 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> /*