assign_submission_edulegit::get_editor_fields()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * This file contains the definition for the library class for edulegit submission plugin.
19
 *
20
 *
21
 * @package   assignsubmission_edulegit
22
 * @author    Alex Crosby <[email protected]>
23
 * @copyright @2024 EduLegit.com
24
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
27
use assignsubmission_edulegit\edulegit_submission_entity;
28
29
defined('MOODLE_INTERNAL') || die();
30
31
require_once($CFG->dirroot . '/mod/assign/submission/edulegit/lib.php');
32
33
/**
34
 * Library class for edulegit submission plugin extending submission plugin base class.
35
 *
36
 * @package   assignsubmission_edulegit
37
 * @author    Alex Crosby <[email protected]>
38
 * @copyright @2024 EduLegit.com
39
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class assign_submission_edulegit extends assign_submission_plugin {
0 ignored issues
show
Bug introduced by
The type assign_submission_plugin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
42
    /**
43
     * Get the name of the edulegit submission plugin.
44
     *
45
     * @return string
46
     */
47
    public function get_name(): string {
48
        return $this->translate('edulegit');
49
    }
50
51
    /**
52
     * Get the default setting for EduLegit submission plugin
53
     *
54
     * @param MoodleQuickForm $mform The form to add elements to
55
     * @return void
56
     */
57
    public function get_settings(MoodleQuickForm $mform) {
0 ignored issues
show
Bug introduced by
The type MoodleQuickForm was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
58
59
        $config = $this->get_edulegit()->get_config();
60
61
        $name = $this->translate('enable_attention_label');
62
        $mform->addElement('advcheckbox', 'assignsubmission_edulegit_enable_attention',
63
                $name, $this->translate('enable_attention'), null, [0, 1]);
64
65
        if ($this->assignment->has_instance()) {
66
            $mform->setDefault('assignsubmission_edulegit_enable_attention',
67
                    $config->get_plugin_or_global_config('enable_attention'));
68
        }
69
        $mform->addHelpButton('assignsubmission_edulegit_enable_attention',
70
                'enable_attention',
71
                'assignsubmission_edulegit');
72
        $mform->hideIf('assignsubmission_edulegit_enable_attention', 'assignsubmission_edulegit_enabled', 'notchecked');
73
74
        $name = $this->translate('enable_camera_label');
75
        $mform->addElement('advcheckbox', 'assignsubmission_edulegit_enable_camera',
76
                $name, $this->translate('enable_camera'), null, [0, 1]);
77
        if ($this->assignment->has_instance()) {
78
            $mform->setDefault('assignsubmission_edulegit_enable_camera',
79
                    $config->get_plugin_or_global_config('enable_camera'));
80
        }
81
        $mform->addHelpButton('assignsubmission_edulegit_enable_camera',
82
                'enable_camera',
83
                'assignsubmission_edulegit');
84
        $mform->hideIf('assignsubmission_edulegit_enable_camera', 'assignsubmission_edulegit_enabled', 'notchecked');
85
86
        $name = $this->translate('enable_screen_label');
87
        $mform->addElement('advcheckbox', 'assignsubmission_edulegit_enable_screen',
88
                $name, $this->translate('enable_screen'), null, [0, 1]);
89
        if ($this->assignment->has_instance()) {
90
            $mform->setDefault('assignsubmission_edulegit_enable_screen',
91
                    $config->get_plugin_or_global_config('enable_screen'));
92
        }
93
        $mform->addHelpButton('assignsubmission_edulegit_enable_screen',
94
                'enable_screen',
95
                'assignsubmission_edulegit');
96
        $mform->hideIf('assignsubmission_edulegit_enable_screen', 'assignsubmission_edulegit_enabled', 'notchecked');
97
98
        $name = $this->translate('enable_plagiarism_label');
99
        $mform->addElement('advcheckbox', 'assignsubmission_edulegit_enable_plagiarism',
100
                $name, $this->translate('enable_plagiarism'), null, [0, 1]);
101
        if ($this->assignment->has_instance()) {
102
            $mform->setDefault('assignsubmission_edulegit_enable_plagiarism',
103
                    $config->get_plugin_or_global_config('enable_plagiarism'));
104
        }
105
        $mform->addHelpButton('assignsubmission_edulegit_enable_plagiarism',
106
                'enable_plagiarism',
107
                'assignsubmission_edulegit');
108
        $mform->hideIf('assignsubmission_edulegit_enable_plagiarism', 'assignsubmission_edulegit_enabled', 'notchecked');
109
110
        $name = $this->translate('enable_ai_label');
111
        $mform->addElement('advcheckbox', 'assignsubmission_edulegit_enable_ai',
112
                $name, $this->translate('enable_ai'), null, [0, 1]);
113
        if ($this->assignment->has_instance()) {
114
            $mform->setDefault('assignsubmission_edulegit_enable_ai',
115
                    $config->get_plugin_or_global_config('enable_ai'));
116
        }
117
        $mform->addHelpButton('assignsubmission_edulegit_enable_ai',
118
                'enable_ai',
119
                'assignsubmission_edulegit');
120
        $mform->hideIf('assignsubmission_edulegit_enable_ai', 'assignsubmission_edulegit_enabled', 'notchecked');
121
122
    }
