MDL-47197 core: Private files handler
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 10 Sep 2014 08:10:02 +0000 (16:10 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Tue, 7 Oct 2014 02:01:19 +0000 (10:01 +0800)
This issue is a part of the MDL-47194 Task.
This issue is a part of the MDL-39707 Epic.

lang/en/moodle.php
lib/classes/message/inbound/private_files_handler.php [new file with mode: 0644]
lib/db/messageinbound_handlers.php [new file with mode: 0644]
user/files.php
user/files_form.php

index 3bb13f0..61a0f35 100644 (file)
@@ -698,6 +698,8 @@ $string['emailresetconfirmationsubject'] = '{$a}: Password reset request';
 $string['emailresetconfirmsent'] = 'An email has been sent to your address at <b>{$a}</b>.
 <br />It contains easy instructions to confirm and complete this password change.
 If you continue to have difficulty, contact the site administrator.';
+$string['emailtoprivatefiles'] = 'You can also e-mail files as attachments straight to your private files space. Simply attach your files to an e-mail and send it to {$a}';
+$string['emailtoprivatefilesdenied'] = 'Your administrator has disabled the option to upload your own private files.';
 $string['emptydragdropregion'] = 'empty region';
 $string['enable'] = 'Enable';
 $string['encryptedcode'] = 'Encrypted code';
@@ -1445,6 +1447,8 @@ $string['previous'] = 'Previous';
 $string['previouslyselectedusers'] = 'Previously selected users not matching \'{$a}\'';
 $string['previoussection'] = 'Previous section';
 $string['primaryadminsetup'] = 'Setup administrator account';
+$string['private_files_handler'] = 'Store attachments to an e-mail in the user\'s private files storage space.';
+$string['private_files_handler_name'] = 'Email to Private files';
 $string['profile'] = 'Profile';
 $string['profilenotshown'] = 'This profile description will not be shown until this person is enrolled in at least one course.';
 $string['publicprofile'] = 'Public profile';
diff --git a/lib/classes/message/inbound/private_files_handler.php b/lib/classes/message/inbound/private_files_handler.php
new file mode 100644 (file)
index 0000000..4e95a76
--- /dev/null
@@ -0,0 +1,137 @@
+<?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/>.
+
+/**
+ * A Handler to store attachments sent in e-mails as private files.
+ *
+ * @package    core_message
+ * @copyright  2014 Andrew Nicols
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\message\inbound;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * A Handler to store attachments sent in e-mails as private files.
+ *
+ * @package    core
+ * @copyright  2014 Andrew Nicols
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class private_files_handler extends handler {
+
+    /**
+     * Return a description for the current handler.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return get_string('private_files_handler', 'moodle');
+    }
+
+    /**
+     * Return a short name for the current handler.
+     * This appears in the admin pages as a human-readable name.
+     *
+     * @return string
+     */
+    public function get_name() {
+        return get_string('private_files_handler_name', 'moodle');
+    }
+
+    /**
+     * Process a message received and validated by the Inbound Message processor.
+     *
+     * @param $messagedata The Inbound Message record
+     * @param $messagedata The message data packet
+     * @return bool Whether the message was successfully processed.
+     */
+    public function process_message(\stdClass $record, \stdClass $data) {
+        global $USER, $DB, $CFG;
+
+        $context = \context_user::instance($USER->id);
+
+        if (!has_capability('moodle/user:manageownfiles', $context)) {
+            throw new \message\inbound\processing_failed_exception('emailtoprivatefilesdenied', 'moodle', $data);
+        }
+
+        // Initial setup.
+        $component  = 'user';
+        $filearea   = 'private';
+        $itemid     = 0;
+        $license    = $CFG->sitedefaultlicense;
+        $author     = fullname($USER);
+
+        // Determine the quota space for this user.
+        $maxbytes = $CFG->userquota;
+        if (has_capability('moodle/user:ignoreuserquota', $context)) {
+            $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS;
+        }
+
+        // Keep track of files which were uploaded, and which were skipped.
+        $skippedfiles   = array();
+        $uploadedfiles  = array();
+        $failedfiles    = array();
+
+        $fs = get_file_storage();
+        foreach ($data->attachments as $attachmenttype => $attachments) {
+            foreach ($attachments as $attachment) {
+                mtrace("--- Processing attachment '{$attachment->filename}'");
+
+                if (file_is_draft_area_limit_reached($itemid, $maxbytes, $attachment->filesize)) {
+                    // The user quota will be exceeded if this file is included.
+                    $skippedfiles[] = $attachment;
+                    mtrace("---- Skipping attacment. User will be over quota.");
+                    continue;
+                }
+
+                // Create a new record for this file.
+                $record = new \stdClass();
+                $record->filearea   = $filearea;
+                $record->component  = $component;
+                $record->filepath   = '/';
+                $record->itemid     = $itemid;
+                $record->license    = $license;
+                $record->author     = $author;
+                $record->contextid  = $context->id;
+                $record->userid     = $USER->id;
+
+                $record->filename = $fs->get_unused_filename($context->id, $record->component, $record->filearea,
+                        $record->itemid, $record->filepath, $attachment->filename);
+
+                mtrace("--> Attaching {$record->filename} to " .
+                       "/{$record->contextid}/{$record->component}/{$record->filearea}/" .
+                       "{$record->itemid}{$record->filepath}{$record->filename}");
+
+                if ($fs->create_file_from_string($record, $attachment->content)) {
+                    // File created successfully.
+                    mtrace("---- File uploaded successfully as {$record->filename}.");
+                    $uploadedfiles[] = $attachment;
+                } else {
+                    mtrace("---- Skipping attacment. Unknown failure during creation.");
+                    $failedfiles[] = $attachment;
+                }
+            }
+        }
+
+        // TODO send the user a confirmation e-mail.
+        // Note, some files may have failed because the user has been pushed over quota. This does not constitute a failure.
+
+        return true;
+    }
+}
diff --git a/lib/db/messageinbound_handlers.php b/lib/db/messageinbound_handlers.php
new file mode 100644 (file)
index 0000000..05e1ae8
--- /dev/null
@@ -0,0 +1,32 @@
+<?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/>.
+
+/**
+ * Inbound Message Handlers for core.
+ *
+ * @package    core_message
+ * @copyright  2014 Andrew NIcols
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$handlers = array(
+    array(
+        'classname' => '\core\message\inbound\private_files_handler',
+        'defaultexpiration' => null,
+    ),
+);
index f1f03b7..00d1eba 100644 (file)
@@ -64,6 +64,12 @@ $options = array('subdirs' => 1, 'maxbytes' => $maxbytes, 'maxfiles' => -1, 'acc
         'areamaxbytes' => $maxareabytes);
 file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0);
 
+// Attempt to generate an inbound message address to support e-mail to private files.
+$generator = new \core\message\inbound\address_manager();
+$generator->set_handler('\core\message\inbound\private_files_handler');
+$generator->set_data(-1);
+$data->emaillink = $generator->generate($USER->id);
+
 $mform = new user_files_form(null, array('data' => $data, 'options' => $options));
 
 if ($mform->is_cancelled()) {
@@ -75,6 +81,8 @@ if ($mform->is_cancelled()) {
 
 echo $OUTPUT->header();
 echo $OUTPUT->box_start('generalbox');
+
+
 $mform->display();
 echo $OUTPUT->box_end();
 echo $OUTPUT->footer();
index 9c0947e..709b3c9 100644 (file)
@@ -45,6 +45,11 @@ class user_files_form extends moodleform {
 
         $mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options);
         $mform->addElement('hidden', 'returnurl', $data->returnurl);
+        if (isset($data->emaillink)) {
+            $emaillink = html_writer::link(new moodle_url('mailto:' . $data->emaillink), $data->emaillink);
+            $mform->addElement('static', 'emailaddress', '',
+                get_string('emailtoprivatefiles', 'moodle', $emaillink));
+        }
         $mform->setType('returnurl', PARAM_LOCALURL);
 
         $this->add_action_buttons(true, get_string('savechanges'));