General developer forum

 
 
Picture of Oleg Mikheev
plugin function in custom block
 

Hello to everyone!

I was created my custom block and put there filemanger form. In lib.php file i was created plugin function. When file was downloaded, i hava a link via pluginfile.php and all users can download it.

But i have a little trouble. I want to get my custom itemid to all downloaded files. In my form i do this:

    file_prepare_draft_area($draftitemid, $blockcontext->id, 'block_kfu_turndocument', $req_id, 'attachments', array('subdirs' => 0, 'maxbytes' => $maxbytes, 'maxfiles' => 50));
    file_save_draft_area_files($draftitemid, $blockcontext->id, 'block_kfu_turndocument', 'attachments', $req_id, array('subdirs' => 0, 'maxbytes' => $maxbytes, 'maxfiles' => 50));

    $fs = get_file_storage();
    $files = $fs->get_area_files($blockcontext->id, 'block_kfu_turndocument', 'attachments', $req_id, 'filename', false);
    foreach ($files as $file) {
     $fullurl_array = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
     $fullurl = '<a href="'.$CFG->wwwroot.'/pluginfile.php/'.$file->get_contextid().'/'.$file->get_component().'/'.$file->get_filearea().'/'.$file->get_filename().'" target="_blank">link</a>';
     print_r($fullurl);
    }

In lib.php i have this code:

    function block_kfu_turndocument_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload) {

....

....

....

    $fs = get_file_storage();

    $filename = array_pop($args);
    $filepath = $args ? '/'.implode('/', $args).'/' : '/';


    if (!$file = $fs->get_file($context->id, 'block_kfu_turndocument', 'attachments', 5, $filepath, $filename) or $file->is_directory()) {
        send_file_not_found();
    }

If you can see, in the get_file function i put custom itemid=5. But it need to be send in pluginfile function by variable. I don't understand how to do it. Thanks for your help.

 
Average of ratings: -
Picture of Jitendra Gaur
Re: plugin function in custom block
 

You can found your solution in this forum - https://moodle.org/mod/forum/discuss.php?d=218454

 
Average of ratings: -
Picture of Oleg Mikheev
Re: plugin function in custom block
 

Hello, Gaur!

I was read this discussion, but not found answer to my question. I think my problem should be solved, when i can give $itemid into pluginfile function in lib.php file. But how can i do this?

 
Average of ratings: -
Davo
Re: plugin function in custom block
Group DevelopersGroup Particularly helpful Moodlers

@Oleg - have you tried looking at how the existing core Moodle plugins retrieve the $itemid within the mod_xx_pluginfile() functions, for example:

https://github.com/moodle/moodle/blob/master/mod/forum/lib.php#l4218

In case you can't figure it out from the above link - if the itemid was used when creating the pluginfile link, then it will be the first item in the 'args' array.

However, you seem to have done something rather strange in the code you included above - you generate $fullurl_array (although that is a very odd name, as it appears to be a moodle_url object, not an array), then, instead of outputting this variable as a link, you generate $fullurl (again, an odd name, as this is a link, not a URL) without reference to $fullurl_array and without including the $itemid in the link.

Normally, you would do something like this:

$fullurl = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
echo '<a href="'.$fullurl.'" target="_blank">link</a>';

 
Average of ratings: -
Picture of Oleg Mikheev
Re: plugin function in custom block
 

Hi, Davo!

i must do like this $itemid = $args[0] ?

About your message for strange $fullurl. If i put $file->get_itemid() moodle write me, that file not found. I was tested this and have strange result. In database itemid was inserted. But if i download by link with it like this , file not found. If i delete /2/ file download perfectly. hmm...

 
Average of ratings: -
Davo
Re: plugin function in custom block
Group DevelopersGroup Particularly helpful Moodlers

Oleg.

The better way of writing the code is $itemid = array_shift($args); (as per the line of code I indicated), this does not rely on the first item in the array having index 0 AND it also removes the first item, so that the args now contains the filepath + filename.

If you include the itemid, then the args value will contain:

[itemid, path, to, the, file, filename.extn]

If you do not include the itemid, then the args value will contain:

[path, to, the, file, filename.extn]

If, as you have done in the code you show, you assume that the args does not start with the itemid, then pop the filename off the end and assume what you have left is the filepath, then it will not work (as you will end searching for a non-existent filepath '/itemid/path/to/the/file' instead of '/path/to/the/file').

 
Average of ratings:Useful (1)
Picture of Oleg Mikheev
Re: plugin function in custom block
 

All works perfectly!

Thank you master Yoda)))

 
Average of ratings: -
Picture of Abdul Bashet
Re: plugin function in custom block
 

Hi Oleg,

Try to see this post. There is a gibhub link below. You will find cliear view how to access files from showimages.php and image.php file.

https://moodle.org/mod/forum/discuss.php?d=220284

 

Hope you will enjoy the the filemanager.

 
Average of ratings: -
Davo
Re: plugin function in custom block
Group DevelopersGroup Particularly helpful Moodlers

Abdul - there are a few issues with your example code, which you might want to fix, before sharing it as an example of good practice.

Fristly, you should never be accessing $_GET params directly - Moodle has built-in optional_param / required_param functions to deal with this.

Secondly, you bypass the FilesAPI by using SQL queries directly into the mdl_files table.

Thirdly, you are using the deprecated get_context_instance function instead of context_xx::instance functions.

Fourthly, you completely bypass the pluginfile.php mechanism for serving files securely from within Moodle (which makes it a terrible example in this case, where someone is specifically asking how to use the correct pluginfile.php mechanism for serving files).

That's all I've spotted from a quick glance.

 
Average of ratings:Useful (1)
Picture of Abdul Bashet
Re: plugin function in custom block
 

Hi Davo,

I would never say my example is a good practice in a sense of moodle. But I would say, those code will help anyone to understand how moodle file system works! And how we can use the parameters to call a file in moodle way.

Unfortunately moodle documentation doesn't explain straight forward with easy example and that's why we have to spend time in forum with this kind of topics.

"There is no benefit to have lots of resources, if we don't know why/which/how to use them"

 
Average of ratings: -
Davo
Re: plugin function in custom block
Group DevelopersGroup Particularly helpful Moodlers

But the problem is that, as outlined above, your code does not demonstrate how to use parameters to call the file in a Moodle way - it shows how to bypass the Moodle way and retrieve files directly.

Yes, the documentation could be improved - I think it is great that Andy Normore started off the local/filemanager example as a demo of how to use the filemanager and access files within Moodle (I extended it and corrected some of the problems in my version here https://github.com/davosmith/filemanager ). Maybe when I have some spare time, I will look at updating the docs at http://docs.moodle.org/dev/File_API and http://docs.moodle.org/dev/Using_the_File_API_in_Moodle_forms or maybe just provide an extra page with a simple worked example in it. However, there are also lots of examples of how to use the files API inside Moodle core - take a look at the code for mod/resource for a reasonably straightforward example.

 
Average of ratings:Useful (1)