Merge pull request #61 from creative-commoners/pulls/4.0/ss4-compat

API Upgrade for SS4 compatibility
This commit is contained in:
Franco Springveldt 2017-09-07 16:20:03 +12:00 committed by GitHub
commit 521c8c9128
30 changed files with 750 additions and 387 deletions

View File

@ -1,36 +1,35 @@
# See https://github.com/silverstripe/silverstripe-travis-support for setup details
sudo: false
language: php language: php
dist: precise dist: trusty
php:
- 5.3
- 5.4
- 5.5
env: env:
- DB=MYSQL CORE_RELEASE=3.5 global:
- COMPOSER_ROOT_VERSION=4.0.x-dev
matrix: matrix:
include: include:
- php: 5.6 - php: 5.6
env: DB=MYSQL CORE_RELEASE=3 env: DB=MYSQL PHPCS_TEST=1 PHPUNIT_TEST=1
- php: 5.6 - php: 7.0
env: DB=MYSQL CORE_RELEASE=3.1 env: DB=PGSQL PHPUNIT_TEST=1
- php: 5.6
env: DB=PGSQL CORE_RELEASE=3.2
- php: 7.1 - php: 7.1
env: DB=MYSQL CORE_RELEASE=3.6 env: DB=MYSQL PHPUNIT_COVERAGE_TEST=1
before_script: before_script:
- composer self-update || true # Init PHP
- git clone git://github.com/silverstripe/silverstripe-travis-support.git ~/travis-support - phpenv rehash
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss - phpenv config-rm xdebug.ini
- cd ~/builds/ss
- composer install # Install composer dependencies
- composer install --prefer-dist
- composer require --prefer-dist --no-update silverstripe/recipe-cms:1.0.x-dev
- if [[ $DB == PGSQL ]]; then composer require --prefer-dist --no-update silverstripe/postgresql:2.0.x-dev; fi
- composer update
script: script:
- vendor/bin/phpunit contentreview/tests - if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit; fi
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi
- if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs --standard=framework/phpcs.xml.dist src/ tests/; fi
after_success:
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml; fi

18
.upgrade.yml Normal file
View File

@ -0,0 +1,18 @@
mappings:
ContentReviewCompatability: SilverStripe\ContentReview\Compatibility\ContentReviewCompatability
ContentReviewCMSExtension: SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension
ContentReviewDefaultSettings: SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings
ContentReviewOwner: SilverStripe\ContentReview\Extensions\ContentReviewOwner
SiteTreeContentReview: SilverStripe\ContentReview\Extensions\SiteTreeContentReview
ContentReviewNotificationJob: SilverStripe\ContentReview\Jobs\ContentReviewNotificationJob
ContentReviewLog: SilverStripe\ContentReview\Models\ContentReviewLog
PagesDueForReviewReport: SilverStripe\ContentReview\Reports\PagesDueForReviewReport
PagesWithoutReviewScheduleReport: SilverStripe\ContentReview\Reports\PagesWithoutReviewScheduleReport
ContentReviewEmails: SilverStripe\ContentReview\Tasks\ContentReviewEmails
ContentReviewOwnerMigrationTask: SilverStripe\ContentReview\Tasks\ContentReviewOwnerMigrationTask
ContentReviewBaseTest: SilverStripe\ContentReview\Tests\ContentReviewBaseTest
ContentReviewCMSPageEditControllerTest: SilverStripe\ContentReview\Tests\ContentReviewCMSPageEditControllerTest
ContentReviewNotificationTest: SilverStripe\ContentReview\Tests\ContentReviewNotificationTest
ContentReviewReportTest: SilverStripe\ContentReview\Tests\ContentReviewReportTest
ContentReviewSettingsTest: SilverStripe\ContentReview\Tests\ContentReviewSettingsTest
SiteTreeContentReviewTest: SilverStripe\ContentReview\Tests\SiteTreeContentReviewTest

View File

@ -1,18 +1,21 @@
SiteTree: ---
Name: contentreviewextensions
---
SilverStripe\CMS\Model\SiteTree:
extensions: extensions:
- SiteTreeContentReview - SilverStripe\ContentReview\Extensions\SiteTreeContentReview
Group: SilverStripe\Security\Group:
extensions: extensions:
- ContentReviewOwner - SilverStripe\ContentReview\Extensions\ContentReviewOwner
Member: SilverStripe\Security\Member:
extensions: extensions:
- ContentReviewOwner - SilverStripe\ContentReview\Extensions\ContentReviewOwner
CMSPageEditController: SilverStripe\CMS\Controllers\CMSPageEditController:
extensions: extensions:
- ContentReviewCMSExtension - SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension
CMSPageSettingsController: SilverStripe\CMS\Controllers\CMSPageSettingsController:
extensions: extensions:
- ContentReviewCMSExtension - SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension
SiteConfig: SilverStripe\SiteConfig\SiteConfig:
extensions: extensions:
- ContentReviewDefaultSettings - SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings

6
_config/legacy.yml Normal file
View File

@ -0,0 +1,6 @@
---
Name: contentreviewlegacy
---
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
ContentReviewLog: SilverStripe\ContentReview\Models\ContentReviewLog

1
codecov.yml Normal file
View File

@ -0,0 +1 @@
comment: false

View File

@ -20,16 +20,29 @@
} }
], ],
"require": { "require": {
"composer/installers": "*", "silverstripe/framework": "^4@dev",
"silverstripe/framework": "~3.1", "silverstripe/cms": "^4@dev",
"silverstripe/cms": "~3.1" "silverstripe/reports": "^4@dev",
"silverstripe/siteconfig": "^4@dev"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
"squizlabs/php_codesniffer": "^3.0"
}, },
"suggest": { "suggest": {
"silverstripe/queuedjobs": "Automatically schedules content review emails to be sent, only requiring one crontask to be created" "symbiote/silverstripe-queuedjobs": "Automatically schedules content review emails to be sent, only requiring one crontask to be created"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "4.0.x-dev" "dev-master": "4.0.x-dev"
} }
} },
"autoload": {
"psr-4": {
"SilverStripe\\ContentReview\\": "src/",
"SilverStripe\\ContentReview\\Tests\\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true
} }

View File

@ -1,4 +1,4 @@
Copyright (c) 2016, SilverStripe Limited Copyright (c) 2017, SilverStripe Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

13
phpunit.xml.dist Normal file
View File

