Skip to content

Commit

Permalink
BUG: Incomplete data fix (missing some versioned history records).
Browse files Browse the repository at this point in the history
  • Loading branch information
mfendeksilverstripe committed Oct 11, 2023
1 parent a56953c commit eb6b6a2
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 21 deletions.
21 changes: 13 additions & 8 deletions src/ActivityEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

use Exception;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\ArrayData;

/**
* @property DataObject $Subject
* @property DataObject|null $Subject
* @property string|null $Action
* @property string|null $Owner
* @property string $Date
*/
class ActivityEntry extends ArrayData
{
Expand All @@ -26,7 +30,7 @@ class ActivityEntry extends ArrayData

const UNPUBLISHED = 'UNPUBLISHED';

public static function createFromSnapshotItem(SnapshotItem $item): self
public function createFromSnapshotItem(SnapshotItem $item): ?self
{
/** @var DataObject|Versioned $itemObj */
$itemObj = $item->getItem();
Expand Down Expand Up @@ -75,18 +79,19 @@ public static function createFromSnapshotItem(SnapshotItem $item): self
}

if (!$itemObj) {
throw new Exception(sprintf(
'Could not resolve SnapshotItem %s to a previous %s version',
$item->ID,
$item->ObjectClass
));
// We couldn't compose the activity entry from available versioned history records
// This is a valid case as some projects opt to delete some of their older versioned records
return null;
}

/** @var DBDatetime $createdField */
$createdField = $item->obj('Created');

return static::create([
'Subject' => $itemObj,
'Action' => $flag,
'Owner' => null,
'Date' => $item->obj('Created')->Nice(),
'Date' => $createdField->Nice(),
]);
}

Expand Down
13 changes: 6 additions & 7 deletions src/Snapshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@
use SilverStripe\Versioned\Versioned;

/**
* Class Snapshot
*
* @property string $OriginHash
* @property int $OriginID
* @property string $OriginClass
* @property int AuthorID
* @method DataObject Origin()
* @method Member Author()
* @method HasManyList|SnapshotItem[] Items()
* @package SilverStripe\Snapshots
*/
class Snapshot extends DataObject
{
Expand Down Expand Up @@ -177,9 +174,10 @@ public function getActivityDescription(): string
{
/** @var SnapshotItem $item */
$item = $this->getOriginItem();
$entry = ActivityEntry::singleton()->createFromSnapshotItem($item);

return $item
? ActivityEntry::createFromSnapshotItem($item)->getDescription()
return $entry
? $entry->getDescription()
: _t(self::class . 'ACTIVITY_NONE', 'none');
}

Expand Down Expand Up @@ -227,9 +225,10 @@ public function getActivityType(): ?string
{
/** @var SnapshotItem $item */
$item = $this->getOriginItem();
$entry = ActivityEntry::singleton()->createFromSnapshotItem($item);

return $item
? ActivityEntry::createFromSnapshotItem($item)->Action
return $entry
? $entry->Action
: null;
}

Expand Down
3 changes: 0 additions & 3 deletions src/SnapshotItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
use SilverStripe\Versioned\Versioned;

/**
* Class SnapshotItem
*
* @property int $ObjectVersion
* @property int $WasPublished
* @property int $WasUnpublished
Expand All @@ -29,7 +27,6 @@
* @method DataObject Object()
* @method SnapshotItem Parent()
* @method HasManyList|SnapshotItem[] Children()
* @package SilverStripe\Snapshots
*/
class SnapshotItem extends DataObject
{
Expand Down
11 changes: 8 additions & 3 deletions src/SnapshotPublishable.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
use SilverStripe\Versioned\Versioned;

/**
* Class SnapshotPublishable
*
* @property DataObject|SnapshotPublishable|Versioned $owner
*/
class SnapshotPublishable extends RecursivePublishable
Expand Down Expand Up @@ -754,7 +752,14 @@ public function getActivityFeed(?int $minVersion = null, ?int $maxVersion = null
$list = ArrayList::create();

foreach ($items as $item) {
$list->push(ActivityEntry::createFromSnapshotItem($item));
$entry = ActivityEntry::singleton()->createFromSnapshotItem($item);

if (!$entry) {
// We couldn't compose an activity entry from the item, so we will skip this entry
continue;
}

$list->push($entry);
}

return $list;
Expand Down
86 changes: 86 additions & 0 deletions tests/IncompleteDataTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace SilverStripe\Snapshots\Tests;

use Exception;
use Page;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\Queries\SQLDelete;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Snapshots\Snapshot;
use SilverStripe\Snapshots\SnapshotPublishable;

class IncompleteDataTest extends SapphireTest
{
/**
* @var string
*/
protected static $fixture_file = 'IncompleteDataTest.yml';

/**
* @return void
* @throws Exception
*/
protected function setUp(): void
{
DBDatetime::set_mock_now('2020-01-01 00:00:00');

parent::setUp();
}

/**
* @return void
* @throws ValidationException
* @throws Exception
*/
public function testGetActivityFeed(): void
{
/** @var Page|SnapshotPublishable $page1 */
$page1 = $this->objFromFixture(Page::class, 'page1');

/** @var Page|SnapshotPublishable $page2 */
$page2 = $this->objFromFixture(Page::class, 'page2');

$actions = [
'2020-01-02 00:00:00' => [
$page1,
[
$page2,
],
],
'2020-01-03 00:00:00' => [
$page2,
[
$page1,
],
],
'2020-01-04 00:00:00' => [
$page1,
[
$page2,
],
],
];

// Create some mock actions
foreach ($actions as $time => $data) {
[$origin, $models] = $data;
DBDatetime::set_mock_now($time);
$snapshot = Snapshot::singleton()->createSnapshot($origin, $models);
$snapshot->write();
}

// Remove all traces of page 2 to create an incomplete data set
$page2->doArchive();
$query = SQLDelete::create(
'"SiteTree_Versions"',
[
'"RecordID"' => $page2->ID,
]
);
$query->execute();

$this->assertCount(2, $page1->getActivityFeed(), 'We expect only entries which have complete data');
}
}
7 changes: 7 additions & 0 deletions tests/IncompleteDataTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Page:
page1:
Title: 'Page1'
URLSegment: 'page1'
page2:
Title: 'Page2'
URLSegment: 'page2'

0 comments on commit eb6b6a2

Please sign in to comment.