Skip to content

Commit

Permalink
added indexing for live and basic data-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes committed Jul 27, 2016
1 parent d5805c5 commit f554841
Show file tree
Hide file tree
Showing 14 changed files with 833 additions and 36 deletions.
8 changes: 7 additions & 1 deletion Command/ReindexCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function configure()
{
$this->setName('sulu:article:index-rebuild')
->addArgument('locale', InputArgument::REQUIRED)
->addOption('live', 'l', InputOption::VALUE_NONE)
->addOption('clear', null, InputOption::VALUE_NONE);
}

Expand All @@ -38,7 +39,12 @@ public function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$indexer = $this->getContainer()->get('sulu_article.elastic_search.article_indexer');
$id = 'sulu_article.elastic_search.article_indexer';
if ($input->getOption('live')) {
$id = 'sulu_article.elastic_search.article_live_indexer';
}

$indexer = $this->getContainer()->get($id);
$documentManager = $this->getContainer()->get('sulu_document_manager.document_manager');
$query = $documentManager->createQuery(
'SELECT * FROM [nt:unstructured] AS a WHERE [jcr:mixinTypes] = "sulu:article"'
Expand Down
68 changes: 68 additions & 0 deletions Content/ArticleDataItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Sulu\Bundle\ArticleBundle\Content;

use Sulu\Bundle\ArticleBundle\Document\ArticleOngrDocument;
use Sulu\Component\SmartContent\ItemInterface;

class ArticleDataItem implements ItemInterface
{
/**
* @var string
*/
private $id;

/**
* @var string
*/
private $title;

/**
* @var ArticleOngrDocument
*/
private $resource;

/**
* @param string $id
* @param string $title
* @param ArticleOngrDocument $resource
*/
public function __construct($id, $title, ArticleOngrDocument $resource)
{
$this->id = $id;
$this->title = $title;
$this->resource = $resource;
}

/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
}

/**
* {@inheritdoc}
*/
public function getTitle()
{
return $this->title;
}

/**
* {@inheritdoc}
*/
public function getResource()
{
return $this->resource;
}

/**
* {@inheritdoc}
*/
public function getImage()
{
return null;
}
}
294 changes: 294 additions & 0 deletions Content/ArticleDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
<?php

namespace Sulu\Bundle\ArticleBundle\Content;

use ONGR\ElasticsearchBundle\Result\DocumentIterator;
use ONGR\ElasticsearchBundle\Service\Manager;
use ONGR\ElasticsearchDSL\Query\BoolQuery;
use ONGR\ElasticsearchDSL\Query\MatchAllQuery;
use ONGR\ElasticsearchDSL\Query\TermQuery;
use ONGR\ElasticsearchDSL\Search;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
use Sulu\Bundle\ArticleBundle\Document\ArticleOngrDocument;
use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Sulu\Component\SmartContent\Configuration\Builder;
use Sulu\Component\SmartContent\DataProviderInterface;
use Sulu\Component\SmartContent\DataProviderResult;

