예제 #1
0
 /**
  * Constructor
  *
  * @param string $elementName (optional) name of the editor
  * @param string $elementLabel (optional) editor label
  * @param array $attributes (optional) Either a typical HTML attribute string
  *              or an associative array
  * @param array $options set of options to initalize filepicker
  */
 function MoodleQuickForm_editor($elementName = null, $elementLabel = null, $attributes = null, $options = null)
 {
     global $CFG, $PAGE;
     $options = (array) $options;
     foreach ($options as $name => $value) {
         if (array_key_exists($name, $this->_options)) {
             $this->_options[$name] = $value;
         }
     }
     if (!empty($options['maxbytes'])) {
         $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
     }
     if (!$this->_options['context']) {
         // trying to set context to the current page context to make legacy files show in filepicker (e.g. forum post)
         if (!empty($PAGE->context->id)) {
             $this->_options['context'] = $PAGE->context;
         } else {
             $this->_options['context'] = context_system::instance();
         }
     }
     $this->_options['trusted'] = trusttext_trusted($this->_options['context']);
     parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
     // Note: for some reason the code using this setting does not like bools.
     $this->_options['subdirs'] = (int) ($this->_options['subdirs'] == 1);
     editors_head_setup();
 }
예제 #2
0
 function MoodleQuickForm_editor($elementName = null, $elementLabel = null, $attributes = null, $options = null)
 {
     global $CFG, $PAGE;
     $options = (array) $options;
     foreach ($options as $name => $value) {
         if (array_key_exists($name, $this->_options)) {
             $this->_options[$name] = $value;
         }
     }
     if (!empty($options['maxbytes'])) {
         $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
     }
     if (!$this->_options['context']) {
         $this->_options['context'] = get_context_instance(CONTEXT_SYSTEM);
     }
     $this->_options['trusted'] = trusttext_trusted($this->_options['context']);
     parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
     editors_head_setup();
 }
예제 #3
0
파일: lib.php 프로젝트: Jtgadbois/Pedadida
/**
 * Given an object containing all the necessary data,
 * (defined by the form in mod_form.php) this function
 * will update an existing instance with new data.
 *
 * @global object
 * @param object $forum forum instance (with magic quotes)
 * @return bool success
 */
