diff --git a/report/mergefiles/README.md b/report/mergefiles/README.md new file mode 100755 index 0000000..c61e079 --- /dev/null +++ b/report/mergefiles/README.md @@ -0,0 +1,27 @@ +# mergefiles +Moodle Plugin for merging pdf files in a course
+ +The ‘Merge PDF Files’ plugin offers the user a convenient way by which he/she can merge the files (only PDF documents) in a Moodle course.
+This plugin requires 2 tools:
+ * PDFtk (short for PDF Toolkit) is a cross-platform tool for manipulating Portable Document Format (PDF) documents. It comes in three flavors: PDFtk Free, PDFtk Pro, and a command-line tool PDFtk Server.
+ * LaTeX – A document preparation system for high-quality typesetting. It is most often used for medium-to-large technical or scientific documents but it can be used for almost any form of publishing.
+ +The module is created and is currently being worked upon at IIT, Bombay (India).
+ +How to use?
+After applying this patch to moodle: + * Go to a particular course + * Click on settings icon + * A link saying "Merge PDF files" will appear in the course settings (drop-down menu) list. + * Then, you get a page listing all the pdf files in that particular course. + * At the end of this page, you get a button labeled "Merge pdf files". + * On clicking the button, the user will get a merged document of all the course files listed on that page. + +Usage:
+Through this feature, now users will be able to merge pdf files in a particular course from within moodle itself. +Work to be done
+ +Work in progress:
+The following functionality is being incorporated into this plugin wherein: +* user can shufffle the listed pdf files +* user can select only a few/all pdf files diff --git a/report/mergefiles/db/install.xml b/report/mergefiles/db/install.xml new file mode 100755 index 0000000..01b9f7d --- /dev/null +++ b/report/mergefiles/db/install.xml @@ -0,0 +1,13 @@ + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/report/mergefiles/index.php b/report/mergefiles/index.php new file mode 100755 index 0000000..a5c8896 --- /dev/null +++ b/report/mergefiles/index.php @@ -0,0 +1,341 @@ +. + +/* + * @package report + * @subpackage mergefiles + * @author + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL + * @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com + * + * The user selects if he wants to publish the course on Moodle.org hub or + * on a specific hub. The site must be registered on a hub to be able to + * publish a course on it. + */ + +require('../../config.php'); +require_once 'performmerge_form.php'; +if(empty($id)){ + $id = required_param('courseid', PARAM_INT); +} +$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); + +require_login($course); +$context = context_course::instance($course->id); +$PAGE->set_pagelayout('incourse'); + +$strlastmodified = get_string('lastmodified'); +$strlocation = get_string('location'); +$strintro = get_string('moduleintro'); +$strname = get_string('name'); +$strresources = get_string('resources'); +$strsectionname = get_string('sectionname', 'format_'.$course->format); +$strsize = get_string('size'); +$strsizeb = get_string('sizeb'); + +$heading = get_string('heading', 'report_mergefiles'); +$note = get_string('note', 'report_mergefiles'); +$pluginname = get_string('pluginname', 'report_mergefiles'); + +$PAGE->set_url('/report/mergefiles/index.php', array('id' => $course->id)); +$PAGE->set_title($course->shortname.' | '.$pluginname); +$PAGE->set_heading($course->fullname.' | '.$pluginname); +$PAGE->navbar->add($pluginname); + +//require_capability('report/mergefiles:view', $context); + +echo $OUTPUT->header(); +echo $OUTPUT->heading($heading); +echo $note; +echo "

