<?php

// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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/>.

/**
 * Library of useful functions
 *
 * @copyright 1999 Martin Dougiamas  http://dougiamas.com
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @package core_course
 */
defined('MOODLE_INTERNAL') || die;
require_once($CFG->libdir . '/moodlelib.php');

/**
 * This class pertains to course requests and contains methods associated with
 * create, approving, and removing course requests.
 *
 * Please note we do not allow embedded images here because there is no context
 * to store them with proper access control.
 *
 * @copyright 2009 Sam Hemelryk
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @since Moodle 2.0
 *
 * @property-read int $id
 * @property-read string $fullname
 * @property-read string $shortname
 * @property-read string $summary
 * @property-read int $summaryformat
 * @property-read int $summarytrust
 * @property-read string $reason
 * @property-read int $requester
 */
class course_request_hsh
{

    /**
     * This is the stdClass that stores the properties for the course request
     * and is externally accessed through the __get magic method
     * @var stdClass
     */
    protected $properties;

    /**
     * An array of options for the summary editor used by course request forms.
     * This is initially set by {@link summary_editor_options()}
     * @var array
     * @static
     */
    protected static $summaryeditoroptions;

    /**
     * Static function to prepare the summary editor for working with a course
     * request.
     *
     * @static
     * @param null|stdClass $data Optional, an object containing the default values
     *                       for the form, these may be modified when preparing the
     *                       editor so this should be called before creating the form
     * @return stdClass An object that can be used to set the default values for
     *                   an mforms form
     */
    public static function prepare($data = null)
    {
        if ($data === null) {
            $data = new stdClass;
        }
        $data = file_prepare_standard_editor($data, 'summary', self::summary_editor_options());
        return $data;
    }

    /**
     * Static function to create a new course request when passed an array of properties
     * for it.
     *
     * This function also handles saving any files that may have been used in the editor
     *
     * @static
     * @param stdClass $data
     * @return course_request_hsh The newly created course request
     */
    public static function create($data) {
        global $USER, $DB, $CFG;
        $data->requester = $USER->id;

        // Setting the default category if none set.
        if (empty($data->category) || !empty($CFG->lockrequestcategory)) {
            $data->category = $CFG->defaultrequestcategory;
        }

        // Summary is a required field so copy the text over
        $data->summary = $data->summary_editor['text'];
        $data->summaryformat = $data->summary_editor['format'];

        // > HsH
        $data->fullname = \course_request_hsh::get_hsh_name(
            $data->fullname,
            $data->teachername,
            $data->customfield_semester,
            false
        );
        $data->shortname = \course_request_hsh::get_hsh_name(
            $data->shortname,
            $data->teachername,
            $data->customfield_semester,
            true
        );

        if (isset($data->consult)) {
            $data->reason .= '</br> ' . get_string('elcconsult', 'local_hsh');
        }
        // < HsH

        $data->id = $DB->insert_record('local_hsh_course_request', $data);

        // Create a new course_request object and return it
        $request = new course_request_hsh($data);

        // Notify the admin if required.
        if ($users = get_users_from_config($CFG->courserequestnotify, 'moodle/site:approvecourse')) {

            $data->user = fullname($USER);
            $data->link = $CFG->wwwroot . "/local/hsh/pending.php";
            $data->email = $USER->email;
            $cats = \core_course_category::make_categories_list('', 0, ' / ');
            $data->category = $cats[$data->category];
            $subject = get_string('courserequest', 'local_hsh');
            $message = get_string('courserequestnotifyemail', 'local_hsh', $data);
            foreach ($users as $user) {
                $request->notify('moodle', $user, $USER, 'courserequested', $subject, $message);
            }
        }

        return $request;
    }

    /**
     * Returns an array of options to use with a summary editor
     *
     * @return array An array of options to use with the editor
     * @uses course_request_hsh::$summaryeditoroptions
     */
    public static function summary_editor_options() {
        global $CFG;
        if (self::$summaryeditoroptions === null) {
            self::$summaryeditoroptions = array('maxfiles' => 0, 'maxbytes' => 0);
        }
        return self::$summaryeditoroptions;
    }

