diff --git a/ChangeLog b/ChangeLog index 2996e26f862..798f3ef91f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -152,6 +152,52 @@ Dolibarr better: - The trigger that activate or close a contract line is run on a contract line, not on contract. +***** ChangeLog for 4.0.3 to 4.0.2 ***** +FIX: #5853 $conf->global->$calc==0 || $conf->global->$calc==1 +FIX: #5958 no discount on supplier command made by replenishment +FIX: #5966 Bug: getNomUrl tooltips show Proposal info even if user has no rights to read them +FIX: #5972 #5734 +FIX: #6007 +FIX: #6010 +FIX: #6029 +FIX: #6043 - Payment mode not visible on supplier invoice list +FIX: #6051 +FIX: #6062 +FIX: #6088 +FIX: A draft can be deleted by a user with create permission. +FIX: bad permission to see contract on home page +FIX: bad permission to see contract statistics +FIX: Bcc must not appears to recipient when using SMTPs lib +FIX: Consistent description for add or edit product +FIX: delete contract extrafields on contract deletion +FIX: Deposits and credit notes weren't added in the received and pending columns +FIX: export extrafields must not include separe type +FIX: Export of opportunity status must be code, not id. +FIX: False positive on services not activated +FIX: Filter was wrong or lost during navigation +FIX: HT and TTC price should always be displayed together +FIX: if a supplier price reference is changed after creating an order, we can't clone order. +FIX: in export. Error when using a separate extrafields. +FIX: Introduce hidden option MAIL_PREFIX_FOR_EMAIL_ID to solve pb of tracking email. +FIX: javascript error when using on mobile/smartphone +FIX: javascript xss injection and a translation +FIX: Label of project is in field title not label. +FIX: List of people able to validate an expense report was not complete. +FIX: Missing field +FIX: Module gravatar was not triggered on thirdparty and contact card +FIX: Must use external link into a forged email content. +FIX: Pb in management of date end of projects +FIX: Regression when deleting product +FIX: rendering of output of estimated amount on project overview page. +FIX: Sanitize title of ajax_dialog +FIX: Security to restrict email sending was not efficient +FIX: Setting supplier as client when accept a supplier proposal +FIX: Some statistics not compatible with multicompany module. +FIX: the time spent on project was not visible in its overwiew +FIX: Update intervention lline crash with PgSQL +FIX: wrong test on dict.php +FIX: wrong var name + ***** ChangeLog for 4.0.2 compared to 4.0.1 ***** FIX: #5340 FIX: #5779 @@ -357,6 +403,115 @@ So if you included it into your module, change your code like this to be compati if (! $res) include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php'; + +***** ChangeLog for 3.9.4 compared to 3.9.3 ***** +FIX: #2853 +FIX: #3128 +FIX: #4447 +FIX: #5128 if create method return duplicated code error not use GETPOST in order to get a new code +FIX: #5340 +FIX: #5473 +FIX: #5474 Country_id of "Don" object is still empty +FIX: #5534 +FIX: #5535 bad dependency. +FIX: #5537 AJAX project search does not work properly +FIX: #5540 getFormMail is not registered as addReplace hook +FIX: #5544 Disabled Contact still appear in lists to send emails +FIX: #5549 getNomUrl tooltips show Order info even if user has no rights to read them +FIX: #5568 +FIX: #5594 +FIX: #5629 PgSQL Interger string stylish error +FIX: #5651 +FIX: #5660 +FIX: #5853 $conf->global->$calc==0 || $conf->global->$calc==1 +FIX: #5907 +FIX: #5966 Bug: getNomUrl tooltips show Proposal info even if user has no rights to read them +FIX: #6051 +FIX: #6088 +FIX: Can correct stock of lot using eatby or sell by date +FIX: Can make a movement on "out of sell" products +FIX: cannot update bank account on invoice if module order not activated +FIX: Can't create withdrawal document +FIX: delete contract extrafields on contract deletion +FIX: Direction of movement lost if an error occurs +FIX: Error when CATEGORIE_RECURSIV_ADD is enabled and new category is daughter of an already linked to object +FIX: export extrafields must not include separe type +FIX: External user must not be able to edit its discounts +FIX: Failed to export contact categories with contact extra fields +FIX: header title in commercial area +FIX: HT and TTC price should always be displayed together +FIX: incoterms +FIX: incoterms do not output into crabe invoice PDF +FIX: in PgSQL no quote "word style" is permitted around column name +FIX: Introduce hidden option MAIL_PREFIX_FOR_EMAIL_ID to solve pb of tracking email. +FIX: margin tab on customer card must filter on current entity invoices +FIX: missing column into SQL on thridparty list +FIX: only show projects of related third if external user +FIX: PgSQL Module Ressource list crash #5637 +FIX: php Strict +FIX: Regression when deleting product +FIX: Security to restrict email sending was not efficient +FIX: tag for date rfc in odt substitution +FIX: Update intervention lline crash with PgSQL +FIX: update limit stock on product stock +FIX: vat dictionary should allow enter and edit multiple values for localtaxes, separated by: (ex -19:-15) +FIX: wrong test on dict.php + + +***** ChangeLog for 3.9.4 compared to 3.9.3 ***** +FIX: #2853 +FIX: #3128 +FIX: #4447 +FIX: #5128 if create method return duplicated code error not use GETPOST in order to get a new code +FIX: #5340 +FIX: #5473 +FIX: #5474 Country_id of "Don" object is still empty +FIX: #5534 +FIX: #5535 bad dependency. +FIX: #5537 AJAX project search does not work properly +FIX: #5540 getFormMail is not registered as addReplace hook +FIX: #5544 Disabled Contact still appear in lists to send emails +FIX: #5549 getNomUrl tooltips show Order info even if user has no rights to read them +FIX: #5568 +FIX: #5594 +FIX: #5629 PgSQL Interger string stylish error +FIX: #5651 +FIX: #5660 +FIX: #5853 $conf->global->$calc==0 || $conf->global->$calc==1 +FIX: #5907 +FIX: #5966 Bug: getNomUrl tooltips show Proposal info even if user has no rights to read them +FIX: #6051 +FIX: #6088 +FIX: Can correct stock of lot using eatby or sell by date +FIX: Can make a movement on "out of sell" products +FIX: cannot update bank account on invoice if module order not activated +FIX: Can't create withdrawal document +FIX: delete contract extrafields on contract deletion +FIX: Direction of movement lost if an error occurs +FIX: Error when CATEGORIE_RECURSIV_ADD is enabled and new category is daughter of an already linked to object +FIX: export extrafields must not include separe type +FIX: External user must not be able to edit its discounts +FIX: Failed to export contact categories with contact extra fields +FIX: header title in commercial area +FIX: HT and TTC price should always be displayed together +FIX: incoterms +FIX: incoterms do not output into crabe invoice PDF +FIX: in PgSQL no quote "word style" is permitted around column name +FIX: Introduce hidden option MAIL_PREFIX_FOR_EMAIL_ID to solve pb of tracking email. +FIX: margin tab on customer card must filter on current entity invoices +FIX: missing column into SQL on thridparty list +FIX: only show projects of related third if external user +FIX: PgSQL Module Ressource list crash #5637 +FIX: php Strict +FIX: Regression when deleting product +FIX: Security to restrict email sending was not efficient +FIX: tag for date rfc in odt substitution +FIX: Update intervention lline crash with PgSQL +FIX: update limit stock on product stock +FIX: vat dictionary should allow enter and edit multiple values for localtaxes, separated by: (ex -19:-15) +FIX: wrong test on dict.php + + ***** ChangeLog for 3.9.3 compared to 3.9.2 ***** FIX: #4383 $userid not defined FIX: #4448 $filebonprev is not used, $this->filename now diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php old mode 100644 new mode 100755 index 1bc0e2b6620..07e87dd86bb --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -65,6 +65,8 @@ fputs($fp, ''."\n"); fputs($fp, ''."\n"); +$checksumconcat=array(); + $dir_iterator1 = new RecursiveDirectoryIterator(dirname(__FILE__).'/../htdocs/'); $iterator1 = new RecursiveIteratorIterator($dir_iterator1); // need to ignore document custom etc @@ -81,12 +83,22 @@ foreach ($files as $file) { $needtoclose=1; } if (filetype($file)=="file") { - fputs($fp, ''.md5_file($file).''."\n"); + $md5=md5_file($file); + $checksumconcat[]=$md5; + fputs($fp, ''.$md5.''."\n"); } } fputs($fp, ''."\n"); fputs($fp, ''."\n"); +asort($checksumconcat); // Sort list of checksum +//var_dump($checksumconcat); +fputs($fp, ''."\n"); +fputs($fp, md5(join(',',$checksumconcat))."\n"); +fputs($fp, ''."\n"); + + +$checksumconcat=array(); fputs($fp, ''."\n"); @@ -106,12 +118,18 @@ foreach ($files as $file) { $needtoclose=1; } if (filetype($file)=="file") { - fputs($fp, ''.md5_file($file).''."\n"); + $md5=md5_file($file); + $checksumconcat[]=$md5; + fputs($fp, ''.$md5.''."\n"); } } fputs($fp, ''."\n"); fputs($fp, ''."\n"); +asort($checksumconcat); // Sort list of checksum +fputs($fp, ''."\n"); +fputs($fp, md5(join(',',$checksumconcat))."\n"); +fputs($fp, ''."\n"); fputs($fp, ''."\n"); fclose($fp); 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/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 268b5fa69c2..524326e320c 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -357,7 +357,7 @@ class AccountancyExport $Tab['libelle_ecriture'] = str_pad(self::trunc($data->doc_ref . ' ' . $data->label_compte, 20), 20); $Tab['sens'] = $data->sens; // C or D $Tab['signe_montant'] = '+'; - $Tab['montant'] = str_pad(abs($data->montant) * 100, 12, '0', STR_PAD_LEFT); // TODO manage negative amount + $Tab['montant'] = str_pad(abs($data->montant), 12, '0', STR_PAD_LEFT); // TODO manage negative amount $Tab['contrepartie'] = str_repeat(' ', 8); if (! empty($data->date_echeance)) $Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE); 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/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/dict.php b/htdocs/admin/dict.php index 0cd4886f8c9..2ca1337736e 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -1274,6 +1274,7 @@ if ($id) // Title line with search boxes print ''; + $filterfound=0; foreach ($fieldlist as $field => $value) { $showfield=1; // By defaut @@ -1284,21 +1285,25 @@ if ($id) { if ($value == 'country') { - print ''; + print ''; print $form->select_country($search_country_id, 'search_country_id', '', 28, 'maxwidth200 maxwidthonsmartphone'); print ''; + $filterfound++; } else { - print ''; + print ''; } } } if ($id == 4) print ''; - print ''; + print ''; print ''; - $searchpitco=$form->showFilterAndCheckAddButtons(0); - print $searchpitco; + if ($filterfound) + { + $searchpitco=$form->showFilterAndCheckAddButtons(0); + print $searchpitco; + } print ''; print ''; @@ -1314,19 +1319,17 @@ if ($id) print ''; if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code))) { - print '
'; - print ''; - print ''; - print ''; - $tmpaction='edit'; $parameters=array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]); $reshook=$hookmanager->executeHooks('editDictionaryFieldlist',$parameters,$obj, $tmpaction); // Note that $action and $object may have been modified by some hooks $error=$hookmanager->error; $errors=$hookmanager->errors; + // Show fields if (empty($reshook)) fieldList($fieldlist,$obj,$tabname[$id],'edit'); print ''; + print ''; + print ''; print ''; print '
'; print ''; diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index d05518374c1..ed290060370 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -619,6 +619,12 @@ else print ''; + if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') + { + $text = $langs->trans("WarningPHPMail"); + print info_admin($text); + } + // Run the test to connect if ($action == 'testconnect') { diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index 5bea1b521ac..1340b5ae3c1 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -75,9 +75,9 @@ $file_list = array('missing' => array(), 'updated' => array()); // File to analyze //$xmlfile = DOL_DOCUMENT_ROOT.'/install/filelist-'.DOL_VERSION.'.xml'; -$xmlshortfile = '/install/filelist-'.DOL_VERSION.'.xml'; +$xmlshortfile = GETPOST('xmlshortfile')?GETPOST('xmlshortfile'):'/install/filelist-'.DOL_VERSION.'.xml'; $xmlfile = DOL_DOCUMENT_ROOT.$xmlshortfile; -$xmlremote = 'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.'.xml'; +$xmlremote = GETPOST('xmlremote')?GETPOST('xmlremote'):'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.'.xml'; // Test if remote test is ok @@ -87,21 +87,27 @@ if (preg_match('/beta|alpha/i', DOL_VERSION)) $enableremotecheck=False; print ''; print $langs->trans("MakeIntegrityAnalysisFrom").':
'; +print ''."\n"; if (dol_is_file($xmlfile)) { print ' '.$langs->trans("LocalSignature").' = '.$xmlshortfile.'
'; } else { - print ' '.$langs->trans("LocalSignature").' = '.$xmlshortfile.' ('.$langs->trans("AvailableOnlyOnPackagedVersions").')
'; + print ' '.$langs->trans("LocalSignature").' = '.$xmlshortfile; + if (! GETPOST('xmlshortfile')) print ' ('.$langs->trans("AvailableOnlyOnPackagedVersions").')'; + print '
'; } +print ''."\n"; if ($enableremotecheck) { print ' '.$langs->trans("RemoteSignature").' = '.$xmlremote.'
'; } else { - print ' '.$langs->trans("RemoteSignature").' = '.$xmlremote.' ('.$langs->trans("FeatureAvailableOnlyOnStable").')
'; + print ' '.$langs->trans("RemoteSignature").' = '.$xmlremote; + if (! GETPOST('xmlremote')) print ' ('.$langs->trans("FeatureAvailableOnlyOnStable").')'; + print '
'; } print '
'; print '
'; @@ -128,7 +134,8 @@ if (GETPOST('target') == 'remote') if (! $xmlarray['curl_error_no'] && $xmlarray['http_code'] != '404') { $xmlfile = $xmlarray['content']; - $xml = simplexml_load_file($xmlfile); + //print "eee".$xmlfile."eee"; + $xml = simplexml_load_string($xmlfile); } else { @@ -141,11 +148,14 @@ if (GETPOST('target') == 'remote') if ($xml) { + $checksumconcat = array(); + + // Scan htdocs if (is_object($xml->dolibarr_htdocs_dir[0])) { - $file_list = array(); - $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0]); // Fill array $file_list - + $file_list = array(); + $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat); // Fill array $file_list + print ''; print ''; print ''; @@ -181,10 +191,10 @@ if ($xml) print ''; print ''."\n"; $var = true; - $tmpfilelist = dol_sort_array($file_list['updated'], 'filename'); - if (is_array($tmpfilelist) && count($tmpfilelist)) + $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename'); + if (is_array($tmpfilelist2) && count($tmpfilelist2)) { - foreach ($tmpfilelist as $file) + foreach ($tmpfilelist2 as $file) { $var = !$var; print ''; @@ -201,12 +211,44 @@ if ($xml) print ''; } print '
' . $langs->trans("FilesMissing") . '' . $langs->trans("DateModification") . '
'.$langs->trans("None").'
'; + + if (empty($tmpfilelist) && empty($tmpfilelist2)) + { + setEventMessage($langs->trans("FileIntegrityIsStrictlyConformedWithReference")); + } + else + { + setEventMessage($langs->trans("FileIntegritySomeFilesWereRemovedOrModified"), 'warnings'); + } } else { print 'Error: Failed to found dolibarr_htdocs_dir into XML file '.$xmlfile; $error++; } + + + // Scan scripts + /* + if (is_object($xml->dolibarr_script_dir[0])) + { + $file_list = array(); + $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', ???, $checksumconcat); // Fill array $file_list + }*/ + + + asort($checksumconcat); // Sort list of checksum + //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; + } + } @@ -223,12 +265,14 @@ exit($error); * Function to get list of updated or modified files. * $file_list is used as global variable * - * @param array $file_list Array for response - * @param SimpleXMLElement $dir SimpleXMLElement of files to test - * @param string $path Path of file - * @return array Array of filenames + * @param array $file_list Array for response + * @param SimpleXMLElement $dir SimpleXMLElement of files to test + * @param string $path Path of files relative to $pathref. We start with ''. Used by recursive calls. + * @param string $pathref Path ref (DOL_DOCUMENT_ROOT) + * @param array $checksumconcat Array of checksum + * @return array Array of filenames */ -function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '') +function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathref = '', &$checksumconcat = array()) { $exclude = 'install'; @@ -236,20 +280,21 @@ function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '') { $filename = $path.$file['name']; - if (preg_match('#'.$exclude.'#', $filename)) continue; + //if (preg_match('#'.$exclude.'#', $filename)) continue; - if (!file_exists(DOL_DOCUMENT_ROOT.'/'.$filename)) + if (!file_exists($pathref.'/'.$filename)) { $file_list['missing'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file); } else { - $md5_local = md5_file(DOL_DOCUMENT_ROOT.'/'.$filename); + $md5_local = md5_file($pathref.'/'.$filename); if ($md5_local != (string) $file) $file_list['updated'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file, 'md5'=>(string) $md5_local); - } + $checksumconcat[] = $md5_local; + } } - foreach ($dir->dir as $subdir) getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/'); + foreach ($dir->dir as $subdir) getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/', $pathref, $checksumconcat); return $file_list; } diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 43f2953ccda..7d07f7ead94 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -105,7 +105,7 @@ if ($action == 'add' || (GETPOST('add') && $action != 'update')) } if (! $error) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."overwrite_trans(lang, transkey, transvalue) VALUE ('".$db->escape($langcode)."','".$db->escape($transkey)."','".$db->escape($transvalue)."')"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."overwrite_trans(lang, transkey, transvalue) VALUES ('".$db->escape($langcode)."','".$db->escape($transkey)."','".$db->escape($transvalue)."')"; $result = $db->query($sql); if ($result > 0) { 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/card.php b/htdocs/comm/action/card.php index 4b6380b1240..b4a9f8b5395 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -278,7 +278,7 @@ if ($action == 'add') if (GETPOST("doneby") > 0) $object->userdoneid = GETPOST("doneby","int"); } - $object->note = trim($_POST["note"]); + $object->note = trim(GETPOST("note")); if (isset($_POST["contactid"])) $object->contact = $contact; @@ -290,11 +290,6 @@ if ($action == 'add') $object->societe = $object->thirdparty; // For backward compatibility } - // Special for module webcal and phenix - // TODO external modules - if (! empty($conf->webcalendar->enabled) && GETPOST('add_webcal') == 'on') $object->use_webcal=1; - if (! empty($conf->phenix->enabled) && GETPOST('add_phenix') == 'on') $object->use_phenix=1; - // Check parameters if (empty($object->userownerid) && empty($_SESSION['assignedtouser'])) { 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/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 7c34498e6b4..c37c61ca88c 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -756,8 +756,9 @@ else $sendingmode=$conf->global->MAIN_MAIL_SENDMODE; if (empty($sendingmode)) $sendingmode='mail'; // If not defined, we use php mail function - // MAILING_NO_USING_PHPMAIL may be defined or not - // MAILING_LIMIT_SENDBYWEB is always defined to something != 0, MAILING_LIMIT_SENDBYCLI may be defined ot not. + // MAILING_NO_USING_PHPMAIL may be defined or not. + // MAILING_LIMIT_SENDBYWEB is always defined to something != 0 (-1=forbidden). + // MAILING_LIMIT_SENDBYCLI may be defined ot not (-1=forbidden, 0=no limit). if (! empty($conf->global->MAILING_NO_USING_PHPMAIL) && $sendingmode == 'mail') { // EMailing feature may be a spam problem, so when you host several users/instance, having this option may force each user to use their own SMTP agent. @@ -797,7 +798,7 @@ else } $text.=$langs->trans('ConfirmSendingEmailing').'
'; $text.=$langs->trans('LimitSendingEmailing',$conf->global->MAILING_LIMIT_SENDBYWEB); - print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('SendMailing'),$text,'sendallconfirmed',$formquestion,'',1,270); + print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('SendMailing'),$text,'sendallconfirmed',$formquestion,'',1,300); } } @@ -844,23 +845,28 @@ else print $langs->trans("TotalNbOfDistinctRecipients"); print ''; $nbemail = ($object->nbemail?$object->nbemail:img_warning('').' '.$langs->trans("NoTargetYet").''); - if ($object->statut != 3 && !empty($conf->global->MAILING_LIMIT_SENDBYWEB) && is_numeric($nbemail) && $conf->global->MAILING_LIMIT_SENDBYWEB < $nbemail) + if ($object->statut != 3 && is_numeric($nbemail)) { - if ($conf->global->MAILING_LIMIT_SENDBYWEB > 0) - { - $text=$langs->trans('LimitSendingEmailing',$conf->global->MAILING_LIMIT_SENDBYWEB); - print $form->textwithpicto($nbemail,$text,1,'warning'); - } - else - { - $text=$langs->trans('NotEnoughPermissions'); - print $form->textwithpicto($nbemail,$text,1,'warning'); - } - - } - else - { - print $nbemail; + $text=''; + if (! empty($conf->global->MAILING_LIMIT_SENDBYWEB) && $conf->global->MAILING_LIMIT_SENDBYWEB < $nbemail) + { + if ($conf->global->MAILING_LIMIT_SENDBYWEB > 0) + { + $text.=$langs->trans('LimitSendingEmailing',$conf->global->MAILING_LIMIT_SENDBYWEB); + } + else + { + $text.=$langs->trans('NotEnoughPermissions'); + } + } + if ($text) + { + print $form->textwithpicto($nbemail,$text,1,'warning'); + } + else + { + print $nbemail; + } } print ''; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 74566100f89..01ac00cd6d2 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2025,7 +2025,7 @@ if ($action == 'create') $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code); } else { $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code); - if($object->statut == 0) { + if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code != $conf->currency) { print '
        '; print ''.$langs->trans("ActualizeCurrency").''; print '
