[SearchEngine] Update PR to latest master

This commit is contained in:
Romain Neutron
2012-10-30 11:40:57 +01:00
parent 497b8993fe
commit 0ec2117b60
5 changed files with 129 additions and 95 deletions

View File

@@ -11,33 +11,64 @@
namespace Alchemy\Phrasea\SearchEngine\Phrasea; namespace Alchemy\Phrasea\SearchEngine\Phrasea;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface; use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions; use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineResult; use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class PhraseaEngine implements SearchEngineInterface class PhraseaEngine implements SearchEngineInterface
{ {
private static $initialized = false;
/** /**
* *
* @var SearchEngineOptions * @var SearchEngineOptions
*/ */
protected $options; private $options;
protected $queries = array(); private $queries = array();
protected $arrayq = array(); private $arrayq = array();
protected $colls = array(); private $colls = array();
protected $qp = array(); private $qp = array();
protected $needthesaurus = array(); private $needthesaurus = array();
protected $configurationPanel; private $configurationPanel;
protected $resetCacheNextQuery = false; private $resetCacheNextQuery = false;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function __construct() public function __construct(Application $app)
{ {
$this->app = $app;
$this->options = new SearchEngineOptions(); $this->options = new SearchEngineOptions();
$this->initialize();
$this->checkSession();
}
private function checkSession()
{
if (!$this->app['phraseanet.user']) {
throw new \RuntimeException('Phrasea currently support only authenticated queries');
}
if (!phrasea_open_session($this->app['session']->get('phrasea_session_id'), $this->app['phraseanet.user']->get_id())) {
if (!$ses_id = phrasea_create_session((string) $this->app['phraseanet.user']->get_id())) {
throw new \Exception_InternalServerError('Unable to create phrasea session');
}
$this->app['session']->set('phrasea_session_id', $ses_id);
}
}
private function initialize()
{
if(!self::$initialized) {
\phrasea::start($this->app['phraseanet.configuration']);
self::$initialized = true;
}
} }
/** /**
@@ -111,7 +142,7 @@ class PhraseaEngine implements SearchEngineInterface
*/ */
public function updateRecord(\record_adapter $record) public function updateRecord(\record_adapter $record)
{ {
$record->set_binary_status(\databox_status::dec2bin(bindec($record->get_status()) & ~7 | 4)); $record->set_binary_status(\databox_status::dec2bin($this->app, bindec($record->get_status()) & ~7 | 4));
return $this; return $this;
} }
@@ -197,12 +228,9 @@ class PhraseaEngine implements SearchEngineInterface
$query .= ' AND recordtype=' . $this->options->getRecordType(); $query .= ' AND recordtype=' . $this->options->getRecordType();
} }
$appbox = \appbox::get_instance(\bootstrap::getCore());
$session = $appbox->get_session();
$sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id'; $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id';
$stmt = $appbox->get_connection()->prepare($sql); $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
$stmt->execute(array(':ses_id' => $session->get_ses_id())); $stmt->execute(array(':ses_id' => $this->app['session']->get('phrasea_session_id')));
$row = $stmt->fetch(\PDO::FETCH_ASSOC); $row = $stmt->fetch(\PDO::FETCH_ASSOC);
$stmt->closeCursor(); $stmt->closeCursor();
@@ -217,24 +245,24 @@ class PhraseaEngine implements SearchEngineInterface
} }
if ($this->resetCacheNextQuery === true) { if ($this->resetCacheNextQuery === true) {
phrasea_clear_cache($session->get_ses_id()); phrasea_clear_cache($this->app['session']->get('phrasea_session_id'));
$this->addQuery($query); $this->addQuery($query);
$this->executeQuery($query); $this->executeQuery($query);
$sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id'; $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id';
$stmt = $appbox->get_connection()->prepare($sql); $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
$stmt->execute(array(':ses_id' => $session->get_ses_id())); $stmt->execute(array(':ses_id' => $this->app['session']->get('phrasea_session_id')));
$row = $stmt->fetch(\PDO::FETCH_ASSOC); $row = $stmt->fetch(\PDO::FETCH_ASSOC);
$stmt->closeCursor(); $stmt->closeCursor();
} else { } else {
/** /**
* @todo clean this in DB * @todo clean this in DB
*/ */
$this->total_available = $this->total_results = $session->get_session_prefs('phrasea_engine_n_results'); $this->total_available = $this->total_results = $this->app['session']->get('phrasea_engine_n_results');
} }
$res = phrasea_fetch_results( $res = phrasea_fetch_results(
$session->get_ses_id(), $offset + 1, $perPage, false $this->app['session']->get('phrasea_session_id'), $offset + 1, $perPage, false
); );
$rs = array(); $rs = array();
@@ -251,7 +279,8 @@ class PhraseaEngine implements SearchEngineInterface
foreach ($rs as $data) { foreach ($rs as $data) {
try { try {
$records->add(new \record_adapter( $records->add(new \record_adapter(
\phrasea::sbasFromBas($data['base_id']), $this->app,
\phrasea::sbasFromBas($this->app, $data['base_id']),
$data['record_id'], $data['record_id'],
$resultNumber $resultNumber
)); ));
@@ -265,15 +294,16 @@ class PhraseaEngine implements SearchEngineInterface
return new SearchEngineResult($records, $query, $row['duration'], $offset, $row['total'], $row['total'], $error, '', new ArrayCollection(), new ArrayCollection(), ''); return new SearchEngineResult($records, $query, $row['duration'], $offset, $row['total'], $row['total'], $error, '', new ArrayCollection(), new ArrayCollection(), '');
} }
public static function create(Application $app)
{
return new static($app);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
private function executeQuery($query) private function executeQuery($query)
{ {
$appbox = \appbox::get_instance(\bootstrap::getCore());
$session = $appbox->get_session();
$registry = $appbox->get_registry();
$dateLog = date("Y-m-d H:i:s"); $dateLog = date("Y-m-d H:i:s");
$nbanswers = $total_time = 0; $nbanswers = $total_time = 0;
$sort = ''; $sort = '';
@@ -299,12 +329,12 @@ class PhraseaEngine implements SearchEngineInterface
} }
$results = phrasea_query2( $results = phrasea_query2(
$session->get_ses_id() $this->app['session']->get('phrasea_session_id')
, $sbas_id , $sbas_id
, $this->colls[$sbas_id] , $this->colls[$sbas_id]
, $this->arrayq[$sbas_id] , $this->arrayq[$sbas_id]
, $registry->get('GV_sit') , $this->app['phraseanet.registry']->get('GV_sit')
, $session->get_usr_id() , $this->app['session']->get('usr_id')
, false , false
, $this->options->searchType() == SearchEngineOptions::RECORD_GROUPING ? PHRASEA_MULTIDOC_REGONLY : PHRASEA_MULTIDOC_DOCONLY , $this->options->searchType() == SearchEngineOptions::RECORD_GROUPING ? PHRASEA_MULTIDOC_REGONLY : PHRASEA_MULTIDOC_DOCONLY
, $sort , $sort
@@ -316,26 +346,26 @@ class PhraseaEngine implements SearchEngineInterface
$nbanswers += $results["nbanswers"]; $nbanswers += $results["nbanswers"];
} }
$logger = $session->get_logger($appbox->get_databox($sbas_id)); // $logger = $session->get_logger($this->appbox->get_databox($sbas_id));
//
$conn2 = \connection::getPDOConnection($sbas_id); // $conn2 = \connection::getPDOConnection($sbas_id);
//
$sql3 = "INSERT INTO log_search // $sql3 = "INSERT INTO log_search
(id, log_id, date, search, results, coll_id ) // (id, log_id, date, search, results, coll_id )
VALUES // VALUES
(null, :log_id, :date, :query, :nbresults, :colls)"; // (null, :log_id, :date, :query, :nbresults, :colls)";
//
$params = array( // $params = array(
':log_id' => $logger->get_id() // ':log_id' => $logger->get_id()
, ':date' => $dateLog // , ':date' => $dateLog
, ':query' => $query // , ':query' => $query
, ':nbresults' => $results["nbanswers"] // , ':nbresults' => $results["nbanswers"]
, ':colls' => implode(',', $this->colls[$sbas_id]) // , ':colls' => implode(',', $this->colls[$sbas_id])
); // );
//
$stmt = $conn2->prepare($sql3); // $stmt = $conn2->prepare($sql3);
$stmt->execute($params); // $stmt->execute($params);
$stmt->closeCursor(); // $stmt->closeCursor();
} }
$sql = 'UPDATE cache $sql = 'UPDATE cache
@@ -344,16 +374,18 @@ class PhraseaEngine implements SearchEngineInterface
$params = array( $params = array(
'query' => $query, 'query' => $query,
':ses_id' => $session->get_ses_id(), ':ses_id' => $this->app['session']->get('phrasea_session_id'),
':duration' => $total_time, ':duration' => $total_time,
':total' => $nbanswers, ':total' => $nbanswers,
); );
$stmt = $appbox->get_connection()->prepare($sql); $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
$stmt->execute($params); $stmt->execute($params);
$stmt->closeCursor(); $stmt->closeCursor();
\User_Adapter::saveQuery($query); if ($this->app['phraseanet.user']) {
\User_Adapter::saveQuery($this->app, $query);
}
return $this; return $this;
} }
@@ -373,10 +405,8 @@ class PhraseaEngine implements SearchEngineInterface
{ {
$ret = array(); $ret = array();
$appbox = \appbox::get_instance(\bootstrap::getCore());
$session = $appbox->get_session();
$res = phrasea_fetch_results( $res = phrasea_fetch_results(
$session->get_ses_id(), ($record->get_number() + 1), 1, true, "[[em]]", "[[/em]]" $this->app['session']->get('phrasea_session_id'), ($record->get_number() + 1), 1, true, "[[em]]", "[[/em]]"
); );
if ( ! isset($res['results']) || ! is_array($res['results'])) { if ( ! isset($res['results']) || ! is_array($res['results'])) {
@@ -514,7 +544,7 @@ class PhraseaEngine implements SearchEngineInterface
private function singleParse($sbas, $query) private function singleParse($sbas, $query)
{ {
$this->qp[$sbas] = new PhraseaEngineQueryParser($this->options->getLocale()); $this->qp[$sbas] = new PhraseaEngineQueryParser($this->app, $this->options->getLocale());
$this->qp[$sbas]->debug = false; $this->qp[$sbas]->debug = false;
if ($sbas == 'main') { if ($sbas == 'main') {

View File

@@ -11,6 +11,8 @@
namespace Alchemy\Phrasea\SearchEngine\Phrasea; namespace Alchemy\Phrasea\SearchEngine\Phrasea;
use Alchemy\Phrasea\Application;
/** /**
* *
* @package searchEngine * @package searchEngine
@@ -84,15 +86,17 @@ class PhraseaEngineQueryParser
*/ */
public $proposals = Array("QRY" => "", "BASES" => array(), "QUERIES" => array()); public $proposals = Array("QRY" => "", "BASES" => array(), "QUERIES" => array());
public $app;
/** /**
* Current language for thesaurus * Current language for thesaurus
* @var <type> * @var <type>
*/ */
public $lng = null; public $lng;
protected $unicode; protected $unicode;
public function __construct($lng = "???") public function __construct(Application $app, $lng = "???")
{ {
$this->app = $app;
$this->lng = $lng; $this->lng = $lng;
$this->unicode = new \unicode(); $this->unicode = new \unicode();
@@ -1723,13 +1727,12 @@ class PhraseaEngineQueryParser
public function addsimple($t, $type, $nodetype, $pnum, $tree, $depth) public function addsimple($t, $type, $nodetype, $pnum, $tree, $depth)
{ {
$nok = 0; $nok = 0;
$registry = \registry::get_instance();
$w = $t["VALUE"]; $w = $t["VALUE"];
if ($w != "?" && $w != "*") { // on laisse passer les 'isolés' pour les traiter plus tard comme des mots vides if ($w != "?" && $w != "*") { // on laisse passer les 'isolés' pour les traiter plus tard comme des mots vides
for ($i = 0; $i < strlen($w); $i ++ ) { for ($i = 0; $i < strlen($w); $i ++ ) {
$c = substr($w, $i, 1); $c = substr($w, $i, 1);
if ($c == "?" || $c == "*") { if ($c == "?" || $c == "*") {
if ($nok < $registry->get('GV_min_letters_truncation')) { if ($nok < $this->app['phraseanet.registry']->get('GV_min_letters_truncation')) {
if ($this->errmsg != "") if ($this->errmsg != "")
$this->errmsg .= sprintf("\\n"); $this->errmsg .= sprintf("\\n");
$this->errmsg .= _('qparser:: Formulation incorrecte, necessite plus de caractere : ') . "<br>" . $registry->get('GV_min_letters_truncation'); $this->errmsg .= _('qparser:: Formulation incorrecte, necessite plus de caractere : ') . "<br>" . $registry->get('GV_min_letters_truncation');

View File

@@ -11,15 +11,14 @@
namespace Alchemy\Phrasea\SearchEngine\SphinxSearch; namespace Alchemy\Phrasea\SearchEngine\SphinxSearch;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface; use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions; use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineResult; use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion; use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Silex\Application;
use Symfony\Component\Process\ExecutableFinder; use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
require_once __DIR__ . '/../../../../vendor/sphinx/sphinxapi.php'; require_once __DIR__ . '/../../../../vendor/sphinx/sphinxapi.php';
@@ -45,9 +44,11 @@ class SphinxSearchEngine implements SearchEngineInterface
protected $rt_conn; protected $rt_conn;
protected $configurationPanel; protected $configurationPanel;
protected $options; protected $options;
protected $app;
public function __construct($host, $port, $rt_host, $rt_port) public function __construct(Application $app, $host, $port, $rt_host, $rt_port)
{ {
$this->app = $app;
$this->options = new SearchEngineOptions(); $this->options = new SearchEngineOptions();
$this->sphinx = new \SphinxClient(); $this->sphinx = new \SphinxClient();
@@ -297,9 +298,10 @@ class SphinxSearchEngine implements SearchEngineInterface
try { try {
$record = $record =
new \record_adapter( new \record_adapter(
$match['attrs']['sbas_id'] $this->app,
, $match['attrs']['record_id'] $match['attrs']['sbas_id'],
, $resultOffset $match['attrs']['record_id'],
$resultOffset
); );
$results->add($record); $results->add($record);

View File

@@ -8,35 +8,36 @@ require_once __DIR__ . '/../../../PhraseanetPHPUnitAuthenticatedAbstract.class.i
abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedAbstract abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedAbstract
{ {
protected static $searchEngine; protected static $searchEngine;
protected static $initialized = false; protected static $initialized = false;
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
foreach (self::$records['record_24']->get_databox()->get_meta_structure()->get_elements() as $field) {
if ( ! $field->isBusiness()) {
continue;
}
$found = true;
}
if ( ! $found) {
$field = \databox_field::create(self::$records['record_24']->get_databox(), 'testBusiness' . mt_rand(), false);
$field->set_business(true);
$field->save();
}
}
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$appbox = \appbox::get_instance(\bootstrap::getCore());
foreach ($appbox->get_databoxes() as $databox) { if (!self::$initialized) {
break; $found = false;
foreach (self::$DI['record_24']->get_databox()->get_meta_structure()->get_elements() as $field) {
if (!$field->isBusiness()) {
continue;
}
$found = true;
}
if (!$found) {
$field = \databox_field::create(self::$DI['app'], self::$DI['record_24']->get_databox(), 'testBusiness' . mt_rand(), false);
$field->set_business(true);
$field->save();
}
foreach (self::$DI['app']['phraseanet.appbox']->get_databoxes() as $databox) {
break;
}
} }
$this->initialize();
if (!self::$initialized) { if (!self::$initialized) {
$found = false; $found = false;
foreach (self::$DI['record_24']->get_databox()->get_meta_structure()->get_elements() as $field) { foreach (self::$DI['record_24']->get_databox()->get_meta_structure()->get_elements() as $field) {
@@ -456,10 +457,6 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA
$this->assertEquals(1, $results->total()); $this->assertEquals(1, $results->total());
} }
self::$searchEngine->removeStory($story);
$this->updateIndex();
}
public function testStatusQueryOffOverOn() public function testStatusQueryOffOverOn()
{ {
$options = $this->getDefaultOptions(); $options = $this->getDefaultOptions();
@@ -551,6 +548,8 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA
$this->assertInstanceOf('\record_adapter', $foundRecord); $this->assertInstanceOf('\record_adapter', $foundRecord);
$this->assertInstanceOf('\record_adapter', $foundRecord);
foreach ($foundRecord->get_caption()->get_fields() as $field) { foreach ($foundRecord->get_caption()->get_fields() as $field) {
$fields[$field->get_name()] = array( $fields[$field->get_name()] = array(
'value' => $field->get_serialized_values() 'value' => $field->get_serialized_values()

View File

@@ -110,7 +110,7 @@ class SphinxSearchEngineTest extends SearchEngineAbstractTest
public function testAutocomplete() public function testAutocomplete()
{ {
$record = self::$records['record_24']; $record = self::$DI['record_24'];
$toupdate = array(); $toupdate = array();
@@ -142,7 +142,7 @@ class SphinxSearchEngineTest extends SearchEngineAbstractTest
$process = new Process($indexer . ' --all --rotate -c ' . self::$config); $process = new Process($indexer . ' --all --rotate -c ' . self::$config);
$process->run(); $process->run();
$appbox = \appbox::get_instance(self::$core); $appbox = self::$DI['app']['phraseanet.appbox'];
self::$searchEngine->buildSuggestions($appbox->get_databoxes(), self::$config, 0); self::$searchEngine->buildSuggestions($appbox->get_databoxes(), self::$config, 0);
$suggestions = self::$searchEngine->autoComplete('jean'); $suggestions = self::$searchEngine->autoComplete('jean');