    /**
     * Loads the properties for this course request object. Id is required and if
     * only id is provided then we load the rest of the properties from the database
     *
     * @param stdClass|int $properties Either an object containing properties
     *                      or the course_request id to load
     */
    public function __construct($properties) {
        global $DB;
        if (empty($properties->id)) {
            if (empty($properties)) {
                throw new coding_exception('You must provide a course request id when creating a course_request object');
            }
            $id = $properties;
            $properties = new stdClass;
            $properties->id = (int)$id;
            unset($id);
        }
        if (empty($properties->requester)) {
            if (!($this->properties = $DB->get_record('local_hsh_course_request', array('id' => $properties->id)))) {
                throw new \moodle_exception('unknowncourserequest');
            }
        } else {
            $this->properties = $properties;
        }
        $this->properties->collision = null;
    }

    /**
     * Returns the requested property
     *
     * @param string $key
     * @return mixed
     */
    public function __get($key) {
        return $this->properties->$key;
    }

    /**
     * Override this to ensure empty($request->blah) calls return a reliable answer...
     *
     * This is required because we define the __get method
     *
     * @param mixed $key
     * @return bool True is it not empty, false otherwise
     */
    public function __isset($key)  {
        return (!empty($this->properties->$key));
    }

    /**
     * Returns the user who requested this course
     *
     * Uses a static var to cache the results and cut down the number of db queries
     *
     * @staticvar array $requesters An array of cached users
     * @return stdClass The user who requested the course
     */
    public function get_requester() {
        global $DB;
        static $requesters = array();
        if (!array_key_exists($this->properties->requester, $requesters)) {
            $requesters[$this->properties->requester] = $DB->get_record('user', array('id' => $this->properties->requester));
        }
        return $requesters[$this->properties->requester];
    }

    /**
     * Checks that the shortname used by the course does not conflict with any other
     * courses that exist
     *
     * @param string|null $shortnamemark The string to append to the requests shortname
     *                     should a conflict be found
     * @return bool true is there is a conflict, false otherwise
     */
    public function check_shortname_collision($shortnamemark = '[*]') {
        global $DB;

        if ($this->properties->collision !== null) {
            return $this->properties->collision;
        }

        if (empty($this->properties->shortname)) {
            debugging('Attempting to check a course request shortname before it has been set', DEBUG_DEVELOPER);
            $this->properties->collision = false;
        } else if ($DB->record_exists('course', array('shortname' => $this->properties->shortname))) {
            if (!empty($shortnamemark)) {
                $this->properties->shortname .= ' ' . $shortnamemark;
            }
            $this->properties->collision = true;
        } else {
            $this->properties->collision = false;
        }
        return $this->properties->collision;
    }

    /**
     * Checks user capability to approve a requested course
     *
     * If course was requested without category for some reason (might happen if $CFG->defaultrequestcategory is
     * misconfigured), we check capabilities 'moodle/site:approvecourse' and 'moodle/course:changecategory'.
     *
     * @return bool
     */
    public function can_approve() {
        global $CFG;
        $category = null;
        if ($this->properties->category) {
            $category = core_course_category::get($this->properties->category, IGNORE_MISSING);
        } else if ($CFG->defaultrequestcategory) {
            $category = core_course_category::get($CFG->defaultrequestcategory, IGNORE_MISSING);
        }
        if ($category) {
            return has_capability('moodle/site:approvecourse', $category->get_context());
        }

        // We can not determine the context where the course should be created. The approver should have
        // both capabilities to approve courses and change course category in the system context.
        return has_all_capabilities(['moodle/site:approvecourse', 'moodle/course:changecategory'], context_system::instance());
    }

    /**
     * Returns the category where this course request should be created
     *
     * Note that we don't check here that user has a capability to view
     * hidden categories if he has capabilities 'moodle/site:approvecourse' and
     * 'moodle/course:changecategory'
     *
     * @return core_course_category
     */
    public function get_category()
    {
        global $CFG;
        if ($this->properties->category && ($category = core_course_category::get($this->properties->category, IGNORE_MISSING))) {
            return $category;
        } else if ($CFG->defaultrequestcategory &&
            ($category = core_course_category::get($CFG->defaultrequestcategory, IGNORE_MISSING))) {
            return $category;
        } else {
            return core_course_category::get_default();
        }
    }

