Gitlab CSE Unil

Commit 37c852c7 authored by M. Chardon's avatar M. Chardon
Browse files

affichage pdf

parent d921fd04
...@@ -100,4 +100,34 @@ class annotation { ...@@ -100,4 +100,34 @@ class annotation {
} }
} }
/**
* Convert a hexa decimal color code to its RGB equivalent
*
* @param string $hexStr (hexadecimal color value)
* @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array)
* @param string $seperator (to separate RGB values. Applicable only if second parameter is true.)
* @return array or string (depending on second parameter. Returns False if invalid hex color value)
*/
private function hex2RGB($hexStr, $returnAsString = false, $seperator = ',') {
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
$rgbArray = array();
if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
$colorVal = hexdec($hexStr);
$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
$rgbArray['blue'] = 0xFF & $colorVal;
} elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
} else {
return false; //Invalid hex color code
}
return $returnAsString ? implode($seperator, $rgbArray) : $rgbArray; // returns the rgb string or the associative array
}
public function getColorRGB() {
return $this->hex2RGB($this->colour, true);
}
} }
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
...@@ -40,16 +41,22 @@ class document_services { ...@@ -40,16 +41,22 @@ class document_services {
/** File area for generated pdf */ /** File area for generated pdf */
const FINAL_PDF_FILEAREA = 'download'; const FINAL_PDF_FILEAREA = 'download';
/** File area for combined pdf */ /** File area for combined pdf */
const COMBINED_PDF_FILEAREA = 'combined'; const COMBINED_PDF_FILEAREA = 'combined';
/** File area for importing html */ /** File area for importing html */
const IMPORT_HTML_FILEAREA = 'importhtml'; const IMPORT_HTML_FILEAREA = 'importhtml';
/** File area for page images */ /** File area for page images */
const PAGE_IMAGE_FILEAREA = 'pages'; const PAGE_IMAGE_FILEAREA = 'pages';
/** File area for readonly page images */ /** File area for readonly page images */
const PAGE_IMAGE_READONLY_FILEAREA = 'readonlypages'; const PAGE_IMAGE_READONLY_FILEAREA = 'readonlypages';
/** File area for the stamps */ /** File area for the stamps */
const STAMPS_FILEAREA = 'stamps'; const STAMPS_FILEAREA = 'stamps';
/** Filename for combined pdf */ /** Filename for combined pdf */
const COMBINED_PDF_FILENAME = 'combined.pdf'; const COMBINED_PDF_FILENAME = 'combined.pdf';
...@@ -363,8 +370,7 @@ EOD; ...@@ -363,8 +370,7 @@ EOD;
if ($readonly) { if ($readonly) {
$grade = $assignment->get_user_grade($userid, true, $attemptnumber); $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
$fs = get_file_storage(); $fs = get_file_storage();
$files = $fs->get_directory_files($assignment->get_context()->id, 'assignfeedback_editpdfplus', $files = $fs->get_directory_files($assignment->get_context()->id, 'assignfeedback_editpdfplus', self::PAGE_IMAGE_READONLY_FILEAREA, $grade->id, '/');
self::PAGE_IMAGE_READONLY_FILEAREA, $grade->id, '/');
$pagecount = count($files); $pagecount = count($files);
if ($pagecount > 0) { if ($pagecount > 0) {
return $pagecount; return $pagecount;
...@@ -379,15 +385,13 @@ EOD; ...@@ -379,15 +385,13 @@ EOD;
// Store the combined pdf file somewhere to be opened by tcpdf. // Store the combined pdf file somewhere to be opened by tcpdf.
$tmpdir = \make_temp_directory('assignfeedback_editpdfplus/pagetotal/' $tmpdir = \make_temp_directory('assignfeedback_editpdfplus/pagetotal/'
. self::hash($assignment, $userid, $attemptnumber)); . self::hash($assignment, $userid, $attemptnumber));
$combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME; $combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
$file->copy_content_to($combined); // Copy the file. $file->copy_content_to($combined); // Copy the file.
// Get the total number of pages. // Get the total number of pages.
$pdf = new pdf(); $pdf = new pdf();
$pagecount = $pdf->set_pdf($combined); $pagecount = $pdf->set_pdf($combined);
$pdf->Close(); // PDF loaded and never saved/outputted needs to be closed. $pdf->Close(); // PDF loaded and never saved/outputted needs to be closed.
// Delete temporary folders and files. // Delete temporary folders and files.
@unlink($combined); @unlink($combined);
@rmdir($tmpdir); @rmdir($tmpdir);
...@@ -525,14 +529,14 @@ EOD; ...@@ -525,14 +529,14 @@ EOD;
// Need to reorder the files following their name. // Need to reorder the files following their name.
// because get_directory_files() return a different order than generate_page_images_for_attempt(). // because get_directory_files() return a different order than generate_page_images_for_attempt().
foreach($files as $file) { foreach ($files as $file) {
// Extract the page number from the file name image_pageXXXX.png. // Extract the page number from the file name image_pageXXXX.png.
preg_match('/page([\d]+)\./', $file->get_filename(), $matches); preg_match('/page([\d]+)\./', $file->get_filename(), $matches);
if (empty($matches) or !is_numeric($matches[1])) { if (empty($matches) or ! is_numeric($matches[1])) {
throw new \coding_exception("'" . $file->get_filename() throw new \coding_exception("'" . $file->get_filename()
. "' file hasn't the expected format filename: image_pageXXXX.png."); . "' file hasn't the expected format filename: image_pageXXXX.png.");
} }
$pagenumber = (int)$matches[1]; $pagenumber = (int) $matches[1];
// Save the page in the ordered array. // Save the page in the ordered array.
$pages[$pagenumber] = $file; $pages[$pagenumber] = $file;
...@@ -569,13 +573,13 @@ EOD; ...@@ -569,13 +573,13 @@ EOD;
$groupname = ''; $groupname = '';
if ($groupmode) { if ($groupmode) {
$groupid = groups_get_activity_group($assignment->get_course_module(), true); $groupid = groups_get_activity_group($assignment->get_course_module(), true);
$groupname = groups_get_group_name($groupid).'-'; $groupname = groups_get_group_name($groupid) . '-';
} }
if ($groupname == '-') { if ($groupname == '-') {
$groupname = ''; $groupname = '';
} }
$grade = $assignment->get_user_grade($userid, true, $attemptnumber); $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST); $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
if ($assignment->is_blind_marking()) { if ($assignment->is_blind_marking()) {
$prefix = $groupname . get_string('participant', 'assign'); $prefix = $groupname . get_string('participant', 'assign');
...@@ -625,20 +629,36 @@ EOD; ...@@ -625,20 +629,36 @@ EOD;
$file->copy_content_to($combined); // Copy the file. $file->copy_content_to($combined); // Copy the file.
$pdf = new pdf(); $pdf = new pdf();
/*$defaultstamps = array('twoway_h.png', 'twoway_v.png');
// Stamp file object.
$filerecord = new stdClass;
$filerecord->component = 'assignfeedback_editpdfplus';
$filerecord->contextid = context_system::instance()->id;
$filerecord->userid = get_admin()->id;
$filerecord->filearea = 'stamps';
$filerecord->filepath = '/';
$filerecord->itemid = 0;
$fs = \get_file_storage();
// Load all default stamps.
foreach ($defaultstamps as $stamp) {
$filerecord->filename = $stamp;
$fs->create_file_from_pathname($filerecord,
$CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/' . $filerecord->filename);
}*/
$fs = \get_file_storage(); $fs = \get_file_storage();
$stamptmpdir = \make_temp_directory('assignfeedback_editpdfplus/stamps/' . self::hash($assignment, $userid, $attemptnumber)); $stamptmpdir = \make_temp_directory('assignfeedback_editpdfplus/stamps/' . self::hash($assignment, $userid, $attemptnumber));
$grade = $assignment->get_user_grade($userid, true, $attemptnumber); $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
// Copy any new stamps to this instance. // Copy any new stamps to this instance.
if ($files = $fs->get_area_files($assignment->get_context()->id, if ($files = $fs->get_area_files($assignment->get_context()->id, 'assignfeedback_editpdfplus', 'stamps', $grade->id, "filename", false)) {
'assignfeedback_editpdfplus',
'stamps',
$grade->id,
"filename",
false)) {
foreach ($files as $file) { foreach ($files as $file) {
$filename = $stamptmpdir . '/' . $file->get_filename(); $filename = $stamptmpdir . '/' . $file->get_filename();
$file->copy_content_to($filename); // Copy the file. $file->copy_content_to($filename); // Copy the file.
debugging($filename);
} }
} }
...@@ -652,22 +672,11 @@ EOD; ...@@ -652,22 +672,11 @@ EOD;
$annotations = page_editor::get_annotations($grade->id, $i, false); $annotations = page_editor::get_annotations($grade->id, $i, false);
foreach ($comments as $comment) { foreach ($comments as $comment) {
$pdf->add_comment($comment->rawtext, $pdf->add_comment($comment->rawtext, $comment->x, $comment->y, $comment->width, $comment->colour);
$comment->x,
$comment->y,
$comment->width,
$comment->colour);
} }
foreach ($annotations as $annotation) { foreach ($annotations as $annotation) {
$pdf->add_annotation($annotation->x, $pdf->add_annotation($annotation, $annotation->path, $stamptmpdir);
$annotation->y,
$annotation->endx,
$annotation->endy,
$annotation->colour,
$annotation->type, //@TODO
$annotation->path,
$stamptmpdir);
} }
} }
...@@ -759,12 +768,7 @@ EOD; ...@@ -759,12 +768,7 @@ EOD;
$filepath = '/'; $filepath = '/';
$fs = \get_file_storage(); $fs = \get_file_storage();
$files = $fs->get_area_files($contextid, $files = $fs->get_area_files($contextid, $component, $filearea, $itemid, "itemid, filepath, filename", false);
$component,
$filearea,
$itemid,
"itemid, filepath, filename",
false);
if ($files) { if ($files) {
return reset($files); return reset($files);
} }
......
...@@ -159,6 +159,34 @@ class page_editor { ...@@ -159,6 +159,34 @@ class page_editor {
return $tools; return $tools;
} }
/**
* Get a single tool by id.
* @param int $toolid
* @return tool or false
*/
public static function get_tool($toolid) {
global $DB;
$record = $DB->get_record('assignfeedback_editpp_tool', array('id' => $toolid), '*', IGNORE_MISSING);
if ($record) {
return new tool($record);
}
return false;
}
/**
* Get the tool with id tooltypeid.
* @param int $tooltypeid
* @return type_tool
*/
public static function get_type_tool($tooltypeid) {
global $DB;
$record = $DB->get_record('assignfeedback_editpp_typet', array('id' => $tooltypeid));
if ($record) {
return new type_tool($record);
}
return false;
}
public static function get_typetools($contextidlist) { public static function get_typetools($contextidlist) {
global $DB; global $DB;
$typetools = array(); $typetools = array();
...@@ -258,7 +286,7 @@ class page_editor { ...@@ -258,7 +286,7 @@ class page_editor {
if ($newid) { if ($newid) {
if ($currentdiv != '') { if ($currentdiv != '') {
$annotationdiv[$currentdiv] = $newid; $annotationdiv[$currentdiv] = $newid;
debugging($currentdiv . ' -> ' . $newid); //debugging($currentdiv . ' -> ' . $newid);
} }
$added++; $added++;
} }
...@@ -383,7 +411,6 @@ class page_editor { ...@@ -383,7 +411,6 @@ class page_editor {
global $DB; global $DB;
$annotation->id = null; $annotation->id = null;
debugging('idparent : ' . $annotation->parent_annot);
if ($annotation->parent_annot == 0) { if ($annotation->parent_annot == 0) {
$annotation->parent_annot = null; $annotation->parent_annot = null;
} }
......
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
...@@ -27,8 +28,8 @@ namespace assignfeedback_editpdfplus; ...@@ -27,8 +28,8 @@ namespace assignfeedback_editpdfplus;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
global $CFG; global $CFG;
require_once($CFG->libdir.'/pdflib.php'); require_once($CFG->libdir . '/pdflib.php');
require_once($CFG->dirroot.'/mod/assign/feedback/editpdf/fpdi/fpdi.php'); require_once($CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi.php');
/** /**
* Library code for manipulating PDFs * Library code for manipulating PDFs
...@@ -41,31 +42,43 @@ class pdf extends \FPDI { ...@@ -41,31 +42,43 @@ class pdf extends \FPDI {
/** @var int the number of the current page in the PDF being processed */ /** @var int the number of the current page in the PDF being processed */
protected $currentpage = 0; protected $currentpage = 0;
/** @var int the total number of pages in the PDF being processed */ /** @var int the total number of pages in the PDF being processed */
protected $pagecount = 0; protected $pagecount = 0;
/** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */ /** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */
protected $scale = 0.0; protected $scale = 0.0;
/** @var string the path in which to store generated page images */ /** @var string the path in which to store generated page images */
protected $imagefolder = null; protected $imagefolder = null;
/** @var string the path to the PDF currently being processed */ /** @var string the path to the PDF currently being processed */
protected $filename = null; protected $filename = null;
/** No errors */ /** No errors */
const GSPATH_OK = 'ok'; const GSPATH_OK = 'ok';
/** Not set */ /** Not set */
const GSPATH_EMPTY = 'empty'; const GSPATH_EMPTY = 'empty';
/** Does not exist */ /** Does not exist */
const GSPATH_DOESNOTEXIST = 'doesnotexist'; const GSPATH_DOESNOTEXIST = 'doesnotexist';
/** Is a dir */ /** Is a dir */
const GSPATH_ISDIR = 'isdir'; const GSPATH_ISDIR = 'isdir';
/** Not executable */ /** Not executable */
const GSPATH_NOTEXECUTABLE = 'notexecutable'; const GSPATH_NOTEXECUTABLE = 'notexecutable';
/** Test file missing */ /** Test file missing */
const GSPATH_NOTESTFILE = 'notestfile'; const GSPATH_NOTESTFILE = 'notestfile';
/** Any other error */ /** Any other error */
const GSPATH_ERROR = 'error'; const GSPATH_ERROR = 'error';
/** Min. width an annotation should have */ /** Min. width an annotation should have */
const MIN_ANNOTATION_WIDTH = 5; const MIN_ANNOTATION_WIDTH = 5;
/** Min. height an annotation should have */ /** Min. height an annotation should have */
const MIN_ANNOTATION_HEIGHT = 5; const MIN_ANNOTATION_HEIGHT = 5;
...@@ -92,7 +105,7 @@ class pdf extends \FPDI { ...@@ -92,7 +105,7 @@ class pdf extends \FPDI {
foreach ($pdflist as $file) { foreach ($pdflist as $file) {
$pagecount = $this->setSourceFile($file); $pagecount = $this->setSourceFile($file);
$totalpagecount += $pagecount; $totalpagecount += $pagecount;
for ($i = 1; $i<=$pagecount; $i++) { for ($i = 1; $i <= $pagecount; $i++) {
$this->create_page_from_source($i); $this->create_page_from_source($i);
} }
} }
...@@ -171,7 +184,7 @@ class pdf extends \FPDI { ...@@ -171,7 +184,7 @@ class pdf extends \FPDI {
if (!$this->filename) { if (!$this->filename) {
return false; return false;
} }
if ($this->currentpage>=$this->pagecount) { if ($this->currentpage >= $this->pagecount) {
return false; return false;
} }
$this->currentpage++; $this->currentpage++;
...@@ -273,40 +286,50 @@ class pdf extends \FPDI { ...@@ -273,40 +286,50 @@ class pdf extends \FPDI {
* @param string $imagefolder - Folder containing stamp images. * @param string $imagefolder - Folder containing stamp images.
* @return bool true if successful (always) * @return bool true if successful (always)
*/ */
public function add_annotation($sx, $sy, $ex, $ey, $colour = 'yellow', $type = 'line', $path, $imagefolder) { public function add_annotation(annotation $annotation, $path, $imagefolder) {
global $CFG; global $CFG;
if (!$this->filename) { if (!$this->filename) {
return false; return false;
} }
switch ($colour) { $colour = $annotation->colour;
case 'yellow': if (substr($colour, 0, 1) == '#') {
$colourarray = array(255, 207, 53); $colourarray = $annotation->getColorRGB();
break; } else {
case 'green': switch ($colour) {
$colourarray = array(153, 202, 62); case 'yellow':
break; $colourarray = array(255, 207, 53);
case 'blue': break;
$colourarray = array(125, 159, 211); case 'green':
break; $colourarray = array(153, 202, 62);
case 'white': break;
$colourarray = array(255, 255, 255); case 'blue':
break; $colourarray = array(125, 159, 211);
case 'black': break;
$colourarray = array(51, 51, 51); case 'white':
break; $colourarray = array(255, 255, 255);
default: /* Red */ break;
$colour = 'red'; case 'black':
$colourarray = array(239, 69, 64); $colourarray = array(51, 51, 51);
break; break;
default: /* Red */
$colour = 'red';
$colourarray = array(239, 69, 64);
break;
}
} }
$this->SetDrawColorArray($colourarray); $this->SetDrawColorArray($colourarray);
$sx *= $this->scale; $sx = $this->scale * $annotation->x;
$sy *= $this->scale; $sy = $this->scale * $annotation->y;
$ex *= $this->scale; $ex = $this->scale * $annotation->endx;
$ey *= $this->scale; $ey = $this->scale * $annotation->endy;
$this->SetLineWidth(3.0 * $this->scale); $this->SetLineWidth(3.0 * $this->scale);
//$type = 'line';
$toolid = $annotation->toolid;
$toolObject = page_editor::get_tool($toolid);
$typetool = page_editor::get_type_tool($toolObject->type);
$type = $typetool->label;
switch ($type) { switch ($type) {
case 'oval': case 'oval':
$rx = abs($sx - $ex) / 2; $rx = abs($sx - $ex) / 2;
...@@ -378,6 +401,77 @@ class pdf extends \FPDI { ...@@ -378,6 +401,77 @@ class pdf extends \FPDI {
// Stamp is always more than 40px, so no need to check width/height. // Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h); $this->Image($imgfile, $sx, $sy, $w, $h);
break; break;
case 'highlightplus':
$w = abs($sx - $ex);
$h = 8.0 * $this->scale;
$sx = min($sx, $ex);
$sy = min($sy, $ey) + ($h * 0.5);
$this->SetAlpha(0.5, 'Normal', 0.5, 'Normal');
$this->SetLineWidth(8.0 * $this->scale);
// width should be >= min width
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}
$this->Rect($sx, $sy, $w, $h);
$this->SetAlpha(1.0, 'Normal', 1.0, 'Normal');
break;
case 'verticalline':
$this->Line($sx, $sy, $sx, $ey);
break;
case 'frame':
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Width or height should be >= min width and height
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}
if ($h < self::MIN_ANNOTATION_HEIGHT) {
$h = self::MIN_ANNOTATION_HEIGHT;
}
$this->Rect($sx, $sy, $w, $h);
break;
case 'stampcomment':
$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_h.png';
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
break;
case 'commentplus':
$imgfile = $CFG->dirroot . 'mod/assign/feedback/editpdfplus/pix/comment.png';
$w = abs(16);
$h = abs(16);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
break;
case 'stampplus':
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Width or height should be >= min width and height
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}