5.7 file upload example? (working, but seems ‘sketchy’)

Permalink
I have been watching the 5.6 tutorial videos and trying to translate 5.6 instructions into 5.7… but I am lost when it comes to uploading files.

I managed to get it working, but I am not very confident that this is the best/right way…


relevant parts of controller
<?php namespace Application\Controller\SinglePage ;
use Loader;
use PageController;
use Concrete\Core\File\Importer as Importer;
class MyImages extends PageController {     
        $form = Loader::helper('form');
        $this->set('form',$form);
}
public function update() {
         $fi = new Importer();
         $pathToFile=$_FILES['myImage']['tmp_name'];
         $nameOfFile=$_FILES['myImage']['name'];
         $myFileObject = $fi->import($pathToFile,$nameOfFile);     
         $this->redirect('/my_images','image_updated');
}



<form method="post" action="<?= $this->action('update') ?> " enctype="multipart/form-data">
File: <?= $form->file('myImage') ?>
<?= $form->submit('submit', 'Save') ?>
</form>

ntisithoj
View Replies:
ntisithoj replied on at Permalink Reply
ntisithoj
ok, I can confirm it's not completely correct because when I add

$this->myUI->setAttribute('picture',$myFileObject);


i get

Whoops \ Exception \ ErrorException (E_ERROR)
Call to undefined method Concrete\Core\File\Version::isError()
/store/jw/sites/istandc57/web/concrete/attributes/image_file/controller.php
    // run when we call setAttribute(), instead of saving through the UI
    public function saveValue($obj)
    {
    if (!is_object($obj)) {
    $obj = File::getByID($obj);
    }
    $db = Loader::db();
    if (is_object($obj) && (!$obj->isError())) {
    $db->Replace('atFile', array('avID' => $this->getAttributeValueID(), 'fID' => $obj->getFileID()), 'avID', true);
    }


sooo... now I'm completely lost :( I added the 'Image/File' attribute to the user.

I see that $fv is getting returned from concrete/src/File/Importer.php

if (!($fr instanceof File)) {
    // THIS IS WHERE IT GOES ON A NEW FILE UPLOAD
            // we have to create a new file object for this file version
            $fv = ConcreteFile::add($sanitizedFilename, $prefix, array('fvTitle' => $filename), $fsl);
            $fv->refreshAttributes();
            $fr = $fv->getFile();
    } else {
            // We get a new version to modify
            $fv = $fr->getVersionToModify(true);
            $fv->updateFile($sanitizedFilename, $prefix);
            $fv->refreshAttributes();
    }
    return $fv;


So the $fv object is returned into $myFileObject, and the code in concrete/attributes/image_file/controller.php is clearly looking for isError
if (is_object($obj) && (!$obj->isError())) {


The only place I see isError defined is in concrete/src/File/File.hp
/**
     * @deprecated
     */
public function isError()    {
        return false;
}


So I do not understand why, if $fr is NOT an instance of File (which we know because it passes the “ if (!($fr instanceof File)) {“ condition, why is isError() being called? Or, in more simple terms… how do I fix this?
kimkooren replied on at Permalink Reply
bump
andrew replied on at Permalink Reply
andrew
In general the importer code looks totally correct (apologies that we haven't gotten the updated docs for this but it should be very similar to 5.6.x):

I think the issue is that this is returning a \Concrete\Core\File\Version object, not a \Concrete\Core\File\File object. So $myFileObject isn't actually a file object. You pass this version object into the setAttribute() method, and it really ought to be a file object you pass.

Try this:

$file = $myFileObject->getFile();
$this->myUI->setAttribute('picture', $file);


Now, for developers' sanity we probably ought to detect whether you're passing in a file object or a version object, since we could handle both of them easily and the error that gets thrown isn't tremendously helpful, but I believe that's what's going on.
ntisithoj replied on at Permalink Reply
ntisithoj
Thanks for the info...

def in the rigth directions... i no longer get an error, but nothign is saved... so s little bit closer but still not actually working.

Also, when I print_r($file), should I be seeing the entire session object? because that is what I see. was expecting some smaller.

public function update_data() {
        if ($this->myUI instanceof UserInfo) {
            $fs = FileSet::getByName('test garbage');
            $fsp = new Permissions($fs);
            $fsp = FilePermissions::getGlobal();
            if ($fsp->canAddFiles()) {
                $pathToFile = $_FILES['myImage']['tmp_name'];
                $nameOfFile = $_FILES['myImage']['name'];                
                $fi = new Importer();
                $myFileObject = $fi->import($pathToFile, $nameOfFile, true);
                if (is_object($myFileObject)) {
                    $file = $myFileObject->getFile();
//  with the following line, no error but nothing is saved to the attribute (but the file is uploaded into FM
                    $this->myUI->setAttribute('favorite_picture', $file);
//  with the following line, "Call to undefined method Concrete\Core\File\Version::isError() "
andrew replied on at Permalink Reply
andrew
That's really strange. I just tried this using a setAttribute call on a user info object with a file object and it worked. This will only work with the first line of code in your example, not the second.
andrew replied on at Permalink Reply
andrew
I would try adding some debug code and exit; into the concrete/attributes/file/controller.php "saveValue" method. That method is one of the last run to insert the actual association between the file object and the attribute.