How to display uploader without form builder

emergingdzns - 7 months ago

I'm building a module with severals streams. I need to display a form on the front end of the site. This one form is going to post data to various streams (depending on input). Those streams include some file field types and some files field types.

But I can't figure out how to display the field type on the front end without using the form builder.

If it's not possible, how to do I handle the uploading on my controller?

jcastillotx - 7 months ago

So you need to be able to send data based on conditions to other streams ??

emergingdzns - 7 months ago

Sort of. I have a stream called "registration". There are 3 sub-types of registrations, each with it's own stream because each sub-type has different data fields. So building my form, I have it setup using javascript to show the fields for each sub-type depending on the one chosen. So, when the data is submitted it includes the registration stream data and the data for the sub-type chosen. Two of the sub types have a file field type and one has a files field type.

So in my form I have basic file selectors and submitting to my controller. In the controller I have the following (with a LOT stripped out to simplify the example):

use Request;
...
public function receiveData(Request $request) {
                if ($request->file('form_field_name')) {
                    if ($upload_file = $uploader->upload($request->file('form_field_name'), $folders->find('named_folder'))) {
                        print_r($upload_file->getAttributes());
                    }
                }
}

Just trying to get a handle on how to have the system automatically handle the file in a way that makes more sense than how I'm doing it above. Seems like I ought to be able to say use Request; ... public function receiveData(Request $request) { if ($request->file('form_field_name')) { if ($upload_file = $uploader->upload($request->file('form_field_name'), $folders->find('named_folder'))) { print_r($upload_file->getAttributes()); } } } or something like this and have it know to take the file I named and deal with the upload data and add it to the records based on the stream configuration.

piterden - 7 months ago

    /**
     * Accepts the information of the uploaded file as provided by the PHP global $_FILES.
     *
     * The file object is only created when the uploaded file is valid (i.e. when the
     * isValid() method returns true). Otherwise the only methods that could be called
     * on an UploadedFile instance are:
     *
     *   * getClientOriginalName,
     *   * getClientMimeType,
     *   * isValid,
     *   * getError.
     *
     * Calling any other method on an non-valid instance will cause an unpredictable result.
     *
     * @param string      $path         The full temporary path to the file
     * @param string      $originalName The original file name
     * @param string|null $mimeType     The type of the file as provided by PHP; null defaults to application/octet-stream
     * @param int|null    $size         The file size
     * @param int|null    $error        The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
     * @param bool        $test         Whether the test mode is active
     *
     * @throws FileException         If file_uploads is disabled
     * @throws FileNotFoundException If the file does not exist
     */
                    $uploaded = new UploadedFile(
                        $path,
                        $name,
                        $mime,
                        filesize($file),
                        null,
                        true
                    );

                    $file = $this->uploader->upload($uploaded, $folder);
                }

emergingdzns - 7 months ago

Thanks. I have that already. My point is, that the stream that has the files field type has another table that's associated because on that stream the user can upload multiple files. It seems strange that with all the intelligence built into P3 that there's no simply one-line that I could write that would make it take all the files uploaded, put them where they need to go, associate them to the files module AND also add the record of those files to the stream that I'm working with. Instead it looks like I'm going to have to create a model for that sub-table that has just the relationship for the files to the stream. Maybe there is a way to do it but it isn't documented anywhere. There's documentation on how to DISPLY files AFTER they are uploaded, but nothing about the actual uploading/relationship process.

ryanthompson - 7 months ago

I would start with obtaining the field type from the field type collection and start building it up with whatever it needs to operate. Off the top of my head idk but $useMe = $fieldTypes->get('files'); or file or whatever. Then see what breaks and keep adding information to it until it doesn't break lol

emergingdzns - 7 months ago

Ok I made a break through in a sort of "duh" moment. I've got it able to upload the file, get the ids and assign the id to the stream. However, I have one more question about this. I need to be able to create a folder dynamically, if it doesn't already exist, either for the user or for the specific "registration" object. I have it now doing this to get the top level folder:

$folder = $folders->findBySlug('works');

But I would like to then add a sub-folder inside of the 'works' folder. So for registration id $folder = $folders->findBySlug('works'); I would like a folder inside of 3456 called works. How do I do this. I've been digging through the files module looking for clues as to how to add the folder but I'm just not seeing it. Can someone point me in the right direction there?

edster - 1 month ago

@emergingdzns not sure if you solved this but you can't have a sub-folder in the files module. (This was a long discussion I had with Ryan back in alpha/beta). It was decided it isn't needed unfortunately.

emergingdzns - 1 month ago

Thanks @edster . I understand that hierarchical structures like this are difficult. The challenge that I have is that the files module doesn't rename the files when uploaded. So, in our case, we have several thousand clients that are uploading files to be secure and if we don't segregate the files there's a possibility that the files could end up with the same name. For example it could be as simple as Document.docx. If two people upload we could run into a real problem. The old Pyro would rename the files with a hash that I think was timestamp based so you shouldn't end up with the same file name. It would then rename the file back to the original when it is downloaded.

I was able to work around it to a degree in the code but ultimately, for someone that's not a coder and just using P3 as a CMS they may not be able to work around it. Not saying that adding nested folders is the answer, but just might want to think about the naming collision issue.

edster - 1 month ago

I agree with you, I'm actually dealing with this exact issue right now. Laravel assigns a has by default, however the files ft uses the original name instead.

emergingdzns - 1 month ago

I just looked at my code and remembered that I never did actually find a work-around for it. I needed to get back to this but never did. Thanks for the reminder. I was WANTING to be able to add something to the $uploader->upload(request()->file('upload'), $folder)). So I guess I should put in a feature request for adding a file name as a 3rd parameter to the upload() function. That way, we can programmatically assign whatever name we want to the file when it's actually saved to disk. If a file name isn't passed into the function then it would default to the file's original name. Thoughts?