我需要支持TYPO3 Flow中文件上传的multiple
属性(<input type="file" multiple />
)。所以这就是我到目前为止所做的。
我是一个拥有资源集合的实体:
/**
* @var \Doctrine\Common\Collections\Collection<\TYPO3\Flow\Resource\Resource>
* @ORM\ManyToMany(cascade={"all"})
* @ORM\JoinTable(inverseJoinColumns={@ORM\JoinColumn(unique=true,onDelete="cascade")})
*/
protected $resources;
因此我增强了f:form.upload
视图助手:
/**
* Overrides upload view helper.
*/
class UploadViewHelper extends \TYPO3\Fluid\ViewHelpers\Form\UploadViewHelper {
/**
* Initialize the arguments.
*
* @return void
* @api
*/
public function initializeArguments() {
parent::initializeArguments();
$this->registerArgument('multiple', 'boolean', 'Specifies that the user is allowed to enter more than one value in the <input> element.', FALSE, FALSE);
}
/**
* Renders the upload field.
*
* @return string
* @api
*/
public function render() {
$name = $this->getName();
$multiple = $this->arguments['multiple'];
$this->registerFieldNameForFormTokenGeneration($name);
$output = '';
if ($multiple) {
$collectionObject = $this->getUploadedResources();
if ($collectionObject !== NULL) {
foreach($collectionObject as $resourceObjectIndex => $resourceObject) {
$output .= $this->renderUploadedResource($resourceObject, $resourceObjectIndex);
}
}
$this->tag->addAttribute('multiple', 'multiple');
} else {
$resourceObject = $this->getUploadedResource();
if ($resourceObject !== NULL) {
$output .= $this->renderUploadedResource($resourceObject);
}
}
$this->tag->addAttribute('type', 'file');
$this->tag->addAttribute('name', $name);
$this->setErrorClassAttribute();
$output .= $this->tag->render();
return $output;
}
protected function renderUploadedResource($resourceObject, $resourceObjectIndex = NULL) {
$output = '';
$resourceObjectIndex = $resourceObjectIndex === NULL ? '' : '[' . $resourceObjectIndex . ']';
$filenameIdAttribute = $resourcePointerIdAttribute = '';
if ($this->hasArgument('id')) {
$filenameIdAttribute = ' id="' . htmlspecialchars($this->arguments['id']) . '-filename"';
$resourcePointerIdAttribute = ' id="' . htmlspecialchars($this->arguments['id']) . '-resourcePointer"';
}
$filenameValue = $resourceObject->getFilename();
$resourcePointerValue = $resourceObject->getResourcePointer();
$output .= '<input type="hidden" name="' . parent::getName() . $resourceObjectIndex . '[submittedFile][filename]" value="' . htmlspecialchars($filenameValue) . '"' . $filenameIdAttribute . ' />';
$output .= '<input type="hidden" name="' . parent::getName() . $resourceObjectIndex . '[submittedFile][resourcePointer]" value="' . htmlspecialchars($resourcePointerValue) . '"' . $resourcePointerIdAttribute . ' />';
return $output;
}
/**
* Returns a previously uploaded resources.
* If errors occurred during property mapping for this property, NULL is returned
*
* @return \Doctrine\Common\Collections\Collection
*/
protected function getUploadedResources() {
if ($this->getMappingResultsForProperty()->hasErrors()) {
return NULL;
}
$collectionObject = $this->getValue(FALSE);
if ($collectionObject instanceof Collection) {
return $collectionObject;
}
return $this->propertyMapper->convert($collectionObject, 'Doctrine\Common\Collections\Collection<\TYPO3\Flow\Resource\Resource>');
}
/**
* Override `getName()`.
*
* @return string Name
*/
protected function getName() {
$name = parent::getName();
return $this->postfixFieldName($name);
}
/**
* Append `[]` to the field name when the argument `multiple` is set.
*
* @param string $name
* @return string Name
*/
protected function postfixFieldName($name) {
return $this->hasArgument('multiple') && $this->arguments['multiple'] ? $name . '[]' : $name;
}
}
因此视图帮助器<my:form.upload property="resources" multiple="1" />
将为多个文件创建一个数组字段:
<input multiple="multiple" name="entity[resources][]" type="file">
如果已经上传,则显示如下:
<input name="entity[resources][0][submittedFile][filename]" value="Foo.jpg" type="hidden">
<input name="entity[resources][0][submittedFile][resourcePointer]" value="7c94c0200e9f25b1ccb48c2853147f52286328d0" type="hidden">
<input multiple="multiple" name="entity[resources][]" type="file">
为了使其正常工作,我将其添加到控制器中:
protected function initializeAction() {
parent::initializeAction();
switch($this->actionMethodName) {
case 'createAction':
case 'updateAction':
$this->arguments
->getArgument('resource')
->getPropertyMappingConfiguration()
->forProperty('resources.*')
->setTypeConverterOption(
'TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter',
\TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED,
TRUE
);
break;
}
}
问题是,每次调用更新操作时,只要上传已经存在,就会重新添加现有上传,并且表typo3_flow_resource_resource
会增长和增长。有人知道如何解决这个问题吗?
通知 此解决方案应仅允许替换上传的文件。