Search code examples
phpfile-uploadzipmoodlemoodle-api

Uploading files and folders in a course programatically in Moodle


I need to upload files and folders into a course in moodle from a zip file, I have been searching and I found how to upload files. I try to upload, and the files are uploaded correctly into the database and in the file repository, but this files are not showed in the course when I enter to the course.

The code below is what I trying

$packer = get_file_packer('application/zip');
$files = $packer->extract_to_pathname($archivo_zip, $carpeta_unzip );

foreach($files as $path => $status){
    $fs = get_file_storage();                                   
    $context = context_course::instance($courseid);

    $filename = basename($path);
    $path_directory = "/" . str_replace($filename, "", $path);

    $author = $DB->get_record('user', array('id'=>$userid ), '*', MUST_EXIST);

    $file_record = new stdClass;
    $file_record->component = 'mod_folder';     //mod_resource  
    $file_record->contextid = $context->id;         
    $file_record->userid    = $userid ;                 
    $file_record->filearea  = 'content';            //draft, attachment
    $file_record->filename = $filename;             
    $file_record->filepath  = $path_directory;      
    $file_record->itemid    = 0;                
    $file_record->author    = fullname($author);
    $file_record->license   = $CFG->sitedefaultlicense;
    $file_record->source    = $filename;            
    //$file_record->timecreated    = time();            
    //$file_record->timemodified    = time();           

    $existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
    $file_record->itemid, $file_record->filepath, $file_record->filename);

    if ($existingfile) {
        //throw new file_exception('filenameexist');
    } else {
        $stored_file = $fs->create_file_from_pathname($file_record, $path_upload);
    }
}

I try to upload the files manually through the website and I've noticed that the folders ara created in another table called mdl_folder or in the table called mdl_file, but i don't know how do that and the best way to create and relate folders with files programatically for then displayed in the website well.

So if anyone knows how to do it or have any examples or documentation that may be useful, it would be helpful.

Thanks in advance.


Solution

  • I found a solution that works for me, I don't know if it is the most appropriate or not, if someone can take a look and tell me if it is correct or not, or what changes could make would be grateful.

    The solution i found is:

    • Create or get it back the folder who will contain the files
    • Upload the files

    Code:

        $packer = get_file_packer('application/zip');
        $files = $packer->extract_to_pathname($archivo_zip, $carpeta_unzip );
    
        foreach($files as $path => $status){
            $fs = get_file_storage();    
    
            $folder = get_folder($courseid, 'Upload Test');   
    
            $filename = basename($path);
            $path_directory = "/" . str_replace($filename, "", $path);
    
            $author = $DB->get_record('user', array('id'=>$userid ), '*', MUST_EXIST);
    
            $file_record = new stdClass;
            $file_record->component = 'mod_folder';     //mod_resource  
            $file_record->contextid = $folder->id;         
            $file_record->userid    = $userid ;                 
            $file_record->filearea  = 'content';            //draft, attachment
            $file_record->filename = $filename;             
            $file_record->filepath  = $path_directory;      
            $file_record->itemid    = 0;                
            $file_record->author    = fullname($author);
            $file_record->license   = $CFG->sitedefaultlicense;
            $file_record->source    = $filename;            
            //$file_record->timecreated    = time();            
            //$file_record->timemodified    = time();           
    
            $existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
            $file_record->itemid, $file_record->filepath, $file_record->filename);
    
            if ($existingfile) {
                //throw new file_exception('filenameexist');
            } else {
                $stored_file = $fs->create_file_from_pathname($file_record, $path_upload);
            }
        }
    

    And the function to create or get it back the folder is:

    function get_folder($courseid, $resource_name) {
        global $DB, $CFG;
    
        //Comprobamos si la carpeta ya existe ya existe
    
        $sql = "SELECT cm.id as cmid FROM {course_modules} cm, {folder} res
            WHERE res.name = '" . $resource_name . "'
            AND cm.course = " . $courseid . "
            AND cm.instance = res.id";
    
        if (! $coursemodule = $DB->get_record_sql($sql)) {      
            require_once($CFG->dirroot.'/course/lib.php');
    
            echo "\tCreate new folder\n";
    
            $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
    
            // get module id
            $module = $DB->get_record('modules', array('name' => 'folder'), '*', MUST_EXIST);
    
            // get course section
            /*course_create_sections_if_missing($course->id, 0);
            $modinfo = get_fast_modinfo($course->id);
            $cw = $modinfo->get_section_info(0);
    
            echo "section id: " . $cw->id;*/
    
            $sectionid = $DB->get_record('course_sections', array('course' => $course->id, 'name' => 'Recursos'), '*', MUST_EXIST);
    
            $folder_data = new stdClass();
            $folder_data->course = $course->id;
            $folder_data->name = $resource_name;            
            $folder_data->intro = '<p>'.$resource_name.'</p>';
            $folder_data->introformat = 1;
            $folder_data->revision = 1;
            $folder_data->timemodified = time();
            $folder_data->display = 0;
            $folder_data->showexpanded = 1;
            $folder_data->showdownloadfolder = 1;
    
            $folder_id = $DB->insert_record('folder', $folder_data);
    
            echo "folder id: " . $folder_id;
    
            // add course module
            $cm = new stdClass();
            $cm->course = $courseid;
            $cm->module = $module->id; // should be retrieved from mdl_modules
            $cm->instance = $folder_id; // from mdl_resource
            $cm->section = $sectionid->id; // from mdl_course_sections
            $cm->visible = 1;
            $cm->visibleold = 1;
            $cm->showavailability = 1;
            $cm->added = time();
    
            $cmid = $DB->insert_record('course_modules', $cm);
    
            // add module to course section so it'll be visible
            if ($DB->record_exists('course_sections', array('course' => $courseid, 'section' => 1))) {
                $sectionid = $DB->get_record('course_sections', array('course' => $courseid, 'section' => 1));
    
                // if sequence is not empty, add another course_module id
                if (!empty($sectionid->sequence)) {
                    $sequence = $sectionid->sequence . ',' . $cmid;
                } else {
                    // if sequence is empty, add course_module id
                    $sequence = $cmid;
                }
    
                $course_section = new stdClass();
                $course_section->id = $sectionid->id;
                $course_section->course = $courseid;
                $course_section->section = 1;
                $course_section->sequence = $sequence;
                $csid = $DB->update_record('course_sections', $course_section);
    
            } else {
    
                $sequence = $cmid;
    
                $course_section = new stdClass();
                $course_section->course = $courseid;
                $course_section->section = 1;
                $course_section->sequence = $sequence;
    
                $csid = $DB->insert_record('course_sections', $course_section);
            }
    
            rebuild_course_cache($courseid, true);      
    
            // get context again, this time with all resources present
            $context = get_folder($courseid, $resource_name);
            return $context;
    
        } else {
            $context = context_module::instance($coursemodule->cmid); 
    
            return $context;
        }
    } // get_folder