diff --git a/interfaces/SphinxToolkitFoolzInterface.php b/interfaces/SphinxToolkitFoolzInterface.php index 6756833..ef01096 100644 --- a/interfaces/SphinxToolkitFoolzInterface.php +++ b/interfaces/SphinxToolkitFoolzInterface.php @@ -29,7 +29,7 @@ interface SphinxToolkitFoolzInterface { public static function init(string $sphinx_connection_host, string $sphinx_connection_port, $options = []); /** - * Создает коннекшен для множественных обновлений (в крон-скриптах, к примеру, вызывается после init() ) + * Создает коннекшен и устанавливает параметры подключения: хост и порт */ public static function initConnection(); @@ -123,9 +123,18 @@ public static function rt_TruncateIndex(string $index_name, bool $is_reconfigure public static function rt_RebuildAbstractIndex(PDO $pdo_connection, string $sql_source_table, string $sphinx_index, Closure $make_updateset_method, string $condition = ''); /** - * Получает инстанс (для множественных обновлений) + * Создает инстанс на основе сохраненного в классе коннекшена * * @return SphinxQL */ public static function getInstance(); + + /** + * Возвращает META-информацию (после запроса) + * + * @throws ConnectionException + * @throws DatabaseException + * @throws SphinxQLException + */ + public static function showMeta(); } \ No newline at end of file diff --git a/interfaces/SphinxToolkitMysqliInterface.php b/interfaces/SphinxToolkitMysqliInterface.php index ec9c00f..226229c 100644 --- a/interfaces/SphinxToolkitMysqliInterface.php +++ b/interfaces/SphinxToolkitMysqliInterface.php @@ -5,6 +5,7 @@ use Closure; use Exception; use PDO; +use Psr\Log\LoggerInterface; /** * Interface __SphinxToolkitMysqliInterface @@ -14,14 +15,15 @@ * @package Arris\Toolkit */ interface SphinxToolkitMysqliInterface { - + /** * SphinxToolkit constructor. * * @param PDO $mysql_connection * @param PDO $sphinx_connection + * @param LoggerInterface|null $logger */ - public function __construct(PDO $mysql_connection, PDO $sphinx_connection); + public function __construct(PDO $mysql_connection, PDO $sphinx_connection, LoggerInterface $logger = null); /** * Устанавливает опции для перестроителя RT-индекса @@ -61,19 +63,4 @@ public function rebuildAbstractIndex(string $mysql_table, string $sphinx_index, */ public function rebuildAbstractIndexMVA(string $mysql_table, string $sphinx_index, Closure $make_updateset_method, string $condition = '', array $mva_indexes_list = []):int; - /** - * Эмулирует BuildExcerpts из SphinxAPI - * - * @param $source - * @param $needle - * @param $options - * 'before_match' => '', // Строка, вставляемая перед ключевым словом. По умолчанию "". - * 'after_match' => '', // Строка, вставляемая после ключевого слова. По умолчанию "". - * 'chunk_separator' => '...', // Строка, вставляемая между частями фрагмента. по умолчанию "...". - * - * опции 'limit', 'around', 'exact_phrase' и 'single_passage' в эмуляции не реализованы - * - * @return mixed - */ - public static function EmulateBuildExcerpts($source, $needle, $options); } \ No newline at end of file diff --git a/src/SphinxToolkit.php b/src/SphinxToolkit.php index b3ff7e7..15c45a9 100644 --- a/src/SphinxToolkit.php +++ b/src/SphinxToolkit.php @@ -15,6 +15,7 @@ use Foolz\SphinxQL\Exception\DatabaseException; use Foolz\SphinxQL\Helper; use Foolz\SphinxQL\SphinxQL; +use Psr\Log\LoggerInterface; class SphinxToolkit implements SphinxToolkitMysqliInterface, SphinxToolkitFoolzInterface { @@ -35,16 +36,22 @@ class SphinxToolkit implements SphinxToolkitMysqliInterface, SphinxToolkitFoolzI * @var PDO */ private $sphinx_connection; + + /** + * @var LoggerInterface + */ + private $logger; - public function __construct(PDO $mysql_connection, PDO $sphinx_connection) + public function __construct(PDO $mysql_connection, PDO $sphinx_connection, LoggerInterface $logger = null) { $this->mysql_connection = $mysql_connection; $this->sphinx_connection = $sphinx_connection; + $this->logger = $logger; } public function setRebuildIndexOptions(array $options = []):array { - // на самом деле разворачиваем опции с установкой дефолтов + // разворачиваем опции с установкой дефолтов $this->rai_options['chunk_length'] = SphinxToolkitHelper::setOption($options, 'chunk_length', 500); $this->rai_options['log_rows_inside_chunk'] = SphinxToolkitHelper::setOption($options, 'log_rows_inside_chunk', true); @@ -287,46 +294,6 @@ public function checkIndexExist(string $sphinx_index) return count($index_definition) > 0; } - - - /* =========================== СТАТИЧЕСКИЕ МЕТОДЫ ==================================== */ - - public static function EmulateBuildExcerpts($source, $needle, $options) - { - $opts = [ - // Строка, вставляемая перед ключевым словом. По умолчанию "". - 'before_match' => SphinxToolkitHelper::setOption($options, 'before_match', ''), - - // Строка, вставляемая после ключевого слова. По умолчанию "". - 'after_match' => SphinxToolkitHelper::setOption($options, 'after_match', ''), - // Строка, вставляемая между частями фрагмента. по умолчанию "...". - 'chunk_separator' => '...', - - // НЕ РЕАЛИЗОВАНО: Максимальный размер фрагмента в символах. Integer, по умолчанию 256. - 'limit' => SphinxToolkitHelper::setOption($options, 'limit', 256), - - // НЕ РЕАЛИЗОВАНО: Сколько слов необходимо выбрать вокруг каждого совпадающего с ключевыми словами блока. Integer, по умолчанию 5. - 'around' => SphinxToolkitHelper::setOption($options, 'around', 5), - - // НЕ РЕАЛИЗОВАНО: Необходимо ли подсвечивать только точное совпадение с поисковой фразой, а не отдельные ключевые слова. Boolean, по умолчанию FALSE. - 'exact_phrase' => SphinxToolkitHelper::setOption($options, 'around', null), - - // НЕ РЕАЛИЗОВАНО: Необходимо ли извлечь только единичный наиболее подходящий фрагмент. Boolean, по умолчанию FALSE. - 'single_passage' => SphinxToolkitHelper::setOption($options, 'single_passage', null), - - ]; - - $target = strip_tags($source); - - $target = SphinxToolkitHelper::mb_str_replace($needle, $opts['before_match'] . $needle . $opts['after_match'], $target); - - if (($opts['limit'] > 0) && ( mb_strlen($source) > $opts['limit'] )) { - $target = SphinxToolkitHelper::mb_trim_text($target, $opts['limit'] ,true,false, $opts['chunk_separator']); - } - - return $target; - } // EmulateBuildExcerpts - /* =========================== STATIC IMPLEMENTATION ================================= */ /** @@ -334,7 +301,7 @@ public static function EmulateBuildExcerpts($source, $needle, $options) * * @var array */ - private static $rlo = []; + private static $spql_options = []; /** * @var Connection @@ -349,58 +316,82 @@ public static function EmulateBuildExcerpts($source, $needle, $options) * @var Connection */ private static $spql_connection; - - public static function init(string $sphinx_connection_host, string $sphinx_connection_port, $options = []) + + /** + * @var SphinxQL + */ + private static $spql_instance; + + /** + * @var LoggerInterface + */ + private static $spql_logger; + + /** + * @inheritDoc + */ + public static function init(string $sphinx_connection_host, string $sphinx_connection_port, $options = [], LoggerInterface $logger = null) { self::$spql_connection_host = $sphinx_connection_host; self::$spql_connection_port = $sphinx_connection_port; - self::$rlo['chunk_length'] = SphinxToolkitHelper::setOption($options, 'chunk_length', 500); + self::$spql_options['chunk_length'] = SphinxToolkitHelper::setOption($options, 'chunk_length', 500); - self::$rlo['log_rows_inside_chunk'] = SphinxToolkitHelper::setOption($options, 'log_rows_inside_chunk', true); - self::$rlo['log_total_rows_found'] = SphinxToolkitHelper::setOption($options, 'log_total_rows_found', true); + self::$spql_options['log_rows_inside_chunk'] = SphinxToolkitHelper::setOption($options, 'log_rows_inside_chunk', true); + self::$spql_options['log_total_rows_found'] = SphinxToolkitHelper::setOption($options, 'log_total_rows_found', true); - self::$rlo['log_before_chunk'] = SphinxToolkitHelper::setOption($options, 'log_before_chunk', true); - self::$rlo['log_after_chunk'] = SphinxToolkitHelper::setOption($options, 'log_after_chunk', true); + self::$spql_options['log_before_chunk'] = SphinxToolkitHelper::setOption($options, 'log_before_chunk', true); + self::$spql_options['log_after_chunk'] = SphinxToolkitHelper::setOption($options, 'log_after_chunk', true); - self::$rlo['sleep_after_chunk'] = SphinxToolkitHelper::setOption($options, 'sleep_after_chunk', true); + self::$spql_options['sleep_after_chunk'] = SphinxToolkitHelper::setOption($options, 'sleep_after_chunk', true); - self::$rlo['sleep_time'] = SphinxToolkitHelper::setOption($options, 'sleep_time', 1); - if (self::$rlo['sleep_time'] == 0) { - self::$rlo['sleep_after_chunk'] = false; + self::$spql_options['sleep_time'] = SphinxToolkitHelper::setOption($options, 'sleep_time', 1); + if (self::$spql_options['sleep_time'] == 0) { + self::$spql_options['sleep_after_chunk'] = false; } - self::$rlo['log_before_index'] = SphinxToolkitHelper::setOption($options, 'log_before_index', true); - self::$rlo['log_after_index'] = SphinxToolkitHelper::setOption($options, 'log_after_index', true); + self::$spql_options['log_before_index'] = SphinxToolkitHelper::setOption($options, 'log_before_index', true); + self::$spql_options['log_after_index'] = SphinxToolkitHelper::setOption($options, 'log_after_index', true); + + self::$spql_logger = $logger; } - + + /** + * @inheritDoc + */ public static function initConnection() { - $conn = new Connection(); - $conn->setParams([ + $connection = new Connection(); + $connection->setParams([ 'host' => self::$spql_connection_host, 'port' => self::$spql_connection_port ]); - self::$spql_connection = $conn; + return $connection; } - + + /** + * @inheritDoc + */ public static function getInstance() { return (new SphinxQL(self::$spql_connection)); } - + + /** + * @inheritDoc + */ public static function createInstance() { - $conn = new Connection(); - $conn->setParams([ - 'host' => self::$spql_connection_host, - 'port' => self::$spql_connection_port - ]); - - return (new SphinxQL($conn)); + self::$spql_connection = self::initConnection(); + self::$spql_instance = self::getInstance(); + + return self::$spql_instance; } - + + /** + * @inheritDoc + */ public static function rt_ReplaceIndex(string $index_name, array $updateset) { if (empty($updateset)) return null; @@ -411,7 +402,10 @@ public static function rt_ReplaceIndex(string $index_name, array $updateset) ->set($updateset) ->execute(); } - + + /** + * @inheritDoc + */ public static function rt_UpdateIndex(string $index_name, array $updateset) { if (empty($updateset)) return null; @@ -422,7 +416,10 @@ public static function rt_UpdateIndex(string $index_name, array $updateset) ->set($updateset) ->execute(); } - + + /** + * @inheritDoc + */ public static function rt_DeleteIndex(string $index_name, string $field, $field_value = null) { if (is_null($field_value)) return null; @@ -449,11 +446,7 @@ public static function rt_DeleteIndexMatch(string $index_name, string $field, $f } /** - * Делает truncate index с реконфигурацией по умолчанию - * - * @param string $index_name - * @param bool $is_reconfigure - * @return bool + * @inheritDoc */ public static function rt_TruncateIndex(string $index_name, bool $is_reconfigure = true) { @@ -462,10 +455,13 @@ public static function rt_TruncateIndex(string $index_name, bool $is_reconfigure return (bool)self::createInstance()->query("TRUNCATE RTINDEX {$index_name} {$with}"); } - + + /** + * @inheritDoc + */ public static function rt_RebuildAbstractIndex(PDO $pdo_connection, string $sql_source_table, string $sphinx_index, Closure $make_updateset_method, string $condition = '') { - $chunk_size = self::$rlo['chunk_length']; + $chunk_size = self::$spql_options['chunk_length']; self::rt_TruncateIndex($sphinx_index); @@ -475,17 +471,17 @@ public static function rt_RebuildAbstractIndex(PDO $pdo_connection, string $sql_ ->fetchColumn(); $total_updated = 0; - if (self::$rlo['log_before_index']) + if (self::$spql_options['log_before_index']) CLIConsole::say("[{$sphinx_index}] index : ", false); - if (self::$rlo['log_total_rows_found']) + if (self::$spql_options['log_total_rows_found']) CLIConsole::say("{$total_count} elements found for rebuild."); // iterate chunks for ($i = 0; $i < ceil($total_count / $chunk_size); $i++) { $offset = $i * $chunk_size; - if (self::$rlo['log_before_chunk']) CLIConsole::say("Rebuilding elements from {$offset}, {$chunk_size} count... " , false); + if (self::$spql_options['log_before_chunk']) CLIConsole::say("Rebuilding elements from {$offset}, {$chunk_size} count... " , false); $query_chunk_data = "SELECT * FROM {$sql_source_table} "; $query_chunk_data.= $condition != '' ? " WHERE {$condition} " : ' '; @@ -495,7 +491,7 @@ public static function rt_RebuildAbstractIndex(PDO $pdo_connection, string $sql_ // iterate inside chunk while ($item = $sth->fetch()) { - if (self::$rlo['log_rows_inside_chunk']) + if (self::$spql_options['log_rows_inside_chunk']) CLIConsole::say("{$sql_source_table}: {$item['id']}"); $update_set = $make_updateset_method($item); @@ -505,25 +501,30 @@ public static function rt_RebuildAbstractIndex(PDO $pdo_connection, string $sql_ $total_updated++; } // while - $breakline_after_chunk = !self::$rlo['sleep_after_chunk']; + $breakline_after_chunk = !self::$spql_options['sleep_after_chunk']; - if (self::$rlo['log_after_chunk']) { + if (self::$spql_options['log_after_chunk']) { CLIConsole::say("Updated RT-index {$sphinx_index}.", $breakline_after_chunk); } else { CLIConsole::say("Ok", $breakline_after_chunk); } - if (self::$rlo['sleep_after_chunk']) { - CLIConsole::say(" ZZZZzzz for " . self::$rlo['sleep_time'] . " second(s)... ", FALSE); - sleep(self::$rlo['sleep_time']); + if (self::$spql_options['sleep_after_chunk']) { + CLIConsole::say(" ZZZZzzz for " . self::$spql_options['sleep_time'] . " second(s)... ", FALSE); + sleep(self::$spql_options['sleep_time']); CLIConsole::say("I woke up!"); } } // for - if (self::$rlo['log_after_index']) + if (self::$spql_options['log_after_index']) CLIConsole::say("Total updated {$total_updated} elements for {$sphinx_index} RT-index.
"); return $total_updated; } + + public static function showMeta() + { + (new Helper(self::$spql_connection))->showMeta()->execute()->fetchAllAssoc(); + } /** * diff --git a/traits/SphinxToolkitHelper.php b/traits/SphinxToolkitHelper.php index 82c6b3e..24f00d3 100644 --- a/traits/SphinxToolkitHelper.php +++ b/traits/SphinxToolkitHelper.php @@ -183,4 +183,54 @@ public static function MySQL_GetRowsCount(PDO $pdo, string $table, string $condi return $pdo->query($query)->fetchColumn(); } + /** + * Эмулирует BuildExcerpts из SphinxAPI + * + * @param $source + * @param $needle + * @param $options + * 'before_match' => '', // Строка, вставляемая перед ключевым словом. По умолчанию "". + * 'after_match' => '', // Строка, вставляемая после ключевого слова. По умолчанию "". + * 'chunk_separator' => '...', // Строка, вставляемая между частями фрагмента. по умолчанию "...". + * + * опции 'limit', 'around', 'exact_phrase' и 'single_passage' в эмуляции не реализованы + * + * @return mixed + */ + public static function EmulateBuildExcerpts($source, $needle, $options) + { + $opts = [ + // Строка, вставляемая перед ключевым словом. По умолчанию "". + 'before_match' => SphinxToolkitHelper::setOption($options, 'before_match', ''), + + // Строка, вставляемая после ключевого слова. По умолчанию "". + 'after_match' => SphinxToolkitHelper::setOption($options, 'after_match', ''), + // Строка, вставляемая между частями фрагмента. по умолчанию "...". + 'chunk_separator' => '...', + + // НЕ РЕАЛИЗОВАНО: Максимальный размер фрагмента в символах. Integer, по умолчанию 256. + 'limit' => SphinxToolkitHelper::setOption($options, 'limit', 256), + + // НЕ РЕАЛИЗОВАНО: Сколько слов необходимо выбрать вокруг каждого совпадающего с ключевыми словами блока. Integer, по умолчанию 5. + 'around' => SphinxToolkitHelper::setOption($options, 'around', 5), + + // НЕ РЕАЛИЗОВАНО: Необходимо ли подсвечивать только точное совпадение с поисковой фразой, а не отдельные ключевые слова. Boolean, по умолчанию FALSE. + 'exact_phrase' => SphinxToolkitHelper::setOption($options, 'around', null), + + // НЕ РЕАЛИЗОВАНО: Необходимо ли извлечь только единичный наиболее подходящий фрагмент. Boolean, по умолчанию FALSE. + 'single_passage' => SphinxToolkitHelper::setOption($options, 'single_passage', null), + + ]; + + $target = strip_tags($source); + + $target = SphinxToolkitHelper::mb_str_replace($needle, $opts['before_match'] . $needle . $opts['after_match'], $target); + + if (($opts['limit'] > 0) && ( mb_strlen($source) > $opts['limit'] )) { + $target = SphinxToolkitHelper::mb_trim_text($target, $opts['limit'] ,true,false, $opts['chunk_separator']); + } + + return $target; + } // EmulateBuildExcerpts + } \ No newline at end of file