diff --git a/dev/skeletons/build_class_from_table.php b/dev/skeletons/build_class_from_table.php index 62ad1188759..d9e30b23501 100755 --- a/dev/skeletons/build_class_from_table.php +++ b/dev/skeletons/build_class_from_table.php @@ -303,7 +303,7 @@ foreach($property as $key => $prop) $varprop.="\$this->db->escape(\$this->".$prop['field'].")"; $varprop.=".\"'\")"; } - elseif ($prop['field']=='fk_user_mod' || $prop['field']=='fk_user_author') + elseif ($prop['field']=='fk_user_mod' || $prop['field']=='fk_user_m' || $prop['field']=='fk_user_author') { $varprop.="'.\$user->id"; } @@ -367,7 +367,7 @@ foreach($property as $key => $prop) $varprop.=')."\'" : \'null\')'; } - elseif ($prop['field']=='fk_user_mod') { + elseif ($prop['field']=='fk_user_mod' || $prop['field']=='fk_user_m') { $varprop.="'.\$user->id"; } else diff --git a/dev/skeletons/skeleton_class.class.php b/dev/skeletons/skeleton_class.class.php index 4f725fa2dbe..01b48c35f75 100644 --- a/dev/skeletons/skeleton_class.class.php +++ b/dev/skeletons/skeleton_class.class.php @@ -188,11 +188,13 @@ class Skeleton_Class extends CommonObject // Retrieve all extrafields for invoice // fetch optionals attributes and labels + /* require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $extrafields=new ExtraFields($this->db); $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true); $this->fetch_optionals($this->id,$extralabels); - + */ + // $this->fetch_lines(); $this->db->free($resql); @@ -251,23 +253,19 @@ class Skeleton_Class extends CommonObject $sql .= $this->db->order($sortfield,$sortorder); } if (!empty($limit)) { - $sql .= ' ' . $this->db->plimit($limit + 1, $offset); + $sql .= ' ' . $this->db->plimit($limit, $offset); } - $this->lines = array(); - $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); while ($obj = $this->db->fetch_object($resql)) { - $line = new Skeleton_ClassLine(); + $line = new self($this->db); $line->id = $obj->rowid; $line->prop1 = $obj->field1; $line->prop2 = $obj->field2; - - $this->lines[$line->id] = $line; //... } $this->db->free($resql); diff --git a/dev/tools/github_authors_peryear.sh b/dev/tools/github_authors_peryear.sh new file mode 100755 index 00000000000..99b28d4d417 --- /dev/null +++ b/dev/tools/github_authors_peryear.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +FROM=2016-01-01 +TO=2016-12-31 + +echo "git log --since $FROM --before $TO | grep ^Author | sort -u -f -i -b | wc -l" +git log --since $FROM --before $TO | grep ^Author | sort -u -f -i -b | wc -l + diff --git a/dev/tools/github_commits_perversion.sh b/dev/tools/github_commits_perversion.sh new file mode 100755 index 00000000000..40ddafee617 --- /dev/null +++ b/dev/tools/github_commits_perversion.sh @@ -0,0 +1,15 @@ +#/bin/bash +Releases=("3.8" "3.9" "4.0" "5.0", "develop") +Dates=("2010-01-01", "2011-01-01", "2012-01-01", "2013-01-01", "2014-01-01", "2015-01-01", "2016-07-01") +let "counter = 1" + +for i in "${Releases[@]}" +do + git shortlog -s -n --after=${Dates[counter-1]} --before=${Dates[counter]} + echo -n "Total $i: " + git log --pretty=oneline --after=${Dates[counter-1]} --before=${Dates[counter]} | wc -l + echo "=======================" + echo + let "counter +=1" +done + diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index d4b5407c912..ba2643a04b8 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -888,18 +888,18 @@ if ($id) { if ($value == 'country') { - print ''; + print ''; print $form->select_country($search_country_id, 'search_country_id', '', 28, 'maxwidth200 maxwidthonsmartphone'); print ''; } else { - print ''; + print ''; } } } if ($id == 4) print ''; - print ''; + print ''; print ''; $searchpitco=$form->showFilterAndCheckAddButtons(0); print $searchpitco; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 6308c2d3edc..ca6a3657774 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -235,9 +235,8 @@ print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60" print "\n"; print ''; -print '
'; -print '' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . ''; -print ''; +print '' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . ''; +print ''; print ''; print $langs->trans('From') . ': '; print $form->select_date($search_date_start, 'date_start', 0, 0, 1); @@ -247,10 +246,10 @@ print $form->select_date($search_date_end, 'date_end', 0, 0, 1); print ''; print ''; print ''; -print ' '; -print ' '; -print ''; -print ''; +print ' '; +print ' '; +print ''; +print ''; $searchpitco=$form->showFilterAndCheckAddButtons(0); print $searchpitco; print ''; diff --git a/htdocs/accountancy/class/html.formventilation.class.php b/htdocs/accountancy/class/html.formventilation.class.php index 376e5b00d56..e1a21d852ea 100644 --- a/htdocs/accountancy/class/html.formventilation.class.php +++ b/htdocs/accountancy/class/html.formventilation.class.php @@ -83,6 +83,8 @@ class FormVentilation extends Form require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; + $out = ''; + $options = array(); if ($usecache && ! empty($this->options_cache[$usecache])) { @@ -109,7 +111,7 @@ class FormVentilation extends Form return -1; } - $out = ajax_combobox($htmlname, $event); + $out .= ajax_combobox($htmlname, $event); $selected = 0; while ($obj = $this->db->fetch_object($resql)) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index ef5c512179a..dddc7c896c0 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -29,6 +29,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; // Langs $langs->load("compta"); @@ -179,7 +180,14 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 1) print 'global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; +} else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; +} +$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG); $result = $db->query($sql); @@ -222,6 +230,11 @@ $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "' $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; +if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; +} else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; +} $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label"; dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG); @@ -273,6 +286,11 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy +if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; +} else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; +} $sql .= " AND aa.account_number IS NOT NULL"; $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label"; @@ -301,97 +319,105 @@ print "\n"; - - -print '
'; -print '
'; - - -print_fiche_titre($langs->trans("OtherInfo"), '', ''); - - -print "
\n"; -print ''; -print ''; -for($i = 1; $i <= 12; $i ++) { - print ''; +if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ? +{ + print '
'; + print '
'; + + print_fiche_titre($langs->trans("OtherInfo"), '', ''); + + print "
\n"; + print '
' . $langs->trans("TotalVente") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '
'; + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + + $sql = "SELECT '" . $langs->trans("TotalVente") . "' AS total,"; + for($i = 1; $i <= 12; $i ++) { + $sql .= " SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; + } + $sql .= " SUM(fd.total_ht) as total"; + $sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; + $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; + $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; + $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy + if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; + } else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; + } + + dol_syslog('htdocs/accountancy/customer/index.php'); + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num = $db->num_rows($resql); + + while ($row = $db->fetch_row($resql)) { + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + print ''; + $i ++; + } + $db->free($resql); + } else { + print $db->lasterror(); // Show last sql error + } + print "
' . $langs->trans("TotalVente") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . $row[0] . '' . price($row[$i]) . '' . price($row[13]) . '
\n"; + + if (! empty($conf->margin->enabled)) { + print "
\n"; + print ''; + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + + $sql = "SELECT '" . $langs->trans("Vide") . "' AS marge,"; + for($i = 1; $i <= 12; $i ++) { + $sql .= " SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, '(fd.total_ht-(fd.qty * fd.buy_price_ht))', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; + } + $sql .= " SUM((fd.total_ht-(fd.qty * fd.buy_price_ht))) as total"; + $sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; + $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; + $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; + $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy + if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; + } else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; + } + + dol_syslog('htdocs/accountancy/customer/index.php:: $sql=' . $sql); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + + while ($row = $db->fetch_row($resql)) { + + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + print ''; + } + $db->free($resql); + } else { + print $db->lasterror(); // Show last sql error + } + print "
' . $langs->trans("TotalMarge") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . $row[0] . '' . price(price2num($row[$i])) . '' . price(price2num($row[13])) . '
\n"; + } } -print '' . $langs->trans("Total") . ''; -$sql = "SELECT '" . $langs->trans("TotalVente") . "' AS total,"; -for($i = 1; $i <= 12; $i ++) { - $sql .= " SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; -} -$sql .= " SUM(fd.total_ht) as total"; -$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; -$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; -$sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; -$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy - -dol_syslog('htdocs/accountancy/customer/index.php'); -$resql = $db->query($sql); -if ($resql) { - $i = 0; - $num = $db->num_rows($resql); - - while ($row = $db->fetch_row($resql)) { - print '' . $row[0] . ''; - for($i = 1; $i <= 12; $i ++) { - print '' . price($row[$i]) . ''; - } - print '' . price($row[13]) . ''; - print ''; - $i ++; - } - $db->free($resql); -} else { - print $db->lasterror(); // Show last sql error -} -print "\n"; - -if (! empty($conf->margin->enabled)) { - print "
\n"; - print ''; - print ''; - for($i = 1; $i <= 12; $i ++) { - print ''; - } - print ''; - - $sql = "SELECT '" . $langs->trans("Vide") . "' AS marge,"; - for($i = 1; $i <= 12; $i ++) { - $sql .= " SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, '(fd.total_ht-(fd.qty * fd.buy_price_ht))', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; - } - $sql .= " SUM((fd.total_ht-(fd.qty * fd.buy_price_ht))) as total"; - $sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; - $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; - $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; - $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy - - dol_syslog('htdocs/accountancy/customer/index.php:: $sql=' . $sql); - $resql = $db->query($sql); - if ($resql) { - $num = $db->num_rows($resql); - - while ($row = $db->fetch_row($resql)) { - - print ''; - for($i = 1; $i <= 12; $i ++) { - print ''; - } - print ''; - print ''; - } - $db->free($resql); - } else { - print $db->lasterror(); // Show last sql error - } - print "
' . $langs->trans("TotalMarge") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . $row[0] . '' . price(price2num($row[$i])) . '' . price(price2num($row[13])) . '
\n"; -} -print "\n"; -print ''; llxFooter(); $db->close(); diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 7f214ffdf3c..dbb34299104 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -210,6 +210,11 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("l.tva_tx",$search_vat,1); } +if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; +} else { + $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; +} $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy $sql .= $db->order($sortfield, $sortorder); diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index b4c5da80af4..b4d7c0bbb7a 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -290,55 +290,55 @@ print "\n"; -print '
'; -print '
'; - - -print_fiche_titre($langs->trans("OtherInfo"), '', ''); - - - -print "
\n"; -print ''; -print ''; -for($i = 1; $i <= 12; $i ++) { - print ''; +if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ? +{ + print '
'; + print '
'; + + print_fiche_titre($langs->trans("OtherInfo"), '', ''); + + print "
\n"; + print '
' . $langs->trans("Total") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '
'; + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + + $sql = "SELECT '" . $langs->trans("TotalExpenseReport") . "' AS label,"; + for($i = 1; $i <= 12; $i ++) { + $sql .= " SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; + } + $sql .= " ROUND(SUM(erd.total_ht),2) as total"; + $sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expensereport as er ON er.rowid = erd.fk_expensereport"; + $sql .= " WHERE er.date_debut >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; + $sql .= " AND er.date_debut <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; + $sql .= " AND er.fk_statut > 0 "; + $sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")"; // We don't share object for accountancy + + dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + + while ( $row = $db->fetch_row($resql)) { + + + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + print ''; + } + + $db->free($resql); + } else { + print $db->lasterror(); // Show last sql error + } + print "
' . $langs->trans("Total") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . $row[0] . '' . price($row[$i]) . '' . price($row[13]) . '
\n"; } -print '' . $langs->trans("Total") . ''; - -$sql = "SELECT '" . $langs->trans("TotalExpenseReport") . "' AS label,"; -for($i = 1; $i <= 12; $i ++) { - $sql .= " SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; -} -$sql .= " ROUND(SUM(erd.total_ht),2) as total"; -$sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expensereport as er ON er.rowid = erd.fk_expensereport"; -$sql .= " WHERE er.date_debut >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; -$sql .= " AND er.date_debut <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; -$sql .= " AND er.fk_statut > 0 "; -$sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")"; // We don't share object for accountancy - -dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql); -$resql = $db->query($sql); -if ($resql) { - $num = $db->num_rows($resql); - - while ( $row = $db->fetch_row($resql)) { - - - print '' . $row[0] . ''; - for($i = 1; $i <= 12; $i ++) { - print '' . price($row[$i]) . ''; - } - print '' . price($row[13]) . ''; - print ''; - } - - $db->free($resql); -} else { - print $db->lasterror(); // Show last sql error -} -print "\n"; llxFooter(); $db->close(); diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index ef7d470bb07..a747342a508 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -289,58 +289,56 @@ print "\n"; - -print '
'; -print '
'; - - -print_fiche_titre($langs->trans("OtherInfo"), '', ''); - - - - - -print "
\n"; -print ''; -print ''; -for($i = 1; $i <= 12; $i ++) { - print ''; +if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. Why showing a report that should rely on result of this step ? +{ + print '
'; + print '
'; + + print_fiche_titre($langs->trans("OtherInfo"), '', ''); + + print "
\n"; + print '
' . $langs->trans("Total") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '
'; + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + + $sql = "SELECT '" . $langs->trans("CAHTF") . "' AS label,"; + for($i = 1; $i <= 12; $i ++) { + $sql .= " SUM(" . $db->ifsql('MONTH(ff.datef)=' . $i, 'ffd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; + } + $sql .= " ROUND(SUM(ffd.total_ht),2) as total"; + $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as ffd"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn"; + $sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; + $sql .= " AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; + $sql .= " AND ff.fk_statut > 0 "; + $sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")"; // We don't share object for accountancy + + dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + + while ( $row = $db->fetch_row($resql)) { + + + print ''; + for($i = 1; $i <= 12; $i ++) { + print ''; + } + print ''; + print ''; + } + + $db->free($resql); + } else { + print $db->lasterror(); // Show last sql error + } + print "
' . $langs->trans("Total") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . $row[0] . '' . price($row[$i]) . '' . price($row[13]) . '
\n"; } -print '' . $langs->trans("Total") . ''; -$sql = "SELECT '" . $langs->trans("CAHTF") . "' AS label,"; -for($i = 1; $i <= 12; $i ++) { - $sql .= " SUM(" . $db->ifsql('MONTH(ff.datef)=' . $i, 'ffd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; -} -$sql .= " ROUND(SUM(ffd.total_ht),2) as total"; -$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as ffd"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn"; -$sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; -$sql .= " AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; -$sql .= " AND ff.fk_statut > 0 "; -$sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")"; // We don't share object for accountancy - -dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql); -$resql = $db->query($sql); -if ($resql) { - $num = $db->num_rows($resql); - - while ( $row = $db->fetch_row($resql)) { - - - print '' . $row[0] . ''; - for($i = 1; $i <= 12; $i ++) { - print '' . price($row[$i]) . ''; - } - print '' . price($row[13]) . ''; - print ''; - } - - $db->free($resql); -} else { - print $db->lasterror(); // Show last sql error -} -print "\n"; llxFooter(); $db->close(); diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index cab52dceccc..85b591f0fca 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -91,10 +91,10 @@ if ($action == 'add' && $user->rights->adherent->configurer) $object = new AdherentType($db); $object->libelle = trim($label); - $object->subscription = trim($subscription); + $object->subscription = (int) trim($subscription); $object->note = trim($comment); - $object->mail_valid = trim($mail_valid); - $object->vote = trim($vote); + $object->mail_valid = (boolean) trim($mail_valid); + $object->vote = (boolean) trim($vote); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost($extralabels,$object); @@ -129,10 +129,10 @@ if ($action == 'update' && $user->rights->adherent->configurer) $object = new AdherentType($db); $object->id = $rowid; $object->libelle = trim($label); - $object->subscription = trim($subscription); + $object->subscription = (int) trim($subscription); $object->note = trim($comment); - $object->mail_valid = trim($mail_valid); - $object->vote = trim($vote); + $object->mail_valid = (boolean) trim($mail_valid); + $object->vote = (boolean) trim($vote); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost($extralabels,$object); diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index b41ae78d4c7..2433575e553 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -104,6 +104,11 @@ if ($action == 'setvalue' && $user->admin) * View */ +// Define $urlwithroot +$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + $form = new Form($db); llxHeader('',$langs->trans("PrintingSetup")); @@ -127,70 +132,179 @@ if ($mode == 'setup' && $user->admin) if (in_array($key[0], array_keys($supportedoauth2array))) $supported=1; if (! $supported) continue; // show only supported + + $OAUTH_SERVICENAME='Unknown'; + if ($key[0] == 'OAUTH_GITHUB_NAME') + { + $OAUTH_SERVICENAME='GitHub'; + $urltorenew=$urlwithroot.'/core/modules/oauth/github_oauthcallback.php?state=user,public_repo&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete=$urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltocheckperms='https://github.com/settings/applications/'; + } + if ($key[0] == 'OAUTH_GOOGLE_NAME') + { + $OAUTH_SERVICENAME='Google'; + $urltorenew=$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?state=userinfo_email,userinfo_profile,cloud_print&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete=$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltocheckperms='https://security.google.com/settings/security/permissions'; + } + + // Show value of token + $tokenobj=null; + // Token + require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; + require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; + // Dolibarr storage + $storage = new DoliStorage($db, $conf); + try + { + $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); + } + catch(Exception $e) + { + // Return an error if token not found + } + + // Set other properties + $refreshtoken=false; + $expiredat=''; + + $expire = false; + // Is token expired or will token expire in the next 30 seconds + if (is_object($tokenobj)) { + $expire = ($tokenobj->getEndOfLife() !== $tokenobj::EOL_NEVER_EXPIRES && $tokenobj->getEndOfLife() !== $tokenobj::EOL_UNKNOWN && time() > ($tokenobj->getEndOfLife() - 30)); + } + + if ($key[1] != '' && $key[2] != '') { + if (is_object($tokenobj)) { + $refreshtoken = $tokenobj->getRefreshToken(); + + $endoflife = $tokenobj->getEndOfLife(); + if ($endoflife == $tokenobj::EOL_NEVER_EXPIRES) + { + $expiredat = $langs->trans("Never"); + } + elseif ($endoflife == $tokenobj::EOL_UNKNOWN) + { + $expiredat = $langs->trans("Unknown"); + } + else + { + $expiredat=dol_print_date($endoflife, "dayhour"); + } + } + } + + $submit_enabled=0; + print ''; print ''; print ''; print ''."\n"; - $var=true; + + $var=false; print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; print "\n"; - $submit_enabled=0; - + print ''; - print ''.$langs->trans($key['varname']).''; - print ''; + print ''; + //var_dump($key); + print $langs->trans("OAuthIDSecret").''; + print ''; print ''; print ''."\n"; - // Show value of token - if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS') + $var = ! $var; + print ''; + print ''; + //var_dump($key); + print $langs->trans("IsTokenGenerated"); + print ''; + print ''; + print ''; - print ''; - print ''; - print ''; - print ''."\n"; + //test on $storage->hasAccessToken($OAUTH_SERVICENAME) ? + print ''.$langs->trans('DeleteAccess').'

'; } + // Request remote token + print ''.$langs->trans('RequestAccess').'

'; + // Check remote access + if ($urltocheckperms) + { + print $langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': '.$urltocheckperms.''; + } + print ''; + print ''; + + $var = ! $var; + print ''; + print ''; + //var_dump($key); + print $langs->trans("Token").''; + print ''; + print ''."\n"; + + if (is_object($tokenobj)) + { + // Token refresh + $var = ! $var; + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_REFRESH").''; + print ''; + print ''; + // Token expired + $var = ! $var; + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_EXPIRED").''; + print ''; + print ''; + + // Token expired at + $var = ! $var; + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_EXPIRE_AT").''; + print ''; + print ''; + } + print '
'.$langs->trans("Parameters").''.$langs->trans("Value").' '.$langs->trans($key[0]).'
'.$langs->trans($key['info']).''; + print $langs->trans("SeePreviousTab"); + print ''; - if ($key['varname'] == 'PRINTGCP_TOKEN_ACCESS') - { - // Delete remote tokens - if (! empty($key['delete'])) print ''.$langs->trans('DeleteAccess').'

'; - // Request remote token - print ''.$langs->trans('RequestAccess').'

'; - // Check remote access - print $langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME_GOOGLE).': https://security.google.com/settings/security/permissions'; - } print '
'; + if (is_object($tokenobj)) print $langs->trans("HasAccessToken"); + else print $langs->trans("NoAccessToken"); + print ''; + // Links to delete/checks token + if (is_object($tokenobj)) { - // Token - print '
'.$langs->trans("Token").''; - // Dolibarr storage - $storage = new DoliStorage($db, $conf); - try - { - $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME_GOOGLE); - } - catch(Exception $e) - { - // Return an error if token not found - } - if (is_object($tokenobj)) - { - //var_dump($tokenobj); - print $tokenobj->getAccessToken().'
'; - //print 'Refresh: '.$tokenobj->getRefreshToken().'
'; - //print 'EndOfLife: '.$tokenobj->getEndOfLife().'
'; - //var_dump($tokenobj->getExtraParams()); - /*print '
Extra:
';*/ - } - print '
'; - print '
'; + if (is_object($tokenobj)) + { + //var_dump($tokenobj); + print $tokenobj->getAccessToken().'
'; + //print 'Refresh: '.$tokenobj->getRefreshToken().'
'; + //print 'EndOfLife: '.$tokenobj->getEndOfLife().'
'; + //var_dump($tokenobj->getExtraParams()); + /*print '
Extra:
';*/ + } + print '
'; + print yn($refreshtoken); + print '
'; + print yn($expire); + print '
'; + print $expiredat; + print '
'; if (! empty($driver)) @@ -199,7 +313,8 @@ if ($mode == 'setup' && $user->admin) print '
'; } } - + + print '
'; } diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index 1340b5ae3c1..c0ff5d75819 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -82,8 +82,8 @@ $xmlremote = GETPOST('xmlremote')?GETPOST('xmlremote'):'https://www.dolibarr.org // Test if remote test is ok $enableremotecheck = True; -if (preg_match('/beta|alpha/i', DOL_VERSION)) $enableremotecheck=False; - +if (preg_match('/beta|alpha|rc/i', DOL_VERSION) || ! empty($conf->global->MAIN_ALLOW_INTEGRITY_CHECK_ON_UNSTABLE)) $enableremotecheck=False; +$enableremotecheck = true; print '
'; print $langs->trans("MakeIntegrityAnalysisFrom").':
'; @@ -101,7 +101,8 @@ else print ''."\n"; if ($enableremotecheck) { - print ' '.$langs->trans("RemoteSignature").' = '.$xmlremote.'
'; + print ' '.$langs->trans("RemoteSignature").' = '; + print '
'; } else { @@ -156,19 +157,25 @@ if ($xml) $file_list = array(); $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat); // Fill array $file_list + print_fiche_titre($langs->trans("FilesMissing")); + print ''; print ''; - print ''; + print ''; + print ''; print ''; print ''."\n"; $var = true; $tmpfilelist = dol_sort_array($file_list['missing'], 'filename'); if (is_array($tmpfilelist) && count($tmpfilelist)) { + $i = 0; foreach ($tmpfilelist as $file) { + $i++; $var = !$var; print ''; + print '' . "\n"; print '' . "\n"; print '' . "\n"; print "\n"; @@ -176,15 +183,18 @@ if ($xml) } else { - print ''; + print ''; } print '
' . $langs->trans("FilesMissing") . '#' . $langs->trans("Filename") . '' . $langs->trans("ExpectedChecksum") . '
'.$i.''.$file['filename'].''.$file['expectedmd5'].'
'.$langs->trans("None").'
'.$langs->trans("None").'
'; print '
'; + print_fiche_titre($langs->trans("FilesUpdated")); + print ''; print ''; - print ''; + print ''; + print ''; print ''; print ''; print ''; @@ -194,10 +204,13 @@ if ($xml) $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename'); if (is_array($tmpfilelist2) && count($tmpfilelist2)) { + $i = 0; foreach ($tmpfilelist2 as $file) { + $i++; $var = !$var; print ''; + print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; @@ -241,14 +254,12 @@ if ($xml) //var_dump($checksumconcat); $checksumget = md5(join(',',$checksumconcat)); $checksumtoget = $xml->dolibarr_htdocs_dir_checksum; - if ($checksumtoget) - { - print '
'; - print ''.$langs->trans("GlobalChecksum").'
'; - print $langs->trans("ExpectedChecksum").' = '.$checksumtoget.'
'; - print $langs->trans("CurrentChecksum").' = '.$checksumget; - } - + + print '
'; + + print_fiche_titre($langs->trans("GlobalChecksum")).'
'; + print $langs->trans("ExpectedChecksum").' = '. ($checksumtoget ? $checksumtoget : $langs->trans("Unknown")) .'
'; + print $langs->trans("CurrentChecksum").' = '.$checksumget; } diff --git a/htdocs/admin/tools/update.php b/htdocs/admin/tools/update.php index e306862b67a..5cebb1dac4e 100644 --- a/htdocs/admin/tools/update.php +++ b/htdocs/admin/tools/update.php @@ -39,7 +39,7 @@ if (GETPOST('msg','alpha')) { } -$urldolibarr='http://www.dolibarr.org/downloads/'; +$urldolibarr='https://www.dolibarr.org/downloads/'; $urldolibarrmodules='https://www.dolistore.com/'; $urldolibarrthemes='https://www.dolistore.com/'; $dolibarrroot=preg_replace('/([\\/]+)$/i','',DOL_DOCUMENT_ROOT); diff --git a/htdocs/cashdesk/class/Facturation.class.php b/htdocs/cashdesk/class/Facturation.class.php index 240b32e34db..579d244246b 100644 --- a/htdocs/cashdesk/class/Facturation.class.php +++ b/htdocs/cashdesk/class/Facturation.class.php @@ -37,7 +37,7 @@ class Facturation * int $prix => Prix HT du produit en cours * int $tva => 'rowid' du taux de tva dans llx_c_tva */ - var $id; + public $id; protected $ref; protected $qte; protected $stock; diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 2dd5d78d9b9..4f4ef6a580c 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -656,7 +656,7 @@ foreach ($typeofevents as $typeofevent) if ($todayarray['mday']==$tmpday && $todayarray['mon']==$tmpmonth && $todayarray['year']==$tmpyear) $today=1; if ($today) $style='cal_today_peruser'; - show_day_events2($username, $tmpday, $tmpmonth, $tmpyear, $monthshown, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, $showheader, $colorsbytype, $var); + show_day_events_pertype($username, $tmpday, $tmpmonth, $tmpyear, $monthshown, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, $showheader, $colorsbytype, $var); $i++; } @@ -756,7 +756,7 @@ $db->close(); * @param bool $var true or false for alternat style on tr/td * @return void */ -function show_day_events2($username, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint=0, $maxnbofchar=16, $newparam='', $showinfo=0, $minheight=60, $showheader=false, $colorsbytype=array(), $var=false) +function show_day_events_pertype($username, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint=0, $maxnbofchar=16, $newparam='', $showinfo=0, $minheight=60, $showheader=false, $colorsbytype=array(), $var=false) { global $db; global $user, $conf, $langs, $hookmanager, $action; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index baf18c329c1..26d4d4822e2 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -223,7 +223,7 @@ if (empty($reshook)) } } - // Categorisation dans projet + // Link to a project else if ($action == 'classin' && $user->rights->commande->creer) { $object->setProject(GETPOST('projectid')); diff --git a/htdocs/compta/paiement/class/cpaiement.class.php b/htdocs/compta/paiement/class/cpaiement.class.php index 5428f4abdbf..d6031ae1685 100644 --- a/htdocs/compta/paiement/class/cpaiement.class.php +++ b/htdocs/compta/paiement/class/cpaiement.class.php @@ -39,10 +39,6 @@ class Cpaiement */ public $table_element = 'c_paiement'; - /** - * @var CpaiementLine[] Lines - */ - public $lines = array(); /** */ @@ -227,84 +223,6 @@ class Cpaiement } } - /** - * Load object in memory from the database - * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit offset limit - * @param int $offset offset limit - * @param array $filter filter array - * @param string $filtermode filter mode (AND or OR) - * - * @return int <0 if KO, >0 if OK - */ - public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') - { - dol_syslog(__METHOD__, LOG_DEBUG); - - $sql = 'SELECT'; - $sql .= ' t.id,'; - $sql .= " t.code,"; - $sql .= " t.libelle,"; - $sql .= " t.type,"; - $sql .= " t.active,"; - $sql .= " t.accountancy_code,"; - $sql .= " t.module"; - - - $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; - - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - $sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; - } - } - if (count($sqlwhere) > 0) { - $sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere); - } - - if (!empty($sortfield)) { - $sql .= $this->db->order($sortfield,$sortorder); - } - if (!empty($limit)) { - $sql .= ' ' . $this->db->plimit($limit + 1, $offset); - } - $this->lines = array(); - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - - while ($obj = $this->db->fetch_object($resql)) { - $line = new CpaiementLine(); - - $line->id = $obj->id; - - $line->code = $obj->code; - $line->libelle = $obj->libelle; - $line->type = $obj->type; - $line->active = $obj->active; - $line->accountancy_code = $obj->accountancy_code; - $line->module = $obj->module; - - - - $this->lines[$line->id] = $line; - } - $this->db->free($resql); - - return $num; - } else { - $this->errors[] = 'Error ' . $this->db->lasterror(); - dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); - - return - 1; - } - } - /** * Update object into database * diff --git a/htdocs/compta/sociales/class/cchargesociales.class.php b/htdocs/compta/sociales/class/cchargesociales.class.php index 538754e63b2..a44b820c8ea 100644 --- a/htdocs/compta/sociales/class/cchargesociales.class.php +++ b/htdocs/compta/sociales/class/cchargesociales.class.php @@ -43,11 +43,6 @@ class Cchargesociales */ public $table_element = 'c_chargesociales'; - /** - * @var CchargesocialesLine[] Lines - */ - public $lines = array(); - /** */ @@ -237,83 +232,6 @@ class Cchargesociales } } - /** - * Load object in memory from the database - * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit offset limit - * @param int $offset offset limit - * @param array $filter filter array - * @param string $filtermode filter mode (AND or OR) - * - * @return int <0 if KO, >0 if OK - */ - public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') - { - dol_syslog(__METHOD__, LOG_DEBUG); - - $sql = 'SELECT'; - $sql .= " t.id,"; - $sql .= " t.libelle,"; - $sql .= " t.deductible,"; - $sql .= " t.active,"; - $sql .= " t.code,"; - $sql .= " t.fk_pays,"; - $sql .= " t.module,"; - $sql .= " t.accountancy_code"; - - - $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; - - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - $sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; - } - } - if (count($sqlwhere) > 0) { - $sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere); - } - - if (!empty($sortfield)) { - $sql .= $this->db->order($sortfield,$sortorder); - } - if (!empty($limit)) { - $sql .= ' ' . $this->db->plimit($limit + 1, $offset); - } - $this->lines = array(); - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - - while ($obj = $this->db->fetch_object($resql)) { - $line = new CchargesocialesLine(); - - $line->id = $obj->id; - $line->libelle = $obj->libelle; - $line->deductible = $obj->deductible; - $line->active = $obj->active; - $line->code = $obj->code; - $line->fk_pays = $obj->fk_pays; - $line->module = $obj->module; - $line->accountancy_code = $obj->accountancy_code; - - $this->lines[$line->id] = $line; - } - $this->db->free($resql); - - return $num; - } else { - $this->errors[] = 'Error ' . $this->db->lasterror(); - dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); - - return - 1; - } - } - /** * Update object into database * diff --git a/htdocs/core/actions_linkedfiles.inc.php b/htdocs/core/actions_linkedfiles.inc.php index 672da011a79..018baab0cc0 100644 --- a/htdocs/core/actions_linkedfiles.inc.php +++ b/htdocs/core/actions_linkedfiles.inc.php @@ -18,10 +18,12 @@ * or see http://www.gnu.org/ */ - // Variable $upload_dir must be defined when entering here // Variable $upload_dirold may also exists. +//var_dump($upload_dir); +//var_dump($upload_dirold); + // Submit file/link if (GETPOST('sendit') && ! empty($conf->global->MAIN_UPLOAD_DOC)) { @@ -165,7 +167,11 @@ elseif ($action == 'renamefile' && GETPOST('renamefilesave')) setEventMessages($langs->trans("FileRenamed"), null); } - else setEventMessages($langs->trans("ErrorFailToRenameFile", $filenamefrom, $filenameto), null, 'errors'); + else + { + $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now. + setEventMessages($langs->trans("ErrorFailToRenameFile", $filenamefrom, $filenameto), null, 'errors'); + } } } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 5e83f59ea36..89795e7df5d 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1929,7 +1929,10 @@ abstract class CommonObject */ function updateRangOfLine($rowid,$rang) { - $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET rang = '.$rang; + $fieldposition = 'rang'; + if ($this->table_element_line == 'ecm_files') $fieldposition = 'position'; + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.$rang; $sql.= ' WHERE rowid = '.$rowid; dol_syslog(get_class($this)."::updateRangOfLine", LOG_DEBUG); @@ -3296,84 +3299,90 @@ abstract class CommonObject $usemargins=0; if (! empty($conf->margin->enabled) && ! empty($this->element) && in_array($this->element,array('facture','propal','commande'))) $usemargins=1; - print ''; - - if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) print ''; - - // Description - print ''; - - if ($this->element == 'supplier_proposal') - { - print ''; - } - - // VAT - print ''; - - // Price HT - print ''; - - // Multicurrency - if (!empty($conf->multicurrency->enabled)) print ''; - - if ($inputalsopricewithtax) print ''; - - // Qty - print ''; - - if($conf->global->PRODUCT_USE_UNITS) - { - print ''; - } - - // Reduction short - print ''; - - if ($this->situation_cycle_ref) { - print ''; - } - - if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) - { - if (!empty($user->rights->margins->creer)) - { - if ($conf->global->MARGIN_TYPE == "1") - print ''; - else - print ''; - } - - if (! empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) - print ''; - if (! empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) - print ''; - } - - // Total HT - print ''; - - // Multicurrency - if (!empty($conf->multicurrency->enabled)) print ''; - - if ($outputalsopricetotalwithtax) print ''; - - print ''; // No width to allow autodim - - print ''; - - print ''; - - print "\n"; - $num = count($this->lines); - $var = true; - $i = 0; - + //Line extrafield require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $extrafieldsline = new ExtraFields($this->db); $extralabelslines=$extrafieldsline->fetch_name_optionals_label($this->table_element_line); + + $parameters = array('num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline); + $reshook = $hookmanager->executeHooks('printObjectLineTitle', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if (empty($reshook)) + { + print ''; + + if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) print ''; + + // Description + print ''; + + if ($this->element == 'supplier_proposal') + { + print ''; + } + + // VAT + print ''; + + // Price HT + print ''; + + // Multicurrency + if (!empty($conf->multicurrency->enabled)) print ''; + + if ($inputalsopricewithtax) print ''; + + // Qty + print ''; + + if($conf->global->PRODUCT_USE_UNITS) + { + print ''; + } + + // Reduction short + print ''; + + if ($this->situation_cycle_ref) { + print ''; + } + + if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) + { + if (!empty($user->rights->margins->creer)) + { + if ($conf->global->MARGIN_TYPE == "1") + print ''; + else + print ''; + } + + if (! empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) + print ''; + if (! empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) + print ''; + } + + // Total HT + print ''; + + // Multicurrency + if (!empty($conf->multicurrency->enabled)) print ''; + + if ($outputalsopricetotalwithtax) print ''; + + print ''; // No width to allow autodim + + print ''; + + print ''; + + print "\n"; + } + + $var = true; + $i = 0; foreach ($this->lines as $line) { @@ -3392,7 +3401,7 @@ abstract class CommonObject } else { - $parameters = array('line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline); + $parameters = array('line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline, 'fk_parent_line'=>$line->fk_parent_line); $reshook = $hookmanager->executeHooks('printObjectSubLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks } } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index be5272cf7c2..7ef28b3ee76 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -331,16 +331,40 @@ class ExtraFields $table=$elementtype.'_extrafields'; + $error=0; + if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname)) { - $result=$this->db->DDLDropField(MAIN_DB_PREFIX.$table,$attrname); // This also drop the unique key + $result=$this->delete_label($attrname,$elementtype); if ($result < 0) { - $this->error=$this->db->lasterror(); + $this->error=$this->db->lasterror(); + $error++; } - $result=$this->delete_label($attrname,$elementtype); - + if (! $error) + { + $sql = "SELECT COUNT(rowid) as nb"; + $sql.= " FROM ".MAIN_DB_PREFIX."extrafields"; + $sql.= " WHERE elementtype = '".$elementtype."'"; + $sql.= " AND name = '".$attrname."'"; + //$sql.= " AND entity IN (0,".$conf->entity.")"; Do not test on entity here. We want to see if there is still on field remaning in other entities before deleting field in table + $resql = $this->db->query($sql); + if ($resql) + { + $obj = $this->db->fetch_object($resql); + if ($obj->nb <= 0) + { + $result=$this->db->DDLDropField(MAIN_DB_PREFIX.$table,$attrname); // This also drop the unique key + if ($result < 0) + { + $this->error=$this->db->lasterror(); + $error++; + } + } + } + } + return $result; } else diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 95b7b41da4d..cd56b4d0b59 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -856,38 +856,62 @@ class FormFile /** - * Show list of documents in a directory + * Show list of documents in $filearray (may be they are all in same directory but may not) * - * @param array $filearray Array of files loaded by dol_dir_list('files') function before calling this - * @param Object $object Object on which document is linked to - * @param string $modulepart Value for modulepart used by download or viewimage wrapper + * @param array $filearray Array of files loaded by dol_dir_list('files') function before calling this. + * @param Object $object Object on which document is linked to. + * @param string $modulepart Value for modulepart used by download or viewimage wrapper. * @param string $param Parameters on sort links (param must start with &, example &aaa=bbb&ccc=ddd) - * @param int $forcedownload Force to open dialog box "Save As" when clicking on file - * @param string $relativepath Relative path of docs (autodefined if not provided) + * @param int $forcedownload Force to open dialog box "Save As" when clicking on file. + * @param string $relativepath Relative path of docs (autodefined if not provided), relative to module dir, not to MAIN_DATA_ROOT. * @param int $permonobject Permission on object (so permission to delete or crop document) * @param int $useinecm Change output for use in ecm module * @param string $textifempty Text to show if filearray is empty ('NoFileFound' if not defined) - * @param int $maxlength Maximum length of file name shown + * @param int $maxlength Maximum length of file name shown. * @param string $title Title before list * @param string $url Full url to use for click links ('' = autodetect) * @param int $showrelpart 0=Show only filename (default), 1=Show first level 1 dir - * @param int $permtoeditline Permission to edit document line (-1 is deprecated) + * @param int $permtoeditline Permission to edit document line (You must provide a value, -1 is deprecated and must not be used any more) + * @param string $upload_dir Full path directory so we can know dir relative to MAIN_DATA_ROOT. Fill this if you want to complete file data with database indexes. + * @param string $sortfield Sort field ('name', 'size', 'position', ...) + * @param string $sortorder Sort order ('ASC' or 'DESC') + * @param int $disablemove 1=Disable move button, 0=Position move is possible. * @return int <0 if KO, nb of files shown if OK */ - function list_of_documents($filearray,$object,$modulepart,$param='',$forcedownload=0,$relativepath='',$permonobject=1,$useinecm=0,$textifempty='',$maxlength=0,$title='',$url='', $showrelpart=0, $permtoeditline=-1) + function list_of_documents($filearray,$object,$modulepart,$param='',$forcedownload=0,$relativepath='',$permonobject=1,$useinecm=0,$textifempty='',$maxlength=0,$title='',$url='', $showrelpart=0, $permtoeditline=-1,$upload_dir='',$sortfield='',$sortorder='ASC', $disablemove=1) { global $user, $conf, $langs, $hookmanager; - global $bc; + global $bc,$bcdd; global $sortfield, $sortorder, $maxheightmini; - $hookmanager->initHooks(array('formfile')); + // Define relative path used to store the file + if (empty($relativepath)) + { + $relativepath=(! empty($object->ref)?dol_sanitizeFileName($object->ref):'').'/'; + if ($object->element == 'invoice_supplier') $relativepath=get_exdir($object->id,2,0,0,$object,'invoice_supplier').$relativepath; // TODO Call using a defined value for $relativepath + if ($object->element == 'project_task') $relativepath='Call_not_supported_._Call_function_using_a_defined_relative_path_.'; + } + // For backward compatiblity, we detect file is stored into an old path + if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO) && $file['level1name'] == 'photos') + { + $relativepath=preg_replace('/^.*\/produit\//','',$file['path']).'/'; + } + // Defined relative dir to DOL_DATA_ROOT + $relativedir = ''; + if ($upload_dir) + { + $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir); + $relativedir = preg_replace('/^[\\/]/','',$relativedir); + } + $hookmanager->initHooks(array('formfile')); $parameters=array( 'filearray' => $filearray, 'modulepart'=> $modulepart, 'param' => $param, 'forcedownload' => $forcedownload, - 'relativepath' => $relativepath, + 'relativepath' => $relativepath, // relative filename to module dir + 'relativedir' => $relativedir, // relative dirname to DOL_DATA_ROOT 'permtodelete' => $permonobject, 'useinecm' => $useinecm, 'textifempty' => $textifempty, @@ -932,45 +956,119 @@ class FormFile print ''; print ''; } - print '
' . $langs->trans("FilesUpdated") . '#' . $langs->trans("Filename") . '' . $langs->trans("ExpectedChecksum") . '' . $langs->trans("CurrentChecksum") . '' . $langs->trans("Size") . '
'.$i.''.$file['filename'].''.$file['expectedmd5'].''.$file['md5'].'
 '.$langs->trans('Description').''.$langs->trans("SupplierProposalRefFourn").''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('PriceUHTCurrency', $this->multicurrency_code).''.$langs->trans('PriceUTTC').''.$langs->trans('Qty').''.$langs->trans('Unit').''.$langs->trans('ReductionShort').'' . $langs->trans('Progress') . ''.$langs->trans('BuyingPrice').''.$langs->trans('CostPrice').''.$langs->trans('MarginRate').''.$langs->trans('MarkRate').''.$langs->trans('TotalHTShort').''.$langs->trans('TotalHTShortCurrency', $this->multicurrency_code).''.$langs->trans('TotalTTCShort').'
 '.$langs->trans('Description').''.$langs->trans("SupplierProposalRefFourn").''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('PriceUHTCurrency', $this->multicurrency_code).''.$langs->trans('PriceUTTC').''.$langs->trans('Qty').''.$langs->trans('Unit').''.$langs->trans('ReductionShort').'' . $langs->trans('Progress') . ''.$langs->trans('BuyingPrice').''.$langs->trans('CostPrice').''.$langs->trans('MarginRate').''.$langs->trans('MarkRate').''.$langs->trans('TotalHTShort').''.$langs->trans('TotalHTShortCurrency', $this->multicurrency_code).''.$langs->trans('TotalTTCShort').'
'."\n"; + print '
'."\n"; - print ''; + print ''; print_liste_field_titre($langs->trans("Documents2"),$url,"name","",$param,'align="left"',$sortfield,$sortorder); print_liste_field_titre($langs->trans("Size"),$url,"size","",$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre($langs->trans("Date"),$url,"date","",$param,'align="center"',$sortfield,$sortorder); if (empty($useinecm)) print_liste_field_titre('',$url,"","",$param,'align="center"'); print_liste_field_titre(''); + if (! $disablemove) print_liste_field_titre(''); print "\n"; + // Get list of files stored into database for same relative directory + if ($relativedir) + { + $filearrayindatabase = dol_dir_list_in_database($relativedir, '', null, 'name', SORT_ASC); + + //var_dump($filearray); + //var_dump($filearrayindatabase); + + // Complete filearray with properties found into $filearrayindatabase + foreach($filearray as $key => $val) + { + $found=0; + // Search if it exists into $filearrayindatabase + foreach($filearrayindatabase as $key2 => $val2) + { + if ($filearrayindatabase[$key2]['name'] == $filearray[$key]['name']) + { + $filearray[$key]['position_name']=($filearrayindatabase[$key2]['position']?$filearrayindatabase[$key2]['position']:'0').'_'.$filearrayindatabase[$key2]['name']; + $filearray[$key]['position']=$filearrayindatabase[$key2]['position']; + $filearray[$key]['cover']=$filearrayindatabase[$key2]['cover']; + $filearray[$key]['acl']=$filearrayindatabase[$key2]['acl']; + $filearray[$key]['rowid']=$filearrayindatabase[$key2]['rowid']; + $filearray[$key]['label']=$filearrayindatabase[$key2]['label']; + $found=1; + break; + } + } + + if (! $found) // This happen in transition towerd version 6, or if files were added manually into os dir. + { + $filearray[$key]['position']='999999'; // File not indexed are at end. So if we add a file, it will not replace an existing position + $filearray[$key]['cover']=0; + $filearray[$key]['acl']=''; + + $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filearray[$key]['fullname']); + if (! preg_match('/(\/temp\/|\/thumbs|\.meta$)/', $rel_filetorenameafter)) // If not a tmp file + { + dol_syslog("list_of_documents We found a file called '".$filearray[$key]['name']."' not indexed into database. We add it"); + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($this->db); + + // Add entry into database + $filename = basename($rel_filename); + $rel_dir = dirname($rel_filename); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $ecmfile->label = md5_file(dol_osencode($filearray[$key]['fullname'])); // $destfile is a full path to file + $ecmfile->fullpath_orig = $filearray[$key]['fullname']; + $ecmfile->gen_or_uploaded = 'unknown'; + $ecmfile->description = ''; // indexed content + $ecmfile->keyword = ''; // keyword content + $result = $ecmfile->create($user); + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + else + { + $filearray[$key]['rowid']=$result; + } + } + else + { + $filearray[$key]['rowid']=0; // Should not happened + } + } + } + + /*var_dump($filearray); + var_dump($sortfield); + var_dump($sortorder);*/ + + if ($sortfield && $sortorder) + { + $filearray=dol_sort_array($filearray, $sortfield, $sortorder); + } + //var_dump($filearray); + } + $nboffiles=count($filearray); - if ($nboffiles > 0) include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; - - $var=true; + + $var=true; $i=0; $nboflines = 0; $lastrowid=0; foreach($filearray as $key => $file) // filearray must be only files here { if ($file['name'] != '.' && $file['name'] != '..' && ! preg_match('/\.meta$/i',$file['name'])) { - // Define relative path used to store the file - if (empty($relativepath)) - { - $relativepath=(! empty($object->ref)?dol_sanitizeFileName($object->ref):'').'/'; - if ($object->element == 'invoice_supplier') $relativepath=get_exdir($object->id,2,0,0,$object,'invoice_supplier').$relativepath; // TODO Call using a defined value for $relativepath - if ($object->element == 'project_task') $relativepath='Call_not_supported_._Call_function_using_a_defined_relative_path_.'; - } - // For backward compatiblity, we detect file is stored into an old path - if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO) && $file['level1name'] == 'photos') - { - $relativepath=preg_replace('/^.*\/produit\//','',$file['path']).'/'; - } $var=!$var; - $editline=0; + if ($filearray[$key]['rowid'] > 0) $lastrowid = $filearray[$key]['rowid']; - print ''."\n"; - print ''; + $editline=0; + $nboflines++; + print ''."\n"; + // Do we have entry into database ? + print ''."\n"; + print ''; print '"; + + if (empty($disablemove)) + { + if ($nboffiles > 1 && empty($conf->browser->phone)) { + print ''; + } + else { + print ''; + } + } } else { @@ -1081,18 +1197,32 @@ class FormFile print ''; print ''; print ''; + if (empty($disablemove)) print ''; } print "\n"; + + $i++; } } if ($nboffiles == 0) { - print ''; } print "
'; //print "XX".$file['name']; //$file['name'] must be utf8 @@ -1074,6 +1172,24 @@ class FormFile print ''.img_delete().''; } print "'; + if ($i > 0) { + print 'id.'">'.img_up('default',0,'imgupforline').''; + } + if ($i < $nboffiles-1) { + print 'id.'">'.img_down('default',0,'imgdownforline').''; + } + print 'browser->phone) && empty($disablemove)) ?' class="linecolmove tdlineupdown"':' class="linecolmove"').'>'; + print '
'; + $colspan=(empty($useinecm)?'5':'5'); + if (empty($disablemove)) $colspan++; + print '
'; if (empty($textifempty)) print $langs->trans("NoFileFound"); else print $textifempty; print '
"; + + + if (! $editline && $nboflines > 1) { + if (! empty($conf->use_javascript_ajax) && $permtoeditline) { + $table_element_line = 'ecm_files'; + include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php'; + } + } + if (GETPOST('action') == 'editfile' && $permtoeditline) { print '
'; diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 6c2b5600917..20eb2dd35cb 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -79,7 +79,7 @@ class FormProjets $project->fetch($selected); $selected_input_value=$project->ref; } - $urloption='socid='.$socid.'&htmlname='.$htmlname; + $urloption='socid='.$socid.'&htmlname='.$htmlname.'&discardclosed='.$discard_closed; $out.=ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array( // 'update' => array( // 'projectid' => 'id' @@ -458,13 +458,16 @@ class FormProjets if ($table_element == 'projet_task') return ''; // Special cas of element we never link to a project (already always done) $linkedtothirdparty=false; - if (! in_array($table_element, array('don','expensereport_det','expensereport'))) $linkedtothirdparty=true; + if (! in_array($table_element, array('don','expensereport_det','expensereport','loan'))) $linkedtothirdparty=true; $sqlfilter=''; $projectkey="fk_projet"; //print $table_element; switch ($table_element) { + case "loan": + $sql = "SELECT t.rowid, t.label as ref"; + break; case "facture": $sql = "SELECT t.rowid, t.facnumber as ref"; break; diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 2744946e215..d097cc484ba 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -41,7 +41,7 @@ function dol_basename($pathfile) * Scan a directory and return a list of files/directories. * Content for string is UTF8 and dir separator is "/". * - * @param string $path Starting path from which to search + * @param string $path Starting path from which to search. This is a full path. * @param string $types Can be "directories", "files", or "all" * @param int $recursive Determines whether subdirectories are searched * @param string $filter Regex filter to restrict list. This regex value must be escaped for '/', since this char is used for preg_match function @@ -50,7 +50,8 @@ function dol_basename($pathfile) * @param string $sortorder Sort order (SORT_ASC, SORT_DESC) * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like date and size to be loaded (slower), 2=Force load of date only, 3=Force load of size only * @param int $nohook Disable all hooks - * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file') + * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file',...) + * @see dol_dir_list_indatabase */ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter="", $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=false) { @@ -87,7 +88,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil } // $reshook may contain returns stacked by other modules - // $reshook is always empty with an array for can not lose returns stacked with other modules + // $reshook is always empty with an array to not lose returns stacked with other modules // $hookmanager->resArray may contain array stacked by other modules if (! $nohook && ! empty($hookmanager->resArray)) // forced to use $hookmanager->resArray even if $hookmanager->resArray['nodes'] is empty { @@ -205,6 +206,84 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil } +/** + * Scan a directory and return a list of files/directories. + * Content for string is UTF8 and dir separator is "/". + * + * @param string $path Starting path from which to search. Example: 'produit/MYPROD' + * @param string $filter Regex filter to restrict list. This regex value must be escaped for '/', since this char is used for preg_match function + * @param array|null $excludefilter Array of Regex for exclude filter (example: array('(\.meta|_preview\.png)$','^\.')) + * @param string $sortcriteria Sort criteria ("","fullname","name","date","size") + * @param string $sortorder Sort order (SORT_ASC, SORT_DESC) + * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like description + * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','type'=>'dir|file',...) + * @see dol_dir_list + */ +function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0) +{ + global $conf, $db; + + $sql=" SELECT rowid, label, entity, filename, filepath, fullpath_orig, keywords, cover, gen_or_uploaded, extraparams, date_c, date_m, fk_user_c, fk_user_m, acl, position"; + if ($mode) $sql.=", description"; + $sql.=" FROM ".MAIN_DB_PREFIX."ecm_files"; + $sql.=" WHERE filepath = '".$db->escape($path)."'"; + $sql.=" AND entity = ".$conf->entity; + + $resql = $db->query($sql); + if ($resql) + { + $file_list=array(); + $num = $db->num_rows($resql); + $i = 0; + while ($i < $num) + { + $obj = $db->fetch_object($resql); + if ($obj) + { + preg_match('/([^\/]+)\/[^\/]+$/',DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,$reg); + $level1name=(isset($reg[1])?$reg[1]:''); + $file_list[] = array( + "rowid" => $obj->rowid, + "label" => $obj->label, // md5 + "name" => $obj->filename, + "path" => DOL_DATA_ROOT.'/'.$obj->filepath, + "level1name" => $level1name, + "fullname" => DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename, + "fullpath_orig" => $obj->fullpath_orig, + "date_c" => $db->jdate($obj->date_c), + "date_m" => $db->jdate($obj->date_m), + "type" => 'file', + "keywords" => $obj->keywords, + "cover" => $obj->cover, + "position" => (int) $obj->position, + "acl" => $obj->acl + ); + } + $i++; + } + + // Obtain a list of columns + if (! empty($sortcriteria)) + { + $myarray=array(); + foreach ($file_list as $key => $row) + { + $myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:''); + } + // Sort the data + if ($sortorder) array_multisort($myarray, $sortorder, $file_list); + } + + return $file_list; + } + else + { + dol_print_error($db); + return array(); + } +} + + /** * Fast compare of 2 files identified by their properties ->name, ->date and ->size * @@ -497,11 +576,19 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists) */ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1) { - global $conf; + global $user, $db, $conf; $result=false; dol_syslog("files.lib.php::dol_move srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists); + $srcexists=dol_is_file($srcfile); $destexists=dol_is_file($destfile); + + if (! $srcexists) + { + dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request."); + return false; + } + if ($overwriteifexists || ! $destexists) { $newpathofsrcfile=dol_osencode($srcfile); @@ -512,13 +599,68 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1) { if ($destexists) { - dol_syslog("files.lib.php::dol_move failed. We try to delete first and move after.", LOG_WARNING); + dol_syslog("files.lib.php::dol_move Failed. We try to delete target first and move after.", LOG_WARNING); // We force delete and try again. Rename function sometimes fails to replace dest file with some windows NTFS partitions. dol_delete_file($destfile); $result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @ } - else dol_syslog("files.lib.php::dol_move failed", LOG_WARNING); + else dol_syslog("files.lib.php::dol_move Failed.", LOG_WARNING); } + + // Move ok + if ($result) + { + // Rename entry into ecm database + $rel_filetorenamebefore = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $srcfile); + $rel_filetorenameafter = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $destfile); + if (! preg_match('/(\/temp\/|\/thumbs|\.meta$)/', $rel_filetorenameafter)) // If not a tmp file + { + $rel_filetorenamebefore = preg_replace('/^[\\/]/', '', $rel_filetorenamebefore); + $rel_filetorenameafter = preg_replace('/^[\\/]/', '', $rel_filetorenameafter); + //var_dump($rel_filetorenamebefore.' - '.$rel_filetorenameafter); + + dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG); + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $result = $ecmfile->fetch(0, '', $rel_filetorenamebefore); + if ($result > 0) // If found + { + $filename = basename($rel_filetorenameafter); + $rel_dir = dirname($rel_filetorenameafter); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $result = $ecmfile->update($user); + } + elseif ($result == 0) // If not found + { + $filename = basename($rel_filetorenameafter); + $rel_dir = dirname($rel_filetorenameafter); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $ecmfile->label = md5_file(dol_osencode($destfile)); // $destfile is a full path to file + $ecmfile->fullpath_orig = $srcfile; + $ecmfile->gen_or_uploaded = 'unknown'; + $ecmfile->description = ''; // indexed content + $ecmfile->keyword = ''; // keyword content + $result = $ecmfile->create($user); + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + } + elseif ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + } + } + if (empty($newmask)) $newmask=empty($conf->global->MAIN_UMASK)?'0755':$conf->global->MAIN_UMASK; $newmaskdec=octdec($newmask); // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too) @@ -743,10 +885,33 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n { if ($nophperrors) $ok=@unlink($filename); else $ok=unlink($filename); - if ($ok) dol_syslog("Removed file ".$filename, LOG_DEBUG); + if ($ok) + { + dol_syslog("Removed file ".$filename, LOG_DEBUG); + + // Delete entry into ecm database + $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename); + if (! preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete)) // If not a tmp file + { + $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete); + + dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG); + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $result = $ecmfile->fetch(0, '', $rel_filetodelete); + if ($result >= 0) + { + $result = $ecmfile->delete($user); + } + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + } + } else dol_syslog("Failed to remove file ".$filename, LOG_WARNING); // TODO Failure to remove can be because file was already removed or because of permission - // If error because of not exists, we must can return true but we should return false if this is a permission problem + // If error because of not exists, we must should return true and we should return false if this is a permission problem } } else dol_syslog("No files to delete found", LOG_WARNING); @@ -995,12 +1160,12 @@ function dol_init_file_process($pathtoscan='', $trackid='') * All information used are in db, conf, langs, user and _FILES. * Note: This function can be used only into a HTML page context. * - * @param string $upload_dir Directory where to store uploaded file (note: also find in first part of dest_file) + * @param string $upload_dir Directory where to store uploaded file (note: used to forge $destpath = $upload_dir + filename) * @param int $allowoverwrite 1=Allow overwrite existing file * @param int $donotupdatesession 1=Do no edit _SESSION variable * @param string $varfiles _FILES var name * @param string $savingdocmask Mask to use to define output filename. For example 'XXXXX-__YYYYMMDD__-__file__' - * @param string $link Link to add + * @param string $link Link to add (to add a link instead of a file) * @param string $trackid Track id (used to prefix name of session vars to avoid conflict) * @return void */ @@ -1026,49 +1191,82 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio for ($i = 0; $i < $nbfile; $i++) { - // Define $destpath (path to file including filename) and $destfile (only filename) - $destpath=$upload_dir . "/" . $TFile['name'][$i]; + // Define $destfull (path to file including filename) and $destfile (only filename) + $destfull=$upload_dir . "/" . $TFile['name'][$i]; $destfile=$TFile['name'][$i]; $savingdocmask = dol_sanitizeFileName($savingdocmask); if ($savingdocmask) { - $destpath=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask); + $destfull=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask); $destfile=preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask); } // lowercase extension - $info = pathinfo($destpath); - $destpath = $info['dirname'].'/'.$info['filename'].'.'.strtolower($info['extension']); + $info = pathinfo($destfull); + $destfull = $info['dirname'].'/'.$info['filename'].'.'.strtolower($info['extension']); $info = pathinfo($destfile); $destfile = $info['filename'].'.'.strtolower($info['extension']); - - $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destpath, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles); - if (is_numeric($resupload) && $resupload > 0) + + $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles); + + if (is_numeric($resupload) && $resupload > 0) // $resupload can be 'ErrorFileAlreadyExists' { global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini; include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; + + // Generate thumbs. + if (image_format_supported($destfull) == 1) + { + // Create thumbs + // We can't use $object->addThumbs here because there is no $object known + + // Used on logon for example + $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); + // Create mini thumbs for image (Ratio is near 16/9) + // Used on menu or for setup page for example + $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); + } + + // Update session if (empty($donotupdatesession)) { include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($db); $formmail->trackid = $trackid; - $formmail->add_attached_files($destpath, $destfile, $TFile['type'][$i]); + $formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]); } - if (image_format_supported($destpath) == 1) + + // Update table of files + if ($donotupdatesession) { - // Create thumbs - // We can't use $object->addThumbs here because there is no $object known - - // Used on logon for example - $imgThumbSmall = vignette($destpath, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); - // Create mini thumbs for image (Ratio is near 16/9) - // Used on menu or for setup page for example - $imgThumbMini = vignette($destpath, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); + $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir); + + if (! preg_match('/[\\/]temp[\\/]/', $rel_dir)) // If not a tmp dir + { + $filename = basename($destfile); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $ecmfile->label = md5_file(dol_osencode($destfull)); + $ecmfile->fullpath_orig = $TFile['name'][$i]; + $ecmfile->gen_or_uploaded = 'uploaded'; + $ecmfile->description = ''; // indexed content + $ecmfile->keyword = ''; // keyword content + $result = $ecmfile->create($user); + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + } } - + setEventMessages($langs->trans("FileTransferComplete"), null, 'mesgs'); } else @@ -1145,7 +1343,7 @@ function dol_remove_file_process($filenb,$donotupdatesession=0,$donotdeletefile= { $pathtodelete=$listofpaths[$keytodelete]; $filetodelete=$listofnames[$keytodelete]; - if (empty($donotdeletefile)) $result = dol_delete_file($pathtodelete,1); + if (empty($donotdeletefile)) $result = dol_delete_file($pathtodelete,1); // The delete of ecm database is inside the function dol_delete_file else $result=0; if ($result >= 0) { @@ -1337,11 +1535,11 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta * Security check when accessing to a document (used by document.php, viewimage.php and webservices) * * @param string $modulepart Module of document ('module', 'module_user_temp', 'module_user' or 'module_temp') - * @param string $original_file Relative path with filename + * @param string $original_file Relative path with filename, relative to modulepart. * @param string $entity Restrict onto entity * @param User $fuser User object (forced) * @param string $refname Ref of object to check permission for external users (autodetect if not provided) - * @return mixed Array with access information : accessallowed & sqlprotectagainstexternals & original_file (as full path name) + * @return mixed Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name) */ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fuser='',$refname='') { @@ -1635,7 +1833,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $accessallowed=1; } $original_file=$conf->projet->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project', 1).")"; } else if ($modulepart == 'project_task') { @@ -1644,7 +1842,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $accessallowed=1; } $original_file=$conf->projet->dir_output.'/'.$original_file; - $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project', 1).")"; } // Wrapping for interventions else if ($modulepart == 'fichinter') @@ -1759,6 +1957,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $accessallowed=1; } $original_file=$conf->contrat->dir_output.'/'.$original_file; + $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."contrat WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('contract', 1).")"; } // Wrapping pour les dons diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 245754d1311..10610963b66 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -203,7 +203,7 @@ function getBrowserInfo($user_agent) elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name='opera'; $version=$reg[2]; } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];\srv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name='ie'; $version=end($reg); } // MS products at end elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { $name='lynxlinks'; $version=$reg[4]; } - + if ($tablet) { $layout = 'tablet'; } elseif ($phone) { @@ -268,14 +268,14 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL) { $tmp=dol_getdate(dol_now(), true); $out = $tmp['mon']; - } + } elseif ($reg[1] == 'YEAR') { $tmp=dol_getdate(dol_now(), true); $out = $tmp['year']; } } - + switch ($check) { case 'int': @@ -409,15 +409,15 @@ function dol_buildpath($path, $type=0) if ($type == 1) $res = DOL_URL_ROOT.'/'.$path; // Standard value if ($type == 2) $res = DOL_MAIN_URL_ROOT.'/'.$path; // Standard value if ($type == 3) $res = DOL_URL_ROOT.'/'.$path; - + foreach ($conf->file->dol_document_root as $key => $dirroot) // ex: array(["main"]=>"/home/main/htdocs", ["alt0"]=>"/home/dirmod/htdocs", ...) { - if ($key == 'main') + if ($key == 'main') { if ($type == 3) { global $dolibarr_main_url_root; - + // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file @@ -444,12 +444,12 @@ function dol_buildpath($path, $type=0) if ($type == 3) { global $dolibarr_main_url_root; - + // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - + $res=(preg_match('/^http/i',$conf->file->dol_url_root[$key])?'':$urlwithroot).$conf->file->dol_url_root[$key].'/'.$path; // Test on start with http is for old conf syntax } break; @@ -716,13 +716,13 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' throw new Exception('Incorrect log level'); } if ($level > $conf->global->SYSLOG_LEVEL) return; - + // If adding log inside HTML page is required if (! empty($_REQUEST['logtohtml']) && (! empty($conf->global->MAIN_ENABLE_LOG_TO_HTML) || ! empty($conf->global->MAIN_LOGTOHTML))) // MAIN_LOGTOHTML kept for backward compatibility { $conf->logbuffer[] = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".$message; } - + //TODO: Remove this. MAIN_ENABLE_LOG_INLINE_HTML should be deprecated and use a log handler dedicated to HTML output // If enable html log tag enabled and url parameter log defined, we show output log on HTML comments if (! empty($conf->global->MAIN_ENABLE_LOG_INLINE_HTML) && ! empty($_GET["log"])) @@ -731,7 +731,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' print $message."\n"; print "Log end -->\n"; } - + $data = array( 'message' => $message, 'script' => (isset($_SERVER['PHP_SELF'])? basename($_SERVER['PHP_SELF'],'.php') : false), @@ -739,7 +739,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' 'user' => ((is_object($user) && $user->id) ? $user->login : false), 'ip' => false ); - + if (! empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) else if (! empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR']; @@ -926,7 +926,7 @@ function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $pi { $out = $hookmanager->resPrint; } - + return $out; } @@ -985,7 +985,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($object->element == 'member') $modulepart='memberphoto'; if ($object->element == 'user') $modulepart='userphoto'; if ($object->element == 'product') $modulepart='product'; - + if ($object->element == 'product') { $width=80; $cssclass='photoref'; @@ -993,7 +993,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r $maxvisiblephotos=(isset($conf->global->PRODUCT_MAX_VISIBLE_PHOTO)?$conf->global->PRODUCT_MAX_VISIBLE_PHOTO:5); if ($conf->browser->phone) $maxvisiblephotos=1; if ($showimage) $morehtmlleft.='
'.$object->show_photos($conf->product->multidir_output[$object->entity],'small',$maxvisiblephotos,0,0,0,$width,0).'
'; - else + else { if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) { $nophoto=''; @@ -1003,14 +1003,14 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r $nophoto='/public/theme/common/nophoto.png'; $morehtmlleft.='
No photo
'; } - + } } - else + else { - if ($showimage) + if ($showimage) { - if ($modulepart != 'unknown') + if ($modulepart != 'unknown') { $phototoshow = $form->showphoto($modulepart,$object,0,0,0,'photoref','small',1,0,$maxvisiblephotos); if ($phototoshow) @@ -1023,7 +1023,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r elseif ($conf->browser->layout != 'phone') // Show no photo link { $morehtmlleft.='
'; - if ($object->element == 'action') + if ($object->element == 'action') { $cssclass='photorefcenter'; $nophoto=img_picto('', 'title_agenda', '', false, 1); @@ -1042,7 +1042,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($showbarcode) $morehtmlleft.='
'.$form->showbarcode($object).'
'; if ($object->element == 'societe' && ! empty($conf->use_javascript_ajax) && $user->rights->societe->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { $morehtmlstatus.=ajax_object_onoff($object, 'status', 'status', 'InActivity', 'ActivityCeased'); - } + } elseif ($object->element == 'product') { //$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Sell").') '; @@ -1062,7 +1062,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r elseif ($object->element == 'facture' || $object->element == 'invoice' || $object->element == 'invoice_supplier') { $tmptxt=$object->getLibStatut(6, $object->totalpaye); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); $morehtmlstatus.=$tmptxt; } elseif ($object->element == 'chargesociales') @@ -1084,7 +1084,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r } else { // Generic case $tmptxt=$object->getLibStatut(6); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5); $morehtmlstatus.=$tmptxt; } if (! empty($object->name_alias)) $morehtmlref.='
'.$object->name_alias.'
'; // For thirdparty @@ -1278,9 +1278,9 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e $reduceformat=(! empty($conf->dol_optimize_smallscreen) && in_array($format,array('day','dayhour')))?1:0; $formatwithoutreduce = preg_replace('/reduceformat/','',$format); if ($formatwithoutreduce != $format) { $format = $formatwithoutreduce; $reduceformat=1; } // so format 'dayreduceformat' is processed like day - + // Change predefined format into computer format. If found translation in lang file we use it, otherwise we use default. - // TODO Add format daysmallyear and dayhoursmallyear + // TODO Add format daysmallyear and dayhoursmallyear if ($format == 'day') $format=($outputlangs->trans("FormatDateShort")!="FormatDateShort"?$outputlangs->trans("FormatDateShort"):$conf->format_date_short); else if ($format == 'hour') $format=($outputlangs->trans("FormatHourShort")!="FormatHourShort"?$outputlangs->trans("FormatHourShort"):$conf->format_hour_short); else if ($format == 'hourduration') $format=($outputlangs->trans("FormatHourShortDuration")!="FormatHourShortDuration"?$outputlangs->trans("FormatHourShortDuration"):$conf->format_hour_short_duration); @@ -1782,7 +1782,7 @@ function dol_print_phone($phone,$countrycode='',$cid=0,$socid=0,$addlink='',$sep $newphone=($separ!=''?'(':'').substr($newphone,0,3).($separ!=''?')':'').$separ.substr($newphone,3,3).($separ!=''?'-':'').substr($newphone,6,4); } } - + if (! empty($addlink)) // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set) { if (! empty($conf->browser->phone) || (! empty($conf->clicktodial->enabled) && ! empty($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) // If phone or option for, we use link of phone @@ -1912,7 +1912,7 @@ function dol_user_country() * @param int $mode thirdparty|contact|member|other * @param int $id Id of object * @param int $noprint No output. Result is the function return - * @param string $charfornl Char to use instead of nl2br. '' means we use a standad nl2br. + * @param string $charfornl Char to use instead of nl2br. '' means we use a standad nl2br. * @return string|void Nothing if noprint is 0, formatted address if noprint is 1 * @see dol_format_address */ @@ -1933,7 +1933,7 @@ function dol_print_address($address, $htmlid, $mode, $id, $noprint=0, $charfornl { if (empty($charfornl)) $out.=nl2br($address); else $out.=preg_replace('/[\r\n]+/', $charfornl, $address); - + $showgmap=$showomap=0; // TODO Add a hook here @@ -2061,7 +2061,7 @@ function dol_print_graph($htmlid,$width,$height,$data,$showlegend=0,$type='pie', print '
'.$langs->trans("NotEnoughDataYet").'
'; return; } - + if (empty($conf->use_javascript_ajax)) return; $jsgraphlib='flot'; $datacolor=array(); @@ -2230,7 +2230,7 @@ function dol_trunc($string,$size=40,$trunc='right',$stringencoding='UTF-8',$nodo global $conf; if ($size==0 || ! empty($conf->global->MAIN_DISABLE_TRUNC)) return $string; - + if (empty($stringencoding)) $stringencoding='UTF-8'; // reduce for small screen if ($conf->dol_optimize_smallscreen==1 && $display==1) $size = round($size/3); @@ -3196,11 +3196,11 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', function load_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1, $totalnboflines=-1, $picto='title_generic.png', $pictoisfullpath=0, $morehtml='', $morecss='', $limit=-1, $hideselectlimit=0) { global $conf,$langs; - + $savlimit = $limit; $savtotalnboflines = $totalnboflines; $totalnboflines=abs($totalnboflines); - + if ($picto == 'setup') $picto='title_setup.png'; if (($conf->browser->name == 'ie') && $picto=='title_generic.png') $picto='title.gif'; if ($limit < 0) $limit = $conf->liste_limit; @@ -3433,7 +3433,7 @@ function print_fleche_navigation($page, $file, $options='', $nextpage=0, $betwee function vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0) { $morelabel=''; - + if (preg_match('/%/',$rate)) { $rate=str_replace('%','',$rate); @@ -3636,7 +3636,7 @@ function price2num($amount,$rounding='',$alreadysqlnb=0) /** * Output a dimension with best unit - * + * * @param float $dimension Dimension * @param int $unit Unit of dimension (0, -3, ...) * @param string $type 'weight', 'volume', ... @@ -3648,16 +3648,16 @@ function price2num($amount,$rounding='',$alreadysqlnb=0) function showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no') { require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; - - if (($forceunitoutput == 'no' && $dimension < 1/10000) || (is_numeric($forceunitoutput) && $forceunitoutput == -6)) + + if (($forceunitoutput == 'no' && $dimension < 1/10000) || (is_numeric($forceunitoutput) && $forceunitoutput == -6)) { $dimension = $dimension * 1000000; - $unit = $unit - 6; + $unit = $unit - 6; } elseif (($forceunitoutput == 'no' && $dimension < 1/10) || (is_numeric($forceunitoutput) && $forceunitoutput == -3)) { $dimension = $dimension * 1000; - $unit = $unit - 3; + $unit = $unit - 3; } elseif (($forceunitoutput == 'no' && $dimension > 100000000) || (is_numeric($forceunitoutput) && $forceunitoutput == 6)) { @@ -3669,9 +3669,9 @@ function showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round= $dimension = $dimension / 1000; $unit = $unit + 3; } - + $ret=price($dimension, 0, $outputlangs, 0, 0, $round).' '.measuring_units_string($unit, $type); - + return $ret; } @@ -3702,12 +3702,12 @@ function get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller $vatratecleaned = trim($reg[1]); $vatratecode = $reg[2]; } - + /*if ($thirdparty_buyer->country_code != $thirdparty_seller->country_code) { return 0; }*/ - + // Some test to guess with no need to make database access if ($mysoc->country_code == 'ES') // For spain localtaxes 1 and 2, tax is qualified if buyer use local taxe { @@ -3805,7 +3805,7 @@ function get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller if ($local==1) return $obj->localtax1; elseif ($local==2) return $obj->localtax2; } - + return 0; } @@ -3865,7 +3865,7 @@ function get_localtax_by_third($local) /** * Get vat rate and npr from id. - * You can call getLocalTaxesFromRate after to get other fields + * You can call getLocalTaxesFromRate after to get other fields * * @param int $vatrowid Line ID into vat rate table. * @return array array(localtax_type1(1-6 / 0 if not found), rate of localtax1, ...) @@ -3919,7 +3919,7 @@ function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisi $vatratecleaned = $reg[1]; $vatratecode = $reg[2]; } - + // Search local taxes $sql = "SELECT t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.accountancy_code_sell, t.accountancy_code_buy"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t"; @@ -3932,7 +3932,7 @@ function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisi $sql.= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1"; if ($vatratecode) $sql.= " AND t.code ='".$vatratecode."'"; } - + $resql=$db->query($sql); if ($resql) { @@ -4339,7 +4339,7 @@ function yn($yesno, $case=1, $color=0) /** * Return a path to have a directory according to object. * New usage: $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'modulepart') - * Old usage: '015' with level 3->"0/1/5/", '015' with level 1->"5/", 'ABC-1' with level 3 ->"0/0/1/" + * Old usage: '015' with level 3->"0/1/5/", '015' with level 1->"5/", 'ABC-1' with level 3 ->"0/0/1/" * * @param string $num Id of object (deprecated, $object will be used in future) * @param int $level Level of subdirs to return (1, 2 or 3 levels). (deprecated, global option will be used in future) @@ -4356,7 +4356,7 @@ function get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart) $path = ''; $arrayforoldpath=array('cheque','user','category','holiday','shipment','supplier_invoice','invoice_supplier','mailing'); - if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $arrayforoldpath[]='product'; + if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $arrayforoldpath[]='product'; if (! empty($level) && in_array($modulepart, $arrayforoldpath)) { // This part should be removed once all code is using "get_exdir" to forge path, with all parameters provided @@ -4509,7 +4509,7 @@ function dolGetFirstLineOfText($text) { $firstline=preg_replace('/]*>.*$/s','',$text); // The s pattern modifier means the . can match newline characters $firstline=preg_replace('/]*>.*$/s','',$firstline); // The s pattern modifier means the . can match newline characters - + } else { @@ -5415,7 +5415,7 @@ function picto_from_langcode($codelang) } /** - * Complete or removed entries into a head array (used to build tabs). + * Complete or removed entries into a head array (used to build tabs). * For example, with value added by external modules. Such values are declared into $conf->modules_parts['tab']. * Or by change using hook completeTabsHead * @@ -5445,7 +5445,7 @@ function picto_from_langcode($codelang) function complete_head_from_modules($conf,$langs,$object,&$head,&$h,$type,$mode='add') { global $hookmanager; - + if (isset($conf->modules_parts['tabs'][$type]) && is_array($conf->modules_parts['tabs'][$type])) { foreach ($conf->modules_parts['tabs'][$type] as $value) @@ -5511,7 +5511,7 @@ function complete_head_from_modules($conf,$langs,$object,&$head,&$h,$type,$mode= } } } - + // No need to make a return $head. Var is modified as a reference if (! empty($hookmanager)) { @@ -5549,11 +5549,11 @@ function printCommonFooter($zone='private') { print ''."\n"; print ''."\n"; } - + // Google Analytics (need Google module) if (! empty($conf->google->enabled) && ! empty($conf->global->MAIN_GOOGLE_AN_ID)) { @@ -5717,7 +5717,7 @@ function dol_getmypid() * If param $mode is 1, can contains an operator <, > or = like "<10" or ">=100.5 < 1000" * If param $mode is 2, can contains a list of id separated by comma like "1,3,4" * @param integer $mode 0=value is list of keywords, 1=value is a numeric test (Example ">5.5 <10"), 2=value is a list of id separated with comma (Example '1,3,4') - * @param integer $nofirstand 1=Do now output the first 'AND' + * @param integer $nofirstand 1=Do not output the first 'AND' * @return string $res The statement to append to the SQL query */ function natural_search($fields, $value, $mode=0, $nofirstand=0) @@ -5732,6 +5732,9 @@ function natural_search($fields, $value, $mode=0, $nofirstand=0) { $value=preg_replace('/([<>=]+)\s+([0-9'.preg_quote($langs->trans("DecimalSeparator"),'/').'\-])/','\1\2',$value); // Clean string '< 10' into '<10' so we can the explode on space to get all tests to do } + + $value = preg_replace('/\s*\|\s*/','|', $value); + $crits = explode(' ', $value); $res = ''; if (! is_array($fields)) $fields = array($fields); @@ -5786,15 +5789,15 @@ function natural_search($fields, $value, $mode=0, $nofirstand=0) $tmpcrit=trim($tmpcrit); $tmpcrit2=$tmpcrit; $tmpbefore='%'; $tmpafter='%'; - if (preg_match('/^[\^\$]/', $tmpcrit)) - { + if (preg_match('/^[\^\$]/', $tmpcrit)) + { $tmpbefore=''; - $tmpcrit2 = preg_replace('/^[\^\$]/', '', $tmpcrit2); + $tmpcrit2 = preg_replace('/^[\^\$]/', '', $tmpcrit2); } - if (preg_match('/[\^\$]$/', $tmpcrit)) - { + if (preg_match('/[\^\$]$/', $tmpcrit)) + { $tmpafter=''; - $tmpcrit2 = preg_replace('/[\^\$]$/', '', $tmpcrit2); + $tmpcrit2 = preg_replace('/[\^\$]$/', '', $tmpcrit2); } $newres .= $tmpbefore; $newres .= $db->escape($tmpcrit2); @@ -5859,7 +5862,7 @@ function getImageFileNameForSize($file, $extName, $extImgTarget='') function getAdvancedPreviewUrl($modulepart, $relativepath) { global $conf; - + if (empty($conf->use_javascript_ajax)) return ''; $mime_preview = array('bmp', 'jpeg', 'png', 'gif', 'tiff', 'pdf', 'plain', 'css'); diff --git a/htdocs/core/lib/images.lib.php b/htdocs/core/lib/images.lib.php index 9cf745a0da0..00153a7849d 100644 --- a/htdocs/core/lib/images.lib.php +++ b/htdocs/core/lib/images.lib.php @@ -37,8 +37,10 @@ $quality = 80; */ function image_format_supported($file) { + $regeximgext='\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.xpm|\.xbm'; // See also into product.class.php + // Case filename is not a format image - if (! preg_match('/(\.gif|\.jpg|\.jpeg|\.png|\.bmp)$/i',$file,$reg)) return -1; + if (! preg_match('/('.$regeximgext.')$/i',$file,$reg)) return -1; // Case filename is a format image but not supported by this PHP $imgfonction=''; @@ -47,6 +49,8 @@ function image_format_supported($file) if (strtolower($reg[1]) == '.jpg') $imgfonction = 'imagecreatefromjpeg'; if (strtolower($reg[1]) == '.jpeg') $imgfonction = 'imagecreatefromjpeg'; if (strtolower($reg[1]) == '.bmp') $imgfonction = 'imagecreatefromwbmp'; + if (strtolower($reg[1]) == '.xpm') $imgfonction = 'imagecreatefromxpm'; + if (strtolower($reg[1]) == '.xbm') $imgfonction = 'imagecreatefromxbm'; if ($imgfonction) { if (! function_exists($imgfonction)) diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php index 6f47ef6e62b..0149b581fa2 100644 --- a/htdocs/core/lib/oauth.lib.php +++ b/htdocs/core/lib/oauth.lib.php @@ -26,9 +26,13 @@ // Supported OAUTH (a provider is supported when a file xxx_oauthcallback.php is available into htdocs/core/modules/oauth) $supportedoauth2array=array( 'OAUTH_GOOGLE_NAME'=>'google', - 'OAUTH_GITHUB_NAME'=>'github' ); +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) +{ + $supportedoauth2array['OAUTH_GITHUB_NAME']='github'; +} +$supportedoauth2array['OAUTH_GITHUB_NAME']='github'; // API access parameters OAUTH $list = array ( array( @@ -264,7 +268,7 @@ function oauthadmin_prepare_head() $h++; $head[$h][0] = dol_buildpath('/admin/oauthlogintokens.php', 1); - $head[$h][1] = $langs->trans("ManualTokenGeneration"); + $head[$h][1] = $langs->trans("TokenManager"); $head[$h][2] = 'tokengeneration'; $h++; diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index a88e180b16a..8c6c7311f82 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -111,13 +111,13 @@ function print_eldy_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0,$mode $chaine=""; if (! empty($conf->product->enabled)) { - $chaine.=$langs->trans("Products"); + $chaine.=$langs->trans("TMenuProducts"); } if (! empty($conf->product->enabled) && ! empty($conf->service->enabled)) { - $chaine.="/"; + $chaine.=" | "; } if (! empty($conf->service->enabled)) { - $chaine.=$langs->trans("Services"); + $chaine.=$langs->trans("TMenuServices"); } if (empty($noout)) print_start_menu_entry($idsel,$classname,$showmode); @@ -261,7 +261,7 @@ function print_eldy_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0,$mode $idsel='tools'; if (empty($noout)) print_start_menu_entry($idsel,$classname,$showmode); - if (empty($noout)) print_text_menu_entry($langs->trans("Tools"), $showmode, DOL_URL_ROOT.'/core/tools.php?mainmenu=tools&leftmenu=', $id, $idsel, $classname, $atarget); + if (empty($noout)) print_text_menu_entry($langs->trans("TMenuTools"), $showmode, DOL_URL_ROOT.'/core/tools.php?mainmenu=tools&leftmenu=', $id, $idsel, $classname, $atarget); if (empty($noout)) print_end_menu_entry($showmode); $menu->add('/core/tools.php?mainmenu=tools&leftmenu=', $langs->trans("Tools"), 0, $showmode, $atarget, "tools", ''); } diff --git a/htdocs/core/modules/modAgenda.class.php b/htdocs/core/modules/modAgenda.class.php index a0c2a6e9de4..2ba37ad3cbd 100644 --- a/htdocs/core/modules/modAgenda.class.php +++ b/htdocs/core/modules/modAgenda.class.php @@ -189,7 +189,7 @@ class modAgenda extends DolibarrModules // $r++; $this->menu[$r]=array('fk_menu'=>0, 'type'=>'top', - 'titre'=>'Agenda', + 'titre'=>'TMenuAgenda', 'mainmenu'=>'agenda', 'url'=>'/comm/action/index.php', 'langs'=>'agenda', diff --git a/htdocs/core/modules/oauth/github_oauthcallback.php b/htdocs/core/modules/oauth/github_oauthcallback.php new file mode 100644 index 00000000000..83c3da66a47 --- /dev/null +++ b/htdocs/core/modules/oauth/github_oauthcallback.php @@ -0,0 +1,171 @@ + + * + * 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 . + */ + +/** + * \file htdocs/core/modules/oauth/github_oauthcallback.php + * \ingroup oauth + * \brief Page to get oauth callback + */ + +require '../../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; +use OAuth\Common\Storage\DoliStorage; +use OAuth\Common\Consumer\Credentials; +use OAuth\OAuth2\Service\GitHub; + +// Define $urlwithroot +$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + + +$action = GETPOST('action', 'alpha'); +$backtourl = GETPOST('backtourl', 'alpha'); + + +/** + * Create a new instance of the URI class with the current URI, stripping the query string + */ +$uriFactory = new \OAuth\Common\Http\Uri\UriFactory(); +//$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); +//$currentUri->setQuery(''); +$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/github_oauthcallback.php'); + + +/** + * Load the credential for the service + */ + +/** @var $serviceFactory \OAuth\ServiceFactory An OAuth service factory. */ +$serviceFactory = new \OAuth\ServiceFactory(); +$httpClient = new \OAuth\Common\Http\Client\CurlClient(); +// TODO Set options for proxy and timeout +// $params=array('CURLXXX'=>value, ...) +//$httpClient->setCurlParameters($params); +$serviceFactory->setHttpClient($httpClient); + +// Dolibarr storage +$storage = new DoliStorage($db, $conf); + +// Setup the credentials for the requests +$credentials = new Credentials( + $conf->global->OAUTH_GITHUB_ID, + $conf->global->OAUTH_GITHUB_SECRET, + $currentUri->getAbsoluteUri() +); + +$requestedpermissionsarray=array(); +if (GETPOST('state')) $requestedpermissionsarray=explode(',', GETPOST('state')); // Example: 'userinfo_email,userinfo_profile,cloud_print'. 'state' parameter is standard to retrieve some parameters back +if ($action != 'delete' && empty($requestedpermissionsarray)) +{ + print 'Error, parameter state is not defined'; + exit; +} +//var_dump($requestedpermissionsarray);exit; + +// Instantiate the Api service using the credentials, http client and storage mechanism for the token +/** @var $apiService Service */ +$apiService = $serviceFactory->createService('GitHub', $credentials, $storage, $requestedpermissionsarray); + +// access type needed to have oauth provider refreshing token +//$apiService->setAccessType('offline'); + +$langs->load("oauth"); + + +/* + * Actions + */ + + +if ($action == 'delete') +{ + $storage->clearToken('GitHub'); + + setEventMessages($langs->trans('TokenDeleted'), null, 'mesgs'); + + header('Location: ' . $backtourl); + exit(); +} + +if (! empty($_GET['code'])) // We are coming from oauth provider page +{ + //llxHeader('',$langs->trans("OAuthSetup")); + + //$linkback=''.$langs->trans("BackToModuleList").''; + //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup'); + + //dol_fiche_head(); + // retrieve the CSRF state parameter + $state = isset($_GET['state']) ? $_GET['state'] : null; + //print ''; + + // This was a callback request from service, get the token + try { + //var_dump($_GET['code']); + //var_dump($state); + //var_dump($apiService); // OAuth\OAuth2\Service\GitHub + + //$token = $apiService->requestAccessToken($_GET['code'], $state); + $token = $apiService->requestAccessToken($_GET['code']); + // Github is a service that does not need state yo be stored. + // Into constructor of GitHub, the call + // parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri) + // has not the ending parameter to true like the Google class constructor. + + setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token + } catch (Exception $e) { + print $e->getMessage(); + } + + $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"]; + unset($_SESSION["backtourlsavedbeforeoauthjump"]); + + header('Location: ' . $backtourl); + exit(); +} +else // If entry on page with no parameter, we arrive here +{ + $_SESSION["backtourlsavedbeforeoauthjump"]=$backtourl; + + // This may create record into oauth_state before the header redirect. + // Creation of record with state in this tables depend on the Provider used (see its constructor). + if (GETPOST('state')) + { + $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state'))); + } + else + { + $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated + } + + // we go on oauth provider authorization page + header('Location: ' . $url); + exit(); +} + + +/* + * View + */ + +// No view at all, just actions + +$db->close(); + diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php index 3068a29098c..c69493ed9a5 100644 --- a/htdocs/core/modules/oauth/google_oauthcallback.php +++ b/htdocs/core/modules/oauth/google_oauthcallback.php @@ -17,7 +17,7 @@ */ /** - * \file htdocs/core/modules/oauth/getoauthcallback.php + * \file htdocs/core/modules/oauth/google_oauthcallback.php * \ingroup oauth * \brief Page to get oauth callback */ @@ -83,7 +83,7 @@ if ($action != 'delete' && empty($requestedpermissionsarray)) /** @var $apiService Service */ $apiService = $serviceFactory->createService('Google', $credentials, $storage, $requestedpermissionsarray); -// access type needed for google refresh token +// access type needed to have oauth provider refreshing token $apiService->setAccessType('offline'); $langs->load("oauth"); @@ -104,7 +104,7 @@ if ($action == 'delete') exit(); } -if (! empty($_GET['code'])) // We are coming from Google oauth page +if (! empty($_GET['code'])) // We are coming from oauth provider page { //llxHeader('',$langs->trans("OAuthSetup")); @@ -121,6 +121,7 @@ if (! empty($_GET['code'])) // We are coming from Google oauth page //var_dump($_GET['code']); //var_dump($state); //var_dump($apiService); // OAuth\OAuth2\Service\Google + $token = $apiService->requestAccessToken($_GET['code'], $state); setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token @@ -138,6 +139,8 @@ else // If entry on page with no parameter, we arrive here { $_SESSION["backtourlsavedbeforeoauthjump"]=$backtourl; + // This may create record into oauth_state before the header redirect. + // Creation of record with state in this tables depend on the Provider used (see its constructor). if (GETPOST('state')) { $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state'))); @@ -146,7 +149,8 @@ else // If entry on page with no parameter, we arrive here { $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated } - // we go on google authorization page + + // we go on oauth provider authorization page header('Location: ' . $url); exit(); } diff --git a/htdocs/core/modules/printing/printgcp.modules.php b/htdocs/core/modules/printing/printgcp.modules.php index 3d086466c87..baa5106ae93 100644 --- a/htdocs/core/modules/printing/printgcp.modules.php +++ b/htdocs/core/modules/printing/printgcp.modules.php @@ -66,6 +66,7 @@ class printing_printgcp extends PrintingDriver $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + $this->db = $db; if (!$conf->oauth->enabled) { @@ -117,10 +118,28 @@ class printing_printgcp extends PrintingDriver $this->conf[] = array('varname'=>'PRINTGCP_INFO', 'info'=>'GoogleAuthConfigured', 'type'=>'info'); $this->conf[] = array('varname'=>'PRINTGCP_TOKEN_ACCESS', 'info'=>$access, 'type'=>'info', 'renew'=>$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?state=userinfo_email,userinfo_profile,cloud_print&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'), 'delete'=>($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)?$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'):'')); if ($token_ok) { + $expiredat=''; + $refreshtoken = $token->getRefreshToken(); + + $endoflife=$token->getEndOfLife(); + + if ($endoflife == $token::EOL_NEVER_EXPIRES) + { + $expiredat = $langs->trans("Never"); + } + elseif ($endoflife == $token::EOL_UNKNOWN) + { + $expiredat = $langs->trans("Unknown"); + } + else + { + $expiredat=dol_print_date($endoflife, "dayhour"); + } + $this->conf[] = array('varname'=>'TOKEN_REFRESH', 'info'=>((! empty($refreshtoken))?'Yes':'No'), 'type'=>'info'); $this->conf[] = array('varname'=>'TOKEN_EXPIRED', 'info'=>($expire?'Yes':'No'), 'type'=>'info'); - $this->conf[] = array('varname'=>'TOKEN_EXPIRE_AT', 'info'=>(dol_print_date($token->getEndOfLife(), "dayhour")), 'type'=>'info'); + $this->conf[] = array('varname'=>'TOKEN_EXPIRE_AT', 'info'=>($expiredat), 'type'=>'info'); } /* if ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)) { diff --git a/htdocs/core/photos_resize.php b/htdocs/core/photos_resize.php index 778c37f686a..8fcd0d2b930 100644 --- a/htdocs/core/photos_resize.php +++ b/htdocs/core/photos_resize.php @@ -134,11 +134,50 @@ if ($action == 'confirm_resize' && (isset($_POST["file"]) != "") && (isset($_POS { $fullpath=$dir."/".$original_file; $result=dol_imageResizeOrCrop($fullpath,0,$_POST['sizex'],$_POST['sizey']); - + if ($result == $fullpath) { $object->addThumbs($fullpath); + // Update/create database for file $fullpath + $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $fullpath); + $rel_filename = preg_replace('/^[\\/]/','',$rel_filename); + + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $result = $ecmfile->fetch(0, '', $rel_filename); + if ($result > 0) // If found + { + $filename = basename($rel_filename); + $rel_dir = dirname($rel_filename); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->label = md5_file(dol_osencode($fullpath)); + $result = $ecmfile->update($user); + } + elseif ($result == 0) // If not found + { + $filename = basename($rel_filename); + $rel_dir = dirname($rel_filename); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $ecmfile->label = md5_file(dol_osencode($fullpath)); // $fullpath is a full path to file + $ecmfile->fullpath_orig = $fullpath; + $ecmfile->gen_or_uploaded = 'unknown'; + $ecmfile->description = ''; // indexed content + $ecmfile->keyword = ''; // keyword content + $result = $ecmfile->create($user); + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + $result = $ecmfile->create($user); + } + if ($backtourl) { header("Location: ".$backtourl); @@ -168,6 +207,45 @@ if ($action == 'confirm_crop') { $object->addThumbs($fullpath); + // Update/create database for file $fullpath + $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $fullpath); + $rel_filename = preg_replace('/^[\\/]/','',$rel_filename); + + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $result = $ecmfile->fetch(0, '', $rel_filename); + if ($result > 0) // If found + { + $filename = basename($rel_filename); + $rel_dir = dirname($rel_filename); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->label = md5_file(dol_osencode($fullpath)); + $result = $ecmfile->update($user); + } + elseif ($result == 0) // If not found + { + $filename = basename($rel_filename); + $rel_dir = dirname($rel_filename); + $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); + $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); + + $ecmfile->filepath = $rel_dir; + $ecmfile->filename = $filename; + $ecmfile->label = md5_file(dol_osencode($fullpath)); // $fullpath is a full path to file + $ecmfile->fullpath_orig = $fullpath; + $ecmfile->gen_or_uploaded = 'unknown'; + $ecmfile->description = ''; // indexed content + $ecmfile->keyword = ''; // keyword content + $result = $ecmfile->create($user); + if ($result < 0) + { + setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); + } + $result = $ecmfile->create($user); + } + if ($backtourl) { header("Location: ".$backtourl); @@ -218,10 +296,11 @@ print ''.$langs->trans("Resize").''; print $langs->trans("ResizeDesc").'
'; print $langs->trans("NewLength").': px   '.$langs->trans("or").'   '; print $langs->trans("NewHeight").': px  
'; + print ''; print ''; print ''; -print ''; +print ''; print ''; print '
'; print ''; diff --git a/htdocs/core/tpl/ajaxrow.tpl.php b/htdocs/core/tpl/ajaxrow.tpl.php index 123fcef662c..d0a7b45efea 100644 --- a/htdocs/core/tpl/ajaxrow.tpl.php +++ b/htdocs/core/tpl/ajaxrow.tpl.php @@ -17,18 +17,19 @@ * * Javascript code to activate drag and drop on lines * You can use this if you want to be abale to drag and drop rows of a table. - * You must add id="tablelines" on table level tag and have count($object->lines) or count($taskarray) > 0 + * You must add id="tablelines" on table level tag and have ($nboflines or count($object->lines) or count($taskarray) > 0) */ ?> - +id; $fk_element=$object->fk_element; -$table_element_line=$object->table_element_line; -$nboflines=(isset($object->lines)?count($object->lines):(isset($tasksarray)?count($tasksarray):0)); +$table_element_line=(empty($table_element_line)?$object->table_element_line:$table_element_line); +$nboflines=(isset($object->lines)?count($object->lines):(isset($tasksarray)?count($tasksarray):(empty($nboflines)?0:$nboflines))); $forcereloadpage=empty($conf->global->MAIN_FORCE_RELOAD_PAGE)?0:1; $tagidfortablednd=(empty($tagidfortablednd)?'tablelines':$tagidfortablednd); +$filepath=(empty($filepath)?'':$filepath); if (GETPOST('action') != 'editline' && $nboflines > 1) { ?>