diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php
index 60ed409fc7f..b33ea772aa8 100644
--- a/htdocs/core/class/html.formfile.class.php
+++ b/htdocs/core/class/html.formfile.class.php
@@ -863,7 +863,7 @@ class FormFile
* @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 string $relativepath Relative path of docs (autodefined if not provided), relative to module.
* @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)
@@ -871,23 +871,40 @@ class FormFile
* @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 msut provide a value, -1 is deprecated and must not be used any more)
* @return int <0 if KO, nb of files shown if OK
+ * @return string $upload_dir Full path directory so we can know dir relative to MAIN_DATA_ROOT.
*/
- 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='')
{
global $user, $conf, $langs, $hookmanager;
global $bc;
global $sortfield, $sortorder, $maxheightmini;
+ // 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
+ $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir);
+ $rel_dir = preg_replace('/^[\\/]/','',$rel_dir);
+
$hookmanager->initHooks(array('formfile'));
-
$parameters=array(
'filearray' => $filearray,
'modulepart'=> $modulepart,
'param' => $param,
'forcedownload' => $forcedownload,
- 'relativepath' => $relativepath,
+ 'relativepath' => $relativepath, // relative filename to module dir
+ 'reldir' => $rel_dir, // relative dirname to DOL_DATA_ROOT
'permtodelete' => $permonobject,
'useinecm' => $useinecm,
'textifempty' => $textifempty,
@@ -942,10 +959,42 @@ class FormFile
print_liste_field_titre('');
print "\n";
+ // Get list of files stored into database for same directory
+ $filearrayindatabase = dol_dir_list_in_database($rel_dir, '', 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']=$filearrayindatabase[$key2]['position'];
+ $filearray[$key]['cover']=$filearrayindatabase[$key2]['cover'];
+ $filearray[$key]['acl']=$filearrayindatabase[$key2]['acl'];
+ $found=1;
+ break;
+ }
+ }
+ if (! $found)
+ {
+ $filearray[$key]['position']=999999; // File not indexed are at end. So if we add a file, it will not replace existing in position
+ $filearray[$key]['cover']=0;
+ $filearray[$key]['acl']='';
+ }
+ }
+
+ $filearray=dol_sort_array($filearray, 'position');
+ //var_dump($filearray);
+
$nboffiles=count($filearray);
-
if ($nboffiles > 0) include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
-
+
$var=true;
foreach($filearray as $key => $file) // filearray must be only files here
{
@@ -953,23 +1002,13 @@ class FormFile
&& $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;
- print ''."\n";
+ print ''."\n";
+ // Do we have entry into database ?
+ print ''."\n";
print '
';
print '';
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index cc22f44ec48..059448b35dc 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)
{
@@ -205,6 +206,82 @@ 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
+ * @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 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(
+ "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
*
@@ -751,7 +828,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n
$rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename);
if (! preg_match('/\/temp\//', $rel_filetodelete)) // If not a tmp file
{
- $rel_filetodelete = preg_replace('/^\//', '', $rel_filetodelete);
+ $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete);
dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG);
include DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
@@ -1083,10 +1160,10 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
else // Update table of files
{
$rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir);
- if (! preg_match('/\/temp\//', $rel_dir)) // If not a tmp file
+ if (! preg_match('/[\\/]temp[\\/]/', $rel_dir)) // If not a tmp file
{
- $rel_dir = preg_replace('/\/$/', '', $rel_dir);
- $rel_dir = preg_replace('/^\//', '', $rel_dir);
+ $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
+ $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
include DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
$ecmfile=new EcmFiles($db);
@@ -1384,11 +1461,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='')
{
@@ -1682,7 +1759,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')
{
@@ -1691,7 +1768,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')
@@ -1806,6 +1883,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/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php
index 83d38793072..546cec91142 100644
--- a/htdocs/core/tpl/document_actions_post_headers.tpl.php
+++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php
@@ -79,7 +79,7 @@ $formfile->list_of_documents(
$modulepart,
$param,
0,
- $relativepathwithnofile, // relative path with no file. For example "moduledir/0/1"
+ $relativepathwithnofile, // relative path with no file. For example "0/1"
$permission,
0,
'',
@@ -87,7 +87,8 @@ $formfile->list_of_documents(
'',
'',
0,
- $permtoedit
+ $permtoedit,
+ $upload_dir
);
print " ";
diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php
index 0133bff2580..0e1885fa62f 100644
--- a/htdocs/ecm/class/ecmfiles.class.php
+++ b/htdocs/ecm/class/ecmfiles.class.php
@@ -136,6 +136,21 @@ class EcmFiles //extends CommonObject
}
if (empty($this->date_c)) $this->date_c = dol_now();
+ $maxposition=0;
+ if (empty($this->position)) // Get max used
+ {
+ $sql = "SELECT MAX(position) as maxposition FROM " . MAIN_DB_PREFIX . $this->table_element;
+ $sql.= " WHERE filepath ='".$this->filepath."'";
+
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $obj = $this->db->fetch_object($resql);
+ $maxposition = (int) $obj->maxposition;
+ }
+ else dol_print_error($this->db);
+ }
+ $maxposition=$maxposition+1;
// Check parameters
// Put here code to add control on parameters values
@@ -167,7 +182,7 @@ class EcmFiles //extends CommonObject
$sql .= ' '.(! isset($this->description)?'NULL':"'".$this->db->escape($this->description)."'").',';
$sql .= ' '.(! isset($this->keywords)?'NULL':"'".$this->db->escape($this->keywords)."'").',';
$sql .= ' '.(! isset($this->cover)?'NULL':"'".$this->db->escape($this->cover)."'").',';
- $sql .= ' '.(! isset($this->position)?'0':$this->db->escape($this->position)).',';
+ $sql .= ' '.$maxposition.',';
$sql .= ' '.(! isset($this->gen_or_uploaded)?'NULL':"'".$this->db->escape($this->gen_or_uploaded)."'").',';
$sql .= ' '.(! isset($this->extraparams)?'NULL':"'".$this->db->escape($this->extraparams)."'").',';
$sql .= ' '."'".$this->db->idate($this->date_c)."'".',';
diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql
index 9c6aefdec6d..73d209b0cdc 100644
--- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql
+++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql
@@ -27,3 +27,4 @@
ALTER TABLE llx_ecm_files CHANGE COLUMN fullpath filepath varchar(750);
ALTER TABLE llx_ecm_files ADD COLUMN position integer;
+ALTER TABLE llx_ecm_files CHANGE COLUMN keyword keyword varchar(750);
diff --git a/htdocs/install/mysql/tables/llx_ecm_files.key.sql b/htdocs/install/mysql/tables/llx_ecm_files.key.sql
index 9b1f4fcf164..2b8b1348ba3 100644
--- a/htdocs/install/mysql/tables/llx_ecm_files.key.sql
+++ b/htdocs/install/mysql/tables/llx_ecm_files.key.sql
@@ -17,5 +17,7 @@
-- ============================================================================
-ALTER TABLE llx_ecm_files ADD UNIQUE INDEX uk_ecm_files (label, entity);
+ALTER TABLE llx_ecm_files ADD UNIQUE INDEX uk_ecm_files (label, entity); -- label is a md5
--ALTER TABLE llx_ecm_files ADD UNIQUE INDEX uk_ecm_files_fullpath(fullpath); Disabled, mysql limits size of index
+
+
diff --git a/htdocs/install/mysql/tables/llx_ecm_files.sql b/htdocs/install/mysql/tables/llx_ecm_files.sql
index 7a30066c2b2..45157cdf959 100644
--- a/htdocs/install/mysql/tables/llx_ecm_files.sql
+++ b/htdocs/install/mysql/tables/llx_ecm_files.sql
@@ -19,13 +19,13 @@
CREATE TABLE llx_ecm_files
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
- label varchar(64) NOT NULL,
+ label varchar(64) NOT NULL, -- label contains a md5
entity integer DEFAULT 1 NOT NULL, -- multi company id
- filepath varchar(750) NOT NULL, -- relative to dolibarr document dir. example module/def
+ filepath varchar(750) NOT NULL, -- relative to dolibarr document dir. Example module/def
filename varchar(255) NOT NULL, -- file name only without any directory
fullpath_orig varchar(750), -- full path of original filename, when file is uploaded from a local computer
description text,
- keywords text, -- list of keywords, separated with comma
+ keywords varchar(750), -- list of keywords, separated with comma. Must be limited to most important keywords.
cover text, -- is this file a file to use for a cover
position integer, -- position of file among others
gen_or_uploaded varchar(12), -- 'generated' or 'uploaded'
|