Ident = self::get_ident($this->Server, $this->Port, $this->Socket); } /** * Create server ident based on connection information * * @param string $Server server address or hostname * @param int $Port listening port * @param string $Socket Unix socket address, overrides $Server:$Port * @return string identification string */ private static function get_ident($Server, $Port, $Socket) { if ($Socket) { return $Socket; } else { return "$Server:$Port"; } } /** * Create Sphinxql object or return existing one * * @param string $Server server address or hostname * @param int $Port listening port * @param string $Socket Unix socket address, overrides $Server:$Port * @return Sphinxql object */ public static function init_connection($Server, $Port, $Socket) { $Ident = self::get_ident($Server, $Port, $Socket); if (!isset(self::$Connections[$Ident])) { self::$Connections[$Ident] = new Sphinxql($Server, $Port, $Socket); } return self::$Connections[$Ident]; } /** * Connect the Sphinxql object to the Sphinx server */ public function sph_connect() { if ($this->Connected || $this->connect_errno) { return; } global $Debug; $Debug->mark("Connecting to Sphinx server $this->Ident"); for ($Attempt = 0; $Attempt < 3; $Attempt++) { parent::__construct($this->Server, '', '', '', $this->Port, $this->Socket); /** @phpstan-ignore-line kittens were drowned for this */ if (!$this->connect_errno) { $this->Connected = true; break; } sleep(1); } if ($this->connect_errno) { $Errno = $this->connect_errno; $Error = $this->connect_error; $this->error("Connection failed. (" . strval($Errno) . ": " . strval($Error) . ")"); $Debug->mark("Could not connect to Sphinx server $this->Ident. (" . strval($Errno) . ": " . strval($Error) . ")"); } else { $Debug->mark("Connected to Sphinx server $this->Ident"); } } /** * Print a message to privileged users and optionally halt page processing */ public function error(string $message, bool $halt = false) { global $Debug, $Viewer; $error = "SphinxQL ({$this->Ident}): $message"; $Debug->analysis( $Viewer->requestContext()->module(), 'SphinxQL Error', $error, 86_400, ); if ($halt === true) { if ($Viewer->permitted('site_debug')) { echo '
' . display_str($error) . ''; die(); } else { Gazelle\Error500::error($message); } } } /** * Escape special characters before sending them to the Sphinx server. * Two escapes needed because the first one is eaten up by the mysql driver. * Lowercase ASCII characters because some Sphinx operators are all caps words. * * @param string $String string to escape * @return string escaped string */ public static function sph_escape_string($String) { return strtr(strtolower($String), [ '(' => '\\\\(', ')' => '\\\\)', '|' => '\\\\|', '-' => '\\\\-', '@' => '\\\\@', '~' => '\\\\~', '&' => '\\\\&', '\'' => '\\\'', '<' => '\\\\<', '!' => '\\\\!', '"' => '\\\\"', '/' => '\\\\/', '*' => '\\\\*', '$' => '\\\\$', '^' => '\\\\^', '\\' => '\\\\\\\\'] ); } /** * Register sent queries globally for later retrieval by debug functions * * @param string $QueryString query text * @param float $QueryProcessTime time building and processing the query */ public static function register_query($QueryString, $QueryProcessTime) { self::$Queries[] = [$QueryString, $QueryProcessTime]; self::$Time += $QueryProcessTime; } }