From 73feff40e448b93705725615401d42ee04086b03 Mon Sep 17 00:00:00 2001 From: Alan Thompson Date: Mon, 27 Jan 2014 11:34:50 +0000 Subject: [PATCH] OUBlog: Add email notification functionality to delete post #8764 --- deletepost.php | 217 ++++++++++++++++++--- deletepost_form.php | 91 +++++++++ internaldoc/testcase.delete.txt | 321 ++++++++++++++++++++++++++++++++ lang/en/oublog.php | 51 ++++- locallib.php | 22 +-- module.js | 60 ++++++ renderer.php | 79 +++++--- styles.css | 7 + version.php | 2 +- 9 files changed, 773 insertions(+), 77 deletions(-) create mode 100644 deletepost_form.php create mode 100644 internaldoc/testcase.delete.txt diff --git a/deletepost.php b/deletepost.php index 5275384..14522f9 100644 --- a/deletepost.php +++ b/deletepost.php @@ -20,23 +20,29 @@ * @package oublog */ require_once("../../config.php"); -require_once("locallib.php"); +require_once($CFG->dirroot . '/mod/oublog/locallib.php'); require_once($CFG->libdir . '/completionlib.php'); -$blog = required_param('blog', PARAM_INT); // Blog ID -$postid = required_param('post', PARAM_INT); // Post ID for editing -$confirm = optional_param('confirm', 0, PARAM_INT); // Confirm that it is ok to delete post +$blog = required_param('blog', PARAM_INT); // Blog ID. +$postid = required_param('post', PARAM_INT); // Post ID for editing. +$confirm = optional_param('confirm', 0, PARAM_INT);// Confirm that it is ok to delete post. +$delete = optional_param('delete', 0, PARAM_INT); +$email = optional_param('email', 0, PARAM_INT); // Email author. if (!$oublog = $DB->get_record("oublog", array("id"=>$blog))) { print_error('invalidblog', 'oublog'); } +if (!$post = oublog_get_post($postid, false)) { + print_error('invalidpost', 'oublog'); +} if (!$cm = get_coursemodule_from_instance('oublog', $blog)) { print_error('invalidcoursemodule'); } if (!$course = $DB->get_record("course", array("id"=>$oublog->course))) { print_error('coursemisconf'); } -$url = new moodle_url('/mod/oublog/deletepost.php', array('blog'=>$blog, 'post'=>$postid, 'confirm'=>$confirm)); +$url = new moodle_url('/mod/oublog/deletepost.php', + array('blog' => $blog, 'post' => $postid, 'confirm' => $confirm)); $PAGE->set_url($url); // Check security. @@ -54,54 +60,205 @@ require_capability('mod/oublog:manageposts', $context); } +$oublogoutput = $PAGE->get_renderer('mod_oublog'); + if ($oublog->global) { $blogtype = 'personal'; $oubloguser = $USER; - $viewurl = new moodle_url('/mod/oublog/view.php', array('user'=>$USER->id)); + $viewurl = new moodle_url('/mod/oublog/view.php', array('user' => $USER->id)); + // Print the header. + $PAGE->navbar->add(fullname($oubloguser), new moodle_url('/user/view.php', + array('id' => $oubloguser->id))); + $PAGE->navbar->add(format_string($oublog->name)); } else { $blogtype = 'course'; - $viewurl = new moodle_url('/mod/oublog/view.php', array('id'=>$cm->id)); + $viewurl = new moodle_url('/mod/oublog/view.php', array('id' => $cm->id)); } -if (!empty($postid) && !empty($confirm)) { - $expost=$DB->get_record('oublog_posts', array('id'=>$postid)); +if ($email) { + // Then open and process the form. + require_once($CFG->dirroot . '/mod/oublog/deletepost_form.php'); + $customdata = (object)array('blog' => $blog, 'post' => $postid, + 'delete' => $delete, 'email' => $email, 'url' => $viewurl); + $mform = new mod_oublog_deletepost_form('deletepost.php', $customdata); + if ($mform->is_cancelled()) { + // Form is cancelled, redirect back to the blog. + redirect($viewurl); + } else if ($submitted = $mform->get_data()) { + // Mark the post as deleted. + oublog_do_delete($course, $cm, $oublog, $post); + // We need these for the call to render post. + $canaudit = $canmanageposts = false; + + // Store copy of the post for the author. + // If subject is set in this post, use it. + if (!isset($post->title) || empty($post->title)) { + $post->title = get_string('deletedblogpost', 'oublog'); + } + $messagepost = $oublogoutput->render_post($cm, $oublog, $post, $viewurl, $blogtype, + $canmanageposts, $canaudit, false, false, false, true); + + // Set up the email message detail. + $messagetext = $submitted->message['text']; + $copyself = (isset($submitted->copyself)) ? true : false; + $includepost = (isset($submitted->includepost)) ? true : false; + $from = $SITE->fullname; + + // Always send HTML version. + $user = (object)array( + 'email' => $post->email, + 'mailformat' => 1, + 'id' => $post->userid + ); + + $messagehtml = text_to_html($messagetext); + // Include the copy of the post in the email to the author. + if ($includepost) { + $messagehtml .= $messagepost; + } + // Send an email to the author of the post. + if (!email_to_user($user, $from, $post->title, '', $messagehtml)) { + print_error(get_string('emailerror', 'oublog')); + } + // Prepare for copies. + $emails = $selfmail = array(); + if ($copyself) { + $selfmail[] = $USER->email; + } + // Addition of 'Email address of other recipients'. + if (!empty($submitted->emailadd)) { + $emails = preg_split('~[; ]+~', $submitted->emailadd); + } + $emails = array_merge($emails, $selfmail); + + // If there are any recipients listed send them a copy. + if (!empty($emails[0])) { + $subject = strtoupper(get_string('copy')) . ' - '. $post->title; + foreach ($emails as $email) { + $fakeuser = (object)array( + 'email' => $email, + 'mailformat' => 1, + 'id' => 0 + ); + if (!email_to_user($fakeuser, $from, $subject, '', $messagehtml)) { + print_error(get_string('emailerror', 'oublog')); + } + } + } + redirect($viewurl); + } else if (($delete && $email) ) { + // If subject is set in this post, use it. + if (!isset($post->title) || empty($post->title)) { + $post->title = get_string('deletedblogpost', 'oublog'); + } + $displayname = oublog_get_displayname($oublog, true); + // Prepare the object for the emailcontenthtml get_string. + $emailmessage = new stdClass; + $emailmessage->subject = $post->title; + $emailmessage->blog = $oublog->name; + $emailmessage->activityname = $displayname; + $emailmessage->firstname = $USER->firstname; + $emailmessage->lastname = $USER->lastname; + $emailmessage->course = $COURSE->fullname; + $emailmessage->deleteurl = $CFG->wwwroot . '/mod/oublog/viewpost.php?&post=' . $post->id; + $formdata = new stdClass; + $messagetext = get_string('emailcontenthtml', 'oublog', $emailmessage); + $formdata->message['text'] = $messagetext; + // Display the form. + echo $OUTPUT->header(); + $mform->set_data($formdata); + $mform->display(); + } +} else { + if (!$confirm) { + $PAGE->set_title(format_string($oublog->name)); + $PAGE->set_heading(format_string($course->fullname)); + echo $OUTPUT->header(); + $confirmdeletestring = get_string('confirmdeletepost', 'oublog'); + $confirmstring = get_string('deleteemailpostdescription', 'oublog'); + + $deletebutton = new single_button(new moodle_url('/mod/oublog/deletepost.php', + array('blog' => $blog, 'post' => $postid, 'delete' => '1', + 'confirm' => '1')), get_string('delete'), 'post'); + $cancelbutton = new single_button($viewurl, get_string('cancel'), 'get'); + + if ($USER->id == $post->userid) { + print $OUTPUT->confirm($confirmdeletestring, $deletebutton, $cancelbutton); + } else { + // Delete - Delete and email || Cancel. + $deleteemailbutton = new single_button(new moodle_url('/mod/oublog/deletepost.php', + array('blog' => $blog, 'post' => $postid, 'email' => '1', 'delete' => '1')), + get_string('deleteemailpostbutton', 'oublog'), 'post'); + print oublog_three_button($confirmstring, + $deletebutton, + $deleteemailbutton, + $cancelbutton); + } + } else { + // Mark the post as deleted. + oublog_do_delete($course, $cm, $oublog, $post); + redirect($viewurl); + } +} + +echo $OUTPUT->footer(); + +function oublog_do_delete($course, $cm, $oublog, $post) { + global $DB, $USER; $updatepost = (object)array( - 'id' => $postid, - 'deletedby' => $USER->id, - 'timedeleted' => time() + 'id' => $post->id, + 'deletedby' => $USER->id, + 'timedeleted' => time() ); + $transaction = $DB->start_delegated_transaction(); $DB->update_record('oublog_posts', $updatepost); - if (!oublog_update_item_tags($expost->oubloginstancesid, $expost->id, array(), $expost->visibility)) { + if (!oublog_update_item_tags($post->oubloginstancesid, $post->id, + array(), $post->visibility)) { print_error('tagupdatefailed', 'oublog'); } if (oublog_search_installed()) { - $doc=oublog_get_search_document($updatepost, $cm); + $doc = oublog_get_search_document($updatepost, $cm); $doc->delete(); } // Inform completion system, if available. $completion = new completion_info($course); if ($completion->is_enabled($cm) && ($oublog->completionposts)) { - $completion->update_state($cm, COMPLETION_INCOMPLETE, $postauthor); + $completion->update_state($cm, COMPLETION_INCOMPLETE, $post->userid); } - redirect($viewurl); - exit; + $transaction->allow_commit(); } -// Get Strings. -$stroublogs = get_string('modulenameplural', 'oublog'); -$stroublog = get_string('modulename', 'oublog'); +/** + * Print a message along with three buttons buttoneone/buttontwo/Cancel + * + * If a string or moodle_url is given instead of a single_button, method defaults to post. + * + * @param string $message The question to ask the user. + * @param single_button $buttonone The single_button component representing the buttontwo response. + * @param single_button $buttontwo The single_button component representing the buttontwo response. + * @param single_button $cancel The single_button component representing the Cancel response. + * @return string HTML fragment + */ +function oublog_three_button($message, $buttonone, $buttontwo, $cancel) { + global $OUTPUT; + if (!($buttonone instanceof single_button)) { + throw new coding_exception('The buttonone param must be an instance of a single_button.'); + } + + if (!($buttontwo instanceof single_button)) { + throw new coding_exception('The buttontwo param must be an instance of a single_button.'); + } -// Print the header + if (!($cancel instanceof single_button)) { + throw new coding_exception('The cancel param must be an instance of a single_button.'); + } -if ($blogtype == 'personal') { - $PAGE->navbar->add(fullname($oubloguser), new moodle_url('/user/view.php', array('id'=>$oubloguser->id))); - $PAGE->navbar->add(format_string($oublog->name)); + $output = $OUTPUT->box_start('generalbox', 'notice'); + $output .= html_writer::tag('p', $message); + $buttons = $OUTPUT->render($buttonone) . $OUTPUT->render($buttontwo) . $OUTPUT->render($cancel); + $output .= html_writer::tag('div', $buttons, array('class' => 'buttons')); + $output .= $OUTPUT->box_end(); + return $output; } -$PAGE->set_title(format_string($oublog->name)); -$PAGE->set_heading(format_string($course->fullname)); -echo $OUTPUT->header(); -echo $OUTPUT->confirm(get_string('confirmdeletepost', 'oublog'), - new moodle_url('/mod/oublog/deletepost.php', array('blog'=>$blog, 'post'=>$postid, 'confirm'=>'1')), - $viewurl); diff --git a/deletepost_form.php b/deletepost_form.php new file mode 100644 index 0000000..ffb9883 --- /dev/null +++ b/deletepost_form.php @@ -0,0 +1,91 @@ +. + +require_once($CFG->libdir.'/formslib.php'); + +/** + * Form for sending an email to the author of a post when deleting + * @package mod + * @subpackage oublog + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_oublog_deletepost_form extends moodleform { + + public function definition() { + $mform =& $this->_form; + + // Header. + $mform->addElement('header', 'general', get_string('deleteandemail', 'oublog')); + + // Message box. + $mform->addElement('editor', 'message', + get_string('emailmessage', 'oublog'), array('size'=>'64', 'id' => 'id_oublog_delete_msg')); + $mform->setType('message', PARAM_RAW); + $mform->addRule('message', null, 'required', null, 'client'); + + // Send a copy to self. + $mform->addElement('checkbox', 'copyself', get_string('copytoself', 'oublog')); + + // Adding optional text field 'Email address of other recipients'. + $mform->addElement('text', 'emailadd', get_string('extra_emails', 'oublog'), + array('size' => '48')); + $mform->addHelpButton('emailadd', 'extra_emails', 'oublog'); + $mform->setType('emailadd', PARAM_RAW); + + // Include a copy of the post. + $mform->addElement('checkbox', 'includepost', get_string('includepost', 'oublog')); + + // Hidden fields for return url. + $mform->addElement('hidden', 'blog', $this->_customdata->blog); + $mform->setType('blog', PARAM_INT); + + $mform->addElement('hidden', 'post', $this->_customdata->post); + $mform->setType('post', PARAM_INT); + + $mform->addElement('hidden', 'email', $this->_customdata->email); + $mform->setType('email', PARAM_INT); + + $mform->addElement('hidden', 'delete', $this->_customdata->delete); + $mform->setType('delete', PARAM_INT); + + $mform->addElement('hidden', 'confirm', 1); + $mform->setType('confirm', PARAM_INT); + + // Add some buttons. + $this->add_action_buttons(true, get_string('sendanddelete', 'oublog')); + + } + + public function validation($data, $files) { + $errors = parent::validation($data, $files); + if (!empty($data['emailadd'])) { + $emails = preg_split('~[; ]+~', $data['emailadd']); + if (count($emails) < 1) { + $errors['emailadd'] = get_string('invalidemails', 'forumng'); + } else { + foreach ($emails as $email) { + if (!validate_email($email)) { + $errors['emailadd'] = get_string('invalidemails', 'forumng'); + break; + } + } + } + } + return $errors; + } + +} diff --git a/internaldoc/testcase.delete.txt b/internaldoc/testcase.delete.txt new file mode 100644 index 0000000..9255a12 --- /dev/null +++ b/internaldoc/testcase.delete.txt @@ -0,0 +1,321 @@ +This script describes steps to test the OU Blog facility for deleting and emailing a user +notification. It is intended to cover most of the UI and features. + +NOTE: In this test case, the word 'blog' always refers to the OU blog. + +The test steps in this script follow on from each other and aren't independent. + +Initial setup +============= + +This test case requires: + +- a course which has at least one blog. +- two test student users (US1, and US2). +- make use of the admin and (UET) a user with the teacher role. +- a reporting email is provided in oublog administration settings, to enable the 'Report post' link. +- access to each test users email account to read delete notification emails. +- at least two web browsers, to enable distinctly different sessions, + with and without javascript enabled. + +The test server must have debugging set to DEVELOPER level and to display +errors; during all parts of the test script, there should be no debugging +warnings. + + +CRE Creating blog and data +=========================== + +CRE01 / Logged in as admin. + Create a blog called CRE01 which is a whole-course blog (no groups) and + visible to anyone in the world. + +CRE01-A / Log out user Admin. +CRE01-B / Log in as US1. + +CRE01-UP1 / Logged in as US1. + Go to blog "CRE01". + Click to add a new post with title "CRE01-P1" and text "User one post one visible to participants + on this course. To be deleted without the possibility of email notification.". + Insert any image to the text area, give the image a description. + Insert the tag 'us1t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post'. + +CRE01-UP2 / Logged in as US1. + Add a new post with title "CRE01-P2" and text "User one post two visible to participants on this course. + To be deleted with the possibility of email notification.". + Insert a new image to the text area, give the image a description. + Insert the tags 'us1t2, us1t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click the 'Add post' button. + +CRE01-UP3 / Logged in as US1. + Add a new post with title "CRE01-P3" and text "User one post three visible to participants on this course. + To be deleted with email notification.". + Insert a third image to the text area, give the image a description. + Insert the tags 'us1t3,us1t2, us1t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click the 'Add post' button to save the post. + +CRE01-UP4 / Logged in as US1. + Add a new post with title "CRE01-P4" and text "User one post four to remain visible to participants on this course.". + Insert an image to the text area, give the image a description. + Insert the tags 'us1t4,us1t3,us1t2,us1t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click the 'Add post' button to save the post. + +CRE01-C / Log out user US1. +CRE01-D / Log in as US2. + +CRE02-UP1 / Logged in as US2. + Go to blog "CRE01". + Add a new post with title "CRE01-P5" and text "User two post one visible to participants on this course. + To be deleted without the possibility of email notification.". + Insert an image to the text area, give the image a description. + Insert the tag 'us2t4,us2t3,us2t2,us2t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post' and save this post. + +CRE02-UP2 / Logged in as US2. + Add a new post with title "CRE01-P6" and text "User two post two visible to participants on this course. + To be deleted with email notification.". + Insert an image to the text area, give the image a description. + Insert the tag 'us2t3,us2t2,us2t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post'. + +CRE02-UP3 / Logged in as US2. + Add a new post with title "CRE01-P7" and text "User two post three remaining visible to participants on this course.". + Insert an to the text area, give the image a description. + Insert the tag 'us2t1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post' again. + +CRE03-A / Log out user US2. +CRE03-B / Log in as UET. + +CRE03-P1 / Logged in as UET. + Go to blog "CRE01". + Add a new post with title "CRE01-P8" and text "Teacher post one visible to participants on this course, + to be deleted.". + Insert an image to the text area, give the image a description. + Insert the tag 'uett1'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post' again. + +CRE03-P2 / Logged in as UET. + Add a new post with title "CRE01-P9" and text "Teacher post two stays visible to participants on this course.". + Insert an image to the text area, give the image a description. + Insert the tag 'uett1, uett2'. + Leave 'Allow comments' at default setting. + Add the same image as an attachment to the post. +-- Click 'Add post'. + + +BSC Basic Delete usage (JS not enabled in the browser) +====================== + +BSC01-NJ1 / Log in as UET + Go to blog "CRE01". + Tab to the 'Delete' link beneath "CRE01-P1". + Click this 'Delete' link.. +-- Confirm that the page refreshes and shows a boxed form, with the description + 'Select to delete the post or delete and send a customisable email notification.' + and three buttons; 'Delete', 'Delete and email' and 'Cancel'. + +BSC01-NJ2 / as UET. + Tab to the 'Cancel' button and activate it. +-- Verify that the page refreshes, when 'Cancel' is clicked, returning to the blog view page, + without making any changes. + +BSC01-NJ3 / as UET. + Click 'Delete' beneath "CRE01-P1" again. +-- Confirming that the dialog page appears. + +BSC01-NJ4 / as UET. + Tab to the 'Delete' button. + Activate this 'Delete' button. +-- Confirm that the page refreshes. (The page should automatically redirect. If nothing happens please use the continue link.) +-- Verify that the page refreshes and that all "CRE01-P1" post content is now dimmed, + and that there is now an additional entry beneath the post title and attachments block; + 'Deleted by' {uet username} 'the date', which has highlighting in red. + +BSC01-NJ5 / as UET. + Tab to the 'Delete' link beneath post "CRE01-P2". + Click this 'Delete' link. +-- Confirm that a dialog page opens as before. + This time tab to the 'Delete and email' button and click it. +-- Confirm that a new page 'Delete and email' opens, with a form showing a message box with a default message + notification showing that the post was deleted by {uet username} and a block of post detail showing + Subject, Blog and Module, followed by an html link 'View the deleted post'. +-- Confirm that below this message box are; + 'Send a copy to yourself' check box , + 'Email address of other recipients', text input box for list entry and + 'Include post' check box. +-- Confirm that the form ends with 'Send and delete' and 'Cancel' buttons. + +BSC01-NJ5a / as UET. + Tab to the 'Cancel' button and activate it. +-- Verify that the page refreshes, when 'Cancel' is clicked, returning to the blog view page + and that the post has not been deleted. + +BSC01-NJ6 / as UET. + Again tab to the 'Delete' link beneath post "CRE01-P2". + Click this 'Delete' link. + Tab to the 'Delete and email' button and click it. + Leave all 'Delete and email' form settings at their defaults and click + 'Send and delete'. +-- Verify that the page refreshes and that all "CRE01-P2" content is now dimmed, + and that there is now an additional entry beneath the post title - 'Deleted by' {uet username} 'the date' + with highlighting in red. + +BSC01-NJ7a / as UET. +-- Verify that an email notification has been received: + This is a notification to advise you that your Blog post with the + following details has been deleted by {uet username}: + Subject: CRE01-P2 + Blog: CRE-01 + Module: OUBlog delete and email functionality + View the deleted post (an html link) + +BSC01-NJ7b / as UET. + Click to open the 'View the deleted post' link in the email. + In the browser which opens from this link, login as student user US.1. + (It may be necessary to click the link in the email again) +-- Confirm that the post "CRE01-P2" is opened in the 'Viewpost' page and that the post appears + the same as in the main page, ie dimmed and with the deleted notification. + Log out and close the browser. + +BSC01-NJ7c / as UET. + Click to open the 'View the deleted post' link in the email. + In the browser which opens from this link, login as student user US.2. + (It may be necessary to click the link in the email again) +-- Confirm that the post "CRE01-P2" can not be seen by as student user US.2. + Log out and close the browser. + +Return to the blog main page, in the original browser session. + +BSC01-NJ8 / as UET. + Tab to the 'Delete' link beneath post "CRE01-P3". + Click this 'Delete' button. +-- Confirm that a dialog page opens as before. + Tab to the 'Delete and email' button and click it. +-- Confirm that a new page 'Delete and email' opens, with a form showing a message box with a default message + notification showing that the post was deleted by {uet username} and a block of post detail showing + Subject, Blog and Module, followed by a link 'View the deleted post'. +-- Confirm that below this message box are; + 'Send a copy to yourself' check box, + 'Email address of other recipients', text input box for list entry and + 'Include post' check box. + +BSC01-NJ9 / as UET. + Click both checkboxes, and enter the known checkable email address into the text input box. + Click the 'Send and delete' button. +-- Verify that the page refreshes and that all "CRE01-P3" content is now dimmed, + and that there is now an additional entry beneath the post title - + 'Deleted by' {uet username} 'the date' with highlighting in red. + +BSC01-NJ10 / as UET. +-- Confirm that email notifications have been recieved by each test user. +-- Confirm that the notification is as above, and that the email also contains the content of the blog post + in plain html format, with no delete highlighting. + +Return to the blog main page. + +BSC Basic delete usage (JS enabled) +====================== + Return to the main blog page. + +BSC02-JE1 / Log in as UET. + Go to blog "CRE01". + Tab to the 'Delete' link beneath "CRE01-P5". + Click this 'Delete' link. +-- Confirm that the current page is slightly dimmed and grey all over, highlighting the central popup box + with a close widget [X] and the description + 'Select to delete the post or delete and send a customisable email notification.' + and three buttons; 'Delete', 'Delete and email' and 'Cancel'. + +BSC02-JE2 / as UET. + Tab to the close widget, and click it. +-- Verify that the dialog disappears, when the close widget is clicked. + On post "CRE01-P5" click 'Delete' again, and tab to the 'Cancel' button. +-- Verify that the dialog disappears, when the 'Cancel' button is clicked, + and that focus remains upon the "CRE01-P5" 'Delete' link. + +BSC02-JE3 / as UET. + Click this 'Delete' link again beneath "CRE01-P5" post content. +-- Confirm that a dialog pops up as before. + Tab to the 'Delete' button and click it. +-- Verify that the page refreshes. +-- Confirm that all "CRE01-P5" post content is now dimmed, + and that there is an additional entry beneath the post title - + 'Deleted by' {uet username} 'the date' with highlighting in red. + +BSC02-JE4 / as UET. + Tab to the 'Delete' link beneath "CRE01-P6". + Click this 'Delete' link. +-- Confirm that the dialog pops up as before. + Tab to the 'Delete and email' button and click it. +-- Confirm that a new page opens containing a 'Delete and email' form page. + +BSC02-JE5 / as UET. + Leave all form settings at their defaults and click 'Send and delete'. + (This page should automatically redirect. If nothing happens please use the continue link.) +-- Verify that the page refreshes and that all "CRE01-P6" post content is now dimmed, + and that there is now an additional entry beneath the post title - + 'Deleted by' {uet username} 'the date' with highlighting in red. + +BSC02-JE6 / as UET. +-- Confirm that an email notification has been recieved : + This is a notification to advise you that your blog post with the + following details has been deleted by 'uetuser teacher': + Subject: CRE01-P6 + Blog: CRE01 + Course: OUBlog delete and email functionality + View the deleted post (an html link) + +Return to the blog main page. + +BSC02-JE7 / as UET. + Tab to the 'Delete' link beneath post "CRE01-P8" by user UET. + Click this 'Delete' link. +-- Confirm that the page refreshes and shows a boxed form, with the description + 'Are you sure you want to delete this post?' + and two buttons 'Delete' and 'Cancel'. + +BSC02-JE8 / as UET. + Click the 'Delete' button. + (This page should automatically redirect. If nothing happen please use the continue link.) +-- Verify that the page refreshes and that all "CRE01-P8" content is now dimmed, + and that there is also an additional entry beneath the post title - + 'Deleted by' {uet username} 'the date' with highlighting in red. +-- Confirm that no email was sent following this deletion. + + +Student user post visibility test. +---------------------------------- + +BSC03-U01 / Log in as US.1. + Go to blog main page for "CRE01". +-- Confirm that only five posts are visible as US.1. + Posts CRE01-P9 by {uet username}. + Posts CRE01-P7 and CRE01-P4 by students two and one. + And deleted posts CRE01-P3, CRE01-P2 and CRE01-P1 by student user one + +BSC03-U02 / Log in as US.2. + Go to blog main page for "CRE01". +-- Confirm that only five posts are visible as US.2. + Posts CRE01-P9 by {uet username}. + Post CRE01-P7 and CRE01-P4 by students two and one. + And deleted posts, CRE01-P6 and CRE01-P5 by student user two + +Test ends. diff --git a/lang/en/oublog.php b/lang/en/oublog.php index e82f01a..09a53d5 100644 --- a/lang/en/oublog.php +++ b/lang/en/oublog.php @@ -1,4 +1,18 @@ . $string['attachments'] = "Attachments"; $string['oublog'] = 'OU blog'; $string['modulename'] = 'OU blog'; @@ -187,7 +201,7 @@ log in for full access.'; $string['noposts']='There are no visible posts in this {$a}.'; -//Errors +// Errors. $string['accessdenied']='Sorry: you do not have access to view this page.'; $string['invalidpost'] = 'Invalid Post Id'; $string['invalidcomment'] = 'Invalid Comment Id'; @@ -210,10 +224,6 @@ $string['invalidvisbilitylevel'] = 'Invalid visibility level {$a}'; $string['invalidblogdetails'] = 'Can\'t find details for blog post {$a}'; - - - - $string['siteentries'] = 'View site entries'; $string['overviewnumentrylog1'] = 'entry since last log in'; $string['overviewnumentrylog'] = 'entries since last log in'; @@ -338,7 +348,7 @@ $string['pluginadministration'] = 'OU Blog administration'; $string['pluginname'] = 'OU Blog'; -//help strings +// Help strings. $string['allowcomments_help'] = '‘Yes, from signed-on users’ allows comments from users who have access to the post. ‘Yes, from everybody’ allows comments from users and from the general public. You will receive emails to approve or reject comments from users who are not signed in. @@ -370,13 +380,13 @@ the whole blog is set to the first level, you cannot change the level of an individual post at all.