@ -0,0 +1,13 @@
<phpunit bootstrap="cms/tests/bootstrap.php" colors="true">
<testsuite name="Default">
<directory>tests/</directory>
</testsuite>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src/</directory>
<exclude>
<directory suffix=".php">tests/</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@ -1,33 +1,33 @@
# Content Review module # Content Review module
[![Build Status](http://img.shields.io/travis/silverstripe/silverstripe-contentreview.svg?style=flat-square)](https://travis-ci.org/silverstripe/silverstripe-contentreview) [![Build status](https://travis-ci.org/silverstripe/silverstripe-contentreview.png?branch=master)](https://travis-ci.org/silverstripe/silverstripe-contentreview)
[![Code Quality](http://img.shields.io/scrutinizer/g/silverstripe/silverstripe-contentreview.svg?style=flat-square)](https://scrutinizer-ci.com/g/silverstripe/silverstripe-contentreview) [![Code quality](https://scrutinizer-ci.com/g/silverstripe/silverstripe-contentreview/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/silverstripe/silverstripe-contentreview/?branch=master)
[![Version](http://img.shields.io/packagist/v/silverstripe/contentreview.svg?style=flat-square)](https://packagist.org/packages/silverstripe/contentreview) [![Code coverage](https://codecov.io/gh/silverstripe/silverstripe-contentreview/branch/master/graph/badge.svg)](https://codecov.io/gh/silverstripe/silverstripe-contentreview)
[![License](http://img.shields.io/packagist/l/silverstripe/contentreview.svg?style=flat-square)](license.md) [![Version](http://img.shields.io/packagist/v/silverstripe/contentreview.svg)](https://packagist.org/packages/silverstripe/contentreview)
![helpfulrobot](https://helpfulrobot.io/silverstripe/contentreview/badge) [![License](http://img.shields.io/packagist/l/silverstripe/contentreview.svg)](license.md)
This module helps keep your website content accurate and up-to-date, which keeps your users happy. This module helps keep your website content accurate and up-to-date, which keeps your users happy.
It does so by sending reviewers reminder emails to go in and check the content. For a reviewer this It does so by sending reviewers reminder emails to go in and check the content. For a reviewer this
often includes checking links, grammar, factual information and look and feel. often includes checking links, grammar, factual information and look and feel.
There are two types of roles with this module. There are two types of roles with this module.
* Website owner; (typically assigned to the Administrator group) ensures that a website is accurate and up-to-date, by delegating responsibility to content reviewers. * Website owner; (typically assigned to the Administrator group) ensures that a website is accurate and up-to-date, by delegating responsibility to content reviewers.
* Content reviewer; responsible for keeping a website or part of a website accurate and up-to-date. * Content reviewer; responsible for keeping a website or part of a website accurate and up-to-date.
## Requirements ## Requirements
* SilverStripe ^3.1 * SilverStripe ^4.0
## Features ## Features
* Content reviewer will receive an email notification when a page is due for review. * Content reviewer will receive an email notification when a page is due for review.
* Content reviewer can mark a page as 'reviewed', and provide review notes. * Content reviewer can mark a page as 'reviewed', and provide review notes.
* Website owner can assign content reviewers to a page and set when the content should be reviewed. * Website owner can assign content reviewers to a page and set when the content should be reviewed.
* Website owner can see a report of pages and their reviewed status. * Website owner can see a report of pages and their reviewed status.
* Content reviewers can be assigned to a page, a page and all sub-pages, or globally. * Content reviewers can be assigned to a page, a page and all sub-pages, or globally.
* The content review schedule can be automatic, e.g. every month, and/or a specific date. * The content review schedule can be automatic, e.g. every month, and/or a specific date.
## Wishlist features ## Wishlist features

View File

@ -1,5 +1,12 @@
<?php <?php
namespace SilverStripe\ContentReview\Compatibility;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Subsites\Model\Subsite;
// @todo add translatable namespace
use Translatable;
/** /**
* This is a helper class which lets us do things with content review data without subsites * This is a helper class which lets us do things with content review data without subsites
* and translatable messing our SQL queries up. * and translatable messing our SQL queries up.
@ -25,12 +32,12 @@ class ContentReviewCompatability
self::TRANSLATABLE => null, self::TRANSLATABLE => null,
); );
if (ClassInfo::exists("Subsite")) { if (ClassInfo::exists(Subsite::class)) {
$compatibility[self::SUBSITES] = Subsite::$disable_subsite_filter; $compatibility[self::SUBSITES] = Subsite::$disable_subsite_filter;
Subsite::disable_subsite_filter(true); Subsite::disable_subsite_filter(true);
} }
if (ClassInfo::exists("Translatable")) { if (ClassInfo::exists(Translatable::class)) {
$compatibility[self::TRANSLATABLE] = Translatable::locale_filter_enabled(); $compatibility[self::TRANSLATABLE] = Translatable::locale_filter_enabled();
Translatable::disable_locale_filter(); Translatable::disable_locale_filter();
} }
@ -43,11 +50,11 @@ class ContentReviewCompatability
*/ */
public static function done(array $compatibility) public static function done(array $compatibility)
{ {
if (class_exists("Subsite")) { if (class_exists(Subsite::class)) {
Subsite::$disable_subsite_filter = $compatibility[self::SUBSITES]; Subsite::$disable_subsite_filter = $compatibility[self::SUBSITES];
} }
if (class_exists("Translatable")) { if (class_exists(Translatable::class)) {
Translatable::enable_locale_filter($compatibility[self::TRANSLATABLE]); Translatable::enable_locale_filter($compatibility[self::TRANSLATABLE]);
} }
} }

View File

@ -1,5 +1,14 @@
<?php <?php
namespace SilverStripe\ContentReview\Extensions;
use SilverStripe\Admin\LeftAndMainExtension;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Forms\Form;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
/** /**
* CMSPageEditController extension to receive the additional action button from * CMSPageEditController extension to receive the additional action button from
* SiteTreeContentReview::updateCMSActions() * SiteTreeContentReview::updateCMSActions()
@ -21,7 +30,7 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
* *
* @return string * @return string
* *
* @throws SS_HTTPResponse_Exception * @throws HTTPResponse_Exception
*/ */
public function savereview($data, Form $form) public function savereview($data, Form $form)
{ {
@ -30,14 +39,17 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
return Security::permissionFailure($this->owner); return Security::permissionFailure($this->owner);
} }
$notes = (!empty($data["ReviewNotes"]) ? $data["ReviewNotes"] : _t("ContentReview.NOCOMMENTS", "(no comments)")); $notes = (!empty($data["ReviewNotes"])
? $data["ReviewNotes"]
: _t("ContentReview.NOCOMMENTS", "(no comments)"));
$page->addReviewNote(Member::currentUser(), $notes); $page->addReviewNote(Member::currentUser(), $notes);
$page->advanceReviewDate(); $page->advanceReviewDate();
$this->owner->getResponse()->addHeader("X-Status", _t("ContentReview.REVIEWSUCCESSFUL", "Content reviewed successfully")); $this->owner->getResponse()
->addHeader("X-Status", _t("ContentReview.REVIEWSUCCESSFUL", "Content reviewed successfully"));
return $this->owner->redirectBack(); return $this->owner->redirectBack();
} }
/** /**
* Find the page this form is updating * Find the page this form is updating
* *
@ -48,7 +60,7 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
protected function findRecord($data) protected function findRecord($data)
{ {
if (empty($data["ID"])) { if (empty($data["ID"])) {
throw new SS_HTTPResponse_Exception("No record ID", 404); throw new HTTPResponse_Exception("No record ID", 404);
} }
$page = null; $page = null;
@ -58,7 +70,7 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
} }
if (!$page || !$page->ID) { if (!$page || !$page->ID) {
throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404); throw new HTTPResponse_Exception("Bad record ID #{$id}", 404);
} }
return $page; return $page;

View File

@ -1,5 +1,20 @@
<?php <?php
namespace SilverStripe\ContentReview\Extensions;
use SilverStripe\Core\Config\Config;
use SilverStripe\Control\Email\Email;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\Security\Permission;
/** /**
* This extensions add a default schema for new pages and pages without a content * This extensions add a default schema for new pages and pages without a content
* review setting. * review setting.
@ -36,8 +51,8 @@ class ContentReviewDefaultSettings extends DataExtension
* @var array * @var array
*/ */
private static $many_many = array( private static $many_many = array(
'ContentReviewGroups' => 'Group', 'ContentReviewGroups' => Group::class,
'ContentReviewUsers' => 'Member', 'ContentReviewUsers' => Member::class,
); );
/** /**
@ -49,7 +64,7 @@ class ContentReviewDefaultSettings extends DataExtension
* *
* @var string * @var string
*/ */
private static $content_review_template = 'ContentReviewEmail'; private static $content_review_template = 'SilverStripe\\ContentReview\\ContentReviewEmail';
/** /**
* @return string * @return string
@ -121,7 +136,6 @@ class ContentReviewDefaultSettings extends DataExtension
asort($usersMap); asort($usersMap);
$userField = ListboxField::create('OwnerUsers', _t('ContentReview.PAGEOWNERUSERS', 'Users'), $usersMap) $userField = ListboxField::create('OwnerUsers', _t('ContentReview.PAGEOWNERUSERS', 'Users'), $usersMap)
->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users')) ->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users'))
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
@ -137,7 +151,6 @@ class ContentReviewDefaultSettings extends DataExtension
asort($groupsMap); asort($groupsMap);
$groupField = ListboxField::create('OwnerGroups', _t('ContentReview.PAGEOWNERGROUPS', 'Groups'), $groupsMap) $groupField = ListboxField::create('OwnerGroups', _t('ContentReview.PAGEOWNERGROUPS', 'Groups'), $groupsMap)
->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups')) ->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups'))
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews'));
@ -151,7 +164,10 @@ class ContentReviewDefaultSettings extends DataExtension
->setRightTitle(_t('Review.EMAILFROM_RIGHTTITLE', 'e.g: do-not-reply@site.com')), ->setRightTitle(_t('Review.EMAILFROM_RIGHTTITLE', 'e.g: do-not-reply@site.com')),
TextField::create('ReviewSubject', _t('ContentReview.EMAILSUBJECT', 'Subject line')), TextField::create('ReviewSubject', _t('ContentReview.EMAILSUBJECT', 'Subject line')),
TextAreaField::create('ReviewBody', _t('ContentReview.EMAILTEMPLATE', 'Email template')), TextAreaField::create('ReviewBody', _t('ContentReview.EMAILTEMPLATE', 'Email template')),
LiteralField::create('TemplateHelp', $this->owner->renderWith('ContentReviewAdminHelp')), LiteralField::create(
'TemplateHelp',
$this->owner->renderWith('SilverStripe\\ContentReview\\ContentReviewAdminHelp')
),
) )
); );
} }
@ -200,7 +216,7 @@ class ContentReviewDefaultSettings extends DataExtension
} }
// Fall back to admin email // Fall back to admin email
return Config::inst()->get('Email', 'admin_email'); return Config::inst()->get(Email::class, 'admin_email');
} }
/** /**
@ -217,7 +233,7 @@ class ContentReviewDefaultSettings extends DataExtension
return $value; return $value;
} }
// fallback to default value // fallback to default value
$defaults = $this->owner->config()->defaults; $defaults = $this->owner->config()->get('defaults');
if (isset($defaults[$field])) { if (isset($defaults[$field])) {
return $defaults[$field]; return $defaults[$field];
} }

View File

@ -1,5 +1,10 @@
<?php <?php
namespace SilverStripe\ContentReview\Extensions;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ORM\DataExtension;
/** /**
* Description of GroupContentReview. * Description of GroupContentReview.
*/ */
@ -9,6 +14,6 @@ class ContentReviewOwner extends DataExtension
* @var array * @var array
*/ */
private static $many_many = array( private static $many_many = array(
"SiteTreeContentReview" => "SiteTree", "SiteTreeContentReview" => SiteTree::class,
); );
} }

View File

@ -1,5 +1,46 @@
<?php <?php
namespace SilverStripe\ContentReview\Extensions;
use Exception;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ContentReview\Jobs\ContentReviewNotificationJob;
use SilverStripe\ContentReview\Models\ContentReviewLog;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\DateField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\Forms\HeaderField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataExtension;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBDate;
use SilverStripe\ORM\SS_List;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\Security\Permission;
use SilverStripe\Security\PermissionProvider;
use SilverStripe\Security\Security;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\View\Requirements;
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
use Symbiote\QueuedJobs\Services\QueuedJobService;
/** /**
* Set dates at which content needs to be reviewed and provide a report and emails to alert * Set dates at which content needs to be reviewed and provide a report and emails to alert
* to content needing review. * to content needing review.
@ -38,15 +79,15 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
* @var array * @var array
*/ */
private static $has_many = array( private static $has_many = array(
"ReviewLogs" => "ContentReviewLog", "ReviewLogs" => ContentReviewLog::class,
); );
/** /**
* @var array * @var array
*/ */
private static $belongs_many_many = array( private static $belongs_many_many = array(
"ContentReviewGroups" => "Group", "ContentReviewGroups" => Group::class,
"ContentReviewUsers" => "Member", "ContentReviewUsers" => Member::class,
); );
/** /**
@ -70,7 +111,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public static function get_schedule() public static function get_schedule()
{ {
return self::$schedule; return Config::inst()->get(static::class, 'schedule');
} }
/** /**
@ -99,9 +140,10 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
array_unique($groupIDs); array_unique($groupIDs);
if (count($groupIDs)) { if (count($groupIDs)) {
$groupMembers = DataObject::get("Member")->where("\"Group\".\"ID\" IN (" . implode(",", $groupIDs) . ")") $groupMembers = DataObject::get(Member::class)->where("\"Group\".\"ID\" IN (" . implode(",", $groupIDs) . ")")
->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"") ->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"")
->leftJoin("Group", "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\""); /** @skipUpgrade */
->leftJoin('Group', "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\"");
$contentReviewOwners->merge($groupMembers); $contentReviewOwners->merge($groupMembers);
} }
@ -118,8 +160,8 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public function updateCMSActions(FieldList $actions) public function updateCMSActions(FieldList $actions)
{ {
if ($this->canBeReviewedBy(Member::currentUser())) { if ($this->canBeReviewedBy(Security::getCurrentUser())) {
Requirements::css("contentreview/css/contentreview.css"); Requirements::css("silverstripe/contentreview:css/contentreview.css");
$reviewTitle = LiteralField::create( $reviewTitle = LiteralField::create(
"ReviewContentNotesLabel", "ReviewContentNotesLabel",
@ -155,8 +197,8 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
$page = $this->owner; $page = $this->owner;
} }
if ($page->obj("NextReviewDate")->exists()) { if ($page->obj('NextReviewDate')->exists()) {
return $page->obj("NextReviewDate"); return $page->obj('NextReviewDate');
} }
$options = $this->owner->getOptions(); $options = $this->owner->getOptions();
@ -170,9 +212,9 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
} }
// Failover to check on ReviewPeriodDays + LastEdited // Failover to check on ReviewPeriodDays + LastEdited
$nextReviewUnixSec = strtotime(" + " . $options->ReviewPeriodDays . " days", SS_Datetime::now()->format("U")); $nextReviewUnixSec = strtotime(' + ' . $options->ReviewPeriodDays . ' days', DBDatetime::now()->getTimestamp());
$date = Date::create("NextReviewDate"); $date = DBDate::create('NextReviewDate');
$date->setValue(date("Y-m-d H:i:s", $nextReviewUnixSec)); $date->setValue($nextReviewUnixSec);
return $date; return $date;
} }
@ -205,7 +247,6 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
// $page is inheriting it's settings from it's parent, find // $page is inheriting it's settings from it's parent, find
// the first valid parent with a valid setting // the first valid parent with a valid setting
while ($parent = $page->Parent()) { while ($parent = $page->Parent()) {
// Root page, use site config // Root page, use site config
if (!$parent->exists()) { if (!$parent->exists()) {
return SiteConfig::current_site_config(); return SiteConfig::current_site_config();
@ -254,7 +295,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public function getEditorName() public function getEditorName()
{ {
$member = Member::currentUser(); $member = Security::getCurrentUser();
if ($member) { if ($member) {
return $member->getTitle(); return $member->getTitle();
@ -298,7 +339,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public function updateSettingsFields(FieldList $fields) public function updateSettingsFields(FieldList $fields)
{ {
Requirements::javascript("contentreview/javascript/contentreview.js"); Requirements::javascript("silverstripe/contentreview:javascript/contentreview.js");
// Display read-only version only // Display read-only version only
if (!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) { if (!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
@ -313,8 +354,8 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
} }
$logConfig = GridFieldConfig::create() $logConfig = GridFieldConfig::create()
->addComponent(new GridFieldSortableHeader()) ->addComponent(Injector::inst()->create(GridFieldSortableHeader::class))
->addComponent($logColumns = new GridFieldDataColumns()); ->addComponent($logColumns = Injector::inst()->create(GridFieldDataColumns::class));
// Cast the value to the users preferred date format // Cast the value to the users preferred date format
$logColumns->setFieldCasting(array( $logColumns->setFieldCasting(array(
@ -351,7 +392,6 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
asort($usersMap); asort($usersMap);
$userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap) $userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
->setMultiple(true)
->addExtraClass('custom-setting') ->addExtraClass('custom-setting')
->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users")) ->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users"))
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
@ -364,15 +404,11 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
asort($groupsMap); asort($groupsMap);
$groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap) $groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
->setMultiple(true)
->addExtraClass('custom-setting') ->addExtraClass('custom-setting')
->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups")) ->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups"))
->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews")); ->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));
$reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date")) $reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"))
->setConfig("showcalendar", true)
->setConfig("dateformat", "yyyy-MM-dd")
->setConfig("datavalueformat", "yyyy-MM-dd")
->setDescription(_t("ContentReview.NEXTREVIEWDATADESCRIPTION", "Leave blank for no review")); ->setDescription(_t("ContentReview.NEXTREVIEWDATADESCRIPTION", "Leave blank for no review"));
$reviewFrequency = DropdownField::create( $reviewFrequency = DropdownField::create(
@ -386,7 +422,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
$notesField = GridField::create("ReviewNotes", "Review Notes", $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create()); $notesField = GridField::create("ReviewNotes", "Review Notes", $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create());
$fields->addFieldsToTab("Root.ContentReview", array( $fields->addFieldsToTab("Root.ContentReview", array(
new HeaderField(_t("ContentReview.REVIEWHEADER", "Content review"), 2), HeaderField::create('ContentReviewHeader', _t("ContentReview.REVIEWHEADER", "Content review"), 2),
$viewersOptionsField, $viewersOptionsField,
CompositeField::create( CompositeField::create(
$userField, $userField,
@ -422,17 +458,20 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public function advanceReviewDate() public function advanceReviewDate()
{ {
$nextDate = false; $nextDateTimestamp = false;
$options = $this->getOptions(); $options = $this->getOptions();
if ($options && $options->ReviewPeriodDays) { if ($options && $options->ReviewPeriodDays) {
$nextDate = date('Y-m-d', strtotime('+ ' . $options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U'))); $nextDateTimestamp = strtotime(
' + ' . $options->ReviewPeriodDays . ' days',
DBDatetime::now()->getTimestamp()
);
$this->owner->NextReviewDate = $nextDate; $this->owner->NextReviewDate = DBDate::create()->setValue($nextDateTimestamp)->Format('y-MM-dd');
$this->owner->write(); $this->owner->write();
} }
return (bool) $nextDate; return (bool) $nextDateTimestamp;
} }
/** /**
@ -453,12 +492,12 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
} }
$options = $this->getOptions(); $options = $this->getOptions();
if (!$options) { if (!$options) {
return false; return false;
} }
if (!$options || !$options->hasExtension($this->class)) { if (!$options || !$options->hasExtension(__CLASS__)) {
return false; return false;
} }
@ -488,7 +527,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
{ {
// Only update if DB fields have been changed // Only update if DB fields have been changed
$changedFields = $this->owner->getChangedFields(true, 2); $changedFields = $this->owner->getChangedFields(true, 2);
if($changedFields) { if ($changedFields) {
$this->owner->LastEditedByName = $this->owner->getEditorName(); $this->owner->LastEditedByName = $this->owner->getEditorName();
$this->owner->OwnerNames = $this->owner->getOwnerNames(); $this->owner->OwnerNames = $this->owner->getOwnerNames();
} }
@ -518,9 +557,12 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
// parent page change its review period // parent page change its review period
// && !$this->owner->isChanged('ContentReviewType', 2) // && !$this->owner->isChanged('ContentReviewType', 2)
if ($this->owner->isChanged("ReviewPeriodDays", 2)) { if ($this->owner->isChanged('ReviewPeriodDays', 2)) {
$nextReviewUnixSec = strtotime(" + " . $this->owner->ReviewPeriodDays . " days", SS_Datetime::now()->format("U")); $nextReviewUnixSec = strtotime(
$this->owner->NextReviewDate = date("Y-m-d", $nextReviewUnixSec); ' + ' . $this->owner->ReviewPeriodDays . ' days',
DBDatetime::now()->getTimestamp()
);
$this->owner->NextReviewDate = DBDate::create()->setValue($nextReviewUnixSec)->Format('y-MM-dd');
} }
} }
@ -591,17 +633,17 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
*/ */
public function requireDefaultRecords() public function requireDefaultRecords()
{ {
if (class_exists("ContentReviewNotificationJob")) { if (class_exists(ContentReviewNotificationJob::class)) {
// Ensure there is not already a job queued // Ensure there is not already a job queued
if (QueuedJobDescriptor::get()->filter("Implementation", "ContentReviewNotificationJob")->first()) { if (QueuedJobDescriptor::get()->filter("Implementation", ContentReviewNotificationJob::class)->first()) {
return; return;
} }
$nextRun = new ContentReviewNotificationJob(); $nextRun = Injector::inst()->create(ContentReviewNotificationJob::class);
$runHour = Config::inst()->get("ContentReviewNotificationJob", "first_run_hour"); $runHour = Config::inst()->get(ContentReviewNotificationJob::class, "first_run_hour");
$firstRunTime = date("Y-m-d H:i:s", mktime($runHour, 0, 0, date("m"), date("d") + 1, date("y"))); $firstRunTime = date("Y-m-d H:i:s", mktime($runHour, 0, 0, date("m"), date("d") + 1, date("y")));
singleton("QueuedJobService")->queueJob( singleton(QueuedJobService::class)->queueJob(
$nextRun, $nextRun,
$firstRunTime $firstRunTime
); );

View File

@ -1,6 +1,15 @@
<?php <?php
if (!class_exists("AbstractQueuedJob")) { namespace SilverStripe\ContentReview\Jobs;
use SilverStripe\ContentReview\Tasks\ContentReviewEmails;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Config\Config;
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;
if (!class_exists(AbstractQueuedJob::class)) {
return; return;
} }
@ -76,7 +85,7 @@ class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJo
$this->queueNextRun(); $this->queueNextRun();
$task = new ContentReviewEmails(); $task = new ContentReviewEmails();
$task->run(new SS_HTTPRequest("GET", "/dev/tasks/ContentReviewEmails")); $task->run(new HTTPRequest("GET", "/dev/tasks/ContentReviewEmails"));
$this->currentStep = 1; $this->currentStep = 1;
$this->isComplete = true; $this->isComplete = true;
@ -98,7 +107,7 @@ class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJo
date("Y") date("Y")
); );
singleton("QueuedJobService")->queueJob( singleton(QueuedJobService::class)->queueJob(
$nextRun, $nextRun,
date("Y-m-d H:i:s", $nextRunTime) date("Y-m-d H:i:s", $nextRunTime)
); );

View File

@ -1,5 +1,12 @@
<?php <?php
namespace SilverStripe\ContentReview\Models;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
class ContentReviewLog extends DataObject class ContentReviewLog extends DataObject
{ {
/** /**
@ -13,8 +20,8 @@ class ContentReviewLog extends DataObject
* @var array * @var array
*/ */
private static $has_one = array( private static $has_one = array(
"Reviewer" => "Member", "Reviewer" => Member::class,
"SiteTree" => "SiteTree", "SiteTree" => SiteTree::class,
); );
/** /**
@ -31,6 +38,8 @@ class ContentReviewLog extends DataObject
*/ */
private static $default_sort = "Created DESC"; private static $default_sort = "Created DESC";
private static $table_name = 'ContentReviewLog';
/** /**
* @param mixed $member * @param mixed $member
* *
@ -38,6 +47,6 @@ class ContentReviewLog extends DataObject
*/ */
public function canView($member = null) public function canView($member = null)
{ {
return (bool) Member::currentUser(); return (bool) Security::getCurrentUser();
} }
} }

View File

@ -1,11 +1,29 @@
<?php <?php
require_once "Zend/Date.php"; namespace SilverStripe\ContentReview\Reports;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\CMS\Model\VirtualPage;
use SilverStripe\ContentReview\Compatibility\ContentReviewCompatability;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\DateField;
use SilverStripe\Forms\FieldList;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Reports\Report;
use SilverStripe\Security\Security;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Versioned\Versioned;
/** /**
* Show all pages that need to be reviewed. * Show all pages that need to be reviewed.
*/ */
class PagesDueForReviewReport extends SS_Report class PagesDueForReviewReport extends Report
{ {
/** /**
* @return string * @return string
@ -20,21 +38,36 @@ class PagesDueForReviewReport extends SS_Report
*/ */
public function parameterFields() public function parameterFields()
{ {
$filtersList = new FieldList(); $filtersList = FieldList::create();
$filtersList->push( $filtersList->push(
DateField::create("ReviewDateAfter", _t("PagesDueForReviewReport.REVIEWDATEAFTER", "Review date after or on")) DateField::create(
->setConfig("showcalendar", true) "ReviewDateAfter",
_t("PagesDueForReviewReport.REVIEWDATEAFTER", "Review date after or on")
)
); );
$filtersList->push( $filtersList->push(
DateField::create("ReviewDateBefore", _t("PagesDueForReviewReport.REVIEWDATEBEFORE", "Review date before or on"), date("d/m/Y", strtotime("midnight"))) DateField::create(
->setConfig("showcalendar", true) "ReviewDateBefore",
_t("PagesDueForReviewReport.REVIEWDATEBEFORE", "Review date before or on"),
date("d/m/Y", strtotime("midnight"))
)
); );
$filtersList->push(new CheckboxField("ShowVirtualPages", _t("PagesDueForReviewReport.SHOWVIRTUALPAGES", "Show Virtual Pages"))); $filtersList->push(
CheckboxField::create(
"ShowVirtualPages",
_t("PagesDueForReviewReport.SHOWVIRTUALPAGES", "Show Virtual Pages")
)
);
$filtersList->push(new CheckboxField("OnlyMyPages", _t("PagesDueForReviewReport.ONLYMYPAGES", "Only Show pages assigned to me"))); $filtersList->push(
CheckboxField::create(
"OnlyMyPages",
_t("PagesDueForReviewReport.ONLYMYPAGES", "Only Show pages assigned to me")
)
);
return $filtersList; return $filtersList;
} }
@ -44,7 +77,7 @@ class PagesDueForReviewReport extends SS_Report
*/ */
public function columns() public function columns()
{ {
$linkBase = singleton("CMSPageEditController")->Link("show"); $linkBase = singleton(CMSPageEditController::class)->Link("show");
$linkPath = parse_url($linkBase, PHP_URL_PATH); $linkPath = parse_url($linkBase, PHP_URL_PATH);
$linkQuery = parse_url($linkBase, PHP_URL_QUERY); $linkQuery = parse_url($linkBase, PHP_URL_QUERY);
@ -80,7 +113,8 @@ class PagesDueForReviewReport extends SS_Report
$liveLink = $item->AbsoluteLiveLink; $liveLink = $item->AbsoluteLiveLink;
$stageLink = $item->AbsoluteLink(); $stageLink = $item->AbsoluteLink();
return sprintf("%s <a href='%s'>%s</a>", return sprintf(
"%s <a href='%s'>%s</a>",
$stageLink, $stageLink,
$liveLink ? $liveLink : $stageLink . "?stage=Stage", $liveLink ? $liveLink : $stageLink . "?stage=Stage",
$liveLink ? "(live)" : "(draft)" $liveLink ? "(live)" : "(draft)"
@ -120,36 +154,50 @@ class PagesDueForReviewReport extends SS_Report
*/ */
public function sourceRecords($params = array()) public function sourceRecords($params = array())
{ {
Versioned::reading_stage("Stage"); Versioned::set_stage(Versioned::DRAFT);
$records = SiteTree::get(); $records = SiteTree::get();
$compatibility = ContentReviewCompatability::start(); $compatibility = ContentReviewCompatability::start();
if (empty($params["ReviewDateBefore"]) && empty($params["ReviewDateAfter"])) { if (empty($params['ReviewDateBefore']) && empty($params['ReviewDateAfter'])) {
// If there's no review dates set, default to all pages due for review now // If there's no review dates set, default to all pages due for review now
$reviewDate = new Zend_Date(SS_Datetime::now()->Format("U")); $records = $records->where(
$reviewDate->add(1, Zend_Date::DAY); sprintf(
$records = $records->where(sprintf('"NextReviewDate" < \'%s\'', $reviewDate->toString("YYYY-MM-dd"))); '"NextReviewDate" < \'%s\'',
DBDatetime::now()->Format('y-MM-dd')
)
);
} else { } else {
// Review date before // Review date before
if (!empty($params['ReviewDateBefore'])) { if (!empty($params['ReviewDateBefore'])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here // TODO Get value from DateField->dataValue() once we have access to form elements here
$reviewDate = new Zend_Date($params["ReviewDateBefore"], Config::inst()->get("i18n", "date_format")); $nextReviewUnixSec = strtotime(
$reviewDate->add(1, Zend_Date::DAY); ' + 1 day',
$records = $records->where(sprintf("\"NextReviewDate\" < '%s'", $reviewDate->toString("YYYY-MM-dd"))); strtotime($params['ReviewDateBefore'])
);
$records = $records->where(
sprintf(
"\"NextReviewDate\" < '%s'",
DBDatetime::create()->setValue($nextReviewUnixSec)->Format('y-MM-dd')
)
);
} }
// Review date after // Review date after
if (!empty($params["ReviewDateAfter"])) { if (!empty($params['ReviewDateAfter'])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here // TODO Get value from DateField->dataValue() once we have access to form elements here
$reviewDate = new Zend_Date($params["ReviewDateAfter"], Config::inst()->get("i18n", "date_format")); $records = $records->where(
$records = $records->where(sprintf("\"NextReviewDate\" >= '%s'", $reviewDate->toString("YYYY-MM-dd"))); sprintf(
"\"NextReviewDate\" >= '%s'",
DBDatetime::create()->setValue(strtotime($params['ReviewDateAfter']))->Format('y-MM-dd')
)
);
} }
} }
// Show virtual pages? // Show virtual pages?
if (empty($params["ShowVirtualPages"])) { if (empty($params["ShowVirtualPages"])) {
$virtualPageClasses = ClassInfo::subclassesFor("VirtualPage"); $virtualPageClasses = ClassInfo::subclassesFor(VirtualPage::class);
$records = $records->where(sprintf( $records = $records->where(sprintf(
"\"SiteTree\".\"ClassName\" NOT IN ('%s')", "\"SiteTree\".\"ClassName\" NOT IN ('%s')",
implode("','", array_values($virtualPageClasses)) implode("','", array_values($virtualPageClasses))
@ -157,15 +205,15 @@ class PagesDueForReviewReport extends SS_Report
} }
// Owner dropdown // Owner dropdown
if (!empty($params["ContentReviewOwner"])) { if (!empty($params[ContentReviewOwner::class])) {
$ownerNames = Convert::raw2sql($params["ContentReviewOwner"]); $ownerNames = Convert::raw2sql($params[ContentReviewOwner::class]);
$records = $records->filter("OwnerNames:PartialMatch", $ownerNames); $records = $records->filter("OwnerNames:PartialMatch", $ownerNames);
} }
// Only show pages assigned to the current user? // Only show pages assigned to the current user?
// This come last because it transforms $records to an ArrayList. // This come last because it transforms $records to an ArrayList.
if (!empty($params["OnlyMyPages"])) { if (!empty($params["OnlyMyPages"])) {
$currentUser = Member::currentUser(); $currentUser = Security::getCurrentUser();
$records = $records->filterByCallback(function ($page) use ($currentUser) { $records = $records->filterByCallback(function ($page) use ($currentUser) {
$options = $page->getOptions(); $options = $page->getOptions();

View File

@ -1,11 +1,24 @@
<?php <?php
require_once "Zend/Date.php"; namespace SilverStripe\ContentReview\Reports;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\FieldList;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\CMS\Model\VirtualPage;
use SilverStripe\ContentReview\Compatibility\ContentReviewCompatability;
use SilverStripe\Core\ClassInfo;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\Reports\Report;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Versioned\Versioned;
/** /**
* Show all pages that need to be reviewed. * Show all pages that need to be reviewed.
*/ */
class PagesWithoutReviewScheduleReport extends SS_Report class PagesWithoutReviewScheduleReport extends Report
{ {
/** /**
* @return string * @return string
@ -20,8 +33,8 @@ class PagesWithoutReviewScheduleReport extends SS_Report
*/ */
public function parameterFields() public function parameterFields()
{ {
$params = new FieldList(); $params = FieldList::create();
$params->push(new CheckboxField("ShowVirtualPages", "Show Virtual Pages")); $params->push(CheckboxField::create("ShowVirtualPages", "Show Virtual Pages"));
return $params; return $params;
} }
@ -31,7 +44,7 @@ class PagesWithoutReviewScheduleReport extends SS_Report
*/ */
public function columns() public function columns()
{ {
$linkBase = singleton("CMSPageEditController")->Link("show"); $linkBase = singleton(CMSPageEditController::class)->Link("show");
$linkPath = parse_url($linkBase, PHP_URL_PATH); $linkPath = parse_url($linkBase, PHP_URL_PATH);
$linkQuery = parse_url($linkBase, PHP_URL_QUERY); $linkQuery = parse_url($linkBase, PHP_URL_QUERY);
@ -54,7 +67,8 @@ class PagesWithoutReviewScheduleReport extends SS_Report
$liveLink = $item->AbsoluteLiveLink; $liveLink = $item->AbsoluteLiveLink;
$stageLink = $item->AbsoluteLink(); $stageLink = $item->AbsoluteLink();
return sprintf("%s <a href='%s'>%s</a>", return sprintf(
"%s <a href='%s'>%s</a>",
$stageLink, $stageLink,
$liveLink ? $liveLink : $stageLink . "?stage=Stage", $liveLink ? $liveLink : $stageLink . "?stage=Stage",
$liveLink ? "(live)" : "(draft)" $liveLink ? "(live)" : "(draft)"
@ -94,7 +108,7 @@ class PagesWithoutReviewScheduleReport extends SS_Report
*/ */
public function sourceRecords($params = array()) public function sourceRecords($params = array())
{ {
Versioned::reading_stage("Stage"); Versioned::set_stage(Versioned::DRAFT);
$records = SiteTree::get(); $records = SiteTree::get();
$compatibility = ContentReviewCompatability::start(); $compatibility = ContentReviewCompatability::start();
@ -103,7 +117,7 @@ class PagesWithoutReviewScheduleReport extends SS_Report
// Show virtual pages? // Show virtual pages?
if (empty($params["ShowVirtualPages"])) { if (empty($params["ShowVirtualPages"])) {
$virtualPageClasses = ClassInfo::subclassesFor("VirtualPage"); $virtualPageClasses = ClassInfo::subclassesFor(VirtualPage::class);
$records = $records->where(sprintf( $records = $records->where(sprintf(
"\"SiteTree\".\"ClassName\" NOT IN ('%s')", "\"SiteTree\".\"ClassName\" NOT IN ('%s')",
implode("','", array_values($virtualPageClasses)) implode("','", array_values($virtualPageClasses))
@ -114,7 +128,7 @@ class PagesWithoutReviewScheduleReport extends SS_Report
$records = $records->toArray(); $records = $records->toArray();
// Trim out calculated values // Trim out calculated values
$list = new ArrayList(); $list = ArrayList::create();
foreach ($records as $record) { foreach ($records as $record) {
if (!$this->hasReviewSchedule($record)) { if (!$this->hasReviewSchedule($record)) {
$list->push($record); $list->push($record);

View File

@ -1,12 +1,28 @@
<?php <?php
namespace SilverStripe\ContentReview\Tasks;
use Page;
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;
/** /**
* Daily task to send emails to the owners of content items when the review date rolls around. * Daily task to send emails to the owners of content items when the review date rolls around.
*/ */
class ContentReviewEmails extends BuildTask class ContentReviewEmails extends BuildTask
{ {
/** /**
* @param SS_HTTPRequest $request * @param HTTPRequest $request
*/ */
public function run($request) public function run($request)
{ {
@ -14,7 +30,7 @@ class ContentReviewEmails extends BuildTask
// First grab all the pages with a custom setting // First grab all the pages with a custom setting
$pages = Page::get() $pages = Page::get()
->filter('NextReviewDate:LessThanOrEqual', SS_Datetime::now()->URLDate()); ->filter('NextReviewDate:LessThanOrEqual', DBDatetime::now()->URLDate());
$overduePages = $this->getOverduePagesForOwners($pages); $overduePages = $this->getOverduePagesForOwners($pages);
@ -28,11 +44,11 @@ class ContentReviewEmails extends BuildTask
} }
/** /**
* @param SS_list $pages * @param SS_List $pages
* *
* @return array * @return array
*/ */
protected function getOverduePagesForOwners(SS_list $pages) protected function getOverduePagesForOwners(SS_List $pages)
{ {
$overduePages = array(); $overduePages = array();
@ -45,7 +61,7 @@ class ContentReviewEmails extends BuildTask
foreach ($option->ContentReviewOwners() as $owner) { foreach ($option->ContentReviewOwners() as $owner) {
if (!isset($overduePages[$owner->ID])) { if (!isset($overduePages[$owner->ID])) {
$overduePages[$owner->ID] = new ArrayList(); $overduePages[$owner->ID] = ArrayList::create();
} }
$overduePages[$owner->ID]->push($page); $overduePages[$owner->ID]->push($page);
@ -67,7 +83,7 @@ class ContentReviewEmails extends BuildTask
$templateVariables = $this->getTemplateVariables($owner, $siteConfig, $pages); $templateVariables = $this->getTemplateVariables($owner, $siteConfig, $pages);
// Build email // Build email
$email = new Email(); $email = Email::create();
$email->setTo($owner->Email); $email->setTo($owner->Email);
$email->setFrom($siteConfig->ReviewFrom); $email->setFrom($siteConfig->ReviewFrom);
$email->setSubject($siteConfig->ReviewSubject); $email->setSubject($siteConfig->ReviewSubject);
@ -76,13 +92,17 @@ class ContentReviewEmails extends BuildTask
$body = $this->getEmailBody($siteConfig, $templateVariables); $body = $this->getEmailBody($siteConfig, $templateVariables);
// Populate mail body with fixed template // Populate mail body with fixed template
$email->setTemplate($siteConfig->config()->content_review_template); $email->setHTMLTemplate($siteConfig->config()->get('content_review_template'));
$email->populateTemplate($templateVariables); $email->setData(
$email->populateTemplate(array( array_merge(
'EmailBody' => $body, $templateVariables,
'Recipient' => $owner, [
'Pages' => $pages, 'EmailBody' => $body,
)); 'Recipient' => $owner,
'Pages' => $pages,
]
)
);
$email->send(); $email->send();
} }
@ -97,7 +117,7 @@ class ContentReviewEmails extends BuildTask
protected function getEmailBody($config, $variables) protected function getEmailBody($config, $variables)
{ {
$template = SSViewer::fromString($config->ReviewBody); $template = SSViewer::fromString($config->ReviewBody);
$value = $template->process(new ArrayData($variables)); $value = $template->process(ArrayData::create($variables));
// Cast to HTML // Cast to HTML
return DBField::create_field('HTMLText', (string) $value); return DBField::create_field('HTMLText', (string) $value);
@ -117,13 +137,13 @@ class ContentReviewEmails extends BuildTask
*/ */
protected function getTemplateVariables($recipient, $config, $pages) protected function getTemplateVariables($recipient, $config, $pages)
{ {
return array( return [
'Subject' => $config->ReviewSubject, 'Subject' => $config->ReviewSubject,
'PagesCount' => $pages->count(), 'PagesCount' => $pages->count(),
'FromEmail' => $config->ReviewFrom, 'FromEmail' => $config->ReviewFrom,
'ToFirstName' => $recipient->FirstName, 'ToFirstName' => $recipient->FirstName,
'ToSurname' => $recipient->Surname, 'ToSurname' => $recipient->Surname,
'ToEmail' => $recipient->Email, 'ToEmail' => $recipient->Email,
); ];
} }
} }

View File

@ -1,12 +1,18 @@
<?php <?php
namespace SilverStripe\ContentReview\Tasks;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Dev\BuildTask;
use SilverStripe\ORM\DB;
/** /**
* Task which migrates the ContentReview Module's SiteTree->OwnerID column to a new column name. * Task which migrates the ContentReview Module's SiteTree->OwnerID column to a new column name.
*/ */
class ContentReviewOwnerMigrationTask extends BuildTask class ContentReviewOwnerMigrationTask extends BuildTask
{ {
/** /**
* @param SS_HTTPRequest $request * @param HTTPRequest $request
*/ */
public function run($request) public function run($request)
{ {
@ -20,7 +26,7 @@ class ContentReviewOwnerMigrationTask extends BuildTask
DB::query("UPDATE \"SiteTree_versions\" SET \"ContentReviewOwnerID\" = \"OwnerID\""); DB::query("UPDATE \"SiteTree_versions\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
DB::query("ALTER TABLE \"SiteTree\" DROP COLUMN \"OwnerID\""); DB::query("ALTER TABLE \"SiteTree\" DROP COLUMN \"OwnerID\"");
DB::query("ALTER TABLE \"SiteTree_Live\" DROP COLUMN \"OwnerID\""); DB::query("ALTER TABLE \"SiteTree_Live\" DROP COLUMN \"OwnerID\"");
DB::query("ALTER TABLE \"SiteTree_versions\" DROP COLUMN \"OwnerID\""); DB::query("ALTER TABLE \"SiteTree_Versions\" DROP COLUMN \"OwnerID\"");
echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>"; echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>";
} }
} }

View File

@ -9,15 +9,15 @@
$EmailBody $EmailBody
</td> </td>
</tr> </tr>
<% loop Pages %> <% loop $Pages %>
<tr> <tr>
<td valign="top">$Title</td> <td valign="top">$Title</td>
<td><a href="{$BaseURL}admin/pages/edit/show/$ID"><% _t('ContentReviewEmails.REVIEWPAGELINK','Review the page in the CMS') %></a><br /> <td><a href="{$BaseURL}admin/pages/edit/show/$ID"><%t ContentReviewEmails.REVIEWPAGELINK 'Review the page in the CMS' %></a><br />
<a href="$AbsoluteLink"><% _t('ContentReviewEmails.VIEWPUBLISHEDLINK','View this page on the website') %></a> <a href="$AbsoluteLink"><%t ContentReviewEmails.VIEWPUBLISHEDLINK 'View this page on the website' %></a>
</td> </td>
</tr> </tr>
<% end_loop %> <% end_loop %>
</tbody> </tbody>
</table> </table>
</body> </body>
</html> </html>

View File

@ -1,5 +1,12 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\CMS\Model\SiteTree;
// @todo add translatable namespace
use Translatable;
/** /**
* Extend this class when writing unit tests which are compatible with other modules. * Extend this class when writing unit tests which are compatible with other modules.
* All compatibility code goes here. * All compatibility code goes here.
@ -11,7 +18,7 @@ abstract class ContentReviewBaseTest extends FunctionalTest
*/ */
protected $translatableEnabledBefore; protected $translatableEnabledBefore;
public function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();
@ -21,21 +28,21 @@ abstract class ContentReviewBaseTest extends FunctionalTest
* (e.g. $this->post()) do not seem to get passed the tester's locale, but instead fallback to the default locale. * (e.g. $this->post()) do not seem to get passed the tester's locale, but instead fallback to the default locale.
* *
* So we set the pages locale to be the default locale, which will then match any subsequent requests. * So we set the pages locale to be the default locale, which will then match any subsequent requests.
* *
* If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call * If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call
* self::compat() on the page, for the same reasons as above. * self::compat() on the page, for the same reasons as above.
*/ */
if (class_exists("Translatable")) { if (class_exists(Translatable::class)) {
$this->translatableEnabledBefore = SiteTree::has_extension("Translatable"); $this->translatableEnabledBefore = SiteTree::has_extension(Translatable::class);
SiteTree::remove_extension("Translatable"); SiteTree::remove_extension(Translatable::class);
} }
} }
public function tearDown() protected function tearDown()
{ {
if (class_exists("Translatable")) { if (class_exists(Translatable::class)) {
if ($this->translatableEnabledBefore) { if ($this->translatableEnabledBefore) {
SiteTree::add_extension("Translatable"); SiteTree::add_extension(Translatable::class);
} }
} }

View File

@ -1,5 +1,22 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use Page;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ContentReview\Extensions\SiteTreeContentReview;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension;
use SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\SiteConfig\SiteConfig;
/** /**
* @mixin PHPUnit_Framework_TestCase * @mixin PHPUnit_Framework_TestCase
*/ */
@ -8,27 +25,27 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
/** /**
* @var string * @var string
*/ */
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml"; protected static $fixture_file = 'ContentReviewTest.yml';
/** /**
* @var array * @var array
*/ */
protected $requiredExtensions = array( protected static $required_extensions = [
"SiteTree" => array("SiteTreeContentReview"), SiteTree::class => [SiteTreeContentReview::class],
"Group" => array("ContentReviewOwner"), Group::class => [ContentReviewOwner::class],
"Member" => array("ContentReviewOwner"), Member::class => [ContentReviewOwner::class],
"CMSPageEditController" => array("ContentReviewCMSExtension"), CMSPageEditController::class => [ContentReviewCMSExtension::class],
"SiteConfig" => array("ContentReviewDefaultSettings"), SiteConfig::class => [ContentReviewDefaultSettings::class],
); ];
public function testReviewedThrowsExceptionWithNoRecordID() public function testReviewedThrowsExceptionWithNoRecordID()
{ {
$this->setExpectedException("SS_HTTPResponse_Exception"); $this->setExpectedException(HTTPResponse_Exception::class);
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */ /** @var CMSPageEditController|ContentReviewCMSExtension $controller */
$controller = new CMSPageEditController(); $controller = new CMSPageEditController();
$dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList()); $dummyForm = new Form($controller, "EditForm", new FieldList(), new FieldList());
$controller->savereview(array( $controller->savereview(array(
"ID" => null, "ID" => null,
@ -38,12 +55,12 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
public function testReviewedThrowsExceptionWithWrongRecordID() public function testReviewedThrowsExceptionWithWrongRecordID()
{ {
$this->setExpectedException("SS_HTTPResponse_Exception"); $this->setExpectedException(HTTPResponse_Exception::class);
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */ /** @var CMSPageEditController|ContentReviewCMSExtension $controller */
$controller = new CMSPageEditController(); $controller = new CMSPageEditController();
$dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList()); $dummyForm = new Form($controller, "EditForm", new FieldList(), new FieldList());
$controller->savereview(array( $controller->savereview(array(
"ID" => "FAIL", "ID" => "FAIL",
@ -54,20 +71,20 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
public function testReviewedWithAuthor() public function testReviewedWithAuthor()
{ {
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
$this->loginAs($author); $this->logInAs($author);
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home"); $page = $this->objFromFixture(Page::class, "home");
$data = array( $data = array(
"action_savereview" => 1, "action_savereview" => 1,
"ID" => $page->ID, "ID" => $page->ID,
); );
$this->get('admin/pages/edit/show/' . $page->ID); $this->get('admin/pages/edit/show/' . $page->ID);
$response = $this->post(singleton('CMSPageEditController')->getEditForm($page->ID)->FormAction(), $data); $response = $this->post($this->getFormAction($page), $data);
$this->assertEquals("OK", $response->getStatusDescription()); $this->assertEquals("OK", $response->getStatusDescription());
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
@ -76,21 +93,21 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
public function testSaveReview() public function testSaveReview()
{ {
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
$this->loginAs($author); $this->logInAs($author);
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home"); $page = $this->objFromFixture(Page::class, "home");
$data = array( $data = array(
"action_savereview" => 1, "action_savereview" => 1,
"ID" => $page->ID, "ID" => $page->ID,
"ReviewNotes" => "This is the best page ever", "ReviewNotes" => "This is the best page ever",
); );
$this->get('admin/pages/edit/show/' . $page->ID); $this->get('admin/pages/edit/show/' . $page->ID);
$response = $this->post(singleton('CMSPageEditController')->getEditForm($page->ID)->FormAction(), $data); $response = $this->post($this->getFormAction($page), $data);
$this->assertEquals("OK", $response->getStatusDescription()); $this->assertEquals("OK", $response->getStatusDescription());
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
@ -100,4 +117,19 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
$this->assertEquals($data["ReviewNotes"], $reviewLog->Note); $this->assertEquals($data["ReviewNotes"], $reviewLog->Note);
} }
/**
* Return a CMS page edit form action via using a dummy request and session
*
* @param Page $page
* @return string
*/
protected function getFormAction(Page $page)
{
$controller = singleton(CMSPageEditController::class);
$controller->setRequest(new HTTPRequest('GET', '/'));
$controller->getRequest()->setSession($this->session());
return $controller->getEditForm($page->ID)->FormAction();
}
} }

View File

@ -1,5 +1,22 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use Page;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension;
use SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\ContentReview\Extensions\SiteTreeContentReview;
use SilverStripe\ContentReview\Tasks\ContentReviewEmails;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\SiteConfig\SiteConfig;
/** /**
* @mixin PHPUnit_Framework_TestCase * @mixin PHPUnit_Framework_TestCase
*/ */
@ -8,14 +25,14 @@ class ContentReviewNotificationTest extends SapphireTest
/** /**
* @var string * @var string
*/ */
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml'; protected static $fixture_file = 'ContentReviewTest.yml';
public function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();
// Hack to ensure only desired siteconfig is scaffolded // Hack to ensure only desired siteconfig is scaffolded
$desiredID = $this->idFromFixture('SiteConfig', 'mysiteconfig'); $desiredID = $this->idFromFixture(SiteConfig::class, 'mysiteconfig');
foreach (SiteConfig::get()->exclude('ID', $desiredID) as $config) { foreach (SiteConfig::get()->exclude('ID', $desiredID) as $config) {
$config->delete(); $config->delete();
} }
@ -24,25 +41,25 @@ class ContentReviewNotificationTest extends SapphireTest
/** /**
* @var array * @var array
*/ */
protected $requiredExtensions = array( protected static $required_extensions = [
'SiteTree' => array('SiteTreeContentReview'), SiteTree::class => [SiteTreeContentReview::class],
'Group' => array('ContentReviewOwner'), Group::class => [ContentReviewOwner::class],
'Member' => array('ContentReviewOwner'), Member::class => [ContentReviewOwner::class],
'CMSPageEditController' => array('ContentReviewCMSExtension'), CMSPageEditController::class => [ContentReviewCMSExtension::class],
'SiteConfig' => array('ContentReviewDefaultSettings'), SiteConfig::class => [ContentReviewDefaultSettings::class],
); ];
public function testContentReviewEmails() public function testContentReviewEmails()
{ {
SS_Datetime::set_mock_now('2010-02-24 12:00:00'); DBDatetime::set_mock_now('2010-02-24 12:00:00');
/** @var Page|SiteTreeContentReview $childParentPage */ /** @var Page|SiteTreeContentReview $childParentPage */
$childParentPage = $this->objFromFixture('Page', 'contact'); $childParentPage = $this->objFromFixture(Page::class, 'contact');
$childParentPage->NextReviewDate = '2010-02-23'; $childParentPage->NextReviewDate = '2010-02-23';
$childParentPage->write(); $childParentPage->write();
$task = new ContentReviewEmails(); $task = new ContentReviewEmails();
$task->run(new SS_HTTPRequest('GET', '/dev/tasks/ContentReviewEmails')); $task->run(new HTTPRequest('GET', '/dev/tasks/ContentReviewEmails'));
// Set template variables (as per variable case) // Set template variables (as per variable case)
$ToEmail = 'author@example.com'; $ToEmail = 'author@example.com';
@ -54,12 +71,12 @@ class ContentReviewNotificationTest extends SapphireTest
$this->assertNotNull($email, "Email haven't been sent."); $this->assertNotNull($email, "Email haven't been sent.");
$this->assertContains( $this->assertContains(
"<h1>$Subject</h1><p>There are $PagesCount pages that are due for review today by you, $ToFirstName.</p><p>This email was sent to $ToEmail</p>", "<h1>$Subject</h1><p>There are $PagesCount pages that are due for review today by you, $ToFirstName.</p><p>This email was sent to $ToEmail</p>",
$email['htmlContent'] $email['HtmlContent']
); );
$this->assertContains('Staff', $email['htmlContent']); $this->assertContains('Staff', $email['HtmlContent']);
$this->assertContains('Contact Us', $email['htmlContent']); $this->assertContains('Contact Us', $email['HtmlContent']);
$this->assertContains('Contact Us Child', $email['htmlContent']); $this->assertContains('Contact Us Child', $email['HtmlContent']);
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
} }

View File

@ -1,27 +1,43 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension;
use SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\ContentReview\Extensions\SiteTreeContentReview;
use SilverStripe\ContentReview\Reports\PagesDueForReviewReport;
use SilverStripe\ContentReview\Reports\PagesWithoutReviewScheduleReport;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\SiteConfig\SiteConfig;
class ContentReviewReportTest extends FunctionalTest class ContentReviewReportTest extends FunctionalTest
{ {
/** /**
* @var string * @var string
*/ */
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml"; protected static $fixture_file = 'ContentReviewTest.yml';
/** /**
* @var array * @var array
*/ */
protected $requiredExtensions = array( protected static $required_extensions = [
"SiteTree" => array("SiteTreeContentReview"), SiteTree::class => [SiteTreeContentReview::class],
"Group" => array("ContentReviewOwner"), Group::class => [ContentReviewOwner::class],
"Member" => array("ContentReviewOwner"), Member::class => [ContentReviewOwner::class],
"CMSPageEditController" => array("ContentReviewCMSExtension"), CMSPageEditController::class => [ContentReviewCMSExtension::class],
"SiteConfig" => array("ContentReviewDefaultSettings"), SiteConfig::class => [ContentReviewDefaultSettings::class],
); ];
public function testPagesDueForReviewReport() public function testPagesDueForReviewReport()
{ {
/** @var Member $editor */ /** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor"); $editor = $this->objFromFixture(Member::class, "editor");
$this->logInAs($editor); $this->logInAs($editor);
@ -32,8 +48,8 @@ class ContentReviewReportTest extends FunctionalTest
$report->title(); $report->title();
$results = $report->sourceRecords(array( $results = $report->sourceRecords(array(
"ReviewDateAfter" => "01/01/2010", "ReviewDateAfter" => "2010-01-01",
"ReviewDateBefore" => "12/12/2010", "ReviewDateBefore" => "2010-12-12",
)); ));
$this->assertEquals(array( $this->assertEquals(array(
@ -44,7 +60,7 @@ class ContentReviewReportTest extends FunctionalTest
"Contact Us", "Contact Us",
), $results->column("Title")); ), $results->column("Title"));
SS_Datetime::set_mock_now("2010-02-13 00:00:00"); DBDatetime::set_mock_now("2010-02-13 00:00:00");
$results = $report->sourceRecords(array()); $results = $report->sourceRecords(array());
@ -53,13 +69,13 @@ class ContentReviewReportTest extends FunctionalTest
"About Us", "About Us",
), $results->column("Title")); ), $results->column("Title"));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testPagesWithoutReviewScheduleReport() public function testPagesWithoutReviewScheduleReport()
{ {
/** @var Member $editor */ /** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor"); $editor = $this->objFromFixture(Member::class, "editor");
$this->logInAs($editor); $this->logInAs($editor);

View File

@ -1,5 +1,22 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use Page;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension;
use SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\ContentReview\Extensions\SiteTreeContentReview;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDate;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\SiteConfig\SiteConfig;
/** /**
* This class tests that settings are inherited correctly based on the inherited, * This class tests that settings are inherited correctly based on the inherited,
* custom or disabled settings. * custom or disabled settings.
@ -11,18 +28,18 @@ class ContentReviewSettingsTest extends SapphireTest
/** /**
* @var string * @var string
*/ */
public static $fixture_file = "contentreview/tests/ContentReviewSettingsTest.yml"; protected static $fixture_file = 'ContentReviewSettingsTest.yml';
/** /**
* @var array * @var array
*/ */
protected $requiredExtensions = array( protected static $required_extensions = [
"SiteTree" => array("SiteTreeContentReview"), SiteTree::class => [SiteTreeContentReview::class],
"Group" => array("ContentReviewOwner"), Group::class => [ContentReviewOwner::class],
"Member" => array("ContentReviewOwner"), Member::class => [ContentReviewOwner::class],
"CMSPageEditController" => array("ContentReviewCMSExtension"), CMSPageEditController::class => [ContentReviewCMSExtension::class],
"SiteConfig" => array("ContentReviewDefaultSettings"), SiteConfig::class => [ContentReviewDefaultSettings::class],
); ];
public function testAdvanceReviewDate10Days() public function testAdvanceReviewDate10Days()
{ {
@ -36,7 +53,7 @@ class ContentReviewSettingsTest extends SapphireTest
$page->write(); $page->write();
$this->assertEquals(date("Y-m-d", strtotime("now + 10 days")), $page->NextReviewDate); $this->assertEquals(date('Y-m-d', strtotime("now + 10 days")), $page->NextReviewDate);
} }
public function testAdvanceReviewDateNull() public function testAdvanceReviewDateNull()
@ -57,51 +74,51 @@ class ContentReviewSettingsTest extends SapphireTest
public function testAdvanceReviewFromCustomSettings() public function testAdvanceReviewFromCustomSettings()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom"); $page = $this->objFromFixture(Page::class, "custom");
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date("Y-m-d", strtotime("now + " . $page->ReviewPeriodDays . " days")), $page->NextReviewDate); $this->assertEquals(date('Y-m-d', strtotime("now + " . $page->ReviewPeriodDays . " days")), $page->NextReviewDate);
} }
public function testAdvanceReviewFromInheritedSettings() public function testAdvanceReviewFromInheritedSettings()
{ {
// When a parent page is advanced, the next review date of the child is not automatically advanced // When a parent page is advanced, the next review date of the child is not automatically advanced
$parentPage = $this->objFromFixture("Page", "page-1"); $parentPage = $this->objFromFixture(Page::class, "page-1");
$this->assertTrue($parentPage->advanceReviewDate()); $this->assertTrue($parentPage->advanceReviewDate());
$parentPage->write(); $parentPage->write();
$page = $this->objFromFixture("Page", "page-1-1"); $page = $this->objFromFixture(Page::class, "page-1-1");
$this->assertEquals(date("Y-m-d", strtotime("now + 5 days")), $parentPage->NextReviewDate); $this->assertEquals(date('Y-m-d', strtotime("now + 5 days")), $parentPage->NextReviewDate);
$this->assertEquals('2011-04-12', $page->NextReviewDate); $this->assertEquals('2011-04-12', $page->NextReviewDate);
// When a sub page is advanced, the next review date is advanced by the number of days in the parent // When a sub page is advanced, the next review date is advanced by the number of days in the parent
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date("Y-m-d", strtotime("now + 5 days")), $page->NextReviewDate); $this->assertEquals(date('Y-m-d', strtotime("now + 5 days")), $page->NextReviewDate);
} }
public function testAdvanceReviewFromInheritedSiteConfigSettings() public function testAdvanceReviewFromInheritedSiteConfigSettings()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "inherit"); $page = $this->objFromFixture(Page::class, "inherit");
/** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */ /** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */
$siteConfig = $this->objFromFixture("SiteConfig", "default"); $siteConfig = $this->objFromFixture(SiteConfig::class, "default");
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date("Y-m-d", strtotime("now + " . $siteConfig->ReviewPeriodDays . " days")), $page->NextReviewDate); $this->assertEquals(date('Y-m-d', strtotime("now + " . $siteConfig->ReviewPeriodDays . " days")), $page->NextReviewDate);
} }
public function testGetSettingsObjectFromCustom() public function testGetSettingsObjectFromCustom()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom"); $page = $this->objFromFixture(Page::class, "custom");
$this->assertEquals("Custom", $page->ContentReviewType); $this->assertEquals("Custom", $page->ContentReviewType);
$this->assertEquals($page, $page->getOptions()); $this->assertEquals($page, $page->getOptions());
@ -110,7 +127,7 @@ class ContentReviewSettingsTest extends SapphireTest
public function testGetSettingsObjectFromDisabled() public function testGetSettingsObjectFromDisabled()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "disabled"); $page = $this->objFromFixture(Page::class, "disabled");
$this->assertEquals("Disabled", $page->ContentReviewType); $this->assertEquals("Disabled", $page->ContentReviewType);
$this->assertFalse($page->getOptions()); $this->assertFalse($page->getOptions());
@ -119,7 +136,7 @@ class ContentReviewSettingsTest extends SapphireTest
public function testGetOptionObjectFromInheritedDisabled() public function testGetOptionObjectFromInheritedDisabled()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-2-1-1"); $page = $this->objFromFixture(Page::class, "page-2-1-1");
$this->assertEquals("Inherit", $page->ContentReviewType); $this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertFalse($page->getOptions()); $this->assertFalse($page->getOptions());
@ -128,19 +145,19 @@ class ContentReviewSettingsTest extends SapphireTest
public function testGetOptionObjectFromDeeplyInheritedPage() public function testGetOptionObjectFromDeeplyInheritedPage()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-3-1-1-1"); $page = $this->objFromFixture(Page::class, "page-3-1-1-1");
$this->assertEquals("Inherit", $page->ContentReviewType); $this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertInstanceOf("SiteConfig", $page->getOptions()); $this->assertInstanceOf(SiteConfig::class, $page->getOptions());
} }
public function testGetSettingsObjectFromInheritPage() public function testGetSettingsObjectFromInheritPage()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-1-1"); $page = $this->objFromFixture(Page::class, "page-1-1");
/** @var Page|SiteTreeContentReview $parentPage */ /** @var Page|SiteTreeContentReview $parentPage */
$parentPage = $this->objFromFixture("Page", "page-1"); $parentPage = $this->objFromFixture(Page::class, "page-1");
$this->assertEquals("Inherit", $page->ContentReviewType); $this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertEquals(get_class($parentPage), get_class($page->getOptions())); $this->assertEquals(get_class($parentPage), get_class($page->getOptions()));
@ -150,52 +167,52 @@ class ContentReviewSettingsTest extends SapphireTest
public function testGetSettingsObjectFromInheritedRootPage() public function testGetSettingsObjectFromInheritedRootPage()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "inherit"); $page = $this->objFromFixture(Page::class, "inherit");
$this->assertEquals("Inherit", $page->ContentReviewType); $this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertEquals($this->objFromFixture("SiteConfig", "default"), $page->getOptions()); $this->assertEquals($this->objFromFixture(SiteConfig::class, "default")->ID, $page->getOptions()->ID);
} }
public function testGetNextReviewDateFromCustomSettings() public function testGetNextReviewDateFromCustomSettings()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture('Page', 'custom'); $page = $this->objFromFixture(Page::class, 'custom');
$date = $page->getReviewDate(); $date = $page->getReviewDate();
$this->assertEquals('2010-02-01', $date->format('Y-m-d')); $this->assertEquals('2010-02-01', $date->format('Y-MM-dd'));
} }
public function testGetNextReviewDateFromSiteConfigInheritedSetting() public function testGetNextReviewDateFromSiteConfigInheritedSetting()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "inherit"); $page = $this->objFromFixture(Page::class, "inherit");
$nextReviewDate = $page->getReviewDate(); $nextReviewDate = $page->getReviewDate();
$this->assertInstanceOf("Date", $nextReviewDate); $this->assertInstanceOf(DBDate::class, $nextReviewDate);
/** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */ /** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */
$siteConfig = $this->objFromFixture("SiteConfig", "default"); $siteConfig = $this->objFromFixture(SiteConfig::class, "default");
$expected = $this->addDaysToDate(SS_Datetime::now(), $siteConfig->ReviewPeriodDays); $expected = $this->addDaysToDate(DBDatetime::now(), $siteConfig->ReviewPeriodDays);
$this->assertEquals($expected, $nextReviewDate->format("Y-m-d")); $this->assertEquals($expected, $nextReviewDate->format('Y-MM-dd'));
} }
public function testGetNextReviewDateFromPageInheritedSetting() public function testGetNextReviewDateFromPageInheritedSetting()
{ {
// Although page-1-1 inherits from page-1, it has an independent review date // Although page-1-1 inherits from page-1, it has an independent review date
$page = $this->objFromFixture("Page", "page-1-1"); $page = $this->objFromFixture(Page::class, "page-1-1");
$nextReviewDate = $page->getReviewDate(); $nextReviewDate = $page->getReviewDate();
$this->assertInstanceOf("Date", $nextReviewDate); $this->assertInstanceOf(DBDate::class, $nextReviewDate);
$this->assertEquals('2011-04-12', $nextReviewDate->format("Y-m-d")); $this->assertEquals('2011-04-12', $nextReviewDate->format('Y-MM-dd'));
} }
public function testUpdateNextReviewDateFromCustomToDisabled() public function testUpdateNextReviewDateFromCustomToDisabled()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom"); $page = $this->objFromFixture(Page::class, "custom");
// before write() // before write()
$this->assertEquals("2010-02-01", $page->NextReviewDate); $this->assertEquals("2010-02-01", $page->NextReviewDate);
@ -207,7 +224,7 @@ class ContentReviewSettingsTest extends SapphireTest
unset($page); unset($page);
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom"); $page = $this->objFromFixture(Page::class, "custom");
$this->assertNull($page->NextReviewDate); $this->assertNull($page->NextReviewDate);
} }
@ -215,7 +232,7 @@ class ContentReviewSettingsTest extends SapphireTest
public function testUpdateNextReviewDateFromDisabledToCustom() public function testUpdateNextReviewDateFromDisabledToCustom()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "disabled"); $page = $this->objFromFixture(Page::class, "disabled");
$this->assertNull($page->NextReviewDate); $this->assertNull($page->NextReviewDate);
@ -227,9 +244,9 @@ class ContentReviewSettingsTest extends SapphireTest
unset($page); unset($page);
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "disabled"); $page = $this->objFromFixture(Page::class, "disabled");
$expected = date("Y-m-d", strtotime("+ " . $page->ReviewPeriodDays . " days")); $expected = date('Y-m-d', strtotime("+ " . $page->ReviewPeriodDays . " days"));
$this->assertEquals($expected, $page->NextReviewDate); $this->assertEquals($expected, $page->NextReviewDate);
} }
@ -237,10 +254,10 @@ class ContentReviewSettingsTest extends SapphireTest
public function testParentChangedOptionsAndChildShouldToo() public function testParentChangedOptionsAndChildShouldToo()
{ {
/** @var Page|SiteTreeContentReview $parentPage */ /** @var Page|SiteTreeContentReview $parentPage */
$parentPage = $this->objFromFixture("Page", "page-1"); $parentPage = $this->objFromFixture(Page::class, "page-1");
/** @var Page|SiteTreeContentReview $childPage */ /** @var Page|SiteTreeContentReview $childPage */
$childPage = $this->objFromFixture("Page", "page-1-1"); $childPage = $this->objFromFixture(Page::class, "page-1-1");
// Parent and child pages have different review dates // Parent and child pages have different review dates
$this->assertNotEquals($parentPage->NextReviewDate, $childPage->NextReviewDate); $this->assertNotEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
@ -253,36 +270,38 @@ class ContentReviewSettingsTest extends SapphireTest
DataObject::flush_and_destroy_cache(); DataObject::flush_and_destroy_cache();
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$parentPage = $this->objFromFixture("Page", "page-1"); $parentPage = $this->objFromFixture(Page::class, "page-1");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$childPage = $this->objFromFixture("Page", "page-1-1"); $childPage = $this->objFromFixture(Page::class, "page-1-1");
// The parent page's date advances, but not the child's // The parent page's date advances, but not the child's
$this->assertEquals('2011-04-12', $childPage->NextReviewDate); $this->assertEquals('2011-04-12', $childPage->NextReviewDate);
$this->assertEquals($this->addDaysToDate(date("Y-m-d"), 10), $parentPage->NextReviewDate); $this->assertEquals($this->addDaysToDate(date('Y-m-d'), 10), $parentPage->NextReviewDate);
// Reviewing the child page should, however, advance its review by 10 days // Reviewing the child page should, however, advance its review by 10 days
$childPage->advanceReviewDate(); $childPage->advanceReviewDate();
$childPage->write(); $childPage->write();
$this->assertEquals($this->addDaysToDate(date("Y-m-d"), 10), $childPage->NextReviewDate); $this->assertEquals($this->addDaysToDate(date('Y-m-d'), 10), $childPage->NextReviewDate);
} }
/** /**
* @param string|SS_DateTime|DateTime $date * Note: all input dates should be DBDatetime or strings in CLDR date format. See {@link DBDate} for information
* @param int $days *
* @param string $format * @param string|DBDatetime $date
* @param int $days
* @param string $format
* *
* @return bool|string * @return bool|string
*/ */
private function addDaysToDate($date, $days, $format = "Y-m-d") private function addDaysToDate($date, $days, $format = 'Y-MM-dd')
{ {
if (is_object($date)) { if (is_object($date)) {
$sec = strtotime("+ " . $days . " days", $date->format("U")); $sec = strtotime("+ " . $days . " days", $date->getTimestamp());
} else { } else {
$sec = strtotime("+ " . $days . " days", strtotime($date)); $sec = strtotime("+ " . $days . " days", DBDate::create()->setValue($date)->getTimestamp());
} }
return date($format, $sec); return DBDate::create()->setValue($sec)->format($format);
} }
} }

View File

@ -1,4 +1,4 @@
Permission: SilverStripe\Security\Permission:
cmsmain1: cmsmain1:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
cmsmain2: cmsmain2:
@ -10,46 +10,56 @@ Permission:
workflowadmin2: workflowadmin2:
Code: IS_WORKFLOW_ADMIN Code: IS_WORKFLOW_ADMIN
Group: SilverStripe\Security\Group:
webmastergroup: webmastergroup:
Title: Edit existing pages Title: Edit existing pages
Code: editorgroup Code: editorgroup
Permissions: =>Permission.cmsmain1,=>Permission.workflowadmin1,=>Permission.setreviewdates Permissions:
- =>SilverStripe\Security\Permission.cmsmain1
- =>SilverStripe\Security\Permission.workflowadmin1
- =>SilverStripe\Security\Permission.setreviewdates
editorgroup: editorgroup:
Title: Edit existing pages Title: Edit existing pages
Code: editorgroup Code: editorgroup
Permissions: =>Permission.cmsmain1,=>Permission.workflowadmin1,=>Permission.setreviewdates Permissions:
- =>SilverStripe\Security\Permission.cmsmain1
- =>SilverStripe\Security\Permission.workflowadmin1
- =>SilverStripe\Security\Permission.setreviewdates
authorgroup: authorgroup:
Title: Author existing pages Title: Author existing pages
Code: authorgroup Code: authorgroup
Permissions: =>Permission.cmsmain2,=>Permission.workflowadmin2 Permissions:
- =>SilverStripe\Security\Permission.cmsmain2
- =>SilverStripe\Security\Permission.workflowadmin2
Member: SilverStripe\Security\Member:
webmaster: webmaster:
FirstName: Web FirstName: Web
Surname: Master Surname: Master
Email: webmaster@example.com Email: webmaster@example.com
Groups: =>Group.webmastergroup Groups: =>SilverStripe\Security\Group.webmastergroup
author: author:
FirstName: Test FirstName: Test
Surname: Author Surname: Author
Email: author@example.com Email: author@example.com
Groups: =>Group.authorgroup Groups: =>SilverStripe\Security\Group.authorgroup
editor: editor:
FirstName: Test FirstName: Test
Surname: Editor Surname: Editor
Groups: =>Group.editorgroup Groups: =>SilverStripe\Security\Group.editorgroup
SiteConfig:
SilverStripe\SiteConfig\SiteConfig:
default: default:
ContentReviewUsers: =>Member.webmaster ContentReviewUsers: =>SilverStripe\Security\Member.webmaster
ContentReviewGroups: =>Group.webmastergroup ContentReviewGroups: =>SilverStripe\Security\Group.webmastergroup
ReviewPeriodDays: 30 ReviewPeriodDays: 30
Page: Page:
custom: custom:
Title: custom Title: custom
ContentReviewType: Custom ContentReviewType: Custom
NextReviewDate: 2010-02-01 NextReviewDate: 2010-02-01
ContentReviewUsers: =>Member.editor ContentReviewUsers: =>SilverStripe\Security\Member.editor
ReviewPeriodDays: 10 ReviewPeriodDays: 10
disabled: disabled:
Title: disabled Title: disabled
@ -89,7 +99,7 @@ Page:
page-3-1-1: page-3-1-1:
Title: page 3 1 1 Title: page 3 1 1
ContentReviewType: Inherit ContentReviewType: Inherit
ParentID: =>Page.page-3-1 ParentID: =>Page.page-3-1
page-3-1-1-1: page-3-1-1-1:
Title: page 3 1 1 1 Title: page 3 1 1 1
ContentReviewType: Inherit ContentReviewType: Inherit

View File

@ -1,10 +1,10 @@
SiteConfig: SilverStripe\SiteConfig\SiteConfig:
mysiteconfig: mysiteconfig:
ReviewFrom: sender@silverstripe.com ReviewFrom: sender@silverstripe.com
ReviewSubject: 'Please log in to review some content!' ReviewSubject: 'Please log in to review some content!'
ReviewBody: '<h1>$Subject</h1><p>There are $PagesCount pages that are due for review today by you, $ToFirstName.</p><p>This email was sent to $ToEmail</p>' ReviewBody: '<h1>$Subject</h1><p>There are $PagesCount pages that are due for review today by you, $ToFirstName.</p><p>This email was sent to $ToEmail</p>'
Permission: SilverStripe\Security\Permission:
cmsmain1: cmsmain1:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
cmsmain2: cmsmain2:
@ -16,39 +16,44 @@ Permission:
workflowadmin2: workflowadmin2:
Code: IS_WORKFLOW_ADMIN Code: IS_WORKFLOW_ADMIN
Group: SilverStripe\Security\Group:
editorgroup: editorgroup:
Title: Edit existing pages Title: Edit existing pages
Code: editorgroup Code: editorgroup
Permissions: =>Permission.cmsmain1,=>Permission.workflowadmin1,=>Permission.setreviewdates Permissions:
- =>SilverStripe\Security\Permission.cmsmain1
- =>SilverStripe\Security\Permission.workflowadmin1
- =>SilverStripe\Security\Permission.setreviewdates
authorgroup: authorgroup:
Title: Author existing pages Title: Author existing pages
Code: authorgroup Code: authorgroup
Permissions: =>Permission.cmsmain2,=>Permission.workflowadmin2 Permissions:
- =>SilverStripe\Security\Permission.cmsmain2
- =>SilverStripe\Security\Permission.workflowadmin2
Member: SilverStripe\Security\Member:
author: author:
FirstName: Test FirstName: Test
Surname: Author Surname: Author
Email: author@example.com Email: author@example.com
Groups: =>Group.authorgroup Groups: =>SilverStripe\Security\Group.authorgroup
editor: editor:
FirstName: Test FirstName: Test
Surname: Editor Surname: Editor
Groups: =>Group.editorgroup Groups: =>SilverStripe\Security\Group.editorgroup
visitor: visitor:
FirstName: Kari FirstName: Kari
Surname: Visitor Surname: Visitor
Email: visitor@example.com Email: visitor@example.com
Page: Page:
# Cant be reviewed, no owners # Cant be reviewed, no owners
home: home:
Title: Home Title: Home
ContentReviewType: Custom ContentReviewType: Custom
NextReviewDate: 2010-02-01 NextReviewDate: 2010-02-01
ReviewPeriodDays: 10 ReviewPeriodDays: 10
# Cant be reviewed, no owners # Cant be reviewed, no owners
about: about:
Title: About Us Title: About Us
ContentReviewType: Custom ContentReviewType: Custom
@ -59,24 +64,24 @@ Page:
ContentReviewType: Custom ContentReviewType: Custom
NextReviewDate: 2010-02-14 NextReviewDate: 2010-02-14
ReviewPeriodDays: 10 ReviewPeriodDays: 10
ContentReviewUsers: =>Member.author ContentReviewUsers: =>SilverStripe\Security\Member.author
contact: contact:
Title: Contact Us Title: Contact Us
ContentReviewType: Custom ContentReviewType: Custom
ReviewPeriodDays: 10 ReviewPeriodDays: 10
NextReviewDate: 2010-02-21 NextReviewDate: 2010-02-21
ContentReviewGroups: =>Group.authorgroup ContentReviewGroups: =>SilverStripe\Security\Group.authorgroup
contact-child: contact-child:
Title: Contact Us Child Title: Contact Us Child
ContentReviewType: Inherit ContentReviewType: Inherit
ParentID: =>Page.contact ParentID: =>Page.contact
# Cant be reviewed, no NextReviewDate # Cant be reviewed, no NextReviewDate
no-review: no-review:
Title: Page without review date Title: Page without review date
ContentReviewType: Custom ContentReviewType: Custom
ContentReviewUsers: =>Member.author ContentReviewUsers: =>SilverStripe\Security\Member.author
# Cant be reviewed, no NextReviewDate # Cant be reviewed, no NextReviewDate
group-owned: group-owned:
Title: Page owned by group Title: Page owned by group
ContentReviewType: Custom ContentReviewType: Custom
ContentReviewGroups: =>Group.authorgroup ContentReviewGroups: =>SilverStripe\Security\Group.authorgroup

View File

@ -1,5 +1,20 @@
<?php <?php
namespace SilverStripe\ContentReview\Tests;
use Page;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ContentReview\Extensions\SiteTreeContentReview;
use SilverStripe\ContentReview\Extensions\ContentReviewOwner;
use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension;
use SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings;
use SilverStripe\Security\Group;
use SilverStripe\Security\Member;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Versioned\Versioned;
/** /**
* @mixin PHPUnit_Framework_TestCase * @mixin PHPUnit_Framework_TestCase
*/ */
@ -8,23 +23,23 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
/** /**
* @var string * @var string
*/ */
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml"; protected static $fixture_file = 'ContentReviewTest.yml';
/** /**
* @var array * @var array
*/ */
protected $requiredExtensions = array( protected static $required_extensions = [
"SiteTree" => array("SiteTreeContentReview"), SiteTree::class => [SiteTreeContentReview::class],
"Group" => array("ContentReviewOwner"), Group::class => [ContentReviewOwner::class],
"Member" => array("ContentReviewOwner"), Member::class => [ContentReviewOwner::class],
"CMSPageEditController" => array("ContentReviewCMSExtension"), CMSPageEditController::class => [ContentReviewCMSExtension::class],
"SiteConfig" => array("ContentReviewDefaultSettings"), SiteConfig::class => [ContentReviewDefaultSettings::class],
); ];
public function testOwnerNames() public function testOwnerNames()
{ {
/** @var Member $editor */ /** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor"); $editor = $this->objFromFixture(Member::class, "editor");
$this->logInAs($editor); $this->logInAs($editor);
@ -41,7 +56,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
$this->assertEquals($page->OwnerNames, "Test Editor", "Test Editor should be the owner"); $this->assertEquals($page->OwnerNames, "Test Editor", "Test Editor should be the owner");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "about"); $page = $this->objFromFixture(Page::class, "about");
$page->OwnerUsers()->removeAll(); $page->OwnerUsers()->removeAll();
$page->write(); $page->write();
@ -53,7 +68,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testPermissionsExists() public function testPermissionsExists()
{ {
$perms = singleton("SiteTreeContentReview")->providePermissions(); $perms = singleton(SiteTreeContentReview::class)->providePermissions();
$this->assertTrue(isset($perms["EDIT_CONTENT_REVIEW_FIELDS"])); $this->assertTrue(isset($perms["EDIT_CONTENT_REVIEW_FIELDS"]));
} }
@ -61,7 +76,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testUserWithPermissionCanEdit() public function testUserWithPermissionCanEdit()
{ {
/** @var Member $editor */ /** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor"); $editor = $this->objFromFixture(Member::class, "editor");
$this->logInAs($editor); $this->logInAs($editor);
@ -76,7 +91,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testUserWithoutPermissionCannotEdit() public function testUserWithoutPermissionCannotEdit()
{ {
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
$this->logInAs($author); $this->logInAs($author);
@ -91,7 +106,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testAutomaticallyToNotSetReviewDate() public function testAutomaticallyToNotSetReviewDate()
{ {
/** @var Member $editor */ /** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor"); $editor = $this->objFromFixture(Member::class, "editor");
$this->logInAs($editor); $this->logInAs($editor);
@ -108,15 +123,15 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testAddReviewNote() public function testAddReviewNote()
{ {
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home"); $page = $this->objFromFixture(Page::class, "home");
$page->addReviewNote($author, "This is a message"); $page->addReviewNote($author, "This is a message");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$homepage = $this->objFromFixture("Page", "home"); $homepage = $this->objFromFixture(Page::class, "home");
$this->assertEquals(1, $homepage->ReviewLogs()->count()); $this->assertEquals(1, $homepage->ReviewLogs()->count());
$this->assertEquals("This is a message", $homepage->ReviewLogs()->first()->Note); $this->assertEquals("This is a message", $homepage->ReviewLogs()->first()->Note);
@ -125,7 +140,7 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testGetContentReviewOwners() public function testGetContentReviewOwners()
{ {
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "group-owned"); $page = $this->objFromFixture(Page::class, "group-owned");
$owners = $page->ContentReviewOwners(); $owners = $page->ContentReviewOwners();
@ -135,134 +150,135 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
public function testCanNotBeReviewBecauseNoReviewDate() public function testCanNotBeReviewBecauseNoReviewDate()
{ {
SS_Datetime::set_mock_now("2010-01-01 12:00:00"); DBDatetime::set_mock_now("2010-01-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "no-review"); $page = $this->objFromFixture(Page::class, "no-review");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanNotBeReviewedBecauseInFuture() public function testCanNotBeReviewedBecauseInFuture()
{ {
SS_Datetime::set_mock_now("2010-01-01 12:00:00"); DBDatetime::set_mock_now("2010-01-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "staff"); $page = $this->objFromFixture(Page::class, "staff");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanNotBeReviewedByUser() public function testCanNotBeReviewedByUser()
{ {
SS_Datetime::set_mock_now("2010-03-01 12:00:00"); DBDatetime::set_mock_now("2010-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home"); $page = $this->objFromFixture(Page::class, "home");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanBeReviewedByUser() public function testCanBeReviewedByUser()
{ {
SS_Datetime::set_mock_now("2010-03-01 12:00:00"); DBDatetime::set_mock_now("2010-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "staff"); $page = $this->objFromFixture(Page::class, "staff");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanNotBeReviewedByGroup() public function testCanNotBeReviewedByGroup()
{ {
SS_Datetime::set_mock_now("2010-03-01 12:00:00"); DBDatetime::set_mock_now("2010-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "editor"); $author = $this->objFromFixture(Member::class, "editor");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact"); $page = $this->objFromFixture(Page::class, "contact");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanBeReviewedByGroup() public function testCanBeReviewedByGroup()
{ {
SS_Datetime::set_mock_now("2010-03-01 12:00:00"); DBDatetime::set_mock_now("2010-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact"); $page = $this->objFromFixture(Page::class, "contact");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testCanBeReviewedFromInheritedSetting() public function testCanBeReviewedFromInheritedSetting()
{ {
SS_Datetime::set_mock_now("2013-03-01 12:00:00"); DBDatetime::set_mock_now("2013-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
/** @var Page|SiteTreeContentReview $parentPage */ /** @var Page|SiteTreeContentReview $parentPage */
$parentPage = $this->objFromFixture("Page", "contact"); $parentPage = $this->objFromFixture(Page::class, "contact");
$parentPage->NextReviewDate = "2013-01-01"; $parentPage->NextReviewDate = "2013-01-01";
$parentPage->write(); $parentPage->write();
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact-child"); $page = $this->objFromFixture(Page::class, "contact-child");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testUnModifiedPagesDontChangeEditor() { public function testUnModifiedPagesDontChangeEditor()
SS_Datetime::set_mock_now("2013-03-01 12:00:00"); {
DBDatetime::set_mock_now("2013-03-01 12:00:00");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
$this->logInAs($author); $this->logInAs($author);
// Page which is un-modified doesn't advance version of have an editor assigned // Page which is un-modified doesn't advance version of have an editor assigned
$contactPage = $this->objFromFixture("Page", "contact"); $contactPage = $this->objFromFixture(Page::class, "contact");
$contactPageVersion = $contactPage->Version; $contactPageVersion = $contactPage->Version;
$contactPage->write(); $contactPage->write();
$this->assertEmpty($contactPage->LastEditedByName); $this->assertEmpty($contactPage->LastEditedByName);
$this->assertEquals( $this->assertEquals(
$contactPageVersion, $contactPageVersion,
Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $contactPage->ID, false) Versioned::get_versionnumber_by_stage(SiteTree::class, 'Stage', $contactPage->ID, false)
); );
// Page with modifications gets marked // Page with modifications gets marked
$homePage = $this->objFromFixture("Page", "home"); $homePage = $this->objFromFixture(Page::class, "home");
$homePageVersion = $homePage->Version; $homePageVersion = $homePage->Version;
$homePage->Content = '<p>Welcome!</p>'; $homePage->Content = '<p>Welcome!</p>';
$homePage->write(); $homePage->write();
@ -270,21 +286,21 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
$this->assertEquals($author->getTitle(), $homePage->LastEditedByName); $this->assertEquals($author->getTitle(), $homePage->LastEditedByName);
$this->assertGreaterThan( $this->assertGreaterThan(
$homePageVersion, $homePageVersion,
Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $homePage->ID, false) Versioned::get_versionnumber_by_stage(SiteTree::class, 'Stage', $homePage->ID, false)
); );
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testReviewActionVisibleForAuthor() public function testReviewActionVisibleForAuthor()
{ {
SS_Datetime::set_mock_now("2020-03-01 12:00:00"); DBDatetime::set_mock_now("2020-03-01 12:00:00");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact"); $page = $this->objFromFixture(Page::class, "contact");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "author"); $author = $this->objFromFixture(Member::class, "author");
$this->logInAs($author); $this->logInAs($author);
@ -292,18 +308,18 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
$this->assertNotNull($fields->fieldByName("ActionMenus.ReviewContent")); $this->assertNotNull($fields->fieldByName("ActionMenus.ReviewContent"));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
public function testReviewActionNotVisibleForEditor() public function testReviewActionNotVisibleForEditor()
{ {
SS_Datetime::set_mock_now("2020-03-01 12:00:00"); DBDatetime::set_mock_now("2020-03-01 12:00:00");
/** @var Page|SiteTreeContentReview $page */ /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact"); $page = $this->objFromFixture(Page::class, "contact");
/** @var Member $author */ /** @var Member $author */
$author = $this->objFromFixture("Member", "editor"); $author = $this->objFromFixture(Member::class, "editor");
$this->logInAs($author); $this->logInAs($author);
@ -311,6 +327,6 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest
$this->assertNull($fields->fieldByName("ActionMenus.ReviewContent")); $this->assertNull($fields->fieldByName("ActionMenus.ReviewContent"));
SS_Datetime::clear_mock_now(); DBDatetime::clear_mock_now();
} }
} }