symfony2admingenerator / AvocodeFormExtensionsBundle

(old-legacy) Symfony2 form extensions for Admingenerator project (also working standalone!)
Other
48 stars 31 forks source link

afe_single_upload issue #129

Closed lionelbzv closed 10 years ago

lionelbzv commented 10 years ago

Env = SF2.3 / Propel 1.6 / AdminGeneratorGenerator 1.0.0

Since 01c2a0e9c3491c2f6acc4c1a9739e60c48b5f92b i've got an Exception for the "afe_single_upload" extension.

Call to undefined method: getUploaded_file_name 

acme-generator.yml

                uploaded_file_name:
                    dbType:                     VARCHAR
                    label:                      Photo
                    formType:                   afe_single_upload
                    addFormOptions:
                        nameable:              fileName
                        deleteable:             fileName
                        data_class:             Symfony\Component\HttpFoundation\File\File

Acme code:

class Acme {
    // virtual column to manage file upload
    public $uploaded_file_name;

    /**
     *
     */
    public function getUploadedFileNameWebPath()
    {
        return Acme::UPLOAD_WEB_PATH . $this->file_name;
    }

    /**
     *
     */
    public function getAbsolutePath() {
        return __DIR__ . Acme::UPLOAD_PATH . $this->getFileName();
    }

    /**
     * 
     */
    public function getUploadedFileName()
    {
        // inject file into property (if uploaded)
        if ($this->file_name) {
            return new \Symfony\Component\HttpFoundation\File\File(
                $this->getAbsolutePath()
            );
        }

        return null;
    }

    /**
     *  Gestion physique de l'upload
     */
    public function upload($file = null)
    {
        if (null === $file) {
            return;
        }

        // Extension et nom de fichier
        $extension = $file->guessExtension();
        if (!$extension) {
              $extension = 'bin';
        }
        $fileName = 'acme-' . uniq() . '.' . $extension;

        // move takes the target directory and then the target filename to move to
        $fileUploaded = $file->move(__DIR__ . Acme::UPLOAD_PATH, $fileName);

        // file_name
        return $fileName;
    }    

    /**
     *  Surcharge pour gérer la suppression physique.
     */
    public function setFileName($v)
    {
        if (!$v) {
            $this->removeUpload(true);
        }
        parent::setFileName($v);
    }

    /**
     *  Surcharge pour gérer la suppression physique.
     */
    public function postDelete(\PropelPDO $con = null)
    {
        $this->removeUpload();
    }

    /**
     *  Suppression physique des fichiers.
     */
    public function removeUpload($uploaded_file_name = true)
    {
        if ($uploaded_file_name && $this->file_name && file_exists(__DIR__ . Acme::UPLOAD_PATH . $this->file_name)) {
            unlink(__DIR__ . Acme::UPLOAD_PATH . $this->file_name);
        }
    }

If I just add the missing specified method (getUploaded_file_name), it goes right, but perhaps I'm going wrong in config somewhere?

Thanks.

denys281 commented 10 years ago

Confirm. I have same issue.

ioleo commented 10 years ago

Well, your field name is uploaded_file_name.

The getter and setter both are defined as 'get'.ucfirst($field).. where $field is defined as $child->getName().

So yes, this is expected behaviour. Your field is uploaded_file_name so the getter is getUploaded_file_name.

Change your field name to uploadedFileName and your code will be OK.

lionelbzv commented 10 years ago

Thanks @loostro for your explanations but something has been broken or is not clear somewhere, I can't have a satisfying working solution.

If I change the field name to uploadedFileName has you suggest, I've got either an upload error or an display problem, depend how I implement the getUploadedFileName method.

Note: the DB field name is file_name

Good display / Exception on upload:

    /**
     * 
     */
    public function getUploadedFileName()
    {
        // inject file into property (if uploaded)
        if ($this->file_name) {
            return new \Symfony\Component\HttpFoundation\File\File(
                __DIR__ . MyObject::UPLOAD_PATH . $this->file_name
            );
        }

        return null;
    }

Good upload / No display if file has been uploaded:

    public function getUploadedFileName()
    {
        return $this->uploadedFileName;
    }

config-generator.yml

                uploadedFileName:
                    dbType:                     VARCHAR
                    label:                      Photo
                    formType:                   afe_single_upload
                    addFormOptions:
                        nameable:               fileName
                        deleteable:             fileName
                        data_class:             Symfony\Component\HttpFoundation\File\File
denys281 commented 10 years ago

For me, all works.

lionelbzv commented 10 years ago

@denys281 can you please show me your class model code? thanks

denys281 commented 10 years ago

@StudioEcho

Part of model (I use vich uploader)

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;

  /**
    * @Assert\File(
    *     maxSize="10M",
    *     mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
    * )
    * @Vich\UploadableField(mapping="event", fileNameProperty="photo1")
    */
  public $firstPhoto;

  /**
   * @var string
   *
   * @ORM\Column(name="photo_1", type="string", length=255, nullable=true)
   */
  private $photo1;

/**
   * Set photo1
   *
   * @param string $photo1
   * @return Event
   */
  public function setPhoto1($photo1)
  {
    $this->photo1 = $photo1;

    return $this;
  }

  /**
   * Get photo1
   *
   * @return string
   */
  public function getPhoto1()
  {
    return $this->photo1;
  }

  /**
     * Get Picture File
     *
     * @return File
     */
    public function getFirstPhoto()
    {
        return $this->firstPhoto;
    }

    /**
     * Set picture file as $file
     *
     * @param  File    $file
     */
    public function setFirstPhoto(File $firstPhoto = null)
    {
        $this->firstPhoto = $firstPhoto;

        if ($firstPhoto) {
            $this->updatedAt = new \DateTime('now');
        }

        return $this;
    }
firstPhoto:
        label:            Photo 1
        formType:         afe_single_upload
        dbType:           string
        addFormOptions:
         data_class:     Symfony\Component\HttpFoundation\File\File
lionelbzv commented 10 years ago

thanks @denys281 my config is w. Propel & "without dependancies" (Vich, etc.), so I cannot get your config

@loostro with my last config, the Exception throwed in the getUploadedFileName method is:

The file "/my/absolute/path/to/model/../../../web/upload/path/selected-upload-file-name.jpg" does not exist

it's right, this file does not exist, it has not been uploaded yet: I've inherit the "preSave" method to do the upload in the EditController, but the call has not been done yet.

    /**
     * Manage file upload
     *
     * @param \Symfony\Component\Form\Form $form the valid form
     * @param \My\Current\Model $currentObject object
     */
    public function preSave(\Symfony\Component\Form\Form $form, \My\Current\Model $currentObject)
    {
        $file = $form['uploadedFileName']->getData();
        if ($file) {
            $currentObject->removeUpload();
            $fileName = $currentObject->upload($file);
            $currentObject->setFileName($fileName);
        }
    }

I feel a little bit confused, my previous code was ok but now I can't fix it.

lionelbzv commented 10 years ago

I finally got it, I just had to delete the nameable property in the yml config file.

Sorry for this huge monolog :)

ioleo commented 10 years ago

@StudioEcho I do huge monologs on github sometimes too, don't worry :P I kept reading, I just had no anwsers for you, thats why I didn't reply. I'm glad you resolved it.