Skip to content

Commit

Permalink
Merge branch '3.3-release'
Browse files Browse the repository at this point in the history
  • Loading branch information
emodric committed Feb 22, 2018
2 parents 6b64c8c + 1648291 commit e09c7bf
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 143 deletions.
276 changes: 276 additions & 0 deletions bundle/Core/Persistence/Cache/TagsHandler.php
@@ -0,0 +1,276 @@
<?php

namespace Netgen\TagsBundle\Core\Persistence\Cache;

use eZ\Publish\Core\Persistence\Cache\PersistenceLogger;
use Netgen\TagsBundle\SPI\Persistence\Tags\CreateStruct;
use Netgen\TagsBundle\SPI\Persistence\Tags\Handler as TagsHandlerInterface;
use Netgen\TagsBundle\SPI\Persistence\Tags\SynonymCreateStruct;
use Netgen\TagsBundle\SPI\Persistence\Tags\UpdateStruct;
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;

class TagsHandler implements TagsHandlerInterface
{
const ALL_TRANSLATIONS_KEY = '0';

/**
* @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface
*/
protected $cache;

/**
* @var \Netgen\TagsBundle\SPI\Persistence\Tags\Handler
*/
protected $tagsHandler;

/**
* @var \eZ\Publish\Core\Persistence\Cache\PersistenceLogger
*/
protected $logger;

public function __construct(TagAwareAdapterInterface $cache, TagsHandlerInterface $tagsHandler, PersistenceLogger $logger)
{
$this->cache = $cache;
$this->tagsHandler = $tagsHandler;
$this->logger = $logger;
}

public function load($tagId, array $translations = null, $useAlwaysAvailable = true)
{
$translationsKey = empty($translations) ? self::ALL_TRANSLATIONS_KEY : implode('|', $translations);
$alwaysAvailableKey = $useAlwaysAvailable ? '1' : '0';
$cacheItem = $this->cache->getItem("netgen-tag-${tagId}-${translationsKey}-${alwaysAvailableKey}");
if ($cacheItem->isHit()) {
return $cacheItem->get();
}

$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));
$tag = $this->tagsHandler->load($tagId, $translations, $useAlwaysAvailable);
$cacheItem->set($tag);
$cacheItem->tag($this->getCacheTags($tag->id, $tag->pathString));
$this->cache->save($cacheItem);

return $tag;
}

public function loadTagInfo($tagId)
{
$cacheItem = $this->cache->getItem("netgen-tag-info-${tagId}");
if ($cacheItem->isHit()) {
return $cacheItem->get();
}

$this->logger->logCall(__METHOD__, array('tag' => $tagId));
$tagInfo = $this->tagsHandler->loadTagInfo($tagId);
$cacheItem->set($tagInfo);
$cacheItem->tag($this->getCacheTags($tagInfo->id, $tagInfo->pathString));
$this->cache->save($cacheItem);

return $tagInfo;
}

public function loadByRemoteId($remoteId, array $translations = null, $useAlwaysAvailable = true)
{
$translationsKey = empty($translations) ? self::ALL_TRANSLATIONS_KEY : implode('|', $translations);
$alwaysAvailableKey = $useAlwaysAvailable ? '1' : '0';
$cacheItem = $this->cache->getItem("netgen-tag-byRemoteId-${remoteId}-${translationsKey}-${alwaysAvailableKey}");
if ($cacheItem->isHit()) {
return $cacheItem->get();
}

$this->logger->logCall(__METHOD__, array('tag' => $remoteId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));
$tag = $this->tagsHandler->loadByRemoteId($remoteId, $translations, $useAlwaysAvailable);
$cacheItem->set($tag);
$cacheItem->tag($this->getCacheTags($tag->id, $tag->pathString));
$this->cache->save($cacheItem);

return $tag;
}

public function loadTagInfoByRemoteId($remoteId)
{
$cacheItem = $this->cache->getItem("netgen-tag-info-byRemoteId-${remoteId}");
if ($cacheItem->isHit()) {
return $cacheItem->get();
}

$this->logger->logCall(__METHOD__, array('tag' => $remoteId));
$tagInfo = $this->tagsHandler->loadTagInfoByRemoteId($remoteId);
$cacheItem->set($tagInfo);
$cacheItem->tag($this->getCacheTags($tagInfo->id, $tagInfo->pathString));
$this->cache->save($cacheItem);

return $tagInfo;
}