123
124
    /**
125
     * Save the settings for EduLegit submission plugin
126
     *
127
     * @param stdClass $formdata
128
     * @return bool
129
     */
130
    public function save_settings(stdClass $formdata) {
131
132
        $this->set_config('enable_attention', $formdata->assignsubmission_edulegit_enable_attention);
133
        $this->set_config('enable_camera', $formdata->assignsubmission_edulegit_enable_camera);
134
        $this->set_config('enable_screen', $formdata->assignsubmission_edulegit_enable_screen);
135
        $this->set_config('enable_plagiarism', $formdata->assignsubmission_edulegit_enable_plagiarism);
136
        $this->set_config('enable_ai', $formdata->assignsubmission_edulegit_enable_ai);
137
138
        return true;
139
140
    }
141
142
    /**
143
     * Add form elements for settings.
144
     *
145
     * @param mixed $submissionorgrade can be null
146
     * @param MoodleQuickForm $mform
147
     * @param stdClass $data
148
     * @return bool if elements were added to the form
149
     */
150
    public function get_form_elements($submissionorgrade, MoodleQuickForm $mform, stdClass $data) {
151
        global $USER;
152
        $submissionmanager = $this->get_edulegit()->get_manager();
153
        $edulegitsubmission = $submissionmanager->init($submissionorgrade, ['user' => $USER]);
154
        if (!$edulegitsubmission) {
155
            return false;
156
        }
157
158
        $redirecturl = $edulegitsubmission->get_user_login_url();
159
        if (!$redirecturl || $edulegitsubmission->error) {
160
            $error = $this->translate('open_edulegit_error') . ' ' . $edulegitsubmission->error ?:
161
                    $this->translate('default_open_edulegit_error');
162
163
            global $OUTPUT;
164
            $html = $OUTPUT->notification($error, 'error');
165
            $mform->addElement('html', $html, $this->get_name(), null, null);
166
167
            return false;
168
        }
169
170
        $mform->addElement('hidden', 'edulegit_submission_id', $edulegitsubmission->id);
171
        $mform->setType('edulegit_submission_id', PARAM_INT);
0 ignored issues
show
Bug introduced by
The constant PARAM_INT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
172
173
        $label = $this->translate('open_edulegit_label');
174
175
        $button = html_writer::link($redirecturl, $this->translate('open_edulegit'), [
0 ignored issues
show
Bug introduced by
The type html_writer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
176
                'type' => 'button',
177
                'class' => 'btn btn-primary',
178
                'target' => '_blank',
179
                'title' => $this->translate('open_edulegit_help'),
180
        ]);
181
182
        $html = '<div class="mb-3 row">
183
            <div class="col-md-3 d-flex col-form-label pb-0 pr-md-0">' . $label . '</div>
184
            <div class="col-md-9 d-flex flex-wrap align-items-start">' . $button . '</div>
185
        </div>';
186
187
        $mform->addElement('html', $html, $this->get_name(), null, null);
188
189
        return true;
190
    }
191
192
    /**
193
     * Save data to the database and trigger plagiarism plugin,
194
     * if enabled, to scan the uploaded content via events trigger.
195
     *
196
     * @param stdClass $submissionorgrade
197
     * @param stdClass $data
198
     * @return bool
199
     */
