l3pp4rd/DoctrineExtensions — pull request #307 by comfortablynumb (2012-04-05 13:50:07+00:00)
Title: [WIP] Uploadable

The minimum requirements to use it:

``` php
/**
* @ORM\Entity
* @Gedmo\Uploadable(fileInfoProperty="fileInfo")
*/
class File
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @ORM\Column(name="path", type="string", nullable=true)
* @Gedmo\UploadableFilePath
*/
private $filePath;

private $fileInfo;

public function setFileInfo(array $fileInfo)
{
$this->fileInfo = $fileInfo;
}
}
```

So, $filePath will contain the full path to the uploaded file. $fileInfo is used to receive the info of the uploaded file and process it.

Usage:

``` php
// Path can be set on the listener as a default for all classes, or in each class via an option on the Uploadable
// annotation: @Gedmo\Uploadable(path="/my/path"). It could even be configured at runtime via a method
// on the class
$listener->setDefaultPath('/my/path');

// Suppose "Article" class has many "Image"s, which is the Uploadable class described before
$art = new Article();

if (isset($_FILES['images'])) {
foreach ($_FILES['images'] as $image) {
// We set the $fileInfo property
$image = new Image();
$image->setFileInfo($image);

$art->addImage($image);

$em->persist($image);
}
}

$em->persist($art);

$em->flush();
```

On flush, uploaded files will be processed and saved on disk. Notice that the extension does not work with $_FILES array directly, so we don't have to worry of the $_FILES index needed, nor handle directly the $_FILES array from the extension.

Now, there's a problem yet to solve. When updating a file, as the $fileInfo property is not part of the schema, if this is the only field that changes on the entity, it won't be marked for update and the listener won't process the new file. Of course, setting a new value on any field will solve this, but there has to be a better way to do this.

Regarding validation and mime type guessing, I agree with both.

One thing that is missing here is how to handle file removal (or avoid it) if any exception happens on the process of the transaction? I've seen an issue you opened about some new events that are needed in Doctrine (onBeginTransaction, onCommit, onRollback), so maybe we should wait to have this events to handle this situation? I'll take a look later to see how much time would require to add them and maybe create a PR for it.

Features:

* Handling of file moving and removal automatically.
* Setting of properties with information about mime type, size, etc.
* Options to allow overwrite, append a number to the file name if it already exists, etc.
* It optionally allows to give a path for each class or even individual file using a method instead of hardcoding the path in the class.
* Not limited to file uploading. It could handle files that already exist on the server (not implemented yet)
* Each of the upload errors has a custom exception

Missing features - Not finished functionalities:

1. It does not include validation nor mime type guessing (yet)
2. If an update on a file is needed and the only value that is changing is the $fileInfo one, then the listener won't process the update, since this property is not part of the schema and, therefore, the change is not recognized.
3. Handle file removal (or avoid it) on exception.
4. Add a post-process-handler option to allow file manipulation after moving the uploaded file.
5. Normalize file names. Maybe include an option to allow the user to configure a custom class to handle this.
6. More tests