'; $string['tags_help'] = 'Tags are labels that help you find and categorise posts.'; -// Used at OU only +// Used at OU only. $string['externaldashboardadd'] = 'Add blog to dashboard'; $string['externaldashboardremove'] = 'Remove blog from dashboard'; $string['viewblogdetails'] = 'View blog details'; $string['viewblogposts'] = 'Return to blog'; -// User participation +// User participation. $string['oublog:grade'] = 'Grade OU Blog user participation'; $string['oublog:viewparticipation'] = 'View OU Blog user participation'; $string['userparticipation'] = 'User participation'; @@ -395,14 +405,14 @@ $string['gradesupdated'] = 'Grades updated'; $string['usergrade'] = 'User grade'; -// Participation download strings +// Participation download strings. $string['downloadas'] = 'Download data as'; $string['postauthor'] = 'Post author'; $string['postdate'] = 'Post date'; $string['posttime'] = 'Post time'; $string['posttitle'] = 'Post title'; -// Export +// Export. $string['exportedpost'] = 'Exported post'; $string['exportpostscomments'] = ' all currently visible posts and their comments.'; $string['exportuntitledpost'] = 'An untitled post '; @@ -454,3 +464,24 @@ $string['commentposts_info_alltime'] = 'Posts with the most number of comments'; $string['commentposts_info_thisyear'] = 'Posts with the most number of comments added in the past year'; $string['commentposts_info_thismonth'] = 'Posts with the most number of comments added in the past month'; + +$string['emailcontenthtml'] = 'This is a notification to advise you that your {$a->activityname} post with the +following details has been deleted by \'{$a->firstname} {$a->lastname}\':
+
+Subject: {$a->subject}
+{$a->activityname}: {$a->blog}
+Course: {$a->course}
+
+deleteurl} title="view deleted post">View the deleted post'; +$string['deleteemailpostbutton'] = 'Delete and email'; +$string['deleteandemail'] = 'Delete and email'; +$string['emailmessage'] = 'Message'; +$string['cancel'] = 'Cancel'; +$string['deleteemailpostdescription'] = 'Select to delete the post or delete and send a customisable email notification.'; +$string['copytoself'] = 'Send a copy to yourself'; +$string['includepost'] = 'Include post'; +$string['deletedblogpost'] = 'Untitled post.'; +$string['emailerror'] = 'There was an error sending the email'; +$string['sendanddelete'] = 'Send and delete'; +$string['extra_emails'] = 'Email address of other recipients'; +$string['extra_emails_help'] = 'Enter one or more email address(es) separated by spaces or semicolons.'; diff --git a/locallib.php b/locallib.php index 2ef2b7a..ab1b4e7 100644 --- a/locallib.php +++ b/locallib.php @@ -308,7 +308,7 @@ function oublog_get_activity_groupmode($cm, $course=null) { * @param object $cm Moodle course-module */ function oublog_is_writable_group($cm) { - $groupmode = oublog_get_activity_groupmode($cm); + $groupmode = oublog_get_activity_groupmode($cm, $cm->course); if ($groupmode != VISIBLEGROUPS) { // If no groups, then they must be allowed to access this; // if separate groups, then because this is defined to only work @@ -340,7 +340,7 @@ function oublog_is_writable_group($cm) { * @return bool */ function oublog_can_view_post($post, $user, $context, $personalblog) { - if ($personalblog && empty($post->userid)) { + if (empty($post->userid)) { // Not sent userid from pluginfile etc so get it. global $DB; if ($instance = $DB->get_record('oublog_instances', @@ -348,15 +348,14 @@ function oublog_can_view_post($post, $user, $context, $personalblog) { $post->userid = $instance->userid; } } + // If you dont have capabilities and its not yours, you cant see it. + if ($post->deletedby && !has_capability('mod/oublog:manageposts', $context, $user->id) && + ($post->userid !== $user->id)) { + return false; + } // Public visibility means everyone if ($post->visibility == OUBLOG_VISIBILITY_PUBLIC) { - if (!$post->deletedby || ($post->userid == $user->id || - has_capability('mod/oublog:manageposts', $context, $user->id))) { - // If not deleted, or is and author or has manage cap then show. - return true; - } else { - return false; - } + return true; } // Logged-in user visibility means everyone logged in, but no guests if ($post->visibility==OUBLOG_VISIBILITY_LOGGEDINUSER && @@ -558,7 +557,8 @@ function oublog_get_posts($oublog, $context, $offset = 0, $cm, $groupid, $indivi } } if (!$canaudit) { - $sqlwhere .= " AND p.deletedby IS NULL "; + $sqlwhere .= " AND (p.deletedby IS NULL or bi.userid = ?)"; + $params[] = $USER->id; } if ($tag) { $sqlwhere .= " AND t.tag = ? "; @@ -3910,7 +3910,7 @@ protected function get_form_identifier() { return parent::get_form_identifier() . '_' . $this->type; } - function add_action_buttons($cancel = true, $submitlabel=null){ + public function add_action_buttons($cancel = true, $submitlabel = null) { // Override submit to ensure name unique. $mform =& $this->_form; $mform->addElement('submit', 'submitbutton' . '_' . $this->type, $submitlabel); diff --git a/module.js b/module.js index a20b939..f8b4bee 100644 --- a/module.js +++ b/module.js @@ -81,3 +81,63 @@ M.mod_oublog.init_showhide = function(Y, name, curpref) { } } }; + +M.mod_oublog.init_deleteandemail = function(Y, cmid, postid) { + this.Y = Y; + this.YAHOO = Y.YUI2; + // Trap for individual 'Delete' links. + var delbtns = Y.one('a.oublog_deleteandemail_' + postid); + delbtns.on('click', function(e) { + var uri = e.target.get('href'); + // Show the dialogue. + delbtns.set('disabled', false); + var content = M.util.get_string('deleteemailpostdescription', 'oublog'); + var panel = new M.core.dialogue({ + bodyContent: content, + width: 400, + centered: true, + render: true, + zIndex: 5000, + lightbox : true, + buttons: {}, + plugins: [Y.Plugin.Drag], + modal: true}); + // Add the two Delete and Cancel buttons to the bottom of the dialog. + panel.addButton({ + label: M.util.get_string('delete', 'oublog'), + section: Y.WidgetStdMod.FOOTER, + action : function (e) { + e.preventDefault(); + // Add on the 'confirm' delete marker to the link uri. + uri += '&confirm=1'; + document.location.href = uri; + panel.hide(); + panel.destroy(); + } + }); + panel.addButton({ + label: M.util.get_string('deleteandemail', 'oublog'), + section: Y.WidgetStdMod.FOOTER, + action : function (e) { + e.preventDefault(); + // Add on the 'email' marker to the link uri. + uri += '&email=1'; + document.location.href = uri; + panel.hide(); + panel.destroy(); + } + }); + panel.addButton({ + value : 'Cancel', + section: Y.WidgetStdMod.FOOTER, + action : function (e) { + e.preventDefault(); + panel.hide(); + panel.destroy(); + Y.one('a.oublog_deleteandemail_' + postid).focus(); + } + }); + e.preventDefault(); + Y.one('a.oublog_deleteandemail_' + postid).focus(); + }); +}; diff --git a/renderer.php b/renderer.php index 66d7e46..bc5a2d8 100644 --- a/renderer.php +++ b/renderer.php @@ -36,11 +36,12 @@ class mod_oublog_renderer extends plugin_renderer_base { * @param bool $canaudit Has capability toggle * @param bool $cancomment Has capability toggle * @param bool $forexport Export output rendering toggle + * @param bool $email Email output rendering toggle * @return bool */ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $canmanageposts = false, $canaudit = false, $commentcount = true, - $forexport = false, $format = false) { + $forexport = false, $format = false, $email = false) { global $CFG, $USER; $output = ''; $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); @@ -70,7 +71,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $output .= html_writer::start_tag('div', array('class'=>'oublog-post-attachments')); $output .= get_string('attachments', 'mod_oublog') . ': '; foreach ($files as $file) { - if (!$forexport) { + if (!$forexport && !$email) { $filename = $file->get_filename(); $mimetype = $file->get_mimetype(); $iconimage = html_writer::empty_tag('img', @@ -89,7 +90,12 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $output .= html_writer::tag('a', s($filename), array('href' => $path)); $output .= html_writer::end_tag('div'); } else { - $output .= $format->file_output($file) . ' '; + $filename = $file->get_filename(); + if (is_object($format)) { + $output .= $format->file_output($file) . ' '; + } else { + $output .= $filename . ' '; + } } } $output .= html_writer::end_tag('div'); @@ -162,7 +168,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $a = new stdClass(); $a->editby = fullname($edit); $a->editdate = oublog_date($edit->timeupdated); - if (!$forexport) { + if (!$forexport && !$email) { if ($edit->userid == $post->userid) { $output .= '- '.html_writer::tag('a', get_string('editsummary', 'oublog', $a), array('href' => @@ -199,7 +205,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $output .= html_writer::end_tag('div'); $output .= html_writer::start_tag('div', array('class' => 'oublog-post-content')); if (!$forexport) { - if ($post->visibility == OUBLOG_VISIBILITY_PUBLIC) { + if ($post->visibility == OUBLOG_VISIBILITY_PUBLIC || $email) { $fileurlbase = 'mod/oublog/pluginfile.php'; } else { $fileurlbase = 'pluginfile.php'; @@ -207,6 +213,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $post->message = file_rewrite_pluginfile_urls($post->message, $fileurlbase, $modcontext->id, 'mod_oublog', 'message', $post->id); } else { + require_once($CFG->libdir . '/portfoliolib.php'); $post->message = portfolio_rewrite_pluginfile_urls($post->message, $modcontext->id, 'mod_oublog', 'message', $post->id, $format); } @@ -230,11 +237,11 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, if ($tagcounter < count($post->tags)) { $taglinktext .= ','; } - if (!$forexport) { + if (!$forexport && !$email) { $output .= html_writer::tag('a', $taglinktext, array('href' => $baseurl . - '&tag=' . urlencode($taglink))).' '; + '&tag=' . urlencode($taglink))) . ' '; } else { - $output .= $taglinktext .' '; + $output .= $taglinktext . ' '; } $tagcounter++; } @@ -242,23 +249,29 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, } $output .= html_writer::start_tag('div', array('class' => 'oublog-post-links')); - if (!$forexport) { + if (!$forexport && !$email) { $output .= html_writer::tag('a', $strpermalink, array('href' => $CFG->wwwroot . '/mod/oublog/viewpost.php?post=' . $post->id)).' '; - } else { - $output .= $strpermalink .' '; } + if (!$post->deletedby) { if (($post->userid == $USER->id || $canmanageposts)) { - if (!$forexport) { + if (!$forexport && !$email) { $output .= html_writer::tag('a', $stredit, array('href' => $CFG->wwwroot . '/mod/oublog/editpost.php?blog=' . $post->oublogid . '&post=' . $post->id)).' '; - $output .= html_writer::tag('a', $strdelete, array('href' => $CFG->wwwroot . - '/mod/oublog/deletepost.php?blog=' . $post->oublogid . - '&post=' . $post->id)).' '; - } else { - $output .= $stredit . ' ' . $strdelete . ' '; + if (($post->userid !== $USER->id)) { + // Add email and 'oublog_deleteandemail' to delete link. + $output .= html_writer::tag('a', $strdelete, array('href' => $CFG->wwwroot . + '/mod/oublog/deletepost.php?blog=' . $post->oublogid . + '&post=' . $post->id . '&delete=1', + 'class' => 'oublog_deleteandemail_' . $post->id)); + self::render_oublog_print_delete_dialog($cm->id, $post->id); + } else { + $output .= html_writer::tag('a', $strdelete, array('href' => $CFG->wwwroot . + '/mod/oublog/deletepost.php?blog=' . $post->oublogid . + '&post=' . $post->id . '&delete=1')); + } } } // Show portfolio export link. @@ -266,7 +279,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, (has_capability('mod/oublog:exportpost', $modcontext) || ($post->userid == $USER->id && has_capability('mod/oublog:exportownpost', $modcontext)))) { - if (!$forexport) { + if (!$forexport && !$email) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); $button->set_callback_options('oublog_portfolio_caller', @@ -277,8 +290,6 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $button->set_formats(PORTFOLIO_FORMAT_RICHHTML); } $output .= $button->to_html(PORTFOLIO_ADD_TEXT_LINK).' '; - } else { - $output .= get_string('oublog:exportpost', 'oublog'); } } // Show OU Alerts reporting link. @@ -288,7 +299,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $itemnurl = new moodle_url('/mod/oublog/viewpost.php', array('post' => $post->id)); $reportlink = oualerts_generate_alert_form_url('oublog', $modcontext->id, 'post', $post->id, $itemnurl, $itemnurl, '', false, true); - if ($reportlink != '') { + if ($reportlink != '' && !$forexport && !$email) { $output .= html_writer::tag('a', get_string('postalert', 'oublog'), array('href' => $reportlink)); } @@ -323,7 +334,7 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $output .= html_writer::tag('a', $linktext, array('href' => $CFG->wwwroot . '/mod/oublog/viewpost.php?post=' . $post->id . '#oublogcomments')); } else { - $output .= '$linktext'; + $output .= $linktext; } // Display information about most recent comment. if (isset($post->comments)) { @@ -339,9 +350,11 @@ public function render_post($cm, $oublog, $post, $baseurl, $blogtype, $output .= ' ' . get_string('lastcomment', 'oublog', $a); } } else if (oublog_can_comment($cm, $oublog, $post)) { - $output .= html_writer::tag('a', $strcomment, array('href' => - $CFG->wwwroot . '/mod/oublog/editcomment.php?blog=' . $post->oublogid . - '&post=' . $post->id)); + if (!$forexport && !$email) { + $output .= html_writer::tag('a', $strcomment, array('href' => + $CFG->wwwroot . '/mod/oublog/editcomment.php?blog=' . $post->oublogid . + '&post=' . $post->id)); + } } } } @@ -1038,6 +1051,22 @@ public function render_oublog_statsinfo(oublog_statsinfo $info) { $out = $avatar . $infodiv; return $this->output->container($out, 'oublog_statsinfo'); } + + public function render_oublog_print_delete_dialog($cmid, $postid) { + global $PAGE; + $PAGE->requires->js('/mod/oublog/module.js'); + $stringlist[] = array('deleteemailpostdescription', 'oublog'); + $stringlist[] = array('delete', 'oublog'); + $stringlist[] = array('deleteandemail', 'oublog'); + $stringlist[] = array('cancel', 'oublog'); + $jsmodule = array( + 'name' => 'mod_oublog.init_deleteandemail', + 'fullpath' => '/mod/oublog/module.js', + 'requires' => array('base', 'event', 'node', 'panel', 'anim', 'moodle-core-notification', 'button'), + 'strings' => $stringlist); + $PAGE->requires->js_init_call('M.mod_oublog.init_deleteandemail', array($cmid, $postid), true, $jsmodule); + } + } class oublog_statsinfo implements renderable { diff --git a/styles.css b/styles.css index 4dbe14b..37d0688 100644 --- a/styles.css +++ b/styles.css @@ -162,6 +162,13 @@ color: #aaa; } +div.oublog-deleted div.oublog-userpic, +div.oublog-deleted .oublog-post-attachments a, +div.oublog-deleted .oublog-post-content { + opacity: 0.5; + filter: alpha(opacity=50); +} + .oublog-paging { border-top: 1px solid #F2F2F2; margin-top: .5em; diff --git a/version.php b/version.php index c003ddc..fec043e 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ * @package oublog **/ -$module->version = 2014012700; +$module->version = 2014012701; $module->requires = 2013040500; $module->cron = 60*60*4; // 4 hours.