[Typo3-dev] TCEmain Hook processing of uploaded files
Christoph Köpernick @ proSystem Media GmbH
christoph at psysm.com
Mon Sep 26 14:26:11 CEST 2005
I´ve found the solution myself, I hope somebody could help this too.
I made a XCLASS extension for TCEmain function
checkValue_group_select_file().
For case 1:
Edit TCEform and remove multiple="multiple" doesn´t take effect, because
the JS of the element browser makes it multiple, if you add an file
through the element browser. Because I don´t want multiple files in the
array I added the following at the beginning of
checkValue_group_select_file().:
if($valueArray[0] && $uploadedFileArray[tmp_name]) {
unset($uploadedFileArray);
}
If a file is already in the field, and a new one is provided the new is
discarded. If a user wants to overwrite the file he has to remove it
first by clicking on the trash (saving directly after this isn´t needed
anymore).
For case 2:
The files are removed AFTER trying to write the new files, see
#$this->removeFilesStore
So I changed $this->removeFilesStore[]=$dest.'/'.$theFile; to
unlink($dest.'/'.$theFile); Now the file is removed (unlinked)
instantly.
Here is my full XCLASS:
<?php
/**
* User-Extension of TCEmain class
*
* @author Christoph Koepernick <christoph at psysm.com>
*/
class ux_t3lib_TCEmain extends t3lib_TCEmain {
function
checkValue_group_select_file($valueArray,$tcaFieldConf,$curValue,$upload
edFileArray,$status,$table,$id,$recFID) {
if($valueArray[0] && $uploadedFileArray[tmp_name]) {
unset($uploadedFileArray);
}
// If any files are uploaded:
if (is_array($uploadedFileArray) &&
$uploadedFileArray['name'] &&
strcmp($uploadedFileArray['tmp_name'],'none')) {
$valueArray[]=$uploadedFileArray['tmp_name'];
$this->alternativeFileName[$uploadedFileArray['tmp_name']] =
$uploadedFileArray['name'];
}
// Creating fileFunc object.
if (!$this->fileFunc) {
$this->fileFunc =
t3lib_div::makeInstance('t3lib_basicFileFunctions');
$this->include_filefunctions=1;
}
// Setting permitted extensions.
$all_files = Array();
$all_files['webspace']['allow'] = $tcaFieldConf['allowed'];
$all_files['webspace']['deny'] = $tcaFieldConf['disallowed']
? $tcaFieldConf['disallowed'] : '*';
$all_files['ftpspace'] = $all_files['webspace'];
$this->fileFunc->init('', $all_files);
// If there is an upload folder defined:
if ($tcaFieldConf['uploadfolder']) {
// For logging..
$propArr = $this->getRecordProperties($table,$id);
// Get destrination path:
$dest =
$this->destPathFromUploadFolder($tcaFieldConf['uploadfolder']);
// If we are updating:
if ($status=='update') {
// Finding the CURRENT files listed, either from
MM or from the current record.
$theFileValues=array();
if ($tcaFieldConf['MM']) { // If MM relations
for the files also!
$dbAnalysis =
t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start('','files',$tcaFieldConf['MM'],$id);
reset($dbAnalysis->itemArray);
while
(list($somekey,$someval)=each($dbAnalysis->itemArray)) {
if ($someval['id']) {
$theFileValues[]=$someval['id'];
}
}
} else {
$theFileValues=t3lib_div::trimExplode(',',$curValue,1);
}
// DELETE files: If existing files were found,
traverse those and register files for deletion which has been removed:
if (count($theFileValues)) {
// Traverse the input values and for all
input values which match an EXISTING value, remove the existing from
$theFileValues array (this will result in an array of all the existing
files which should be deleted!)
foreach($valueArray as $key => $theFile) {
if ($theFile &&
!strstr(t3lib_div::fixWindowsFilePath($theFile),'/')) {
$theFileValues =
t3lib_div::removeArrayEntryByValue($theFileValues,$theFile);
}
}
// This array contains the filenames in the
uploadfolder that should be deleted:
foreach($theFileValues as $key => $theFile) {
$theFile = trim($theFile);
if (@is_file($dest.'/'.$theFile)) {
#$this->removeFilesStore[]=$dest.'/'.$theFile;
unlink($dest.'/'.$theFile);
} elseif ($theFile) {
$this->log($table,$id,5,0,1,"Could not
delete file '%s' (does not exist). (%s)",10,array($dest.'/'.$theFile,
$recFID),$propArr['event_pid']);
}
}
}
}
// Traverse the submitted values:
foreach($valueArray as $key => $theFile) {
// NEW FILES? If the value contains '/' it
indicates, that the file is new and should be added to the uploadsdir
(whether its absolute or relative does not matter here)
if
(strstr(t3lib_div::fixWindowsFilePath($theFile),'/')) {
// Init:
$maxSize = intval($tcaFieldConf['max_size']);
$cmd='';
$theDestFile=''; // Must be cleared. Else
a faulty fileref may be inserted if the below code returns an error!!
(Change: 22/12/2000)
// Check various things before copying file:
if (@is_dir($dest) && (@is_file($theFile) ||
@is_uploaded_file($theFile))) { // File and destination must
exist
// Finding size. For safe_mode we have
to rely on the size in the upload array if the file is uploaded.
if (is_uploaded_file($theFile) &&
$theFile==$uploadedFileArray['tmp_name']) {
$fileSize = $uploadedFileArray['size'];
} else {
$fileSize = filesize($theFile);
}
if (!$maxSize || $fileSize<=($maxSize*1024))
{ // Check file size:
// Prepare filename:
$theEndFileName =
isset($this->alternativeFileName[$theFile]) ?
$this->alternativeFileName[$theFile] : $theFile;
$fI =
t3lib_div::split_fileref($theEndFileName);
// Check for allowed extension:
if
($this->fileFunc->checkIfAllowed($fI['fileext'], $dest,
$theEndFileName)) {
$theDestFile =
$this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($fI['file'
]), $dest);
// If we have a unique
destination filename, then write the file:
if ($theDestFile) {
t3lib_div::upload_copy_move($theFile,$theDestFile);
$this->copiedFileMap[$theFile] =
$theDestFile;
clearstatcache();
if (!@is_file($theDestFile))
$this->log($table,$id,5,0,1,"Copying file '%s' failed!: The destination
path (%s) may be write protected. Please make it write enabled!.
(%s)",16,array($theFile, dirname($theDestFile),
$recFID),$propArr['event_pid']);
} else
$this->log($table,$id,5,0,1,"Copying file '%s' failed!: No destination
file (%s) possible!. (%s)",11,array($theFile, $theDestFile,
$recFID),$propArr['event_pid']);
} else
$this->log($table,$id,5,0,1,"Fileextension '%s' not allowed.
(%s)",12,array($fI['fileext'], $recFID),$propArr['event_pid']);
} else $this->log($table,$id,5,0,1,"Filesize
(%s) of file '%s' exceeds limit (%s).
(%s)",13,array(t3lib_div::formatSize($fileSize),$theFile,t3lib_div::form
atSize($maxSize*1024),$recFID),$propArr['event_pid']);
} else $this->log($table,$id,5,0,1,'The
destination (%s) or the source file (%s) does not exist.
(%s)',14,array($dest, $theFile, $recFID),$propArr['event_pid']);
// If the destination file was created, we
will set the new filename in the value array, otherwise unset the entry
in the value array!
if (@is_file($theDestFile)) {
$info =
t3lib_div::split_fileref($theDestFile);
$valueArray[$key]=$info['file']; // The
value is set to the new filename
} else {
unset($valueArray[$key]); // The value is
set to the new filename
}
}
}
// If MM relations for the files, we will set the
relations as MM records and change the valuearray to contain a single
entry with a count of the number of files!
if ($tcaFieldConf['MM']) {
$dbAnalysis =
t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->tableArray['files']=array(); // dummy
reset($valueArray);
while (list($key,$theFile)=each($valueArray)) {
// explode files
$dbAnalysis->itemArray[]['id']=$theFile;
}
if ($status=='update') {
$dbAnalysis->writeMM($tcaFieldConf['MM'],$id,0);
} else {
$this->dbAnalysisStore[] = array($dbAnalysis,
$tcaFieldConf['MM'], $id, 0); // This will be traversed later to execute
the actions
}
$cc=count($dbAnalysis->itemArray);
$valueArray = array($cc);
}
}
return $valueArray;
}
}
?>
Please write me an email if that also helps for your purpose ;)
Best regards, Christoph Köpernick
> -----Ursprüngliche Nachricht-----
> Von: typo3-dev-bounces at lists.netfielders.de [mailto:typo3-dev-
> bounces at lists.netfielders.de] Im Auftrag von Christoph Köpernick @
> proSystem Media GmbH
> Gesendet: Montag, 26. September 2005 10:54
> An: typo3-dev at lists.netfielders.de
> Betreff: [Typo3-dev] TCEmain Hook processing of uploaded files
>
> Dear List members,
>
> I´d like to preprocess uploaded files in a backend form. So I created
a
> hook, that works. But I got some problems with the names of uploaded
> files.
>
> My hook names the uploaded files (only images) in this scheme
> myextkey_img_1.jpg
> myextkey_img_2.jpg
> ...
>
> by setting
>
> $this->uploadedFileArray['myextkey'][$id]['my'.$k.'img']['name'] =
> 'myextkey_img_'.$k.'.jpg';
>
> Also I want to save them into an extra directory for each $id:
>
> $TCA[$table]['columns']['my'.$k.'img']['config']['uploadfolder'] .=
> '/'.$id];
>
> That works too.
>
> But two strange cases occur:
>
> 1. If an image is already in the select field of the backend form. I
> don´t click on the trash, browse for files on my PC and then submit
the
> form. The new selected image is saved with the postfix _01 and the old
> image is still in the form.
>
> -> Maybe a <select multiple=multiple> problem? But setting multiple=0
or
> false in the TCA doesn´t make any effect. How can I get around this?
>
>
> 2. If an image is already in the select field of the backend form. I
do
> delete it by clicking on the trash, browse for a new image file on my
PC
> and submit. The old image is deleted and the new is saved with postfix
> _01.
>
> -> I´ve no idea how this happens. By looking in the source of tcemain,
I
> think the old file is deleted first and then the new file is saved
(with
> calling for a unique filename).
>
> Now I´ve to delete, save the form, and then select the new to get the
> right filenames and no problems. I´m using 3.7.0
>
> I hope that somebody can help me or make some suggestions how to solve
> that.
>
> Best regards, Christoph Köpernick
>
> _______________________________________________
> Typo3-dev mailing list
> Typo3-dev at lists.netfielders.de
> http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev
More information about the TYPO3-dev
mailing list