Your IP : 216.73.216.95


Current Path : /var/www/ljmtc/cbt/mod/grouptool/classes/
Upload File :
Current File : /var/www/ljmtc/cbt/mod/grouptool/classes/pdf.php

<?php
// This file is part of mod_grouptool for Moodle - http://moodle.org/
//
// It is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// It is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Extending the moodle pdf class with a custom header and some helperfunctions for proper data-output.
 *
 * @package   mod_grouptool
 * @author    Philipp Hager
 * @copyright 2014 Academic Moodle Cooperation {@link http://www.academic-moodle-cooperation.org}
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
namespace mod_grouptool;

use context_course;

defined('MOODLE_INTERNAL') || die();

require_once('../../lib/pdflib.php');

/**
 * Extended pdf class with convenience methods for outputting Grouptool pdfs
 *
 * @package   mod_grouptool
 * @author    Philipp Hager
 * @copyright 2014 Academic Moodle Cooperation {@link http://www.academic-moodle-cooperation.org}
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class pdf extends \pdf {
    /** int NORMLINEHEIGHT = 12 */
    const NORMLINEHEIGHT = 12;

    /** @var string[] $header1 defines what's in the upper row of page-header **/
    protected $header1 = null;

    /** @var string[] $header2 defines what's in the lower row of page-header **/
    protected $header2 = null;

    /**
     * @var string[] $header numerical array of strings, used for storage of column-headers
     * each index corresponds to the index in {@see $data}, {@see $width} and {@see $align}
     */
    protected $header = [];

    /**
     * @var float[] $width numerical array of floats, used for storage of column-header-widths
     * each index corresponds to the index in {@see $data}, {@see $width} and {@see $align}
     * If index in $width is set to null the corresponding column-width gets calculated
     * automatically (the same calculated width is used for each of those columns)
     */
    protected $width = [];

    /**
     * @var [] $align numerical array of chars, used for storage of column-header-alignment
     * each index corresponds to the index in {@see $data}, {@see $width} and {@see $align}
     * use 'C' for center, 'L' for left and 'R' for right
     */
    protected $align = [];

    /** @var int|null used to calculate heights of text-blocks */
    protected $normalheight = null;

    /** @var int|null used to calculate heights of text-blocks */
    protected $bigheight = null;

    /**
     * Class constructor
     *
     * Enhances moodle's pdf class by adding calculated values for text-height. {@inheritDoc}
     *
     * @param string $orientation page orientation
     * @param string $unit User measure unit
     * @param string $format The format used for pages
     * @param bool $unicode TRUE means that the input text is unicode (default = true)
     * @param string $encoding Charset encoding (used only when converting back html entities); default is UTF-8.
     * @throws \coding_exception
     */
    public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8') {
        global $SITE, $USER;

        parent::__construct($orientation, $unit, $format, $unicode, $encoding);

        $this->setFontSubsetting(false);

        // Set orientation (P/L)!
        $orientation = (optional_param('orientation', 0, PARAM_BOOL) == 0) ? 'P' : 'L';
        $this->setPageOrientation($orientation);

        // Set document information!
        $this->SetCreator(format_string($SITE->fullname, true, ['context' => context_course::instance(SITEID)]).' | '.
                get_string('pluginname', 'grouptool'));
        $this->SetAuthor(fullname($USER));

        // Set header/footer!
        $this->setPrintHeader(true);
        $this->setPrintFooter(true);

        $textsize = optional_param('textsize', 1, PARAM_INT);
        switch ($textsize){
            case "0":
                $this->SetFontSize(8);
                break;
            case "1":
                $this->SetFontSize(10);
                break;
            case "2":
                $this->SetFontSize(12);
                break;
        }

        // Set default monospaced font!
        $this->SetDefaultMonospacedFont(/*PDF_FONT_MONOSPACED*/'freeserif');

        // Set auto page breaks!
        $this->SetAutoPageBreak(true, /*PDF_MARGIN_BOTTOM*/10);

        // Set image scale factor
        $this->setImageScale(/*PDF_IMAGE_SCALE_RATIO*/1);

        /*
         * ---------------------------------------------------------
         */

        // Set font!
        $this->SetFont('freeserif', '');

        // Set margins!
        $this->setHeaderMargin(7);
        $this->setFooterMargin(7);
        $this->SetMargins(10, 30, 10, true); // Left Top Right.

        // Calculate height.
        $this->SetFontSize(1.25 * self::NORMLINEHEIGHT);
        $this->bigheight = $this->getStringHeight(0, 'testtext');
        $this->SetFontSize(1.0 * self::NORMLINEHEIGHT);
        $this->normalheight = $this->getStringHeight(0, 'testtext');

        $this->AddPage($orientation, 'A4', false, false);
    }

    /**
     * set_overview_header_data() helper method to set the strings for page header for Overview PDF
     *
     * @param string $coursename the name of the course
     * @param string $grouptoolname name of grouptool instance
     * @param int $timeavailable time since the checkmark is available
     * @param int $timedue time due to which students can submit
     * @param string $viewname the checkmark-modulename to view
     * @throws \coding_exception
     */
    public function set_overview_header_data($coursename='coursename', $grouptoolname='grouptoolname', $timeavailable=0, $timedue=0,
                                             $viewname='viewname') {
        $this->header1 = [];
        $this->header1[0] = get_string('course').":";
        $this->header1[1] = $coursename;
        $this->header1[2] = get_string('availabledate', 'grouptool').":";
        $this->header1[3] = empty($timeavailable) ? get_string('availabledateno', 'grouptool') : userdate($timeavailable);
        $this->header1[4] = get_string('groupoverview', 'grouptool');

        $this->header2 = [];
        $this->header2[0] = get_string('modulename', 'grouptool').":";
        $this->header2[1] = $grouptoolname;
        $this->header2[2] = get_string('duedate', 'grouptool').":";
        $this->header2[3] = empty($timedue) ? get_string('duedateno', 'grouptool') : userdate($timedue);
        $this->header2[4] = $viewname;
    }

    /**
     * set_userlist_header_data() helper method to set the strings for page header for UserList PDF
     *
     * @param string $coursename the name of the course
     * @param string $grouptoolname name of the grouptoolinstance
     * @param int $timeavailable time since the checkmark is available
     * @param int $timedue time due to which students can submit
     * @param string $viewname the checkmark-modulename to view
     * @throws \coding_exception
     */
    public function set_userlist_header_data($coursename, $grouptoolname, $timeavailable, $timedue,
                                             $viewname ) {
        $this->header1 = [];
        $this->header1[0] = get_string('course').":";
        $this->header1[1] = $coursename;
        $this->header1[2] = get_string('availabledate', 'grouptool').":";
        $this->header1[3] = empty($timeavailable) ? get_string('availabledateno', 'grouptool') : userdate($timeavailable);
        $this->header1[4] = get_string('userlist', 'grouptool');

        $this->header2 = [];
        $this->header2[0] = get_string('modulename', 'grouptool').":";
        $this->header2[1] = $grouptoolname;
        $this->header2[2] = get_string('duedate', 'grouptool').":";
        $this->header2[3] = empty($timedue) ? get_string('duedateno', 'grouptool') : userdate($timedue);
        $this->header2[4] = $viewname;
    }

    /**
     * set_header_data() helper method to set the right texts for page header
     *
     * @param string $coursename the name of the course
     * @param string $grouptoolname name of the grouptoolinstance
     * @param int $timeavailable time since the checkmark is available
     * @param int $timedue time due to which students can submit
     * @param string $viewname the grouptool-modulename to view
     * @throws \coding_exception
     */
    public function set_header_data($coursename, $grouptoolname, $timeavailable, $timedue,
                                    $viewname) {
        $this->header1 = [];
        $this->header1[0] = get_string('course').":";
        $this->header1[1] = $coursename;
        $this->header1[2] = get_string('availabledate', 'grouptool').":";
        $this->header1[3] = empty($timeavailable) ? get_string('availabledateno', 'grouptool') : userdate($timeavailable);
        $this->header1[4] = get_string('overview', 'grouptool');

        $this->header2 = [];
        $this->header2[0] = get_string('modulename', 'grouptool').":";
        $this->header2[1] = $grouptoolname;
        $this->header2[2] = get_string('duedate', 'grouptool').":";
        $this->header1[3] = empty($timedue) ? get_string('duedateno', 'grouptool') : userdate($timedue);
        $this->header2[4] = $viewname;
    }

    /**
     * Header() helper method to actually print the page header in the PDF
     */
    public function header() {
        // Set font.
        $this->SetFont('', '');

        $pagewidth = $this->getPageWidth();
        $scale = $pagewidth / 200;
        $oldfontsize = $this->getFontSize();
        $this->SetFontSize('10');

        // First row.
        $border = 0;
        $height = 7;
        $this->SetFont('', 'B');
        $this->MultiCell(15 * $scale, $height, $this->header1[0],
                         $border, 'L', 0, 0, null, null, true, 1, false, false, $height, 'M', true);
        $this->SetFont('', '');
        $this->MultiCell(41 * $scale, $height, $this->header1[1],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        // Spacer!
        $this->MultiCell(15 * $scale, $height, "",
                         $border, 'C', 0, 0, null, null, true, 1, false, false, $height, 'M', true);
        $this->SetFont('', 'B');
        $this->MultiCell(26 * $scale, $height, $this->header1[2],
                         $border, 'L', 0, 0, null, null, true, 1, false, false, $height, 'M', true);
        $this->SetFont('', '');
        $this->MultiCell(46 * $scale, $height, $this->header1[3],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        // Spacer!
        $this->MultiCell(15 * $scale, $height, "", $border, 'C', 0, 0, null, null, true, 1,
                         false, false, $height, 'M', true);
        $this->SetFont('', 'B');
        $this->MultiCell(0, $height, $this->header1[4],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->Ln();

        // Second row.

        $this->SetFont('', 'B');
        $this->MultiCell(15 * $scale, $height, $this->header2[0],
                         $border, 'L', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->SetFont('', '');
        $this->MultiCell(41 * $scale, $height, $this->header2[1],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        // Spacer!
        $this->MultiCell(15 * $scale, $height, "",
                         $border, 'C', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->SetFont('', 'B');
        $this->MultiCell(26 * $scale, $height, $this->header2[2],
                         $border, 'L', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->SetFont('', '');
        $this->MultiCell(46 * $scale, $height, $this->header2[3],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        // Spacer!
        $this->MultiCell(15 * $scale, $height, "",
                         $border, 'C', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->SetFont('', '');
        $this->MultiCell(0, $height, $this->header2[4],
                         $border, 'R', 0, 0, null, null, true, 1, false, false, $height, 'M', true);

        $this->Ln();
        $this->SetFontSize($oldfontsize);
    }

    /**
     * If showheaderfooter is selected
     * Displays the number and total number of pages in the footer
     */
    public function footer() {
        // Set font.
        $this->SetFont('', '');

        // Position at 15 mm from bottom.
        $this->SetY(-15);

        // Page number.
        $this->Cell(0, 10, $this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
    }

    /**
     * add_grp_overview writes data about 1 group to pdf
     *
     * @param string $groupname
     * @param string $groupinfo some statistic data about the group
     * @param \stdClass[] $registration the users registered in grouptool-group
     * @param \stdClass[] $queue the queued users
     * @param \stdClass[] $moodlemembers the users registered in moodle-group
     * @throws \coding_exception
     */
    public function add_grp_overview($groupname, $groupinfo, $registration=[], $queue=[], $moodlemembers = []) {
        $fill = 0;

        // Calculate height.
        $bigheight = $this->bigheight;
        $normalheight = $this->normalheight;

        $height = $bigheight + $normalheight + (count($registration) + count($queue) + 1) * $normalheight;

        // Move to next page if too high.
        $this->checkPageBreak($height);

        // Color and font restoration!
        $this->SetDrawColor(0);
        $this->SetFillColor(0xe8, 0xe8, 0xe8);
        $this->SetTextColor(0);
        $this->SetFont('');

        // Insert groupname!
        $this->SetFontSize(1.25 * self::NORMLINEHEIGHT);
        $this->MultiCell(0, $bigheight, $groupname, 0, 'L', false, 1, null, null, true, 1, true,
                         false, $bigheight, 'M', true);
        $this->Ln();

        // Insert groupinfo!
        $this->SetFontSize(1.0 * self::NORMLINEHEIGHT);
        $this->MultiCell(0, $normalheight, $groupinfo, 0, 'L', false, 1, null, null, true, 1,
                         true, false, $normalheight, 'M', true);
        $this->Ln();
        // Insert registrations & queue tables!
        if (count($registration)) {
            $this->add_overview_table_header();
            foreach ($registration as $row) {
                $this->add_overview_row($row['status'], $row['name'], $row['idnumber'], $row['email'], $fill);
            }
        } else if (count($moodlemembers) == 0) {
            $this->SetFont('', 'I');
            $this->MultiCell(0, $normalheight,
                             "--".get_string('no_registrations', 'grouptool')."--", 0, 'C', false,
                             1, null, null, true, 1, true, false, $normalheight, 'M', true);
            $this->SetFont('', '');
        }

        if (count($moodlemembers) >= 1) {
            if (count($registration) == 0) {
                $this->add_overview_table_header();
            }
            foreach ($moodlemembers as $row) {
                $this->add_overview_row('?', $row['name'], $row['idnumber'], $row['email'], $fill);
            }
        }

        if (count($queue)) {
            $fill = !isset($fill) ? 0 : $fill;
            $this->SetFillColor(0xe8, 0xe8, 0xe8);
            $this->SetFont('', '');
            foreach ($queue as $row) {
                if ($fill) {
                    $this->SetFillColor(0xff, 0xff, 0x99);
                } else {
                    $this->SetFillColor(0xff, 0xcc, 0x99);
                }
                $this->add_overview_row($row['rank'], $row['name'], $row['idnumber'], $row['email'], $fill, 1);
            }
        } else {
            $this->SetFont('', 'I');
            $this->MultiCell(0, $normalheight, "--".get_string('nobody_queued', 'grouptool')."--",
                             0, 'C', false, 1, null, null, true, 1, true, false, $normalheight,
                             'M', true);
            $this->SetFont('', '');
        }
    }

    /**
     * Writes the table header for overview tables to the PDF
     *
     * @throws \coding_exception
     */
    private function add_overview_table_header() {
        // Print table-header!
        $margins = $this->getMargins();
        $writewidth = $this->getPageWidth() - $margins['left'] - $margins['right'];
        $normalheight = $this->normalheight;

        $this->SetFont('', 'B');
        $this->MultiCell(0.1 * $writewidth, $normalheight, get_string('status', 'grouptool'),
                         'RB', 'C', true, 0, null, null, true, 1, true, false, $normalheight,
                         'M', true);
        $this->MultiCell(0.3 * $writewidth, $normalheight, get_string('fullname'), 'LRB', 'C',
                         true, 0, null, null, true, 1, true, false, $normalheight, 'M', true);
        $this->MultiCell(0.2 * $writewidth, $normalheight, get_string('idnumber'), 'LRB', 'C',
                         true, 0, null, null, true, 1, true, false, $normalheight, 'M', true);
        $this->MultiCell(0.4 * $writewidth, $normalheight, get_string('email'), 'LB', 'C', true,
                         1, null, null, true, 1, true, false, $normalheight, 'M', true);
        $this->SetFillColor(0xe8, 0xe8, 0xe8);
        $this->SetFont('', '');
    }

    /**
     * Adds a single row of group overview entry data to the PDF
     *
     * @param string $status column content
     * @param string $name column content
     * @param string $idnumber column content
     * @param string $email column content
     * @param bool $fill whether or not this row's cells will contain a background color (gets toggled afterwards)!
     * @param bool $forcefill force cell background color ($fill gets toggled anyways)!
     */
    private function add_overview_row($status, $name, $idnumber, $email, &$fill, $forcefill = false) {
        $margins = $this->getMargins();
        $writewidth = $this->getPageWidth() - $margins['left'] - $margins['right'];
        $normalheight = $this->normalheight;

        $this->MultiCell(0.1 * $writewidth, $normalheight, $status, 'TR', 'C', $fill || $forcefill, 0, null, null, true,
                         1, true, false, $normalheight, 'M', true);
        $this->MultiCell(0.3 * $writewidth, $normalheight, $name, 'TLR', 'L', $fill || $forcefill, 0, null, null, true,
                         1, true, false, $normalheight, 'M', true);
        $this->MultiCell(0.2 * $writewidth, $normalheight, $idnumber, 'TLR', 'L', $fill || $forcefill, 0, null, null, true,
                         1, true, false, $normalheight, 'M', true);
        $this->MultiCell(0.4 * $writewidth, $normalheight, $email, 'TL', 'L', $fill || $forcefill, 1, null, null, true,
                         1, true, false, $normalheight, 'M', true);
        $fill ^= 1;
    }

    /**
     * add_userdata helper method to write the data about 1 user in a row (also for table-header)
     *
     * @param string $name of user
     * @param string|integer $idnumber of user
     * @param string $email user's email
     * @param \stdClass[] $registrations
     * @param \stdClass[] $queues
     * @param bool $header if it's a header-row or not
     * @param bool $getheightonly return only the height of the row
     * @return int height of written row
     * @throws \coding_exception
     *
     */
    public function add_userdata($name, $idnumber, $email, $registrations, $queues, $header=false,
                                 $getheightonly=false) {
        global $SESSION;

        $margins = $this->getMargins();
        $writewidth = $this->getPageWidth() - $margins['left'] - $margins['right'];

        $this->SetFontSize(1.0 * self::NORMLINEHEIGHT);

        // Get row-height!
        if (!$getheightonly) {
            $height = $this->add_userdata($name, $idnumber, $email, $registrations, $queues,
                                          $header, true);
            // Move to next page if too high!
            $this->checkPageBreak($height);

        } else {
            // Store current object!
            $this->startTransaction();

            $height = 0;
        }

        if ($header) {
            $borderf = "R";
            $border = "LR";
            $borderl = "L";
            $fill = 1;
            $this->SetFont('', 'B');
            $this->SetFillColor(0xe8, 0xe8, 0xe8);
        } else {
            $borderf = "TR";
            $border = "TLR";
            $borderl = "TL";
            $fill = 0;
            $this->SetFont('', '');
        }

        if (isset($SESSION->mod_grouptool->userlist->collapsed)) {
            $collapsed = $SESSION->mod_grouptool->userlist->collapsed;
        } else {
            $collapsed = [];
        }

        $basicwidths = [
                'fullname' => 0.225,
                'idnumber' => 0.15,
                'email' => 0.225,
                'registrations' => 0.225,
                'queues' => 0.175
        ];
        $totalwidth = array_sum($basicwidths);
        $colapsedwidth = $totalwidth;
        foreach ($collapsed as $column) {
            $colapsedwidth -= $basicwidths[$column];
        }
        $widths = [];
        foreach ($basicwidths as $column => $width) {
            $widths[$column] = $width * ($totalwidth / $colapsedwidth) * $writewidth;
        }
        // Set the last column to stretch over the rest of the page!
        end($widths);
        $widths[key($widths)] = 0;

        if (!in_array('fullname', $collapsed)) {
            $this->MultiCell($widths['fullname'], $height, $name, $borderf, 'L', $fill, 0, null,
                             null, true, 1, false, false, $height, 'M', true);
            if ($getheightonly) {
                $height = max([$height, $this->getLastH()]);
            }
        }
        if (!in_array('idnumber', $collapsed)) {
            $this->MultiCell($widths['idnumber'], $height, $idnumber, $border, 'L', $fill, 0, null,
                             null, true, 1, false, false, $height, 'M', true);
            if ($getheightonly) {
                $height = max([$height, $this->getLastH()]);
            }
        }
        if (!in_array('email', $collapsed)) {
            $this->MultiCell($widths['email'], $height, $email, $border, 'L', $fill, 0, null, null,
                             true, 1, false, false, $height, 'M', true);
            if ($getheightonly) {
                $height = max([$height, $this->getLastH()]);
            }
        }
        if (!in_array('registrations', $collapsed)) {
            if (!empty($registrations) && is_array($registrations)) {
                $registrationsstring = (count($registrations) > 1) ? implode("\n", $registrations) : $registrations[0];
                if ($getheightonly) {
                    $this->MultiCell($widths['registrations'], $height, $registrationsstring,
                                     $border, 'L', $fill, 0, null, null, true, 1, false, false,
                                     $height, 'M', false);
                    $height = count($registrations) * max([$height, $this->getLastH()]);
                } else {
                    $this->MultiCell($widths['registrations'], $height, $registrationsstring,
                                     $border, 'L', $fill, 0, null, null, true, 1, false, false,
                                     $height, 'M', true);
                }
            } else if ($header) {
                $this->SetFont('', 'B');
                $this->MultiCell($widths['registrations'], $height, $registrations, $border, 'L',
                                $fill, 0, null, null, true, 1, false, false, $height, 'M', true);
                if ($getheightonly) {
                    $height = max([$height, $this->getLastH()]);
                }
                $this->SetFont('', '');
            } else {
                $this->SetFont('', 'I');
                $this->MultiCell($widths['registrations'], $height,
                                 get_string('no_registrations', 'grouptool'), $border, 'L', $fill,
                                 0, null, null, true, 1, false, false, $height, 'M', true);
                if ($getheightonly) {
                    $height = max([$height, $this->getLastH()]);
                }
                $this->SetFont('', '');
            }
        }
        if (!in_array('queues', $collapsed)) {
            if (!empty($queues) && is_array($queues)) {
                $queuesstrings = [];
                foreach ($queues as $queue) {
                    $queuesstrings[] = $queue['name'].' (#'.$queue['rank'].')';
                }
                if ($getheightonly) {
                    $this->MultiCell(0, $height, implode("\n", $queuesstrings), $borderl,
                                     'L', $fill, 0, null, null, true, 1, false, false, $height,
                                     'M', false);
                    $height = count($queues) * max([$height, $this->getLastH()]);
                } else {
                    $this->MultiCell(0, $height, implode("\n", $queuesstrings), $borderl,
                                     'L', $fill, 0, null, null, true, 1, false, false, $height,
                                     'M', true);
                }
            } else if ($header) {
                $this->SetFont('', 'B');
                $this->MultiCell(0, $height, $queues, $borderl, 'L', $fill, 0, null, null,
                                 true, 1, false, false, $height, 'M', true);
                if ($getheightonly) {
                    $height = max([$height, $this->getLastH()]);
                }
                $this->SetFont('', '');
            } else {
                $this->SetFont('', 'I');
                $this->MultiCell(0, $height, get_string('nowhere_queued', 'grouptool'), $borderl,
                                 'L', $fill, 0, null, null, true, 1, false, false, $height,
                                 'M', true);
                if ($getheightonly) {
                    $height = max([$height, $this->getLastH()]);
                }
                $this->SetFont('', '');
            }
        }
        $this->Ln($height);
        if ($getheightonly) {
            // Restore previous object!
            $this->rollbackTransaction(true);
        }
        return $height;
    }

}