'; diff --git a/htdocs/comm/propal/note.php b/htdocs/comm/propal/note.php index d161fe03870..57181b83f6b 100644 --- a/htdocs/comm/propal/note.php +++ b/htdocs/comm/propal/note.php @@ -132,9 +132,9 @@ if ($id > 0 || ! empty($ref)) print '
'; print '
'; + $cssclass="titlefield"; include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; - print '
'; print ''; dol_fiche_end(); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index db11214803d..baf18c329c1 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2219,7 +2219,7 @@ if ($action == 'create' && $user->rights->commande->creer) $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code); } else { $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code); - if($object->statut == 0) { + if($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code != $conf->currency) { print '
        '; print ''.$langs->trans("ActualizeCurrency").''; print '
'; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 9ca79421f20..6e304a019d0 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1061,7 +1061,8 @@ if ($resql) $text_info=''; $text_warning=''; $nbprod=0; - + + // Ref if (! empty($arrayfields['c.ref']['checked'])) { print ''; @@ -1186,12 +1187,12 @@ if ($resql) print ''; } - // Warning late icon + // Warning late icon and note print ''; if ($generic_commande->hasDelay()) { print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); } - if(!empty($obj->note_private)) + if (!empty($obj->note_private) || !empty($obj->note_public)) { print ' '; print ''.img_picto($langs->trans("ViewPrivateNote"),'object_generic').''; diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index cd44122b981..91267578197 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1345,8 +1345,16 @@ if (empty($reshook)) setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors'); $error ++; } + if (! GETPOST('prod_entry_mode')) + { + if (GETPOST('type') < 0 && ! GETPOST('search_idprod')) + { + setEventMessages($langs->trans('ErrorChooseBetweenFreeAntryOrPredefinedProduct'), null, 'errors'); + $error ++; + } + } if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && GETPOST('type') < 0) { - setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors'); $error ++; } if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && (! ($price_ht >= 0) || $price_ht == '') && $price_ht_devise == '') // Unit price can be 0 but not '' @@ -3257,7 +3265,7 @@ else if ($id > 0 || ! empty($ref)) $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code); } else { $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code); - if($object->statut == 0) { + if($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code != $conf->currency) { print '
        '; print ''.$langs->trans("ActualizeCurrency").''; print '
'; @@ -3723,7 +3731,7 @@ else if ($id > 0 || ! empty($ref)) else print $langs->trans('ExcessReceived'); print ' :'; - print '' . price($resteapayeraffiche) . ''; + print '' . price($resteapayeraffiche) . ''; print ' '; } else // Credit note diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 93b2b63070f..d2c20099edc 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -867,18 +867,20 @@ if ($resql) $facturestatic->type=$obj->type; $facturestatic->statut=$obj->fk_statut; $facturestatic->date_lim_reglement=$db->jdate($obj->datelimite); - $facturestatic->type=$obj->type; $facturestatic->note_public=$obj->note_public; $facturestatic->note_private=$obj->note_private; + + $paiement = $facturestatic->getSommePaiement(); + $totalcreditnotes = $facturestatic->getSumCreditNotesUsed(); + $totaldeposits = $facturestatic->getSumDepositsUsed(); + $totalpay = $paiement + $totalcreditnotes + $totaldeposits; + $remaintopay = $obj->total_ttc - $totalpay; print ''; if (! empty($arrayfields['f.facnumber']['checked'])) { print ''; - - $paiement = $facturestatic->getSommePaiement(); - $remaintopay = $obj->total_ttc - $paiement; - + print ''; print ''; // TODO Use a denormalized field + print ''; // TODO Use a denormalized field if (! $i) $totalarray['nbfield']++; if (! $i) $totalarray['totalamfield']=$totalarray['nbfield']; - $totalarray['totalam'] += $paiement; + $totalarray['totalam'] += $totalpay; } if (! empty($arrayfields['rtp']['checked'])) 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/recap-compta.php b/htdocs/compta/recap-compta.php index 3f952ef15c6..aec371ac0b3 100644 --- a/htdocs/compta/recap-compta.php +++ b/htdocs/compta/recap-compta.php @@ -30,14 +30,14 @@ require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; $langs->load("companies"); if (! empty($conf->facture->enabled)) $langs->load("bills"); -// Security check -$socid = GETPOST("socid",'int'); -if ($user->societe_id > 0) -{ - $action = ''; - $socid = $user->societe_id; -} +$id = GETPOST('id')?GETPOST('id','int'):GETPOST('socid','int'); +// Security check +if ($user->societe_id) $id=$user->societe_id; +$result = restrictedArea($user, 'societe', $id, '&societe'); + +$object = new Societe($db); +if ($id > 0) $object->fetch($id); /* @@ -47,20 +47,21 @@ if ($user->societe_id > 0) $form = new Form($db); $userstatic=new User($db); -llxHeader(); +$title=$langs->trans("ThirdParty").' - '.$langs->trans("Summary"); +if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name.' - '.$langs->trans("Symmary"); +$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; -if ($socid > 0) +llxHeader('',$title,$help_url); + +if ($id > 0) { - $societe = new Societe($db); - $societe->fetch($socid); - /* * Affichage onglets */ - $head = societe_prepare_head($societe); + $head = societe_prepare_head($object); dol_fiche_head($head, 'customer', $langs->trans("ThirdParty"), 0, 'company'); - dol_banner_tab($societe, 'socid', '', ($user->societe_id?0:1), 'rowid', 'nom'); + dol_banner_tab($object, 'socid', '', ($user->societe_id?0:1), 'rowid', 'nom', '', '', 0, '', '', 1); dol_fiche_end(); if (! empty($conf->facture->enabled) && $user->rights->facture->lire) @@ -86,7 +87,7 @@ if ($socid > 0) $sql.= " f.paye as paye, f.fk_statut as statut, f.rowid as facid,"; $sql.= " u.login, u.rowid as userid"; $sql.= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f,".MAIN_DB_PREFIX."user as u"; - $sql.= " WHERE f.fk_soc = s.rowid AND s.rowid = ".$societe->id; + $sql.= " WHERE f.fk_soc = s.rowid AND s.rowid = ".$object->id; $sql.= " AND f.entity = ".$conf->entity; $sql.= " AND f.fk_user_valid = u.rowid"; $sql.= " ORDER BY f.datef ASC"; diff --git a/htdocs/compta/resultat/index.php b/htdocs/compta/resultat/index.php index 62ef55fb711..74b80ec0e82 100644 --- a/htdocs/compta/resultat/index.php +++ b/htdocs/compta/resultat/index.php @@ -646,7 +646,7 @@ print ''; for ($annee = $year_start ; $annee <= $year_end ; $annee++) { - print ''; print ''; for ($annee = $year_start ; $annee <= $year_end ; $annee++) { - print ''; - print ''; + print ''; + print ''; } print ''; @@ -678,7 +678,7 @@ for ($mois = 1+$nb_mois_decalage ; $mois <= 12+$nb_mois_decalage ; $mois++) if($mois>12) {$annee_decalage=$annee+1;} $case = strftime("%Y-%m",dol_mktime(12,0,0,$mois_modulo,1,$annee_decalage)); - print '"; - print ''; +print ''; for ($annee = $year_start ; $annee <= $year_end ; $annee++) { $nbcols+=2; @@ -714,7 +714,7 @@ for ($annee = $year_start ; $annee <= $year_end ; $annee++) print "\n"; // Empty line -print ''; +print ''; print ''; print "\n"; diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index e917e1e1c71..77393b78f4e 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -556,34 +556,42 @@ if ($id > 0) print ''; print ''; print ''; - print ''; print ''; - $var=True; - while ($i < $num) + $var=true; + if ($num > 0) + { + while ($i < $num) + { + $objp = $db->fetch_object($resql); + $var=!$var; + print "'; + print '\n"; + $labeltype=$langs->trans("PaymentType".$objp->type_code)!=("PaymentType".$objp->type_code)?$langs->trans("PaymentType".$objp->type_code):$objp->paiement_type; + print "\n"; + print '\n"; + print ""; + $totalpaye += $objp->amount; + $i++; + } + } + else { - $objp = $db->fetch_object($resql); $var=!$var; - print "'; - print '\n"; - $labeltype=$langs->trans("PaymentType".$objp->type_code)!=("PaymentType".$objp->type_code)?$langs->trans("PaymentType".$objp->type_code):$objp->paiement_type; - print "\n"; - print '\n"; - print ""; - $totalpaye += $objp->amount; - $i++; + print ''; } - + if ($object->paye == 0) { - print "\n"; - print "\n"; + print "\n"; + print "\n"; $resteapayer = $object->amount - $totalpaye; - + $cssforamountpaymentcomplete = 'amountpaymentcomplete'; + print ""; - print "\n"; + print '\n"; } print "
'; @@ -1028,10 +1030,10 @@ if ($resql) if (! empty($arrayfields['dynamount_payed']['checked'])) { - print ''.(! empty($paiement)?price($paiement,0,$langs):' ').''.(! empty($totalpay)?price($totalpay,0,$langs):' ').'
 '; + print ''; print ''; print $annee; if ($conf->global->SOCIETE_FISCAL_MONTH_START > 1) print '-'.($annee+1); @@ -656,8 +656,8 @@ print '
'.$langs->trans("Month").''.$langs->trans("Outcome").''.$langs->trans("Income").''.$langs->trans("Outcome").''.$langs->trans("Income").'
 '; + print ' '; if (isset($decaiss_ttc[$case]) && $decaiss_ttc[$case] != 0) { print ''.price(price2num($decaiss_ttc[$case],'MT')).''; @@ -687,7 +687,7 @@ for ($mois = 1+$nb_mois_decalage ; $mois <= 12+$nb_mois_decalage ; $mois++) } print " '; + print ' '; //if (isset($encaiss_ttc[$case]) && $encaiss_ttc[$case] != 0) if (isset($encaiss_ttc[$case])) { @@ -704,7 +704,7 @@ for ($mois = 1+$nb_mois_decalage ; $mois <= 12+$nb_mois_decalage ; $mois++) // Total $var=!$var; $nbcols=0; -print '
'.$langs->trans("TotalTTC").'
'.$langs->trans("TotalTTC").'
 
  
'.$langs->trans("Date").''.$langs->trans("Type").''.$langs->trans("Amount").' 
"; + print ''.img_object($langs->trans("Payment"),"payment").' '.$objp->rowid.''.dol_print_date($db->jdate($objp->dp),'day')."".$labeltype.' '.$objp->num_paiement."'.price($objp->amount)."
"; - print ''.img_object($langs->trans("Payment"),"payment").' '.$objp->rowid.''.dol_print_date($db->jdate($objp->dp),'day')."".$labeltype.' '.$objp->num_paiement."'.price($objp->amount)." ".$langs->trans("Currency".$conf->currency)."
'.$langs->trans("None").'
".$langs->trans("AlreadyPaid")." :".price($totalpaye)." ".$langs->trans("Currency".$conf->currency)."
".$langs->trans("AmountExpected")." :".price($object->amount)." ".$langs->trans("Currency".$conf->currency)."
".$langs->trans("AlreadyPaid")." :".price($totalpaye)."
".$langs->trans("AmountExpected")." :".price($object->amount)."
".$langs->trans("RemainderToPay")." :".price($resteapayer)." ".$langs->trans("Currency".$conf->currency)."
'.price($resteapayer)."
"; $db->free($resql); 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/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index 1fdd567745f..61546b39061 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -510,7 +510,7 @@ class ChargeSociales extends CommonObject function info($id) { $sql = "SELECT e.rowid, e.tms as datem, e.date_creation as datec, e.date_valid as datev, e.import_key,"; - $sql.= " fk_user_author, fk_user_modif, fk_user_valid"; + $sql.= " e.fk_user_author, e.fk_user_modif, e.fk_user_valid"; $sql.= " FROM ".MAIN_DB_PREFIX."chargesociales as e"; $sql.= " WHERE e.rowid = ".$id; @@ -543,7 +543,7 @@ class ChargeSociales extends CommonObject } $this->date_creation = $this->db->jdate($obj->datec); - if (! empty($obj->fk_user_modif)) $this->date_modification = $this->db->jdate($obj->datem); + $this->date_modification = $this->db->jdate($obj->datem); $this->date_validation = $this->db->jdate($obj->datev); $this->import_key = $obj->import_key; } diff --git a/htdocs/compta/stats/casoc.php b/htdocs/compta/stats/casoc.php index 26063587c5d..636c4e29d17 100644 --- a/htdocs/compta/stats/casoc.php +++ b/htdocs/compta/stats/casoc.php @@ -456,10 +456,10 @@ print ''; print $form->select_country($search_country, 'search_country'); //print ''; print ''; -print ' '; -print ' '; -print ' '; -print ' '; +print ' '; +print ' '; +print ' '; +print ' '; print ''; $var=true; diff --git a/htdocs/compta/stats/index.php b/htdocs/compta/stats/index.php index 8d1aceeaa77..9d942caf57a 100644 --- a/htdocs/compta/stats/index.php +++ b/htdocs/compta/stats/index.php @@ -197,13 +197,13 @@ for ($annee = $year_start ; $annee <= $year_end ; $annee++) } print ''; -print ''.$langs->trans("Month").''; +print ''.$langs->trans("Month").''; for ($annee = $year_start ; $annee <= $year_end ; $annee++) { - if ($modecompta == 'CREANCES-DETTES') print ''.$langs->trans("AmountHT").''; - print ''.$langs->trans("AmountTTC").''; - print ''.$langs->trans("Delta").''; - if ($annee != $year_end) print ' '; + if ($modecompta == 'CREANCES-DETTES') print ''.$langs->trans("AmountHT").''; + print ''.$langs->trans("AmountTTC").''; + print ''.$langs->trans("Delta").''; + if ($annee != $year_end) print ' '; } print ''; diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index c03e41b386c..89e1458d4fd 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -250,11 +250,16 @@ $dolibarr_main_restrict_os_commands='mysqldump, mysql, pg_dump, pgrestore'; $dolibarr_nocsrfcheck='0'; // dolibarr_mailing_limit_sendbyweb -// Can set a limit for mailing send by web. Can be used for a restricted mode. -// Default value: 0 (use database value if exist) -// Examples: -// $dolibarr_mailing_limit_sendbyweb='0'; +// Can set a limit for mailing send by web. This overwrite database value. Can be used to restrict on OS level. +// Default value: '25' +// Examples: '-1' (sending by web is forbidden) +// $dolibarr_mailing_limit_sendbyweb='25'; +// dolibarr_mailing_limit_sendbycli +// Can set a limit for mailing send by cli. This overwrite database value. Can be used to restrict on OS level. +// Default value: '0' (no hard limit, use soft database value if exists) +// Examples: '-1' (sending by cli is forbidden) +// $dolibarr_mailing_limit_sendbycli='0'; //################## @@ -273,18 +278,6 @@ $dolibarr_nocsrfcheck='0'; // Examples: // $dolibarr_main_limit_users='0'; -// dolibarr_mailing_limit_sendbyweb -// Can set a limit for mailing send by web. This overwrite database value. Can be used to restrict on OS level. -// Default value: '0' (no overwrite, use database value if exists) -// Examples: '-1' (sending by web is forbidden) -// $dolibarr_mailing_limit_sendbyweb='0'; - -// dolibarr_mailing_limit_sendbycli -// Can set a limit for mailing send by cli. This overwrite database value. Can be used to restrict on OS level. -// Default value: '0' (no overwrite, use database value if exists) -// Examples: '-1' (sending by cli is forbidden) -// $dolibarr_mailing_limit_sendbycli='0'; - // dolibarr_strict_mode // Set this to 1 to enable the PHP strict mode. For dev environment only. // Default value: 0 (use database value if exist) 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/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 027bedebb6e..9e11001745c 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -488,28 +488,35 @@ class CMailFile // Check number of recipient is lower or equal than MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL=10; - $tmparray = explode(',', $this->addr_to); - if (count($tmparray) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL) + $tmparray1 = explode(',', $this->addr_to); + if (count($tmparray1) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL) { $this->error = 'Too much recipients in to:'; dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING); return false; } - $tmparray = explode(',', $this->addr_cc); - if (count($tmparray) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL) + $tmparray2 = explode(',', $this->addr_cc); + if (count($tmparray2) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_CC_IN_SAME_EMAIL) { $this->error = 'Too much recipients in cc:'; dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING); return false; } - $tmparray = explode(',', $this->addr_bcc); - if (count($tmparray) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL) + $tmparray3 = explode(',', $this->addr_bcc); + if (count($tmparray3) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_BCC_IN_SAME_EMAIL) { $this->error = 'Too much recipients in bcc:'; dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING); return false; } - + if ((count($tmparray1)+count($tmparray2)+count($tmparray3)) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL) + { + $this->error = 'Too much recipients in to:, cc:, bcc:'; + dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING); + return false; + } + + // Action according to choosed sending method if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') { @@ -538,25 +545,28 @@ class CMailFile } else { - $bounce = ''; // By default + $additionnalparam = ''; // By default if (! empty($conf->global->MAIN_MAIL_ALLOW_SENDMAIL_F)) { // le "Return-Path" (retour des messages bounced) dans les header ne fonctionne pas avec tous les MTA // Le forcage de la valeur grace à l'option -f de sendmail est donc possible si la constante MAIN_MAIL_ALLOW_SENDMAIL_F est definie. - // La variable definie pose des pb avec certains sendmail securisee (option -f refusee car dangereuse) - $bounce .= ($bounce?' ':'').(! empty($conf->global->MAIN_MAIL_ERRORS_TO) ? '-f' . $this->getValidAddress($conf->global->MAIN_MAIL_ERRORS_TO,2) : ($this->addr_from != '' ? '-f' . $this->getValidAddress($this->addr_from,2) : '') ); + // Having this variable defined may create problems with some sendmail (option -f refused) + // Having this variable not defined may create problems with some other sendmail (option -f required) + $additionnalparam .= ($additionnalparam?' ':'').(! empty($conf->global->MAIN_MAIL_ERRORS_TO) ? '-f' . $this->getValidAddress($conf->global->MAIN_MAIL_ERRORS_TO,2) : ($this->addr_from != '' ? '-f' . $this->getValidAddress($this->addr_from,2) : '') ); } if (! empty($conf->global->MAIN_MAIL_SENDMAIL_FORCE_BA)) // To force usage of -ba option. This option tells sendmail to read From: or Sender: to setup sender { - $bounce .= ($bounce?' ':'').'-ba'; + $additionnalparam .= ($additionnalparam?' ':'').'-ba'; } - dol_syslog("CMailFile::sendfile: mail start HOST=".ini_get('SMTP').", PORT=".ini_get('smtp_port').", additionnal_parameters=".$bounce, LOG_DEBUG); + if (! empty($conf->global->MAIN_MAIL_SENDMAIL_FORCE_ADDPARAM)) $additionnalparam .= ($additionnalparam?' ':'').'-U '.$additionnalparam; // Use -U to add additionnal params + + dol_syslog("CMailFile::sendfile: mail start HOST=".ini_get('SMTP').", PORT=".ini_get('smtp_port').", additionnal_parameters=".$additionnalparam, LOG_DEBUG); $this->message=stripslashes($this->message); 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); + if (! empty($additionnalparam)) $res = mail($dest, $this->encodetorfc2822($this->subject), $this->message, $this->headers, $additionnalparam); else $res = mail($dest, $this->encodetorfc2822($this->subject), $this->message, $this->headers); if (! $res) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 5e83f59ea36..98bf53743ba 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); diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index c451b2e32fd..81de34e012f 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -282,6 +282,7 @@ class Conf // Define default dir_output and dir_temp for directories of modules foreach($this->modules as $module) { + //var_dump($module); // For multicompany sharings $this->$module->multidir_output = array($this->entity => $rootfordata."/".$module); $this->$module->multidir_temp = array($this->entity => $rootfordata."/".$module."/temp"); 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 ''."\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/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index ad592359936..09f89ba0c3f 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -239,7 +239,7 @@ function show_array_actions_to_do($max=5) print ''; print ''; - print ''; $var = true; @@ -336,7 +336,7 @@ function show_array_last_actions_done($max=5) print '
'.$langs->trans("LastActionsToDo",$max).''.$langs->trans("FullList").''; + print ''.$langs->trans("FullList").''; print '
'; print ''; - print ''; $var = true; $i = 0; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index ff6459413a4..f5f8ec5456d 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -965,7 +965,7 @@ function show_actions_todo($conf,$langs,$db,$filterobj,$objcon='',$noprint=0,$ac * @return mixed Return html part or void if noprint is 1 * TODO change function to be able to list event linked to an object. */ -function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint=0, $actioncode='', $donetodo='done', $filters=array(), $sortfield='a.datep, a.id', $sortorder='DESC') +function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint=0, $actioncode='', $donetodo='done', $filters=array(), $sortfield='a.datep,a.id', $sortorder='DESC') { global $bc,$user,$conf; global $form; @@ -993,16 +993,26 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= $sql.= " u.login, u.rowid as user_id"; if (get_class($filterobj) == 'Societe') $sql.= ", sp.lastname, sp.firstname"; if (get_class($filterobj) == 'Adherent') $sql.= ", m.lastname, m.firstname"; + if (get_class($filterobj) == 'CommandeFournisseur') $sql.= ", o.ref"; $sql.= " FROM ".MAIN_DB_PREFIX."user as u, ".MAIN_DB_PREFIX."actioncomm as a"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action = c.id"; if (get_class($filterobj) == 'Societe') $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON a.fk_contact = sp.rowid"; if (get_class($filterobj) == 'Adherent') $sql.= ", ".MAIN_DB_PREFIX."adherent as m"; + if (get_class($filterobj) == 'CommandeFournisseur') $sql.= ", ".MAIN_DB_PREFIX."commande_fournisseur as o"; $sql.= " WHERE u.rowid = a.fk_user_author"; $sql.= " AND a.entity IN (".getEntity('agenda', 1).")"; if (get_class($filterobj) == 'Societe' && $filterobj->id) $sql.= " AND a.fk_soc = ".$filterobj->id; if (get_class($filterobj) == 'Project' && $filterobj->id) $sql.= " AND a.fk_project = ".$filterobj->id; - if (get_class($filterobj) == 'Adherent') $sql.= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; - if (get_class($filterobj) == 'Adherent' && $filterobj->id) $sql.= " AND a.fk_element = ".$filterobj->id; + if (get_class($filterobj) == 'Adherent') + { + $sql.= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; + if ($filterobj->id) $sql.= " AND a.fk_element = ".$filterobj->id; + } + if (get_class($filterobj) == 'CommandeFournisseur') + { + $sql.= " AND a.fk_element = o.rowid AND a.elementtype = 'order_supplier'"; + if ($filterobj->id) $sql.= " AND a.fk_element = ".$filterobj->id; + } if (is_object($objcon) && $objcon->id) $sql.= " AND a.fk_contact = ".$objcon->id; // Condition on actioncode if (! empty($actioncode)) @@ -1133,6 +1143,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; + require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; @@ -1142,9 +1153,10 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= $userstatic=new User($db); $contactstatic = new Contact($db); - // TODO uniformize + // TODO mutualize/uniformize $propalstatic=new Propal($db); $orderstatic=new Commande($db); + $supplierorderstatic=new CommandeFournisseur($db); $facturestatic=new Facture($db); $out.=''; @@ -1171,7 +1183,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= } $out.=getTitleFieldOfList($langs->trans("Ref"), 0, $_SERVER["PHP_SELF"], 'a.id', '', $param, '', $sortfield, $sortorder); $out.=''; - $out.=getTitleFieldOfList($langs->trans("Date"), 0, $_SERVER["PHP_SELF"], 'a.datep, a.id', '', $param, '', $sortfield, $sortorder); + $out.=getTitleFieldOfList($langs->trans("Date"), 0, $_SERVER["PHP_SELF"], 'a.datep,a.id', '', $param, '', $sortfield, $sortorder); $out.=''; $out.=''; $out.=''; @@ -1286,7 +1298,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon='', $noprint= //$out.=''; // Objet lie - // TODO uniformize + // TODO mutualize/uniformize $out.=''; - print ''; - print ''; - print ''; - print '
'.$langs->trans("LastDoneTasks",$max).''.$langs->trans("FullList").''; + print ''.$langs->trans("FullList").''; print '
'.$langs->trans("Label").''.$langs->trans("Type").''.dol_trunc($histo[$key]['note'], 40).''; //var_dump($histo[$key]['elementtype']); if (isset($histo[$key]['elementtype'])) 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/fourn.lib.php b/htdocs/core/lib/fourn.lib.php index 4c277a69968..3ac3cf49a9c 100644 --- a/htdocs/core/lib/fourn.lib.php +++ b/htdocs/core/lib/fourn.lib.php @@ -101,7 +101,8 @@ function facturefourn_prepare_head($object) */ function ordersupplier_prepare_head($object) { - global $db, $langs, $conf; + global $db, $langs, $conf, $user; + $h = 0; $head = array(); @@ -159,7 +160,12 @@ function ordersupplier_prepare_head($object) $h++; $head[$h][0] = DOL_URL_ROOT.'/fourn/commande/info.php?id='.$object->id; - $head[$h][1] = $langs->trans("Info"); + $head[$h][1].= $langs->trans("Events"); + if (! empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read) )) + { + $head[$h][1].= '/'; + $head[$h][1].= $langs->trans("Agenda"); + } $head[$h][2] = 'info'; $h++; complete_head_from_modules($conf,$langs,$object,$head,$h,'supplier_order', 'remove'); 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/report.lib.php b/htdocs/core/lib/report.lib.php index fa05e632983..f58aa180d88 100644 --- a/htdocs/core/lib/report.lib.php +++ b/htdocs/core/lib/report.lib.php @@ -110,12 +110,9 @@ function report_header($nom,$variante,$period,$periodlink,$description,$builddat if ($exportlink) print ''.$langs->trans("Export").''.$exportlink; print '
'; + print '
'; print ''; dol_fiche_end(); diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 6b14a6c99fa..a3ff1af0726 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -110,8 +110,8 @@ class pdf_einstein extends ModelePDFCommandes { $this->posxtva=99; $this->posxup=114; - $this->posxqty=133; - $this->posxunit=150; + $this->posxqty=130; + $this->posxunit=147; } else { @@ -129,6 +129,7 @@ class pdf_einstein extends ModelePDFCommandes $this->posxtva-=20; $this->posxup-=20; $this->posxqty-=20; + $this->posxunit-=20; $this->posxdiscount-=20; $this->postotalht-=20; } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 1701f82c47b..6b9b2bf5dd0 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -119,8 +119,8 @@ class pdf_crabe extends ModelePDFFactures { $this->posxtva=99; $this->posxup=114; - $this->posxqty=133; - $this->posxunit=150; + $this->posxqty=130; + $this->posxunit=147; } else { @@ -135,12 +135,14 @@ class pdf_crabe extends ModelePDFFactures $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images if ($this->page_largeur < 210) // To work with US executive format { - $this->posxpicture-=20; - $this->posxtva-=20; - $this->posxup-=20; - $this->posxqty-=20; - $this->posxdiscount-=20; - $this->postotalht-=20; + $this->posxpicture-=20; + $this->posxtva-=20; + $this->posxup-=20; + $this->posxqty-=20; + $this->posxunit-=20; + $this->posxdiscount-=20; + $this->posxprogress-=20; + $this->postotalht-=20; } $this->tva=array(); @@ -297,7 +299,7 @@ class pdf_crabe extends ModelePDFFactures $this->atleastonediscount++; } } - if (empty($this->atleastonediscount) && empty($conf->global->PRODUCT_USE_UNITS)) + if (empty($this->atleastonediscount) && empty($conf->global->PRODUCT_USE_UNITS)) // retreive space not used by discount { $this->posxpicture+=($this->postotalht - $this->posxdiscount); $this->posxtva+=($this->postotalht - $this->posxdiscount); @@ -527,9 +529,9 @@ class pdf_crabe extends ModelePDFFactures $pdf->MultiCell($this->posxprogress-$this->posxdiscount+2, 3, $remise_percent, 0, 'R'); } + // Situation progress if ($this->situationinvoice) { - // Situation progress $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails); $pdf->SetXY($this->posxprogress, $curY); $pdf->MultiCell($this->postotalht-$this->posxprogress, 3, $progress, 0, 'R'); diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index 0e3dedb0109..e9c7fb309ad 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -50,8 +50,8 @@ class modAccounting extends DolibarrModules $this->name = preg_replace('/^mod/i', '', get_class($this)); $this->description = "Advanced accounting management"; - // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = 'experimental'; + // Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version + $this->version = 'dolibarr'; $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); $this->special = 0; diff --git a/htdocs/core/modules/modMultiCurrency.class.php b/htdocs/core/modules/modMultiCurrency.class.php index 43e49ce55d3..7eb58e32a3a 100644 --- a/htdocs/core/modules/modMultiCurrency.class.php +++ b/htdocs/core/modules/modMultiCurrency.class.php @@ -62,7 +62,7 @@ class modMultiCurrency extends DolibarrModules $this->description = "Module to enter elements with a foreign currency"; // Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version - $this->version = 'experimental'; + $this->version = 'dolibarr'; // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 9aa1ca994ef..fc2e7a0e5d6 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -108,8 +108,8 @@ class pdf_azur extends ModelePDFPropales { $this->posxtva=99; $this->posxup=114; - $this->posxqty=133; - $this->posxunit=150; + $this->posxqty=130; + $this->posxunit=147; } else { @@ -127,6 +127,7 @@ class pdf_azur extends ModelePDFPropales $this->posxtva-=20; $this->posxup-=20; $this->posxqty-=20; + $this->posxunit-=20; $this->posxdiscount-=20; $this->postotalht-=20; } diff --git a/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php b/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php index c5f68df95c1..dd29a839a48 100644 --- a/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php +++ b/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php @@ -102,8 +102,8 @@ class pdf_canelle extends ModelePDFSuppliersInvoices if($conf->global->PRODUCT_USE_UNITS) { $this->posxtva=99; $this->posxup=114; - $this->posxqty=133; - $this->posxunit=150; + $this->posxqty=130; + $this->posxunit=147; } //if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) $this->posxtva=$this->posxup; $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images @@ -113,6 +113,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $this->posxtva-=20; $this->posxup-=20; $this->posxqty-=20; + $this->posxunit-=20; $this->posxdiscount-=20; $this->postotalht-=20; } diff --git a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php index e76da5abef3..d6d904ecb35 100644 --- a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php @@ -111,8 +111,8 @@ class pdf_muscadet extends ModelePDFSuppliersOrders { $this->posxtva=99; $this->posxup=114; - $this->posxqty=133; - $this->posxunit=150; + $this->posxqty=130; + $this->posxunit=147; } else { $this->posxtva=112; $this->posxup=126; @@ -127,6 +127,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $this->posxtva-=20; $this->posxup-=20; $this->posxqty-=20; + $this->posxunit-=20; $this->posxdiscount-=20; $this->postotalht-=20; } diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index 953b1a46206..e73e7f0f1c6 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -115,6 +115,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $this->posxtva-=20; $this->posxup-=20; $this->posxqty-=20; + $this->posxunit-=20; $this->posxdiscount-=20; $this->postotalht-=20; } 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) { ?>