Accessing Course Files via PHP and MySQL

Re: Accessing Course Files via PHP and MySQL

by Frank Troglauer -
Number of replies: 7

Thanks for pointing me in sort of the right direction Gareth. Unfortunately, I haven't been 100% successful with it. Nowhere on that page does it talk about getting the base information for the queries on that page. Thankfully I found this post that had some hints at what I wanted. 

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

From that page, I built my query. 

$sql = "SELECT f.id, f.contextid, f.component, f.filearea, f.itemid, f.filepath, f.filename

          FROM mdl_context cx

          JOIN mdl_course c ON cx.instanceid=c.id

          JOIN mdl_files f ON cx.id=f.contextid

          WHERE f.filename <> '.'

          AND f.component = 'course'

          AND c.id = $cid ";

  $result = $DB->get_records_sql($sql);

  

When that runs I get this. 

array (size=1)
  29669 => 
    object(stdClass)[264]
      public 'id' =>  '29669' (length=5)
      public 'contextid' =>  '96' (length=2)
      public 'component' =>  'course' (length=6)
      public 'filearea' =>  'overviewfiles' (length=13)
      public 'itemid' =>  '0' (length=1)
      public 'filepath' =>  '/' (length=1)
      public 'filename' =>  'CoursePhoto.jpg' (length=15)


Which is great because it is all of the information needed for some of the FileAPI scripts. The problem is I don't know how to build the link to display the file to users when they load a page. According to the warnings for the FileAPI Read section I should be using the File Browser instead. Here is my code showing use of file storage and file browser. 


