Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"require": {
"php": "^7.4 || ^8.0",
"silverstripe/vendor-plugin": "^1",
"silverstripe/framework": "^4.10",
"silverstripe/framework": "^4.8",
"silverstripe/cms": "^4.2",
"silverstripe/reports": "^4.2",
"silverstripe/siteconfig": "^4.2"
Expand Down
12 changes: 10 additions & 2 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@

The module is set up in the `Settings` section of the CMS, see the [User guide](userguide/index.md).

### Reminder emails
### Email notifications

In order for the contentreview module to send emails, you need to *either*:
In order for the contentreview module to send overdue review and reminder email notifications, you need to *either*:

* Setup the `ContentReviewEmails` script to run daily via a system cron job.
* Setup the `ContentReviewReminderEmails` script to run daily via a system cron job.
* Install the [queuedjobs](https://github.com/symbiote/silverstripe-queuedjobs) module and follow the configuration steps to create a cron job for that module. Once installed, you can just run `dev/build` to have a job created, which will run at 9am every day by default.

## Reminders
Content Review module has two notification workflows.
This allows for authors to be reminded of upcoming reviews and then reminded of overdue review(s).

1. A review date is assigned to a page that will send notifications to the author on the review date at a frequency specified by site admins.
2. Concurrent to the review date an interval configuration of `7`, `30` and `60` days will check if a piece of content is x days away from review and send a reminder that day to the author.

## Using

See the [user guide](userguide/index.md).
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
3 changes: 2 additions & 1 deletion docs/en/userguide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ summary: Mark pages in the CMS with a date and an owner for future reviews.
Global settings can be configured via the global settings admin in the CMS under the "Content Review" tab.
This includes global groups, users, as well as a template editor that supports a limited number of variables.

![SiteConfig settings](_images/content-review-siteconfig-settings.png)
![SiteConfig settings](_images/content-review-siteconfig-settings-part-1.png)
![SiteConfig settings](_images/content-review-siteconfig-settings-part-2.png)

## Schedules

Expand Down
8 changes: 5 additions & 3 deletions lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ en:
DEFAULTSETTINGSHELP: 'These settings will apply to all pages that do not have a specific Content Review schedule.'
EMAILFROM: 'From email address'
EMAILFROM_RIGHTTITLE: 'e.g: do-not-reply@site.com'
EMAILSUBJECT: 'Subject line'
EMAILTEMPLATE: 'Email template'
OVERDUEEMAILSUBJECT: 'Overdue subject line'
OVERDUEEMAILTEMPLATE: 'Overdue review email template'
REMINDEREMAILSUBJECT: 'Reminder subject line'
REMINDEREMAILTEMPLATE: 'Reminder email template'
OWNERGROUPSDESCRIPTION: 'Page owners that are responsible for reviews'
OWNERUSERSDESCRIPTION: 'Page owners that are responsible for reviews'
PAGEOWNERGROUPS: Groups
Expand All @@ -24,7 +26,7 @@ en:
DISABLE: 'Disable content review'
INHERIT: 'Inherit from parent page'
NEXTREVIEWDATADESCRIPTION: 'Leave blank for no review'
NEXTREVIEWDATE: 'Next review date'
NEXTREVIEWDATE: 'Overdue review date'
OPTIONS: Options
OWNERGROUPSDESCRIPTION: 'Page owners that are responsible for reviews'
OWNERUSERSDESCRIPTION: 'Page owners that are responsible for reviews'
Expand Down
76 changes: 73 additions & 3 deletions src/Extensions/ContentReviewDefaultSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
use SilverStripe\Control\Email\Email;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\Forms\HTMLEditor\TinyMCEConfig;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextAreaField;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Security\Group;
Expand All @@ -33,6 +35,8 @@ class ContentReviewDefaultSettings extends DataExtension
'ReviewFrom' => 'Varchar(255)',
'ReviewSubject' => 'Varchar(255)',
'ReviewBody' => 'HTMLText',
'ReminderSubject' => 'Varchar(255)',
'ReminderBody' => 'HTMLText',
);

/**
Expand All @@ -44,6 +48,9 @@ class ContentReviewDefaultSettings extends DataExtension
'ReviewSubject' => 'Page(s) are due for content review',
'ReviewBody' => '<h2>Page(s) due for review</h2>'
. '<p>There are $PagesCount pages that are due for review today by you.</p>',
'ReminderSubject' => 'Reminder: Page(s) are upcoming for content review',
'ReminderBody' => '<h2>Reminder: Your Page(s) are approaching overdue for review</h2>'
. '<p>There are $PagesCount pages that have reviews upcoming for you.</p>',
);

/**
Expand All @@ -67,6 +74,17 @@ class ContentReviewDefaultSettings extends DataExtension
*/
private static $content_review_template = 'SilverStripe\\ContentReview\\ContentReviewEmail';

/**
* Template to use for Reminder content review emails.
*
* This should contain an $EmailBody variable as a placeholder for the user-defined copy
*
* @config
*
* @var string
*/
private static $content_review_reminder_template = 'SilverStripe\\ContentReview\\ContentReviewReminderEmail';

/**
* @return string
*/
Expand Down Expand Up @@ -163,14 +181,66 @@ public function updateCMSFields(FieldList $fields)
[
TextField::create('ReviewFrom', _t(__CLASS__ . '.EMAILFROM', 'From email address'))
->setDescription(_t(__CLASS__ . '.EMAILFROM_RIGHTTITLE', 'e.g: do-not-reply@site.com')),
TextField::create('ReviewSubject', _t(__CLASS__ . '.EMAILSUBJECT', 'Subject line')),
TextAreaField::create('ReviewBody', _t(__CLASS__ . '.EMAILTEMPLATE', 'Email template')),
TextField::create(
'ReviewSubject',
_t(__CLASS__ . '.OVERDUEEMAILSUBJECT', 'Overdue review subject line')
),
$overdueReviewBody = HTMLEditorField::create(
'ReviewBody',
_t(__CLASS__ . '.OVERDUEEMAILTEMPLATE', 'Overdue email template')
),
TextField::create(
'ReminderSubject',
_t(__CLASS__ . '.REMINDEREMAILSUBJECT', 'Reminder review subject line')
),
$reminderReviewBody = HTMLEditorField::create(
'ReminderBody',
_t(__CLASS__ . '.REMINDEREMAILTEMPLATE', 'Reminder Email template')
),
LiteralField::create(
'TemplateHelp',
$this->owner->renderWith('SilverStripe\\ContentReview\\ContentReviewAdminHelp')
),
]
);