"; + +// Source code from course/resources.php....used for getting all the pdf files in the course in order to merge them + +// Get list of all resource-like modules +$allmodules = $DB->get_records('modules', array('visible'=>1)); +$availableresources = array(); +foreach ($allmodules as $key=>$module) { + $modname = $module->name; + $libfile = "$CFG->dirroot/mod/$modname/lib.php"; + if (!file_exists($libfile)) { + continue; + } + $archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); + if ($archetype != MOD_ARCHETYPE_RESOURCE) { + continue; + } + + $availableresources[] = $modname; // List of all available resource types +} + +$modinfo = get_fast_modinfo($course); // Fetching all course data +$usesections = course_format_uses_sections($course->format); + +$cms = array(); +$resources = array(); + +foreach ($modinfo->cms as $cm) { // Fetching all modules in the course, like forum, quiz, resource etc. + if (!in_array($cm->modname, $availableresources)) { + continue; + } + if (!$cm->uservisible) { + continue; + } + if (!$cm->has_view()) { + // Exclude label and similar + continue; + } + $cms[$cm->id] = $cm; + $resources[$cm->modname][] = $cm->instance; // Fetch only modules having modname -'resource'.. + //..pdf files have modname 'resource' +} + +// Preload instances +foreach ($resources as $modname=>$instances) { // Getting data from mdl_resource table..id, name of the pdf file.. + $resources[$modname] = $DB->get_records_list($modname, 'id', $instances, 'id', 'id,name'); +} + +if (!$cms) { + notice(get_string('thereareno', 'moodle', $strresources), "$CFG->wwwroot/course/view.php?id=$course->id"); + exit; +} + +$table = new html_table(); +$table->attributes['class'] = 'generaltable mod_index'; + +if ($usesections) { + $strsectionname = get_string('sectionname', 'format_'.$course->format); + $table->head = array ($strsectionname, $strname, $strintro, $strsize.' ('.$strsizeb.')', "Location (moodledata/filedir/..)"); + $table->align = array ('center', 'left', 'left', 'left'); +} else { + $table->head = array ($strlastmodified, $strname, $strintro, $strsize.' ('.$strsizeb.')', $strlocation); + $table->align = array ('left', 'left', 'left', 'left'); +} + +$fs = get_file_storage(); +$currentsection = ''; +foreach ($cms as $cm) { + if (!isset($resources[$cm->modname][$cm->instance])) { + continue; + } + $resource = $resources[$cm->modname][$cm->instance]; + + $printsection = ''; + if ($usesections) { + if ($cm->sectionnum !== $currentsection) { + if ($cm->sectionnum) { + $printsection = get_section_name($course, $cm->sectionnum); + } + if ($currentsection !== '') { + //$table->data[] = 'hr'; + } + $currentsection = $cm->sectionnum; + } + } + + $extra = empty($cm->extra) ? '' : $cm->extra; + $icon = ''.$cm->get_module_type_name().' '; + $class = $cm->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed + + //---------------------------------------------------------------------------- + // Source from mod/resource/view.php....used for getting contenthash of the file + + $context = context_module::instance($cm->id); + $files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false); // TODO: this is not very efficient!! + if (count($files) < 1) { + //resource_print_filenotfound($resource, $cm, $course); + continue; + } else { + $file = reset($files); + unset($files); + } + + // end of source from mod/resource/view.php + //--------------------------------------------------------------------------- + + $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename()); + $contenthash = $file->get_contenthash(); + + static $p = 0; + $loc[$p] = substr($contenthash,0,2).'/'.substr($contenthash,2,2).'/'.$contenthash; + $arr[$p] = $CFG->dataroot."/filedir/".$loc[$p]; + + $table->data[] = array ( + $printsection, + "".$icon.$cm->get_formatted_name()."", + $file->get_filename(), + $file->get_filesize(), + $loc[$p]); + $p++; +} + +echo html_writer::table($table); + +$mform = new performmerge_form(null); +$formdata = array('courseid' => $id); +$mform->set_data($formdata); +$mform->display(); + +if ($data = $mform->get_data()) { + if (!empty($data->save)) { + + // Code for merging all the course pdfs -------------------------------------------------------------------- + // merge all course pdf files and store the merged document at a temporary location + + $path = $CFG->dataroot."/temp/filestorage"; // create temporary storage location for merged pdf file + if (!file_exists($path)) { + $mkdir = mkdir($path, 0777, true); + } + $datadir = $path."/"; + + $mergedpdf = $datadir.uniqid('mergedfile_').".pdf"; // path to the merged pdf document with unique filename + + // merge all the pdf files in the course using pdftk + $cmd = "pdftk "; + // add each pdf file to the command + foreach($arr as $file) { + $cmd .= $file." "; + } + $cmd .= " output $mergedpdf"; + $result = shell_exec($cmd); + + // copy the merged pdf document from temp loc to moodledata/filedir/.. + $mergedfileinfo = array( + 'contextid' => $context->id, // ID of context + 'component' => 'mod_resource', // usually = table name + 'filearea' => 'content', // usually = table name + 'itemid' => 0, // usually = ID of row in table + 'filepath' => '/', // any path beginning and ending in / + 'filename' => uniqid('mergedfile_').'.pdf'); // any filename + + $fs->create_file_from_pathname($mergedfileinfo, $mergedpdf); + + $mergedfile = $fs->get_file( + $mergedfileinfo['contextid'], + $mergedfileinfo['component'], + $mergedfileinfo['filearea'], + $mergedfileinfo['itemid'], + $mergedfileinfo['filepath'], + $mergedfileinfo['filename']); + + $mergedfileurl = moodle_url::make_pluginfile_url( + $mergedfile -> get_contextid(), + $mergedfile -> get_component(), + $mergedfile -> get_filearea(), + $mergedfile -> get_itemid(), + $mergedfile -> get_filepath(), + $mergedfile -> get_filename()); + + // create a blank numbered pdf document -------------------------------------------------------------------- + + // find no. of pages in the merged pdf document + $noofpages = shell_exec("pdftk $mergedpdf dump_data | grep NumberOfPages | awk '{print $2}'"); + + // latex script for creating blank numbered pdf document + $startpage = 1; + $texscript = ' + \documentclass[12pt,a4paper]{article} + \usepackage{helvet} + \usepackage{times} + \usepackage{multido} + \usepackage{fancyhdr} + \usepackage[hmargin=.8cm,vmargin=1.5cm,nohead,nofoot]{geometry} + \renewcommand{\familydefault}{\sfdefault} + \begin{document} + \fancyhf{} % clear all header and footer fields + \renewcommand{\headrulewidth}{0pt} + \pagestyle{fancy} + %\rhead{{\large\bfseries\thepage}} + \rhead{{\fbox{\large\bfseries\thepage}}} + \setcounter{page}{'.$startpage.'} + \multido{}{'.$noofpages.'}{\vphantom{x}\newpage} + \end{document} + '; + + $tempfilename = uniqid('latexfile_'); + $latexfilename = $datadir.$tempfilename; + $latexfile = $latexfilename.'.tex'; + + $latexfileinfo = array( + 'contextid' => $context->id, + 'component' => 'mod_resource', + 'filearea' => 'content', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => $tempfilename.'.tex'); + + $fs->create_file_from_string($latexfileinfo, $texscript); + + $latexfile1 = $fs->get_file( + $latexfileinfo['contextid'], + $latexfileinfo['component'], + $latexfileinfo['filearea'], + $latexfileinfo['itemid'], + $latexfileinfo['filepath'], + $latexfileinfo['filename']); + + $latexfile1->copy_content_to($latexfile); + + // execute pdflatex with parameter + // store the output blank numbered pdf document and all the intermediate files at the temp loc + $result1 = shell_exec('pdflatex -aux-directory='.$datadir.' -output-directory='.$datadir.' '.$latexfile.' '); + + // var_dump( $pdflatex ); + // test for success + if (!file_exists($latexfile)){ + print_r( file_get_contents($latexfilename.".log") ); + } else { + //echo "\nPDF created!\n"; + } + + // merge the blank numbered pdf document with the merged pdf document (containing all course pdfs) + + $stampedpdf = $datadir.uniqid('stampedfile_').".pdf"; // unique filename (with entire path to the file) for the merged and stamped pdf document + $result2 = shell_exec("pdftk $mergedpdf multistamp ".$latexfilename.".pdf output $stampedpdf"); + $stampedfilename = uniqid('stampedfile_').'.pdf'; + + $stampedfileinfo = array( + 'contextid' => $context->id, + 'component' => 'mod_resource', + 'filearea' => 'content', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => $stampedfilename); + + $fs->create_file_from_pathname($stampedfileinfo, $stampedpdf); + + $stampedfile = $fs->get_file( + $stampedfileinfo['contextid'], + $stampedfileinfo['component'], + $stampedfileinfo['filearea'], + $stampedfileinfo['itemid'], + $stampedfileinfo['filepath'], + $stampedfileinfo['filename']); + + $stampedfileurl = moodle_url::make_pluginfile_url( + $stampedfile -> get_contextid(), + $stampedfile -> get_component(), + $stampedfile -> get_filearea(), + $stampedfile -> get_itemid(), + $stampedfile -> get_filepath(), + $stampedfile -> get_filename()); + + echo "
Merged PDF Document | "."".$icon."Available here!"; + + } +} + +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/report/mergefiles/lang/en/report_mergefiles.php b/report/mergefiles/lang/en/report_mergefiles.php new file mode 100755 index 0000000..fe63500 --- /dev/null +++ b/report/mergefiles/lang/en/report_mergefiles.php @@ -0,0 +1,27 @@ +. + +/** + * Strings for component 'report/mergefiles' + * + * @package report/mergefiles + * @copyright + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['heading'] = "Course files"; +$string['note'] = "(Note: Files in pdf format only)"; +$string['pluginname'] = 'Merge PDF Files'; diff --git a/report/mergefiles/performmerge_form.php b/report/mergefiles/performmerge_form.php new file mode 100755 index 0000000..ee082fd --- /dev/null +++ b/report/mergefiles/performmerge_form.php @@ -0,0 +1,35 @@ +. + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page +} + +require_once $CFG->libdir.'/formslib.php'; + +class performmerge_form extends moodleform { + function definition() { + global $CFG; + $mform = $this->_form; + + $mform->addElement('hidden', 'courseid'); + $mform->setType('courseid', PARAM_INT); + + $submitstring = "Merge pdf files"; + $mform->addElement('submit', 'save', $submitstring); + } +} \ No newline at end of file diff --git a/report/mergefiles/version.php b/report/mergefiles/version.php new file mode 100755 index 0000000..0108abb --- /dev/null +++ b/report/mergefiles/version.php @@ -0,0 +1,30 @@ +. + +/** + * Version information + * + * @package report_mergefiles + * @copyright + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2017052800; // The current module version (Date: YYYYMMDDXX) +$plugin->requires = 2016112900; // Requires this Moodle version +$plugin->component = 'report_mergefiles'; // Full name of the plugin (used for diagnostics) + diff --git a/theme/boost/classes/output/core_renderer.php b/theme/boost/classes/output/core_renderer.php index 4e5835e..ab29731 100755 --- a/theme/boost/classes/output/core_renderer.php +++ b/theme/boost/classes/output/core_renderer.php @@ -570,6 +570,11 @@ class core_renderer extends \core_renderer { // We only add a list to the full settings menu if we didn't include every node in the short menu. if ($skipped) { + $text = get_string('pluginname', 'report_mergefiles'); + $url = new moodle_url('/report/mergefiles/index.php', array('courseid' => $this->page->course->id)); + $link = new action_link($url, $text, null, null, new pix_icon('t/download', $text)); + $menu->add_secondary_action($link); + $text = get_string('morenavigationlinks'); $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id)); $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));