diff --git a/build/debian/README.howto b/build/debian/README.howto index cd7cd93c24e..696ea9a2bef 100644 --- a/build/debian/README.howto +++ b/build/debian/README.howto @@ -295,12 +295,16 @@ If script fails with error Bad certificate, you can set "export PERL_LWP_SSL_VER * Edit orig.tar.gz file to remove - debian - htdocs/includes/ckeditor -- htdocs/includes/jszip +- htdocs/includes/jquery/css +- htdocs/includes/jquery/js +- htdocs/includes/jquery/plugins/flot +- htdocs/includes/jquery/plugins/multiselect - htdocs/includes/jquery/plugins/datatables +- htdocs/includes/jszip - htdocs/includes/mike42 - htdocs/includes/phpexcel or htdocs/includes/phpoffice -- htdocs/includes/swiftmailer - htdocs/includes/restler/framework/Luracast/Restler/explorer +- htdocs/includes/swiftmailer - htdocs/includes/tcpdf or htdocs/includes/tecnickcom And rename file into dolibarr-x.y.z+dfsgw.tgz diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 5de8be91d20..1cb37e92baa 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -329,7 +329,7 @@ if ($result) print ''; print ''; - print ''; + print ''; if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print ''; // On sell print ''; diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 45f2be3e4da..e3081d10400 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -23,8 +23,7 @@ use Luracast\Restler\Defaults; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; /** - * Class for API - * + * Class for API REST v1 */ class DolibarrApi { @@ -55,6 +54,8 @@ class DolibarrApi $this->db = $db; $production_mode = ( empty($conf->global->API_PRODUCTION_MODE) ? false : true ); $this->r = new Restler($production_mode); + + $this->r->setAPIVersion(1); } /** @@ -97,6 +98,7 @@ class DolibarrApi unset($object->statuts); unset($object->statuts_short); unset($object->statuts_logo); + unset($object->statuts_long); // Remove the $oldcopy property because it is not supported by the JSON // encoder. The following error is generated when trying to serialize diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 80cfb5485df..7fe3e6437ac 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -106,7 +106,10 @@ foreach ($modulesdir as $dir) elseif ($module == 'facture') { $moduledirforclass = 'compta/facture'; } - + elseif ($module == 'project') { + $moduledirforclass = 'projet'; + } + // Defined if module is enabled $enabled=true; if (empty($conf->$moduleforperm->enabled)) $enabled=false; @@ -135,7 +138,7 @@ foreach ($modulesdir as $dir) require_once $dir_part.$file_searched; if (class_exists($classname)) { - dol_syslog("Found deprecated API classname=".$classname." into ".$dir); + dol_syslog("Found deprecated API by index.php classname=".$classname." into ".$dir); $api->r->addAPIClass($classname, '/'); } } @@ -145,7 +148,7 @@ foreach ($modulesdir as $dir) require_once $dir_part.$file_searched; if (class_exists($classname)) { - dol_syslog("Found API classname=".$classname." into ".$dir); + dol_syslog("Found API by index.php classname=".$classname." into ".$dir); $listofapis[] = $classname; } } @@ -161,13 +164,14 @@ foreach ($modulesdir as $dir) // shows the classes in the order they are added and it's a mess if they are // not sorted. sort($listofapis); +//var_dump($listofapis); foreach ($listofapis as $classname) { $api->r->addAPIClass($classname); } // TODO If not found, redirect to explorer - +//var_dump($api); // Call API (we suppose we found it) $api->r->handle(); diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 92dc2726030..b2020b71222 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -1,6 +1,6 @@ - * Copyright (C) 2005-2012 Laurent Destailleur + * Copyright (C) 2005-2016 Laurent Destailleur * Copyright (C) 2005-2016 Regis Houssin * * This program is free software; you can redistribute it and/or modify @@ -668,7 +668,15 @@ if ($action == 'create') print ''; print ''; - print load_fiche_titre($langs->trans("NewMailing")); + $htmltext = ''.$langs->trans("FollowingConstantsWillBeSubstituted").':
'; + foreach($object->substitutionarray as $key => $val) + { + $htmltext.=$key.' = '.$langs->trans($val).'
'; + } + $htmltext.='
'; + + // Print mail form + print load_fiche_titre($langs->trans("NewMailing"), $form->textwithpicto($langs->trans("AvailableVariables"), $htmltext), 'title_generic'); dol_fiche_head(); @@ -693,21 +701,16 @@ if ($action == 'create') print ''.$langs->trans("BackgroundColorByDefault").''; print $htmlother->selectColor($_POST['bgcolor'],'bgcolor','new_mailing',0); print ''; - print ''.$langs->trans("MailMessage").'
'; - print '
'.$langs->trans("CommonSubstitutions").':
'; - foreach($object->substitutionarray as $key => $val) - { - print $key.' = '.$langs->trans($val).'
'; - } - print '
'; - print ''; + + print ''; + + print '
'; // Editeur wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $doleditor=new DolEditor('body',$_POST['body'],'',320,'dolibarr_mailings','',true,true,$conf->global->FCKEDITOR_ENABLE_MAILING,20,'90%'); $doleditor->Create(); - print ''; - print ''; - + print '
'; + dol_fiche_end(); print '
'; @@ -788,17 +791,24 @@ else } } - print ''; - $linkback = ''.$langs->trans("BackToList").''; - print ''; + $morehtmlright=''; + if ($object->statut == 2) $morehtmlright.=' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.') '; + + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', '', '', 0, '', $morehtmlright); + + print '
'; + + print '
'.$langs->trans("Ref").'
'; + +/* print ''; print ''; - +*/ // Description - print ''; @@ -813,10 +823,12 @@ else print ''; // Status + /* print ''; - + */ + // Nb of distinct emails print ''; - print ''; - print ''; - - print '
'.$langs->trans("Ref").''; print $form->showrefnav($object,'id', $linkback); print '
'.$form->editfieldkey("MailTitle",'titre',$object->titre,$object,$user->rights->mailing->creer && $object->statut < 3,'string').''; + print '
'.$form->editfieldkey("MailTitle",'titre',$object->titre,$object,$user->rights->mailing->creer && $object->statut < 3,'string').''; print $form->editfieldval("MailTitle",'titre',$object->titre,$object,$user->rights->mailing->creer && $object->statut < 3,'string'); print '
'.$langs->trans("Status").''.$object->getLibStatut(4); if ($object->statut == 2) print ' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.')'; print'
'; print $langs->trans("TotalNbOfDistinctRecipients"); @@ -987,11 +999,19 @@ else print '
'; } + + $htmltext = ''.$langs->trans("FollowingConstantsWillBeSubstituted").':
'; + foreach($object->substitutionarray as $key => $val) + { + $htmltext.=$key.' = '.$langs->trans($val).'
'; + } + $htmltext.='
'; + // Print mail content - print load_fiche_titre($langs->trans("EMail"),'',''); - + print load_fiche_titre($langs->trans("EMail"), $form->textwithpicto($langs->trans("AvailableVariables"), $htmltext), 'title_generic'); + dol_fiche_head(''); - + print ''; // Subject @@ -1019,16 +1039,11 @@ else /*print '';*/ - + + print '
'.$langs->trans("BackgroundColorByDefault").''; print $htmlother->selectColor($object->bgcolor,'bgcolor','edit_mailing',0); print '
'; + // Message - print '
'.$langs->trans("MailMessage").'
'; - print '
'.$langs->trans("CommonSubstitutions").':
'; - foreach($object->substitutionarray as $key => $val) - { - print $key.' = '.$langs->trans($val).'
'; - } - print '
'; + print '
'; if (empty($object->bgcolor) || strtolower($object->bgcolor) == 'ffffff') { $readonly=1; @@ -1038,12 +1053,10 @@ else $doleditor->Create(); } else print dol_htmlentitiesbr($object->body); - print '
'; + print ''; dol_fiche_end(); + } else { @@ -1051,19 +1064,28 @@ else * Mailing en mode edition */ - print ''; - $linkback = ''.$langs->trans("BackToList").''; + $morehtmlright=''; + if ($object->statut == 2) $morehtmlright.=' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.') '; + + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', '', '', 0, '', $morehtmlright); + + print '
'; + + print '
'; + + /* print ''; print ''; - + */ + // Topic - print ''; + print ''; // From - print ''; + print ''; // To print ''; @@ -1100,21 +1122,29 @@ else - print "\n"; + print "
\n"; + print ''."\n"; print ''; print ''; print ''; - + + $htmltext = ''.$langs->trans("FollowingConstantsWillBeSubstituted").':
'; + foreach($object->substitutionarray as $key => $val) + { + $htmltext.=$key.' = '.$langs->trans($val).'
'; + } + $htmltext.='
'; + // Print mail content - print load_fiche_titre($langs->trans("EMail"),'',''); + print load_fiche_titre($langs->trans("EMail"), $form->textwithpicto($langs->trans("AvailableVariables"), $htmltext), 'title_generic'); dol_fiche_head(); - + print '
'.$langs->trans("Ref").''; print $form->showrefnav($object,'id', $linkback); print '
'.$langs->trans("MailTitle").''.$object->titre.'
'.$langs->trans("MailTitle").''.$object->titre.'
'.$langs->trans("MailFrom").''.dol_print_email($object->email_from,0,0,0,0,1).'
'.$langs->trans("MailFrom").''.dol_print_email($object->email_from,0,0,0,0,1).'
'.$langs->trans("MailErrorsTo").''.dol_print_email($object->email_errorsto,0,0,0,0,1).'
'; // Subject - print ''; + print ''; $trackid=''; // TODO To avoid conflicts with 2 mass emailing, we should set a trackid here, even if we use another one into email header. dol_init_file_process($upload_dir, $trackid); @@ -1159,23 +1189,17 @@ else print ''; - + + print '
'.$langs->trans("MailTopic").'
'.$langs->trans("MailTopic").'
'.$langs->trans("BackgroundColorByDefault").''; print $htmlother->selectColor($object->bgcolor,'bgcolor','edit_mailing',0); print '
'; + // Message - print ''.$langs->trans("MailMessage").'
'; - print '
'.$langs->trans("CommonSubstitutions").':
'; - foreach($object->substitutionarray as $key => $val) - { - print $key.' = '.$langs->trans($val).'
'; - } - print '
'; - print ''; + print '
'; // Editeur wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $doleditor=new DolEditor('body',$object->body,'',320,'dolibarr_mailings','',true,true,$conf->global->FCKEDITOR_ENABLE_MAILING,20,120); $doleditor->Create(); - print ''; + print '
'; - print ''; dol_fiche_end(); diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index cc5b16f1935..b12121293d7 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -178,17 +178,24 @@ if ($object->fetch($id) >= 0) dol_fiche_head($head, 'targets', $langs->trans("Mailing"), 0, 'email'); - - print ''; - $linkback = ''.$langs->trans("BackToList").''; + $morehtmlright=''; + if ($object->statut == 2) $morehtmlright.=' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.') '; + + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', '', '', 0, '', $morehtmlright); + + + print '
'; + + print '
'; +/* print ''; print ''; - - print ''; +*/ + print ''; print ''; @@ -197,10 +204,10 @@ if ($object->fetch($id) >= 0) print ''; // Status - print ''; - +*/ // Nb of distinct emails print ''; // EMail print ''; // Name print ''; // Firstname print ''; // Other print ' > diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index 40e3b80a510..0d0552b41ad 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -117,7 +117,7 @@ if (count($listofsearchfields)) { if ($i == 0) print ''; print ''; - print ''; + print ''; if ($i == 0) print ''; print ''; $i++; diff --git a/htdocs/contrat/services.php b/htdocs/contrat/services.php index 8e37e392603..dc4d229dc6e 100644 --- a/htdocs/contrat/services.php +++ b/htdocs/contrat/services.php @@ -50,6 +50,7 @@ $search_contract=GETPOST("search_contract"); $search_service=GETPOST("search_service"); $search_status=GETPOST("search_status","alpha"); $statut=GETPOST('statut')?GETPOST('statut'):1; +$search_product_category=GETPOST('search_product_category','int'); $socid=GETPOST('socid','int'); $opouvertureprevuemonth=GETPOST('opouvertureprevuemonth'); @@ -99,6 +100,9 @@ $staticcontrat=new Contrat($db); $staticcontratligne=new ContratLigne($db); $companystatic=new Societe($db); +$arrayfields=array(); + + /* * Actions */ @@ -153,8 +157,10 @@ $sql.= " ".MAIN_DB_PREFIX."societe as s,"; if (!$user->rights->societe->client->voir && !$socid) $sql .= " ".MAIN_DB_PREFIX."societe_commerciaux as sc,"; $sql.= " ".MAIN_DB_PREFIX."contratdet as cd"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; +if ($search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=cd.fk_product'; $sql.= " WHERE c.entity = ".$conf->entity; $sql.= " AND c.rowid = cd.fk_contrat"; +if ($search_product_category > 0) $sql.=" AND cp.fk_categorie = ".$search_product_category; $sql.= " AND c.fk_soc = s.rowid"; if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; if ($mode == "0") $sql.= " AND cd.statut = 0"; @@ -206,17 +212,67 @@ if ($resql) if ($filter_date2 != '') $param.='&op2day='.$op2day.'&op2month='.$op2month.'&op2year='.$op2year; if ($filter_datecloture != '') $param.='&opclotureday='.$op2day.'&opcloturemonth='.$op2month.'&opclotureyear='.$op2year; + // List of mass actions available + $arrayofmassactions = array( + //'presend'=>$langs->trans("SendByMail"), + //'builddoc'=>$langs->trans("PDFMerge"), + ); + //if ($user->rights->contrat->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete"); + //if ($massaction == 'presend') $arrayofmassactions=array(); + $massactionbutton=$form->selectMassAction('', $arrayofmassactions); + + print ''; + if ($optioncss != '') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $title=$langs->trans("ListOfServices"); if ($mode == "0") $title=$langs->trans("ListOfInactiveServices"); // Must use == "0" if ($mode == "4" && $filter != "expired") $title=$langs->trans("ListOfRunningServices"); if ($mode == "4" && $filter == "expired") $title=$langs->trans("ListOfExpiredServices"); if ($mode == "5") $title=$langs->trans("ListOfClosedServices"); - print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder,'',$num,$totalnboflines,'title_commercial.png'); - - print ''; - print ''; - print '
'.$langs->trans("Ref").''; print $form->showrefnav($object,'id', $linkback); print '
'.$langs->trans("MailTitle").''.$object->titre.'
'.$langs->trans("MailTitle").''.$object->titre.'
'.$langs->trans("MailFrom").''.dol_print_email($object->email_from,0,0,0,0,1).'
'.$langs->trans("Status").''.$object->getLibStatut(4); +/* print '
'.$langs->trans("Status").''.$object->getLibStatut(4); if ($object->statut == 2) print ' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.')'; print '
'; print $langs->trans("TotalNbOfDistinctRecipients"); @@ -441,15 +448,15 @@ if ($object->fetch($id) >= 0) print '
'; - print ''; + print ''; print ''; - print ''; + print ''; print ''; - print ''; + print ''; print ''; diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index 6a7ae2cefbe..79201115ea1 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -33,7 +33,8 @@ class Mailing extends CommonObject { public $element='mailing'; public $table_element='mailing'; - + public $picto='email'; + var $titre; var $sujet; var $body; diff --git a/htdocs/comm/mailing/index.php b/htdocs/comm/mailing/index.php index bf7c4624c1e..ba8c2481411 100644 --- a/htdocs/comm/mailing/index.php +++ b/htdocs/comm/mailing/index.php @@ -56,10 +56,10 @@ print ''; print ''; print ''; print ''; +print $langs->trans("Ref").':'; print ''; print ''; +print $langs->trans("Other").':'; print "
'.$langs->trans("SearchAMailing").'
'; -print $langs->trans("Ref").':
'; -print $langs->trans("Other").':

\n"; diff --git a/htdocs/comm/mailing/info.php b/htdocs/comm/mailing/info.php index 77245f74766..5280fcfad59 100644 --- a/htdocs/comm/mailing/info.php +++ b/htdocs/comm/mailing/info.php @@ -43,24 +43,33 @@ llxHeader('',$langs->trans("Mailing"),'EN:Module_EMailing|FR:Module_Mailing|ES:M $form = new Form($db); -$mil = new Mailing($db); +$object = new Mailing($db); -if ($mil->fetch($_REQUEST["id"]) >= 0) +if ($object->fetch($_REQUEST["id"]) >= 0) { - $head = emailing_prepare_head($mil); + $head = emailing_prepare_head($object); dol_fiche_head($head, 'info', $langs->trans("Mailing"), 0, 'email'); + $linkback = ''.$langs->trans("BackToList").''; - print '
'; - $mil->user_creation=$mil->user_creat; - $mil->date_creation=$mil->date_creat; - $mil->user_validation=$mil->user_valid; - $mil->date_validation=$mil->date_valid; - dol_print_object_info($mil); - print '
'; + $morehtmlright=''; + if ($object->statut == 2) $morehtmlright.=' ('.$object->countNbOfTargets('alreadysent').'/'.$object->nbemail.') '; + + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', '', '', 0, '', $morehtmlright); + + print '

'; + + //print '
'; + $object->user_creation=$object->user_creat; + $object->date_creation=$object->date_creat; + $object->user_validation=$object->user_valid; + $object->date_validation=$object->date_valid; + dol_print_object_info($object, 0); + //print '
'; + - print ''; + dol_fiche_end(); } llxFooter(); diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index f000e4ce201..c9931ac6f2a 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -371,7 +371,7 @@ class Orders extends DolibarrApi } $request_data = (object) $request_data; $updateRes = $this->commande->deleteline(DolibarrApiAccess::$user,$lineid); - if ($updateRes == 1) { + if ($updateRes > 0) { return $this->get($id); } return false; diff --git a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php index ce94e4a1212..781f5609915 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php @@ -24,16 +24,21 @@ load("bills"); +$total=0; $ilink=0; $var=true; -$total=0; foreach($linkedObjectBlock as $key => $objectlink) { - $var=!$var; + $ilink++; + $var=!$var; + $trclass=($var?'pair':'impair'); + if ($ilink == count($linkedObjectBlock) && empty($noMoreLinkedObjectBlockAfter) && count($linkedObjectBlock) <= 1) $trclass.=' liste_sub_total'; ?>
trans("RepeatableInvoice"); ?>
'.$langs->trans("Search").'
'; + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $totalnboflines, 'title_commercial.png', 0, '', '', $limit); + if ($sall) + { + foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); + print $langs->trans("FilterOnInto", $sall) . join(', ',$fieldstosearchall); + } + + $morefilter = ''; + + // If the user can view categories of products + if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights->service->lire)) + { + include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $moreforfilter.='
'; + $moreforfilter.=$langs->trans('IncludingProductWithTag'). ': '; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, null, 'parent', null, null, 1); + $moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, '', 1); + $moreforfilter.='
'; + } + + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; + else $moreforfilter = $hookmanager->resPrint; + + + if (! empty($moreforfilter)) + { + print '
'; + print $moreforfilter; + print '
'; + } + + $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; + $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + + print '
'."\n"; + print ''; print_liste_field_titre($langs->trans("Contract"),$_SERVER["PHP_SELF"], "c.rowid",$param,"","",$sortfield,$sortorder); print_liste_field_titre($langs->trans("Service"),$_SERVER["PHP_SELF"], "p.description",$param,"","",$sortfield,$sortorder); diff --git a/htdocs/contrat/tpl/linkedobjectblock.tpl.php b/htdocs/contrat/tpl/linkedobjectblock.tpl.php index aa8d83bb803..9ea21f890fc 100644 --- a/htdocs/contrat/tpl/linkedobjectblock.tpl.php +++ b/htdocs/contrat/tpl/linkedobjectblock.tpl.php @@ -13,7 +13,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * */ ?> @@ -22,19 +21,23 @@ load("contracts"); +$total=0; $ilink=0; $var=true; foreach($linkedObjectBlock as $key => $objectlink) { - $objectlink->fetch_lines(); - $var=!$var; + $ilink++; + $var=!$var; + $trclass=($var?'pair':'impair'); + if ($ilink == count($linkedObjectBlock) && empty($noMoreLinkedObjectBlockAfter) && count($linkedObjectBlock) <= 1) $trclass.=' liste_sub_total'; ?> - > + diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 317b84e0b29..3abd7dd58b5 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -527,7 +527,7 @@ class CMailFile if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->dump_mail(); if (! empty($bounce)) $res = mail($dest,$this->encodetorfc2822($this->subject),$this->message,$this->headers, $bounce); - else $res = mail($dest,$this->encodetorfc2822($this->subject),$this->message,$this->headers); + else $res = mail($dest, $this->encodetorfc2822($this->subject), $this->message, $this->headers); if (! $res) { @@ -840,7 +840,7 @@ class CMailFile // Receiver if (isset($this->addr_cc) && $this->addr_cc) $out.= "Cc: ".$this->getValidAddress($this->addr_cc,2).$this->eol2; - if (isset($this->addr_bcc) && $this->addr_bcc) $out.= "Bcc: ".$this->getValidAddress($this->addr_bcc,2).$this->eol2; + if (isset($this->addr_bcc) && $this->addr_bcc) $out.= "Bcc: ".$this->getValidAddress($this->addr_bcc,2).$this->eol2; // Question: bcc must not be into header, only into SMTP command "RCPT TO". Does php mail support this ? // Delivery receipt if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) $out.= "Disposition-Notification-To: ".$this->getValidAddress($this->addr_from,2).$this->eol2; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 8a6c97e794c..097557de909 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -181,7 +181,14 @@ class Form else if (preg_match('/^text/',$typeofdata) || preg_match('/^note/',$typeofdata)) { $tmp=explode(':',$typeofdata); - $ret.=''; + $cols=$tmp[2]; + $morealt=''; + if (preg_match('/%/',$cols)) + { + $morealt=' style="width: '.$cols.'"'; + $cols=''; + } + $ret.=''; } else if ($typeofdata == 'day' || $typeofdata == 'datepicker') { @@ -211,9 +218,10 @@ class Form if (empty($notabletag)) $ret.=''; if (empty($notabletag)) $ret.=''; if (empty($notabletag)) $ret.='
trans("Contract"); ?> getNomUrl(1); ?> '; - $ret.=''; - if (preg_match('/ckeditor|textarea/',$typeofdata)) $ret.='
'."\n"; - $ret.=''; + else $ret.='
'; + $ret.=''; + if (preg_match('/ckeditor|textarea/',$typeofdata) && empty($notabletag)) $ret.='
'."\n"; + $ret.=''; if (empty($notabletag)) $ret.='
'."\n"; @@ -734,7 +742,7 @@ class Form } $out.= ''; - $out .= ''; + $out .= ''; if (!empty($page)) { @@ -4485,7 +4493,7 @@ class Form if ($usecalendar == "eldy") { // Zone de saisie manuelle de la date - $retstring.='trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript $retstring.='>'; @@ -4513,7 +4521,7 @@ class Form { //$retstring.='
'; // Day - $retstring.=''; + $retstring.=''; if ($emptydate || $set_time == -1) { @@ -4527,7 +4535,7 @@ class Form $retstring.=""; - $retstring.=''; + $retstring.=''; if ($emptydate || $set_time == -1) { $retstring.=''; @@ -4545,11 +4553,11 @@ class Form // Year if ($emptydate || $set_time == -1) { - $retstring.=''; + $retstring.=''; } else { - $retstring.=''; + $retstring.=''; for ($year = $syear - 5; $year < $syear + 10 ; $year++) { @@ -4566,7 +4574,7 @@ class Form if ($h) { // Show hour - $retstring.=''; + $retstring.=''; if ($emptyhours) $retstring.=''; for ($hour = 0; $hour < 24; $hour++) { @@ -4580,7 +4588,7 @@ class Form if ($m) { // Show minutes - $retstring.=''; + $retstring.=''; if ($emptyhours) $retstring.=''; for ($min = 0; $min < 60 ; $min++) { diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index a05d8b27c5e..d79eaae65f0 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -62,7 +62,7 @@ class FormFile * @param int $addcancel 1=Add 'Cancel' button * @param int $sectionid If upload must be done inside a particular ECM section * @param int $perm Value of permission to allow upload - * @param int $size Length of input file area + * @param int $size Length of input file area. Deprecated. * @param Object $object Object to use (when attachment is done on an element) * @param string $options Add an option column * @param integer $useajax Use fileupload ajax (0=never, 1=if enabled, 2=always whatever is option). 2 should never be used. @@ -106,7 +106,7 @@ class FormFile if (! empty($options)) $out .= ''.$options.''; - $out .= ''; + $out .= ''; $max=$conf->global->MAIN_UPLOAD_DOC; // En Kb $maxphp=@ini_get('upload_max_filesize'); // En inconnu @@ -121,10 +121,10 @@ class FormFile { $out .= ''; } - $out .= 'global->MAIN_UPLOAD_DOC) || empty($perm)?' disabled':''); $out .= '>'; - $out .= ' '; + $out .= ' '; $out .= 'global->MAIN_UPLOAD_DOC) || empty($perm)?' disabled':''); $out .= '>'; @@ -183,11 +183,11 @@ class FormFile $out .= '
'; $out .= '
'; if (! empty($conf->global->OPTIMIZEFORTEXTBROWSER)) $out .= ' '; - $out .= ''; + $out .= ''; $out .= '
'; $out .= '
'; if (! empty($conf->global->OPTIMIZEFORTEXTBROWSER)) $out .= ' '; - $out .= ''; + $out .= ''; $out .= ''; $out .= ''; $out .= '
'; @@ -1451,6 +1451,7 @@ class FormFile else { print ''; + print img_picto('', 'object_globe').' '; print ''; print $link->label; print ''; diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index 39a45ad783b..c8ce225e0c2 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -489,14 +489,20 @@ class SMTPs // and send it out "single file" foreach ( $this->get_RCPT_list() as $_address ) { - /* + /* Note: + * BCC email addresses must be listed in the RCPT TO command list, + * but the BCC header should not be printed under the DATA command. + * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server + */ + + /* * TODO - * After each 'RCPT TO:' is sent, we need to make sure it was kosher, - * if not, the whole message will fail - * If any email address fails, we will need to RESET the connection, - * mark the last address as "bad" and start the address loop over again. - * If any address fails, the entire message fails. - */ + * After each 'RCPT TO:' is sent, we need to make sure it was kosher, + * if not, the whole message will fail + * If any email address fails, we will need to RESET the connection, + * mark the last address as "bad" and start the address loop over again. + * If any address fails, the entire message fails. + */ $this->socket_send_str('RCPT TO: <' . $_address . '>', '250'); } @@ -1025,7 +1031,7 @@ class SMTPs /** * Returns an array of addresses for a specific type; TO, CC or BCC * - * @param string $_which Which collection of adresses to return + * @param string $_which Which collection of addresses to return ('to', 'cc', 'bcc') * @return string|false Array of emaill address */ function get_email_list($_which = null) @@ -1174,9 +1180,17 @@ class SMTPs if ( $this->getCC() ) $_header .= 'Cc: ' . $this->getCC() . "\r\n"; + /* Note: + * BCC email addresses must be listed in the RCPT TO command list, + * but the BCC header should not be printed under the DATA command. + * So it is included into the function sendMsg() but not here. + * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server + */ + /* if ( $this->getBCC() ) $_header .= 'Bcc: ' . $this->getBCC() . "\r\n"; - + */ + $host=$this->getHost(); $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index a5866527b50..e99a6913773 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -1159,7 +1159,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= $out.=''; } $out.=getTitleFieldOfList($langs->trans("Ref"), 0, $_SERVER["PHP_SELF"], 'a.id', '', $param, '', $sortfield, $sortorder); - $out.=''.$langs->trans("Label").''; + $out.=''.$langs->trans("Label").''; $out.=getTitleFieldOfList($langs->trans("Date"), 0, $_SERVER["PHP_SELF"], 'a.datep, a.id', '', $param, '', $sortfield, $sortorder); $out.=''.$langs->trans("Type").''; $out.=''; @@ -1176,7 +1176,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= $out.=''; } $out.=''; - $out.=''; + $out.=''; $out.=''; $out.=''; $out.=$formactions->select_type_actions($actioncode, "actioncode", '', empty($conf->global->AGENDA_USE_EVENT_TYPE)?1:-1, 0, 0, 1); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index b1a9c0b2735..d102e264913 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2241,14 +2241,14 @@ function dol_trunc($string,$size=40,$trunc='right',$stringencoding='UTF-8',$nodo * Example: picto.png if picto.png is stored into htdocs/theme/mytheme/img * Example: picto.png@mymodule if picto.png is stored into htdocs/mymodule/img * Example: /mydir/mysubdir/picto.png if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1) - * @param string $options Add more attribute on img tag (For example 'style="float: right"') + * @param string $morealt Add more attribute on img tag (For example 'style="float: right"') * @param int $pictoisfullpath If 1, image path is a full path * @param int $srconly Return only content of the src attribute of img. * @param int $notitle 1=Disable tag title. Use it if you add js tooltip, to avoid duplicate tooltip. * @return string Return img tag * @see #img_object, #img_picto_common */ -function img_picto($titlealt, $picto, $options = '', $pictoisfullpath = false, $srconly=0, $notitle=0) +function img_picto($titlealt, $picto, $morealt = '', $pictoisfullpath = false, $srconly=0, $notitle=0) { global $conf; @@ -2300,7 +2300,7 @@ function img_picto($titlealt, $picto, $options = '', $pictoisfullpath = false, $ if (preg_match('/:[^\s0-9]/',$titlealt)) $tmparray=explode(':',$titlealt); // We explode if we have TextA:TextB. Not if we have TextA: TextB $title=$tmparray[0]; $alt=empty($tmparray[1])?'':$tmparray[1]; - return ''.dol_escape_htmltag($alt).''; // Alt is used for accessibility, title for popup + return ''.dol_escape_htmltag($alt).''; // Alt is used for accessibility, title for popup } } @@ -2310,16 +2310,16 @@ function img_picto($titlealt, $picto, $options = '', $pictoisfullpath = false, $ * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. * @param string $picto Name of image to show object_picto (example: user, group, action, bill, contract, propal, product, ...) * For external modules use imagename@mymodule to search into directory "img" of module. - * @param string $options Add more attribute on img tag (ie: class="datecallink") + * @param string $morealt Add more attribute on img tag (ie: class="datecallink") * @param int $pictoisfullpath If 1, image path is a full path * @param int $srconly Return only content of the src attribute of img. * @param int $notitle 1=Disable tag title. Use it if you add js tooltip, to avoid duplicate tooltip. * @return string Return img tag * @see #img_picto, #img_picto_common */ -function img_object($titlealt, $picto, $options = '', $pictoisfullpath = false, $srconly=0, $notitle=0) +function img_object($titlealt, $picto, $morealt = '', $pictoisfullpath = false, $srconly=0, $notitle=0) { - return img_picto($titlealt, 'object_'.$picto, $options, $pictoisfullpath, $srconly, $notitle); + return img_picto($titlealt, 'object_'.$picto, $morealt, $pictoisfullpath, $srconly, $notitle); } /** @@ -2327,12 +2327,12 @@ function img_object($titlealt, $picto, $options = '', $pictoisfullpath = false, * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. * @param string $picto Name of image file to show (If no extension provided, we use '.png'). Image must be stored into htdocs/theme/common directory. - * @param string $options Add more attribute on img tag + * @param string $morealt Add more attribute on img tag * @param int $pictoisfullpath If 1, image path is a full path * @return string Return img tag * @see #img_object, #img_picto */ -function img_weather($titlealt, $picto, $options = '', $pictoisfullpath = 0) +function img_weather($titlealt, $picto, $morealt = '', $pictoisfullpath = 0) { global $conf; @@ -2340,7 +2340,7 @@ function img_weather($titlealt, $picto, $options = '', $pictoisfullpath = 0) $path = DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/weather/'.$picto; - return img_picto($titlealt, $path, $options, 1); + return img_picto($titlealt, $path, $morealt, 1); } /** @@ -2348,12 +2348,12 @@ function img_weather($titlealt, $picto, $options = '', $pictoisfullpath = 0) * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. * @param string $picto Name of image file to show (If no extension provided, we use '.png'). Image must be stored into htdocs/theme/common directory. - * @param string $options Add more attribute on img tag + * @param string $morealt Add more attribute on img tag * @param int $pictoisfullpath If 1, image path is a full path * @return string Return img tag * @see #img_object, #img_picto */ -function img_picto_common($titlealt, $picto, $options = '', $pictoisfullpath = 0) +function img_picto_common($titlealt, $picto, $morealt = '', $pictoisfullpath = 0) { global $conf; @@ -2372,7 +2372,7 @@ function img_picto_common($titlealt, $picto, $options = '', $pictoisfullpath = 0 } } - return img_picto($titlealt, $path, $options, 1); + return img_picto($titlealt, $path, $morealt, 1); } /** @@ -2478,9 +2478,9 @@ function img_view($titlealt = 'default', $float = 0, $other = '') if ($titlealt == 'default') $titlealt = $langs->trans('View'); - $options = ($float ? 'style="float: right" ' : '').$other; + $morealt = ($float ? 'style="float: right" ' : '').$other; - return img_picto($titlealt, 'view.png', $options); + return img_picto($titlealt, 'view.png', $morealt); } /** @@ -2552,16 +2552,16 @@ function img_info($titlealt = 'default') * Show warning logo * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. - * @param string $options Add more attribute on img tag (For example 'style="float: right"'). If 1 + * @param string $morealt Add more attribute on img tag (For example 'style="float: right"'). If 1 * @return string Return img tag */ -function img_warning($titlealt = 'default', $options = '') +function img_warning($titlealt = 'default', $morealt = '') { global $conf, $langs; if ($titlealt == 'default') $titlealt = $langs->trans('Warning'); - return img_picto($titlealt, 'warning.png', 'class="pictowarning"'.($options ? ($options == '1' ? ' style="float: right"' : ' '.$options): '')); + return img_picto($titlealt, 'warning.png', 'class="pictowarning"'.($morealt ? ($morealt == '1' ? ' style="float: right"' : ' '.$morealt): '')); } /** @@ -2583,32 +2583,32 @@ function img_error($titlealt = 'default') * Show next logo * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. -* @param string $options Add more attribute on img tag (For example 'style="float: right"') +* @param string $morealt Add more attribute on img tag (For example 'style="float: right"') * @return string Return img tag */ -function img_next($titlealt = 'default', $options='') +function img_next($titlealt = 'default', $morealt='') { global $conf, $langs; if ($titlealt == 'default') $titlealt = $langs->trans('Next'); - return img_picto($titlealt, 'next.png', $options); + return img_picto($titlealt, 'next.png', $morealt); } /** * Show previous logo * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. - * @param string $options Add more attribute on img tag (For example 'style="float: right"') + * @param string $morealt Add more attribute on img tag (For example 'style="float: right"') * @return string Return img tag */ -function img_previous($titlealt = 'default', $options='') +function img_previous($titlealt = 'default', $morealt='') { global $conf, $langs; if ($titlealt == 'default') $titlealt = $langs->trans('Previous'); - return img_picto($titlealt, 'previous.png', $options); + return img_picto($titlealt, 'previous.png', $morealt); } /** @@ -2650,16 +2650,16 @@ function img_up($titlealt = 'default', $selected = 0, $moreclass='') * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. * @param int $selected Selected - * @param string $options Add more attribute on img tag (For example 'style="float: right"') + * @param string $morealt Add more attribute on img tag (For example 'style="float: right"') * @return string Return img tag */ -function img_left($titlealt = 'default', $selected = 0, $options='') +function img_left($titlealt = 'default', $selected = 0, $morealt='') { global $conf, $langs; if ($titlealt == 'default') $titlealt = $langs->trans('Left'); - return img_picto($titlealt, ($selected ? '1leftarrow_selected.png' : '1leftarrow.png'), $options); + return img_picto($titlealt, ($selected ? '1leftarrow_selected.png' : '1leftarrow.png'), $morealt); } /** @@ -2667,16 +2667,16 @@ function img_left($titlealt = 'default', $selected = 0, $options='') * * @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. * @param int $selected Selected - * @param string $options Add more attribute on img tag (For example 'style="float: right"') + * @param string $morealt Add more attribute on img tag (For example 'style="float: right"') * @return string Return img tag */ -function img_right($titlealt = 'default', $selected = 0, $options='') +function img_right($titlealt = 'default', $selected = 0, $morealt='') { global $conf, $langs; if ($titlealt == 'default') $titlealt = $langs->trans('Right'); - return img_picto($titlealt, ($selected ? '1rightarrow_selected.png' : '1rightarrow.png'), $options); + return img_picto($titlealt, ($selected ? '1rightarrow_selected.png' : '1rightarrow.png'), $morealt); } /** diff --git a/htdocs/core/tpl/contacts.tpl.php b/htdocs/core/tpl/contacts.tpl.php index 28a02fcd38a..845bc30ce13 100644 --- a/htdocs/core/tpl/contacts.tpl.php +++ b/htdocs/core/tpl/contacts.tpl.php @@ -110,11 +110,10 @@ if ($permission) {
socid; ?> dol_use_jmobile)) + // add company icon before select list + if ($selectedCompany) { - $companystatic->fetch($selectedCompany); - echo $companystatic->getNomUrl(2, '', 0, 1); + echo img_object('', 'company', 'class="hideonsmartphone"'); } ?> selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany', '', 0); ?> diff --git a/htdocs/core/tpl/notes.tpl.php b/htdocs/core/tpl/notes.tpl.php index bc7cf44ce66..c971a49148f 100644 --- a/htdocs/core/tpl/notes.tpl.php +++ b/htdocs/core/tpl/notes.tpl.php @@ -63,8 +63,8 @@ elseif ($module == 'shipping') { $permission=$user->rights->expedition->cr elseif ($module == 'product') { $permission=$user->rights->produit->creer;} //else dol_print_error('','Bad value '.$module.' for param module'); -if (! empty($conf->global->FCKEDITOR_ENABLE_SOCIETE)) $typeofdata='ckeditor:dolibarr_notes:100%:200::1:12:100'; // Rem: This var is for all notes, not only thirdparties note. -else $typeofdata='textarea:12:100'; +if (! empty($conf->global->FCKEDITOR_ENABLE_SOCIETE)) $typeofdata='ckeditor:dolibarr_notes:100%:200::1:12:95%'; // Rem: This var is for all notes, not only thirdparties note. +else $typeofdata='textarea:12:95%'; ?> @@ -72,14 +72,14 @@ else $typeofdata='textarea:12:100';
-
>editfieldkey("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, $moreparam); ?>
-
editfieldval("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, '', null, null, $moreparam); ?>
+
>editfieldkey("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, $moreparam, '', 0); ?>
+
editfieldval("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, '', null, null, $moreparam, 1); ?>
societe_id)) { ?>
-
>editfieldkey("NotePrivate", $note_private, $value_private, $object, $permission, $typeofdata, $moreparam); ?>
-
editfieldval("NotePrivate", $note_private, $value_private, $object, $permission, $typeofdata, '', null, null, $moreparam); ?>
+
>editfieldkey("NotePrivate", $note_private, $value_private, $object, $permission, $typeofdata, $moreparam, '', 0); ?>
+
editfieldval("NotePrivate", $note_private, $value_private, $object, $permission, $typeofdata, '', null, null, $moreparam, 1); ?>
diff --git a/htdocs/don/index.php b/htdocs/don/index.php index 9894de3a2b5..5e4b2966051 100644 --- a/htdocs/don/index.php +++ b/htdocs/don/index.php @@ -96,7 +96,7 @@ if (count($listofsearchfields)) { if ($i == 0) print ''.$langs->trans("Search").''; print ''; - print ''; + print ''; if ($i == 0) print ''; print ''; $i++; diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php index 729543eff56..dd37c86592a 100644 --- a/htdocs/ecm/search.php +++ b/htdocs/ecm/search.php @@ -140,9 +140,9 @@ print ''; print ''; print ""; print ''; -print "'; -print "'; -print "'; +print "'; +print "'; +print "'; print "'; print "
'.$langs->trans("ECMSearchByKeywords").'
".$langs->trans("Ref").':
".$langs->trans("Title").':
".$langs->trans("Keyword").':
".$langs->trans("Ref").':
".$langs->trans("Title").':
".$langs->trans("Keyword").':
"; //print $langs->trans("ECMSectionManualDesc"); diff --git a/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php b/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php index 5afde3a4427..ff16f267431 100644 --- a/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php +++ b/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php @@ -52,7 +52,8 @@ foreach($linkedObjectBlock as $key => $objectlink) getLibStatut(3); ?> ">transnoentitiesnoconv("RemoveLink")); ?> - 1) { ?> diff --git a/htdocs/fourn/facture/tpl/linkedobjectblock.tpl.php b/htdocs/fourn/facture/tpl/linkedobjectblock.tpl.php index 4df741b8ad4..2ab3b4d215b 100644 --- a/htdocs/fourn/facture/tpl/linkedobjectblock.tpl.php +++ b/htdocs/fourn/facture/tpl/linkedobjectblock.tpl.php @@ -54,6 +54,7 @@ foreach($linkedObjectBlock as $key => $objectlink) ">transnoentitiesnoconv("RemoveLink")); ?> 1) { ?> diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql index 1e0f92a1cac..faffe9e53f5 100644 --- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql +++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql @@ -202,3 +202,17 @@ create table llx_user_employment )ENGINE=innodb; + + +-- Sequence to removed duplicated values of llx_links. Use serveral times if you still have duplicate. +drop table tmp_links_double; +--select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2; +create table tmp_links_double as (select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2); +--select * from tmp_links_double; +delete from llx_links where (rowid, label) in (select max_rowid, label from tmp_links_double); --update to avoid duplicate, delete to delete +drop table tmp_links_double; + +ALTER TABLE llx_links ADD UNIQUE INDEX uk_links (objectid,label); + + + diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 99e4a7c556c..3ba06daabce 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -176,6 +176,7 @@ update llx_opensurvey_sondage set format = 'D' where format = 'D+'; update llx_opensurvey_sondage set format = 'A' where format = 'A+'; update llx_opensurvey_sondage set tms = now(); + -- ALTER TABLE llx_facture_fourn ALTER COLUMN fk_cond_reglement DROP NOT NULL; @@ -183,12 +184,21 @@ update llx_product set barcode = null where barcode in ('', '-1', '0'); update llx_societe set barcode = null where barcode in ('', '-1', '0'); +-- Sequence to removed duplicated values of llx_links. Use serveral times if you still have duplicate. +drop table tmp_links_double; +--select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2; +create table tmp_links_double as (select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2); +--select * from tmp_links_double; +delete from llx_links where (rowid, label) in (select max_rowid, label from tmp_links_double); --update to avoid duplicate, delete to delete +drop table tmp_links_double; + + -- Sequence to removed duplicated values of barcode in llx_product. Use serveral times if you still have duplicate. drop table tmp_product_double; --select barcode, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_product where barcode is not null group by barcode having count(rowid) >= 2; create table tmp_product_double as (select barcode, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_product where barcode is not null group by barcode having count(rowid) >= 2); --select * from tmp_product_double; -update llx_product set barcode = null where (rowid, barcode) in (select max_rowid, barcode from tmp_product_double); +update llx_product set barcode = null where (rowid, barcode) in (select max_rowid, barcode from tmp_product_double); --update to avoid duplicate, delete to delete drop table tmp_product_double; diff --git a/htdocs/install/mysql/tables/llx_links.key.sql b/htdocs/install/mysql/tables/llx_links.key.sql new file mode 100644 index 00000000000..7ba509e9d58 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_links.key.sql @@ -0,0 +1,22 @@ +-- ======================================================================== +-- Copyright (C) 2016 Laurent Destailleur +-- +-- 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 . +-- +-- +-- Linked files +-- ======================================================================== + +ALTER TABLE llx_links ADD UNIQUE INDEX uk_links (objectid,label); + diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 27d86696b82..f57dcfdc69d 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1626,7 +1626,7 @@ AddOtherPagesOrServices=Add other pages or services AddModels=Add document or numbering templates AddSubstitutions=Add keys substitutions DetectionNotPossible=Detection not possible -UrlToGetKeyToUseAPIs=Url to get token to use API (once token has been received it is saved on database user table and will be checked on each future access) +UrlToGetKeyToUseAPIs=Url to get token to use API (once token has been received it is saved on database user table and must be provided on each API call) ListOfAvailableAPIs=List of available APIs activateModuleDependNotSatisfied=Module "%s" depends on module "%s" that is missing, so module "%1$s" may not work correclty. Please install module "%2$s" or disable module "%1$s" if you want to be safe from any surprise CommandIsNotInsideAllowedCommands=The command you try to run is not inside list of allowed commands defined into parameter $dolibarr_main_restrict_os_commands into conf.php file. diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 45e8246261a..1c1a3bf3245 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -50,7 +50,6 @@ NbOfEMails=Nb of EMails TotalNbOfDistinctRecipients=Number of distinct recipients NoTargetYet=No recipients defined yet (Go on tab 'Recipients') RemoveRecipient=Remove recipient -CommonSubstitutions=Common substitutions YouCanAddYourOwnPredefindedListHere=To create your email selector module, see htdocs/core/modules/mailings/README. EMailTestSubstitutionReplacedByGenericValues=When using test mode, substitutions variables are replaced by generic values MailingAddFile=Attach this file diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index c123fed51a5..245f6f3ccc0 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -13,7 +13,7 @@ ListOfValidatedPublicMembers=List of validated public members ErrorThisMemberIsNotPublic=This member is not public ErrorMemberIsAlreadyLinkedToThisThirdParty=Another member (name: %s, login: %s) is already linked to a third party %s. Remove this link first because a third party can't be linked to only a member (and vice versa). ErrorUserPermissionAllowsToLinksToItselfOnly=For security reasons, you must be granted permissions to edit all users to be able to link a member to a user that is not yours. -ThisIsContentOfYourCard=This is details of your card +ThisIsContentOfYourCard=Hi.

This is a remind of the information we get about you. Feel free to contact us if something looks wrong.

CardContent=Content of your member card SetLinkToUser=Link to a Dolibarr user SetLinkToThirdParty=Link to a Dolibarr third party diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 8a09c66989e..4a002fab02c 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -8,7 +8,7 @@ EditPassword=Edit password SendNewPassword=Regenerate and send password ReinitPassword=Regenerate password PasswordChangedTo=Password changed to: %s -SubjectNewPassword=Your new password for Dolibarr +SubjectNewPassword=Your new password for %s GroupRights=Group permissions UserRights=User permissions UserGUISetup=User display setup diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 9277de5b498..0b48be2b0d5 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -110,7 +110,7 @@ print ''; print ''; print ''; - print ''.$langs->trans("InventoryCode").''; + print ''.$langs->trans("InventoryCode").''; print ''; print ''; diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index 98fe80f7c90..dfddd1e19f1 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -117,7 +117,7 @@ print ''; print ''; print ''; - print ''.$langs->trans("InventoryCode").''; + print ''.$langs->trans("InventoryCode").''; print ''; print ''; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index f4c5d871fc6..5e639f6c920 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -698,7 +698,7 @@ else // Label print ''.$langs->trans("Label").''; - print ''; + print ''; // Thirdparty if ($conf->societe->enabled) @@ -752,7 +752,7 @@ else // Date start print ''.$langs->trans("DateStart").''; print $form->select_date($object->date_start?$object->date_start:-1,'projectstart',0,0,0,'',1,0,1); - print '     '. $langs->trans("ProjectReportDate"); print ''; @@ -829,33 +829,12 @@ else print ''; - // Ref - /* - print ''; - */ - - // Label - //print ''; - - // Third party - /* - print ''; - */ - // Visibility print ''; - // Statut - //print ''; - if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { // Opportunity status @@ -879,7 +858,11 @@ else print ''; // Budget diff --git a/htdocs/projet/class/api_projects.class.php b/htdocs/projet/class/api_projects.class.php new file mode 100644 index 00000000000..74650407f87 --- /dev/null +++ b/htdocs/projet/class/api_projects.class.php @@ -0,0 +1,568 @@ + + * Copyright (C) 2016 Laurent Destailleur + * + * 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 . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + +/** + * API class for projects + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Projects extends DolibarrApi +{ + + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'ref', + 'title' + ); + + /** + * @var Project $project {@type Project} + */ + public $project; + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->project = new Project($this->db); + } + + /** + * Get properties of a project object + * + * Return an array with project informations + * + * @param int $id ID of project + * @return array|mixed data without useless information + * + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $this->project->fetchObjectLinked(); + return $this->_cleanObjectDatas($this->project); + } + + + + /** + * List projects + * + * Get a list of projects + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $thirdparty_ids Thirdparty ids to filter projects of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i} + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of project objects + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + // case of external user, $thirdpartyid param is ignored and replaced by user's socid + $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT t.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."projet as t"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + + $sql.= ' WHERE t.entity IN ('.getEntity('project', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")"; + if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + dol_syslog("API Rest request"); + $result = $db->query($sql); + + if ($result) + { + $num = $db->num_rows($result); + while ($i < min($num, ($limit <= 0 ? $num : $limit))) + { + $obj = $db->fetch_object($result); + $project_static = new Project($db); + if($project_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($project_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve project list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No project found'); + } + return $obj_ret; + } + + /** + * Create project object + * + * @param array $request_data Request data + * @return int ID of project + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401, "Insuffisant rights"); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->project->$field = $value; + } + /*if (isset($request_data["lines"])) { + $lines = array(); + foreach ($request_data["lines"] as $line) { + array_push($lines, (object) $line); + } + $this->project->lines = $lines; + }*/ + if ($this->project->create(DolibarrApiAccess::$user) <= 0) { + $errormsg = $this->project->error; + throw new RestException(500, $errormsg ? $errormsg : "Error while creating project"); + } + + return $this->project->id; + } + + /** + * Get tasks of a project + * + * @param int $id Id of project + * + * @url GET {id}/tasks + * + * @return int + */ + function getLines($id) { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $this->project->getLinesArray(DolibarrApiAccess::$user); + $result = array(); + foreach ($this->project->lines as $line) { + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + + + /** + * Get users and roles assigned to a project + * + * @param int $id Id of project + * + * @url GET {id}/roles + * + * @return int + */ + function getRoles($id) { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $taskstatic=new Task($this->db); + $this->project->roles = $taskstatic->getUserRolesForProjectsOrTasks(DolibarrApiAccess::$user, 0, $id, 0); + $result = array(); + foreach ($this->project->roles as $line) { + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + + + /** + * Add a task to given project + * + * @param int $id Id of project to update + * @param array $request_data Projectline data + * + * @url POST {id}/tasks + * + * @return int + */ + /* + function postLine($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->addline( + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + $request_data->fk_product, + $request_data->remise_percent, + $request_data->info_bits, + $request_data->fk_remise_except, + 'HT', + 0, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->rang, + $request_data->special_code, + $fk_parent_line, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->array_options, + $request_data->fk_unit, + $this->element, + $request_data->id + ); + + if ($updateRes > 0) { + return $this->get($id)->line->rowid; + + } + return false; + } + */ + + /** + * Update a task to given project + * + * @param int $id Id of project to update + * @param int $lineid Id of line to update + * @param array $request_data Projectline data + * + * @url PUT {id}/tasks/{lineid} + * + * @return object + */ + /* + function putLine($id, $lineid, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->updateline( + $lineid, + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->remise_percent, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + 'HT', + $request_data->info_bits, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->fk_parent_line, + 0, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->special_code, + $request_data->array_options, + $request_data->fk_unit + ); + + if ($updateRes > 0) { + $result = $this->get($id); + unset($result->line); + return $this->_cleanObjectDatas($result); + } + return false; + }*/ + + + /** + * Delete a tasks of given project + * + * + * @param int $id Id of project to update + * @param int $taskid Id of task to delete + * + * @url DELETE {id}/tasks/{taskid} + * + * @return int + */ + function delLine($id, $taskid) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! ($result > 0) ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $taskstatic=new Task($this->db); + $result = $taskstatic->fetch($taskid); + if( ! ($result > 0) ) { + throw new RestException(404, 'Task not found'); + } + + $deleteRes = $taskstatic->delete(DolibarrApiAccess::$user); + + if( ! ($deleteRes > 0)) { + throw new RestException(500, 'Error when delete tasks : '.$taskstatic->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Task deleted' + ) + ); + } + + + /** + * Update project general fields (won't touch lines of project) + * + * @param int $id Id of project to update + * @param array $request_data Datas + * + * @return int + */ + function put($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + foreach($request_data as $field => $value) { + $this->project->$field = $value; + } + + if($this->project->update(DolibarrApiAccess::$user, 0)) + return $this->get($id); + + return false; + } + + /** + * Delete project + * + * @param int $id Project ID + * + * @return array + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->projet->supprimer) { + throw new RestException(401); + } + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( ! $this->project->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when delete project : '.$this->project->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Project deleted' + ) + ); + + } + + /** + * Validate a project + * + * @param int $id Project ID + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * + * @url POST {id}/validate + * + * @return array + * FIXME An error 403 is returned if the request has an empty body. + * Error message: "Forbidden: Content type `text/plain` is not supported." + * Workaround: send this in the body + * { + * "notrigger": 0 + * } + */ + function validate($id, $notrigger=0) + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->project->setValid(DolibarrApiAccess::$user, $notrigger); + if ($result == 0) { + throw new RestException(500, 'Error nothing done. May be object is already validated'); + } + if ($result < 0) { + throw new RestException(500, 'Error when validating Project: '.$this->project->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Project validated' + ) + ); + } + + /** + * Validate fields before create or update object + * + * @param array $data Array with data to verify + * @return array + * @throws RestException + */ + function _validate($data) + { + $object = array(); + foreach (self::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $object[$field] = $data[$field]; + + } + return $object; + } + + + // TODO + // getSummaryOfTimeSpent +} diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 4ac568182de..cdddccbf432 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -241,7 +241,15 @@ class Project extends CommonObject $this->description = trim($this->description); if ($this->opp_amount < 0) $this->opp_amount=''; if ($this->opp_percent < 0) $this->opp_percent=''; - + if ($this->date_end && $this->date_end < $this->date_start) + { + $this->error = $langs->trans("ErrorDateEndLowerThanDateStart"); + $this->errors[] = $this->error; + $this->db->rollback(); + dol_syslog(get_class($this)."::update error -3 " . $this->error, LOG_ERR); + return -3; + } + if (dol_strlen(trim($this->ref)) > 0) { $this->db->begin(); @@ -695,10 +703,11 @@ class Project extends CommonObject /** * Validate a project * - * @param User $user User that validate - * @return int <0 if KO, >0 if OK + * @param User $user User that validate + * @param int $notrigger 1=Disable triggers + * @return int <0 if KO, >0 if OK */ - function setValid($user) + function setValid($user, $notrigger=0) { global $langs, $conf; @@ -725,10 +734,13 @@ class Project extends CommonObject if ($resql) { // Call trigger - $result=$this->call_trigger('PROJECT_VALIDATE',$user); - if ($result < 0) { $error++; } - // End call triggers - + if (empty($notrigger)) + { + $result=$this->call_trigger('PROJECT_VALIDATE',$user); + if ($result < 0) { $error++; } + // End call triggers + } + if (!$error) { $this->statut=1; @@ -1750,12 +1762,12 @@ class Project extends CommonObject global $conf; if (! ($this->statut == 1)) return false; - if (! $this->datee) return false; + if (! $this->datee && ! $this->date_end) return false; $now = dol_now(); - return $this->datee < ($now - $conf->projet->warning_delay); - } + return ($this->datee ? $this->datee : $this->date_end) < ($now - $conf->projet->warning_delay); + } /** @@ -1866,5 +1878,20 @@ class Project extends CommonObject return 1; } + + /** + * Create an array of tasks of current project + * + * @param User $user Object user we want project allowed to + * @return int >0 if OK, <0 if KO + */ + function getLinesArray($user) + { + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $taskstatic = new Task($this->db); + + $this->lines = $taskstatic->getTasksArray(0, $user, $this->id, 0, 0); + } + } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index ad2f5faecbe..2baccfb3382 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -176,7 +176,7 @@ class Task extends CommonObject * * @param int $id Id object * @param int $ref ref object - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, 0 if not found, >0 if OK */ function fetch($id,$ref='') { @@ -214,7 +214,9 @@ class Task extends CommonObject $resql=$this->db->query($sql); if ($resql) { - if ($this->db->num_rows($resql)) + $num_rows = $this->db->num_rows($resql); + + if ($num_rows) { $obj = $this->db->fetch_object($resql); @@ -241,7 +243,8 @@ class Task extends CommonObject $this->db->free($resql); - return 1; + if ($num_rows) return 1; + else return 0; } else { @@ -754,7 +757,7 @@ class Task extends CommonObject * Return list of roles for a user for each projects or each tasks (or a particular project or a particular task). * * @param User $userp Return roles on project for this internal user. If set, usert and taskid must not be defined. - * @param User $usert Return roles on task for this internal user. If set userp must not be defined. + * @param User $usert Return roles on task for this internal user. If set userp must not be defined. -1 means no filter. * @param int $projectid Project id list separated with , to filter on project * @param int $taskid Task id to filter on a task * @param string $filteronprojstatus Filter on project status if userp is set. Not used if userp not defined. diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 787d902768d..8c2c8909a84 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -626,7 +626,7 @@ while ($i < min($num,$limit)) $projectstatic->user_author_id = $obj->fk_user_creat; $projectstatic->public = $obj->public; $projectstatic->ref = $obj->ref; - $projectstatic->datee = $obj->date_end; + $projectstatic->datee = $db->jdate($obj->date_end); $projectstatic->statut = $obj->fk_statut; $projectstatic->opp_status = $obj->fk_opp_status; diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index f1368099864..0edce826479 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -71,7 +71,6 @@ $dol_hide_topmenu=$conf->dol_hide_topmenu; $dol_hide_leftmenu=$conf->dol_hide_leftmenu; $dol_optimize_smallscreen=$conf->dol_optimize_smallscreen; $dol_no_mouse_hover=$conf->dol_no_mouse_hover; -$dol_use_jmobile=$conf->dol_use_jmobile; //$conf->global->THEME_ELDY_ENABLE_PERSONALIZED=0; @@ -221,7 +220,6 @@ print 'dol_hide_topmenu='.$dol_hide_topmenu."\n"; print 'dol_hide_leftmenu='.$dol_hide_leftmenu."\n"; print 'dol_optimize_smallscreen='.$dol_optimize_smallscreen."\n"; print 'dol_no_mouse_hover='.$dol_no_mouse_hover."\n"; -print 'dol_use_jmobile='.$dol_use_jmobile."\n"; print 'dol_screenwidth='.$_SESSION['dol_screenwidth']."\n"; print 'dol_screenheight='.$_SESSION['dol_screenheight']."\n"; print 'fontsize='.$fontsize."\n"; @@ -261,8 +259,6 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla background-color: #FFF; } - - input:focus, textarea:focus, button:focus, select:focus { box-shadow: 0 0 4px #8091BF; } @@ -306,7 +302,6 @@ span.timesheetalreadyrecorded input { border: none; /*background: transparent;*/ } - select.flat, form.flat select { font-weight: normal; @@ -341,9 +336,9 @@ input[type=checkbox] { background-color: transparent; border: none; box-shadow: input[type=radio] { background-color: transparent; border: none; box-shadow: none; } input[type=image] { background-color: transparent; border: none; box-shadow: none; } input:-webkit-autofill { - background-color: !important; + background-color: #FBFFEA !important; background-image:none !important; - -webkit-box-shadow: 0 0 0 50px inset; + -webkit-box-shadow: 0 0 0 50px #FBFFEA inset; } ::-webkit-input-placeholder { color:#ccc; } :-moz-placeholder { color:#bbb; } /* firefox 18- */ @@ -351,9 +346,6 @@ input:-webkit-autofill { :-ms-input-placeholder { color:#ccc; } /* ie */ input:-moz-placeholder { color:#ccc; } - -legend { margin-bottom: 8px; } - fieldset { border: 1px solid #AAAAAA !important; } @@ -542,7 +534,7 @@ div.myavailability { margin-top: 6px; margin-left: 4px; } -.selectlimit { +.selectlimit, .marginrightonly { margin-right: 10px !important; } .strikefordisabled { @@ -622,6 +614,7 @@ div.myavailability { .minwidth500imp { min-width: 500px !important; } } .maxwidth50 { max-width: 50px; } +.maxwidth75 { max-width: 75px; } .maxwidth100 { max-width: 100px; } .maxwidth150 { max-width: 150px; } .maxwidth200 { max-width: 200px; } @@ -665,20 +658,28 @@ div.myavailability { div.titre { line-height: 2em; } + .border tbody tr, .border tbody tr td, div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { + height: 40px !important; + } - input[type=text], select, textarea { + .quatrevingtpercent, .inputsearch { + width: 95%; + } + + input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; line-height: 1.4em; - margin: .5em 0; padding: .4em .1em; border: 1px solid #BBB; + max-width: inherit; } .hideonsmartphone { display: none; } .noenlargeonsmartphone { width : 50px !important; display: inline !important; } .maxwidthonsmartphone { max-width: 100px; } .maxwidth50onsmartphone { max-width: 50px; } + .maxwidth75onsmartphone { max-width: 75px; } .maxwidth100onsmartphone { max-width: 100px; } .maxwidth150onsmartphone { max-width: 150px; } .maxwidth200onsmartphone { max-width: 200px; } @@ -699,7 +700,6 @@ div.myavailability { } select { width: 98%; - dol_use_jmobile)) { ?>max-width: 100px; min-width: 40px; } div.divphotoref { @@ -833,7 +833,6 @@ div.fiche { margin-: px; margin-: dol_optimize_smallscreen)?'12':'6')); ?>px; dol_hide_leftmenu) && ! empty($conf->dol_hide_topmenu)) print 'margin-top: 4px;'."\n"; ?> - dol_use_jmobile)) print ' margin-bottom: 10px;'."\n"; ?> } div.fichecenter { width: 100%; @@ -1929,10 +1928,7 @@ div.tabs { } div.tabsElem { margin-top: 1px; - dol_use_jmobile)) { ?>; - margin-bottom: -1px; - -} /* To avoid overlap of tabs when not browser */ +} /* To avoid overlap of tabs when not browser */ div.tabBar { color: #; @@ -2357,10 +2353,7 @@ table.border, table.dataTable, .table-border, .table-border-col, .table-key-bord table.borderplus { border: 1px solid #BBB; } -.border tbody tr, .border tbody tr td { - height: 20px; -} -div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { +.border tbody tr, .border tbody tr td, div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { height: 20px; } div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar .table-val-border-col { @@ -2490,7 +2483,7 @@ table.listwithfilterbefore { /* Pagination */ div.refidpadding { - padding-top: dol_use_jmobile != 4)?'3':'7'; ?>px; + padding-top: 3px; } div.refid { font-weight: bold; @@ -2526,10 +2519,8 @@ div.pagination li { display: inline-block; padding-left: 0px; padding-right: 0px; -dol_use_jmobile != 4) { ?> padding-top: 6px; padding-bottom: 5px; - } .pagination { display: inline-block; @@ -2538,22 +2529,12 @@ div.pagination li { } div.pagination li.pagination a, div.pagination li.pagination span { -dol_use_jmobile != 4) { ?> padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #000; text-decoration: none; - /* - border-color: #ccc; - background-color: #f5f5f5; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);*/ - background-repeat: repeat-x; - + background-repeat: repeat-x; } div.pagination li.pagination span.inactive { cursor: default; @@ -2585,13 +2566,6 @@ div.pagination li.litext a:hover { background-color: transparent; background-image: none; } -dol_use_jmobile == 4) { ?> -div.pagination li.litext { - padding-top: 13px; - vertical-align: top; -} - -dol_use_jmobile != 4) { ?> div.pagination li.noborder a:hover { border: none; background-color: transparent; @@ -2651,7 +2625,6 @@ div.pagination .disabled a:focus { background-color: #fff; border-color: #ddd; } - div.pagination li.pagination .active { text-decoration: underline; } @@ -4230,11 +4203,7 @@ a.ui-link, a.ui-link:hover, .ui-btn:hover, span.ui-btn-text:hover, span.ui-btn-i min-width: .4em; padding-left: 6px; padding-right: 6px; - - font-size: 13px; - font-size: px; - /* white-space: normal; */ /* Warning, enable this break the truncate feature */ } .ui-btn-icon-right .ui-btn-inner { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 9935c3b2231..3dc4a122aca 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -72,7 +72,6 @@ $dol_hide_topmenu=$conf->dol_hide_topmenu; $dol_hide_leftmenu=$conf->dol_hide_leftmenu; $dol_optimize_smallscreen=$conf->dol_optimize_smallscreen; $dol_no_mouse_hover=$conf->dol_no_mouse_hover; -$dol_use_jmobile=$conf->dol_use_jmobile; //$conf->global->THEME_ELDY_ENABLE_PERSONALIZED=0; @@ -221,7 +220,6 @@ print 'dol_hide_topmenu='.$dol_hide_topmenu."\n"; print 'dol_hide_leftmenu='.$dol_hide_leftmenu."\n"; print 'dol_optimize_smallscreen='.$dol_optimize_smallscreen."\n"; print 'dol_no_mouse_hover='.$dol_no_mouse_hover."\n"; -print 'dol_use_jmobile='.$dol_use_jmobile."\n"; print 'dol_screenwidth='.$_SESSION['dol_screenwidth']."\n"; print 'dol_screenheight='.$_SESSION['dol_screenheight']."\n"; print 'fontsize='.$fontsize."\n"; @@ -261,8 +259,6 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla background-color: #FDFDFD; } - - input:focus, textarea:focus, button:focus, select:focus { box-shadow: 0 0 4px #8091BF; } @@ -308,8 +304,6 @@ span.timesheetalreadyrecorded input { /*background: transparent;*/ } - - select.flat, form.flat select { font-weight: normal; } @@ -347,9 +341,9 @@ input[type=radio] { background-color: transparent; border: none; box-shadow: input[type=image] { background-color: transparent; border: none; box-shadow: none; } input[type=text] { min-width: 20px; } input:-webkit-autofill { - background-color: !important; + background-color: #FBFFEA !important; background-image:none !important; - -webkit-box-shadow: 0 0 0 50px inset; + -webkit-box-shadow: 0 0 0 50px #FBFFEA inset; } ::-webkit-input-placeholder { color:#ccc; } :-moz-placeholder { color:#bbb; } /* firefox 18- */ @@ -357,9 +351,6 @@ input:-webkit-autofill { :-ms-input-placeholder { color:#ccc; } /* ie */ input:-moz-placeholder { color:#ccc; } - -legend { margin-bottom: 8px; } - fieldset { border: 1px solid #AAAAAA !important; } @@ -549,7 +540,7 @@ div.myavailability { margin-top: 6px; margin-left: 4px; } -.selectlimit { +.selectlimit, .marginrightonly { margin-right: 10px !important; } .strikefordisabled { @@ -627,6 +618,7 @@ div.myavailability { .minwidth500imp { min-width: 500px !important; } } .maxwidth50 { max-width: 50px; } +.maxwidth75 { max-width: 75px; } .maxwidth100 { max-width: 100px; } .maxwidth150 { max-width: 150px; } .maxwidth200 { max-width: 200px; } @@ -670,20 +662,28 @@ div.myavailability { div.titre { line-height: 2em; } + .border tbody tr, .border tbody tr td, div.tabBar table.border tr { + height: 40px !important; + } - input[type=text], select, textarea { + .quatrevingtpercent, .inputsearch { + width: 95%; + } + + input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; line-height: 1.4em; - margin: .5em 0; padding: .4em .1em; border: 1px solid #BBB; + max-width: inherit; } .hideonsmartphone { display: none; } .noenlargeonsmartphone { width : 50px !important; display: inline !important; } .maxwidthonsmartphone { max-width: 100px; } .maxwidth50onsmartphone { max-width: 50px; } + .maxwidth75onsmartphone { max-width: 75px; } .maxwidth100onsmartphone { max-width: 100px; } .maxwidth150onsmartphone { max-width: 150px; } .maxwidth200onsmartphone { max-width: 200px; } @@ -697,6 +697,28 @@ div.myavailability { .minwidth500imp { min-width: 50px !important; } .titlefield { width: auto; } .titlefieldcreate { width: auto; } + + #tooltip { + position: absolute; + width: px; + } + select { + width: 98%; + min-width: 40px; + } + div.divphotoref { + padding-right: 5px; + } + img.photoref, div.photoref { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + padding: 4px; + height: 20px; + width: 20px; + object-fit: contain; + } } .linkobject { cursor: pointer; } @@ -2114,13 +2136,11 @@ span.butAction, span.butActionDelete { color: #ffffff !important; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #006dcc; - dol_use_jmobile != 4)) { ?> background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; @@ -2245,10 +2265,7 @@ table.borderplus { border: 1px solid #BBB; } -.border tbody tr, .border tbody tr td { - height: 20px; -} -div.tabBar table.border tr { +.border tbody tr, .border tbody tr td, div.tabBar table.border tr { height: 20px; } @@ -2382,7 +2399,7 @@ table.listwithfilterbefore { /* Pagination */ div.refidpadding { - padding-top: dol_use_jmobile != 4)?'3':'14'; ?>px; + padding-top: 3px; } div.refid { font-weight: bold; @@ -2418,10 +2435,8 @@ div.pagination li { display: inline-block; padding-left: 0px; padding-right: 0px; -dol_use_jmobile != 4)) { ?> padding-top: 6px; padding-bottom: 5px; - } .pagination { display: inline-block; @@ -2431,7 +2446,6 @@ div.pagination li { div.pagination li.pagination a, div.pagination li.pagination span { -dol_use_jmobile != 4) { ?> padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; @@ -2445,7 +2459,6 @@ div.pagination li.pagination span { background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); background-repeat: repeat-x; - } div.pagination li.pagination span.inactive { cursor: default; @@ -2458,13 +2471,6 @@ border: none; padding-left: 4px; font-weight: bold; } -dol_use_jmobile == 4) { ?> -div.pagination li.litext { - padding-top: 13px; - vertical-align: top; -} - -dol_use_jmobile != 4) { ?> div.pagination li.noborder a:hover { border: none; background-color: transparent; @@ -2516,7 +2522,6 @@ div.pagination .disabled a:focus { background-color: #fff; border-color: #ddd; } - div.pagination li.pagination .active { text-decoration: underline; } @@ -4114,11 +4119,7 @@ a.ui-link, a.ui-link:hover, .ui-btn:hover, span.ui-btn-text:hover, span.ui-btn-i min-width: .4em; padding-left: 6px; padding-right: 6px; - - font-size: 13px; - font-size: px; - /* white-space: normal; */ /* Warning, enable this break the truncate feature */ } .ui-btn-icon-right .ui-btn-inner { @@ -4543,7 +4544,6 @@ img.demothumb { } select { width: 98%; - dol_use_jmobile)) { ?>max-width: 100px; min-width: 0 !important; } div.divphotoref { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 997933e234b..75af1dae8e3 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1659,38 +1659,48 @@ class User extends CommonObject $outputlangs->load("users"); $outputlangs->load("other"); - $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword"); + $appli=constant('DOL_APPLICATION_TITLE'); + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE; + + $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli); // 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 + $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 if (! $changelater) { + $url = $urlwithroot.'/'; + $mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived").".\n"; $mesg.= $outputlangs->transnoentitiesnoconv("NewKeyIs")." :\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n"; $mesg.= "\n"; - $url = $urlwithroot.'/'; - $mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $conf->global->MAIN_APPLICATION_TITLE).': '.$url."\n\n"; + + $mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli).': '.$url."\n\n"; $mesg.= "--\n"; $mesg.= $user->getFullName($outputlangs); // Username that make then sending + + dol_syslog(get_class($this)."::send_password changelater is off, url=".$url); } else { + $url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password); + $mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("NewKeyWillBe")." :\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n"; $mesg.= "\n"; $mesg.= $outputlangs->transnoentitiesnoconv("YouMustClickToChange")." :\n"; - $url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password); $mesg.= $url."\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("ForgetIfNothing")."\n\n"; - dol_syslog(get_class($this)."::send_password url=".$url); + + dol_syslog(get_class($this)."::send_password changelater is on, url=".$url); } + $mailfile = new CMailFile( $subject, $this->email,
'.$langs->trans("Ref").''; - print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref'); - print '
'.$langs->trans("Label").''.$object->title.'
'.$langs->trans("ThirdParty").''; - if ($object->thirdparty->id > 0) print $object->thirdparty->getNomUrl(1, 'project'); - else print' '; - print '
'.$langs->trans("Visibility").''; if ($object->public) print $langs->trans('SharedProject'); else print $langs->trans('PrivateProject'); print '
'.$langs->trans("Status").''.$object->getLibStatut(4).'
'.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").''; print dol_print_date($object->date_start,'day'); $end=dol_print_date($object->date_end,'day'); - if ($end) print ' - '.$end; + if ($end) + { + print ' - '.$end; + if ($object->hasDelay()) print img_warning($langs->trans('Late')); + } print '