From bbaf4276af015e2f32d63256f1401bd3e7123faa Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 9 Mar 2017 11:40:13 +1300 Subject: [PATCH] BUG Fix delete / unpublish Split SearchUpdater classes into separate files Fixes #134 --- code/search/SearchUpdater.php | 83 ++----------------- ...hUpdater_BindManipulationCaptureFilter.php | 15 ++++ code/search/SearchUpdater_ObjectHandler.php | 71 ++++++++++++++++ tests/SearchVariantVersionedTest.php | 22 +++++ 4 files changed, 113 insertions(+), 78 deletions(-) create mode 100644 code/search/SearchUpdater_BindManipulationCaptureFilter.php create mode 100644 code/search/SearchUpdater_ObjectHandler.php diff --git a/code/search/SearchUpdater.php b/code/search/SearchUpdater.php index 0c836f0..12e0740 100644 --- a/code/search/SearchUpdater.php +++ b/code/search/SearchUpdater.php @@ -97,6 +97,7 @@ class SearchUpdater extends Object $id = $details['id']; $state = $details['state']; $class = $details['class']; + $command = $details['command']; $fields = isset($details['fields']) ? $details['fields'] : array(); $base = ClassInfo::baseDataClass($class); @@ -111,6 +112,7 @@ class SearchUpdater extends Object 'class' => $class, 'id' => $id, 'statefulids' => $statefulids, + 'command' => $command, 'fields' => array() ); } @@ -125,9 +127,9 @@ class SearchUpdater extends Object } } - // Trim records without fields - foreach(array_keys($writes) as $key) { - if(empty($writes[$key]['fields'])) { + // Trim non-delete records without fields + foreach (array_keys($writes) as $key) { + if ($writes[$key]['command'] !== 'delete' && empty($writes[$key]['fields'])) { unset($writes[$key]); } } @@ -203,78 +205,3 @@ class SearchUpdater extends Object self::$processor = null; } } - -class SearchUpdater_BindManipulationCaptureFilter implements RequestFilter -{ - public function preRequest(SS_HTTPRequest $request, Session $session, DataModel $model) - { - SearchUpdater::bind_manipulation_capture(); - } - - public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) - { - /* NOP */ - } -} - -/** - * Delete operations do not use database manipulations. - * - * If a delete has been requested, force a write on objects that should be - * indexed. This causes the object to be marked for deletion from the index. - */ - -class SearchUpdater_ObjectHandler extends DataExtension -{ - public function onAfterDelete() - { - // Calling delete() on empty objects does nothing - if (!$this->owner->ID) { - return; - } - - // Force SearchUpdater to mark this record as dirty - $manipulation = array( - $this->owner->ClassName => array( - 'fields' => array(), - 'id' => $this->owner->ID, - 'command' => 'update' - ) - ); - $this->owner->extend('augmentWrite', $manipulation); - SearchUpdater::handle_manipulation($manipulation); - } - - /** - * Forces this object to trigger a re-index in the current state - */ - public function triggerReindex() - { - if (!$this->owner->ID) { - return; - } - - $id = $this->owner->ID; - $class = $this->owner->ClassName; - $state = SearchVariant::current_state($class); - $base = ClassInfo::baseDataClass($class); - $key = "$id:$base:".serialize($state); - - $statefulids = array(array( - 'id' => $id, - 'state' => $state - )); - - $writes = array( - $key => array( - 'base' => $base, - 'class' => $class, - 'id' => $id, - 'statefulids' => $statefulids, - 'fields' => array() - ) - ); - - SearchUpdater::process_writes($writes); - } -} diff --git a/code/search/SearchUpdater_BindManipulationCaptureFilter.php b/code/search/SearchUpdater_BindManipulationCaptureFilter.php new file mode 100644 index 0000000..24cef93 --- /dev/null +++ b/code/search/SearchUpdater_BindManipulationCaptureFilter.php @@ -0,0 +1,15 @@ +owner->ID) { + return; + } + + // Force SearchUpdater to mark this record as dirty + // Note: Some extensions require entire hierarchy passed to augmentWrite() + $manipulation = array(); + foreach (ClassInfo::ancestry($this->owner) as $class) { + if (!is_subclass_of($class, 'DataObject')) { + continue; + } + $manipulation[$class] = array( + 'fields' => array(), + 'id' => $this->owner->ID, + // Note: 'delete' command not actually handled by manipulations, + // but added so that SearchUpdater can detect the deletion + 'command' => 'delete' + ); + } + $this->owner->extend('augmentWrite', $manipulation); + SearchUpdater::handle_manipulation($manipulation); + } + + /** + * Forces this object to trigger a re-index in the current state + */ + public function triggerReindex() + { + if (!$this->owner->ID) { + return; + } + + $id = $this->owner->ID; + $class = $this->owner->ClassName; + $state = SearchVariant::current_state($class); + $base = ClassInfo::baseDataClass($class); + $key = "$id:$base:" . serialize($state); + + $statefulids = array( + array( + 'id' => $id, + 'state' => $state + ) + ); + + $writes = array( + $key => array( + 'base' => $base, + 'class' => $class, + 'id' => $id, + 'statefulids' => $statefulids, + 'fields' => array() + ) + ); + + SearchUpdater::process_writes($writes); + } +} diff --git a/tests/SearchVariantVersionedTest.php b/tests/SearchVariantVersionedTest.php index 76747f5..0f490a7 100644 --- a/tests/SearchVariantVersionedTest.php +++ b/tests/SearchVariantVersionedTest.php @@ -72,6 +72,28 @@ class SearchVariantVersionedTest extends SapphireTest )); $added = self::$index->getAdded(array('ID', '_versionedstage')); $this->assertEquals($expected, $added); + + // Test unpublish + + self::$index->reset(); + + $item->deleteFromStage('Live'); + + SearchUpdater::flush_dirty_indexes(); + + $this->assertEquals(1, count(self::$index->deleted)); + $this->assertEquals( + 'SiteTree', + self::$index->deleted[0]['base'] + ); + $this->assertEquals( + $item->ID, + self::$index->deleted[0]['id'] + ); + $this->assertEquals( + 'Live', + self::$index->deleted[0]['state']['SearchVariantVersioned'] + ); } public function testExcludeVariantState()