    /**
     * This function approves the request turning it into a course
     *
     * This function converts the course request into a course, at the same time
     * transferring any files used in the summary to the new course and then removing
     * the course request and the files associated with it.
     *
     * @return int The id of the course that was created from this request
     */
    public function approve()
    {
        global $CFG, $DB, $USER;

        require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');

        $user = $DB->get_record('user', array('id' => $this->properties->requester, 'deleted' => 0), '*', MUST_EXIST);

        $courseconfig = get_config('moodlecourse');

        // Transfer appropriate settings
        $data = clone($this->properties);
        unset($data->id);
        unset($data->reason);
        unset($data->requester);

        // Set category
        $category = $this->get_category();
        $data->category = $category->id;
        // Set misc settings
        $data->requested = 1;

        // Apply course default settings
        $data->format             = $courseconfig->format;
        $data->newsitems          = $courseconfig->newsitems;
        $data->showgrades         = $courseconfig->showgrades;
        $data->showreports        = $courseconfig->showreports;
        $data->maxbytes           = $courseconfig->maxbytes;
        $data->groupmode          = $courseconfig->groupmode;
        $data->groupmodeforce     = $courseconfig->groupmodeforce;
        $data->visible            = $courseconfig->visible;
        $data->visibleold         = $data->visible;
        $data->lang               = $courseconfig->lang;
        $data->enablecompletion   = $courseconfig->enablecompletion;
        $data->numsections        = $courseconfig->numsections;
        $data->startdate          = usergetmidnight(time());
        if ($courseconfig->courseenddateenabled) {
            $data->enddate        = usergetmidnight(time()) + $courseconfig->courseduration;
        }

        list($data->fullname, $data->shortname) = restore_dbops::calculate_course_names(0, $data->fullname, $data->shortname);

        $course = create_course($data);
        $context = context_course::instance($course->id, MUST_EXIST);

        // add enrol instances
        if (!$DB->record_exists('enrol', array('courseid' => $course->id, 'enrol' => 'manual'))) {
            if ($manual = enrol_get_plugin('manual')) {
                $manual->add_default_instance($course);
            }
        }

        // > HsH peter werner - set password for self enrolment from request.php
        if (!empty($data->password)) {
            if ($self = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'self', 'status' => 0))) {
                $self->password = $data->password;
                $DB->update_record('enrol', $self);
            }
        }
        // < HsH
        // enrol default roles from plugin config settings
        $default_roles=get_config('local_hsh', 'defaultrole');
        if (!empty($default_roles) && !isguestuser($user) && !is_enrolled($context, $user, 'moodle/role:assign')) {
            $roles = explode(',', $default_roles);
            foreach($roles as $role) {
                enrol_try_internal_enrol($course->id, $user->id, $role);
            }
        } elseif (!empty($CFG->creatornewroleid) && !isguestuser($user) && !is_enrolled($context, $user, 'moodle/role:assign')) {
            enrol_try_internal_enrol($course->id, $user->id, $CFG->creatornewroleid);
        } // enrol the requester as teacher if necessary

        $this->delete();

        $a = new stdClass();
        $a->coursename = format_string($course->fullname, true, array('context' => context_course::instance($course->id)));
        $a->url = $CFG->wwwroot . '/course/view.php?id=' . $course->id;
        $a->responser = fullname($USER);
        $a->email = $USER->email;
        $a->telefon = $USER->phone1;
        $a->fullname = fullname($user);
        $messageplain = $this->get_message_plain($a);
        $this->notify(
            'local_hsh',
            $user,
            $USER,
            'courserequestapproved_hsh',
            get_string('courseapprovedsubject', 'local_hsh', $a),
            $messageplain,
            $course->id
        );

        return $course->id;
    }

    /**
     * Reject a course request
     *
     * This function rejects a course request, emailing the requesting user the
     * provided notice and then removing the request from the database
     *
     * @param string $notice The message to display to the user
     */
    public function reject($notice)
    {
        global $USER, $DB;
        $user = $DB->get_record('user', array('id' => $this->properties->requester), '*', MUST_EXIST);
        $this->notify(
            'local_hsh',
            $user,
            $USER,
            'courserequestrejected_hsh',
            get_string('courserejectsubject', 'local_hsh'),
            get_string('courserejectemail', 'local_hsh', $notice)
        );
        $this->delete();
    }

    /**
     * Deletes the course request and any associated files
     */
    public function delete()
    {
        global $DB;
        $DB->delete_records('local_hsh_course_request', array('id' => $this->properties->id));
    }

    /**
     * Send a message from one user to another using events_trigger
     *
     * @param object $touser
     * @param object $fromuser
     * @param string $name
     * @param string $subject
     * @param string $message
     * @param int|null $courseid
     */

    protected function notify($component, $touser, $fromuser, $name, $subject, $message, $courseid = null) {
        $eventdata = new \core\message\message();
        $eventdata->courseid          = empty($courseid) ? SITEID : $courseid;
        $eventdata->component         = $component;
        $eventdata->name              = $name;
        $eventdata->userfrom          = $fromuser;
        $eventdata->userto            = $touser;
        $eventdata->subject           = $subject;
        $eventdata->fullmessage       = $message;
        $eventdata->fullmessageformat = FORMAT_PLAIN;
        $eventdata->fullmessagehtml   = '';
        $eventdata->smallmessage      = '';
        $eventdata->notification      = 1;
        message_send($eventdata);
    }

    /**
     * Checks if current user can request a course in this context
     *
     * @param context $context
     * @return bool
     */
    public static function can_request(context $context)
    {
        global $CFG;
        if (empty($CFG->enablecourserequests)) {
            return false;
        }
        if (has_capability('moodle/course:create', $context)) {
            return false;
        }

        if ($context instanceof context_system) {
            $defaultcontext = context_coursecat::instance($CFG->defaultrequestcategory, IGNORE_MISSING);
            return $defaultcontext &&
                has_capability('local/hsh:request', $defaultcontext);
        } else if ($context instanceof context_coursecat) {
            if (!$CFG->lockrequestcategory || $CFG->defaultrequestcategory == $context->instanceid) {
                return has_capability('local/hsh:request', $context);
            }
        }
        return false;
    }

    /**
     *
     * @param type $coursename short or fullname
     * @param type $teacher
     * @param type $semesterValue intvalue from db
     * @return type
     */
    public static function get_hsh_name($coursename, $teacher, $semesterValue, $short = true)
    {
        $semesterName = \customfield_semester\data_controller::get_name_for_semester((int)$semesterValue);

        if ($semesterValue == 1) {
            return $coursename . ", " . $teacher;
        } else {
            if ($short) {
                $exploded = explode(" ", $semesterName);
                return $coursename . ", " . $exploded[1] . ", " . $teacher;
            }
            return $coursename . ", " . $semesterName . ", " . $teacher;
        }
    }

    /**
     * replaces coursecategory items
     * @static
     * @return array
     */
    public static function get_short_categories_list()
    {
        $courselist = \core_course_category::make_categories_list('', 0, '$$$');

        foreach ($courselist as &$actCourse) {
            $actCourseArr = explode('$$$', $actCourse);
            $actCourseSize = sizeof($actCourseArr);
            if ($actCourseSize > 1) {
                $actCourse = '';
                for ($i = 0; $i < $actCourseSize - 1; $i++) {
                    $actCourse .= '../ ';
                }
                $actCourse .= $actCourseArr[$actCourseSize - 1];
            }
        }
        return $courselist;
    }

     protected function get_message_plain($a) {
        $message = get_string('address', 'local_hsh', $a) . "\r\n";
        $message .= "\r\n";
        $message .= get_string('courseapproved', 'local_hsh', $a) . "\r\n";
        $message .= "\r\n";
        $message .= get_string('tocourse_plain', 'local_hsh', $a) . "\r\n";
        $message .= "\r\n";
        if (!empty($this->properties->coursecopyurl)) {
            $message .= get_string('coursecopyinform', 'local_hsh', $a) . "\r\n";
            $message .= "\r\n";
        }
//        $message .= get_string('questionhint', 'local_hsh') . ' ' . get_string('questionhintmail', 'local_hsh') . "." . "\r\n";
        $message .= get_string('questionhint1', 'local_hsh') . "\r\n";
//        $message .= get_string('questionhint2', 'local_hsh') . "\r\n";
//        $message .= get_string('questionhint3', 'local_hsh') . "\r\n";

        $message .= "\r\n";
//        $message .= get_string('consultinghint', 'local_hsh') . "\r\n";
        $message .= "\r\n";
        $message .= get_string('greetings', 'local_hsh') . "\r\n";
//        $message .= "\r\n";
        $message .= "Servicezentrum Lehre" . "\r\n";
//        $message .= $a->email . "\r\n";
//        $message .= $a->telefon . "\r\n";
        $message .= "\r\n";
        $message .= "\r\n";
        $message .= get_string('institute1', 'local_hsh') . "\r\n";
//        $message .= get_string('institute2', 'local_hsh') . "\r\n";
        $message .= get_string('ou1', 'local_hsh') . "\r\n";
        $message .= get_string('ou2', 'local_hsh') . "\r\n";
//        $message .= get_string('street', 'local_hsh') . "\r\n";
//        $message .= get_string('place', 'local_hsh') . "\r\n";
        $message .= "\r\n";
        $message .= get_string('email', 'local_hsh') . ': ' . get_string('elcmailaddress', 'local_hsh') . "\r\n";
        $message .= get_string('elcphone', 'local_hsh');
        return $message;
    }

}    // End HsH