function forum_update_instance($forum, $mform) {
    global $DB, $OUTPUT, $USER;

    $forum->timemodified = time();
    $forum->id           = $forum->instance;

    if (empty($forum->assessed)) {
        $forum->assessed = 0;
    }

    if (empty($forum->ratingtime) or empty($forum->assessed)) {
        $forum->assesstimestart  = 0;
        $forum->assesstimefinish = 0;
    }

    $oldforum = $DB->get_record('forum', array('id'=>$forum->id));

    // MDL-3942 - if the aggregation type or scale (i.e. max grade) changes then recalculate the grades for the entire forum
    // if  scale changes - do we need to recheck the ratings, if ratings higher than scale how do we want to respond?
    // for count and sum aggregation types the grade we check to make sure they do not exceed the scale (i.e. max score) when calculating the grade
    if (($oldforum->assessed<>$forum->assessed) or ($oldforum->scale<>$forum->scale)) {
        forum_update_grades($forum); // recalculate grades for the forum
    }

    if ($forum->type == 'single') {  // Update related discussion and post.
        $discussions = $DB->get_records('forum_discussions', array('forum'=>$forum->id), 'timemodified ASC');
        if (!empty($discussions)) {
            if (count($discussions) > 1) {
                echo $OUTPUT->notification(get_string('warnformorepost', 'forum'));
            }
            $discussion = array_pop($discussions);
        } else {
            // try to recover by creating initial discussion - MDL-16262
            $discussion = new stdClass();
            $discussion->course          = $forum->course;
            $discussion->forum           = $forum->id;
            $discussion->name            = $forum->name;
            $discussion->assessed        = $forum->assessed;
            $discussion->message         = $forum->intro;
            $discussion->messageformat   = $forum->introformat;
            $discussion->messagetrust    = true;
            $discussion->mailnow         = false;
            $discussion->groupid         = -1;

            $message = '';

            forum_add_discussion($discussion, null, $message);

            if (! $discussion = $DB->get_record('forum_discussions', array('forum'=>$forum->id))) {
                print_error('cannotadd', 'forum');
            }
        }
        if (! $post = $DB->get_record('forum_posts', array('id'=>$discussion->firstpost))) {
            print_error('cannotfindfirstpost', 'forum');
        }

        $cm         = get_coursemodule_from_instance('forum', $forum->id);
        $modcontext = context_module::instance($cm->id, MUST_EXIST);

        $post = $DB->get_record('forum_posts', array('id'=>$discussion->firstpost), '*', MUST_EXIST);
        $post->subject       = $forum->name;
        $post->message       = $forum->intro;
        $post->messageformat = $forum->introformat;
        $post->messagetrust  = trusttext_trusted($modcontext);
        $post->modified      = $forum->timemodified;
        $post->userid        = $USER->id;    // MDL-18599, so that current teacher can take ownership of activities.

        if ($mform and $draftid = file_get_submitted_draft_itemid('introeditor')) {
            // Ugly hack - we need to copy the files somehow.
            $options = array('subdirs'=>true); // Use the same options as intro field!
            $post->message = file_save_draft_area_files($draftid, $modcontext->id, 'mod_forum', 'post', $post->id, $options, $post->message);
        }

        $DB->update_record('forum_posts', $post);
        $discussion->name = $forum->name;
        $DB->update_record('forum_discussions', $discussion);
    }

    $DB->update_record('forum', $forum);

    $modcontext = context_module::instance($forum->coursemodule);
    if (($forum->forcesubscribe == FORUM_INITIALSUBSCRIBE) && ($oldforum->forcesubscribe <> $forum->forcesubscribe)) {
        $users = forum_get_potential_subscribers($modcontext, 0, 'u.id, u.email', '');
        foreach ($users as $user) {
            forum_subscribe($user->id, $forum->id);
        }
    }

    forum_grade_item_update($forum);

    return true;
}
예제 #4
0
파일: weblib.php 프로젝트: hatone/moodle
/**
 * Must be called before editing of all texts
 * with trust flag. Removes all XSS nasties
 * from texts stored in database if needed.
 *
 * @param object $object data object with xxx, xxxformat and xxxtrust fields
 * @param string $field name of text field
 * @param object $context active context
 * @return object updated $object
 */
