Commit 386b58b2 by Klimov Paul

Snippet call options added to Sphinx Query.

parent 7fb4bfdd
......@@ -108,20 +108,76 @@ class Query extends Component
* row data. For more details, see [[indexBy()]]. This property is only used by [[all()]].
*/
public $indexBy;
/**
* @var callback PHP callback, which should be used to fetch source data for the snippets.
* Such callback will receive array of query result rows as an argument and must return the
* array of snippet source strings in the order, which match one of incoming rows.
* For example:
* ```php
* $query = new Query;
* $query->from('idx_item')
* ->match('pencil')
* ->snippetCallback(function ($rows) {
* $result = [];
* foreach ($rows as $row) {
* $result[] = file_get_contents('/path/to/index/files/' . $row['id'] . '.txt');
* }
* return $result;
* })
* ->all();
* ```
*/
public $snippetCallback;
/**
* @var array query options for the call snippet.
*/
public $snippetOptions;
/**
* @var Connection the Sphinx connection used to generate the SQL statements.
*/
private $_connection;
/**
* @param Connection $connection Sphinx connection instance
* @return static the query object itself
*/
public function setConnection($connection)
{
$this->_connection = $connection;
return $this;
}
/**
* @return Connection Sphinx connection instance
*/
public function getConnection()
{
if ($this->_connection === null) {
$this->_connection = $this->defaultConnection();
}
return $this->_connection;
}
/**
* @return Connection default connection value.
*/
protected function defaultConnection()
{
return Yii::$app->getComponent('sphinx');
}
/**
* Creates a Sphinx command that can be used to execute this query.
* @param Connection $sphinxConnection the Sphinx connection used to generate the SQL statement.
* @param Connection $connection the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return Command the created Sphinx command instance.
*/
public function createCommand($sphinxConnection = null)
public function createCommand($connection = null)
{
if ($sphinxConnection === null) {
$sphinxConnection = Yii::$app->getComponent('sphinx');
}
list ($sql, $params) = $sphinxConnection->getQueryBuilder()->build($this);
return $sphinxConnection->createCommand($sql, $params);
$this->setConnection($connection);
$connection = $this->getConnection();
list ($sql, $params) = $connection->getQueryBuilder()->build($this);
return $connection->createCommand($sql, $params);
}
/**
......@@ -154,6 +210,7 @@ class Query extends Component
public function all($db = null)
{
$rows = $this->createCommand($db)->queryAll();
$rows = $this->fillUpSnippets($rows);
if ($this->indexBy === null) {
return $rows;
}
......@@ -178,7 +235,11 @@ class Query extends Component
*/
public function one($db = null)
{
return $this->createCommand($db)->queryOne();
$result = $this->createCommand($db)->queryOne();
if ($result) {
list ($result) = $this->fillUpSnippets([$result]);
}
return $result;
}
/**
......@@ -686,4 +747,58 @@ class Query extends Component
}
return $this;
}
/**
* @param callback $callback
* @return static the query object itself
*/
public function snippetCallback($callback)
{
$this->snippetCallback = $callback;
return $this;
}
/**
* @param array $options
* @return static the query object itself
*/
public function snippetOptions($options)
{
$this->snippetOptions = $options;
return $this;
}
/**
* Fills the query result rows with the snippets built from source determined by
* [[snippetCallback]] result.
* @param array $rows raw query result rows.
* @return array query result rows with filled up snippets.
*/
protected function fillUpSnippets($rows)
{
if ($this->snippetCallback === null) {
return $rows;
}
$snippetSources = call_user_func($this->snippetCallback, $rows);
$snippets = $this->callSnippets($snippetSources);
$snippetKey = 0;
foreach ($rows as $key => $row) {
$rows[$key]['snippet'] = $snippets[$snippetKey];
$snippetKey++;
}
return $rows;
}
/**
* Builds a snippets from provided source data.
* @param array $source the source data to extract a snippet from.
* @return array snippets list
*/
protected function callSnippets(array $source)
{
$connection = $this->getConnection();
return $connection->createCommand()
->callSnippets($this->from[0], $source, $this->match, $this->snippetOptions)
->queryColumn();
}
}
\ No newline at end of file
......@@ -151,4 +151,37 @@ class QueryTest extends SphinxTestCase
->all($connection);
$this->assertNotEmpty($rows);
}
/**
* @depends testRun
*/
public function testSnippet()
{
$connection = $this->getConnection();
$match = 'about';
$snippetPrefix = 'snippet#';
$snippetCallback = function() use ($match, $snippetPrefix) {
return [
$snippetPrefix . '1: ' . $match,
$snippetPrefix . '2: ' . $match,
];
};
$snippetOptions = [
'before_match' => '[',
'after_match' => ']',
];
$query = new Query;
$rows = $query->from('yii2_test_article_index')
->match($match)
->snippetCallback($snippetCallback)
->snippetOptions($snippetOptions)
->all($connection);
$this->assertNotEmpty($rows);
foreach ($rows as $row) {
$this->assertContains($snippetPrefix, $row['snippet'], 'Snippet source not present!');
$this->assertContains($snippetOptions['before_match'] . $match, $row['snippet'] . $snippetOptions['after_match'], 'Options not applied!');
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment