Save a student submission for a single assignment

@param int $assignmentid The id of the assignment
@param array $plugindata - The submitted data for plugins
@return array of warnings to indicate any errors
@since Moodle 2.6
428143
public static function save_submission($assignmentid, $plugindata) {
        global $CFG, $USER;

        $params = self::validate_parameters(self::save_submission_parameters(),
                                            array('assignmentid' => $assignmentid,
                                                  'plugindata' => $plugindata));

        list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']);

        $notices = array();

        $assignment->update_effective_access($USER->id);
        if (!$assignment->submissions_open($USER->id)) {
            $notices[] = get_string('duedatereached', 'assign');
        } else {
            $submissiondata = (object)$params['plugindata'];
            $assignment->save_submission($submissiondata, $notices);
        }

        $warnings = array();
        foreach ($notices as $notice) {
            $warnings[] = self::generate_warning($params['assignmentid'],
                                                 'couldnotsavesubmission',
                                                 $notice);
        }

        return $warnings;
    }
689292
public static function get_feedback_document($assignment, $userid, $attemptnumber) {

        $assignment = self::get_assignment_from_param($assignment);

        if (!$assignment->can_view_submission($userid)) {
            print_error('nopermission');
        }

        $grade = $assignment->get_user_grade($userid, true, $attemptnumber);

        $contextid = $assignment->get_context()->id;
        $component = 'assignfeedback_editpdf';
        $filearea = self::FINAL_PDF_FILEAREA;
        $itemid = $grade->id;
        $filepath = '/';

        $fs = get_file_storage();
        $files = $fs->get_area_files($contextid,
                                     $component,
                                     $filearea,
                                     $itemid,
                                     "itemid, filepath, filename",
                                     false);
        if ($files) {
            return reset($files);
        }
        return false;
    }
1291345
public function getAssignment($assignmentId)
    {
        if ($assignmentId == '')
            throw new Exception('Assignment ID not specified');

        //build URI
        $strURI = Product::$baseProductUri . '/tasks/' . $this->getFileName() . '/assignments/' . $assignmentId;

        //sign URI
        $signedURI = Utils::sign($strURI);

        $responseStream = Utils::processCommand($signedURI, 'GET', '', '');

        $json = json_decode($responseStream);

        if ($json->Code == 200)
            return $json->Assignment;
        else
            return false;
    }
613223
public function getAssignments($ruleId, $params = null)
    {
        return $this->client->get("/validation-rules/" . rawurlencode($ruleId) . "/assignments", $params);
    }
149660
public function delete_instance() {
        global $DB;
        $result = true;

        foreach ($this->submissionplugins as $plugin) {
            if (!$plugin->delete_instance()) {
                print_error($plugin->get_error());
                $result = false;
            }
        }
        foreach ($this->feedbackplugins as $plugin) {
            if (!$plugin->delete_instance()) {
                print_error($plugin->get_error());
                $result = false;
            }
        }

        // Delete files associated with this assignment.
        $fs = get_file_storage();
        if (! $fs->delete_area_files($this->context->id) ) {
            $result = false;
        }

        $this->delete_all_overrides();

        // Delete_records will throw an exception if it fails - so no need for error checking here.
        $DB->delete_records('assign_submission', array('assignment' => $this->get_instance()->id));
        $DB->delete_records('assign_grades', array('assignment' => $this->get_instance()->id));
        $DB->delete_records('assign_plugin_config', array('assignment' => $this->get_instance()->id));
        $DB->delete_records('assign_user_flags', array('assignment' => $this->get_instance()->id));
        $DB->delete_records('assign_user_mapping', array('assignment' => $this->get_instance()->id));

        // Delete items from the gradebook.
        if (! $this->delete_grades()) {
            $result = false;
        }

        // Delete the instance.
        // We must delete the module record after we delete the grade item.
        $DB->delete_records('assign', array('id'=>$this->get_instance()->id));

        return $result;
    }
853048
public function createPluginInstance(
        $pluginData,
        SiteEntity $site,
        string $createdByUserId,
        string $createdReason = Tracking::UNKNOWN_REASON,
        $oldPluginInstance = null,
        $doFlush = true
    ) {
        $pluginInstance = new PluginInstanceEntity(
            $createdByUserId,
            $createdReason
        );
        $pluginInstance->populate($pluginData);

        // @deprecated <deprecated-site-wide-plugin>
        $this->updateSiteSitewide(
            $pluginInstance,
            $site,
            $oldPluginInstance
        );

        $this->_em->persist($pluginInstance);

        if ($doFlush) {
            $this->_em->flush($pluginInstance);
        }

        return $pluginInstance;
    }
