Add Form for ElasticSearch Configuration.

Also changed type from array to Options object.
This commit is contained in:
Benoît Burnichon
2015-06-29 15:04:50 +02:00
parent 7271e28cf5
commit 28fee99fc4
20 changed files with 306 additions and 332 deletions

View File

@@ -10,37 +10,62 @@
namespace Alchemy\Phrasea\Controller\Admin; namespace Alchemy\Phrasea\Controller\Admin;
use Alchemy\Phrasea\SearchEngine\ConfigurationPanelInterface; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticSearchSettingFormType;
use Alchemy\Phrasea\SearchEngine\Elastic\GlobalElasticOptions;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
class SearchEngineController class SearchEngineController extends Controller
{ {
/**
* @var ConfigurationPanelInterface
*/
private $configurationPanel;
public function __construct(ConfigurationPanelInterface $configurationPanel)
{
$this->configurationPanel = $configurationPanel;
}
/** /**
* @param Request $request * @param Request $request
* @return Response * @return Response
*/ */
public function getConfigurationPanelAction(Request $request) public function formConfigurationPanelAction(Request $request)
{ {
return $this->configurationPanel->get($request); $options = $this->getElasticSearchOptions();
$form = $this->getConfigurationForm($options);
$form->handleRequest($request);
if ($form->isValid()) {
$this->saveElasticSearchOptions($form->getData());
return $this->app->redirectPath('admin_searchengine_form');
}
return $this->render('admin/search-engine/elastic-search.html.twig', [
'form' => $form->createView(),
]);
} }
/** /**
* @param Request $request * @return GlobalElasticOptions
* @return Response
*/ */
public function postConfigurationPanelAction(Request $request) private function getElasticSearchOptions()
{ {
return $this->configurationPanel->post($request); return $this->app['elasticsearch.options'];
}
/**
* @param GlobalElasticOptions $configuration
* @return void
*/
private function saveElasticSearchOptions(GlobalElasticOptions $configuration)
{
$this->getConf()->set(['main', 'search-engine', 'options'], $configuration->toArray());
}
/**
* @param GlobalElasticOptions $options
* @return FormInterface
*/
private function getConfigurationForm(GlobalElasticOptions $options)
{
return $this->app->form(new ElasticSearchSettingFormType(), $options, [
'action' => $this->app->url('admin_searchengine_form'),
]);
} }
} }

View File

