email options of certificates

email options of certificates

by Wendi Daniels -
Number of replies: 6

Many of us seem confused that there are "issue options" in the certificate that do not appear to work. I was looking at the code in mod > certificate > lib and found the following code. It occurs to me that Mark Nelson may have put the email functions on the back burner for later. No worries, I am grateful for his contribution! Still, does anyone out there see what is wrong with the code that would render the email functions in certificate useless?

 

 

**********************************************************************

Line 285-497 on my upload mod > certificate > lib.php

function certificate_get_teachers($certificate, $user, $course, $cm) {
    global $USER, $DB;

    $context = context_module::instance($cm->id);
    $potteachers = get_users_by_capability($context, 'mod/certificate:manage',
        '', '', '', '', '', '', false, false);
    if (empty($potteachers)) {
        return array();
    }
    $teachers = array();
    if (groups_get_activity_groupmode($cm, $course) == SEPARATEGROUPS) {   // Separate groups are being used
        if ($groups = groups_get_all_groups($course->id, $user->id)) {  // Try to find all groups
            foreach ($groups as $group) {
                foreach ($potteachers as $t) {
                    if ($t->id == $user->id) {
                        continue; // do not send self
                    }
                    if (groups_is_member($group->id, $t->id)) {
                        $teachers[$t->id] = $t;
                    }
                }
            }
        } else {
            // user not in group, try to find teachers without group
            foreach ($potteachers as $t) {
                if ($t->id == $USER->id) {
                    continue; // do not send self
                }
                if (!groups_get_all_groups($course->id, $t->id)) { //ugly hack
                    $teachers[$t->id] = $t;
                }
            }
        }
    } else {
        foreach ($potteachers as $t) {
            if ($t->id == $USER->id) {
                continue; // do not send self
            }
            $teachers[$t->id] = $t;
        }
    }

    return $teachers;
}

/**
 * Alerts teachers by email of received certificates. First checks
 * whether the option to email teachers is set for this certificate.
 *
 * @param stdClass $course
 * @param stdClass $certificate
 * @param stdClass $certrecord
 * @param stdClass $cm course module
 */
function certificate_email_teachers($course, $certificate, $certrecord, $cm) {
    global $USER, $CFG, $DB;

    if ($certificate->emailteachers == 0) {          // No need to do anything
        return;
    }

    $user = $DB->get_record('user', array('id' => $certrecord->userid));

    if ($teachers = certificate_get_teachers($certificate, $user, $course, $cm)) {
        $strawarded = get_string('awarded', 'certificate');
        foreach ($teachers as $teacher) {
            $info = new stdClass;
            $info->student = fullname($USER);
            $info->course = format_string($course->fullname,true);
            $info->certificate = format_string($certificate->name,true);
            $info->url = $CFG->wwwroot.'/mod/certificate/report.php?id='.$cm->id;
            $from = $USER;
            $postsubject = $strawarded . ': ' . $info->student . ' -> ' . $certificate->name;
            $posttext = certificate_email_teachers_text($info);
            $posthtml = ($teacher->mailformat == 1) ? certificate_email_teachers_html($info) : '';

            @email_to_user($teacher, $from, $postsubject, $posttext, $posthtml);  // If it fails, oh well, too bad.
        }
    }
}

/**
 * Alerts others by email of received certificates. First checks
 * whether the option to email others is set for this certificate.
 * Uses the email_teachers info.
 * Code suggested by Eloy Lafuente
 *
 * @param stdClass $course
 * @param stdClass $certificate
 * @param stdClass $certrecord
 * @param stdClass $cm course module
 */
function certificate_email_others($course, $certificate, $certrecord, $cm) {
    global $USER, $CFG, $DB;

    if ($certificate->emailothers) {
       $others = explode(',', $certificate->emailothers);
        if ($others) {
            $strawarded = get_string('awarded', 'certificate');
            foreach ($others as $other) {
                $other = trim($other);
                if (validate_email($other)) {
                    $destination = new stdClass;
                    $destination->email = $other;
                    $info = new stdClass;
                    $info->student = fullname($USER);
                    $info->course = format_string($course->fullname, true);
                    $info->certificate = format_string($certificate->name, true);
                    $info->url = $CFG->wwwroot.'/mod/certificate/report.php?id='.$cm->id;
                    $from = $USER;
                    $postsubject = $strawarded . ': ' . $info->student . ' -> ' . $certificate->name;
                    $posttext = certificate_email_teachers_text($info);
                    $posthtml = certificate_email_teachers_html($info);

                    @email_to_user($destination, $from, $postsubject, $posttext, $posthtml);  // If it fails, oh well, too bad.
                }
            }
        }
    }
}

/**
 * Creates the text content for emails to teachers -- needs to be finished with cron
 *
 * @param $info object The info used by the 'emailteachermail' language string
 * @return string
 */
function certificate_email_teachers_text($info) {
    $posttext = get_string('emailteachermail', 'certificate', $info) . "\n";

    return $posttext;
}

/**
 * Creates the html content for emails to teachers
 *
 * @param $info object The info used by the 'emailteachermailhtml' language string
 * @return string
 */
function certificate_email_teachers_html($info) {
    $posthtml  = '<font face="sans-serif">';
    $posthtml .= '<p>' . get_string('emailteachermailhtml', 'certificate', $info) . '</p>';
    $posthtml .= '</font>';

    return $posthtml;
}