public function loadTagByKeywordAndParentId($keyword, $parentTagId, array $translations = null, $useAlwaysAvailable = true)
{
$this->logger->logCall(__METHOD__, array('keyword' => $keyword, 'parentTag' => $parentTagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->loadTagByKeywordAndParentId($keyword, $parentTagId, $translations, $useAlwaysAvailable);
}

public function loadChildren($tagId, $offset = 0, $limit = -1, array $translations = null, $useAlwaysAvailable = true)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->loadChildren($tagId, $offset, $limit, $translations, $useAlwaysAvailable);
}

public function getChildrenCount($tagId, array $translations = null, $useAlwaysAvailable = true)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->getChildrenCount($tagId, $translations, $useAlwaysAvailable);
}

public function loadTagsByKeyword($keyword, $translation, $useAlwaysAvailable = true, $offset = 0, $limit = -1)
{
$this->logger->logCall(__METHOD__, array('keyword' => $keyword, 'translation' => $translation, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->loadTagsByKeyword($keyword, $translation, $useAlwaysAvailable, $offset, $limit);
}

public function getTagsByKeywordCount($keyword, $translation, $useAlwaysAvailable = true)
{
$this->logger->logCall(__METHOD__, array('keyword' => $keyword, 'translation' => $translation, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->getTagsByKeywordCount($keyword, $translation, $useAlwaysAvailable);
}

public function searchTags($searchString, $translation, $useAlwaysAvailable = true, $offset = 0, $limit = -1)
{
$this->logger->logCall(__METHOD__, array('searchString' => $searchString, 'translation' => $translation, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->searchTags($searchString, $translation, $useAlwaysAvailable, $offset, $limit);
}

public function loadSynonyms($tagId, $offset = 0, $limit = -1, array $translations = null, $useAlwaysAvailable = true)
{
// Method caches all synonyms in cache and only uses offset / limit to slice the cached result
$translationsKey = empty($translations) ? self::ALL_TRANSLATIONS_KEY : implode('|', $translations);
$alwaysAvailableKey = $useAlwaysAvailable ? '1' : '0';
$cacheItem = $this->cache->getItem("netgen-tag-synonyms-${tagId}-${translationsKey}-${alwaysAvailableKey}");
if ($cacheItem->isHit()) {
return array_slice($cacheItem->get(), $offset, $limit > -1 ? $limit : null);
}

$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));

$tagInfo = $this->loadTagInfo($tagId);
$synonyms = $this->tagsHandler->loadSynonyms($tagId, 0, null, $translations, $useAlwaysAvailable);

$cacheItem->set($synonyms);
$cacheTags = $this->getCacheTags($tagInfo->id, $tagInfo->pathString);
foreach ($synonyms as $synonym) {
$cacheTags = array_merge($cacheTags, $this->getCacheTags($synonym->id, $synonym->pathString));
}
$cacheItem->tag(array_unique($cacheTags));
$this->cache->save($cacheItem);

return array_slice($synonyms, $offset, $limit > -1 ? $limit : null);
}

public function getSynonymCount($tagId, array $translations = null, $useAlwaysAvailable = true)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'translations' => $translations, 'useAlwaysAvailable' => $useAlwaysAvailable));

return $this->tagsHandler->getSynonymCount($tagId, $translations, $useAlwaysAvailable);
}

public function create(CreateStruct $createStruct)
{
$this->logger->logCall(__METHOD__, array('struct' => $createStruct));

return $this->tagsHandler->create($createStruct);
}

public function update(UpdateStruct $updateStruct, $tagId)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'struct' => $updateStruct));
$updatedTag = $this->tagsHandler->update($updateStruct, $tagId);

$this->cache->invalidateTags(array('tag-' . $tagId));

return $updatedTag;
}

public function addSynonym(SynonymCreateStruct $createStruct)
{
$this->logger->logCall(__METHOD__, array('struct' => $createStruct));
$synonym = $this->tagsHandler->addSynonym($createStruct);

$this->cache->invalidateTags(array('tag-' . $createStruct->mainTagId));

return $synonym;
}

public function convertToSynonym($tagId, $mainTagId)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId));
$synonym = $this->tagsHandler->convertToSynonym($tagId, $mainTagId);

$this->cache->invalidateTags(array('tag-' . $tagId, 'tag-' . $mainTagId));

return $synonym;
}

public function merge($tagId, $targetTagId)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId, 'targetTag' => $targetTagId));

$this->tagsHandler->merge($tagId, $targetTagId);

$this->cache->invalidateTags(array('tag-path-' . $tagId, 'tag-path-' . $targetTagId));
}

public function copySubtree($sourceId, $destinationParentId)
{
$this->logger->logCall(__METHOD__, array('sourceTag' => $sourceId, 'destinationTag' => $destinationParentId));

$return = $this->tagsHandler->copySubtree($sourceId, $destinationParentId);

$this->cache->invalidateTags(array('tag-path-' . $sourceId, 'tag-path-' . $destinationParentId));

return $return;
}