class ArticleDataProvider implements DataProviderInterface
{
/**
* @var Manager
*/
private $searchManager;

/**
* @var DocumentManagerInterface
*/
private $documentManager;

/**
* @var LazyLoadingValueHolderFactory
*/
private $proxyFactory;

/**
* @param Manager $searchManager
* @param DocumentManagerInterface $documentManager
* @param LazyLoadingValueHolderFactory $proxyFactory
*/
public function __construct(
Manager $searchManager,
DocumentManagerInterface $documentManager,
LazyLoadingValueHolderFactory $proxyFactory
) {
$this->searchManager = $searchManager;
$this->documentManager = $documentManager;
$this->proxyFactory = $proxyFactory;
}

/**
* {@inheritdoc}
*/
public function getConfiguration()
{
return Builder::create()
->enableTags()
->enableCategories()
->enableLimit()
->enablePagination()
->enablePresentAs()
->setDeepLink('article/{locale}/edit:{id}/details')
->getConfiguration();
}

/**
* {@inheritdoc}
*/
public function getDefaultPropertyParameter()
{
return [];
}

/**
* {@inheritdoc}
*/
public function resolveDataItems(
array $filters,
array $propertyParameter,
array $options = [],
$limit = null,
$page = 1,
$pageSize = null
) {
$result = [];
$uuids = [];
/** @var ArticleOngrDocument $document */
foreach ($this->getSearchResult($filters, $limit, $page, $pageSize) as $document) {
$uuids[] = $document->getUuid();
$result[] = new ArticleDataItem($document->getUuid(), $document->getTitle(), $document);
}

return new DataProviderResult($result, false, $uuids);
}

/**
* {@inheritdoc}
*/
public function resolveResourceItems(
array $filters,
array $propertyParameter,
array $options = [],
$limit = null,
$page = 1,
$pageSize = null
) {
$result = [];
$uuids = [];
/** @var ArticleOngrDocument $document */
foreach ($this->getSearchResult($filters, $limit, $page, $pageSize) as $document) {
$uuids[] = $document->getUuid();
$result[] = new ArticleResourceItem(
$document,
$this->getResource($document->getUuid(), $document->getLocale())
);
}

return new DataProviderResult($result, false, $uuids);
}

/**
* {@inheritdoc}
*/
public function resolveDatasource($datasource, array $propertyParameter, array $options)
{
return null;
}

/**
* Creates search for filters and returns search-result.
*
* @param array $filters
* @param int $limit
* @param int $page
* @param int $pageSize
*
* @return DocumentIterator
*/
private function getSearchResult(array $filters, $limit, $page, $pageSize)
{
$repository = $this->searchManager->getRepository(ArticleOngrDocument::class);
$search = $repository->createSearch();

$query = new BoolQuery();

$queriesCount = 0;
$operator = $this->getFilter($filters, 'tagOperator', 'or');
$this->addBoolQuery('tags', $filters, 'excerpt.tags', $operator, $query, $queriesCount);
$operator = $this->getFilter($filters, 'websiteTagsOperator', 'or');
$this->addBoolQuery('websiteTags', $filters, 'excerpt.tags', $operator, $query, $queriesCount);

$operator = $this->getFilter($filters, 'categoryOperator', 'or');
$this->addBoolQuery('categories', $filters, 'excerpt.categories', $operator, $query, $queriesCount);
$operator = $this->getFilter($filters, 'websiteCategoriesOperator', 'or');
$this->addBoolQuery('websiteCategories', $filters, 'excerpt.categories', $operator, $query, $queriesCount);

if (0 === $queriesCount) {
$search->addQuery(new MatchAllQuery());
} else {
$search->addQuery($query);
}

if (null !== $pageSize) {
$this->addPagination($search, $pageSize, $page, $limit);
} elseif (null !== $limit) {
$search->setSize($limit);
}

return $repository->execute($search);
}

/**
* Add the pagination to given query.
*
* @param Search $search
* @param int $pageSize
* @param int $page
* @param int $limit
*/
private function addPagination(Search $search, $pageSize, $page, $limit)
{
$pageSize = intval($pageSize);
$offset = ($page - 1) * $pageSize;

$position = $pageSize * $page;
if ($limit !== null && $position >= $limit) {
$pageSize = $limit - $offset;
$loadLimit = $pageSize;
} else {
$loadLimit = $pageSize;
}

$search->setSize($loadLimit);
$search->setFrom($offset);
}

/**
* Add a boolean-query if filter exists.
*
* @param string $filterName
* @param array $filters
* @param string $field
* @param string $operator
* @param BoolQuery $query
* @param int $queriesCount
*/
private function addBoolQuery($filterName, array $filters, $field, $operator, BoolQuery $query, &$queriesCount)
{
if (0 !== count($tags = $this->getFilter($filters, $filterName))) {
$queriesCount++;
$query->add($this->getBoolQuery($field, $tags, $operator));
}
}

/**
* Returns boolean query for given fields and values.
*
* @param string $field
* @param array $values
* @param string $operator
*
* @return BoolQuery
*/
private function getBoolQuery($field, array $values, $operator)
{
$type = ('or' === strtolower($operator) ? BoolQuery::SHOULD : BoolQuery::MUST);

$query = new BoolQuery();
foreach ($values as $value) {
$query->add(new TermQuery($field, $value), $type);
}

return $query;
}

/**
* Returns filter value.
*
* @param array $filters
* @param string $name
* @param mixed $default
*
* @return mixed
*/
private function getFilter(array $filters, $name, $default = null)
{
if ($this->hasFilter($filters, $name)) {
return $filters[$name];
}

return $default;
}

/**
* Returns true if filter-value exists.
*
* @param array $filters
* @param string $name
*
* @return bool
*/
private function hasFilter(array $filters, $name)
{
return array_key_exists($name, $filters) && null !== $filters[$name];
}

/**
* Returns Proxy document for uuid.
*
* @param string $uuid
* @param string $locale
*
* @return object
*/
private function getResource($uuid, $locale)
{
return $this->proxyFactory->createProxy(
ArticleDocument::class,
function (
&$wrappedObject,
LazyLoadingInterface $proxy,
$method,
array $parameters,
&$initializer
) use ($uuid, $locale) {
$initializer = null;
$wrappedObject = $this->documentManager->find($uuid, $locale);

return true;
}
);
}
}
Loading

0 comments on commit f554841

Please sign in to comment.