200
    public function save(stdClass $submissionorgrade, stdClass $data): bool {
201
        global $DB, $USER;
202
203
        $edulegitsubmission = $this->get_edulegit()->get_manager()->sync($submissionorgrade->id);
204
205
        if (!$edulegitsubmission) {
206
            $edulegitsubmission = $this->get_edulegit_submission($submissionorgrade->id);
207
        }
208
209
        $params = [
210
                'context' => context_module::instance($this->assignment->get_course_module()->id),
0 ignored issues
show
Bug introduced by
The type context_module was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
211
                'courseid' => $this->assignment->get_course()->id,
212
                'objectid' => $submissionorgrade->id,
213
                'other' => [
214
                        'content' => trim($edulegitsubmission->content),
0 ignored issues
show
Bug introduced by
It seems like $edulegitsubmission->content can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

214
                        'content' => trim(/** @scrutinizer ignore-type */ $edulegitsubmission->content),
Loading history...
215
                        'pathnamehashes' => [],
216
                ],
217
        ];
218
219
        if (!empty($submissionorgrade->userid) && ($submissionorgrade->userid != $USER->id)) {
220
            $params['relateduserid'] = $submissionorgrade->userid;
221
        }
222
        if ($this->assignment->is_blind_marking()) {
223
            $params['anonymous'] = 1;
224
        }
225
226
        // Trigger assessable_uploaded event.
227
        $event = \assignsubmission_edulegit\event\assessable_uploaded::create($params);
228
        $event->trigger();
229
230
        // Get the group name as other fields are not transcribed in the logs and this information is important.
231
        $groupname = null;
232
        $groupid = 0;
233
        if (empty($submissionorgrade->userid) && !empty($submissionorgrade->groupid)) {
234
            $groupname = $DB->get_field('groups', 'name', ['id' => $submissionorgrade->groupid], MUST_EXIST);
0 ignored issues
show
Bug introduced by
The constant MUST_EXIST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
235
            $groupid = $submissionorgrade->groupid;
236
        } else {
237
            $params['relateduserid'] = $submissionorgrade->userid;
238
        }
239
240
        // Adapt $params to be used for the submisssion_xxxxx events.
241
        unset($params['objectid']);
242
        unset($params['other']);
243
        $params['other'] = [
244
                'submissionid' => $submissionorgrade->id,
245
                'submissionattempt' => $submissionorgrade->attemptnumber,
246
                'submissionstatus' => $submissionorgrade->status,
247
                'groupid' => $groupid,
248
                'groupname' => $groupname,
249
        ];
250
251
        // Trigger submission created event.
252
        $params['objectid'] = $edulegitsubmission->id;
253
        $event = \assignsubmission_edulegit\event\submission_created::create($params);
254
        $event->set_assign($this->assignment);
255
        $event->trigger();
256
257
        return $edulegitsubmission->id && !$edulegitsubmission->error;
0 ignored issues
show
Bug Best Practice introduced by
The expression $edulegitsubmission->id of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
258
    }
259
260
    /**
261
     * Remove a submission.
262
     *
263
     * @param stdClass $submission The submission.
264
     * @return boolean
265
     */
266
    public function remove(stdClass $submission): bool {
267
        return $this->get_edulegit()->get_repository()->delete_submission($submission ? $submission->id : 0);
0 ignored issues
show
introduced by
$submission is of type stdClass, thus it always evaluated to true.
Loading history...
268
    }
269
270
    /**
271
     * Display EduLegit result in the submission status table.
272
     *
273
     * @param stdClass $submissionorgrade
274
     * @param bool $showviewlink - If the summary has been truncated set this to true
275
     * @return string
276
     */
277
    public function view_summary(stdClass $submissionorgrade, &$showviewlink): string {
278
        $edulegitsubmission = $this->get_edulegit_submission($submissionorgrade->id);
279
        if ($edulegitsubmission && $edulegitsubmission->url) {
280
281
            global $PAGE;
282
            /** @var core_renderer $output */
283
            $output = $PAGE->get_renderer('core');
284
285
            $menubuilder = new \assignsubmission_edulegit\edulegit_submission_menu_builder();
286
            $menu = $menubuilder->build($edulegitsubmission);
287
288
            $html = $output->render($menu);
289
        }
290
        return $html;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $html does not seem to be defined for all execution paths leading up to this point.
Loading history...
291
    }
292
293
    /**
294
     * Produce a list of files suitable for export that represent this submission.
295
     *
296
     * @param stdClass $submissionorgrade - For this is the submission data
297
     * @param stdClass $user - This is the user record for this submission
298
     * @return array - return an array of files indexed by filename
299
     */
300
    public function get_files(stdClass $submissionorgrade, stdClass $user): array {
301
        $files = [];
302
303
        $edulegitsubmission = $this->get_edulegit_submission($submissionorgrade->id);
304
        if ($edulegitsubmission) {
305
            $filename = $this->translate('default_filename');
306
            $files[$filename] = [$edulegitsubmission->content];
307
        }
308
309
        return $files;
310
    }
311
312
    /**
313
     * The assignment has been deleted - remove the plugin specific data.
314
     *
315
     * @return bool
316
     */
317
    public function delete_instance(): bool {
318
        $assignmentid = $this->assignment->get_instance()->id;
319
        return $this->get_edulegit()->get_repository()->delete_assignment($assignmentid);
320
    }
321
322
    /**
323
     * Is this assignment plugin empty?
324
     *
325
     * @param stdClass $submissionorgrade
326
     * @return bool
327
     */
328
    public function is_empty(stdClass $submissionorgrade): bool {
329
        $edulegitsubmission = $this->get_edulegit_submission($submissionorgrade->id);
330
331
        return !$edulegitsubmission || $edulegitsubmission->is_empty();
332
    }