public function moveSubtree($sourceId, $destinationParentId)
{
$this->logger->logCall(__METHOD__, array('sourceTag' => $sourceId, 'destinationTag' => $destinationParentId));

$return = $this->tagsHandler->moveSubtree($sourceId, $destinationParentId);

$this->cache->invalidateTags(array('tag-path-' . $sourceId, 'tag-path-' . $destinationParentId));

return $return;
}

public function deleteTag($tagId)
{
$this->logger->logCall(__METHOD__, array('tag' => $tagId));
$this->tagsHandler->deleteTag($tagId);

$this->cache->invalidateTags(array('tag-path-' . $tagId));
}

/**
* Return relevant cache tags so cache can be purged reliably.
*
* @param int $tagId
* @param string $pathString
* @param array $tags optional, can be used to specify additional tags
*
* @return array
*/
private function getCacheTags($tagId, $pathString, array $tags = array())
{
$tags[] = 'tag-' . $tagId;

foreach (explode('/', trim($pathString, '/')) as $pathId) {
$tags[] = 'tag-path-' . $pathId;
}

return $tags;
}
}
8 changes: 0 additions & 8 deletions bundle/Core/Persistence/Legacy/Tags/Gateway.php
Expand Up @@ -202,12 +202,4 @@ abstract public function moveSubtree(array $sourceTagData, array $destinationPar
* @param mixed $tagId
*/
abstract public function deleteTag($tagId);

/**
* Updated subtree modification time for all tags in path.
*
* @param string $pathString
* @param int $timestamp
*/
abstract public function updateSubtreeModificationTime($pathString, $timestamp = null);
}
46 changes: 15 additions & 31 deletions bundle/Core/Persistence/Legacy/Tags/Gateway/DoctrineDatabase.php
Expand Up @@ -510,6 +510,9 @@ public function create(CreateStruct $createStruct, array $parentTag = null)
)->set(
$this->handler->quoteColumn('main_tag_id'),
$query->bindValue(0, null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('modified'),
$query->bindValue(time(), null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('keyword'),
$query->bindValue($createStruct->keywords[$createStruct->mainLanguageCode], null, PDO::PARAM_STR)
Expand Down Expand Up @@ -585,6 +588,9 @@ public function update(UpdateStruct $updateStruct, $tagId)
$query
->update($this->handler->quoteTable('eztags'))
->set(
$this->handler->quoteColumn('modified'),
$query->bindValue(time(), null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('keyword'),
$query->bindValue($updateStruct->keywords[$updateStruct->mainLanguageCode], null, PDO::PARAM_STR)
)->set(
Expand Down Expand Up @@ -660,6 +666,9 @@ public function createSynonym(SynonymCreateStruct $createStruct, array $tag)
)->set(
$this->handler->quoteColumn('main_tag_id'),
$query->bindValue($createStruct->mainTagId, null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('modified'),
$query->bindValue(time(), null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('keyword'),
$query->bindValue($createStruct->keywords[$createStruct->mainLanguageCode], null, PDO::PARAM_STR)
Expand Down Expand Up @@ -740,6 +749,9 @@ public function convertToSynonym($tagId, $mainTagData)
)->set(
$this->handler->quoteColumn('main_tag_id'),
$query->bindValue($mainTagData['id'], null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('modified'),
$query->bindValue(time(), null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('depth'),
$query->bindValue($mainTagData['depth'], null, PDO::PARAM_INT)
Expand Down Expand Up @@ -913,6 +925,9 @@ public function moveSubtree(array $sourceTagData, array $destinationParentTagDat
)->set(
$this->handler->quoteColumn('depth'),
$query->bindValue($newDepth, null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('modified'),
$query->bindValue(time(), null, PDO::PARAM_INT)
)->set(
$this->handler->quoteColumn('parent_id'),
$query->bindValue($newParentId, null, PDO::PARAM_INT)
Expand Down Expand Up @@ -1002,37 +1017,6 @@ public function deleteTag($tagId)
$query->prepare()->execute();
}

/**
* Updated subtree modification time for all tags in path.
*
* @param string $pathString
* @param int $timestamp
*/
public function updateSubtreeModificationTime($pathString, $timestamp = null)
{
$tagIds = array_filter(explode('/', $pathString));

if (empty($tagIds)) {
return;
}

$query = $this->handler->createUpdateQuery();
$query
->update($this->handler->quoteTable('eztags'))
->set(
$this->handler->quoteColumn('modified'),
$query->bindValue($timestamp ?: time(), null, PDO::PARAM_INT)
)
->where(
$query->expr->in(
$this->handler->quoteColumn('id'),
$tagIds
)
);

$query->prepare()->execute();
}

/**
* Creates a select query for tag objects that fetches only tag IDs.
*
Expand Down

0 comments on commit e09c7bf

Please sign in to comment.