function trusttext_pre_edit($object, $field, $context)
{
    $trustfield = $field . 'trust';
    $formatfield = $field . 'format';
    if (!$object->{$trustfield} or !trusttext_trusted($context)) {
        $object->{$field} = clean_text($object->{$field}, $object->{$formatfield});
    }
    return $object;
}
예제 #5
0
파일: post.php 프로젝트: njorth/marginalia
    }
}
$draftid_editor = file_get_submitted_draft_itemid('message');
$currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_forum', 'post', empty($post->id) ? null : $post->id, array('subdirs' => true), $post->message);
$mform_post->set_data(array('attachments' => $draftitemid, 'general' => $heading, 'subject' => $post->subject, 'message' => array('text' => $currenttext, 'format' => empty($post->messageformat) ? editors_get_preferred_format() : $post->messageformat, 'itemid' => $draftid_editor), 'subscribe' => $subscribe ? 1 : 0, 'mailnow' => !empty($post->mailnow), 'userid' => $post->userid, 'parent' => $post->parent, 'discussion' => $post->discussion, 'course' => $course->id) + $page_params + (isset($post->format) ? array('format' => $post->format) : array()) + (isset($discussion->timestart) ? array('timestart' => $discussion->timestart) : array()) + (isset($discussion->timeend) ? array('timeend' => $discussion->timeend) : array()) + (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) + (isset($discussion->id) ? array('discussion' => $discussion->id) : array()));
if ($fromform = $mform_post->get_data()) {
    if (empty($SESSION->fromurl)) {
        $errordestination = "{$CFG->wwwroot}/mod/forum/view.php?f={$forum->id}";
    } else {
        $errordestination = $SESSION->fromurl;
    }
    $fromform->itemid = $fromform->message['itemid'];
    $fromform->messageformat = $fromform->message['format'];
    $fromform->message = $fromform->message['text'];
    // WARNING: the $fromform->message array has been overwritten, do not use it anymore!
    $fromform->messagetrust = trusttext_trusted($modcontext);
    $contextcheck = isset($fromform->groupinfo) && has_capability('mod/forum:movediscussions', $modcontext);
    if ($fromform->edit) {
        // Updating a post
        unset($fromform->groupid);
        $fromform->id = $fromform->edit;
        $message = '';
        //fix for bug #4314
        if (!($realpost = $DB->get_record('forum_posts', array('id' => $fromform->id)))) {
            $realpost = new stdClass();
            $realpost->userid = -1;
        }
        // if user has edit any post capability
        // or has either startnewdiscussion or reply capability and is editting own post
        // then he can proceed
        // MDL-7066
예제 #6
0
/**
 * Prepares the content of the 'editor' form element with embedded media files to be saved in database
 *
 * This function moves files from draft area to the destination area and
 * encodes URLs to the draft files so they can be safely saved into DB. The
 * form has to contain the 'editor' element named foobar_editor, where 'foobar'
 * is the name of the database field to hold the wysiwyg editor content. The
 * editor data comes as an array with text, format and itemid properties. This
 * function automatically adds $data properties foobar, foobarformat and
 * foobartrust, where foobar has URL to embedded files encoded.
 *
 * @category files
 * @param stdClass $data raw data submitted by the form
 * @param string $field name of the database field containing the html with embedded media files
 * @param array $options editor options (trusttext, subdirs, maxfiles, maxbytes etc.)
 * @param stdClass $context context, required for existing data
 * @param string $component file component
 * @param string $filearea file area name
 * @param int $itemid item id, required if item exists
 * @return stdClass modified data object
 */
function file_postupdate_standard_editor($data, $field, array $options, $context, $component = null, $filearea = null, $itemid = null)
{
    $options = (array) $options;
    if (!isset($options['trusttext'])) {
        $options['trusttext'] = false;
    }
    if (!isset($options['forcehttps'])) {
        $options['forcehttps'] = false;
    }
    if (!isset($options['subdirs'])) {
        $options['subdirs'] = false;
    }
    if (!isset($options['maxfiles'])) {
        $options['maxfiles'] = 0;
        // no files by default
    }
    if (!isset($options['maxbytes'])) {
        $options['maxbytes'] = 0;
        // unlimited
    }
    if ($options['trusttext']) {
        $data->{$field . 'trust'} = trusttext_trusted($context);
    } else {
        $data->{$field . 'trust'} = 0;
    }
    $editor = $data->{$field . '_editor'};
    if ($options['maxfiles'] == 0 or is_null($filearea) or is_null($itemid) or empty($editor['itemid'])) {
        $data->{$field} = $editor['text'];
    } else {
        $data->{$field} = file_save_draft_area_files($editor['itemid'], $context->id, $component, $filearea, $itemid, $options, $editor['text'], $options['forcehttps']);
    }
    $data->{$field . 'format'} = $editor['format'];
    return $data;
}
예제 #7
0
파일: lib.php 프로젝트: richheath/moodle
/**
 * Given an object containing all the necessary data,
 * (defined by the form in mod_form.php) this function
 * will update an existing instance with new data.
 *
 * @global object
 * @param object $forum forum instance (with magic quotes)
 * @return bool success
 */
function forum_update_instance($forum, $mform)
{
    global $DB, $OUTPUT, $USER;
    $forum->timemodified = time();
    $forum->id = $forum->instance;
    if (empty($forum->assessed)) {
        $forum->assessed = 0;
    }
    if (empty($forum->ratingtime) or empty($forum->assessed)) {
        $forum->assesstimestart = 0;
        $forum->assesstimefinish = 0;
    }
    $oldforum = $DB->get_record('forum', array('id' => $forum->id));
    // MDL-3942 - if the aggregation type or scale (i.e. max grade) changes then recalculate the grades for the entire forum
    // if  scale changes - do we need to recheck the ratings, if ratings higher than scale how do we want to respond?
    // for count and sum aggregation types the grade we check to make sure they do not exceed the scale (i.e. max score) when calculating the grade
    if ($oldforum->assessed != $forum->assessed or $oldforum->scale != $forum->scale) {
        forum_update_grades($forum);
        // recalculate grades for the forum
    }
    if ($forum->type == 'single') {
        // Update related discussion and post.
        if (!($discussion = $DB->get_record('forum_discussions', array('forum' => $forum->id)))) {
            if ($discussions = $DB->get_records('forum_discussions', array('forum' => $forum->id), 'timemodified ASC')) {
                echo $OUTPUT->notification('Warning! There is more than one discussion in this forum - using the most recent');
                $discussion = array_pop($discussions);
            } else {
                // try to recover by creating initial discussion - MDL-16262
                $discussion = new stdClass();
                $discussion->course = $forum->course;
                $discussion->forum = $forum->id;
                $discussion->name = $forum->name;
                $discussion->assessed = $forum->assessed;
                $discussion->message = $forum->intro;
                $discussion->messageformat = $forum->introformat;
                $discussion->messagetrust = true;
                $discussion->mailnow = false;
                $discussion->groupid = -1;
                $message = '';
                forum_add_discussion($discussion, null, $message);
                if (!($discussion = $DB->get_record('forum_discussions', array('forum' => $forum->id)))) {
                    print_error('cannotadd', 'forum');
                }
            }
        }
        if (!($post = $DB->get_record('forum_posts', array('id' => $discussion->firstpost)))) {
            print_error('cannotfindfirstpost', 'forum');
        }
        $cm = get_coursemodule_from_instance('forum', $forum->id);
        $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST);
        if ($mform and $draftid = file_get_submitted_draft_itemid('introeditor')) {
            // ugly hack - we need to copy the files somehow
            $discussion = $DB->get_record('forum_discussions', array('id' => $discussion->id), '*', MUST_EXIST);
            $post = $DB->get_record('forum_posts', array('id' => $discussion->firstpost), '*', MUST_EXIST);
            $post->message = file_save_draft_area_files($draftid, $modcontext->id, 'mod_forum', 'post', $post->id, array('subdirs' => true), $post->message);
        }
        $post->subject = $forum->name;
        $post->message = $forum->intro;
        $post->messageformat = $forum->introformat;
        $post->messagetrust = trusttext_trusted($modcontext);
        $post->modified = $forum->timemodified;
        $post->userid = $USER->id;
        // MDL-18599, so that current teacher can take ownership of activities
        $DB->update_record('forum_posts', $post);
        $discussion->name = $forum->name;
        $DB->update_record('forum_discussions', $discussion);
    }
    $DB->update_record('forum', $forum);
    forum_grade_item_update($forum);
    return true;
}
 /**
  * Creates the discussion object to be saved.
  *
  * @param object $forum
  * @param \context_module $context
  * @param array $options These override default post values, EG: set the post message with this
  * @return \stdClass
  */
 public function create_discussion_object($forum, $context, array $options = array())
 {
     $discussion = (object) array('name' => '', 'subject' => '', 'course' => $forum->course, 'forum' => $forum->id, 'groupid' => -1, 'timestart' => 0, 'timeend' => 0, 'message' => '', 'messageformat' => FORMAT_MOODLE, 'messagetrust' => trusttext_trusted($context), 'mailnow' => 0, 'reveal' => 0);
     foreach ($options as $name => $value) {
         if (property_exists($discussion, $name)) {
             $discussion->{$name} = $value;
         }
     }
     return $discussion;
 }
예제 #9
0
    /**
     * Add a new discussion into an existing forum.
     *
     * @param int $forumid the forum instance id
     * @param string $subject new discussion subject
     * @param string $message new discussion message (only html format allowed)
     * @param int $groupid the user course group
     * @param array $options optional settings
     * @return array of warnings and the new discussion id
     * @since Moodle 3.0
     * @throws moodle_exception
     */
    public static function add_discussion($forumid, $subject, $message, $groupid = -1, $options = array()) {
        global $DB, $CFG;
        require_once($CFG->dirroot . "/mod/forum/lib.php");

        $params = self::validate_parameters(self::add_discussion_parameters(),
                                            array(
                                                'forumid' => $forumid,
                                                'subject' => $subject,
                                                'message' => $message,
                                                'groupid' => $groupid,
                                                'options' => $options
                                            ));
        // Validate options.
        $options = array(
            'discussionsubscribe' => true
        );
        foreach ($params['options'] as $option) {
            $name = trim($option['name']);
            switch ($name) {
                case 'discussionsubscribe':
                    $value = clean_param($option['value'], PARAM_BOOL);
                    break;
                default:
                    throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
            }
            $options[$name] = $value;
        }

        $warnings = array();

        // Request and permission validation.
        $forum = $DB->get_record('forum', array('id' => $params['forumid']), '*', MUST_EXIST);
        list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum');

        $context = context_module::instance($cm->id);
        self::validate_context($context);

        // Normalize group.
        if (!groups_get_activity_groupmode($cm)) {
            // Groups not supported, force to -1.
            $groupid = -1;
        } else {
            // Check if we receive the default or and empty value for groupid,
            // in this case, get the group for the user in the activity.
            if ($groupid === -1 or empty($params['groupid'])) {
                $groupid = groups_get_activity_group($cm);
            } else {
                // Here we rely in the group passed, forum_user_can_post_discussion will validate the group.
                $groupid = $params['groupid'];
            }
        }

        if (!forum_user_can_post_discussion($forum, $groupid, -1, $cm, $context)) {
            throw new moodle_exception('cannotcreatediscussion', 'forum');
        }

        $thresholdwarning = forum_check_throttling($forum, $cm);
        forum_check_blocking_threshold($thresholdwarning);

        // Create the discussion.
        $discussion = new stdClass();
        $discussion->course = $course->id;
        $discussion->forum = $forum->id;
        $discussion->message = $params['message'];
        $discussion->messageformat = FORMAT_HTML;   // Force formatting for now.
        $discussion->messagetrust = trusttext_trusted($context);
        $discussion->itemid = 0;
        $discussion->groupid = $groupid;
        $discussion->mailnow = 0;
        $discussion->subject = $params['subject'];
        $discussion->name = $discussion->subject;
        $discussion->timestart = 0;
        $discussion->timeend = 0;

        if ($discussionid = forum_add_discussion($discussion)) {

            $discussion->id = $discussionid;

            // Trigger events and completion.

            $params = array(
                'context' => $context,
                'objectid' => $discussion->id,
                'other' => array(
                    'forumid' => $forum->id,
                )
            );
            $event = \mod_forum\event\discussion_created::create($params);
            $event->add_record_snapshot('forum_discussions', $discussion);
            $event->trigger();

            $completion = new completion_info($course);
            if ($completion->is_enabled($cm) &&
                    ($forum->completiondiscussions || $forum->completionposts)) {
                $completion->update_state($cm, COMPLETION_COMPLETE);
            }

            $settings = new stdClass();
            $settings->discussionsubscribe = $options['discussionsubscribe'];
            forum_post_subscription($settings, $forum, $discussion);
        } else {
            throw new moodle_exception('couldnotadd', 'forum');
        }

        $result = array();
        $result['discussionid'] = $discussionid;
        $result['warnings'] = $warnings;
        return $result;
    }
예제 #10
0
/**
 * Given an object containing all the necessary data,
 * (defined by the form in mod_form.php) this function
 * will update an existing instance with new data.
 *
 * @global object
 * @param object $anonforum anonforum instance (with magic quotes)
 * @return bool success
 */
function anonforum_update_instance($anonforum, $mform)
{
    global $DB, $OUTPUT, $USER;
    $anonforum->timemodified = time();
    $anonforum->id = $anonforum->instance;
    if (empty($anonforum->assessed)) {
        $anonforum->assessed = 0;
    }
    if (empty($anonforum->ratingtime) or empty($anonforum->assessed)) {
        $anonforum->assesstimestart = 0;
        $anonforum->assesstimefinish = 0;
    }
    $oldanonforum = $DB->get_record('anonforum', array('id' => $anonforum->id));
    if ($anonforum->type == 'single') {
        // Update related discussion and post.
        $discussions = $DB->get_records('anonforum_discussions', array('anonforum' => $anonforum->id), 'timemodified ASC');
        if (!empty($discussions)) {
            if (count($discussions) > 1) {
                echo $OUTPUT->notification(get_string('warnformorepost', 'anonforum'));
            }
            $discussion = array_pop($discussions);
        } else {
            // try to recover by creating initial discussion - MDL-16262
            $discussion = new stdClass();
            $discussion->course = $anonforum->course;
            $discussion->anonforum = $anonforum->id;
            $discussion->name = $anonforum->name;
            $discussion->assessed = $anonforum->assessed;
            $discussion->message = $anonforum->intro;
            $discussion->messageformat = $anonforum->introformat;
            $discussion->messagetrust = true;
            $discussion->mailnow = false;
            $discussion->groupid = -1;
            $discussion->anonymouspost = $anonforum->anonymous;
            $message = '';
            anonforum_add_discussion($discussion, null, $message);
            if (!($discussion = $DB->get_record('anonforum_discussions', array('anonforum' => $anonforum->id)))) {
                print_error('cannotadd', 'anonforum');
            }
        }
        if (!($post = $DB->get_record('anonforum_posts', array('id' => $discussion->firstpost)))) {
            print_error('cannotfindfirstpost', 'anonforum');
        }
        $cm = get_coursemodule_from_instance('anonforum', $anonforum->id);
        $modcontext = context_module::instance($cm->id, MUST_EXIST);
        $post = $DB->get_record('anonforum_posts', array('id' => $discussion->firstpost), '*', MUST_EXIST);
        $post->subject = $anonforum->name;
        $post->message = $anonforum->intro;
        $post->messageformat = $anonforum->introformat;
        $post->messagetrust = trusttext_trusted($modcontext);
        $post->modified = $anonforum->timemodified;
        $post->userid = $USER->id;
        // MDL-18599, so that current teacher can take ownership of activities.
        if ($mform and $draftid = file_get_submitted_draft_itemid('introeditor')) {
            // Ugly hack - we need to copy the files somehow.
            $options = array('subdirs' => true);
            // Use the same options as intro field!
            $post->message = file_save_draft_area_files($draftid, $modcontext->id, 'mod_anonforum', 'post', $post->id, $options, $post->message);
        }
        $DB->update_record('anonforum_posts', $post);
        $discussion->name = $anonforum->name;
        $DB->update_record('anonforum_discussions', $discussion);
    }
    $DB->update_record('anonforum', $anonforum);
    $modcontext = context_module::instance($anonforum->coursemodule);
    if ($anonforum->forcesubscribe == ANONFORUM_INITIALSUBSCRIBE && $oldanonforum->forcesubscribe != $anonforum->forcesubscribe) {
        $users = anonforum_get_potential_subscribers($modcontext, 0, 'u.id, u.email', '');
        foreach ($users as $user) {
            anonforum_subscribe($user->id, $anonforum->id);
        }
    }
    anonforum_grade_item_update($anonforum);
    return true;
}
예제 #11
0
    /**
     * Create new posts into an existing discussion.
     *
     * @param int $postid the post id we are going to reply to
     * @param string $subject new post subject
     * @param string $message new post message (only html format allowed)
     * @param array $options optional settings
     * @return array of warnings and the new post id
     * @since Moodle 3.0
     * @throws moodle_exception
     */
    public static function add_discussion_post($postid, $subject, $message, $options = array()) {
        global $DB, $CFG, $USER;
        require_once($CFG->dirroot . "/mod/forum/lib.php");

        $params = self::validate_parameters(self::add_discussion_post_parameters(),
                                            array(
                                                'postid' => $postid,
                                                'subject' => $subject,
                                                'message' => $message,
                                                'options' => $options
                                            ));
        // Validate options.
        $options = array(
            'discussionsubscribe' => true
        );
        foreach ($params['options'] as $option) {
            $name = trim($option['name']);
            switch ($name) {
                case 'discussionsubscribe':
                    $value = clean_param($option['value'], PARAM_BOOL);
                    break;
                default:
                    throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
            }
            $options[$name] = $value;
        }

        $warnings = array();

        if (!$parent = forum_get_post_full($params['postid'])) {
            throw new moodle_exception('invalidparentpostid', 'forum');
        }

        if (!$discussion = $DB->get_record("forum_discussions", array("id" => $parent->discussion))) {
            throw new moodle_exception('notpartofdiscussion', 'forum');
        }

        // Request and permission validation.
        $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
        list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum');

        $context = context_module::instance($cm->id);
        self::validate_context($context);

        if (!forum_user_can_post($forum, $discussion, $USER, $cm, $course, $context)) {
            throw new moodle_exception('nopostforum', 'forum');
        }

        $thresholdwarning = forum_check_throttling($forum, $cm);
        forum_check_blocking_threshold($thresholdwarning);

        // Create the post.
        $post = new stdClass();
        $post->discussion = $discussion->id;
        $post->parent = $parent->id;
        $post->subject = $params['subject'];
        $post->message = $params['message'];
        $post->messageformat = FORMAT_HTML;   // Force formatting for now.
        $post->messagetrust = trusttext_trusted($context);
        $post->itemid = 0;

        if ($postid = forum_add_new_post($post, null)) {

            $post->id = $postid;

            // Trigger events and completion.
            $params = array(
                'context' => $context,
                'objectid' => $post->id,
                'other' => array(
                    'discussionid' => $discussion->id,
                    'forumid' => $forum->id,
                    'forumtype' => $forum->type,
                )
            );
            $event = \mod_forum\event\post_created::create($params);
            $event->add_record_snapshot('forum_posts', $post);
            $event->add_record_snapshot('forum_discussions', $discussion);
            $event->trigger();

            // Update completion state.
            $completion = new completion_info($course);
            if ($completion->is_enabled($cm) &&
                    ($forum->completionreplies || $forum->completionposts)) {
                $completion->update_state($cm, COMPLETION_COMPLETE);
            }

            $settings = new stdClass();
            $settings->discussionsubscribe = $options['discussionsubscribe'];
            forum_post_subscription($settings, $forum, $discussion);
        } else {
            throw new moodle_exception('couldnotadd', 'forum');
        }

        $result = array();
        $result['postid'] = $postid;
        $result['warnings'] = $warnings;
        return $result;
    }
 /**
  * Creates the post object to be saved.
  *
  * @param object $discussion
  * @param object $parent The parent post
  * @param \context_module $context
  * @param array $options These override default post values, EG: set the post message with this
  * @return \stdClass
  */
 public function create_post_object($discussion, $parent, $context, array $options = array())
 {
     $post = new \stdClass();
     $post->course = $discussion->course;
     $post->forum = $discussion->forum;
     $post->discussion = $discussion->id;
     $post->parent = $parent->id;
     $post->reveal = 0;
     $post->privatereply = 0;
     $post->mailnow = 0;
     $post->subject = $parent->subject;
     $post->attachment = '';
     $post->message = '';
     $post->messageformat = FORMAT_MOODLE;
     $post->messagetrust = trusttext_trusted($context);
     $post->itemid = 0;
     // For text editor stuffs.
     $post->groupid = $discussion->groupid == -1 ? 0 : $discussion->groupid;
     $post->flags = null;
     $strre = get_string('re', 'hsuforum');
     if (!(\core_text::substr($post->subject, 0, \core_text::strlen($strre)) == $strre)) {
         $post->subject = $strre . ' ' . $post->subject;
     }
     // Make sure post subject does not go beyond 255 chars.
     $post->subject = \mod_hsuforum\local::shorten_post_name($post->subject);
     foreach ($options as $name => $value) {
         if (property_exists($post, $name)) {
             $post->{$name} = $value;
         }
     }
     return $post;
 }