// set up tinymce config for our body fields
$overdueReviewBody->setEditorConfig($this->getTinyMCEConfig($overdueReviewBody->getEditorConfig()));
$reminderReviewBody->setEditorConfig($this->getTinyMCEConfig($reminderReviewBody->getEditorConfig()));
}

/**
* Get the TinyMCEConfig that should be used for the email template preview
*
* @return TinyMCEConfig
*/
private function getTinyMCEConfig(
TinyMCEConfig $config
): TinyMCEConfig {
$editorButtonsGroupSeparator = '|';
$allowedEditorButtons = [
'undo',
'redo',
$editorButtonsGroupSeparator,
'bold',
'italic',
'underline',
$editorButtonsGroupSeparator,
'bullist',
'numlist',
$editorButtonsGroupSeparator,
'sslink',
$editorButtonsGroupSeparator,
'formatselect',
$editorButtonsGroupSeparator,
'code',
];

$config->setButtonsForLine(1, $allowedEditorButtons);
$config->setButtonsForLine(2, []);
$config->setButtonsForLine(3, []);

return $config;
}

/**
Expand Down
48 changes: 44 additions & 4 deletions src/Extensions/SiteTreeContentReview.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
365 => "12 months",
];

/**
* Array of interval timings used to remind content authors to do
* a review of their content before the overdue review date.
*
* @config
*
* @var string[]
*/
private static $reminder_intervals = [
7 => '7 days',
30 => '30 days',
60 => '60 days',
];

/**
* @return array
*/
Expand All @@ -113,6 +127,14 @@ public static function get_schedule()
return Config::inst()->get(static::class, 'schedule');
}

/**
* @return string[]
*/
public static function get_reminder_intervals()
{
return Config::inst()->get(static::class, 'reminder_intervals');
}

/**
* Takes a list of groups and members and return a list of unique member.
*
Expand Down Expand Up @@ -340,7 +362,7 @@ public function updateSettingsFields(FieldList $fields)
);
$nextReviewAt = DateField::create(
'RONextReviewDate',
_t(__CLASS__ . ".NEXTREVIEWDATE", "Next review date"),
_t(__CLASS__ . ".NEXTREVIEWDATE", "Overdue review date"),
$this->owner->NextReviewDate
);

Expand Down Expand Up @@ -420,7 +442,7 @@ public function updateSettingsFields(FieldList $fields)
->setAttribute("data-placeholder", _t(__CLASS__ . ".ADDGROUP", "Add groups"))
->setDescription(_t(__CLASS__ . ".OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));

$reviewDate = DateField::create("NextReviewDate", _t(__CLASS__ . ".NEXTREVIEWDATE", "Next review date"))
$reviewDate = DateField::create("NextReviewDate", _t(__CLASS__ . ".NEXTREVIEWDATE", "Overdue review date"))
->setDescription(_t(__CLASS__ . ".NEXTREVIEWDATADESCRIPTION", "Leave blank for no review"));

$reviewFrequency = DropdownField::create(
Expand Down Expand Up @@ -504,7 +526,7 @@ public function advanceReviewDate()
}

/**
* Check if a review is due by a member for this owner.
* A function to check whether the content review bell can be displayed
*
* @param Member $member
*
Expand Down Expand Up @@ -558,6 +580,24 @@ public function canBeReviewedBy(Member $member = null)
return false;
}

/**
* Check if a review is overdue and an email can be sent
*
* @param Member $member
*
* @return bool
*/
public function canSendEmail(Member $member = null)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this code is a duplication of canBeReviewedBy apart from one check so it would be better to do something like

    public function canSendEmail(Member $member = null)
    {
        $canSendEmail = $this->canBeReviewedBy($member);

        if ($this->owner->obj("NextReviewDate")->InFuture()) {
            $canSendEmail = false;
        }

        return $canSendEmail;
    }

{
$canSendEmail = $this->canBeReviewedBy($member);

if ($this->owner->obj("NextReviewDate")->InFuture()) {
$canSendEmail = false;
}

return $canSendEmail;
}

/**
* Set the review data from the review period, if set.
*/
Expand All @@ -581,7 +621,7 @@ public function onBeforeWrite()
}
}

// Ensure that a inherited page always have a next review date
// Ensure that an inherited page always has an overdue review date
if ($this->owner->ContentReviewType == "Inherit" && !$this->owner->NextReviewDate) {
$this->setDefaultReviewDateForInherited();
}
Expand Down
Loading