939265
public static function get_gradingform_instances($definitionid, $since = 0) {
        global $DB, $CFG;
        require_once("$CFG->dirroot/grade/grading/form/lib.php");
        $params = self::validate_parameters(self::get_gradingform_instances_parameters(),
            array('definitionid' => $definitionid,
                'since' => $since));
        $instances = array();
        $warnings = array();

        $definition = $DB->get_record('grading_definitions',
            array('id' => $params['definitionid']),
            'areaid,method', MUST_EXIST);
        $area = $DB->get_record('grading_areas',
            array('id' => $definition->areaid),
            'contextid,component', MUST_EXIST);

        $context = context::instance_by_id($area->contextid);
        require_capability('moodle/grade:managegradingforms', $context);

        $gradingmanager = get_grading_manager($definition->areaid);
        $controller = $gradingmanager->get_controller($definition->method);
        $activeinstances = $controller->get_all_active_instances ($params['since']);
        $details = $controller->get_external_instance_filling_details();
        if ($details == null) {
            $warnings[] = array(
                'item' => 'definition',
                'itemid' => $params['definitionid'],
                'message' => 'Fillings unavailable because get_external_instance_filling_details is not defined',
                'warningcode' => '1'
            );
        }
        $getfilling = null;
        if (method_exists('gradingform_'.$definition->method.'_instance', 'get_'.$definition->method.'_filling')) {
            $getfilling = 'get_'.$definition->method.'_filling';
        } else {
            $warnings[] = array(
                'item' => 'definition',
                'itemid' => $params['definitionid'],
                'message' => 'Fillings unavailable because get_'.$definition->method.'_filling is not defined',
                'warningcode' => '1'
            );
        }
        foreach ($activeinstances as $activeinstance) {
            $instance = array();
            $instance['id'] = $activeinstance->get_id();
            $instance['raterid'] = $activeinstance->get_data('raterid');
            $instance['itemid'] = $activeinstance->get_data('itemid');
            $instance['rawgrade'] = $activeinstance->get_data('rawgrade');
            $instance['status'] = $activeinstance->get_data('status');
            $instance['feedback'] = $activeinstance->get_data('feedback');
            $instance['feedbackformat'] = $activeinstance->get_data('feedbackformat');
            // Format the feedback text field.
            $formattedtext = external_format_text($activeinstance->get_data('feedback'),
                $activeinstance->get_data('feedbackformat'),
                $context->id,
                $area->component,
                'feedback',
                $params['definitionid']);
            $instance['feedback'] = $formattedtext[0];
            $instance['feedbackformat'] = $formattedtext[1];
            $instance['timemodified'] = $activeinstance->get_data('timemodified');

            if ($details != null && $getfilling != null) {
                $fillingdata = $activeinstance->$getfilling();
                $filling = array();
                foreach ($details as $key => $value) {
                    $filling[$key] = self::format_text($fillingdata[$key],
                        $context->id,
                        $area->component,
                        $params['definitionid']);
                }
                $instance[$definition->method] = $filling;
            }
            $instances[] = $instance;
        }
        $result = array(
            'instances' => $instances,
            'warnings' => $warnings
        );
        return $result;
    }
210347
public function new_submission_empty($data) {
        foreach ($this->submissionplugins as $plugin) {
            if ($plugin->is_enabled() && $plugin->is_visible() && $plugin->allow_submissions() &&
                    !$plugin->submission_is_empty($data)) {
                return false;
            }
        }
        return true;
    }
498571
public static function copy_previous_attempt($assignmentid) {

        $params = self::validate_parameters(self::copy_previous_attempt_parameters(),
                                            array('assignmentid' => $assignmentid));

        list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']);

        $notices = array();

        $assignment->copy_previous_attempt($notices);

        $warnings = array();
        foreach ($notices as $notice) {
            $warnings[] = self::generate_warning($assignmentid,
                                                 'couldnotcopyprevioussubmission',
                                                 $notice);
        }

        return $warnings;
    }