/**
 * Sends the student their issued certificate from moddata as an email
 * attachment.
 *
 * @param stdClass $course
 * @param stdClass $certificate
 * @param stdClass $certrecord
 * @param stdClass $context
 */
function certificate_email_student($course, $certificate, $certrecord, $context) {
    global $DB, $USER;

    // Get teachers
    if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
        '', '', '', '', false, true)) {
        $users = sort_by_roleassignment_authority($users, $context);
        $teacher = array_shift($users);
    }

    // If we haven't found a teacher yet, look for a non-editing teacher in this course.
    if (empty($teacher) && $users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
        '', '', '', '', false, true)) {
        $users = sort_by_roleassignment_authority($users, $context);
        $teacher = array_shift($users);
    }

    // Ok, no teachers, use administrator name
    if (empty($teacher)) {
        $teacher = fullname(get_admin());
    }

    $info = new stdClass;
    $info->username = fullname($USER);
    $info->certificate = format_string($certificate->name, true);
    $info->course = format_string($course->fullname, true);
    $from = fullname($teacher);
    $subject = $info->course . ': ' . $info->certificate;
    $message = get_string('emailstudenttext', 'certificate', $info) . "\n";

    // Make the HTML version more XHTML happy  (&amp;)
    $messagehtml = text_to_html(get_string('emailstudenttext', 'certificate', $info));

    // Remove full-stop at the end if it exists, to avoid "..pdf" being created and being filtered by clean_filename
    $certname = rtrim($certificate->name, '.');
    $filename = clean_filename("$certname.pdf");

    // Get hashed pathname
    $fs = get_file_storage();

    $component = 'mod_certificate';
    $filearea = 'issue';
    $filepath = '/';
    $files = $fs->get_area_files($context->id, $component, $filearea, $certrecord->id);
    foreach ($files as $f) {
        $filepathname = $f->get_contenthash();
    }
    $attachment = 'filedir/'.certificate_path_from_hash($filepathname).'/'.$filepathname;
    $attachname = $filename;

    return email_to_user($USER, $from, $subject, $message, $messagehtml, $attachment, $attachname);
}

****************************************************************************************

Average of ratings: -
In reply to Wendi Daniels

Re: email options of certificates

by Jean-Michel Védrine -

Hello Wendi,

Please don't post long copy of code in the forums like this. This is absolutely useless: people who know how to fix the code already know where to look for it smile

I have already created an issue about the "Email other" not working: CONTRIB-4892 and already posted a fix in this forum see https://moodle.org/mod/forum/discuss.php?d=254429#p1107763

I was not aware that other mail functions of the certificate were broken but now that I know it I will post a temporary fix tomorrow (European time) and also create a push request for CONTRIB-4892

When you find a bug, the best thing to do is to create an issue in the tracker (for bugs in Moodle itself here: https://tracker.moodle.org/browse/MDL  and for addons like certificate here: https://tracker.moodle.org/browse/CONTRIB

You will need to login but anybody can create new issues in the tracker not just Moodle developpers

Try to give as many details as you can so that the developer is able to reproduce the problem.

Average of ratings: Useful (1)
In reply to Jean-Michel Védrine

Re: email options of certificates

by Wendi Daniels -

I suppose the problem is that I am not a programmer, and I was hoping that if I were to post the code that seems to discuss email options,  that someone might see the flaw in the code. I may be hiring someone to fix it, and if it works I will post the code to the forum so that others can see it and cut & paste, and then alert the developers. Sorry to create a small burden...it is all meant with good intentions.

In reply to Wendi Daniels

Re: email options of certificates

by Mary Cooch -
Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Testers Picture of Translators

 Just for the benefit of others in future, a good way to poste code  into a forum is to paste it into a text editor (like Notepad in Windows) and then add it as an attachment.

In reply to Mary Cooch

Re: email options of certificates

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Attachements are always a pain. If you want to post existing code, the most convenient way is to link to it on github, if possible.

In reply to Jean-Michel Védrine

Re: email options of certificates

by Jean-Michel Védrine -

Here is the result of the tests I did today on certificate email features with the latest version of Moodle 2.6 (Moodle 2.6.2 released just a few days ago) and the latest version of the certificate module freshly downloaded for Mark Nelson's github account https://github.com/markn86/moodle-mod_certificate/

There are 3 features related to mail in the certificate activity

certificate issues options

  1. sending certificate to students if in the issues options you set "Delivery" to ""Email" and "Save certificates" is set to "Yes"
  2. Notifying users enrolled as teachers in the course when a student get a new certificate if in the issues options you set "Email teachers" to "Yes"
  3. Notifying other people when a student get a new certificate if in the issues options you put a comma separated list of email addresses in the "Email others" field

For me according to my tests 1. and 2. are working with no problem, so if you have a problem with mailing certificate to students or notifying teachers of new certificates post more informations so that I can reproduce the problem including your Moodle and certificate versions.

As I said in another message 3. (emailing others) is currently broken but it's easy to correct the problem just by adding a single line in mod/certificate/lib.php, you need to add the line:

$destination->id = 1;

just after the line

$destination = new stdClass;

line 381 in the mod/certificate/lib.php file

After your modification, lines 380-382 should read:

                    $destination = new stdClass;
                    $destination->id = 1;
                    $destination->email = $other;

If you are unable to do this modification, I can attach a modified file.

I will now make some tests with the new customcert module to see if I find some problems related to email functions.

 

In reply to Jean-Michel Védrine

Re: email options of certificates

by Jean-Michel Védrine -

There is currently no email functions in the new customcert module so no bug to correct smile