From 5336a301b4aec47e91a3267677f66c6ff96f725f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 25 Feb 2021 13:05:30 -0700 Subject: [PATCH 1/7] french translation --- CHANGELOG.md | 6 ++++++ languages.yaml | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc78cf..c0ee9c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v3.3.2 +## mm/dd/2021 + +1. [](#improved) + * Added French translation [#100](https://github.com/trilbymedia/grav-plugin-tntsearch/issues/100) + # v3.3.1 ## 02/25/2021 diff --git a/languages.yaml b/languages.yaml index 8e0d127..6b34f43 100644 --- a/languages.yaml +++ b/languages.yaml @@ -13,3 +13,8 @@ ru: FOUND_RESULTS: "Результатов: %s" FOUND_IN: "(%s)" POWERED_BY: "Работает на %s" +fr: + PLUGIN_TNTSEARCH: + FOUND_RESULTS: "Résultats trouvés: %s" + FOUND_IN: "(%s)" + POWERED_BY: "Par %s" \ No newline at end of file From a1ae76e548d07d0e4a07e9e258cd6c1f99fa3bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vilius=20=C5=A0umskas?= Date: Mon, 29 Mar 2021 02:48:18 +0300 Subject: [PATCH 2/7] Add missing stemmer languages (#115) --- README.md | 2 ++ blueprints.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index f9114f0..1d132b2 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,11 @@ The configuration options are as follows: * `default` - Porter stemmer for English language * `no` - no stemmer * `arabic` - Arabic language + * `croatian` - Croatian language * `german` - German language * `italian` - Italian language * `porter` - Porter stemmer for English language + * `portuguese` - Portuguese language * `russian` - Russian language * `ukrainian` - Ukrainian language * `display_route` - display the route in the search results diff --git a/blueprints.yaml b/blueprints.yaml index 49c24fe..f23c271 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -178,9 +178,11 @@ form: default: Default (English) no: Disabled arabic: Arabic + croatian: Croatian porter: English german: German italian: Italian + portuguese: Portuguese russian: Russian ukrainian: Ukrainian From 9620db3caad2475c5ae0445da048c5747df25b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vilius=20=C5=A0umskas?= Date: Mon, 19 Jul 2021 23:08:11 +0300 Subject: [PATCH 3/7] Fix default stemmer (again) (#116) * Fix default stemmer (again) TNTSearch changed default stemmer again https://github.com/teamtnt/tntsearch/commit/b675c625782b20563e4b01bf7c2934b701b80489. To make our plugin behaviour consistent remove 'default' value, use 'NoStemmer' as default and always set stemmer in the code. * Disable stemmer for users with older config --- README.md | 3 +-- blueprints.yaml | 2 +- classes/GravTNTSearch.php | 8 +++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1d132b2..f6a35ce 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ enable_admin_page_events: true search_type: auto fuzzy: false phrases: true -stemmer: default +stemmer: 'no' display_route: true display_hits: true display_time: true @@ -105,7 +105,6 @@ The configuration options are as follows: * `fuzzy` - matches if the words are 'close' but not necessarily exact matches * `phrases` - automatically handle phrases support * `stemmer` - can be one of these types: - * `default` - Porter stemmer for English language * `no` - no stemmer * `arabic` - Arabic language * `croatian` - Croatian language diff --git a/blueprints.yaml b/blueprints.yaml index f23c271..8fda9d4 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -174,8 +174,8 @@ form: classes: fancy label: Stemmer help: An automated process which produces a base string in an attempt to represent related words. If your content is not in the language listed, for best search results it is recommended to disable the stemmer. + default: no options: - default: Default (English) no: Disabled arabic: Arabic croatian: Croatian diff --git a/classes/GravTNTSearch.php b/classes/GravTNTSearch.php index f5a1082..0935135 100644 --- a/classes/GravTNTSearch.php +++ b/classes/GravTNTSearch.php @@ -42,7 +42,7 @@ public function __construct($options = []) $locator = Grav::instance()['locator']; $search_type = $config->get('plugins.tntsearch.search_type', 'auto'); - $stemmer = $config->get('plugins.tntsearch.stemmer', 'default'); + $stemmer = $config->get('plugins.tntsearch.stemmer', 'no'); $limit = $config->get('plugins.tntsearch.limit', 20); $snippet = $config->get('plugins.tntsearch.snippet', 300); $data_path = $locator->findResource('user://data', true) . '/tntsearch'; @@ -225,8 +225,10 @@ public function createIndex() $this->tnt->setDatabaseHandle(new GravConnector); $indexer = $this->tnt->createIndex($this->index); - // Set the stemmer language if set - if ($this->options['stemmer'] !== 'default') { + // Disable stemmer for users with older configuration. + if ($this->options['stemmer'] == 'default') { + $indexer->setLanguage('no'); + } else { $indexer->setLanguage($this->options['stemmer']); } From b4dd092b831af6a29d9d32ee8ef0d1dba853f52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vilius=20=C5=A0umskas?= Date: Sat, 30 Oct 2021 05:13:34 +0300 Subject: [PATCH 4/7] Actually enable fuzzy search (#123) * Actually enable fuzzy search * Switch the default fuzziness For backward compatibility switch the fuzzy option to documented "false", sync with tntsearch.yaml. --- blueprints.yaml | 2 +- classes/GravTNTSearch.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/blueprints.yaml b/blueprints.yaml index 8fda9d4..455e49b 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -150,7 +150,7 @@ form: type: toggle label: Fuzzy Search highlight: 1 - default: 1 + default: 0 options: 1: Enabled 0: Disabled diff --git a/classes/GravTNTSearch.php b/classes/GravTNTSearch.php index 0935135..6f78e4f 100644 --- a/classes/GravTNTSearch.php +++ b/classes/GravTNTSearch.php @@ -42,6 +42,7 @@ public function __construct($options = []) $locator = Grav::instance()['locator']; $search_type = $config->get('plugins.tntsearch.search_type', 'auto'); + $fuzzy = $config->get('plugins.tntsearch.fuzzy', false); $stemmer = $config->get('plugins.tntsearch.stemmer', 'no'); $limit = $config->get('plugins.tntsearch.limit', 20); $snippet = $config->get('plugins.tntsearch.snippet', 300); @@ -64,6 +65,7 @@ public function __construct($options = []) $defaults = [ 'json' => false, 'search_type' => $search_type, + 'fuzzy' => $fuzzy, 'stemmer' => $stemmer, 'limit' => $limit, 'as_you_type' => true, From 60562d62856c114f23c183f7873fe1c809f4c7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vilius=20=C5=A0umskas?= Date: Mon, 1 Nov 2021 00:07:34 +0200 Subject: [PATCH 5/7] Add configurable Levenshtein distance for fuzzy search (#124) * Add configurable Levenshtein distance for fuzzy search * Style fix --- README.md | 2 ++ blueprints.yaml | 7 +++++++ classes/GravTNTSearch.php | 3 +++ tntsearch.yaml | 1 + 4 files changed, 13 insertions(+) diff --git a/README.md b/README.md index f6a35ce..e9541ce 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ built_in_search_page: true enable_admin_page_events: true search_type: auto fuzzy: false +distance: 2 phrases: true stemmer: 'no' display_route: true @@ -103,6 +104,7 @@ The configuration options are as follows: * `boolean` - supports `or` or `minus`. e.g. `foo -bar` * `auto` - automatically detects whether to use `basic` or `boolean` * `fuzzy` - matches if the words are 'close' but not necessarily exact matches +* `distance` - Levenshtein distance of fuzzy search. It represents the amount of characters which need to be changed, removed, or added in a word in order it to match the search keyword. Increasing the distance produces more search results but decreases the accuracy of the search. * `phrases` - automatically handle phrases support * `stemmer` - can be one of these types: * `no` - no stemmer diff --git a/blueprints.yaml b/blueprints.yaml index 455e49b..faa3772 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -157,6 +157,13 @@ form: validate: type: bool + distance: + type: number + size: x-small + label: Levenshtein distance of fuzzy search + help: It represents the amount of characters which need to be changed, removed, or added in a word in order it to match the search keyword. Increasing the distance produces more search results but decreases the accuracy of the search. + default: 2 + phrases: type: toggle label: Match quoted phrases diff --git a/classes/GravTNTSearch.php b/classes/GravTNTSearch.php index 6f78e4f..864856d 100644 --- a/classes/GravTNTSearch.php +++ b/classes/GravTNTSearch.php @@ -43,6 +43,7 @@ public function __construct($options = []) $search_type = $config->get('plugins.tntsearch.search_type', 'auto'); $fuzzy = $config->get('plugins.tntsearch.fuzzy', false); + $distance = $config->get('plugins.tntsearch.distance', 2); $stemmer = $config->get('plugins.tntsearch.stemmer', 'no'); $limit = $config->get('plugins.tntsearch.limit', 20); $snippet = $config->get('plugins.tntsearch.snippet', 300); @@ -66,6 +67,7 @@ public function __construct($options = []) 'json' => false, 'search_type' => $search_type, 'fuzzy' => $fuzzy, + 'distance' => $distance, 'stemmer' => $stemmer, 'limit' => $limit, 'as_you_type' => true, @@ -99,6 +101,7 @@ public function search($query) if (isset($this->options['fuzzy']) && $this->options['fuzzy']) { $this->tnt->fuzziness = true; + $this->tnt->fuzzy_distance = $this->options['distance']; } $limit = (int)$this->options['limit']; diff --git a/tntsearch.yaml b/tntsearch.yaml index c2647ab..c0df206 100644 --- a/tntsearch.yaml +++ b/tntsearch.yaml @@ -7,6 +7,7 @@ built_in_search_page: true enable_admin_page_events: true search_type: auto fuzzy: false +distance: 2 phrases: true stemmer: default display_route: true From 000d8d8a35becb308bb6065040671f7896e28c3a Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 6 Mar 2023 10:04:37 -0700 Subject: [PATCH 6/7] updated changelog + vendors --- CHANGELOG.md | 10 +- composer.lock | 25 +- vendor/autoload.php | 18 + vendor/composer/ClassLoader.php | 156 +++- vendor/composer/InstalledVersions.php | 623 +++++++++------- vendor/composer/autoload_classmap.php | 2 +- vendor/composer/autoload_files.php | 2 +- vendor/composer/autoload_namespaces.php | 2 +- vendor/composer/autoload_psr4.php | 2 +- vendor/composer/autoload_real.php | 49 +- vendor/composer/installed.json | 25 +- vendor/composer/installed.php | 59 +- vendor/teamtnt/tntsearch/.github/stale.yml | 18 + vendor/teamtnt/tntsearch/.travis.yml | 2 +- vendor/teamtnt/tntsearch/README.md | 20 +- vendor/teamtnt/tntsearch/composer.json | 9 +- .../src/Classifier/TNTClassifier.php | 4 +- .../tntsearch/src/Indexer/TNTIndexer.php | 14 +- .../tntsearch/src/Stemmer/FrenchStemmer.php | 693 ++++++++++++++++++ .../tntsearch/src/Stemmer/PolishStemmer.php | 144 ++++ .../tntsearch/src/Support/BigramTokenizer.php | 11 + .../tntsearch/src/Support/Collection.php | 5 +- .../src/Support/EdgeNgramTokenizer.php | 23 + .../tntsearch/src/Support/Expression.php | 2 +- .../src/Support/FivegramTokenizer.php | 12 + .../src/Support/FourgramTokenizer.php | 12 + .../tntsearch/src/Support/Highlighter.php | 114 +-- .../tntsearch/src/Support/NGramTokenizer.php | 34 + .../src/Support/ProductTokenizer.php | 2 +- .../src/Support/TrigramTokenizer.php | 12 + vendor/teamtnt/tntsearch/src/TNTSearch.php | 6 +- .../teamtnt/tntsearch/tests/TNTSearchTest.php | 21 +- .../tntsearch/tests/_files/cities-geo.index | Bin 4509696 -> 4509696 bytes .../tests/stemmer/FrenchStemmerTest.php | 13 + .../tests/stemmer/GermanStemmerTest.php | 2 +- .../tests/stemmer/PolishStemmerTest.php | 21 + .../tests/stemmer/PorterStemmerTest.php | 2 +- .../tests/stemmer/PortugueseStemmerTest.php | 2 +- .../tests/support/BigramTokenizerTest.php | 16 + .../tests/support/EdgeNgramTokenizerTest.php | 26 + .../tests/support/ExpressionTest.php | 3 + .../tests/support/FivegramTokenizerTest.php | 16 + .../tests/support/FourgramTokenizerTest.php | 16 + .../tests/support/NGramTokenizerTest.php | 37 + .../tests/support/TrigramTokenizerTest.php | 16 + 45 files changed, 1809 insertions(+), 492 deletions(-) create mode 100644 vendor/teamtnt/tntsearch/.github/stale.yml create mode 100644 vendor/teamtnt/tntsearch/src/Stemmer/FrenchStemmer.php create mode 100644 vendor/teamtnt/tntsearch/src/Stemmer/PolishStemmer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/BigramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/EdgeNgramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/FivegramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/FourgramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/NGramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/src/Support/TrigramTokenizer.php create mode 100644 vendor/teamtnt/tntsearch/tests/stemmer/FrenchStemmerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/stemmer/PolishStemmerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/BigramTokenizerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/EdgeNgramTokenizerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/FivegramTokenizerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/FourgramTokenizerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/NGramTokenizerTest.php create mode 100644 vendor/teamtnt/tntsearch/tests/support/TrigramTokenizerTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c0ee9c2..e0d6b34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ -# v3.3.2 -## mm/dd/2021 +# v3.4.0 +## mm/dd/2023 1. [](#improved) - * Added French translation [#100](https://github.com/trilbymedia/grav-plugin-tntsearch/issues/100) + * Updated TNTSearch library to `2.9.0` + * Enable Fuzy search [#123](https://github.com/trilbymedia/grav-plugin-tntsearch/pull/123) + * Add configuration for Levenshtein distance for fuzzy search [#124](https://github.com/trilbymedia/grav-plugin-tntsearch/pull/124) + * Added French translation [#100](https://github.com/trilbymedia/grav-plugin-tntsearch/issues/100) + * Added missing stemmers [#115](https://github.com/trilbymedia/grav-plugin-tntsearch/pull/115) [#116](https://github.com/trilbymedia/grav-plugin-tntsearch/pull/116) # v3.3.1 ## 02/25/2021 diff --git a/composer.lock b/composer.lock index 7164cc1..3cb6ef2 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "teamtnt/tntsearch", - "version": "v2.6.0", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/teamtnt/tntsearch.git", - "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4" + "reference": "ccedae0cfe21f7831f2dd1f973cf8904dad42d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/teamtnt/tntsearch/zipball/d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", - "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", + "url": "https://api.github.com/repos/teamtnt/tntsearch/zipball/ccedae0cfe21f7831f2dd1f973cf8904dad42d8d", + "reference": "ccedae0cfe21f7831f2dd1f973cf8904dad42d8d", "shasum": "" }, "require": { @@ -27,16 +27,17 @@ "php": "~7.1|^8" }, "require-dev": { - "phpunit/phpunit": "7.*" + "phpunit/phpunit": "7.*|8.*|9.*", + "symfony/var-dumper": "^4|^5.2" }, "type": "library", "autoload": { - "psr-4": { - "TeamTNT\\TNTSearch\\": "src" - }, "files": [ "helper/helpers.php" - ] + ], + "psr-4": { + "TeamTNT\\TNTSearch\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -65,7 +66,7 @@ ], "support": { "issues": "https://github.com/teamtnt/tntsearch/issues", - "source": "https://github.com/teamtnt/tntsearch/tree/v2.6.0" + "source": "https://github.com/teamtnt/tntsearch/tree/v2.9.0" }, "funding": [ { @@ -81,7 +82,7 @@ "type": "patreon" } ], - "time": "2020-12-21T09:11:54+00:00" + "time": "2022-02-22T10:35:34+00:00" } ], "packages-dev": [], @@ -99,5 +100,5 @@ "platform-overrides": { "php": "7.1.3" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.3.0" } diff --git a/vendor/autoload.php b/vendor/autoload.php index 068ebba..0c40f1f 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInit6693564509f9a3fa6ed2c7bf76fdb017::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 4d989a2..a72151c 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -42,30 +42,79 @@ */ class ClassLoader { + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var ?string */ private $vendorDir; // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ private $missingClasses = array(); + + /** @var ?string */ private $apcuPrefix; + /** + * @var self[] + */ private static $registeredLoaders = array(); + /** + * @param ?string $vendorDir + */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); } + /** + * @return string[] + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { @@ -75,28 +124,47 @@ public function getPrefixes() return array(); } + /** + * @return array[] + * @psalm-return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return string[] Array of classname => path + * @psalm-return array + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void */ public function addClassMap(array $classMap) { @@ -111,9 +179,11 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -156,11 +226,13 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -204,8 +276,10 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -220,10 +294,12 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -243,6 +319,8 @@ public function setPsr4($prefix, $paths) * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -265,6 +343,8 @@ public function getUseIncludePath() * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -285,6 +365,8 @@ public function isClassMapAuthoritative() * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -305,14 +387,18 @@ public function getApcuPrefix() * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); if (null === $this->vendorDir) { - //no-op - } elseif ($prepend) { + return; + } + + if ($prepend) { self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; } else { unset(self::$registeredLoaders[$this->vendorDir]); @@ -322,6 +408,8 @@ public function register($prepend = false) /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { @@ -336,15 +424,18 @@ public function unregister() * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } + + return null; } /** @@ -399,6 +490,11 @@ public static function getRegisteredLoaders() return self::$registeredLoaders; } + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -464,14 +560,26 @@ private function findFileWithExtension($class, $ext) return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index 8053c51..c6b54af 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -1,293 +1,352 @@ + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Composer; use Composer\Autoload\ClassLoader; use Composer\Semver\VersionParser; - - - - - +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ class InstalledVersions { -private static $installed = array ( - 'root' => - array ( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'aliases' => - array ( - ), - 'reference' => '7836c86e194af3454fafab9ca0d717813bf3525e', - 'name' => 'trilbymedia/grav-plugin-tntsearch', - ), - 'versions' => - array ( - 'teamtnt/tntsearch' => - array ( - 'pretty_version' => 'v2.6.0', - 'version' => '2.6.0.0', - 'aliases' => - array ( - ), - 'reference' => 'd9b2d764491c87f03ec214ed8dbc27336cf0c0e4', - ), - 'trilbymedia/grav-plugin-tntsearch' => - array ( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'aliases' => - array ( - ), - 'reference' => '7836c86e194af3454fafab9ca0d717813bf3525e', - ), - ), -); -private static $canGetVendors; -private static $installedByVendor = array(); - - - - - - - -public static function getInstalledPackages() -{ -$packages = array(); -foreach (self::getInstalled() as $installed) { -$packages[] = array_keys($installed['versions']); -} - - -if (1 === \count($packages)) { -return $packages[0]; -} - -return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); -} - - - - - - - - - -public static function isInstalled($packageName) -{ -foreach (self::getInstalled() as $installed) { -if (isset($installed['versions'][$packageName])) { -return true; -} -} - -return false; -} - - - - - - - - - - - - - - -public static function satisfies(VersionParser $parser, $packageName, $constraint) -{ -$constraint = $parser->parseConstraints($constraint); -$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); - -return $provided->matches($constraint); -} - - - - - - - - - - -public static function getVersionRanges($packageName) -{ -foreach (self::getInstalled() as $installed) { -if (!isset($installed['versions'][$packageName])) { -continue; -} - -$ranges = array(); -if (isset($installed['versions'][$packageName]['pretty_version'])) { -$ranges[] = $installed['versions'][$packageName]['pretty_version']; -} -if (array_key_exists('aliases', $installed['versions'][$packageName])) { -$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); -} -if (array_key_exists('replaced', $installed['versions'][$packageName])) { -$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); -} -if (array_key_exists('provided', $installed['versions'][$packageName])) { -$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); -} - -return implode(' || ', $ranges); -} - -throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); -} - - - - - -public static function getVersion($packageName) -{ -foreach (self::getInstalled() as $installed) { -if (!isset($installed['versions'][$packageName])) { -continue; -} - -if (!isset($installed['versions'][$packageName]['version'])) { -return null; -} - -return $installed['versions'][$packageName]['version']; -} - -throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); -} - - - - - -public static function getPrettyVersion($packageName) -{ -foreach (self::getInstalled() as $installed) { -if (!isset($installed['versions'][$packageName])) { -continue; -} - -if (!isset($installed['versions'][$packageName]['pretty_version'])) { -return null; -} - -return $installed['versions'][$packageName]['pretty_version']; -} - -throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); -} - - - - - -public static function getReference($packageName) -{ -foreach (self::getInstalled() as $installed) { -if (!isset($installed['versions'][$packageName])) { -continue; -} - -if (!isset($installed['versions'][$packageName]['reference'])) { -return null; -} - -return $installed['versions'][$packageName]['reference']; -} - -throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); -} - - - - - -public static function getRootPackage() -{ -$installed = self::getInstalled(); - -return $installed[0]['root']; -} - - - - - - - -public static function getRawData() -{ -return self::$installed; -} - - - - - - - - - - - - - - - - - - - -public static function reload($data) -{ -self::$installed = $data; -self::$installedByVendor = array(); -} - - - - -private static function getInstalled() -{ -if (null === self::$canGetVendors) { -self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); -} - -$installed = array(); - -if (self::$canGetVendors) { - -foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { -if (isset(self::$installedByVendor[$vendorDir])) { -$installed[] = self::$installedByVendor[$vendorDir]; -} elseif (is_file($vendorDir.'/composer/installed.php')) { -$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; -} -} -} - -$installed[] = self::$installed; - -return $installed; -} + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 042e42d..750f552 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 66021b0..e127d8d 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -2,7 +2,7 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index b7fc012..15a2ff3 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 51fb010..ebc8519 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index f7abba5..aeacc66 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -25,51 +25,26 @@ public static function getLoader() require __DIR__ . '/platform_check.php'; spl_autoload_register(array('ComposerAutoloaderInit6693564509f9a3fa6ed2c7bf76fdb017', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInit6693564509f9a3fa6ed2c7bf76fdb017', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInit6693564509f9a3fa6ed2c7bf76fdb017::getInitializer($loader)); - call_user_func(\Composer\Autoload\ComposerStaticInit6693564509f9a3fa6ed2c7bf76fdb017::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } + $loader->register(true); - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } + $filesToLoad = \Composer\Autoload\ComposerStaticInit6693564509f9a3fa6ed2c7bf76fdb017::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); + require $file; } - } - - $loader->register(true); - - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit6693564509f9a3fa6ed2c7bf76fdb017::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire6693564509f9a3fa6ed2c7bf76fdb017($fileIdentifier, $file); + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -function composerRequire6693564509f9a3fa6ed2c7bf76fdb017($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 8252194..86b5322 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,17 +2,17 @@ "packages": [ { "name": "teamtnt/tntsearch", - "version": "v2.6.0", - "version_normalized": "2.6.0.0", + "version": "v2.9.0", + "version_normalized": "2.9.0.0", "source": { "type": "git", "url": "https://github.com/teamtnt/tntsearch.git", - "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4" + "reference": "ccedae0cfe21f7831f2dd1f973cf8904dad42d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/teamtnt/tntsearch/zipball/d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", - "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", + "url": "https://api.github.com/repos/teamtnt/tntsearch/zipball/ccedae0cfe21f7831f2dd1f973cf8904dad42d8d", + "reference": "ccedae0cfe21f7831f2dd1f973cf8904dad42d8d", "shasum": "" }, "require": { @@ -22,18 +22,19 @@ "php": "~7.1|^8" }, "require-dev": { - "phpunit/phpunit": "7.*" + "phpunit/phpunit": "7.*|8.*|9.*", + "symfony/var-dumper": "^4|^5.2" }, - "time": "2020-12-21T09:11:54+00:00", + "time": "2022-02-22T10:35:34+00:00", "type": "library", "installation-source": "dist", "autoload": { - "psr-4": { - "TeamTNT\\TNTSearch\\": "src" - }, "files": [ "helper/helpers.php" - ] + ], + "psr-4": { + "TeamTNT\\TNTSearch\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -62,7 +63,7 @@ ], "support": { "issues": "https://github.com/teamtnt/tntsearch/issues", - "source": "https://github.com/teamtnt/tntsearch/tree/v2.6.0" + "source": "https://github.com/teamtnt/tntsearch/tree/v2.9.0" }, "funding": [ { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index e1fef72..6289ad0 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,33 +1,32 @@ - - array ( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'aliases' => - array ( + array( + 'name' => 'trilbymedia/grav-plugin-tntsearch', + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '60562d62856c114f23c183f7873fe1c809f4c7b5', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, ), - 'reference' => '7836c86e194af3454fafab9ca0d717813bf3525e', - 'name' => 'trilbymedia/grav-plugin-tntsearch', - ), - 'versions' => - array ( - 'teamtnt/tntsearch' => - array ( - 'pretty_version' => 'v2.6.0', - 'version' => '2.6.0.0', - 'aliases' => - array ( - ), - 'reference' => 'd9b2d764491c87f03ec214ed8dbc27336cf0c0e4', + 'versions' => array( + 'teamtnt/tntsearch' => array( + 'pretty_version' => 'v2.9.0', + 'version' => '2.9.0.0', + 'reference' => 'ccedae0cfe21f7831f2dd1f973cf8904dad42d8d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../teamtnt/tntsearch', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'trilbymedia/grav-plugin-tntsearch' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '60562d62856c114f23c183f7873fe1c809f4c7b5', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), ), - 'trilbymedia/grav-plugin-tntsearch' => - array ( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'aliases' => - array ( - ), - 'reference' => '7836c86e194af3454fafab9ca0d717813bf3525e', - ), - ), ); diff --git a/vendor/teamtnt/tntsearch/.github/stale.yml b/vendor/teamtnt/tntsearch/.github/stale.yml new file mode 100644 index 0000000..4094449 --- /dev/null +++ b/vendor/teamtnt/tntsearch/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 240 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + - PR +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/vendor/teamtnt/tntsearch/.travis.yml b/vendor/teamtnt/tntsearch/.travis.yml index a02b9d6..cfebe76 100644 --- a/vendor/teamtnt/tntsearch/.travis.yml +++ b/vendor/teamtnt/tntsearch/.travis.yml @@ -4,7 +4,7 @@ php: - 7.1 - 7.2 - 7.3 - - 7.4snapshot + - 7.4 - 8.0 addons: diff --git a/vendor/teamtnt/tntsearch/README.md b/vendor/teamtnt/tntsearch/README.md index 63d6d93..61aed08 100644 --- a/vendor/teamtnt/tntsearch/README.md +++ b/vendor/teamtnt/tntsearch/README.md @@ -8,7 +8,7 @@ # TNTSearch -TNTSearch is a full-featured full text search (FTS) engine written entirely in PHP. A simple configuration allows you to add an amazing search experience in just minutes. Features include: +TNTSearch is a full-text search (FTS) engine written entirely in PHP. A simple configuration allows you to add an amazing search experience in just minutes. Features include: * Fuzzy search * Search as you type @@ -47,9 +47,15 @@ or [Facebook](https://www.facebook.com/tntstudiohr)  |  ## Tutorials -* [Solving the search problem with Laravel and TNTSearch](http://tnt.studio/blog/solving-the-search-problem-with-laravel-and-tntsearch) -* [Searching for Bobby Fisher with Laravel 5](http://tnt.studio/blog/searching-for-bobby-fisher-with-laravel-5) -* [Did you mean functionality with Laravel Scout](http://tnt.studio/blog/did-you-mean-functionality-with-laravel-scout) +* [Solving the search problem with Laravel and TNTSearch](https://tnt.studio/solving-the-search-problem-with-laravel-and-tntsearch) +* [Searching for Users with Laravel Scout and TNTSearch](https://tnt.studio/searching-for-users-with-laravel-scout-and-tntsearch) + +## Premium products + +If you're using TNT Search and finding it useful, take a look at our premium analytics tool: + + +[](https://analytics.tnt.studio) ## Support us on Open Collective @@ -115,7 +121,8 @@ $indexer->setPrimaryKey('article_id'); ### Making the primary key searchable -By default the primary key is not searchable. If you wanna make it searchable, simply run: +By default, the primary key isn't searchable. If you want to make it searchable, simply run: + ```php $indexer->includePrimaryKey(); @@ -123,8 +130,7 @@ $indexer->includePrimaryKey(); ### Searching -Searching for a phrase or keyword is trivial - +Searching for a phrase or keyword is trivial: ```php use TeamTNT\TNTSearch\TNTSearch; diff --git a/vendor/teamtnt/tntsearch/composer.json b/vendor/teamtnt/tntsearch/composer.json index 887ad62..f1a0bad 100644 --- a/vendor/teamtnt/tntsearch/composer.json +++ b/vendor/teamtnt/tntsearch/composer.json @@ -6,11 +6,11 @@ "teamtnt", "tntsearch", "search", - "fulltext", + "fulltext", "geosearch", "text classification", "bm25", - "stemming", + "stemming", "fuzzy search" ], "homepage": "https://github.com/teamtnt/tntsearch", @@ -28,7 +28,8 @@ "ext-mbstring": "*" }, "require-dev": { - "phpunit/phpunit": "7.*" + "phpunit/phpunit": "7.*|8.*|9.*", + "symfony/var-dumper": "^4|^5.2" }, "autoload": { "psr-4": { @@ -38,4 +39,4 @@ "helper/helpers.php" ] } -} +} \ No newline at end of file diff --git a/vendor/teamtnt/tntsearch/src/Classifier/TNTClassifier.php b/vendor/teamtnt/tntsearch/src/Classifier/TNTClassifier.php index b96e6dd..94cfcfd 100644 --- a/vendor/teamtnt/tntsearch/src/Classifier/TNTClassifier.php +++ b/vendor/teamtnt/tntsearch/src/Classifier/TNTClassifier.php @@ -2,7 +2,7 @@ namespace TeamTNT\TNTSearch\Classifier; -use TeamTNT\TNTSearch\Stemmer\PorterStemmer; +use TeamTNT\TNTSearch\Stemmer\NoStemmer; use TeamTNT\TNTSearch\Support\Tokenizer; class TNTClassifier @@ -18,7 +18,7 @@ class TNTClassifier public function __construct() { $this->tokenizer = new Tokenizer; - $this->stemmer = new PorterStemmer; + $this->stemmer = new NoStemmer; } public function predict($statement) diff --git a/vendor/teamtnt/tntsearch/src/Indexer/TNTIndexer.php b/vendor/teamtnt/tntsearch/src/Indexer/TNTIndexer.php index 1742d3a..4275568 100644 --- a/vendor/teamtnt/tntsearch/src/Indexer/TNTIndexer.php +++ b/vendor/teamtnt/tntsearch/src/Indexer/TNTIndexer.php @@ -13,7 +13,7 @@ use TeamTNT\TNTSearch\Connectors\SqlServerConnector; use TeamTNT\TNTSearch\FileReaders\TextFileReader; use TeamTNT\TNTSearch\Stemmer\CroatianStemmer; -use TeamTNT\TNTSearch\Stemmer\PorterStemmer; +use TeamTNT\TNTSearch\Stemmer\NoStemmer; use TeamTNT\TNTSearch\Support\Collection; use TeamTNT\TNTSearch\Support\Tokenizer; use TeamTNT\TNTSearch\Support\TokenizerInterface; @@ -41,7 +41,7 @@ class TNTIndexer public function __construct() { - $this->stemmer = new PorterStemmer; + $this->stemmer = new NoStemmer; $this->tokenizer = new Tokenizer; $this->filereader = new TextFileReader; } @@ -71,7 +71,7 @@ public function loadConfig(array $config) if (!isset($this->config['driver'])) { $this->config['driver'] = ""; } - + if (!isset($this->config['wal'])) { $this->config['wal'] = true; } @@ -131,9 +131,9 @@ public function setCroatianStemmer() } /** - * @param string $language - one of: arabic, croatian, german, italian, porter, russian, ukrainian + * @param string $language - one of: no, arabic, croatian, german, italian, porter, portuguese, russian, ukrainian */ - public function setLanguage($language = 'porter') + public function setLanguage($language = 'no') { $class = 'TeamTNT\\TNTSearch\\Stemmer\\'.ucfirst(strtolower($language)).'Stemmer'; $this->setStemmer(new $class); @@ -178,7 +178,7 @@ public function createIndex($indexName) $this->index = new PDO('sqlite:'.$this->config['storage'].$indexName); $this->index->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - if($this->config['wal']) { + if ($this->config['wal']) { $this->index->exec("PRAGMA journal_mode=wal;"); } @@ -306,7 +306,7 @@ public function run() if ($counter % 10000 == 0) { $this->index->commit(); $this->index->beginTransaction(); - $this->info("Commited"); + $this->info("Committed"); } } $this->index->commit(); diff --git a/vendor/teamtnt/tntsearch/src/Stemmer/FrenchStemmer.php b/vendor/teamtnt/tntsearch/src/Stemmer/FrenchStemmer.php new file mode 100644 index 0000000..90a381a --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Stemmer/FrenchStemmer.php @@ -0,0 +1,693 @@ +analyze($word); + } + + public function analyze($word) + { + $this->word = mb_strtolower($word); + + $this->plainVowels = implode('', static::$vowels); + + $this->step0(); + + $this->rv(); + $this->r1(); + $this->r2(); + + // to know if step1, 2a or 2b have altered the word + $this->originalWord = $this->word; + + $nextStep = $this->step1(); + + // Do step 2a if either no ending was removed by step 1, or if one of endings amment, emment, ment, ments was found. + if (($nextStep == 2) || ($this->originalWord === $this->word) ) { + $modified = $this->step2a(); + + if (!$modified) { + $this->step2b(); + } + } + + if ($this->word != $this->originalWord) { + $this->step3(); + + } else { + $this->step4(); + } + + $this->step5(); + $this->step6(); + $this->finish(); + + return $this->word; + } + + + /** + * Assume the word is in lower case. + * Then put into upper case u or i preceded and followed by a vowel, and y preceded or followed by a vowel. + * u after q is also put into upper case. For example, + * jouer -> joUer + * ennuie -> ennuIe + * yeux -> Yeux + * quand -> qUand + */ + private function step0() + { + $this->word = preg_replace('#([q])u#u', '$1U', $this->word); + $this->word = preg_replace('#(['.$this->plainVowels.'])y#u', '$1Y', $this->word); + $this->word = preg_replace('#y(['.$this->plainVowels.'])#u', 'Y$1', $this->word); + $this->word = preg_replace('#(['.$this->plainVowels.'])u(['.$this->plainVowels.'])#u', '$1U$2', $this->word); + $this->word = preg_replace('#(['.$this->plainVowels.'])i(['.$this->plainVowels.'])#u', '$1I$2', $this->word); + } + + /** + * Step 1 + * Search for the longest among the following suffixes, and perform the action indicated. + * + * @return integer Next step number + */ + private function step1() + { + // ance iqUe isme able iste eux ances iqUes ismes ables istes + // delete if in R2 + if (($position = $this->search([ + 'ances', 'iqUes', 'ismes', 'ables', 'istes', 'ance', 'iqUe','isme', 'able', 'iste', 'eux' + ])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } + + return 3; + } + + // atrice ateur ation atrices ateurs ations + // delete if in R2 + // if preceded by ic, delete if in R2, else replace by iqU + if (($position = $this->search(['atrices', 'ateurs', 'ations', 'atrice', 'ateur', 'ation'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + + if (($position2 = $this->searchIfInR2(['ic'])) !== false) { + $this->word = mb_substr($this->word, 0, $position2); + } else { + $this->word = preg_replace('#(ic)$#u', 'iqU', $this->word); + } + } + + return 3; + } + + // logie logies + // replace with log if in R2 + if (($position = $this->search(['logies', 'logie'])) !== false) { + if ($this->inR2($position)) { + $this->word = preg_replace('#(logies|logie)$#u', 'log', $this->word); + } + + return 3; + } + + // usion ution usions utions + // replace with u if in R2 + if (($position = $this->search(['usions', 'utions', 'usion', 'ution'])) !== false) { + if ($this->inR2($position)) { + $this->word = preg_replace('#(usion|ution|usions|utions)$#u', 'u', $this->word); + } + + return 3; + } + + // ence ences + // replace with ent if in R2 + if (($position = $this->search(['ences', 'ence'])) !== false) { + if ($this->inR2($position)) { + $this->word = preg_replace('#(ence|ences)$#u', 'ent', $this->word); + } + + return 3; + } + + // issement issements + // delete if in R1 and preceded by a non-vowel + if (($position = $this->search(['issements', 'issement'])) != false) { + if ($this->inR1($position)) { + $before = $position - 1; + $letter = mb_substr($this->word, $before, 1); + + if (! in_array($letter, static::$vowels)) { + $this->word = mb_substr($this->word, 0, $position); + } + } + + return 3; + } + + // ement ements + // delete if in RV + // if preceded by iv, delete if in R2 (and if further preceded by at, delete if in R2), otherwise, + // if preceded by eus, delete if in R2, else replace by eux if in R1, otherwise, + // if preceded by abl or iqU, delete if in R2, otherwise, + // if preceded by ièr or Ièr, replace by i if in RV + if (($position = $this->search(['ements', 'ement'])) !== false) { + if ($this->inRv($position)) { + $this->word = mb_substr($this->word, 0, $position); + } + + if (($position = $this->searchIfInR2(['iv'])) !== false) { + $this->word = mb_substr($this->word, 0, $position); + + if (($position2 = $this->searchIfInR2(['at'])) !== false) { + $this->word = mb_substr($this->word, 0, $position2); + } + } elseif (($position = $this->search(['eus'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } elseif ($this->inR1($position)) { + $this->word = preg_replace('#(eus)$#u', 'eux', $this->word); + } + } elseif (($position = $this->searchIfInR2(['abl', 'iqU'])) !== false) { + $this->word = mb_substr($this->word, 0, $position); + } elseif (($this->searchIfInRv(['ièr', 'Ièr'])) !== false) { + $this->word = preg_replace('#(ièr|Ièr)$#u', 'i', $this->word); + } + + return 3; + } + + // ité ités + // delete if in R2 + // if preceded by abil, delete if in R2, else replace by abl, otherwise, + // if preceded by ic, delete if in R2, else replace by iqU, otherwise, + // if preceded by iv, delete if in R2 + if (($position = $this->search(['ités', 'ité'])) !== false) { + // delete if in R2 + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } + + // if preceded by abil, delete if in R2, else replace by abl, otherwise, + if (($position = $this->search(['abil'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } else { + $this->word = preg_replace('#(abil)$#u', 'abl', $this->word); + } + + // if preceded by ic, delete if in R2, else replace by iqU, otherwise, + } elseif (($position = $this->search(['ic'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } else { + $this->word = preg_replace('#(ic)$#u', 'iqU', $this->word); + } + + // if preceded by iv, delete if in R2 + } elseif (($position = $this->searchIfInR2(['iv'])) !== false) { + $this->word = mb_substr($this->word, 0, $position); + } + + return 3; + } + + // if ive ifs ives + // delete if in R2 + // if preceded by at, delete if in R2 (and if further preceded by ic, delete if in R2, else replace by iqU) + if (($position = $this->search(['ifs', 'ives', 'if', 'ive'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } + + if (($position = $this->searchIfInR2(['at'])) !== false) { + $this->word = mb_substr($this->word, 0, $position); + + if (($position2 = $this->search(['ic'])) !== false) { + if ($this->inR2($position2)) { + $this->word = mb_substr($this->word, 0, $position2); + } else { + $this->word = preg_replace('#(ic)$#u', 'iqU', $this->word); + } + } + } + + return 3; + } + + // eaux + // replace with eau + if (($this->search(['eaux'])) !== false) { + $this->word = preg_replace('#(eaux)$#u', 'eau', $this->word); + + return 3; + } + + // aux + // replace with al if in R1 + if (($position = $this->search(['aux'])) !== false) { + if ($this->inR1($position)) { + $this->word = preg_replace('#(aux)$#u', 'al', $this->word); + } + + return 3; + } + + // euse euses + // delete if in R2, else replace by eux if in R1 + if (($position = $this->search(['euses', 'euse'])) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } elseif ($this->inR1($position)) { + $this->word = preg_replace('#(euses|euse)$#u', 'eux', $this->word); + + } + + return 3; + } + + // amment + // replace with ant if in RV + if ( ($position = $this->search(['amment'])) !== false) { + if ($this->inRv($position)) { + $this->word = preg_replace('#(amment)$#u', 'ant', $this->word); + } + return 2; + } + + // emment + // replace with ent if in RV + if (($position = $this->search(['emment'])) !== false) { + if ($this->inRv($position)) { + $this->word = preg_replace('#(emment)$#u', 'ent', $this->word); + } + + return 2; + } + + // ment ments + // delete if preceded by a vowel in RV + if (($position = $this->search(['ments', 'ment'])) != false) { + $before = $position - 1; + $letter = mb_substr($this->word, $before, 1); + + if ($this->inRv($before) && (in_array($letter, static::$vowels)) ) { + $this->word = mb_substr($this->word, 0, $position); + } + + return 2; + } + + return 2; + } + + /** + * Step 2a: Verb suffixes beginning i + * In steps 2a and 2b all tests are confined to the RV region. + * Search for the longest among the following suffixes and if found, delete if preceded by a non-vowel. + * îmes ît îtes i ie ies ir ira irai iraIent irais irait iras irent irez iriez + * irions irons iront is issaIent issais issait issant issante issantes issants isse + * issent isses issez issiez issions issons it + * (Note that the non-vowel itself must also be in RV.) + */ + private function step2a() + { + if (($position = $this->searchIfInRv([ + 'îmes', 'îtes', 'ît', 'ies', 'ie', 'iraIent', 'irais', 'irait', 'irai', 'iras', 'ira', 'irent', 'irez', 'iriez', + 'irions', 'irons', 'iront', 'ir', 'issaIent', 'issais', 'issait', 'issant', 'issantes', 'issante', 'issants', + 'issent', 'isses', 'issez', 'isse', 'issiez', 'issions', 'issons', 'is', 'it', 'i'])) !== false) { + + $before = $position - 1; + $letter = mb_substr($this->word, $before, 1); + + if ( $this->inRv($before) && (!in_array($letter, static::$vowels)) ) { + $this->word = mb_substr($this->word, 0, $position); + + return true; + } + } + + return false; + } + + /** + * Do step 2b if step 2a was done, but failed to remove a suffix. + * Step 2b: Other verb suffixes + */ + private function step2b() + { + // é ée ées és èrent er era erai eraIent erais erait eras erez eriez erions erons eront ez iez + // delete + if (($position = $this->searchIfInRv([ + 'ées', 'èrent', 'erais', 'erait', 'erai', 'eraIent', 'eras', 'erez', 'eriez', + 'erions', 'erons', 'eront', 'era', 'er', 'iez', 'ez','és', 'ée', 'é'])) !== false) { + + $this->word = mb_substr($this->word, 0, $position); + + return true; + } + + // âmes ât âtes a ai aIent ais ait ant ante antes ants as asse assent asses assiez assions + // delete + // if preceded by e, delete + if (($position = $this->searchIfInRv([ + 'âmes', 'âtes', 'ât', 'aIent', 'ais', 'ait', 'antes', 'ante', 'ants', 'ant', + 'assent', 'asses', 'assiez', 'assions', 'asse', 'as', 'ai', 'a'])) !== false) { + + $before = $position - 1; + $letter = mb_substr($this->word, $before, 1); + + if ( $this->inRv($before) && ($letter === 'e') ) { + $this->word = mb_substr($this->word, 0, $before); + } else { + $this->word = mb_substr($this->word, 0, $position); + } + + return true; + } + + // ions + // delete if in R2 + if ( ($position = $this->searchIfInRv(array('ions'))) !== false) { + if ($this->inR2($position)) { + $this->word = mb_substr($this->word, 0, $position); + } + + return true; + } + + return false; + } + + /** + * Step 3: Replace final Y with i or final ç with c + */ + private function step3() + { + $this->word = preg_replace('#(Y)$#u', 'i', $this->word); + $this->word = preg_replace('#(ç)$#u', 'c', $this->word); + } + + /** + * Step 4: Residual suffix + */ + private function step4() + { + //If the word ends s, not preceded by a, i, o, u, è or s, delete it. + if (preg_match('#[^aiouès]s$#', $this->word)) { + $this->word = mb_substr($this->word, 0, -1); + } + + // In the rest of step 4, all tests are confined to the RV region. + // ion + // delete if in R2 and preceded by s or t + if ((($position = $this->searchIfInRv(['ion'])) !== false) && ($this->inR2($position)) ) { + $before = $position - 1; + $letter = mb_substr($this->word, $before, 1); + + if ( $this->inRv($before) && (($letter === 's') || ($letter === 't')) ) { + $this->word = mb_substr($this->word, 0, $position); + } + + return true; + } + + // ier ière Ier Ière + // replace with i + if (($this->searchIfInRv(['ier', 'ière', 'Ier', 'Ière'])) !== false) { + $this->word = preg_replace('#(ier|ière|Ier|Ière)$#u', 'i', $this->word); + + return true; + } + + // e + // delete + if (($this->searchIfInRv(['e'])) !== false) { + $this->word = mb_substr($this->word, 0, -1); + + return true; + } + + // ë + // if preceded by gu, delete + if (($position = $this->searchIfInRv(['guë'])) !== false) { + if ($this->inRv($position + 2)) { + $this->word = mb_substr($this->word, 0, -1); + + return true; + } + } + + return false; + } + + /** + * Step 5: Undouble + * If the word ends enn, onn, ett, ell or eill, delete the last letter + */ + private function step5() + { + if ($this->search(['enn', 'onn', 'ett', 'ell', 'eill']) !== false) { + $this->word = mb_substr($this->word, 0, -1); + } + } + + /** + * Step 6: Un-accent + * If the words ends é or è followed by at least one non-vowel, remove the accent from the e. + */ + private function step6() + { + $this->word = preg_replace('#(é|è)([^'.$this->plainVowels.']+)$#u', 'e$2', $this->word); + } + + /** + * And finally: + * Turn any remaining I, U and Y letters in the word back into lower case. + */ + private function finish() + { + $this->word = str_replace(['I','U','Y'], ['i', 'u', 'y'], $this->word); + } + + /** + * If the word begins with two vowels, RV is the region after the third letter, + * otherwise the region after the first vowel not at the beginning of the word, + * or the end of the word if these positions cannot be found. + * (Exceptionally, par, col or tap, at the begining of a word is also taken to define RV as the region to their right.) + */ + protected function rv() + { + $length = mb_strlen($this->word); + + $this->rv = ''; + $this->rvIndex = $length; + + if ($length < 3) { + return true; + } + + // If the word begins with two vowels, RV is the region after the third letter + $first = mb_substr($this->word, 0, 1); + $second = mb_substr($this->word, 1, 1); + + if ( (in_array($first, static::$vowels)) && (in_array($second, static::$vowels)) ) { + $this->rv = mb_substr($this->word, 3); + $this->rvIndex = 3; + + return true; + } + + // (Exceptionally, par, col or tap, at the begining of a word is also taken to define RV as the region to their right.) + $begin3 = mb_substr($this->word, 0, 3); + + if (in_array($begin3, ['par', 'col', 'tap'])) { + $this->rv = mb_substr($this->word, 3); + $this->rvIndex = 3; + + return true; + } + + // otherwise the region after the first vowel not at the beginning of the word, + for ($i = 1; $i < $length; ++$i) { + $letter = mb_substr($this->word, $i, 1); + + if (in_array($letter, static::$vowels)) { + $this->rv = mb_substr($this->word, ($i + 1)); + $this->rvIndex = $i + 1; + + return true; + } + } + + return false; + } + + protected function inRv($position) + { + return ($position >= $this->rvIndex); + } + + protected function inR1($position) + { + return ($position >= $this->r1Index); + } + + protected function inR2($position) + { + return ($position >= $this->r2Index); + } + + protected function searchIfInRv($suffixes) + { + return $this->search($suffixes, $this->rvIndex); + } + + protected function searchIfInR2($suffixes) + { + return $this->search($suffixes, $this->r2Index); + } + + protected function search($suffixes, $offset = 0) + { + $length = mb_strlen($this->word); + + if ($offset > $length) { + return false; + } + + foreach ($suffixes as $suffixe) { + if ((($position = mb_strrpos($this->word, $suffixe, $offset)) !== false) + && ((mb_strlen($suffixe) + $position) == $length)) { + return $position; + } + } + + return false; + } + + /** + * R1 is the region after the first non-vowel following a vowel, or the end of the word if there is no such non-vowel. + */ + protected function r1() + { + list($this->r1Index, $this->r1) = $this->rx($this->word); + } + + /** + * R2 is the region after the first non-vowel following a vowel in R1, or the end of the word if there is no such non-vowel. + */ + protected function r2() + { + list($index, $value) = $this->rx($this->r1); + + $this->r2 = $value; + $this->r2Index = $this->r1Index + $index; + } + + /** + * Common function for R1 and R2 + * Search the region after the first non-vowel following a vowel in $word, or the end of the word if there is no such non-vowel. + * R1 : $in = $this->word + * R2 : $in = R1 + */ + protected function rx($in) + { + $length = mb_strlen($in); + + // defaults + $value = ''; + $index = $length; + + // we search all vowels + $vowels = []; + + for ($i = 0; $i < $length; ++$i) { + $letter = mb_substr($in, $i, 1); + + if (in_array($letter, static::$vowels)) { + $vowels[] = $i; + } + } + + // search the non-vowel following a vowel + foreach ($vowels as $position) { + $after = $position + 1; + $letter = mb_substr($in, $after, 1); + + if (!in_array($letter, static::$vowels)) { + $index = $after + 1; + $value = mb_substr($in, ($after + 1)); + + break; + } + } + + return [$index, $value]; + } +} diff --git a/vendor/teamtnt/tntsearch/src/Stemmer/PolishStemmer.php b/vendor/teamtnt/tntsearch/src/Stemmer/PolishStemmer.php new file mode 100644 index 0000000..3ff2849 --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Stemmer/PolishStemmer.php @@ -0,0 +1,144 @@ + 7 && in_array(mb_substr($word, -5), array("zacja", "zacją", "zacji"))) { + return mb_substr($word, 0, -4); + } + if (strlen($word) > 6 && in_array(mb_substr($word, -4), array("acja", "acji", "acją", "tach", "anie", "enie", "eniu", "aniu"))) { + return mb_substr($word, 0, -4); + } + if (strlen($word) > 6 && (mb_substr($word, -4) == "tyka")) { + return mb_substr($word, 0, -2); + } + if (strlen($word) > 5 && in_array(mb_substr($word, -3), array("ach", "ami", "nia", "niu", "cia", "ciu"))) { + return mb_substr($word, 0, -3); + } + if (strlen($word) > 5 && in_array(mb_substr($word, -3), array("cji", "cja", "cją"))) { + return mb_substr($word, 0, -2); + } + if (strlen($word) > 5 && in_array(mb_substr($word, -2), array("ce", "ta"))) { + return mb_substr($word, 0, -2); + } + return $word; + } + + public static function removeDiminutive($word) + { + if (strlen($word) > 6) { + if (in_array(mb_substr($word, -5), array("eczek", "iczek", "iszek", "aszek", "uszek"))) { + return mb_substr($word, 0, -5); + } + if (in_array(mb_substr($word, -4), array("enek", "ejek", "erek"))) { + return mb_substr($word, 0, -2); + } + } + if (strlen($word) > 4) { + if (in_array(mb_substr($word, -2), array("ek", "ak"))) { + return mb_substr($word, 0, -2); + } + } + return $word; + } + + public static function removeAdjectiveEnds($word) + { + if (strlen($word) > 7 && (mb_substr($word, 0, 3) == "naj") && in_array(mb_substr($word, -3), array("sze", "szy"))) { + return mb_substr($word, 3, -3); + } + if (strlen($word) > 7 && (mb_substr($word, 0, 3) == "naj") && (mb_substr($word, 0, 5) == "szych")) { + return mb_substr($word, 3, -5); + } + if (strlen($word) > 6 && (mb_substr($word, -4) == "czny")) { + return mb_substr($word, 0, -4); + } + if (strlen($word) > 5 && in_array(mb_substr($word, -3), array("owy", "owa", "owe", "ych", "ego"))) { + return mb_substr($word, 0, -3); + } + if (strlen($word) > 5 && (mb_substr($word, -2) == "ej")) { + return mb_substr($word, 0, -2); + } + return $word; + } + + public static function removeVerbsEnds($word) + { + if (strlen($word) > 5 && (mb_substr($word, -3) == "bym")) { + return mb_substr($word, 0, -3); + } + if (strlen($word) > 5 && in_array(mb_substr($word, -3), array("esz", "asz", "cie", "eść", "aść", "łem", "amy", "emy"))) { + return mb_substr($word, 0, -3); + } + if (strlen($word) > 3 && in_array(mb_substr($word, -3), array("esz", "asz", "eść", "aść", "eć", "ać"))) { + return mb_substr($word, 0, -2); + } + if (strlen($word) > 3 && in_array(mb_substr($word, -2), array("aj"))) { + return mb_substr($word, 0, -1); + } + if (strlen($word) > 3 && in_array(mb_substr($word, -2), array("ać", "em", "am", "ał", "ił", "ić", "ąc"))) { + return mb_substr($word, 0, -2); + } + return $word; + } + + public static function removeAdverbsEnds($word) + { + if (strlen($word) > 4 && in_array(mb_substr($word, -3), array("nie", "wie", "rze"))) { + return mb_substr($word, 0, -2); + } + return $word; + } + + public static function removePluralForms($word) + { + if (strlen($word) > 4 && in_array(mb_substr($word, -2), array("ów", "om"))) { + return mb_substr($word, 0, -2); + } + if (strlen($word) > 4 && (mb_substr($word, -3) == "ami")) { + return mb_substr($word, 0, -3); + } + return $word; + } + + public static function removeGeneralEnds($word) + { + if (strlen($word) > 4 && in_array(substr($word, -2), array("ia", "ie"))) { + return substr($word, 0, -2); + } + if (strlen($word) > 4 && in_array(substr($word, -1), array("u", "ą", "i", "a", "ę", "y", "ę", "ł"))) { + return substr($word, 0, -1); + } + return $word; + } + + + public static function stem($word) + { + + $word = mb_strtolower($word); + + $stem = $word; + + $stem = self::removeNouns($stem); + $stem = self::removeDiminutive($stem); + $stem = self::removeAdjectiveEnds($stem); + $stem = self::removeVerbsEnds($stem); + $stem = self::removeAdverbsEnds($stem); + $stem = self::removePluralForms($stem); + $stem = self::removeGeneralEnds($stem); + + return $stem; + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/BigramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/BigramTokenizer.php new file mode 100644 index 0000000..75dc96b --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/BigramTokenizer.php @@ -0,0 +1,11 @@ +tokenize($text, $stopwords); + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/Collection.php b/vendor/teamtnt/tntsearch/src/Support/Collection.php index 18d339f..b66ca6f 100644 --- a/vendor/teamtnt/tntsearch/src/Support/Collection.php +++ b/vendor/teamtnt/tntsearch/src/Support/Collection.php @@ -5,6 +5,7 @@ use ArrayIterator; use Countable; use IteratorAggregate; +use Traversable; class Collection implements Countable, IteratorAggregate { @@ -120,7 +121,7 @@ public function implode($glue) /** * @return int */ - public function count() + public function count(): int { return count($this->items); } @@ -148,7 +149,7 @@ public function take($limit) /** * @return ArrayIterator */ - public function getIterator() + public function getIterator(): Traversable { return new ArrayIterator($this->items); } diff --git a/vendor/teamtnt/tntsearch/src/Support/EdgeNgramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/EdgeNgramTokenizer.php new file mode 100644 index 0000000..2cd6858 --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/EdgeNgramTokenizer.php @@ -0,0 +1,23 @@ +getPattern(), $text, -1, PREG_SPLIT_NO_EMPTY); + + foreach ($splits as $split) { + for ($i = 2; $i <= strlen($split); $i++) { + $ngrams[] = mb_substr($split, 0, $i); + } + } + + return $ngrams; + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/Expression.php b/vendor/teamtnt/tntsearch/src/Support/Expression.php index 7ce8fff..d1acc59 100644 --- a/vendor/teamtnt/tntsearch/src/Support/Expression.php +++ b/vendor/teamtnt/tntsearch/src/Support/Expression.php @@ -18,7 +18,7 @@ public function toPostfix($exp) $postfix[] = $token; } else { if ($token == ")") { - while (($top = array_pop($stack)) != "(") { + while (($top = array_pop($stack)) != "(" && !empty($top)) { $postfix[] = $top; } diff --git a/vendor/teamtnt/tntsearch/src/Support/FivegramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/FivegramTokenizer.php new file mode 100644 index 0000000..9eb7e0c --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/FivegramTokenizer.php @@ -0,0 +1,12 @@ +tokenize($text, $stopwords); + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/FourgramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/FourgramTokenizer.php new file mode 100644 index 0000000..9334b20 --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/FourgramTokenizer.php @@ -0,0 +1,12 @@ +tokenize($text, $stopwords); + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/Highlighter.php b/vendor/teamtnt/tntsearch/src/Support/Highlighter.php index 01bf151..9d82449 100644 --- a/vendor/teamtnt/tntsearch/src/Support/Highlighter.php +++ b/vendor/teamtnt/tntsearch/src/Support/Highlighter.php @@ -27,14 +27,14 @@ public function __construct(TokenizerInterface $tokenizer = null) } } - /** - * @param $text - * @param $needle - * @param string $tag - * @param array $options - * - * @return string - */ + /** + * @param $text + * @param $needle + * @param string $tag + * @param array $options + * + * @return string + */ public function highlight($text, $needle, $tag = 'em', $options = []) { $this->options = array_merge($this->options, $options); @@ -90,25 +90,25 @@ public function highlight($text, $needle, $tag = 'em', $options = []) return $text; } - /** - * find the locations of each of the words - * Nothing exciting here. The array_unique is required - * unless you decide to make the words unique before passing in - * - * @param $words - * @param $fulltext - * - * @return array - */ + /** + * find the locations of each of the words + * Nothing exciting here. The array_unique is required + * unless you decide to make the words unique before passing in + * + * @param $words + * @param $fulltext + * + * @return array + */ public function _extractLocations($words, $fulltext) { $locations = array(); foreach ($words as $word) { - $wordlen = strlen($word); - $loc = stripos($fulltext, $word); + $wordlen = mb_strlen($word); + $loc = mb_stripos($fulltext, $word); while ($loc !== false) { $locations[] = $loc; - $loc = stripos($fulltext, $word, $loc + $wordlen); + $loc = mb_stripos($fulltext, $word, $loc + $wordlen); } } $locations = array_unique($locations); @@ -117,19 +117,19 @@ public function _extractLocations($words, $fulltext) return $locations; } - /** - * Work out which is the most relevant portion to display - * This is done by looping over each match and finding the smallest distance between two found - * strings. The idea being that the closer the terms are the better match the snippet would be. - * When checking for matches we only change the location if there is a better match. - * The only exception is where we have only two matches in which case we just take the - * first as will be equally distant. - * - * @param $locations - * @param $prevcount - * - * @return int - */ + /** + * Work out which is the most relevant portion to display + * This is done by looping over each match and finding the smallest distance between two found + * strings. The idea being that the closer the terms are the better match the snippet would be. + * When checking for matches we only change the location if there is a better match. + * The only exception is where we have only two matches in which case we just take the + * first as will be equally distant. + * + * @param $locations + * @param $prevcount + * + * @return int + */ public function _determineSnipLocation($locations, $prevcount) { if (!isset($locations[0])) { @@ -162,22 +162,22 @@ public function _determineSnipLocation($locations, $prevcount) return $startpos; } - /** - * 1/6 ratio on prevcount tends to work pretty well and puts the terms - * in the middle of the extract - * - * @param $words - * @param $fulltext - * @param int $rellength - * @param int $prevcount - * @param string $indicator - * - * @return bool|string - */ + /** + * 1/6 ratio on prevcount tends to work pretty well and puts the terms + * in the middle of the extract + * + * @param $words + * @param $fulltext + * @param int $rellength + * @param int $prevcount + * @param string $indicator + * + * @return bool|string + */ public function extractRelevant($words, $fulltext, $rellength = 300, $prevcount = 50, $indicator = '...') { $words = preg_split($this->tokenizer->getPattern(), $words, -1, PREG_SPLIT_NO_EMPTY); - $textlength = strlen($fulltext); + $textlength = mb_strlen($fulltext); if ($textlength <= $rellength) { return $fulltext; } @@ -189,16 +189,30 @@ public function extractRelevant($words, $fulltext, $rellength = 300, $prevcount $startpos = $startpos - ($textlength - $startpos) / 2; } - $reltext = substr($fulltext, $startpos, $rellength); + // in case no match is found, reset position for proper math below + if ($startpos == -1) { + $startpos = 0; + } + + $reltext = mb_substr($fulltext, $startpos, $rellength); + preg_match_all($this->tokenizer->getPattern(), $reltext, $offset, PREG_OFFSET_CAPTURE); + // since PREG_OFFSET_CAPTURE returns offset in bytes we have to use mb_strlen(substr()) hack here + $last = mb_strlen(substr($reltext, 0, end($offset[0])[1])); + $first = mb_strlen(substr($reltext, 0, $offset[0][0][1])); + + // if no match is found, just return first $rellength characters without the last word + if (empty($locations)) { + return mb_substr($reltext, 0, $last) . $indicator; + } // check to ensure we dont snip the last word if thats the match if ($startpos + $rellength < $textlength) { - $reltext = substr($reltext, 0, strrpos($reltext, " ")) . $indicator; // remove last word + $reltext = mb_substr($reltext, 0, $last) . $indicator; // remove last word } // If we trimmed from the front add ... if ($startpos != 0) { - $reltext = $indicator . substr($reltext, strpos($reltext, " ") + 1); // remove first word + $reltext = $indicator . mb_substr($reltext, $first + 1); // remove first word } return $reltext; diff --git a/vendor/teamtnt/tntsearch/src/Support/NGramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/NGramTokenizer.php new file mode 100644 index 0000000..ac938e9 --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/NGramTokenizer.php @@ -0,0 +1,34 @@ +min_gram = $min_gram; + $this->max_gram = $max_gram; + } + + protected static $pattern = '/[\s,\.]+/'; + + public function tokenize($text, $stopwords = []) + { + $text = mb_strtolower($text); + + $ngrams = []; + $splits = preg_split($this->getPattern(), $text, -1, PREG_SPLIT_NO_EMPTY); + + foreach ($splits as $split) { + for ($currentGram = $this->min_gram; $currentGram <= $this->max_gram; $currentGram++) { + for ($i = 0; $i <= strlen($split) - $currentGram; $i++) { + $ngrams[] = mb_substr($split, $i, $currentGram); + } + } + } + + return $ngrams; + } +} diff --git a/vendor/teamtnt/tntsearch/src/Support/ProductTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/ProductTokenizer.php index 1053230..e25c590 100644 --- a/vendor/teamtnt/tntsearch/src/Support/ProductTokenizer.php +++ b/vendor/teamtnt/tntsearch/src/Support/ProductTokenizer.php @@ -3,7 +3,7 @@ class ProductTokenizer extends AbstractTokenizer implements TokenizerInterface { - static protected $pattern = '/[\s,]+/'; + static protected $pattern = '/[\s,\.]+/'; public function tokenize($text, $stopwords = []) { diff --git a/vendor/teamtnt/tntsearch/src/Support/TrigramTokenizer.php b/vendor/teamtnt/tntsearch/src/Support/TrigramTokenizer.php new file mode 100644 index 0000000..bd5531b --- /dev/null +++ b/vendor/teamtnt/tntsearch/src/Support/TrigramTokenizer.php @@ -0,0 +1,12 @@ +tokenize($text, $stopwords); + } +} diff --git a/vendor/teamtnt/tntsearch/src/TNTSearch.php b/vendor/teamtnt/tntsearch/src/TNTSearch.php index d370f39..fabc66e 100644 --- a/vendor/teamtnt/tntsearch/src/TNTSearch.php +++ b/vendor/teamtnt/tntsearch/src/TNTSearch.php @@ -5,7 +5,7 @@ use PDO; use TeamTNT\TNTSearch\Exceptions\IndexNotFoundException; use TeamTNT\TNTSearch\Indexer\TNTIndexer; -use TeamTNT\TNTSearch\Stemmer\PorterStemmer; +use TeamTNT\TNTSearch\Stemmer\NoStemmer; use TeamTNT\TNTSearch\Support\Collection; use TeamTNT\TNTSearch\Support\Expression; use TeamTNT\TNTSearch\Support\Highlighter; @@ -327,7 +327,7 @@ public function getWordlistByKeyword($keyword, $isLastWord = false) */ public function fuzzySearch($keyword) { - $prefix = substr($keyword, 0, $this->fuzzy_prefix_length); + $prefix = mb_substr($keyword, 0, $this->fuzzy_prefix_length); $searchWordlist = "SELECT * FROM wordlist WHERE term like :keyword ORDER BY num_hits DESC LIMIT {$this->fuzzy_max_expansions}"; $stmtWord = $this->index->prepare($searchWordlist); $stmtWord->bindValue(':keyword', mb_strtolower($prefix)."%"); @@ -371,7 +371,7 @@ public function setStemmer() if ($stemmer) { $this->stemmer = new $stemmer; } else { - $this->stemmer = isset($this->config['stemmer']) ? new $this->config['stemmer'] : new PorterStemmer; + $this->stemmer = isset($this->config['stemmer']) ? new $this->config['stemmer'] : new NoStemmer; } } diff --git a/vendor/teamtnt/tntsearch/tests/TNTSearchTest.php b/vendor/teamtnt/tntsearch/tests/TNTSearchTest.php index dfa4e02..d29f352 100644 --- a/vendor/teamtnt/tntsearch/tests/TNTSearchTest.php +++ b/vendor/teamtnt/tntsearch/tests/TNTSearchTest.php @@ -59,13 +59,13 @@ public function testSearchBoolean() $this->assertEquals([3, 4, 1, 2], $res['ids']); $this->assertEquals(4, $res['hits']); - $res = $tnt->searchBoolean('juliet -well'); + $res = $tnt->searchBoolean('juliet ~well'); $this->assertEquals([5, 6, 7, 8, 10], $res['ids']); - $res = $tnt->searchBoolean('juliet -romeo'); + $res = $tnt->searchBoolean('juliet ~romeo'); $this->assertEquals([10], $res['ids']); - $res = $tnt->searchBoolean('hamlet -king'); + $res = $tnt->searchBoolean('hamlet ~king'); $this->assertEquals([2], $res['ids']); $res = $tnt->searchBoolean('hamlet superman'); @@ -77,10 +77,10 @@ public function testSearchBoolean() $res = $tnt->searchBoolean('hamlet'); $this->assertEquals([1, 2], $res['ids']); - $res = $tnt->searchBoolean('eldred -bar'); + $res = $tnt->searchBoolean('eldred ~bar'); $this->assertEquals([11], $res['ids']); - $res = $tnt->searchBoolean('Eldred -bar'); + $res = $tnt->searchBoolean('Eldred ~bar'); $this->assertEquals([11], $res['ids']); } @@ -113,7 +113,7 @@ public function testTotalDocumentCountOnIndexUpdate() $this->assertEquals(12, $tnt->totalDocumentsInCollection()); } - public function testRemovePrimaryKeyFromIndex() + public function testPrimaryKeyIncludedInResult() { $tnt = new TNTSearch; @@ -129,6 +129,14 @@ public function testRemovePrimaryKeyFromIndex() $res = $tnt->search(3); $this->assertEquals([3], $res['ids']); + } + + public function testPrimaryKeyNotIncludedInResult() + { + $tnt = new TNTSearch; + + $tnt->loadConfig($this->config); + $indexer = $tnt->createIndex($this->indexName); $indexer->disableOutput = true; $indexer->query('SELECT id, title, article FROM articles;'); @@ -137,7 +145,6 @@ public function testRemovePrimaryKeyFromIndex() $tnt->selectIndex($this->indexName); $res = $tnt->search(3); $this->assertEquals([], $res['ids']); - } public function testIndexUpdate() diff --git a/vendor/teamtnt/tntsearch/tests/_files/cities-geo.index b/vendor/teamtnt/tntsearch/tests/_files/cities-geo.index index 32b09edc2bbf0c368b4b2591a9785599ed59b535..11b6c0728490a116af9813901c217e8e0e56cf93 100644 GIT binary patch delta 841 zcmWlXZAjBm6o)zgwwdp*n`^1FmXeT}|gI zdn&2Alb*4=ld?K!l>JJC1s(jiL70i5QO87^FpuzEyHG2EEf0hzQuy~HpmBf(_&y`4|2k9#RdLijsDRqBPVk(BG z!leomd3brJ^ouXz_odQjMLgy+ArCmz3B_j7iyCX z$SE7NtZdND$;s1uTQ@61>f2piQxZ}&!#b`R))%(mRzn9;Rgsj)Q)g0dsp%r0bf(tr z#RvWKFZHsSzKeEq8r#i=vQyM7j*&<}CXbO!I4&h&aQ`|^n_i-BUrJ7L)%2juddu)JV_jQl7fuele! UTHJZ32kDyVYP7JcaeH>&e}koPY5)KL delta 841 zcmWlXYe=H+5c?Elr*2Hk;GteT5*Hh+@zOjZ(2iSd8p$xulmaMp3Z} zaiWriQ7P&njcSHv%?gQq@PlY+NMH&Q&Gx1Ke)#cw59d7RInVn%7rSl?7s1VgLbh*f z-EbW>^wSG=^;3Qyx!J!`Skb|M+k}O9a@%Kngk^*udxcXH*!);{E`@(T69PkP};N4`2Mk+Q!qL;ztN{KxOUaFKx4^un;dMO#*X!U4ZVyuAY z!=(x%dDv4bb^9UyR3$z988)hAF&pbEQ)DL>k#`08>^w&9krtnoK!mGTeO!xFCXO}v z@>rAKyO-GBmgWxv*p?PJnvFQGK9KY3gD&Oc+u0KYg4x*(V zc=D?vGL}lj`Bepo1W_OwC_xO*uf|SPpzdK&oK*)at#S4ScyK0;THv95@v$m+x;g%> z1HP+Jbp*irt*YaCOxjzeI=b=0!XB!+m6&w+jS6f531BNwgKa$gCUI&C>ul{w>zi>m zXB|mdC?9kr@t|XSft@~xYgx&>mX%U)hWbSPKnm*zQZ-8YDb~1Bfre{bY122TmbLqL zggl|sTqsK~oIuM~SGqF@HqWH@l)_8u3=fe(UNF0?PQzDP<@VWi!*HC8P1x#h92E!Bgh6h+-=_VJ^*jRQof5V<)-RU+>+BT z_l^#It4+DSeK=z6_gt?1p6B&q&;7IcW&assertSame('abaiss', FrenchStemmer::stem('abaissant')); + $this->assertSame('abandon', FrenchStemmer::stem('abandonnés')); + $this->assertSame(FrenchStemmer::stem('frontières'), FrenchStemmer::stem('frontière')); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/stemmer/GermanStemmerTest.php b/vendor/teamtnt/tntsearch/tests/stemmer/GermanStemmerTest.php index cc8e0c9..ea7361f 100644 --- a/vendor/teamtnt/tntsearch/tests/stemmer/GermanStemmerTest.php +++ b/vendor/teamtnt/tntsearch/tests/stemmer/GermanStemmerTest.php @@ -2,7 +2,7 @@ use TeamTNT\TNTSearch\Stemmer\GermanStemmer; -class GermanStemmerTestTest extends PHPUnit\Framework\TestCase +class GermanStemmerTest extends PHPUnit\Framework\TestCase { public function testStem() diff --git a/vendor/teamtnt/tntsearch/tests/stemmer/PolishStemmerTest.php b/vendor/teamtnt/tntsearch/tests/stemmer/PolishStemmerTest.php new file mode 100644 index 0000000..976fe39 --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/stemmer/PolishStemmerTest.php @@ -0,0 +1,21 @@ +assertEquals("czujnik", $stemmer->stem("czujnikami")); + $this->assertEquals("kabel", $stemmer->stem("kabelek")); + $this->assertEquals("mocniej", $stemmer->stem("najmocniejszy")); + $this->assertEquals("przekaźnik", $stemmer->stem("przekaźnikowy")); + $this->assertEquals("instaluj", $stemmer->stem("instalujesz")); + $this->assertEquals("instaluj", $stemmer->stem("instalujesz")); + $this->assertEquals("ciekaw", $stemmer->stem("ciekawie")); + $this->assertEquals("przekaźnik", $stemmer->stem("przekaźników")); + $this->assertEquals("moduł", $stemmer->stem("modułu")); + $this->assertEquals($stemmer->stem("modułów"), $stemmer->stem("moduły")); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/stemmer/PorterStemmerTest.php b/vendor/teamtnt/tntsearch/tests/stemmer/PorterStemmerTest.php index bdd64d2..2510dd1 100644 --- a/vendor/teamtnt/tntsearch/tests/stemmer/PorterStemmerTest.php +++ b/vendor/teamtnt/tntsearch/tests/stemmer/PorterStemmerTest.php @@ -2,7 +2,7 @@ use TeamTNT\TNTSearch\Stemmer\PorterStemmer; -class PorterStemmerTestTest extends PHPUnit\Framework\TestCase +class PorterStemmerTest extends PHPUnit\Framework\TestCase { public function testStem() diff --git a/vendor/teamtnt/tntsearch/tests/stemmer/PortugueseStemmerTest.php b/vendor/teamtnt/tntsearch/tests/stemmer/PortugueseStemmerTest.php index 66bbd9f..44a4d59 100644 --- a/vendor/teamtnt/tntsearch/tests/stemmer/PortugueseStemmerTest.php +++ b/vendor/teamtnt/tntsearch/tests/stemmer/PortugueseStemmerTest.php @@ -2,7 +2,7 @@ use TeamTNT\TNTSearch\Stemmer\PortugueseStemmer; -class PortugueseStemmerTestTest extends PHPUnit\Framework\TestCase +class PortugueseStemmerTest extends PHPUnit\Framework\TestCase { public function testStem() diff --git a/vendor/teamtnt/tntsearch/tests/support/BigramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/BigramTokenizerTest.php new file mode 100644 index 0000000..fe8637a --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/BigramTokenizerTest.php @@ -0,0 +1,16 @@ +tokenize($text); + + $this->assertEquals(["qu", "ui", "ic", "ck", "fo", "ox", "xe", "es"], $res); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/support/EdgeNgramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/EdgeNgramTokenizerTest.php new file mode 100644 index 0000000..b4f0234 --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/EdgeNgramTokenizerTest.php @@ -0,0 +1,26 @@ +tokenize($text); + + $this->assertEquals(["qu", "qui", "quic", "quick", "fo", "fox", "foxe", "foxes"], $res); + } + + public function testEdgeNgramTokenize2() + { + $tokenizer = new EdgeNgramTokenizer; + + $text = "Germany"; + $res = $tokenizer->tokenize($text); + + $this->assertEquals(["ge", "ger", "germ", "germa", "german", "germany"], $res); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/support/ExpressionTest.php b/vendor/teamtnt/tntsearch/tests/support/ExpressionTest.php index dddccd3..9b26155 100644 --- a/vendor/teamtnt/tntsearch/tests/support/ExpressionTest.php +++ b/vendor/teamtnt/tntsearch/tests/support/ExpressionTest.php @@ -9,6 +9,7 @@ public function testToPostfix() $exp = new Expression; $this->assertEquals(['a', 'b', '&', 'c', '|'], $exp->toPostfix("a&b|c")); $this->assertEquals(['aw', 'bw', '&', 'cw', '|'], $exp->toPostfix("aw&bw|cw")); + $this->assertEquals(['aw', 'bw', '&', 'cw', '|'], $exp->toPostfix("aw&bw|cw)")); $this->assertEquals(['a', 'b', 'd', 'c', '&', '|', '&'], $exp->toPostfix("a&(b|d&c)")); $this->assertEquals(['a', 'b', '|'], $exp->toPostfix("a|b")); $this->assertEquals(['great', 'awsome', '|'], $exp->toPostfix("great|awsome")); @@ -16,5 +17,7 @@ public function testToPostfix() $this->assertEquals(['great', 'awsome', '&'], $exp->toPostfix("great awsome")); $this->assertEquals(['email', 'test', '&', 'com', '&'], $exp->toPostfix("email test com")); $this->assertEquals(['first', 'last', '&', 'something', 'else', '&', '|'], $exp->toPostfix("(first last) or (something else)")); + $this->assertEquals(['first', 'last', '|', 'something', 'else', '|', '&'], $exp->toPostfix("(first or last)&(something or else)")); + $this->assertEquals(['first', 'last', '|', 'something', '&', 'else', '|'], $exp->toPostfix("(first or last)&something or else)")); } } diff --git a/vendor/teamtnt/tntsearch/tests/support/FivegramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/FivegramTokenizerTest.php new file mode 100644 index 0000000..9b0aec5 --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/FivegramTokenizerTest.php @@ -0,0 +1,16 @@ +tokenize($text); + + $this->assertEquals(["quick", "foxes"], $res); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/support/FourgramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/FourgramTokenizerTest.php new file mode 100644 index 0000000..dbebe4b --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/FourgramTokenizerTest.php @@ -0,0 +1,16 @@ +tokenize($text); + + $this->assertEquals(["quic", "uick", "foxe", "oxes"], $res); + } +} diff --git a/vendor/teamtnt/tntsearch/tests/support/NGramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/NGramTokenizerTest.php new file mode 100644 index 0000000..8b75ccb --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/NGramTokenizerTest.php @@ -0,0 +1,37 @@ +tokenize($text); + + $this->assertEquals(["qui", "uic", "ick", "fox", "oxe", "xes"], $res); + } + + public function testNgram12Tokenize() + { + $tokenizer = new NGramTokenizer(1, 2); + + $text = "Quick Fox"; + $res = $tokenizer->tokenize($text); + + $this->assertEquals(["q", "u", "i", "c", "k", "qu", "ui", "ic", "ck", "f", "o", "x", "fo", "ox"], $res); + } + + public function testFourGramTokenize() + { + $tokenizer = new NGramTokenizer(4, 4); + + $text = "Quick Foxes"; + $res = $tokenizer->tokenize($text); + + $this->assertEquals(["quic", "uick", "foxe", "oxes"], $res); + } + +} diff --git a/vendor/teamtnt/tntsearch/tests/support/TrigramTokenizerTest.php b/vendor/teamtnt/tntsearch/tests/support/TrigramTokenizerTest.php new file mode 100644 index 0000000..da2e411 --- /dev/null +++ b/vendor/teamtnt/tntsearch/tests/support/TrigramTokenizerTest.php @@ -0,0 +1,16 @@ +tokenize($text); + + $this->assertEquals(["qui", "uic", "ick", "fox", "oxe", "xes"], $res); + } +} From 1a9d51481b0ffaccf5140c00e3908aebbaea38cd Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 6 Mar 2023 10:05:12 -0700 Subject: [PATCH 7/7] prepare for release --- CHANGELOG.md | 2 +- blueprints.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0d6b34..94bdf5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v3.4.0 -## mm/dd/2023 +## 03/06/2023 1. [](#improved) * Updated TNTSearch library to `2.9.0` diff --git a/blueprints.yaml b/blueprints.yaml index faa3772..e69c536 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: TNT Search type: plugin slug: tntsearch -version: 3.3.1 +version: 3.4.0 testing: false description: Powerful indexed-based full text search engine powered by TNTSearch icon: binoculars