572689
static public function addAssignment( $nodeID, $objectID, $selectedNodeIDArray )
    {
        $userClassIDArray = eZUser::contentClassIDs();

        $object = eZContentObject::fetch( $objectID );
        $class = $object->contentClass();

        $nodeAssignmentList = eZNodeAssignment::fetchForObject( $objectID, $object->attribute( 'current_version' ), 0, false );
        $assignedNodes = $object->assignedNodes();

        $parentNodeIDArray = array();

        foreach ( $assignedNodes as $assignedNode )
        {
            $append = false;
            foreach ( $nodeAssignmentList as $nodeAssignment )
            {
                if ( $nodeAssignment['parent_node'] == $assignedNode->attribute( 'parent_node_id' ) )
                {
                    $append = true;
                    break;
                }
            }
            if ( $append )
            {
                $parentNodeIDArray[] = $assignedNode->attribute( 'parent_node_id' );
            }
        }

        $db = eZDB::instance();
        $db->begin();
        $locationAdded = false;
        $node = eZContentObjectTreeNode::fetch( $nodeID );
        foreach ( $selectedNodeIDArray as $selectedNodeID )
        {
            if ( !in_array( $selectedNodeID, $parentNodeIDArray ) )
            {
                $parentNode = eZContentObjectTreeNode::fetch( $selectedNodeID );
                $parentNodeObject = $parentNode->attribute( 'object' );

                $canCreate = ( ( $parentNode->checkAccess( 'create', $class->attribute( 'id' ), $parentNodeObject->attribute( 'contentclass_id' ) ) == 1 ) ||
                                ( $parentNode->canAddLocation() && $node->canRead() ) );

                if ( $canCreate )
                {
                    $insertedNode = $object->addLocation( $selectedNodeID, true );

                    // Now set is as published and fix main_node_id
                    $insertedNode->setAttribute( 'contentobject_is_published', 1 );
                    $insertedNode->setAttribute( 'main_node_id', $node->attribute( 'main_node_id' ) );
                    $insertedNode->setAttribute( 'contentobject_version', $node->attribute( 'contentobject_version' ) );
                    // Make sure the url alias is set updated.
                    $insertedNode->updateSubTreePath();
                    $insertedNode->sync();

                    $locationAdded = true;
                }
            }
        }
        if ( $locationAdded )
        {

            //call appropriate method from search engine
            eZSearch::addNodeAssignment( $nodeID, $objectID, $selectedNodeIDArray );

            // clear user policy cache if this was a user object
            if ( in_array( $object->attribute( 'contentclass_id' ), $userClassIDArray ) )
            {
                eZUser::purgeUserCacheByUserId( $object->attribute( 'id' ) );
            }


        }
        $db->commit();

        eZContentCacheManager::clearContentCacheIfNeeded( $objectID );

        if ( !eZSearch::getEngine() instanceof eZSearchEngine )
        {
            eZContentOperationCollection::registerSearchObject( $objectID );
        }

        return array( 'status' => true );
    }
728091
public function render_assign_submission_plugin_submission(assign_submission_plugin_submission $submissionplugin) {
        $o = '';

        if ($submissionplugin->view == assign_submission_plugin_submission::SUMMARY) {
            $showviewlink = false;
            $summary = $submissionplugin->plugin->view_summary($submissionplugin->submission,
                                                               $showviewlink);

            $classsuffix = $submissionplugin->plugin->get_subtype() .
                           '_' .
                           $submissionplugin->plugin->get_type() .
                           '_' .
                           $submissionplugin->submission->id;

            $o .= $this->output->box_start('boxaligncenter plugincontentsummary summary_' . $classsuffix);

            $link = '';
            if ($showviewlink) {
                $previewstr = get_string('viewsubmission', 'assign');
                $icon = $this->output->pix_icon('t/preview', $previewstr);

                $expandstr = get_string('viewfull', 'assign');
                $options = array('class'=>'expandsummaryicon expand_' . $classsuffix);
                $o .= $this->output->pix_icon('t/switch_plus', $expandstr, null, $options);

                $jsparams = array($submissionplugin->plugin->get_subtype(),
                                  $submissionplugin->plugin->get_type(),
                                  $submissionplugin->submission->id);

                $this->page->requires->js_init_call('M.mod_assign.init_plugin_summary', $jsparams);

                $action = 'viewplugin' . $submissionplugin->plugin->get_subtype();
                $returnparams = http_build_query($submissionplugin->returnparams);
                $link .= '<noscript>';
                $urlparams = array('id' => $submissionplugin->coursemoduleid,
                                   'sid'=>$submissionplugin->submission->id,
                                   'plugin'=>$submissionplugin->plugin->get_type(),
                                   'action'=>$action,
                                   'returnaction'=>$submissionplugin->returnaction,
                                   'returnparams'=>$returnparams);
                $url = new moodle_url('/mod/assign/view.php', $urlparams);
                $link .= $this->output->action_link($url, $icon);
                $link .= '</noscript>';

                $link .= $this->output->spacer(array('width'=>15));
            }

            $o .= $link . $summary;
            $o .= $this->output->box_end();
            if ($showviewlink) {
                $o .= $this->output->box_start('boxaligncenter hidefull full_' . $classsuffix);
                $classes = 'expandsummaryicon contract_' . $classsuffix;
                $o .= $this->output->pix_icon('t/switch_minus',
                                              get_string('viewsummary', 'assign'),
                                              null,
                                              array('class'=>$classes));
                $o .= $submissionplugin->plugin->view($submissionplugin->submission);
                $o .= $this->output->box_end();
            }
        } else if ($submissionplugin->view == assign_submission_plugin_submission::FULL) {
            $o .= $this->output->box_start('boxaligncenter submissionfull');
            $o .= $submissionplugin->plugin->view($submissionplugin->submission);
            $o .= $this->output->box_end();
        }

        return $o;
    }