333
334
    /**
335
     * Determine if a submission is empty.
336
     *
337
     * This is distinct from is_empty in that it is intended to be used to
338
     * determine if a submission made before saving is empty.
339
     *
340
     * @param stdClass $data The submission data
341
     * @return bool
342
     */
343
    public function submission_is_empty(stdClass $data): bool {
344
        return empty($data->edulegit_submission_id);
345
    }
346
347
    /**
348
     * Get file areas returns a list of areas this plugin stores files.
349
     *
350
     * @return array - An array of fileareas (keys) and descriptions (values)
351
     */
352
    public function get_file_areas(): array {
353
        // For now, this plugin doesn't store any file.
354
        return [];
355
    }
356
357
    /**
358
     * Copy the student's submission from a previous submission.
359
     * Used when a student opts to base their resubmission on the last submission.
360
     *
361
     * @param stdClass $oldsubmission
362
     * @param stdClass $submission
363
     * @return bool
364
     */
365
    public function copy_submission(stdClass $oldsubmission, stdClass $submission): bool {
366
        // Copy the assignsubmission_edulegit record.
367
        $edulegitsubmission = $this->get_edulegit_submission($oldsubmission->id);
368
        if ($edulegitsubmission) {
369
370
            $newsubmission = new edulegit_submission_entity();
371
            $newsubmission->submission = $submission->id;
372
            $newsubmission->assignment = $edulegitsubmission->assignment;
373
            $newsubmission->content = $edulegitsubmission->content;
374
            $newsubmission->status = 0;
375
            $newsubmission->error = '';
376
377
            return $this->get_edulegit()->get_repository()->insert_submission($newsubmission);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_eduleg...mission($newsubmission) could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
378
        }
379
        return true;
380
    }
381
382
    /**
383
     * Return a list of the text fields that can be imported/exported by this plugin.
384
     *
385
     * @return array An array of field names and descriptions. (name=>description, ...)
386
     */
387
    public function get_editor_fields(): array {
388
        return ['edulegit' => $this->translate('pluginname')];
389
    }
390
391
    /**
392
     * Get the saved text content from the editor.
393
     *
394
     * @param string $name
395
     * @param int $submissionorgradeid
396
     * @return string
397
     */
398
    public function get_editor_text($name, $submissionorgradeid): string {
399
        if ($name == 'edulegit') {
400
            $edulegitsubmission = $this->get_edulegit_submission($submissionorgradeid);
401
            if ($edulegitsubmission) {
402
                return $edulegitsubmission->content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $edulegitsubmission->content could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
403
            }
404
        }
405
406
        return '';
407
    }
408
409
    /**
410
     * Get the content format for the editor.
411
     *
412
     * @param string $name
413
     * @param int $submissionid
414
     * @return int
415
     */
416
    public function get_editor_format($name, $submissionid): int {
417
        if ($name == 'edulegit') {
418
            $edulegitsubmission = $this->get_edulegit_submission($submissionid);
419
            if ($edulegitsubmission) {
420
                return FORMAT_HTML;
0 ignored issues
show
Bug introduced by
The constant FORMAT_HTML was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
421
            }
422
        }
423
424
        return 0;
425
    }
426
427
    /**
428
     * Get submission information from the database.
429
     *
430
     * @param int $submissionid
431
     * @return mixed
432
     */
433
    private function get_edulegit_submission(int $submissionid): ?edulegit_submission_entity {
434
        return $this->get_edulegit()->get_repository()->get_submission($submissionid);
435
    }
436
437
    /**
438
     * Edulegit core instance.
439
     *
440
     * @var \assignsubmission_edulegit\edulegit_core|null
441
     */
442
    private ?\assignsubmission_edulegit\edulegit_core $edulegit = null;
443
444
    /**
445
     * Lazy load the edulegit core instance.
446
     *
447
     * @return \assignsubmission_edulegit\edulegit_core
448
     */
449
    public function get_edulegit(): \assignsubmission_edulegit\edulegit_core {
450
        if ($this->edulegit === null) {
451
            $this->edulegit = new \assignsubmission_edulegit\edulegit_core($this->get_config());
452
        }
453
        return $this->edulegit;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->edulegit could return the type null which is incompatible with the type-hinted return assignsubmission_edulegit\edulegit_core. Consider adding an additional type-check to rule them out.
Loading history...
454
    }
455
456
    /**
457
     * Returns a localized string.
458
     *
459
     * @param string $identifier The key identifier for the localized string
460
     * @return lang_string|string
0 ignored issues
show
Bug introduced by
The type lang_string was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
461
     */
462
    private function translate(string $identifier) {
463
        return get_string($identifier, 'assignsubmission_edulegit');
0 ignored issues
show
Bug introduced by
The function get_string was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

463
        return /** @scrutinizer ignore-call */ get_string($identifier, 'assignsubmission_edulegit');
Loading history...
464
    }
465
466
}
467