<commit_before><?php

namespace wcf\system\search\mysql;

use wcf\system\database\DatabaseException as LegacyDatabaseException;
use wcf\system\database\exception\DatabaseException;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\SystemException;
use wcf\system\search\AbstractSearchEngine;
use wcf\system\search\exception\SearchFailed;
use wcf\system\search\SearchEngine;
use wcf\system\search\SearchIndexManager;
use wcf\system\WCF;
use wcf\util\StringUtil;

/**
 * Search engine using MySQL's FULLTEXT index.
 *
 * @author  <NAME>
 * @copyright   2001-2019 WoltLab GmbH
 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package WoltLabSuite\Core\System\Search
 */
class MysqlSearchEngine extends AbstractSearchEngine
{
    /**
     * @deprecated 5.4 - This property is used for the deprecated getFulltextMinimumWordLength().
     */
    protected $ftMinWordLen;

    /**
     * @inheritDoc
     */
    protected $specialCharacters = ['(', ')', '@', '+', '-', '"', '<', '>', '~', '*'];

    /**
     * @inheritDoc
     */
    public function search(
        $q,
        array $objectTypes,
        $subjectOnly = false,
        ?PreparedStatementConditionBuilder $searchIndexCondition = null,
        array $additionalConditions = [],
        $orderBy = 'time DESC',
        $limit = 1000
    ) {
        // build search query
        $sql = '';
        $parameters = [];
        foreach ($objectTypes as $objectTypeName) {
            $objectType = SearchEngine::getInstance()->getObjectType($objectTypeName);

            if (!empty($sql)) {
                $sql .= "\nUNION ALL\n";
            }
            $additionalConditionsConditionBuilder = ($additionalConditions[$objectTypeName] ?? null);

            $query = $objectType->getOuterSQLQuery($q, $searchIndexCondition, $additionalConditionsConditionBuilder);
            if (empty($query)) {
                $query = "
                    SELECT      " . $objectType->getIDFieldName() . " AS objectID,
                                " . $objectType->getSubjectFieldName() . " AS subject,
                                " . $objectType->getTimeFieldName() . " AS time,
                                " . $objectType->getUsernameFieldName() . " AS username,
                                '" . $objectTypeName . "' AS objectType
                                " . ($orderBy == 'relevance ASC' || $orderBy == 'relevance DESC' ? ',search_index.relevance' : '') . "
                    FROM        " . $objectType->getTableName() . "
                    INNER JOIN  ({WCF_SEARCH_INNER_JOIN}) search_index
                    ON          " . $objectType->getIDFieldName() . " = search_index.objectID
                    " . $objectType->getJoins() . "
                    " . ($additionalConditions[$objectTypeName] ?? '');
            }

            if (\mb_strpos($query, '{WCF_SEARCH_INNER_JOIN}')) {
                $innerJoin = $this->getInnerJoin(
                    $objectTypeName,
                    $q,
                    $subjectOnly,
                    $searchIndexCondition,
                    $orderBy,
                    $limit
                );

                $query = \str_replace('{WCF_SEARCH_INNER_JOIN}', $innerJoin['sql'], $query);
                if ($innerJoin['fulltextCondition'] !== null) {
                    $parameters = \array_merge($parameters, $innerJoin['fulltextCondition']->getParameters());
                }
            }

            if ($searchIndexCondition !== null) {
                $parameters = \array_merge($parameters, $searchIndexCondition->getParameters());
            }
            if (isset($additionalConditions[$objectTypeName])) {
                $parameters = \array_merge($parameters, $additionalConditions[$objectTypeName]->getParameters());
            }

            $sql .= $query;
        }
        if (empty($sql)) {
            throw new SystemException('no object types given');
        }

        if (!empty($orderBy)) {
            $sql .= " ORDER BY " . $orderBy;
        }

        try {
            $messages = [];
            $statement = WCF::getDB()->prepareStatement($sql, $limit);
            $statement->execute($parameters);
            while ($row = $statement->fetchArray()) {
                $messages[] = [
                    'objectID' => $row['objectID'],
                    'objectType' => $row['objectType'],
                ];
            }
        } catch (DatabaseException $e) {
            throw new SearchFailed('MySQL search query failed.', $e);
        }<commit_msg>Clean up the objectTypes emptiness check in MysqlSearchEngine<commit_after><?php

namespace wcf\system\search\mysql;

use wcf\system\database\DatabaseException as LegacyDatabaseException;
use wcf\system\database\exception\DatabaseException;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\search\AbstractSearchEngine;
use wcf\system\search\exception\SearchFailed;
use wcf\system\search\SearchEngine;
use wcf\system\search\SearchIndexManager;
use wcf\system\WCF;
use wcf\util\StringUtil;

/**
 * Search engine using MySQL's FULLTEXT index.
 *
 * @author  <NAME>
 * @copyright   2001-2019 WoltLab GmbH
 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package WoltLabSuite\Core\System\Search
 */
class MysqlSearchEngine extends AbstractSearchEngine
{
    /**
     * @deprecated 5.4 - This property is used for the deprecated getFulltextMinimumWordLength().
     */
    protected $ftMinWordLen;

    /**
     * @inheritDoc
     */
    protected $specialCharacters = ['(', ')', '@', '+', '-', '"', '<', '>', '~', '*'];

    /**
     * @inheritDoc
     */
    public function search(
        $q,
        array $objectTypes,
        $subjectOnly = false,
        ?PreparedStatementConditionBuilder $searchIndexCondition = null,
        array $additionalConditions = [],
        $orderBy = 'time DESC',
        $limit = 1000
    ) {
        if (empty($objectTypes)) {
            throw new \InvalidArgumentException('The $objectTypes parameter must not be empty.');
        }

        // build search query
        $sql = '';
        $parameters = [];
        foreach ($objectTypes as $objectTypeName) {
            $objectType = SearchEngine::getInstance()->getObjectType($objectTypeName);

            if (!empty($sql)) {
                $sql .= "\nUNION ALL\n";
            }
            $additionalConditionsConditionBuilder = ($additionalConditions[$objectTypeName] ?? null);

            $query = $objectType->getOuterSQLQuery($q, $searchIndexCondition, $additionalConditionsConditionBuilder);
            if (empty($query)) {
                $query = "
                    SELECT      " . $objectType->getIDFieldName() . " AS objectID,
                                " . $objectType->getSubjectFieldName() . " AS subject,
                                " . $objectType->getTimeFieldName() . " AS time,
                                " . $objectType->getUsernameFieldName() . " AS username,
                                '" . $objectTypeName . "' AS objectType
                                " . ($orderBy == 'relevance ASC' || $orderBy == 'relevance DESC' ? ',search_index.relevance' : '') . "
                    FROM        " . $objectType->getTableName() . "
                    INNER JOIN  ({WCF_SEARCH_INNER_JOIN}) search_index
                    ON          " . $objectType->getIDFieldName() . " = search_index.objectID
                    " . $objectType->getJoins() . "
                    " . ($additionalConditions[$objectTypeName] ?? '');
            }

            if (\mb_strpos($query, '{WCF_SEARCH_INNER_JOIN}')) {
                $innerJoin = $this->getInnerJoin(
                    $objectTypeName,
                    $q,
                    $subjectOnly,
                    $searchIndexCondition,
                    $orderBy,
                    $limit
                );

                $query = \str_replace('{WCF_SEARCH_INNER_JOIN}', $innerJoin['sql'], $query);
                if ($innerJoin['fulltextCondition'] !== null) {
                    $parameters = \array_merge($parameters, $innerJoin['fulltextCondition']->getParameters());
                }
            }

            if ($searchIndexCondition !== null) {
                $parameters = \array_merge($parameters, $searchIndexCondition->getParameters());
            }
            if (isset($additionalConditions[$objectTypeName])) {
                $parameters = \array_merge($parameters, $additionalConditions[$objectTypeName]->getParameters());
            }

            $sql .= $query;
        }
        \assert(!empty($sql));

        if (!empty($orderBy)) {
            $sql .= " ORDER BY " . $orderBy;
        }

        try {
            $messages = [];
            $statement = WCF::getDB()->prepareStatement($sql, $limit);
            $statement->execute($parameters);
            while ($row = $statement->fetchArray()) {
                $messages[] = [
                    'objectID' => $row['objectID'],
                    'objectType' => $row['objectType'],
                ];
            }
        } catch (DatabaseException $e) {
            throw new SearchFailed('MySQL search query failed.', $e);
        }
{'fraction_non_alphanumeric': 0.13349774823075272, 'fraction_numerical': 0.0030023589963542783, 'mean_word_length': 1.8584125038308306, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3874907', 'n_tokens_mistral': 2544, 'n_tokens_neox': 2392, 'n_words': 441}