if(count($result) == 0){

    return "images/centrifugal%20pump%2011.png";

  }else{

    $fs = get_file_storage();

    $fb = new file_browser();

    foreach($result as $key=>$value){

      $url = $fs->get_file($value->contextid, $value->component, $value->filearea, $value->itemid, $value->filepath, $value->filename);

      $context = context::instance_by_id($value->contextid);

      $url2 = $fb->get_file_info($context, $value->component, $value->filearea, $value->itemid, $value->filepath, $value->filename);

    }


$url var_dumps to this. 

object(stored_file)[262]
  private 'fs' => 
    object(file_storage)[253]
      private 'filedir' =>  'D:\ABC\wamp\moodledata2/filedir' (length=31)
      private 'trashdir' =>  'D:\ABC\wamp\moodledata2/trashdir' (length=32)
      private 'tempdir' =>  'D:\ABC\wamp\moodledata2/temp/filestorage' (length=40)
      private 'dirpermissions' =>  '511' (length=3)
      private 'filepermissions' =>  '438' (length=3)
  private 'file_record' => 
    object(stdClass)[266]
      public 'id' =>  '29669' (length=5)
      public 'contenthash' =>  'c99973ab39ab64550229ad896bcb31b07a4136d5' (length=40)
      public 'pathnamehash' =>  '6090dd889624ac111dfa4027bc218cbbbd339218' (length=40)
      public 'contextid' =>  '96' (length=2)
      public 'component' =>  'course' (length=6)
      public 'filearea' =>  'overviewfiles' (length=13)
      public 'itemid' =>  '0' (length=1)
      public 'filepath' =>  '/' (length=1)
      public 'filename' =>  'CoursePhoto.jpg' (length=15)
      public 'userid' =>  '6' (length=1)
      public 'filesize' =>  '16385' (length=5)
      public 'mimetype' =>  'image/jpeg' (length=10)
      public 'status' =>  '0' (length=1)
      public 'source' =>  'centrifugal-pump-11b.jpg' (length=24)
      public 'author' =>  'Willy Wonka' (length=15)
      public 'license' =>  'allrightsreserved' (length=17)
      public 'timecreated' =>  '1511229957' (length=10)
      public 'timemodified' =>  '1511229964' (length=10)
      public 'sortorder' =>  '0' (length=1)
      public 'referencefileid' => null
      public 'repositoryid' => null
      public 'reference' => null
      public 'referencelastsync' => null
  private 'filedir' =>  'D:\ABC\wamp\moodledata2/filedir' (length=31)
  private 'repository' => null

$url2 var_dumps to null. 


So my main problem right now is I am not getting a URL that I can use to show the image stored in the course overviewfiles area. Any additional help with this would be greatly appreciated. 

In reply to Frank Troglauer

Re: Accessing Course Files via PHP and MySQL

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers
In reply to Gareth J Barnard

Re: Accessing Course Files via PHP and MySQL

by Frank Troglauer -

Gareth,

I didn't even attempt get_file because the documentation clearly states

    This is a way to read a file, equivalent to file_get_contentsPlease note your are allowed to do this ONLY from mod/mymodule/* code, it is not acceptable to do this anywhere else. Other code has to use file_browser interface instead.

and the code I am writing that would use it would be in the /local/ directory. That is why I looked into the file_browser interface but couldn't figure out a proper method from there. 


In reply to Frank Troglauer

Re: Accessing Course Files via PHP and MySQL

by Frank Troglauer -

Gareth,

After more research I finally gave in and decided what I wanted to do had to be done with either get_file or make_plugin_file_url. I stuck with the get_file method and ended up with this. 

_______________________________________

  $sql = "SELECT f.id, f.contextid, f.component, f.filearea, f.itemid, f.filepath, f.filename

          FROM mdl_context cx

          JOIN mdl_course c ON cx.instanceid=c.id

          JOIN mdl_files f ON cx.id=f.contextid

          WHERE f.filename <> '.'

          AND f.component = 'course'

          AND c.id = $cid ";


  $result = $DB->get_records_sql($sql);


  if(count($result) == 0){

    return "images/centrifugal%20pump%2011.png";

  }else{

    $fs = get_file_storage();

    foreach($result as $key=>$value){

      $file = $fs->get_file($value->contextid, $value->component, $value->filearea, $value->itemid, $value->filepath, $value->filename);

      // $url3 = moodle_url::make_pluginfile_url($value->contextid, $value->component, $value->filearea, $value->itemid, $value->filepath, $value->filename);

    }

    $fileinfo = pathinfo($value->filename);

    $filename = $cid .'.'. $fileinfo['extension'];

    $filepath = '/local/courses/images/courses/';


    if(!file_exists($CFG->dirroot . $filepath . $filename)){

      $file->copy_content_to($CFG->dirroot . $filepath . $filename);

    }


    return $CFG->wwwroot . $filepath . $filename;

  }

__________________________________

My main concern is that I am copying the file with copy_content_to instead of serving it via some built-in Moodle method. To be 100% clear I just want to display the file to users, not send them the file for download. Is this the best way to tackle this?


On a side note how do I post code neatly in this forum? 

In reply to Frank Troglauer

Re: Accessing Course Files via PHP and MySQL

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Select the code, click on the 'AA' button and select 'pre-formatted'.

and for "To be 100% clear I just want to display the file to users, not send them the file for download. Is this the best way to tackle this?"

Use 'make_pluginfile_url' and echo the URL to users.  Examine how the Grid format works with its 'displayedimage'.

In reply to Gareth J Barnard

Re: Accessing Course Files via PHP and MySQL

by Frank Troglauer -

Gareth,

Thanks for continuing to help with this. It is really appreciated!

I did try the 'make_pluginfile_url' which does make a url and when echoed out it looks like this. 

$url3 = moodle_url::make_pluginfile_url($value->contextid, $value->component, $value->filearea, $value->itemid, $value->filepath, $value->filename);
echo $url3;

http://localhost:8081/lms/pluginfile.php/96/course/overviewfiles/0/CoursePhoto.jpg 

However, if I try to put it into an img element it doesn't show anything and the console says the file cannot be found. 

echo "<img src='". $url3 ."'>";

Console errors

I took a look at your Grid Format plugin and it appears your doing the same thing I am but your using html_writer to create the html for display where I am just hard coding it. I did try it with the html_writer and got the same results. 

    $content = html_writer::empty_tag('img', array(
        'src' => $url3,
        'alt' => 'Course Image',
        'role' => 'img',
        'aria-label' => 'Course Image'));
    echo $content;

Course didn't display, just alt text.

Thanks for the heads up about the code formatting for forum posts!

In reply to Frank Troglauer

Re: Accessing Course Files via PHP and MySQL

by Frank Troglauer -

Gareth, do you have any other suggestions for this and what I might be doing wrong?

In reply to Frank Troglauer

Re: Accessing Course Files via PHP and MySQL

by Gareth J Barnard -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Hi Frank,

Sorry no, not without spending the time attempting to locally solve the problem of fetching the course summary file and displaying it.  Time = money.

Kind regards,

Gareth