Skip to content

Commit

Permalink
index correct ghost content when deleting the locale of an article
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes committed Dec 15, 2023
1 parent 8ccbbf7 commit 12e25e9
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 55 deletions.
12 changes: 12 additions & 0 deletions Document/Index/ArticleIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use ONGR\ElasticsearchBundle\Collection\Collection;
use ONGR\ElasticsearchBundle\Service\Manager;
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
use ONGR\ElasticsearchDSL\Query\MatchAllQuery;
use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery;
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
Expand Down Expand Up @@ -453,6 +454,17 @@ public function replaceWithGhostData(ArticleDocument $document, string $locale):
$article = $this->createOrUpdateArticle($document, $locale);
$article->setLocalizationState(new LocalizationStateViewObject(LocalizationState::GHOST, $document->getOriginalLocale()));

$repository = $this->manager->getRepository($this->documentFactory->getClass('article'));
$search = $repository->createSearch();
$search->addQuery(new TermQuery('localization_state.state', 'ghost'), BoolQuery::MUST);
$search->addQuery(new TermQuery('localization_state.locale', $locale), BoolQuery::MUST);

/** @var array<array{locale: string}> $searchResult */
$searchResult = $repository->findArray($search);
foreach ($searchResult as $result) {
$this->replaceWithGhostData($document, $result['locale']);
}

$this->manager->persist($article);
}

Expand Down
11 changes: 11 additions & 0 deletions Document/Subscriber/ArticleSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,17 @@ public function handleRemoveLocale(RemoveLocaleEvent $event)
return;
}

$concreteLocales = $this->documentInspector->getConcreteLocales($document);
$ghostLocale = $document->getOriginalLocale();
if (!\in_array($ghostLocale, $concreteLocales, true)) {
$ghostLocale = $concreteLocales[0] ?? null;
}

if (null !== $ghostLocale) {
/** @var ArticleDocument $document */
$document = $this->documentManager->find($document->getUuid(), $ghostLocale);
}

$this->indexer->replaceWithGhostData($document, $event->getLocale());
$this->indexer->flush();
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/Application/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
APP_ENV=test
DATABASE_URL=mysql://root:@127.0.0.1:3306/su_article_test?serverVersion=5.7
DATABASE_URL=mysql://root:ChangeMe@127.0.0.1:3306/sulu_test?serverVersion=5.7
DATABASE_CHARSET=utf8mb4
DATABASE_COLLATE=utf8mb4_unicode_ci
ELASTICSEARCH_HOST=127.0.0.1:9200
174 changes: 123 additions & 51 deletions Tests/Functional/Document/Index/ArticleIndexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Sulu\Bundle\PageBundle\Document\PageDocument;
use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
use Sulu\Bundle\TestBundle\Testing\SuluTestCase;
use Sulu\Component\Content\Document\LocalizationState;
use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;

Expand All @@ -35,11 +36,21 @@ class ArticleIndexerTest extends SuluTestCase
*/
private $documentManager;

/**
* @var Manager
*/
private $liveManager;

/**
* @var Manager
*/
private $manager;

/**
* @var ArticleIndexer
*/
private $liveIndexer;

/**
* @var ArticleIndexer
*/
Expand All @@ -58,9 +69,12 @@ public function setUp(): void
$this->initPhpcr();
$this->purgeDatabase();

$this->manager = $this->getContainer()->get('es.manager.live');
$this->liveManager = $this->getContainer()->get('es.manager.live');
$this->manager = $this->getContainer()->get('es.manager.default');
$this->documentManager = $this->getContainer()->get('sulu_document_manager.document_manager');
$this->indexer = $this->getContainer()->get('sulu_article.elastic_search.article_live_indexer');
$this->liveIndexer = $this->getContainer()->get('sulu_article.elastic_search.article_live_indexer');
$this->liveIndexer->clear();
$this->indexer = $this->getContainer()->get('sulu_article.elastic_search.article_indexer');
$this->indexer->clear();
}

Expand Down Expand Up @@ -90,14 +104,14 @@ public function testRemove()