1321462
protected function add_plugin_submission_elements($submission,
                                                    MoodleQuickForm $mform,
                                                    stdClass $data,
                                                    $userid) {
        foreach ($this->submissionplugins as $plugin) {
            if ($plugin->is_enabled() && $plugin->is_visible() && $plugin->allow_submissions()) {
                $plugin->get_form_elements_for_user($submission, $mform, $data, $userid);
            }
        }
    }
1209407
public static function get_submission_assessments($submissionid) {
        global $USER, $DB, $PAGE;

        $params = self::validate_parameters(self::get_submission_assessments_parameters(), array('submissionid' => $submissionid));
        $warnings = $assessments = array();

        // Get and validate the submission and workshop.
        $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
        list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);

        // Check that we can get the assessments and get them.
        self::check_view_submission_assessments($submission, $workshop);
        $assessmentsrecords = $workshop->get_assessments_of_submission($submission->id);

        $related = array('context' => $context);
        foreach ($assessmentsrecords as $assessment) {
            $assessment = self::prepare_assessment_for_external($assessment, $workshop);
            if (empty($assessment)) {
                continue;
            }
            $exporter = new assessment_exporter($assessment, $related);
            $assessments[] = $exporter->export($PAGE->get_renderer('core'));
        }

        return array(
            'assessments' => $assessments,
            'warnings' => $warnings
        );
    }
1315869
public static function save_submission_parameters() {
        global $CFG;
        $instance = new assign(null, null, null);
        $pluginsubmissionparams = array();

        foreach ($instance->get_submission_plugins() as $plugin) {
            if ($plugin->is_visible()) {
                $pluginparams = $plugin->get_external_parameters();
                if (!empty($pluginparams)) {
                    $pluginsubmissionparams = array_merge($pluginsubmissionparams, $pluginparams);
                }
            }
        }

        return new external_function_parameters(
            array(
                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
                'plugindata' => new external_single_structure(
                    $pluginsubmissionparams
                )
            )
        );
    }
1190256
public function submit_for_grading($data, $notices) {
        global $USER;

        $userid = $USER->id;
        if (!empty($data->userid)) {
            $userid = $data->userid;
        }
        // Need submit permission to submit an assignment.
        if ($userid == $USER->id) {
            require_capability('mod/assign:submit', $this->context);
        } else {
            if (!$this->can_edit_submission($userid, $USER->id)) {
                print_error('nopermission');
            }
        }

        $instance = $this->get_instance();

        if ($instance->teamsubmission) {
            $submission = $this->get_group_submission($userid, 0, true);
        } else {
            $submission = $this->get_user_submission($userid, true);
        }

        if (!$this->submissions_open($userid)) {
            $notices[] = get_string('submissionsclosed', 'assign');
            return false;
        }

        if ($instance->requiresubmissionstatement && empty($data->submissionstatement) && $USER->id == $userid) {
            return false;
        }

        if ($submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
            // Give each submission plugin a chance to process the submission.
            $plugins = $this->get_submission_plugins();
            foreach ($plugins as $plugin) {
                if ($plugin->is_enabled() && $plugin->is_visible()) {
                    $plugin->submit_for_grading($submission);
                }
            }

            $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
            $this->update_submission($submission, $userid, true, $instance->teamsubmission);
            $completion = new completion_info($this->get_course());
            if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
                $this->update_activity_completion_records($instance->teamsubmission,
                                                          $instance->requireallteammemberssubmit,
                                                          $submission,
                                                          $userid,
                                                          COMPLETION_COMPLETE,
                                                          $completion);
            }

            if (!empty($data->submissionstatement) && $USER->id == $userid) {
                \mod_assign\event\statement_accepted::create_from_submission($this, $submission)->trigger();
            }
            $this->notify_graders($submission);
            $this->notify_student_submission_receipt($submission);

            \mod_assign\event\assessable_submitted::create_from_submission($this, $submission, false)->trigger();

            return true;
        }
        $notices[] = get_string('submissionsclosed', 'assign');
        return false;
    }