@@ -356,7 +356,7 @@ class V1Controller extends Controller
'engine' => [ 'engine' => [
'type' => $searchEngine->getName(), 'type' => $searchEngine->getName(),
'status' => $SEStatus, 'status' => $SEStatus,
'configuration' => $searchEngine->getConfigurationPanel()->getConfiguration(), 'configuration' => $conf->get(['main', 'searchengine', 'options']),
], ],
], ],
'binary' => [ 'binary' => [

View File

@@ -9,7 +9,6 @@
*/ */
namespace Alchemy\Phrasea\Controller\Prod; namespace Alchemy\Phrasea\Controller\Prod;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Controller\RecordsRequest;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;

View File

@@ -24,9 +24,7 @@ class SearchEngine implements ControllerProviderInterface, ServiceProviderInterf
public function register(Application $app) public function register(Application $app)
{ {
$app['controller.admin.search-engine'] = $app->share(function (PhraseaApplication $app) { $app['controller.admin.search-engine'] = $app->share(function (PhraseaApplication $app) {
/** @var SearchEngineInterface $searchEngine */ return new SearchEngineController($app);
$searchEngine = $app['search_engine'];
return new SearchEngineController($searchEngine->getConfigurationPanel());
}); });
} }
@@ -39,11 +37,9 @@ class SearchEngine implements ControllerProviderInterface, ServiceProviderInterf
/** @var ControllerCollection $controllers */ /** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory']; $controllers = $app['controllers_factory'];
$controllers->get('/', 'controller.admin.search-engine:getConfigurationPanelAction') $controllers->match('/', 'controller.admin.search-engine:formConfigurationPanelAction')
->bind('admin_searchengine_get'); ->method('GET|POST')
->bind('admin_searchengine_form');
$controllers->post('/', 'controller.admin.search-engine:postConfigurationPanelAction')
->bind('admin_searchengine_post');
return $controllers; return $controllers;
} }

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\Core\Provider; namespace Alchemy\Phrasea\Core\Provider;
use Alchemy\Phrasea\Controller\LazyLocator; use Alchemy\Phrasea\Controller\LazyLocator;
use Alchemy\Phrasea\SearchEngine\Elastic\GlobalElasticOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger; use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface; use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
@@ -53,11 +54,14 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
if ($type !== SearchEngineInterface::TYPE_ELASTICSEARCH) { if ($type !== SearchEngineInterface::TYPE_ELASTICSEARCH) {
throw new InvalidArgumentException(sprintf('Invalid search engine type "%s".', $type)); throw new InvalidArgumentException(sprintf('Invalid search engine type "%s".', $type));
} }
/** @var GlobalElasticOptions $options */
$options = $app['elasticsearch.options'];
return new ElasticSearchEngine( return new ElasticSearchEngine(
$app, $app,
$app['search_engine.structure'], $app['search_engine.structure'],
$app['elasticsearch.client'], $app['elasticsearch.client'],
$app['elasticsearch.options']['index'], $options->getIndexName(),
$app['locales.available'], $app['locales.available'],
$app['elasticsearch.facets_response.factory'] $app['elasticsearch.facets_response.factory']
); );
@@ -132,11 +136,13 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
/* Low-level elasticsearch services */ /* Low-level elasticsearch services */
$app['elasticsearch.client'] = $app->share(function($app) { $app['elasticsearch.client'] = $app->share(function($app) {
/** @var GlobalElasticOptions $options */
$options = $app['elasticsearch.options']; $options = $app['elasticsearch.options'];
$clientParams = ['hosts' => [sprintf('%s:%s', $options['host'], $options['port'])]]; $clientParams = ['hosts' => [sprintf('%s:%s', $options->getHost(), $options->getPort())]];
// Create file logger for debug // Create file logger for debug
if ($app['debug']) { if ($app['debug']) {
/** @var Logger $logger */
$logger = new $app['monolog.logger.class']('search logger'); $logger = new $app['monolog.logger.class']('search logger');
$logger->pushHandler(new RotatingFileHandler($app['log.path'].DIRECTORY_SEPARATOR.'elasticsearch.log', 2), Logger::INFO); $logger->pushHandler(new RotatingFileHandler($app['log.path'].DIRECTORY_SEPARATOR.'elasticsearch.log', 2), Logger::INFO);
@@ -148,22 +154,16 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
}); });
$app['elasticsearch.options'] = $app->share(function($app) { $app['elasticsearch.options'] = $app->share(function($app) {
$options = $app['conf']->get(['main', 'search-engine', 'options'], []); $options = GlobalElasticOptions::fromArray($app['conf']->get(['main', 'search-engine', 'options'], []));
$indexName = sprintf('phraseanet_%s', str_replace( if (empty($options->getIndexName())) {
array('/', '.'), array('', ''), $options->setIndexName(strtolower(sprintf('phraseanet_%s', str_replace(
$app['conf']->get(['main', 'key']) array('/', '.'), array('', ''),
)); $app['conf']->get(['main', 'key'])
))));
}
$defaults = [ return $options;
'host' => '127.0.0.1',
'port' => 9200,
'index' => strtolower($indexName),
'shards' => 3,
'replicas' => 0
];
return array_replace($defaults, $options);
}); });
@@ -175,7 +175,7 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
$logger->pushHandler(new \Monolog\Handler\ErrorLogHandler()); $logger->pushHandler(new \Monolog\Handler\ErrorLogHandler());
return new Thesaurus( return new Thesaurus(
$app['elasticsearch.client'], $app['elasticsearch.client'],
$app['elasticsearch.options']['index'], $app['elasticsearch.options'],
$logger $logger
); );
}); });

View File

@@ -1,57 +0,0 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\SearchEngine;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
abstract class AbstractConfigurationPanel implements ConfigurationPanelInterface
{
/** @var PropertyAccess */
protected $conf;
public function __construct(PropertyAccess $conf)
{
$this->conf = $conf;
}
/**
* @param \databox[] $databoxes
* @return array
*/
public function getAvailableDateFields(array $databoxes)
{
$date_fields = [];
foreach ($databoxes as $databox) {
/** @var \databox_field $field */
foreach ($databox->get_meta_structure() as $field) {
if ($field->get_type() !== \databox_field::TYPE_DATE) {
continue;
}
$date_fields[] = $field->get_name();
}
}
return $date_fields;
}
/**
* {@inheritdoc}
*/
public function saveConfiguration(array $configuration)
{
$this->conf->set(['main', 'search-engine', 'options'], $configuration);
return $this;
}
}

View File

@@ -1,65 +0,0 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\SearchEngine;
use Alchemy\Phrasea\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
interface ConfigurationPanelInterface
{
/**
* Handles the GET request to the configuration panel
*
* @param Request $request
* @return Response
*/
public function get(Request $request);
/**
* Handles the POST request to the configuration panel
*
* @param Request $request
* @return Response
*/
public function post(Request $request);
/**
* Return the associated search engine name
*
* @return string The name
*/
public function getName();
/**
* Returns the configuration of the search engine
*
* @return array The configuration
*/
public function getConfiguration();
/**
* Saves the search engine configuration
*
* @param array $configuration
* @return ConfigurationPanelInterface
*/
public function saveConfiguration(array $configuration);
/**
* Return the names of the date fields
*
* @param \databox[] $databoxes
* @return array An array of date fields names
*/
public function getAvailableDateFields(array $databoxes);
}

View File

@@ -1,68 +0,0 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\SearchEngine\Elastic;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\SearchEngine\AbstractConfigurationPanel;
use Symfony\Component\HttpFoundation\Request;
class ConfigurationPanel extends AbstractConfigurationPanel
{
/** @var Application */
private $app;
public function __construct(Application $app, PropertyAccess $conf)
{
parent::__construct($conf);
$this->app = $app;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'elastic-search-engine';
}
/**
* {@inheritdoc}
*/
public function get(Request $request)
{
return $this->app['twig']->render('admin/search-engine/elastic-search.html.twig', ['configuration' => $this->getConfiguration()]);
}
/**
* {@inheritdoc}
*/
public function post(Request $request)
{
$configuration = $this->getConfiguration();
$configuration['host'] = $request->request->get('host');
$configuration['port'] = $request->request->get('port');
$this->saveConfiguration($configuration);
return $this->app->redirectPath('admin_searchengine_get');
}
/**
* {@inheritdoc}
*/
public function getConfiguration()
{
return $this->conf->get(['main', 'search-engine', 'options'], []);
}
}

View File

@@ -100,18 +100,6 @@ class ElasticSearchEngine implements SearchEngineInterface
return $ret; return $ret;
} }
/**
* {@inheritdoc}
*/
public function getConfigurationPanel()
{
if (!$this->configurationPanel) {
$this->configurationPanel = new ConfigurationPanel($this->app, $this->app['conf']);
}
return $this->configurationPanel;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\SearchEngine\Elastic;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Range;
class ElasticSearchSettingFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('host', 'text', [
'label' => 'ElasticSearch server host',
])
->add('port', 'integer', [
'label' => 'ElasticSearch service port',
'constraints' => new Range(['min' => 1, 'max' => 65535]),
])
->add('indexName', 'text', [
'label' => 'ElasticSearch index name',
'constraints' => new NotBlank(),
])
->add('shards', 'integer', [
'label' => 'Number of shards',
'constraints' => new Range(['min' => 1]),
])
->add('replicas', 'integer', [
'label' => 'Number of replicas',
'constraints' => new Range(['min' => 0]),
])
->add('minScore', 'integer', [
'label' => 'Thesaurus Min score',
'constraints' => new Range(['min' => 0]),
])
->add('save', 'submit')
;
}
public function getName()
{
return 'elastic_settings';
}
}

View File

@@ -0,0 +1,165 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\SearchEngine\Elastic;
class GlobalElasticOptions
{
/** @var string */
private $host;
/** @var int */
private $port;
/** @var string */
private $indexName;
/** @var int */
private $shards;
/** @var int */
private $replicas;
/** @var int */
private $minScore;
/**
* Factory method to hydrate an instance from serialized options
*
* @param array $options
* @return self
*/
public static function fromArray(array $options)
{
$options = array_replace([
'host' => '127.0.0.1',
'port' => 9200,
'index' => '',
'shards' => 3,
'replicas' => 0,
'minScore' => 4,
], $options);
$self = new self();
$self->setHost($options['host']);
$self->setPort($options['port']);
$self->setIndexName($options['index']);
$self->setShards($options['shards']);
$self->setReplicas($options['replicas']);
$self->setMinScore($options['minScore']);
return $self;
}
/**
* @return array
*/
public function toArray()
{
return [
'host' => $this->host,
'port' => $this->port,
'index' => $this->indexName,
'shards' => $this->shards,
'replicas' => $this->replicas,
'minScore' => $this->minScore,
];
}
/**
* @param string $host
*/
public function setHost($host)
{
$this->host = $host;
}
/**
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* @param int $port
*/
public function setPort($port)
{
$this->port = (int)$port;
}
/**
* @return int
*/
public function getPort()
{
return $this->port;
}
/**
* @param int $minScore
*/
public function setMinScore($minScore)
{
$this->minScore = (int)$minScore;
}
/**
* @return int
*/
public function getMinScore()
{
return $this->minScore;
}
/**
* @param string $indexName
*/
public function setIndexName($indexName)
{
$this->indexName = $indexName;
}
/**
* @return string
*/
public function getIndexName()
{
return $this->indexName;
}
/**
* @param int $shards
*/
public function setShards($shards)
{
$this->shards = (int)$shards;
}
/**
* @return int
*/
public function getShards()
{
return $this->shards;
}
/**
* @param int $replicas
*/
public function setReplicas($replicas)
{
$this->replicas = (int)$replicas;
}
/**
* @return int
*/
public function getReplicas()
{
return $this->replicas;
}
}

View File