/** @var ArticleDocument $articleDocument */
$articleDocument = $this->documentManager->find($article['id']);
$this->indexer->remove($articleDocument);
$this->indexer->flush();
$this->liveIndexer->remove($articleDocument);
$this->liveIndexer->flush();

self::assertNull($this->findViewDocument($articleDocument->getUuid(), 'de'));
self::assertNull($this->findViewDocument($articleDocument->getUuid(), 'en'));
self::assertNull($this->findLiveViewDocument($articleDocument->getUuid(), 'de'));
self::assertNull($this->findLiveViewDocument($articleDocument->getUuid(), 'en'));
}

public function testRemoveLocale()
public function testReplaceWithGhostData()
{
$article = $this->createArticle(
[
Expand All @@ -123,29 +137,32 @@ public function testRemoveLocale()

/** @var ArticleDocument $articleDocument */
$articleDocument = $this->documentManager->find($article['id']);
$this->indexer->remove($articleDocument, 'en');
$this->indexer->replaceWithGhostData($articleDocument, 'de');
$this->indexer->flush();

self::assertNotNull($this->findViewDocument($articleDocument->getUuid(), 'de'));
self::assertNull($this->findViewDocument($articleDocument->getUuid(), 'en'));
$documentDE = $this->findViewDocument($articleDocument->getUuid(), 'de');
$documentEN = $this->findViewDocument($articleDocument->getUuid(), 'en');

$this->assertSame('Test Article', $documentDE->getTitle());
$this->assertSame('ghost', $documentDE->getLocalizationState()->state);
$this->assertSame('en', $documentDE->getLocalizationState()->locale);

$this->assertSame('Test Article', $documentEN->getTitle());
}

public function testReplaceWithGhostData()
public function testReplaceWithGhostDataUpdateExistingGhosts()
{
$article = $this->createArticle(
[
'article' => 'Test content',
],
'Test Article',
'Test Article English',
'default_with_route'
);

$secondLocale = 'de';

// now add second locale
$this->updateArticle(
$article['id'],
$secondLocale,
'de',
[
'id' => $article['id'],
'article' => 'Test Inhalt',
Expand All @@ -154,19 +171,58 @@ public function testReplaceWithGhostData()
'default_with_route'
);

$this->updateArticle(
$article['id'],
'fr',
[
'id' => $article['id'],
'article' => 'Test Inhalt',
],
'Test Artikel French',
'default_with_route'
);

$documentEN = $this->findViewDocument($article['id'], 'en');
$this->assertSame(LocalizationState::LOCALIZED, $documentEN->getLocalizationState()->state);
$documentDE = $this->findViewDocument($article['id'], 'de');
$this->assertSame(LocalizationState::LOCALIZED, $documentDE->getLocalizationState()->state);
$documentFR = $this->findViewDocument($article['id'], 'fr');
$this->assertSame(LocalizationState::LOCALIZED, $documentFR->getLocalizationState()->state);

/** @var ArticleDocument $articleDocument */
$articleDocument = $this->documentManager->find($article['id']);
$this->indexer->replaceWithGhostData($articleDocument, 'de');
$articleDocument = $this->documentManager->find($article['id'], 'en');
$this->indexer->replaceWithGhostData($articleDocument, 'fr');
$this->indexer->flush();

$documentDE = $this->findViewDocument($articleDocument->getUuid(), 'de');
$documentEN = $this->findViewDocument($articleDocument->getUuid(), 'en');
$documentEN = $this->findViewDocument($article['id'], 'en');
$this->assertSame(LocalizationState::LOCALIZED, $documentEN->getLocalizationState()->state);
$documentDE = $this->findViewDocument($article['id'], 'de');
$this->assertSame(LocalizationState::LOCALIZED, $documentDE->getLocalizationState()->state);
$documentFR = $this->findViewDocument($article['id'], 'fr');
$this->assertSame(LocalizationState::GHOST, $documentFR->getLocalizationState()->state);
$this->assertSame('en', $documentFR->getLocalizationState()->locale);

$this->assertSame('Test Article', $documentDE->getTitle());
$this->assertSame('ghost', $documentDE->getLocalizationState()->state);
$this->assertSame('en', $documentDE->getLocalizationState()->locale);
$this->assertSame('Test Article English', $documentEN->getTitle());
$this->assertSame('Test Artikel Deutsch', $documentDE->getTitle());
$this->assertSame('Test Article English', $documentFR->getTitle());

$this->assertSame('Test Article', $documentEN->getTitle());
/** @var ArticleDocument $articleDocument */
$articleDocument = $this->documentManager->find($article['id'], 'de');
$this->indexer->replaceWithGhostData($articleDocument, 'en');
$this->indexer->flush();

$documentEN = $this->findViewDocument($article['id'], 'en');
$this->assertSame(LocalizationState::GHOST, $documentEN->getLocalizationState()->state);
$this->assertSame('de', $documentEN->getLocalizationState()->locale);
$documentDE = $this->findViewDocument($article['id'], 'de');
$this->assertSame(LocalizationState::LOCALIZED, $documentDE->getLocalizationState()->state);
$documentFR = $this->findViewDocument($article['id'], 'fr');
$this->assertSame(LocalizationState::GHOST, $documentFR->getLocalizationState()->state);
$this->assertSame('de', $documentFR->getLocalizationState()->locale);

$this->assertSame('Test Artikel Deutsch', $documentEN->getTitle());
$this->assertSame('Test Artikel Deutsch', $documentDE->getTitle());
$this->assertSame('Test Artikel Deutsch', $documentFR->getTitle());
}

public function testIndexDefaultWithRoute()
Expand All @@ -179,12 +235,12 @@ public function testIndexDefaultWithRoute()
'default_with_route'
);

$this->indexer = $this->getContainer()->get('sulu_article.elastic_search.article_live_indexer');
$this->liveIndexer = $this->getContainer()->get('sulu_article.elastic_search.article_live_indexer');

$document = $this->documentManager->find($article['id'], $this->locale);
$this->indexer->index($document);
$this->liveIndexer->index($document);

$viewDocument = $this->findViewDocument($article['id']);
$viewDocument = $this->findLiveViewDocument($article['id']);
$this->assertEquals($document->getUuid(), $viewDocument->getUuid());
$this->assertEquals('/articles/test-article', $viewDocument->getRoutePath());
$this->assertInstanceOf('\DateTime', $viewDocument->getPublished());
Expand Down Expand Up @@ -230,7 +286,7 @@ public function testIndexShadow()
null
);

$viewDocument = $this->findViewDocument($article['id'], $secondLocale);
$viewDocument = $this->findLiveViewDocument($article['id'], $secondLocale);

$this->assertEquals($article['id'], $viewDocument->getUuid());
$this->assertEquals('/articles/test-artikel-deutsch', $viewDocument->getRoutePath());
Expand All @@ -257,7 +313,7 @@ public function testIndexShadow()
'default_with_route'
);