1064073
public static function delete_feedback_document($assignment, $userid, $attemptnumber) {

        $assignment = self::get_assignment_from_param($assignment);

        if (!$assignment->can_view_submission($userid)) {
            print_error('nopermission');
        }
        if (!$assignment->can_grade()) {
            print_error('nopermission');
        }

        $grade = $assignment->get_user_grade($userid, true, $attemptnumber);

        $contextid = $assignment->get_context()->id;
        $component = 'assignfeedback_editpdf';
        $filearea = self::FINAL_PDF_FILEAREA;
        $itemid = $grade->id;

        $fs = get_file_storage();
        return $fs->delete_area_files($contextid, $component, $filearea, $itemid);
    }
670858
public function save_submission(stdClass $data, & $notices) {
        global $CFG, $USER, $DB;

        $userid = $USER->id;
        if (!empty($data->userid)) {
            $userid = $data->userid;
        }

        $user = clone($USER);
        if ($userid == $USER->id) {
            require_capability('mod/assign:submit', $this->context);
        } else {
            $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
            if (!$this->can_edit_submission($userid, $USER->id)) {
                print_error('nopermission');
            }
        }
        $instance = $this->get_instance();

        if ($instance->teamsubmission) {
            $submission = $this->get_group_submission($userid, 0, true);
        } else {
            $submission = $this->get_user_submission($userid, true);
        }

        if ($this->new_submission_empty($data)) {
            $notices[] = get_string('submissionempty', 'mod_assign');
            return false;
        }

        // Check that no one has modified the submission since we started looking at it.
        if (isset($data->lastmodified) && ($submission->timemodified > $data->lastmodified)) {
            // Another user has submitted something. Notify the current user.
            if ($submission->status !== ASSIGN_SUBMISSION_STATUS_NEW) {
                $notices[] = $instance->teamsubmission ? get_string('submissionmodifiedgroup', 'mod_assign')
                                                       : get_string('submissionmodified', 'mod_assign');
                return false;
            }
        }

        if ($instance->submissiondrafts) {
            $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
        } else {
            $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
        }

        $flags = $this->get_user_flags($userid, false);

        // Get the flags to check if it is locked.
        if ($flags && $flags->locked) {
            print_error('submissionslocked', 'assign');
            return true;
        }

        $pluginerror = false;
        foreach ($this->submissionplugins as $plugin) {
            if ($plugin->is_enabled() && $plugin->is_visible()) {
                if (!$plugin->save($submission, $data)) {
                    $notices[] = $plugin->get_error();
                    $pluginerror = true;
                }
            }
        }

        $allempty = $this->submission_empty($submission);
        if ($pluginerror || $allempty) {
            if ($allempty) {
                $notices[] = get_string('submissionempty', 'mod_assign');
            }
            return false;
        }

        $this->update_submission($submission, $userid, true, $instance->teamsubmission);

        if ($instance->teamsubmission && !$instance->requireallteammemberssubmit) {
            $team = $this->get_submission_group_members($submission->groupid, true);

            foreach ($team as $member) {
                if ($member->id != $userid) {
                    $membersubmission = clone($submission);
                    $this->update_submission($membersubmission, $member->id, true, $instance->teamsubmission);
                }
            }
        }

        // Logging.
        if (isset($data->submissionstatement) && ($userid == $USER->id)) {
            \mod_assign\event\statement_accepted::create_from_submission($this, $submission)->trigger();
        }

        $complete = COMPLETION_INCOMPLETE;
        if ($submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
            $complete = COMPLETION_COMPLETE;
        }
        $completion = new completion_info($this->get_course());
        if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
            $completion->update_state($this->get_course_module(), $complete, $userid);
        }

        if (!$instance->submissiondrafts) {
            $this->notify_student_submission_receipt($submission);
            $this->notify_graders($submission);
            \mod_assign\event\assessable_submitted::create_from_submission($this, $submission, true)->trigger();
        }
        return true;
    }