@@ -32,6 +32,7 @@ class Indexer
/** @var \Elasticsearch\Client */ /** @var \Elasticsearch\Client */
private $client; private $client;
/** @var GlobalElasticOptions */
private $options; private $options;
private $appbox; private $appbox;
/** @var LoggerInterface|null */ /** @var LoggerInterface|null */
@@ -48,7 +49,7 @@ class Indexer
const DEFAULT_REFRESH_INTERVAL = '1s'; const DEFAULT_REFRESH_INTERVAL = '1s';
const REFRESH_INTERVAL_KEY = 'index.refresh_interval'; const REFRESH_INTERVAL_KEY = 'index.refresh_interval';
public function __construct(Client $client, array $options, TermIndexer $termIndexer, RecordIndexer $recordIndexer, appbox $appbox, LoggerInterface $logger = null) public function __construct(Client $client, GlobalElasticOptions $options, TermIndexer $termIndexer, RecordIndexer $recordIndexer, appbox $appbox, LoggerInterface $logger = null)
{ {
$this->client = $client; $this->client = $client;
$this->options = $options; $this->options = $options;
@@ -64,9 +65,9 @@ class Indexer
public function createIndex($withMapping = true) public function createIndex($withMapping = true)
{ {
$params = array(); $params = array();
$params['index'] = $this->options['index']; $params['index'] = $this->options->getIndexName();
$params['body']['settings']['number_of_shards'] = $this->options['shards']; $params['body']['settings']['number_of_shards'] = $this->options->getShards();
$params['body']['settings']['number_of_replicas'] = $this->options['replicas']; $params['body']['settings']['number_of_replicas'] = $this->options->getReplicas();
$params['body']['settings']['analysis'] = $this->getAnalysis();; $params['body']['settings']['analysis'] = $this->getAnalysis();;
if ($withMapping) { if ($withMapping) {
@@ -80,7 +81,7 @@ class Indexer
public function updateMapping() public function updateMapping()
{ {
$params = array(); $params = array();
$params['index'] = $this->options['index']; $params['index'] = $this->options->getIndexName();
$params['type'] = RecordIndexer::TYPE_NAME; $params['type'] = RecordIndexer::TYPE_NAME;
$params['body'][RecordIndexer::TYPE_NAME] = $this->recordIndexer->getMapping(); $params['body'][RecordIndexer::TYPE_NAME] = $this->recordIndexer->getMapping();
$params['body'][TermIndexer::TYPE_NAME] = $this->termIndexer->getMapping(); $params['body'][TermIndexer::TYPE_NAME] = $this->termIndexer->getMapping();
@@ -91,13 +92,13 @@ class Indexer
public function deleteIndex() public function deleteIndex()
{ {
$params = array('index' => $this->options['index']); $params = array('index' => $this->options->getIndexName());
$this->client->indices()->delete($params); $this->client->indices()->delete($params);
} }
public function indexExists() public function indexExists()
{ {
$params = array('index' => $this->options['index']); $params = array('index' => $this->options->getIndexName());
return $this->client->indices()->exists($params); return $this->client->indices()->exists($params);
} }
@@ -132,7 +133,7 @@ class Indexer
} }
// Optimize index // Optimize index
$params = array('index' => $this->options['index']); $params = array('index' => $this->options->getIndexName());
$this->client->indices()->optimize($params); $this->client->indices()->optimize($params);
}); });
@@ -203,7 +204,7 @@ class Indexer
try { try {
// Prepare the bulk operation // Prepare the bulk operation
$bulk = new BulkOperation($this->client, $this->logger); $bulk = new BulkOperation($this->client, $this->logger);
$bulk->setDefaultIndex($this->options['index']); $bulk->setDefaultIndex($this->options->getIndexName());
$bulk->setAutoFlushLimit(1000); $bulk->setAutoFlushLimit(1000);
// Do the work // Do the work
$work($bulk); $work($bulk);
@@ -233,7 +234,7 @@ class Indexer
private function getSetting($name) private function getSetting($name)
{ {
$index = $this->options['index']; $index = $this->options->getIndexName();
$params = array(); $params = array();
$params['index'] = $index; $params['index'] = $index;
$params['name'] = $name; $params['name'] = $name;
@@ -245,7 +246,7 @@ class Indexer
private function setSetting($name, $value) private function setSetting($name, $value)
{ {
$index = $this->options['index']; $index = $this->options->getIndexName();
$params = array(); $params = array();
$params['index'] = $index; $params['index'] = $index;
$params['body'][$name] = $value; $params['body'][$name] = $value;

View File

@@ -22,16 +22,17 @@ use Psr\Log\LoggerInterface;
class Thesaurus class Thesaurus
{ {
/** @var Client */
private $client; private $client;
private $index; /** @var GlobalElasticOptions */
private $options;
/** @var LoggerInterface */
private $logger; private $logger;
const MIN_SCORE = 4; public function __construct(Client $client, GlobalElasticOptions $options, LoggerInterface $logger)
public function __construct(Client $client, $index, LoggerInterface $logger)
{ {
$this->client = $client; $this->client = $client;
$this->index = $index; $this->options = $options;
$this->logger = $logger; $this->logger = $logger;
} }
@@ -136,7 +137,7 @@ class Thesaurus
// Search request // Search request
$params = array(); $params = array();
$params['index'] = $this->index; $params['index'] = $this->options->getIndexName();
$params['type'] = TermIndexer::TYPE_NAME; $params['type'] = TermIndexer::TYPE_NAME;
$params['body']['query'] = $query; $params['body']['query'] = $query;
$params['body']['aggs'] = $aggs; $params['body']['aggs'] = $aggs;
@@ -144,7 +145,7 @@ class Thesaurus
// inexact concepts. // inexact concepts.
// We also need to disable TF/IDF on terms, and try to boost score only // We also need to disable TF/IDF on terms, and try to boost score only
// when the search match nearly all tokens of term's value field. // when the search match nearly all tokens of term's value field.
$params['body']['min_score'] = self::MIN_SCORE; $params['body']['min_score'] = $this->options->getMinScore();
// No need to get any hits since we extract data from aggs // No need to get any hits since we extract data from aggs
$params['body']['size'] = 0; $params['body']['size'] = 0;

View File

@@ -40,11 +40,6 @@ interface SearchEngineInterface
*/ */
public function getStatus(); public function getStatus();
/**
* @return ConfigurationPanelInterface
*/
public function getConfigurationPanel();
/** /**
* @return array an array of field names * @return array an array of field names
*/ */

View File

@@ -408,7 +408,7 @@ class SearchEngineOptions
}, $value); }, $value);
} }
if (in_array($key, ['collections', 'business_fields'])) { if (in_array($key, ['collections', 'business_fields'])) {
$value = array_map(function ($collection) { $value = array_map(function (\collection $collection) {
return $collection->get_base_id(); return $collection->get_base_id();
}, $value); }, $value);
} }

View File

@@ -1,11 +1,3 @@
<h1>{{ 'ElasticSearch configuration' | trans }}</h1> <h1>{{ 'ElasticSearch configuration' | trans }}</h1>
<form method="post" action="{{ path('admin_searchengine_post') }}"> {{ form(form) }}
<div>{{ 'ElasticSearch connection configuration' | trans }}</div>
<div>{{ 'ElasticSearch server' | trans }}</div>
<input type="text" name="host" value="{{ configuration['host'] | default('localhost') }}"/>
<input type="text" name="port" value="{{ configuration['port'] | default('9200') }}"/>
<button type="submit" class="btn btn-warning" >{{ 'boutton::valider' | trans }}</button>
</form>

View File

@@ -23,7 +23,7 @@
</a> </a>
</li> </li>
<li> <li>
<a target="right" href="{{ path('admin_searchengine_get') }}"> <a target="right" href="{{ path('admin_searchengine_form') }}">
<span>{{ 'SearchEngine settings' | trans }}</span> <span>{{ 'SearchEngine settings' | trans }}</span>
</a> </a>
</li> </li>

View File

@@ -1,43 +0,0 @@
<?php
namespace Alchemy\Tests\Phrasea\SearchEngine;
abstract class ConfigurationPanelAbstractTest extends \PhraseanetTestCase
{
abstract public function getPanel();
public function testGetName()
{
$this->assertInternalType('string', $this->getPanel()->getName());
}
public function testGetConfiguration()
{
$this->assertInternalType('array', $this->getPanel()->getConfiguration());
}
public function testSaveConfiguration()
{
$config = $this->getPanel()->getConfiguration();
$data = 'Yodelali' . mt_rand();
$config['test'] = $data;
$this->getPanel()->saveConfiguration($config);
$config = $this->getPanel()->getConfiguration();
$this->assertEquals($data, $config['test']);
unset($config['test']);
$this->getPanel()->saveConfiguration($config);
}
public function testGetAvailableDateFields()
{
$dateFields = $this->getPanel()->getAvailableDateFields(self::$DI['app']['phraseanet.appbox']->get_databoxes());
$this->assertInternalType('array', $dateFields);
foreach ($dateFields as $dateField) {
$this->assertInternalType('string', $dateField);
}
}
}

View File

@@ -556,11 +556,6 @@ abstract class SearchEngineAbstractTest extends \PhraseanetAuthenticatedTestCase
} }
} }
public function testConfigurationPanel()
{
$this->assertInstanceOf('\\Alchemy\\Phrasea\\SearchEngine\\ConfigurationPanelInterface', self::$searchEngine->getConfigurationPanel());
}
public function testStatus() public function testStatus()
{ {
foreach (self::$searchEngine->getStatus() as $StatusKeyValue) { foreach (self::$searchEngine->getStatus() as $StatusKeyValue) {

View File

@@ -711,9 +711,6 @@ abstract class PhraseanetTestCase extends WebTestCase
$mock->expects($this->any()) $mock->expects($this->any())
->method('createSubscriber') ->method('createSubscriber')
->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface'))); ->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface')));
$mock->expects($this->any())
->method('getConfigurationPanel')
->will($this->returnValue($this->getMock('Alchemy\Phrasea\SearchEngine\ConfigurationPanelInterface')));
$mock->expects($this->any()) $mock->expects($this->any())
->method('getStatus') ->method('getStatus')
->will($this->returnValue([])); ->will($this->returnValue([]));