$viewDocument = $this->findViewDocument($article['id'], $secondLocale);
$viewDocument = $this->findLiveViewDocument($article['id'], $secondLocale);
$this->assertEquals('Test Article - CHANGED!', $viewDocument->getTitle());

$contentData = \json_decode($viewDocument->getContentData(), true);
Expand Down Expand Up @@ -320,17 +376,17 @@ public function testUnpublishedShadows(): void
null
);

self::assertNotNull($this->findViewDocument($article['id'], $this->locale));
self::assertNotNull($this->findViewDocument($article['id'], $secondLocale));
self::assertNotNull($this->findViewDocument($article['id'], $thirdLocale));
self::assertNotNull($this->findLiveViewDocument($article['id'], $this->locale));
self::assertNotNull($this->findLiveViewDocument($article['id'], $secondLocale));
self::assertNotNull($this->findLiveViewDocument($article['id'], $thirdLocale));

$this->unpublishArticle($article['id'], $this->locale);
$this->unpublishArticle($article['id'], $secondLocale);
$this->unpublishArticle($article['id'], $thirdLocale);

self::assertNull($this->findViewDocument($article['id'], $this->locale));
self::assertNull($this->findViewDocument($article['id'], $secondLocale));
self::assertNull($this->findViewDocument($article['id'], $thirdLocale));
self::assertNull($this->findLiveViewDocument($article['id'], $this->locale));
self::assertNull($this->findLiveViewDocument($article['id'], $secondLocale));
self::assertNull($this->findLiveViewDocument($article['id'], $thirdLocale));

