2014-02-25 03:54:27 +01:00
|
|
|
<?php
|
|
|
|
|
2017-09-06 05:49:23 +02:00
|
|
|
namespace SilverStripe\ContentReview\Tasks;
|
|
|
|
|
|
|
|
use Page;
|
2023-04-12 00:45:36 +02:00
|
|
|
use RuntimeException;
|
2017-09-06 05:49:23 +02:00
|
|
|
use SilverStripe\ContentReview\Compatibility\ContentReviewCompatability;
|
|
|
|
use SilverStripe\Control\Email\Email;
|
|
|
|
use SilverStripe\Control\HTTPRequest;
|
|
|
|
use SilverStripe\Dev\BuildTask;
|
|
|
|
use SilverStripe\ORM\ArrayList;
|
|
|
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
|
|
|
use SilverStripe\ORM\FieldType\DBField;
|
|
|
|
use SilverStripe\ORM\SS_List;
|
|
|
|
use SilverStripe\Security\Member;
|
|
|
|
use SilverStripe\SiteConfig\SiteConfig;
|
|
|
|
use SilverStripe\View\ArrayData;
|
|
|
|
use SilverStripe\View\SSViewer;
|
|
|
|
|
2014-02-25 03:54:27 +01:00
|
|
|
/**
|
2015-11-02 00:27:42 +01:00
|
|
|
* Daily task to send emails to the owners of content items when the review date rolls around.
|
2014-02-25 03:54:27 +01:00
|
|
|
*/
|
2015-11-02 00:27:42 +01:00
|
|
|
class ContentReviewEmails extends BuildTask
|
|
|
|
{
|
2023-04-12 00:45:36 +02:00
|
|
|
private array $invalid_emails = [];
|
|
|
|
|
2015-11-02 00:27:42 +01:00
|
|
|
/**
|
2017-09-06 05:49:23 +02:00
|
|
|
* @param HTTPRequest $request
|
2023-04-12 00:45:36 +02:00
|
|
|
* @throws RuntimeException
|
2015-11-02 00:27:42 +01:00
|
|
|
*/
|
|
|
|
public function run($request)
|
|
|
|
{
|
2023-04-12 00:45:36 +02:00
|
|
|
if (!$this->isValidEmail($senderEmail = SiteConfig::current_site_config()->ReviewFrom)) {
|
|
|
|
throw new RuntimeException(
|
|
|
|
sprintf(
|
|
|
|
'Provided sender email address is invalid: "%s".',
|
|
|
|
$senderEmail
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-11-02 00:27:42 +01:00
|
|
|
$compatibility = ContentReviewCompatability::start();
|
|
|
|
|
|
|
|
// First grab all the pages with a custom setting
|
2015-11-17 02:17:54 +01:00
|
|
|
$pages = Page::get()
|
2017-09-06 05:49:23 +02:00
|
|
|
->filter('NextReviewDate:LessThanOrEqual', DBDatetime::now()->URLDate());
|
2015-11-02 00:27:42 +01:00
|
|
|
|
|
|
|
$overduePages = $this->getOverduePagesForOwners($pages);
|
|
|
|
|
|
|
|
// Lets send one email to one owner with all the pages in there instead of no of pages
|
|
|
|
// of emails.
|
|
|
|
foreach ($overduePages as $memberID => $pages) {
|
|
|
|
$this->notifyOwner($memberID, $pages);
|
|
|
|
}
|
|
|
|
|
|
|
|
ContentReviewCompatability::done($compatibility);
|
2023-04-12 00:45:36 +02:00
|
|
|
|
|
|
|
if (is_array($this->invalid_emails) && count($this->invalid_emails) > 0) {
|
|
|
|
$plural = count($this->invalid_emails) > 1 ? 's are' : ' is';
|
|
|
|
throw new RuntimeException(
|
|
|
|
sprintf(
|
|
|
|
'Provided email' . $plural . ' invalid: "%s".',
|
|
|
|
implode(', ', $this->invalid_emails)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2015-11-02 00:27:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-09-06 05:49:23 +02:00
|
|
|
* @param SS_List $pages
|
2015-11-02 00:27:42 +01:00
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
2017-09-06 05:49:23 +02:00
|
|
|
protected function getOverduePagesForOwners(SS_List $pages)
|
2015-11-02 00:27:42 +01:00
|
|
|
{
|
2018-01-08 04:47:31 +01:00
|
|
|
$overduePages = [];
|
2015-11-02 00:27:42 +01:00
|
|
|
|
|
|
|
foreach ($pages as $page) {
|
|
|
|
if (!$page->canBeReviewedBy()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-14 05:43:10 +02:00
|
|
|
// get most recent review log of current [age]
|
|
|
|
$contentReviewLog = $page->ReviewLogs()->sort('Created DESC')->first();
|
|
|
|
|
|
|
|
// check log date vs NextReviewDate. If someone has left a content review
|
|
|
|
// after the review date, then we don't need to notify anybody
|
|
|
|
if ($contentReviewLog && $contentReviewLog->Created >= $page->NextReviewDate) {
|
|
|
|
$page->advanceReviewDate();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-21 22:43:44 +02:00
|
|
|
$options = $page->getOptions();
|
2015-11-02 00:27:42 +01:00
|
|
|
|
2018-08-21 22:20:36 +02:00
|
|
|
if ($options) {
|
2018-08-21 22:43:44 +02:00
|
|
|
foreach ($options->ContentReviewOwners() as $owner) {
|
2018-08-21 22:20:36 +02:00
|
|
|
if (!isset($overduePages[$owner->ID])) {
|
|
|
|
$overduePages[$owner->ID] = ArrayList::create();
|
|
|
|
}
|
2015-11-02 00:27:42 +01:00
|
|
|
|
2018-08-21 22:20:36 +02:00
|
|
|
$overduePages[$owner->ID]->push($page);
|
|
|
|
}
|
2015-11-02 00:27:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $overduePages;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param int $ownerID
|
|
|
|
* @param array|SS_List $pages
|
|
|
|
*/
|
|
|
|
protected function notifyOwner($ownerID, SS_List $pages)
|
|
|
|
{
|
2015-11-17 02:17:54 +01:00
|
|
|
// Prepare variables
|
|
|
|
$siteConfig = SiteConfig::current_site_config();
|
|
|
|
$owner = Member::get()->byID($ownerID);
|
2023-03-31 04:51:10 +02:00
|
|
|
|
2023-04-12 00:45:36 +02:00
|
|
|
if (!$this->isValidEmail($owner->Email)) {
|
|
|
|
$this->invalid_emails[] = $owner->Name . ': ' . $owner->Email;
|
|
|
|
|
2023-03-31 04:51:10 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-17 02:17:54 +01:00
|
|
|
$templateVariables = $this->getTemplateVariables($owner, $siteConfig, $pages);
|
2015-11-02 00:27:42 +01:00
|
|
|
|
2015-11-17 02:17:54 +01:00
|
|
|
// Build email
|
2017-09-06 05:49:23 +02:00
|
|
|
$email = Email::create();
|
2015-11-02 00:27:42 +01:00
|
|
|
$email->setTo($owner->Email);
|
2015-11-17 02:17:54 +01:00
|
|
|
$email->setFrom($siteConfig->ReviewFrom);
|
|
|
|
$email->setSubject($siteConfig->ReviewSubject);
|
|
|
|
|
|
|
|
// Get user-editable body
|
|
|
|
$body = $this->getEmailBody($siteConfig, $templateVariables);
|
|
|
|
|
|
|
|
// Populate mail body with fixed template
|
2017-09-06 05:49:23 +02:00
|
|
|
$email->setHTMLTemplate($siteConfig->config()->get('content_review_template'));
|
|
|
|
$email->setData(
|
|
|
|
array_merge(
|
|
|
|
$templateVariables,
|
|
|
|
[
|
|
|
|
'EmailBody' => $body,
|
|
|
|
'Recipient' => $owner,
|
|
|
|
'Pages' => $pages,
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
2015-11-02 00:27:42 +01:00
|
|
|
$email->send();
|
|
|
|
}
|
2015-11-17 02:17:54 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get string value of HTML body with all variable evaluated.
|
|
|
|
*
|
|
|
|
* @param SiteConfig $config
|
|
|
|
* @param array List of safe template variables to expose to this template
|
|
|
|
*
|
|
|
|
* @return HTMLText
|
|
|
|
*/
|
|
|
|
protected function getEmailBody($config, $variables)
|
|
|
|
{
|
|
|
|
$template = SSViewer::fromString($config->ReviewBody);
|
2017-09-06 05:49:23 +02:00
|
|
|
$value = $template->process(ArrayData::create($variables));
|
2015-11-17 02:17:54 +01:00
|
|
|
|
|
|
|
// Cast to HTML
|
|
|
|
return DBField::create_field('HTMLText', (string) $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets list of safe template variables and their values which can be used
|
|
|
|
* in both the static and editable templates.
|
|
|
|
*
|
|
|
|
* {@see ContentReviewAdminHelp.ss}
|
|
|
|
*
|
|
|
|
* @param Member $recipient
|
|
|
|
* @param SiteConfig $config
|
|
|
|
* @param SS_List $pages
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
protected function getTemplateVariables($recipient, $config, $pages)
|
|
|
|
{
|
2017-09-06 05:49:23 +02:00
|
|
|
return [
|
2015-11-17 02:17:54 +01:00
|
|
|
'Subject' => $config->ReviewSubject,
|
|
|
|
'PagesCount' => $pages->count(),
|
|
|
|
'FromEmail' => $config->ReviewFrom,
|
|
|
|
'ToFirstName' => $recipient->FirstName,
|
|
|
|
'ToSurname' => $recipient->Surname,
|
|
|
|
'ToEmail' => $recipient->Email,
|
2017-09-06 05:49:23 +02:00
|
|
|
];
|
2015-11-17 02:17:54 +01:00
|
|
|
}
|
2023-03-31 04:51:10 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check validity of email
|
|
|
|
*/
|
|
|
|
protected function isValidEmail(?string $email): bool
|
|
|
|
{
|
2023-04-12 00:45:36 +02:00
|
|
|
return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
|
2023-03-31 04:51:10 +02:00
|
|
|
}
|
2014-02-25 03:54:27 +01:00
|
|
|
}
|