// publish the shadow
$this->updateArticle(
Expand All @@ -344,9 +400,9 @@ public function testUnpublishedShadows(): void
);

// only the DE shadow should be published
self::assertNull($this->findViewDocument($article['id'], $this->locale));
self::assertNotNull($this->findViewDocument($article['id'], $secondLocale));
self::assertNull($this->findViewDocument($article['id'], $thirdLocale));
self::assertNull($this->findLiveViewDocument($article['id'], $this->locale));
self::assertNotNull($this->findLiveViewDocument($article['id'], $secondLocale));
self::assertNull($this->findLiveViewDocument($article['id'], $thirdLocale));
}

public function testIndexPageTreeRoute()
Expand All @@ -364,17 +420,17 @@ public function testIndexPageTreeRoute()
);

$document = $this->documentManager->find($article['id'], $this->locale);
$this->indexer->index($document);
$this->liveIndexer->index($document);

$viewDocument = $this->findViewDocument($article['id']);
$viewDocument = $this->findLiveViewDocument($article['id']);
$this->assertEquals($page->getUuid(), $viewDocument->getParentPageUuid());
}

public function testSetUnpublished()
{
$article = $this->createArticle();

$viewDocument = $this->indexer->setUnpublished($article['id'], $this->locale);
$viewDocument = $this->liveIndexer->setUnpublished($article['id'], $this->locale);
$this->assertNull($viewDocument->getPublished());
$this->assertFalse($viewDocument->getPublishedState());
}
Expand Down Expand Up @@ -411,10 +467,10 @@ public function testIndexTaggedProperties()
$this->documentManager->clear();

$document = $this->documentManager->find($article['id'], $this->locale);
$this->indexer->index($document);
$this->indexer->flush();
$this->liveIndexer->index($document);
$this->liveIndexer->flush();

$viewDocument = $this->findViewDocument($article['id']);
$viewDocument = $this->findLiveViewDocument($article['id']);
$contentFields = $viewDocument->getContentFields();

$this->assertSame($article['id'], $viewDocument->getUuid());
Expand Down Expand Up @@ -496,10 +552,10 @@ public function testIndexTaggedPropertiesBlocksInBlocks(): void
$this->documentManager->clear();

$document = $this->documentManager->find($article['id'], $this->locale);
$this->indexer->index($document);
$this->indexer->flush();
$this->liveIndexer->index($document);
$this->liveIndexer->flush();

$viewDocument = $this->findViewDocument($article['id']);
$viewDocument = $this->findLiveViewDocument($article['id']);
$contentFields = $viewDocument->getContentFields();

$this->assertEquals($article['id'], $viewDocument->getUuid());
Expand Down Expand Up @@ -532,10 +588,10 @@ public function testIndexContentData()
$this->documentManager->clear();

$document = $this->documentManager->find($article['id'], $this->locale);
$this->indexer->index($document);
$this->indexer->flush();
$this->liveIndexer->index($document);
$this->liveIndexer->flush();

$viewDocument = $this->findViewDocument($article['id']);
$viewDocument = $this->findLiveViewDocument($article['id']);
$this->assertEquals($article['id'], $viewDocument->getUuid());
$this->assertEquals($data, \json_decode($viewDocument->getContentData(), true));

Expand Down Expand Up @@ -694,7 +750,23 @@ private function createPage($title = 'Test Page', $resourceSegment = '/test-page
}

/**
* Find view-document.
* Find view-document in live index.
*
* @param string $uuid
* @param string $locale
*
* @return ArticleViewDocument
*/
private function findLiveViewDocument($uuid, $locale = null)
{
return $this->liveManager->find(
$this->getContainer()->getParameter('sulu_article.view_document.article.class'),
$uuid . '-' . ($locale ? $locale : $this->locale)
);
}

/**
* Find view-document in live index.
*
* @param string $uuid
* @param string $locale
Expand Down
Loading

0 comments on commit 12e25e9

Please sign in to comment.