From 20affdf5e8e0f77b434b4c11affe3c6e83965383 Mon Sep 17 00:00:00 2001 From: Szymon Kasprzyk Date: Wed, 22 May 2024 13:13:16 +0200 Subject: [PATCH] removes relevanssi plugin --- relevanssi-premium/build/index.asset.php | 1 - relevanssi-premium/build/index.js | 832 -- relevanssi-premium/build/index.js.map | 1 - relevanssi-premium/changelog.txt | 1611 ---- .../relevanssi-cs_CZ-relevanssi-sidebar.json | 1 - .../languages/relevanssi-cs_CZ.mo | Bin 86696 -> 0 bytes .../languages/relevanssi-cs_CZ.po | 3001 ------- .../relevanssi-de_DE-relevanssi-sidebar.json | 1 - .../languages/relevanssi-de_DE.mo | Bin 39004 -> 0 bytes .../languages/relevanssi-de_DE.po | 1010 --- .../relevanssi-es_ES-relevanssi-sidebar.json | 1 - .../relevanssi-fi-relevanssi-sidebar.json | 120 - relevanssi-premium/languages/relevanssi-fi.mo | Bin 136967 -> 0 bytes relevanssi-premium/languages/relevanssi-fi.po | 6886 ----------------- .../languages/relevanssi-fr_CA.mo | Bin 42546 -> 0 bytes .../languages/relevanssi-fr_CA.po | 1589 ---- .../relevanssi-fr_FR-relevanssi-sidebar.json | 1 - .../languages/relevanssi-fr_FR.mo | Bin 44977 -> 0 bytes .../languages/relevanssi-fr_FR.po | 1670 ---- .../relevanssi-it_IT-relevanssi-sidebar.json | 1 - .../languages/relevanssi-it_IT.mo | Bin 12935 -> 0 bytes .../languages/relevanssi-it_IT.po | 321 - .../relevanssi-ja-relevanssi-sidebar.json | 1 - .../relevanssi-nl_NL-relevanssi-sidebar.json | 1 - .../languages/relevanssi-pl_PL.mo | Bin 42153 -> 0 bytes .../languages/relevanssi-pl_PL.po | 1452 ---- .../relevanssi-pt_BR-relevanssi-sidebar.json | 1 - .../languages/relevanssi-pt_BR.mo | Bin 20931 -> 0 bytes .../languages/relevanssi-pt_BR.po | 578 -- .../languages/relevanssi-ru_RU.mo | Bin 36752 -> 0 bytes .../languages/relevanssi-ru_RU.po | 1371 ---- .../languages/relevanssi-sidebar-fi.mo | Bin 3523 -> 0 bytes .../languages/relevanssi-sidebar-fi.po | 148 - .../languages/relevanssi-sidebar.pot | 154 - .../relevanssi-sv_SE-relevanssi-sidebar.json | 1 - relevanssi-premium/lib/admin-ajax.php | 476 -- relevanssi-premium/lib/admin_scripts.js | 540 -- relevanssi-premium/lib/admin_scripts_free.js | 53 - relevanssi-premium/lib/admin_styles.css | 118 - .../lib/class-relevanssi-taxonomy-walker.php | 74 - relevanssi-premium/lib/common.php | 1937 ----- relevanssi-premium/lib/compatibility/acf.php | 284 - .../lib/compatibility/aioseo.php | 108 - .../lib/compatibility/avada.php | 19 - .../lib/compatibility/bricks.php | 97 - .../lib/compatibility/elementor.php | 28 - .../lib/compatibility/fibosearch.php | 27 - .../lib/compatibility/groups.php | 36 - .../lib/compatibility/gutenberg.php | 173 - .../lib/compatibility/jetsmartfilters.php | 47 - .../lib/compatibility/memberpress.php | 31 - .../lib/compatibility/members.php | 37 - .../lib/compatibility/ninjatables.php | 101 - .../lib/compatibility/oxygen.php | 259 - .../lib/compatibility/paidmembershippro.php | 38 - .../lib/compatibility/polylang.php | 205 - .../lib/compatibility/pretty-links.php | 30 - ...duct-gtin-ean-upc-isbn-for-woocommerce.php | 62 - .../lib/compatibility/rankmath.php | 100 - .../lib/compatibility/restrictcontentpro.php | 32 - .../lib/compatibility/seoframework.php | 96 - .../lib/compatibility/seopress.php | 102 - .../lib/compatibility/simplemembership.php | 30 - .../lib/compatibility/tablepress.php | 29 - .../lib/compatibility/useraccessmanager.php | 38 - .../lib/compatibility/woocommerce.php | 300 - .../lib/compatibility/wp-file-download.php | 58 - .../lib/compatibility/wp-members.php | 46 - .../lib/compatibility/wp-search-suggest.php | 25 - .../compatibility/wpjvpostreadinggroups.php | 28 - relevanssi-premium/lib/compatibility/wpml.php | 172 - .../lib/compatibility/yoast-seo.php | 102 - relevanssi-premium/lib/contextual-help.php | 224 - relevanssi-premium/lib/debug.php | 172 - relevanssi-premium/lib/didyoumean.php | 219 - .../lib/excerpts-highlights.php | 1694 ---- relevanssi-premium/lib/indexing.php | 1763 ----- relevanssi-premium/lib/init.php | 548 -- relevanssi-premium/lib/install.php | 149 - relevanssi-premium/lib/interface.php | 525 -- relevanssi-premium/lib/log.php | 431 -- relevanssi-premium/lib/options.php | 391 - relevanssi-premium/lib/phrases.php | 311 - relevanssi-premium/lib/privacy.php | 146 - .../lib/search-query-restrictions.php | 641 -- relevanssi-premium/lib/search-tax-query.php | 418 - relevanssi-premium/lib/search.php | 2001 ----- relevanssi-premium/lib/shortcodes.php | 217 - relevanssi-premium/lib/sorting.php | 449 -- relevanssi-premium/lib/stopwords.php | 424 - .../lib/tabs/attachments-tab.php | 24 - relevanssi-premium/lib/tabs/debugging-tab.php | 166 - relevanssi-premium/lib/tabs/excerpts-tab.php | 457 -- relevanssi-premium/lib/tabs/indexing-tab.php | 545 -- relevanssi-premium/lib/tabs/logging-tab.php | 128 - relevanssi-premium/lib/tabs/overview-tab.php | 131 - relevanssi-premium/lib/tabs/redirects-tab.php | 24 - relevanssi-premium/lib/tabs/search-page.php | 97 - relevanssi-premium/lib/tabs/searching-tab.php | 412 - relevanssi-premium/lib/tabs/stopwords-tab.php | 149 - relevanssi-premium/lib/tabs/synonyms-tab.php | 102 - relevanssi-premium/lib/uninstall.php | 155 - relevanssi-premium/lib/user-searches.php | 385 - relevanssi-premium/lib/utils.php | 1677 ---- relevanssi-premium/premium/admin-ajax.php | 780 -- .../premium/admin_metabox_scripts.js | 71 - .../premium/admin_pdf_scripts.js | 49 - .../premium/admin_scripts_premium.js | 540 -- relevanssi-premium/premium/body-stopwords.php | 388 - .../class-relevanssi-language-packs.php | 211 - .../class-relevanssi-spellcorrector.php | 221 - .../class-relevanssi-wp-auto-update.php | 222 - .../class-relevanssi-wp-cli-command.php | 714 -- relevanssi-premium/premium/click-tracking.php | 1035 --- relevanssi-premium/premium/common.php | 1268 --- .../premium/contextual-help.php | 103 - .../premium/excerpts-highlights.php | 217 - .../premium/gutenberg-sidebar.php | 412 - .../premium/gutenberg-sidebar/index.asset.php | 1 - .../premium/gutenberg-sidebar/index.js | 832 -- .../premium/gutenberg-sidebar/index.js.map | 1 - relevanssi-premium/premium/indexing.php | 1833 ----- relevanssi-premium/premium/interface.php | 1612 ---- relevanssi-premium/premium/metabox_styles.css | 11 - .../premium/network-options.php | 186 - relevanssi-premium/premium/pdf-upload.php | 920 --- relevanssi-premium/premium/pinning.php | 260 - relevanssi-premium/premium/post-metabox.php | 607 -- relevanssi-premium/premium/proximity.php | 189 - relevanssi-premium/premium/redirects.php | 216 - relevanssi-premium/premium/related.php | 763 -- relevanssi-premium/premium/search-multi.php | 511 -- relevanssi-premium/premium/search.php | 244 - relevanssi-premium/premium/spamblock.php | 139 - .../premium/tabs/attachments-tab.php | 197 - .../premium/tabs/import-export-tab.php | 168 - .../premium/tabs/redirects-tab.php | 157 - .../premium/tabs/related-tab.php | 516 -- .../premium/tabs/spamblock-tab.php | 132 - .../premium/tabs/support-tab.php | 121 - .../premium/templates/relevanssi-related.php | 122 - relevanssi-premium/premium/uninstall.php | 159 - relevanssi-premium/readme.txt | 437 -- relevanssi-premium/relevanssi.php | 189 - relevanssi-premium/relevanssi.po | 4490 ----------- relevanssi-premium/stopwords/stopwords.cs_CZ | 327 - relevanssi-premium/stopwords/stopwords.de_DE | 1037 --- relevanssi-premium/stopwords/stopwords.en_CA | 323 - relevanssi-premium/stopwords/stopwords.en_GB | 323 - relevanssi-premium/stopwords/stopwords.en_US | 323 - relevanssi-premium/stopwords/stopwords.es_ES | 386 - relevanssi-premium/stopwords/stopwords.fi | 365 - relevanssi-premium/stopwords/stopwords.fr_FR | 72 - relevanssi-premium/stopwords/stopwords.it_IT | 666 -- relevanssi-premium/stopwords/stopwords.pl_PL | 210 - relevanssi-premium/stopwords/stopwords.pt_BR | 173 - relevanssi-premium/stopwords/stopwords.pt_PT | 173 - relevanssi-premium/stopwords/stopwords.ru_RU | 427 - relevanssi-premium/stopwords/stopwords.zh_TW | 769 -- relevanssi-premium/uninstall.php | 32 - 160 files changed, 68717 deletions(-) delete mode 100644 relevanssi-premium/build/index.asset.php delete mode 100644 relevanssi-premium/build/index.js delete mode 100644 relevanssi-premium/build/index.js.map delete mode 100644 relevanssi-premium/changelog.txt delete mode 100644 relevanssi-premium/languages/relevanssi-cs_CZ-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-cs_CZ.mo delete mode 100644 relevanssi-premium/languages/relevanssi-cs_CZ.po delete mode 100644 relevanssi-premium/languages/relevanssi-de_DE-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-de_DE.mo delete mode 100644 relevanssi-premium/languages/relevanssi-de_DE.po delete mode 100644 relevanssi-premium/languages/relevanssi-es_ES-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-fi-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-fi.mo delete mode 100644 relevanssi-premium/languages/relevanssi-fi.po delete mode 100644 relevanssi-premium/languages/relevanssi-fr_CA.mo delete mode 100644 relevanssi-premium/languages/relevanssi-fr_CA.po delete mode 100644 relevanssi-premium/languages/relevanssi-fr_FR-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-fr_FR.mo delete mode 100644 relevanssi-premium/languages/relevanssi-fr_FR.po delete mode 100644 relevanssi-premium/languages/relevanssi-it_IT-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-it_IT.mo delete mode 100644 relevanssi-premium/languages/relevanssi-it_IT.po delete mode 100644 relevanssi-premium/languages/relevanssi-ja-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-nl_NL-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-pl_PL.mo delete mode 100644 relevanssi-premium/languages/relevanssi-pl_PL.po delete mode 100644 relevanssi-premium/languages/relevanssi-pt_BR-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/languages/relevanssi-pt_BR.mo delete mode 100644 relevanssi-premium/languages/relevanssi-pt_BR.po delete mode 100644 relevanssi-premium/languages/relevanssi-ru_RU.mo delete mode 100644 relevanssi-premium/languages/relevanssi-ru_RU.po delete mode 100644 relevanssi-premium/languages/relevanssi-sidebar-fi.mo delete mode 100644 relevanssi-premium/languages/relevanssi-sidebar-fi.po delete mode 100644 relevanssi-premium/languages/relevanssi-sidebar.pot delete mode 100644 relevanssi-premium/languages/relevanssi-sv_SE-relevanssi-sidebar.json delete mode 100644 relevanssi-premium/lib/admin-ajax.php delete mode 100644 relevanssi-premium/lib/admin_scripts.js delete mode 100644 relevanssi-premium/lib/admin_scripts_free.js delete mode 100644 relevanssi-premium/lib/admin_styles.css delete mode 100644 relevanssi-premium/lib/class-relevanssi-taxonomy-walker.php delete mode 100644 relevanssi-premium/lib/common.php delete mode 100644 relevanssi-premium/lib/compatibility/acf.php delete mode 100644 relevanssi-premium/lib/compatibility/aioseo.php delete mode 100644 relevanssi-premium/lib/compatibility/avada.php delete mode 100644 relevanssi-premium/lib/compatibility/bricks.php delete mode 100644 relevanssi-premium/lib/compatibility/elementor.php delete mode 100644 relevanssi-premium/lib/compatibility/fibosearch.php delete mode 100644 relevanssi-premium/lib/compatibility/groups.php delete mode 100644 relevanssi-premium/lib/compatibility/gutenberg.php delete mode 100644 relevanssi-premium/lib/compatibility/jetsmartfilters.php delete mode 100644 relevanssi-premium/lib/compatibility/memberpress.php delete mode 100644 relevanssi-premium/lib/compatibility/members.php delete mode 100644 relevanssi-premium/lib/compatibility/ninjatables.php delete mode 100644 relevanssi-premium/lib/compatibility/oxygen.php delete mode 100644 relevanssi-premium/lib/compatibility/paidmembershippro.php delete mode 100644 relevanssi-premium/lib/compatibility/polylang.php delete mode 100644 relevanssi-premium/lib/compatibility/pretty-links.php delete mode 100644 relevanssi-premium/lib/compatibility/product-gtin-ean-upc-isbn-for-woocommerce.php delete mode 100644 relevanssi-premium/lib/compatibility/rankmath.php delete mode 100644 relevanssi-premium/lib/compatibility/restrictcontentpro.php delete mode 100644 relevanssi-premium/lib/compatibility/seoframework.php delete mode 100644 relevanssi-premium/lib/compatibility/seopress.php delete mode 100644 relevanssi-premium/lib/compatibility/simplemembership.php delete mode 100644 relevanssi-premium/lib/compatibility/tablepress.php delete mode 100644 relevanssi-premium/lib/compatibility/useraccessmanager.php delete mode 100644 relevanssi-premium/lib/compatibility/woocommerce.php delete mode 100644 relevanssi-premium/lib/compatibility/wp-file-download.php delete mode 100644 relevanssi-premium/lib/compatibility/wp-members.php delete mode 100644 relevanssi-premium/lib/compatibility/wp-search-suggest.php delete mode 100644 relevanssi-premium/lib/compatibility/wpjvpostreadinggroups.php delete mode 100644 relevanssi-premium/lib/compatibility/wpml.php delete mode 100644 relevanssi-premium/lib/compatibility/yoast-seo.php delete mode 100644 relevanssi-premium/lib/contextual-help.php delete mode 100644 relevanssi-premium/lib/debug.php delete mode 100644 relevanssi-premium/lib/didyoumean.php delete mode 100644 relevanssi-premium/lib/excerpts-highlights.php delete mode 100644 relevanssi-premium/lib/indexing.php delete mode 100644 relevanssi-premium/lib/init.php delete mode 100644 relevanssi-premium/lib/install.php delete mode 100644 relevanssi-premium/lib/interface.php delete mode 100644 relevanssi-premium/lib/log.php delete mode 100644 relevanssi-premium/lib/options.php delete mode 100644 relevanssi-premium/lib/phrases.php delete mode 100644 relevanssi-premium/lib/privacy.php delete mode 100644 relevanssi-premium/lib/search-query-restrictions.php delete mode 100644 relevanssi-premium/lib/search-tax-query.php delete mode 100644 relevanssi-premium/lib/search.php delete mode 100644 relevanssi-premium/lib/shortcodes.php delete mode 100644 relevanssi-premium/lib/sorting.php delete mode 100644 relevanssi-premium/lib/stopwords.php delete mode 100644 relevanssi-premium/lib/tabs/attachments-tab.php delete mode 100644 relevanssi-premium/lib/tabs/debugging-tab.php delete mode 100644 relevanssi-premium/lib/tabs/excerpts-tab.php delete mode 100644 relevanssi-premium/lib/tabs/indexing-tab.php delete mode 100644 relevanssi-premium/lib/tabs/logging-tab.php delete mode 100644 relevanssi-premium/lib/tabs/overview-tab.php delete mode 100644 relevanssi-premium/lib/tabs/redirects-tab.php delete mode 100644 relevanssi-premium/lib/tabs/search-page.php delete mode 100644 relevanssi-premium/lib/tabs/searching-tab.php delete mode 100644 relevanssi-premium/lib/tabs/stopwords-tab.php delete mode 100644 relevanssi-premium/lib/tabs/synonyms-tab.php delete mode 100644 relevanssi-premium/lib/uninstall.php delete mode 100644 relevanssi-premium/lib/user-searches.php delete mode 100644 relevanssi-premium/lib/utils.php delete mode 100644 relevanssi-premium/premium/admin-ajax.php delete mode 100644 relevanssi-premium/premium/admin_metabox_scripts.js delete mode 100644 relevanssi-premium/premium/admin_pdf_scripts.js delete mode 100644 relevanssi-premium/premium/admin_scripts_premium.js delete mode 100644 relevanssi-premium/premium/body-stopwords.php delete mode 100644 relevanssi-premium/premium/class-relevanssi-language-packs.php delete mode 100644 relevanssi-premium/premium/class-relevanssi-spellcorrector.php delete mode 100644 relevanssi-premium/premium/class-relevanssi-wp-auto-update.php delete mode 100644 relevanssi-premium/premium/class-relevanssi-wp-cli-command.php delete mode 100644 relevanssi-premium/premium/click-tracking.php delete mode 100644 relevanssi-premium/premium/common.php delete mode 100644 relevanssi-premium/premium/contextual-help.php delete mode 100644 relevanssi-premium/premium/excerpts-highlights.php delete mode 100644 relevanssi-premium/premium/gutenberg-sidebar.php delete mode 100644 relevanssi-premium/premium/gutenberg-sidebar/index.asset.php delete mode 100644 relevanssi-premium/premium/gutenberg-sidebar/index.js delete mode 100644 relevanssi-premium/premium/gutenberg-sidebar/index.js.map delete mode 100644 relevanssi-premium/premium/indexing.php delete mode 100644 relevanssi-premium/premium/interface.php delete mode 100644 relevanssi-premium/premium/metabox_styles.css delete mode 100644 relevanssi-premium/premium/network-options.php delete mode 100644 relevanssi-premium/premium/pdf-upload.php delete mode 100644 relevanssi-premium/premium/pinning.php delete mode 100644 relevanssi-premium/premium/post-metabox.php delete mode 100644 relevanssi-premium/premium/proximity.php delete mode 100644 relevanssi-premium/premium/redirects.php delete mode 100644 relevanssi-premium/premium/related.php delete mode 100644 relevanssi-premium/premium/search-multi.php delete mode 100644 relevanssi-premium/premium/search.php delete mode 100644 relevanssi-premium/premium/spamblock.php delete mode 100644 relevanssi-premium/premium/tabs/attachments-tab.php delete mode 100644 relevanssi-premium/premium/tabs/import-export-tab.php delete mode 100644 relevanssi-premium/premium/tabs/redirects-tab.php delete mode 100644 relevanssi-premium/premium/tabs/related-tab.php delete mode 100644 relevanssi-premium/premium/tabs/spamblock-tab.php delete mode 100644 relevanssi-premium/premium/tabs/support-tab.php delete mode 100644 relevanssi-premium/premium/templates/relevanssi-related.php delete mode 100644 relevanssi-premium/premium/uninstall.php delete mode 100644 relevanssi-premium/readme.txt delete mode 100644 relevanssi-premium/relevanssi.php delete mode 100644 relevanssi-premium/relevanssi.po delete mode 100644 relevanssi-premium/stopwords/stopwords.cs_CZ delete mode 100644 relevanssi-premium/stopwords/stopwords.de_DE delete mode 100644 relevanssi-premium/stopwords/stopwords.en_CA delete mode 100644 relevanssi-premium/stopwords/stopwords.en_GB delete mode 100644 relevanssi-premium/stopwords/stopwords.en_US delete mode 100644 relevanssi-premium/stopwords/stopwords.es_ES delete mode 100644 relevanssi-premium/stopwords/stopwords.fi delete mode 100644 relevanssi-premium/stopwords/stopwords.fr_FR delete mode 100644 relevanssi-premium/stopwords/stopwords.it_IT delete mode 100644 relevanssi-premium/stopwords/stopwords.pl_PL delete mode 100644 relevanssi-premium/stopwords/stopwords.pt_BR delete mode 100644 relevanssi-premium/stopwords/stopwords.pt_PT delete mode 100644 relevanssi-premium/stopwords/stopwords.ru_RU delete mode 100644 relevanssi-premium/stopwords/stopwords.zh_TW delete mode 100644 relevanssi-premium/uninstall.php diff --git a/relevanssi-premium/build/index.asset.php b/relevanssi-premium/build/index.asset.php deleted file mode 100644 index e02dc370..00000000 --- a/relevanssi-premium/build/index.asset.php +++ /dev/null @@ -1 +0,0 @@ - array('wp-components', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-polyfill'), 'version' => 'b81b50e9375d8f85569a43863b885812'); \ No newline at end of file diff --git a/relevanssi-premium/build/index.js b/relevanssi-premium/build/index.js deleted file mode 100644 index b929afaa..00000000 --- a/relevanssi-premium/build/index.js +++ /dev/null @@ -1,832 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./node_modules/@babel/runtime/helpers/arrayLikeToArray.js": -/*!*****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/arrayLikeToArray.js ***! - \*****************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - - for (var i = 0, arr2 = new Array(len); i < len; i++) { - arr2[i] = arr[i]; - } - - return arr2; -} - -module.exports = _arrayLikeToArray; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/arrayWithHoles.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; -} - -module.exports = _arrayWithHoles; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js": -/*!**********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/assertThisInitialized.js ***! - \**********************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return self; -} - -module.exports = _assertThisInitialized; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/classCallCheck.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/classCallCheck.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -} - -module.exports = _classCallCheck; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/createClass.js": -/*!************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/createClass.js ***! - \************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } -} - -function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; -} - -module.exports = _createClass; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/defineProperty.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/defineProperty.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - -module.exports = _defineProperty; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/getPrototypeOf.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _getPrototypeOf(o) { - module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { - return o.__proto__ || Object.getPrototypeOf(o); - }; - return _getPrototypeOf(o); -} - -module.exports = _getPrototypeOf; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/inherits.js": -/*!*********************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/inherits.js ***! - \*********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var setPrototypeOf = __webpack_require__(/*! ./setPrototypeOf */ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js"); - -function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function"); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - writable: true, - configurable: true - } - }); - if (superClass) setPrototypeOf(subClass, superClass); -} - -module.exports = _inherits; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js": -/*!*********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js ***! - \*********************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _iterableToArrayLimit(arr, i) { - if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; -} - -module.exports = _iterableToArrayLimit; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/nonIterableRest.js": -/*!****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/nonIterableRest.js ***! - \****************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - -module.exports = _nonIterableRest; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js": -/*!**************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js ***! - \**************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var _typeof = __webpack_require__(/*! @babel/runtime/helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js"); - -var assertThisInitialized = __webpack_require__(/*! ./assertThisInitialized */ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js"); - -function _possibleConstructorReturn(self, call) { - if (call && (_typeof(call) === "object" || typeof call === "function")) { - return call; - } - - return assertThisInitialized(self); -} - -module.exports = _possibleConstructorReturn; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/setPrototypeOf.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _setPrototypeOf(o, p) { - module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - - return _setPrototypeOf(o, p); -} - -module.exports = _setPrototypeOf; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/slicedToArray.js": -/*!**************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/slicedToArray.js ***! - \**************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var arrayWithHoles = __webpack_require__(/*! ./arrayWithHoles */ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js"); - -var iterableToArrayLimit = __webpack_require__(/*! ./iterableToArrayLimit */ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js"); - -var unsupportedIterableToArray = __webpack_require__(/*! ./unsupportedIterableToArray */ "./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js"); - -var nonIterableRest = __webpack_require__(/*! ./nonIterableRest */ "./node_modules/@babel/runtime/helpers/nonIterableRest.js"); - -function _slicedToArray(arr, i) { - return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest(); -} - -module.exports = _slicedToArray; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/typeof.js": -/*!*******************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/typeof.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _typeof(obj) { - "@babel/helpers - typeof"; - - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - module.exports = _typeof = function _typeof(obj) { - return typeof obj; - }; - } else { - module.exports = _typeof = function _typeof(obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); -} - -module.exports = _typeof; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js": -/*!***************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js ***! - \***************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var arrayLikeToArray = __webpack_require__(/*! ./arrayLikeToArray */ "./node_modules/@babel/runtime/helpers/arrayLikeToArray.js"); - -function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen); -} - -module.exports = _unsupportedIterableToArray; - -/***/ }), - -/***/ "./src/index.js": -/*!**********************!*\ - !*** ./src/index.js ***! - \**********************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"); -/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"); -/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"); -/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @babel/runtime/helpers/inherits */ "./node_modules/@babel/runtime/helpers/inherits.js"); -/* harmony import */ var _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @babel/runtime/helpers/possibleConstructorReturn */ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js"); -/* harmony import */ var _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @babel/runtime/helpers/getPrototypeOf */ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js"); -/* harmony import */ var _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__); -/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"); -/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6__); -/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); -/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__); -/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); -/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__); -/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @wordpress/plugins */ "@wordpress/plugins"); -/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__); -/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @wordpress/edit-post */ "@wordpress/edit-post"); -/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__); -/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n"); -/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__); -/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @wordpress/data */ "@wordpress/data"); -/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__); -/* harmony import */ var _wordpress_compose__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @wordpress/compose */ "@wordpress/compose"); -/* harmony import */ var _wordpress_compose__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_wordpress_compose__WEBPACK_IMPORTED_MODULE_13__); - - - - - - - - - -function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default()(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default()(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4___default()(this, result); }; } - -function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } - - - - - - - - -var relevanssiIcon = wp.element.createElement("svg", { - width: 20, - height: 20 -}, wp.element.createElement("path", { - d: "M5.644 20.665 C6.207 20.545 6.612 20.029 6.574 19.438 6.469 17.784 6.492 16.554 6.617 15.602 L7.388 19.228 C7.454 19.538 7.576 19.815 7.737 20.058 7.742 20.12 7.749 20.181 7.763 20.243 L8.444 23.384 C10.112 23.233 11.311 22.775 11.214 23.077 L10.82 21.227 C10.875 21.218 10.929 21.211 10.984 21.199 10.995 21.197 11.004 21.193 11.015 21.191 L11.35 22.766 C11.571 22.305 13.613 22.092 14.187 21.891 L13.42 19.11 C13.529 18.742 13.553 18.346 13.466 17.936 L12.445 13.134 C12.535 13.088 12.62 13.03 12.698 12.959 12.737 12.929 12.786 12.899 12.84 12.864 13.25 12.596 14.097 12.042 14.433 10.839 L20.429 12.98 C20.642 13.056 20.862 13.067 21.069 13.023 21.456 12.941 21.792 12.667 21.934 12.267 22.154 11.655 21.835 10.981 21.222 10.763 L14.393 8.324 C14.385 8.291 14.379 8.26 14.37 8.226 14.212 7.595 13.573 7.212 12.94 7.372 12.887 7.385 12.838 7.402 12.789 7.422 12.873 6.845 12.859 6.245 12.731 5.643 12.145 2.884 9.422 1.118 6.661 1.705 3.901 2.292 2.132 5.012 2.718 7.771 3.304 10.529 6.027 12.295 8.788 11.708 10.041 11.442 11.088 10.735 11.805 9.786 11.917 9.894 12.05 9.981 12.203 10.04 12.148 10.37 11.997 10.56 11.811 10.71 10.72 11.467 10.238 11.826 9.318 12.07 L8.678 12.167 C7.581 12.344 6.407 12.307 5.457 11.871 4.141 13.689 3.972 15.683 4.221 19.589 4.263 20.238 4.823 20.73 5.473 20.688 5.531 20.685 5.589 20.677 5.644 20.665 Z M8.568 10.67 C6.38 11.135 4.222 9.735 3.758 7.55 3.293 5.364 4.695 3.208 6.883 2.743 9.07 2.278 11.229 3.677 11.693 5.863 12.158 8.049 10.755 10.205 8.568 10.67 Z" -}), wp.element.createElement("path", { - d: "M8.009 5.745 C7.25 5.906 6.576 5.754 6.502 5.406 6.496 5.377 6.496 5.348 6.498 5.318 6.012 5.752 5.765 6.429 5.911 7.115 6.127 8.132 7.122 8.783 8.132 8.568 9.142 8.353 9.786 7.354 9.57 6.338 9.483 5.928 9.269 5.58 8.98 5.323 8.755 5.503 8.411 5.66 8.009 5.745 Z" -})); -var Fragment = wp.element.Fragment; -Object(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__["registerPlugin"])("relevanssi-premium", { - render: function render() { - var _useState = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState2 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState, 2), - relevanssiSees = _useState2[0], - setRelevanssiSees = _useState2[1]; - - var _useState3 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState4 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState3, 2), - relevanssiRelated = _useState4[0], - setRelevanssiRelated = _useState4[1]; - - var _useState5 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState6 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState5, 2), - relevanssiExcluded = _useState6[0], - setRelevanssiExcluded = _useState6[1]; - - var _useState7 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState8 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState7, 2), - relevanssiExcludedIds = _useState8[0], - setRelevanssiExcludedIds = _useState8[1]; - - var _useState9 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState10 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState9, 2), - relevanssiCommonTerms = _useState10[0], - setRelevanssiCommonTerms = _useState10[1]; - - var _useState11 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState12 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState11, 2), - relevanssiLowRankingTerms = _useState12[0], - setRelevanssiLowRankingTerms = _useState12[1]; - - var regenerateRelatedPosts = function regenerateRelatedPosts(postId, metaKey, metaValue) { - if (!metaValue) metaValue = "0"; - wp.apiFetch({ - path: "/relevanssi/v1/regeneraterelatedposts/".concat(postId, "/").concat(metaKey, "/").concat(metaValue) - }).then(function (data) { - setRelevanssiRelated(createRelatedList(data)); - }); - }; - - var RelatedPostControl = Object(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["withFocusOutside"])( /*#__PURE__*/function (_React$Component) { - _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3___default()(_class, _React$Component); - - var _super = _createSuper(_class); - - function _class() { - _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default()(this, _class); - - return _super.apply(this, arguments); - } - - _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default()(_class, [{ - key: "handleFocusOutside", - value: function handleFocusOutside() { - regenerateRelatedPosts(wp.data.select("core/editor").getCurrentPostId(), this.props.metaKey, wp.data.select("core/editor").getEditedPostAttribute("meta")[this.props.metaKey]); - } - }, { - key: "render", - value: function render() { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: this.props.control, - title: this.props.title, - metaKey: this.props.metaKey - }); - } - }]); - - return _class; - }(React.Component)); - var MetaControl = Object(_wordpress_compose__WEBPACK_IMPORTED_MODULE_13__["compose"])(Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["withDispatch"])(function (dispatch, props) { - return { - setMetaValue: function setMetaValue(metaValue) { - dispatch("core/editor").editPost({ - meta: _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default()({}, props.metaKey, metaValue) - }); - } - }; - }), Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["withSelect"])(function (select, props) { - var metaValue = select("core/editor").getEditedPostAttribute("meta")[props.metaKey]; - if (metaValue === "0") metaValue = ""; - return { - metaValue: metaValue - }; - }))(function (props) { - var args = { - label: props.title, - value: props.metaValue, - onChange: function onChange(content) { - props.setMetaValue(content); - } - }; - - if (props.control == _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"]) { - var checked = props.metaValue == "on" ? true : false; - args.value = ""; - args.checked = checked; - - args.onChange = function (content) { - content = content ? "on" : "off"; - props.setMetaValue(content); - }; - } - - return wp.element.createElement(props.control, args); - }); - - var excludeRelatedPost = function excludeRelatedPost(excludedPostId, postId) { - wp.apiFetch({ - path: "/relevanssi/v1/excluderelatedpost/".concat(excludedPostId, "/").concat(postId) - }).then(function (data) { - setRelevanssiExcludedIds(data); - }); - }; - - var unExcludeRelatedPost = function unExcludeRelatedPost(excludedPostId, postId) { - wp.apiFetch({ - path: "/relevanssi/v1/unexcluderelatedpost/".concat(excludedPostId, "/").concat(postId) - }).then(function (data) { - setRelevanssiExcludedIds(data); - }); - }; - - var postId = Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["select"])("core/editor").getCurrentPostId(); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/sees/".concat(postId) - }).then(function (data) { - setRelevanssiSees(data); - }); - }, [postId]); - /* - */ - - var createRelatedList = function createRelatedList(data) { - return data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("a", { - href: row.link - }, row.title), " ", Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Button"], { - onClick: function onClick() { - return excludeRelatedPost(row.id, postId); - } - }, "(", Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("not this", "relevanssi"), ")")); - }); - }; - - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listrelated/".concat(postId) - }).then(function (data) { - setRelevanssiRelated(createRelatedList(data)); - }); - }, [postId, relevanssiExcludedIds]); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listexcluded/".concat(postId) - }).then(function (data) { - var list = data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("a", { - href: row.link - }, row.title), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Button"], { - onClick: function onClick() { - return unExcludeRelatedPost(row.id, postId); - } - }, "(", Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("use this", "relevanssi"), ")")); - }); - setRelevanssiExcluded(list); - }); - }, [postId, relevanssiExcludedIds]); - - var createTermsList = function createTermsList(data) { - return data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, row.query, " (", row.count, ")"); - }); - }; - - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listinsightscommon/".concat(postId) - }).then(function (data) { - setRelevanssiCommonTerms(createTermsList(data)); - }); - }, [postId]); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listinsightslowranking/".concat(postId) - }).then(function (data) { - setRelevanssiLowRankingTerms(createTermsList(data)); - }); - }, [postId]); - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(Fragment, null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__["PluginSidebarMoreMenuItem"], { - target: "relevanssi-premium", - icon: relevanssiIcon - }, "Relevanssi Premium"), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__["PluginSidebar"], { - name: "relevanssi-premium", - icon: relevanssiIcon, - title: "Relevanssi Premium" - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("How Relevanssi sees this post", "relevanssi") - }, relevanssiSees.title && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Title:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.title), relevanssiSees.content && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Content:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.content), relevanssiSees.author && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Author:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.author), relevanssiSees.category && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Categories:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.category), relevanssiSees.tag && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Tags:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.tag), relevanssiSees.taxonomy && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Other taxonomies:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.taxonomy), relevanssiSees.comment && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Comments:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.comment), relevanssiSees.customfield && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Custom fields:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.customfield), relevanssiSees.excerpt && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Excerpt:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.excerpt), relevanssiSees.link && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Links to this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.link), relevanssiSees.mysql && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("MySQL columns:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.mysql), relevanssiSees.reason && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Reason this post is not indexed:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.reason))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Pinning", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Pin this post for all searches it appears in.", "relevanssi"), - metaKey: "_relevanssi_pin_for_all" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of single word keywords or multi-word phrases.", "relevanssi"), - metaKey: "_relevanssi_pin_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("If any of these keywords are present in the search query, this post will be moved on top of the search results.", "relevanssi"))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("You can add weights to pinned keywords like this: 'keyword (100)'. The post with the highest weight will be sorted first if there are multiple posts pinned to the same keyword.", "relevanssi")))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Exclusion", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Exclude this post or page from the index.", "relevanssi"), - metaKey: "_relevanssi_hide_post" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Ignore post content in the indexing.", "relevanssi"), - metaKey: "_relevanssi_hide_content" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of single word keywords or multi-word phrases.", "relevanssi"), - metaKey: "_relevanssi_unpin_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("If any of these keywords are present in the search query, this post will be removed from the search results.", "relevanssi"))))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Related posts", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Don't append the related posts to this page.", "relevanssi"), - metaKey: "_relevanssi_related_no_append" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Don't show this as a related post for any post.", "relevanssi"), - metaKey: "_relevanssi_related_not_related" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(RelatedPostControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of keywords to use for the Related Posts feature.", "relevanssi"), - metaKey: "_relevanssi_related_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Anything entered here will used when searching for related posts. Using phrases with quotes is allowed, but will restrict the related posts to posts including that phrase.", "relevanssi"))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(RelatedPostControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of post IDs to use as related posts for this post", "relevanssi"), - metaKey: "_relevanssi_related_include_ids" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Related posts for this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiRelated), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Excluded posts for this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiExcluded))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Insights", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("The most common search terms used to find this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiCommonTerms), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Low-ranking search terms used to find this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiLowRankingTerms))))); - } -}); - -/***/ }), - -/***/ "@wordpress/components": -/*!************************************!*\ - !*** external ["wp","components"] ***! - \************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["components"]; }()); - -/***/ }), - -/***/ "@wordpress/compose": -/*!*********************************!*\ - !*** external ["wp","compose"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["compose"]; }()); - -/***/ }), - -/***/ "@wordpress/data": -/*!******************************!*\ - !*** external ["wp","data"] ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["data"]; }()); - -/***/ }), - -/***/ "@wordpress/edit-post": -/*!**********************************!*\ - !*** external ["wp","editPost"] ***! - \**********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["editPost"]; }()); - -/***/ }), - -/***/ "@wordpress/element": -/*!*********************************!*\ - !*** external ["wp","element"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["element"]; }()); - -/***/ }), - -/***/ "@wordpress/i18n": -/*!******************************!*\ - !*** external ["wp","i18n"] ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["i18n"]; }()); - -/***/ }), - -/***/ "@wordpress/plugins": -/*!*********************************!*\ - !*** external ["wp","plugins"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["plugins"]; }()); - -/***/ }) - -/******/ }); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/relevanssi-premium/build/index.js.map b/relevanssi-premium/build/index.js.map deleted file mode 100644 index 98a1e00d..00000000 --- a/relevanssi-premium/build/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/@babel/runtime/helpers/arrayLikeToArray.js","webpack:///./node_modules/@babel/runtime/helpers/arrayWithHoles.js","webpack:///./node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack:///./node_modules/@babel/runtime/helpers/classCallCheck.js","webpack:///./node_modules/@babel/runtime/helpers/createClass.js","webpack:///./node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///./node_modules/@babel/runtime/helpers/getPrototypeOf.js","webpack:///./node_modules/@babel/runtime/helpers/inherits.js","webpack:///./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js","webpack:///./node_modules/@babel/runtime/helpers/nonIterableRest.js","webpack:///./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js","webpack:///./node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack:///./node_modules/@babel/runtime/helpers/slicedToArray.js","webpack:///./node_modules/@babel/runtime/helpers/typeof.js","webpack:///./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js","webpack:///./src/index.js","webpack:///external [\"wp\",\"components\"]","webpack:///external [\"wp\",\"compose\"]","webpack:///external [\"wp\",\"data\"]","webpack:///external [\"wp\",\"editPost\"]","webpack:///external [\"wp\",\"element\"]","webpack:///external [\"wp\",\"i18n\"]","webpack:///external [\"wp\",\"plugins\"]"],"names":["relevanssiIcon","wp","element","createElement","width","height","d","Fragment","registerPlugin","render","useState","relevanssiSees","setRelevanssiSees","relevanssiRelated","setRelevanssiRelated","relevanssiExcluded","setRelevanssiExcluded","relevanssiExcludedIds","setRelevanssiExcludedIds","relevanssiCommonTerms","setRelevanssiCommonTerms","relevanssiLowRankingTerms","setRelevanssiLowRankingTerms","regenerateRelatedPosts","postId","metaKey","metaValue","apiFetch","path","then","data","createRelatedList","RelatedPostControl","withFocusOutside","select","getCurrentPostId","props","getEditedPostAttribute","control","title","React","Component","MetaControl","compose","withDispatch","dispatch","setMetaValue","editPost","meta","withSelect","args","label","value","onChange","content","CheckboxControl","checked","excludeRelatedPost","excludedPostId","unExcludeRelatedPost","useEffect","map","row","id","link","__","list","createTermsList","query","count","author","category","tag","taxonomy","comment","customfield","excerpt","mysql","reason","TextareaControl","TextControl"],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA;AACA;;AAEA,wCAAwC,SAAS;AACjD;AACA;;AAEA;AACA;;AAEA,mC;;;;;;;;;;;ACVA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACJA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wC;;;;;;;;;;;ACRA;AACA;AACA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACNA;AACA,iBAAiB,kBAAkB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,8B;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;;AAEA;AACA;;AAEA,iC;;;;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACPA,qBAAqB,mBAAO,CAAC,iFAAkB;;AAE/C;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA,2B;;;;;;;;;;;ACjBA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6CAA6C,+BAA+B;AAC5E;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA,uC;;;;;;;;;;;AC3BA;AACA;AACA;;AAEA,kC;;;;;;;;;;;ACJA,cAAc,mBAAO,CAAC,sFAA+B;;AAErD,4BAA4B,mBAAO,CAAC,+FAAyB;;AAE7D;AACA;AACA;AACA;;AAEA;AACA;;AAEA,4C;;;;;;;;;;;ACZA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,iC;;;;;;;;;;;ACTA,qBAAqB,mBAAO,CAAC,iFAAkB;;AAE/C,2BAA2B,mBAAO,CAAC,6FAAwB;;AAE3D,iCAAiC,mBAAO,CAAC,yGAA8B;;AAEvE,sBAAsB,mBAAO,CAAC,mFAAmB;;AAEjD;AACA;AACA;;AAEA,gC;;;;;;;;;;;ACZA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA,yB;;;;;;;;;;;AChBA,uBAAuB,mBAAO,CAAC,qFAAoB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,6C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACXA;AAUA;AACA;AACA;AACA;AACA;AACA;AAEA,IAAMA,cAAc,GAAGC,EAAE,CAACC,OAAH,CAAWC,aAAX,CACtB,KADsB,EAEtB;AACCC,OAAK,EAAE,EADR;AAECC,QAAM,EAAE;AAFT,CAFsB,EAMtBJ,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyB,MAAzB,EAAiC;AAChCG,GAAC,EAAE;AAD6B,CAAjC,CANsB,EAStBL,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyB,MAAzB,EAAiC;AAChCG,GAAC,EAAE;AAD6B,CAAjC,CATsB,CAAvB;AAcA,IAAQC,QAAR,GAAqBN,EAAE,CAACC,OAAxB,CAAQK,QAAR;AAEAC,yEAAc,CAAC,oBAAD,EAAuB;AACpCC,QAAM,EAAE,kBAAY;AACnB,oBAA4CC,mEAAQ,CAAC,EAAD,CAApD;AAAA;AAAA,QAAOC,cAAP;AAAA,QAAuBC,iBAAvB;;AACA,qBAAkDF,mEAAQ,CAAC,EAAD,CAA1D;AAAA;AAAA,QAAOG,iBAAP;AAAA,QAA0BC,oBAA1B;;AACA,qBAAoDJ,mEAAQ,CAAC,EAAD,CAA5D;AAAA;AAAA,QAAOK,kBAAP;AAAA,QAA2BC,qBAA3B;;AACA,qBAA0DN,mEAAQ,CAAC,EAAD,CAAlE;AAAA;AAAA,QAAOO,qBAAP;AAAA,QAA8BC,wBAA9B;;AACA,qBAA0DR,mEAAQ,CAAC,EAAD,CAAlE;AAAA;AAAA,QAAOS,qBAAP;AAAA,QAA8BC,wBAA9B;;AACA,sBAAkEV,mEAAQ,CACzE,EADyE,CAA1E;AAAA;AAAA,QAAOW,yBAAP;AAAA,QAAkCC,4BAAlC;;AAIA,QAAMC,sBAAsB,GAAG,SAAzBA,sBAAyB,CAACC,MAAD,EAASC,OAAT,EAAkBC,SAAlB,EAAgC;AAC9D,UAAI,CAACA,SAAL,EAAgBA,SAAS,GAAG,GAAZ;AAChBzB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,kDAA2CJ,MAA3C,cAAqDC,OAArD,cAAgEC,SAAhE;AADO,OAAZ,EAEGG,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBhB,4BAAoB,CAACiB,iBAAiB,CAACD,IAAD,CAAlB,CAApB;AACA,OAJD;AAKA,KAPD;;AASA,QAAME,kBAAkB,GAAGC,8EAAgB;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,eAEzC,8BAAqB;AACpBV,gCAAsB,CACrBtB,EAAE,CAAC6B,IAAH,CAAQI,MAAR,CAAe,aAAf,EAA8BC,gBAA9B,EADqB,EAErB,KAAKC,KAAL,CAAWX,OAFU,EAGrBxB,EAAE,CAAC6B,IAAH,CAAQI,MAAR,CAAe,aAAf,EAA8BG,sBAA9B,CAAqD,MAArD,EACC,KAAKD,KAAL,CAAWX,OADZ,CAHqB,CAAtB;AAOA;AAVwC;AAAA;AAAA,eAYzC,kBAAS;AACR,iBACC,yEAAC,WAAD;AACC,mBAAO,EAAE,KAAKW,KAAL,CAAWE,OADrB;AAEC,iBAAK,EAAE,KAAKF,KAAL,CAAWG,KAFnB;AAGC,mBAAO,EAAE,KAAKH,KAAL,CAAWX;AAHrB,YADD;AAOA;AApBwC;;AAAA;AAAA,MAC5Be,KAAK,CAACC,SADsB,EAA3C;AAwBA,QAAMC,WAAW,GAAGC,mEAAO,CAC1BC,qEAAY,CAAC,UAACC,QAAD,EAAWT,KAAX,EAAqB;AACjC,aAAO;AACNU,oBAAY,EAAE,sBAAUpB,SAAV,EAAqB;AAClCmB,kBAAQ,CAAC,aAAD,CAAR,CAAwBE,QAAxB,CAAiC;AAChCC,gBAAI,EAAE,iFAAGZ,KAAK,CAACX,OAAX,EAAqBC,SAArB;AAD4B,WAAjC;AAGA;AALK,OAAP;AAOA,KARW,CADc,EAU1BuB,mEAAU,CAAC,UAACf,MAAD,EAASE,KAAT,EAAmB;AAC7B,UAAIV,SAAS,GACZQ,MAAM,CAAC,aAAD,CAAN,CAAsBG,sBAAtB,CAA6C,MAA7C,EAAqDD,KAAK,CAACX,OAA3D,CADD;AAEA,UAAIC,SAAS,KAAK,GAAlB,EAAuBA,SAAS,GAAG,EAAZ;AACvB,aAAO;AACNA,iBAAS,EAATA;AADM,OAAP;AAGA,KAPS,CAVgB,CAAP,CAkBlB,UAACU,KAAD,EAAW;AACZ,UAAIc,IAAI,GAAG;AACVC,aAAK,EAAEf,KAAK,CAACG,KADH;AAEVa,aAAK,EAAEhB,KAAK,CAACV,SAFH;AAGV2B,gBAAQ,EAAE,kBAAUC,OAAV,EAAmB;AAC5BlB,eAAK,CAACU,YAAN,CAAmBQ,OAAnB;AACA;AALS,OAAX;;AAOA,UAAIlB,KAAK,CAACE,OAAN,IAAiBiB,qEAArB,EAAsC;AACrC,YAAMC,OAAO,GAAGpB,KAAK,CAACV,SAAN,IAAmB,IAAnB,GAA0B,IAA1B,GAAiC,KAAjD;AACAwB,YAAI,CAACE,KAAL,GAAa,EAAb;AACAF,YAAI,CAACM,OAAL,GAAeA,OAAf;;AACAN,YAAI,CAACG,QAAL,GAAgB,UAAUC,OAAV,EAAmB;AAClCA,iBAAO,GAAGA,OAAO,GAAG,IAAH,GAAU,KAA3B;AACAlB,eAAK,CAACU,YAAN,CAAmBQ,OAAnB;AACA,SAHD;AAIA;;AACD,aAAOrD,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyBiC,KAAK,CAACE,OAA/B,EAAwCY,IAAxC,CAAP;AACA,KApCmB,CAApB;;AAsCA,QAAMO,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC,cAAD,EAAiBlC,MAAjB,EAA4B;AACtDvB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,8CAAuC8B,cAAvC,cAAyDlC,MAAzD;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBZ,gCAAwB,CAACY,IAAD,CAAxB;AACA,OAJD;AAKA,KAND;;AAQA,QAAM6B,oBAAoB,GAAG,SAAvBA,oBAAuB,CAACD,cAAD,EAAiBlC,MAAjB,EAA4B;AACxDvB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,gDAAyC8B,cAAzC,cAA2DlC,MAA3D;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBZ,gCAAwB,CAACY,IAAD,CAAxB;AACA,OAJD;AAKA,KAND;;AAQA,QAAMN,MAAM,GAAGU,+DAAM,CAAC,aAAD,CAAN,CAAsBC,gBAAtB,EAAf;AACAyB,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,gCAAyBJ,MAAzB;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBlB,yBAAiB,CAACkB,IAAD,CAAjB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAQA;AACF;;AAIE,QAAMO,iBAAiB,GAAG,SAApBA,iBAAoB,CAACD,IAAD,EAAU;AACnC,aAAOA,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AACxB,eACC;AAAI,aAAG,EAAEA,GAAG,CAACC;AAAb,WACC;AAAG,cAAI,EAAED,GAAG,CAACE;AAAb,WAAoBF,GAAG,CAACvB,KAAxB,CADD,EACoC,GADpC,EAEC,yEAAC,4DAAD;AAAQ,iBAAO,EAAE;AAAA,mBAAMkB,kBAAkB,CAACK,GAAG,CAACC,EAAL,EAASvC,MAAT,CAAxB;AAAA;AAAjB,gBACGyC,2DAAE,CAAC,UAAD,EAAa,YAAb,CADL,MAFD,CADD;AAQA,OATM,CAAP;AAUA,KAXD;;AAYAL,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,uCAAgCJ,MAAhC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBhB,4BAAoB,CAACiB,iBAAiB,CAACD,IAAD,CAAlB,CAApB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,EAASP,qBAAT,CANM,CAAT;AAQA2C,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,wCAAiCJ,MAAjC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjB,YAAMoC,IAAI,GAAGpC,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AAC9B,iBACC;AAAI,eAAG,EAAEA,GAAG,CAACC;AAAb,aACC;AAAG,gBAAI,EAAED,GAAG,CAACE;AAAb,aAAoBF,GAAG,CAACvB,KAAxB,CADD,EAEC,yEAAC,4DAAD;AAAQ,mBAAO,EAAE;AAAA,qBAAMoB,oBAAoB,CAACG,GAAG,CAACC,EAAL,EAASvC,MAAT,CAA1B;AAAA;AAAjB,kBACGyC,2DAAE,CAAC,UAAD,EAAa,YAAb,CADL,MAFD,CADD;AAQA,SATY,CAAb;AAUAjD,6BAAqB,CAACkD,IAAD,CAArB;AACA,OAdD;AAeA,KAhBQ,EAgBN,CAAC1C,MAAD,EAASP,qBAAT,CAhBM,CAAT;;AAkBA,QAAMkD,eAAe,GAAG,SAAlBA,eAAkB,CAACrC,IAAD,EAAU;AACjC,aAAOA,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AACxB,eACC;AAAI,aAAG,EAAEA,GAAG,CAACC;AAAb,WACED,GAAG,CAACM,KADN,QACeN,GAAG,CAACO,KADnB,MADD;AAKA,OANM,CAAP;AAOA,KARD;;AASAT,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,8CAAuCJ,MAAvC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBV,gCAAwB,CAAC+C,eAAe,CAACrC,IAAD,CAAhB,CAAxB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAOAoC,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,kDAA2CJ,MAA3C;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBR,oCAA4B,CAAC6C,eAAe,CAACrC,IAAD,CAAhB,CAA5B;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAQA,WACC,yEAAC,QAAD,QACC,yEAAC,+EAAD;AACC,YAAM,EAAC,oBADR;AAEC,UAAI,EAAExB;AAFP,4BADD,EAOC,yEAAC,mEAAD;AACC,UAAI,EAAC,oBADN;AAEC,UAAI,EAAEA,cAFP;AAGC,WAAK,EAAC;AAHP,OAKC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEiE,2DAAE,CAAC,+BAAD,EAAkC,YAAlC;AAFV,OAIEtD,cAAc,CAAC4B,KAAf,IACA,oFACC,yFAAS0B,2DAAE,CAAC,QAAD,EAAW,YAAX,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC4B,KAHjB,CALF,EAWE5B,cAAc,CAAC2C,OAAf,IACA,oFACC,yFAASW,2DAAE,CAAC,UAAD,EAAa,YAAb,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC2C,OAHjB,CAZF,EAkBE3C,cAAc,CAAC2D,MAAf,IACA,oFACC,yFAASL,2DAAE,CAAC,SAAD,EAAY,YAAZ,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC2D,MAHjB,CAnBF,EAyBE3D,cAAc,CAAC4D,QAAf,IACA,oFACC,yFAASN,2DAAE,CAAC,aAAD,EAAgB,YAAhB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC4D,QAHjB,CA1BF,EAgCE5D,cAAc,CAAC6D,GAAf,IACA,oFACC,yFAASP,2DAAE,CAAC,OAAD,EAAU,YAAV,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC6D,GAHjB,CAjCF,EAuCE7D,cAAc,CAAC8D,QAAf,IACA,oFACC,yFAASR,2DAAE,CAAC,mBAAD,EAAsB,YAAtB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC8D,QAHjB,CAxCF,EA8CE9D,cAAc,CAAC+D,OAAf,IACA,oFACC,yFAAST,2DAAE,CAAC,WAAD,EAAc,YAAd,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC+D,OAHjB,CA/CF,EAqDE/D,cAAc,CAACgE,WAAf,IACA,oFACC,yFAASV,2DAAE,CAAC,gBAAD,EAAmB,YAAnB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACgE,WAHjB,CAtDF,EA4DEhE,cAAc,CAACiE,OAAf,IACA,oFACC,yFAASX,2DAAE,CAAC,UAAD,EAAa,YAAb,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACiE,OAHjB,CA7DF,EAmEEjE,cAAc,CAACqD,IAAf,IACA,oFACC,yFAASC,2DAAE,CAAC,qBAAD,EAAwB,YAAxB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACqD,IAHjB,CApEF,EA0EErD,cAAc,CAACkE,KAAf,IACA,oFACC,yFAASZ,2DAAE,CAAC,gBAAD,EAAmB,YAAnB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACkE,KAHjB,CA3EF,EAiFElE,cAAc,CAACmE,MAAf,IACA,oFACC,yFACEb,2DAAE,CAAC,kCAAD,EAAqC,YAArC,CADJ,CADD,EAIC,oFAJD,EAKEtD,cAAc,CAACmE,MALjB,CAlFF,CADD,CALD,EAkGC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AAAW,iBAAW,EAAE,KAAxB;AAA+B,WAAK,EAAEb,2DAAE,CAAC,SAAD,EAAY,YAAZ;AAAxC,OACC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,+CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CADD,EAWC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,uEADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAXD,EAqBC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,iHAAD,EAAoH,YAApH,CADJ,CADD,CArBD,EA0BC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,kLAAD,EAAqL,YAArL,CADJ,CADD,CA1BD,CADD,EAiCC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEA,2DAAE,CAAC,WAAD,EAAc,YAAd;AAFV,OAIC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,2CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAJD,EAcC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,sCADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAdD,EAwBC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,uEADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAxBD,EAkCC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,8GAAD,EAAiH,YAAjH,CADJ,CADD,CAlCD,CAjCD,CAlGD,EA4KC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEA,2DAAE,CAAC,eAAD,EAAkB,YAAlB;AAFV,OAIC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,8CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAJD,EAcC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,iDADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAdD,EAwBC,yEAAC,8DAAD,QACC,yEAAC,kBAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,0EADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAxBD,EAkCC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,6KAAD,EAAgL,YAAhL,CADJ,CADD,CAlCD,EAuCC,yEAAC,8DAAD,QACC,yEAAC,kBAAD;AACC,aAAO,EAAEe,iEADV;AAEC,WAAK,EAAEf,2DAAE,CACR,0EADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAvCD,EAiDC,oFAAIA,2DAAE,CAAC,8BAAD,EAAiC,YAAjC,CAAN,CAjDD,EAkDC,qFAAKpD,iBAAL,CAlDD,EAoDC,oFAAIoD,2DAAE,CAAC,+BAAD,EAAkC,YAAlC,CAAN,CApDD,EAqDC,qFAAKlD,kBAAL,CArDD,CADD,CA5KD,EAqOC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AAAW,iBAAW,EAAE,KAAxB;AAA+B,WAAK,EAAEkD,2DAAE,CAAC,UAAD,EAAa,YAAb;AAAxC,OACC,oFACEA,2DAAE,CACF,sDADE,EAEF,YAFE,CADJ,CADD,EAOC,qFAAK9C,qBAAL,CAPD,EAQC,oFACE8C,2DAAE,CACF,kDADE,EAEF,YAFE,CADJ,CARD,EAcC,qFAAK5C,yBAAL,CAdD,CADD,CArOD,CAPD,CADD;AAkQA;AAhbmC,CAAvB,CAAd,C;;;;;;;;;;;ACjCA,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I;;;;;;;;;;;ACAtD,aAAa,2CAA2C,EAAE,I;;;;;;;;;;;ACA1D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I;;;;;;;;;;;ACAtD,aAAa,0CAA0C,EAAE,I","file":"index.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/index.js\");\n","function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n\n for (var i = 0, arr2 = new Array(len); i < len; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n}\n\nmodule.exports = _arrayLikeToArray;","function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nmodule.exports = _arrayWithHoles;","function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n\n return self;\n}\n\nmodule.exports = _assertThisInitialized;","function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nmodule.exports = _classCallCheck;","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nmodule.exports = _createClass;","function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nmodule.exports = _defineProperty;","function _getPrototypeOf(o) {\n module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}\n\nmodule.exports = _getPrototypeOf;","var setPrototypeOf = require(\"./setPrototypeOf\");\n\nfunction _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}\n\nmodule.exports = _inherits;","function _iterableToArrayLimit(arr, i) {\n if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nmodule.exports = _iterableToArrayLimit;","function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\n\nmodule.exports = _nonIterableRest;","var _typeof = require(\"@babel/runtime/helpers/typeof\");\n\nvar assertThisInitialized = require(\"./assertThisInitialized\");\n\nfunction _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n }\n\n return assertThisInitialized(self);\n}\n\nmodule.exports = _possibleConstructorReturn;","function _setPrototypeOf(o, p) {\n module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}\n\nmodule.exports = _setPrototypeOf;","var arrayWithHoles = require(\"./arrayWithHoles\");\n\nvar iterableToArrayLimit = require(\"./iterableToArrayLimit\");\n\nvar unsupportedIterableToArray = require(\"./unsupportedIterableToArray\");\n\nvar nonIterableRest = require(\"./nonIterableRest\");\n\nfunction _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();\n}\n\nmodule.exports = _slicedToArray;","function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n module.exports = _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n module.exports = _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nmodule.exports = _typeof;","var arrayLikeToArray = require(\"./arrayLikeToArray\");\n\nfunction _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}\n\nmodule.exports = _unsupportedIterableToArray;","import {\n\tPanel,\n\tPanelBody,\n\tPanelRow,\n\tTextControl,\n\tTextareaControl,\n\tCheckboxControl,\n\tButton,\n\twithFocusOutside,\n} from \"@wordpress/components\"\nimport { registerPlugin } from \"@wordpress/plugins\"\nimport { PluginSidebar, PluginSidebarMoreMenuItem } from \"@wordpress/edit-post\"\nimport { __ } from \"@wordpress/i18n\"\nimport { select, withSelect, withDispatch } from \"@wordpress/data\"\nimport { compose } from \"@wordpress/compose\"\nimport { useState, useEffect } from \"@wordpress/element\"\n\nconst relevanssiIcon = wp.element.createElement(\n\t\"svg\",\n\t{\n\t\twidth: 20,\n\t\theight: 20,\n\t},\n\twp.element.createElement(\"path\", {\n\t\td: \"M5.644 20.665 C6.207 20.545 6.612 20.029 6.574 19.438 6.469 17.784 6.492 16.554 6.617 15.602 L7.388 19.228 C7.454 19.538 7.576 19.815 7.737 20.058 7.742 20.12 7.749 20.181 7.763 20.243 L8.444 23.384 C10.112 23.233 11.311 22.775 11.214 23.077 L10.82 21.227 C10.875 21.218 10.929 21.211 10.984 21.199 10.995 21.197 11.004 21.193 11.015 21.191 L11.35 22.766 C11.571 22.305 13.613 22.092 14.187 21.891 L13.42 19.11 C13.529 18.742 13.553 18.346 13.466 17.936 L12.445 13.134 C12.535 13.088 12.62 13.03 12.698 12.959 12.737 12.929 12.786 12.899 12.84 12.864 13.25 12.596 14.097 12.042 14.433 10.839 L20.429 12.98 C20.642 13.056 20.862 13.067 21.069 13.023 21.456 12.941 21.792 12.667 21.934 12.267 22.154 11.655 21.835 10.981 21.222 10.763 L14.393 8.324 C14.385 8.291 14.379 8.26 14.37 8.226 14.212 7.595 13.573 7.212 12.94 7.372 12.887 7.385 12.838 7.402 12.789 7.422 12.873 6.845 12.859 6.245 12.731 5.643 12.145 2.884 9.422 1.118 6.661 1.705 3.901 2.292 2.132 5.012 2.718 7.771 3.304 10.529 6.027 12.295 8.788 11.708 10.041 11.442 11.088 10.735 11.805 9.786 11.917 9.894 12.05 9.981 12.203 10.04 12.148 10.37 11.997 10.56 11.811 10.71 10.72 11.467 10.238 11.826 9.318 12.07 L8.678 12.167 C7.581 12.344 6.407 12.307 5.457 11.871 4.141 13.689 3.972 15.683 4.221 19.589 4.263 20.238 4.823 20.73 5.473 20.688 5.531 20.685 5.589 20.677 5.644 20.665 Z M8.568 10.67 C6.38 11.135 4.222 9.735 3.758 7.55 3.293 5.364 4.695 3.208 6.883 2.743 9.07 2.278 11.229 3.677 11.693 5.863 12.158 8.049 10.755 10.205 8.568 10.67 Z\",\n\t}),\n\twp.element.createElement(\"path\", {\n\t\td: \"M8.009 5.745 C7.25 5.906 6.576 5.754 6.502 5.406 6.496 5.377 6.496 5.348 6.498 5.318 6.012 5.752 5.765 6.429 5.911 7.115 6.127 8.132 7.122 8.783 8.132 8.568 9.142 8.353 9.786 7.354 9.57 6.338 9.483 5.928 9.269 5.58 8.98 5.323 8.755 5.503 8.411 5.66 8.009 5.745 Z\",\n\t})\n)\n\nconst { Fragment } = wp.element\n\nregisterPlugin(\"relevanssi-premium\", {\n\trender: function () {\n\t\tconst [relevanssiSees, setRelevanssiSees] = useState([])\n\t\tconst [relevanssiRelated, setRelevanssiRelated] = useState([])\n\t\tconst [relevanssiExcluded, setRelevanssiExcluded] = useState([])\n\t\tconst [relevanssiExcludedIds, setRelevanssiExcludedIds] = useState([])\n\t\tconst [relevanssiCommonTerms, setRelevanssiCommonTerms] = useState([])\n\t\tconst [relevanssiLowRankingTerms, setRelevanssiLowRankingTerms] = useState(\n\t\t\t[]\n\t\t)\n\n\t\tconst regenerateRelatedPosts = (postId, metaKey, metaValue) => {\n\t\t\tif (!metaValue) metaValue = \"0\"\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/regeneraterelatedposts/${postId}/${metaKey}/${metaValue}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiRelated(createRelatedList(data))\n\t\t\t})\n\t\t}\n\n\t\tconst RelatedPostControl = withFocusOutside(\n\t\t\tclass extends React.Component {\n\t\t\t\thandleFocusOutside() {\n\t\t\t\t\tregenerateRelatedPosts(\n\t\t\t\t\t\twp.data.select(\"core/editor\").getCurrentPostId(),\n\t\t\t\t\t\tthis.props.metaKey,\n\t\t\t\t\t\twp.data.select(\"core/editor\").getEditedPostAttribute(\"meta\")[\n\t\t\t\t\t\t\tthis.props.metaKey\n\t\t\t\t\t\t]\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\n\t\tconst MetaControl = compose(\n\t\t\twithDispatch((dispatch, props) => {\n\t\t\t\treturn {\n\t\t\t\t\tsetMetaValue: function (metaValue) {\n\t\t\t\t\t\tdispatch(\"core/editor\").editPost({\n\t\t\t\t\t\t\tmeta: { [props.metaKey]: metaValue },\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}),\n\t\t\twithSelect((select, props) => {\n\t\t\t\tlet metaValue =\n\t\t\t\t\tselect(\"core/editor\").getEditedPostAttribute(\"meta\")[props.metaKey]\n\t\t\t\tif (metaValue === \"0\") metaValue = \"\"\n\t\t\t\treturn {\n\t\t\t\t\tmetaValue,\n\t\t\t\t}\n\t\t\t})\n\t\t)((props) => {\n\t\t\tlet args = {\n\t\t\t\tlabel: props.title,\n\t\t\t\tvalue: props.metaValue,\n\t\t\t\tonChange: function (content) {\n\t\t\t\t\tprops.setMetaValue(content)\n\t\t\t\t},\n\t\t\t}\n\t\t\tif (props.control == CheckboxControl) {\n\t\t\t\tconst checked = props.metaValue == \"on\" ? true : false\n\t\t\t\targs.value = \"\"\n\t\t\t\targs.checked = checked\n\t\t\t\targs.onChange = function (content) {\n\t\t\t\t\tcontent = content ? \"on\" : \"off\"\n\t\t\t\t\tprops.setMetaValue(content)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn wp.element.createElement(props.control, args)\n\t\t})\n\n\t\tconst excludeRelatedPost = (excludedPostId, postId) => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/excluderelatedpost/${excludedPostId}/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiExcludedIds(data)\n\t\t\t})\n\t\t}\n\n\t\tconst unExcludeRelatedPost = (excludedPostId, postId) => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/unexcluderelatedpost/${excludedPostId}/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiExcludedIds(data)\n\t\t\t})\n\t\t}\n\n\t\tconst postId = select(\"core/editor\").getCurrentPostId()\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/sees/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiSees(data)\n\t\t\t})\n\t\t}, [postId])\n\n\t\t/*\n\n\n\t\t\t\t\t\t\t*/\n\n\t\tconst createRelatedList = (data) => {\n\t\t\treturn data.map((row) => {\n\t\t\t\treturn (\n\t\t\t\t\t
  • \n\t\t\t\t\t\t{row.title}{\" \"}\n\t\t\t\t\t\t\n\t\t\t\t\t
  • \n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listrelated/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiRelated(createRelatedList(data))\n\t\t\t})\n\t\t}, [postId, relevanssiExcludedIds])\n\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listexcluded/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tconst list = data.map((row) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t
  • \n\t\t\t\t\t\t\t{row.title}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
  • \n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t\tsetRelevanssiExcluded(list)\n\t\t\t})\n\t\t}, [postId, relevanssiExcludedIds])\n\n\t\tconst createTermsList = (data) => {\n\t\t\treturn data.map((row) => {\n\t\t\t\treturn (\n\t\t\t\t\t
  • \n\t\t\t\t\t\t{row.query} ({row.count})\n\t\t\t\t\t
  • \n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listinsightscommon/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiCommonTerms(createTermsList(data))\n\t\t\t})\n\t\t}, [postId])\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listinsightslowranking/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiLowRankingTerms(createTermsList(data))\n\t\t\t})\n\t\t}, [postId])\n\n\t\treturn (\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tRelevanssi Premium\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{relevanssiSees.title && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Title:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.title}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.content && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Content:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.content}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.author && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Author:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.author}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.category && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Categories:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.category}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.tag && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Tags:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.tag}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.taxonomy && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Other taxonomies:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.taxonomy}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.comment && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Comments:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.comment}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.customfield && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Custom fields:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.customfield}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.excerpt && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Excerpt:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.excerpt}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.link && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Links to this post:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.link}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.mysql && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"MySQL columns:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.mysql}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.reason && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{__(\"Reason this post is not indexed:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.reason}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"If any of these keywords are present in the search query, this post will be moved on top of the search results.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"You can add weights to pinned keywords like this: 'keyword (100)'. The post with the highest weight will be sorted first if there are multiple posts pinned to the same keyword.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"If any of these keywords are present in the search query, this post will be removed from the search results.\", \"relevanssi\" )}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Anything entered here will used when searching for related posts. Using phrases with quotes is allowed, but will restrict the related posts to posts including that phrase.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t

    {__(\"Related posts for this post:\", \"relevanssi\")}

    \n\t\t\t\t\t\t\t
      {relevanssiRelated}
    \n\n\t\t\t\t\t\t\t

    {__(\"Excluded posts for this post:\", \"relevanssi\")}

    \n\t\t\t\t\t\t\t
      {relevanssiExcluded}
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t{__(\n\t\t\t\t\t\t\t\t\t\"The most common search terms used to find this post:\",\n\t\t\t\t\t\t\t\t\t\"relevanssi\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
      {relevanssiCommonTerms}
    \n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t{__(\n\t\t\t\t\t\t\t\t\t\"Low-ranking search terms used to find this post:\",\n\t\t\t\t\t\t\t\t\t\"relevanssi\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
      {relevanssiLowRankingTerms}
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t)\n\t},\n})\n","(function() { module.exports = window[\"wp\"][\"components\"]; }());","(function() { module.exports = window[\"wp\"][\"compose\"]; }());","(function() { module.exports = window[\"wp\"][\"data\"]; }());","(function() { module.exports = window[\"wp\"][\"editPost\"]; }());","(function() { module.exports = window[\"wp\"][\"element\"]; }());","(function() { module.exports = window[\"wp\"][\"i18n\"]; }());","(function() { module.exports = window[\"wp\"][\"plugins\"]; }());"],"sourceRoot":""} \ No newline at end of file diff --git a/relevanssi-premium/changelog.txt b/relevanssi-premium/changelog.txt deleted file mode 100644 index 1dd26aca..00000000 --- a/relevanssi-premium/changelog.txt +++ /dev/null @@ -1,1611 +0,0 @@ -= 2.19.1 = -* Minor fix: WooCommerce layered navigation compatibility caused enough problems that I've disabled it by default. You can enable it with `add_filter( 'woocommerce_get_filtered_term_product_counts_query', 'relevanssi_filtered_term_product_counts_query' );`. -* Minor fix: Data attribute handling for in-document highlighting is now better. - -= 2.19.0 = -* New feature: New CLI command `list_pinned_posts` lists all pinned and unpinned posts. -* New feature: New CLI command `list` lists indexed and unindexed posts, taxonomy terms and users. -* New feature: You can now look at how the posts appear in the database from the Debugging tab. -* New feature: Relevanssi now works with WooCommerce layered navigation filters. The filter post counts should now match the Relevanssi search results. -* New feature: You can now export the click tracking logs. -* New feature: New function `relevanssi_count_term_occurrances()` can be used to display how many times search terms appear in the database. -* Changed behaviour: Relevanssi post update trigger is now on `wp_after_insert_post` instead of `wp_insert_post`. This makes the indexing more reliable and better compatible with other plugins. -* Changed behaviour: Previously, throttling searches has been impossible when results are sorted by date. Now if you set Relevanssi to sort by post date from the searching settings, you can enable the throttle and the throttling will make sure to keep the most recent posts. This does not work if you set the `orderby` to `post_date` elsewhere. -* Minor fix: Prevents Relevanssi from interfering in fringe cases (including The Event Calendar event search). -* Minor fix: Relevanssi added the `highlight` parameter to home page URLs, even though it shouldn't. -* Minor fix: Indexing `nav_menu_item` posts is stopped earlier in the process to avoid problems with big menus. -* Minor fix: Add support for WooCommerce products attribute lookup table filtering. -* Minor fix: Improves Polylang language detection. -* Minor fix: Improve excerpts to avoid breaking HTML tags when tags are allowed. -* Minor fix: Add support for JetSmartFilters. -* Minor fix: With multiple excerpts, sometimes Relevanssi would return no excerpt at all. -* Minor fix: If the `sentence` query variable is used to enable phrase searching, Relevanssi now adds quotes to the `highlight` parameter. -* Minor fix: Add support for TablePress `table_filter` shortcodes. -* Minor fix: Improve WPFD file content indexing support. Relevanssi indexing now happens after the WPFD indexing is done. -* Minor fix: User profile update actions now happen at a later priority. This should reduce problems when indexing ACF fields, for example. -* Minor fix: Relevanssi now hyphenates long search terms in the User searches page. This prevents long search terms from messing up the display. -* Minor fix: Stopped some problems with Did you mean suggestions suggesting the same word if a hyphen was included. -* Minor fix: If the API key wasn't set in network settings for a multisite installation, Relevanssi wouldn't fall back to the current site API key setting when indexing attachment content. That works correctly now; still, set the API key on network settings level. -* Minor fix: Paging didn't work in admin searches for hierarchical post types (like pages). -* Minor fix: Relevanssi doesn't add click tracking or highlight parameters to admin searches anymore. -* Minor fix: The search log reset feature now also resets the click tracking log. -* Minor fix: In-document highlighting could break certain elements thanks to Relevanssi messing up data attributes. -* Minor fix: Relevanssi now recursively runs `relevanssi_block_to_render` and the CSS `relevanssi_noindex` filtering for inner blocks. -* Minor fix: Relevanssi redirects now work better with FacetWP searches. Thanks to Jan Willem Oostendorp. - -= 2.18.0 = -* New feature: Oxygen compatibility has been upgraded to support JSON data from Oxygen 4. This is still in early stages, so feedback from Oxygen users is welcome. -* New feature: New filter hook `relevanssi_oxygen_element` is used to filter Oxygen JSON elements. The earlier `relevanssi_oxygen_section_filters` and `relevanssi_oxygen_section_content` filters are no longer used with Oxygen 4; this hook is the only way to filter Oxygen elements. -* Changed behaviour: Relevanssi now applies `remove_accents()` to all strings. This is because default database collations do not care for accents and having accents may cause missing information in indexing. If you use a database collation that doesn't ignore accents, make sure you disable this filter. -* Minor fix: Stops drafts and pending posts from showing up in Relevanssi Live Ajax Searches. -* Minor fix: Remove array_flip() warnings from related posts. -* Minor fix: Relevanssi used `the_category` filter with too few parameters. The missing parameters have been added. -* Minor fix: Language translations didn't update. -* Minor fix: Phrases weren't used in some cases where a multiple-word phrase looked like a single-word phrase. -* Minor fix: Prevents fatal errors from `relevanssi_extract_rt()`. -* Minor fix: Prevents fatal errors from `relevanssi_strip_all_tags()`. - -= 2.17.2 = -* New feature: If you have a valid license, you can now leave support requests from within the Relevanssi settings pages. -* New feature: New filter hook `relevanssi_didyoumean_token` lets you filter Did you mean words before correction. You can use this filter hook to exclude words from being corrected. -* Minor fix: Relevanssi now adds spaces after table cell tags to avoid table cell content sticking together in excerpts. -* Minor fix: Phrase search couldn't find phrases that include an ampersand if they matched the post title. This works now. -* Minor fix: The 'Allowable tags in excerpts' function now automatically corrects the entered value to match what Relevanssi expects the value to be. -* Minor fix: In some cases Relevanssi goofed excerpts for user profiles when custom field content was used for excerpts. This is now corrected and the user custom field excerpts work better now. -* Minor fix: Relevanssi blocked non-post items from the results when used with Relevanssi Live Ajax Search. That is now fixed. -* Minor fix: Phrase searching did not work in multisite searches. This is now fixed. - -= 2.17.1 = -* New feature: New filter hook `relevanssi_update_translations` lets you disable the translation updates from TranslationsPress. If you only use WordPress in English, you can disable the translation updates with `add_filter( 'relevanssi_update_translations', '__return_false' );`. -* Changed behaviour: Relevanssi now ignores WordPress metadata custom fields that aren't interesting for Relevanssi indexing. -* Changed behaviour: Both `relevanssi_get_permalink()` and `relevanssi_the_permalink()` now can take post ID or a post object as a parameter and can thus be used outside the Loop. -* Changed behaviour: The `relevanssi_hits_filter` hook now gets the WP_Query object as the second parameter. -* Minor fix: The "Disable outside connections" option did not apply to the TranslationsPress translation updates. Now it does: those are also disabled when this option is enabled. -* Minor fix: The `mysqlcolumn_detail` feature was completely missing. Nobody has ever asked about it, which suggests nobody actually uses it, but now it works. -* Minor fix: The 'Ignore post content' checkbox did not show up correctly. Now it works. - -= 2.17.0 = -* New feature: 'Ignore post content' checkbox in the Relevanssi post edit sidebar makes Relevanssi ignore post content for that post when indexing. -* New feature: The action hook `relevanssi_init` runs at the end of the `relevanssi_init()` function. -* New feature: The $post->relevanssi_hits data now includes more information about custom field, taxonomy and MySQL column matches. -* New feature: New filter hook `relevanssi_author_query_filter` filters the post author MySQL query. -* New feature: New filter hook `relevanssi_by_date_query_filter` filters the by_date MySQL query. -* New feature: New filter hook `relevanssi_date_query_filter` filters the date query MySQL query. -* New feature: New filter hook `relevanssi_parent_query_filter` filters the post parent MySQL query. -* New feature: New filter hook `relevanssi_post_query_filter` filters the post__in and post__not_in MySQL query. -* New feature: New filter hook `relevanssi_post_status_query_filter` filters the post_status MySQL query. -* New feature: New filter hook `relevanssi_post_type_query_filter` filters the post_type MySQL query. -* New feature: Relevanssi will now show available Premium updates even when the license is not valid or API key is missing. The updates cannot be installed without a valid API key, but they will be visible. -* Major fix: The click tracking log table trimming wasn't implemented before. Now it's up and running. -* Minor fix: The Bricks compatibility was improved, Relevanssi now notices changes to Bricks posts more often. Relevanssi also only reads the text from the `_bricks_page_content_2` custom field. - -= 2.16.8 = -* One trailing comma caused Relevanssi to not work with PHP 7.2 or earlier. That is fixed, and Relevanssi is now again compatible with PHP 7. - -= 2.16.7 = -* Minor fix: The `relevanssi_index_taxonomies_args` filter hook should've been removed from use long time ago, but it was still in use in some cases, and thus `relevanssi_hide_empty_terms` didn't always work, depending on how the terms were indexed. Now the filter use is consistent and `relevanssi_hide_empty_terms` is always used. -* User interface: The synonym settings page now alerts if the synonyms aren't active because of the AND search. - -= 2.16.6 = -* Minor fix: The translations would show up as requiring update, even after the update. This is now fixed. -* Minor fix: Pinning didn't work with numeric keywords. - -= 2.16.5 = -* Security fix: Extra hardening for AJAX requests. Some AJAX actions in Relevanssi could leak information to site subscribers who knew what to look for. - -= 2.16.4 = -* Security fix: Any registered user could empty the Relevanssi index by triggering the index truncate AJAX action. That is no longer possible. -* New feature: The [searchform] shortcode has a new parameter, 'checklist', which you can use to create taxonomy checklists. -* New feature: New filter hook `relevanssi_post_type_archive_ok` allows controlling whether individual post type archives are indexed or not. -* New feature: You can now set the API key with the constant RELEVANSSI_API_KEY. If the constant is set, the API key settings disappear on the Relevanssi settings page. -* Changed behaviour: The `relevanssi_related_output_objects` filter hook has been removed. It was unnecessary: it simply isn't useful to filter a function return value, because you can modify it without a filter hook. -* Changed behaviour: The `relevanssi_search_form` filter hook has an additional parameter which has the shortcode attributes. -* Changed behaviour: The `relevanssi_search_again` parameter array has more parameters the filter can modify. -* Changed behaviour: The `relevanssi_show_matches` filter hook gets the post object as the second parameter. -* Changed behaviour: The `relevanssi_term_add_data` filter hook now runs also when individual terms are modified. Previously it only run when all terms were indexed. -* Translations: Relevanssi Premium is now professionally translated to German and Spanish. - -= 2.16.3 = -* Security fix: User searches page had a XSS vulnerability. -* Changed behaviour: Click tracking is no longer added to links if the user is on the logging block list or a bot. -* Minor fix: `relevanssi_orderby` did not always accept an array-format orderby parameter. -* Minor fix: Removes a highlighting problem stemming from uppercase search terms. -* Minor fix: When image attachment indexing was disabled, saving image attachments would still index the images. Image attachment blocking is now a `relevanssi_indexing_restriction` filter function, which means it's always active. -* Minor fix: Enabling click tracking doesn't break anchor links anymore. -* Minor fix: Relevanssi removes highlights better from inside multiline HTML tags. - -= 2.16.2 = -* Minor fix: Remove unnecessary database calls from admin pages. -* Minor fix: Improved Oxygen compatibility. - -= 2.16.1 = -* Fixes an error on the post query insights screen. - -= 2.16.0 = -* New feature: Click tracking lets you track the way the users click different posts from the search results pages. Enable the click tracking from the Logging settings to see it in effect. -* New feature: Proximity sorting lets you sort posts by geographical distance. See the knowledge base for details on how this works. -* New feature: New filter hook `relevanssi_render_blocks` controls whether Relevanssi renders blocks in a post or not. If you are having problems updating long posts with lots of blocks, having this filter hook return `false` for the post in question will likely help, as rendering the blocks in a long post can take huge amounts of memory. -* New feature: The [searchform] shortcode has a new parameter, 'post_type_boxes', which creates a checkbox for each post type you list in the value. For example [searchform post_type_boxes='*post,page'] would create a search with a checkbox for 'post' and 'page' post types, with 'post' pre-checked. -* New feature: You can now have multiple dropdowns in one [searchform] shortcode. Anything that begins with 'dropdown' is considered a dropdown parameter, so you can do [searchform dropdown_1='category' dropdown_2='post_tag'] for example. -* New feature: New filter hook `relevanssi_search_params` lets you filter search parameters after they've been collected from the WP_Query. -* New feature: New filter hook `relevanssi_excerpt_post` lets you make Relevanssi skip creating excerpts for specific posts. -* Changed behaviour: Redirect queries now support regular expressions. -* Changed behaviour: Filter hooks `relevanssi_1day`, `relevanssi_7days` and `relevanssi_30days` are removed, as the user searches page is now different. The default value for `relevanssi_user_searches_limit` is now 100 instead of 20. -* Minor fix: Stopwords weren't included in the exported options; they are now. -* Minor fix: Relevanssi won't let you adjust synonyms and stopwords anymore if you use Polylang and are in 'Show all languages' mode. -* Minor fix: New parameter for `relevanssi_tokenize()` introduces the context (indexing or search query). The `relevanssi_extract_phrases()` is only used on search queries. -* Minor fix: When you deactivate the Related posts feature from the settings, the Related post caches for posts are flushed. -* Minor fix: In some languages, iOS uses „“ for quotes. Relevanssi now understands those for the phrase operator. -* Minor fix: You can now choose 'user' post type in the admin search post type dropdown. -* Minor fix: The debugging page now lets you debug user profiles and taxonomy terms. -* Minor fix: Highlighting is improved by a more precise HTML entity filter, thanks to Jacob Bearce. -* Minor fix: Fixes problems with the WP-Members compatibility. -* Minor fix: The `relevanssi_premium_tokenizer` filter hook now gets the context (indexing or searching) as a parameter. -* Minor fix: Stops Relevanssi from blocking the admin search for WooCommerce coupons and other WooCommerce custom post types. -* Minor fix: Searching for a stemmed word with the AND search didn't find correct results. - -= 2.15.3.1 = -* Minor fix: The Bricks compatibility was broken, this version fixes it. - -= 2.15.3 = -* New feature: You can add a post type dropdown to [searchform] forms with `dropdown='post_type'`. -* New feature: New filter hook `relevanssi_sku_boost` controls the WooCommerce `_sku` field weight boost. -* New feature: New filter hook `relevanssi_related_posts_cache_id` lets you change the Related posts transient cache ID so allow multiple cached related posts per post. -* New feature: New filter hook `relevanssi_post_to_excerpt` lets you filter the post object before an excerpt is created from it. -* New feature: New filter hook `relevanssi_custom_fields_before_repeaters` filters the list of custom fields before repeater fields are processed, so you can add fields from code using the field_%_subfield notation. -* New feature: Relevanssi is now compatible with the Bricks page builder theme (requires Bricks 1.3.2). -* Changed behaviour: The spam block now returns a 410 Gone status code for blocked pages. -* Changed behaviour: The minimum capability for seeing the Gutenberg sidebar or the Relevanssi meta box is changed from 'manage_options' to 'edit_others_posts' in order to allow editors see the sidebar and the meta box. If you prefer the original way, use the `relevanssi_sidebar_capability` filter hook to adjust. -* Minor fix: Relevanssi removes HTML comments better from the post content. -* Minor fix: Sometimes the Did you mean would return really weird long suggestions from the search logs. That won't happen anymore. -* Minor fix: Oxygen compatibility has been improved. Rich text fields and updating posts when they are saved in Oxygen now work better, and revisions are no longer indexed. -* Minor fix: Improves tax_query handling in fringe cases with multiple AND clauses joined together with OR. -* Minor fix: It's now possible to override global multisite search settings from the `searchblogs` query variable. -* Minor fix: Searching without a search term works much better now, you get more posts in the results (default value is up to 500). - -= 2.15.2 = -* New feature: Adds support for Avada Live Search. -* New feature: Adds support for Fibo Search. -* New feature: Spam blocking can be used to block bots from accessing your search results pages. -* Changed behaviour: The filter hook `relevanssi_indexing_terms` that appeared in post type archive indexing is renamed to `relevanssi_indexing_tokens` what it should've been to begin with. -* Minor fix: Elementor library searches are not broken anymore when Relevanssi is enabled in admin. -* Minor fix: Relevanssi now understands array-style post_type[] parameters. -* Minor fix: The MySQL column detail information has been missing from the index. -* Minor fix: Spam blocking now works with pretty search page URLs and not just with ?s= URLs. You can use the new filter hook `relevanssi_search_url_prefix` to adjust the prefix in case it's not `/search/`. Spam blocking is also extended to page views with spam content in the `highlight` parameter. -* Minor fix: Relevanssi now automatically considers the Turkish 'ı' the same as 'i'. - -= 2.15.1 = -* New feature: New action hooks `relevanssi_disable_stemmer` and `relevanssi_enable_stemmer`. Relevanssi-compatible stemmers should implement these action hooks: the first should disable the stemmer and the second should enable it. -* New feature: Adds compatibility for WP-Members plugin, preventing blocked posts from showing up in the search results. -* New feature: New function `relevanssi_get_attachment_suffix()` can be used to return the attachment file suffix based on a post object or a post ID. -* Major fix: Fixes the broken Relevanssi controls on block editor post edit pages. -* Minor fix: Improved the Missing terms feature when used with stemming. This fix requires updating Snowball Stemmer to version 1.3. -* Minor fix: Improves the Oxygen compatibility. Now also the [oxygen] shortcode tags are removed. - -= 2.15.0 = -* New feature: Relevanssi can now add Google-style missing term lists to the search results. You can either use the `%missing%` tag in the search results breakdown settings, or you can create your own code: the missing terms are also in `$post->missing_terms`. Relevanssi Premium will also add "Must have" links when there's just one missing term. -* New feature: New filter hook `relevanssi_missing_terms_tag` controls which tag is used to wrap the missing terms. -* New feature: New filter hook `relevanssi_missing_terms_template` can be used to filter the template used to display the missing terms. -* New feature: New filter hook `relevanssi_missing_terms_must_have` filters the 'Must have' part of the missing terms element. -* New feature: New filter hook `relevanssi_phrase` filters each phrase before it's used in the MySQL query. -* New feature: New filter hook `relevanssi_multi_results`, which is the same as `relevanssi_results`, but is applied to multisite results, so instead of a post ID, it has 'blog ID|post ID' in the keys and as usual the post weight in the value. -* New feature: New filter hook `relevanssi_site_results`, which is the same as `relevanssi_results`, but only applied in single site results in multisite searching (ie. the filter is applied once for each subsite included in the results). -* New feature: New filter hook `relevanssi_post_author` lets you filter the post author display_name before it is indexed. -* New feature: New function `relevanssi_get_post_meta_for_all_posts()` can be used to fetch particular meta field for a number of posts with just one query. -* New feature: Relevanssi now has a keyword-based spam blocking feature to stop spam searches as soon as possible. -* New feature: The `fields` parameter can be set to `id=>type`, which returns post ID and the post type (post, user, taxonomy term), providing support for non-post results. This only works when using `relevanssi_do_query()` to run the query. -* Changed behaviour: `relevanssi_strip_tags()` used to add spaces between HTML tags before stripping them. It no longer does that, but instead adds a space after specific list of tags (p, br, h1-h6, div, blockquote, hr, li, img) to avoid words being stuck to each other in excerpts. -* Changed behaviour: Relevanssi now indexes the contents of Oxygen Builder PHP & HTML code blocks. -* Changed behaviour: Relevanssi now handles synonyms inside phrases differently. If the new filter hook `relevanssi_phrase_synonyms` returns `true` (default value), synonyms create a new phrase (with synonym 'dog=hound', phrase `"dog biscuits"` becomes `"dog biscuits" "hound biscuits"`). If the value is `false`, synonyms inside phrases are ignored. -* Changed behaviour: Multisite searching code has been refactored, and at the same time new features have been added. It is now possible to use date parameters and synonyms in multisite searching. -* Minor fix: Attachments that cause the reading server run out of memory are now labeled with the "File size too large error". -* Minor fix: Multisite searches were not logged. Now they are. -* Minor fix: Warnings when creating excerpts with search terms that contain a slash were removed. -* Minor fix: Better Ninja Tables compatibility to avoid problems with lightbox images. -* Minor fix: Trying to open the Relevanssi sidebar in Gutenberg when a post type did not support custom fields caused a crash. Now the sidebar is simply disabled if the post type does not support custom fields. -* Minor fix: Relevanssi did not work well in the Media Library grid view. Relevanssi is now blocked there. If you need Relevanssi in Media Library searches, use the list view. -* Minor fix: Relevanssi excerpt creation didn't work correctly when numerical search terms were used. - -= 2.14.5 = -* New feature: New WP CLI command `wp relevanssi remove_attachment_errors` clears out all attachment reading errors. -* Changed behaviour: `relevanssi_excerpt_custom_field_content` now gets the post ID and list of custom field names as a parameter. -* Changed behaviour: Attachments tab will now prevent reading the attachments if the options have been changed and aren't saved. -* Changed behaviour: Instead of setting the attachment reading server to 'us', Relevanssi install process will now guess whether 'eu' would be a better option based on the site locale. -* Minor fix: Avoids admin ajax request flooding when removing lots of posts at once. -* Minor fix: Adds trailing slash to the blog URL in Did you mean links. -* Minor fix: When the contents for an attached attachment are read, Relevanssi will now automatically index the parent post if the setting is enabled. - -= 2.14.4 = -* New feature: New action hooks `relevanssi_pre_the_content` and `relevanssi_post_the_content` fire before and after Relevanssi applies `the_content` filter to the post excerpts. Some Relevanssi default behaviour has been moved to these hooks so it can be modified. -* Changed behaviour: The `relevanssi_do_not_index` gets the post object as a third parameter. -* Minor fix: Remove errors from `relevanssi_strip_all_tags()` getting a `null` parameter. -* Minor fix: Updating posts still used `relevanssi_update_doc_count()`, which can sometimes be really slow. -* Minor fix: Corrected misleading instructions about indexing AND synonyms. - -= 2.14.3 = -* Major fix: Post type weights did not work; improving the caching had broken them. -* Minor fix: 'Read all unread attachments' did not include 'key is not valid' errors. Now it rereads those attachments. -* Minor fix: Stops indexing error messages in WPML. -* Minor fix: Synonyms are now used for highlighting titles in AND searches if 'Index synonyms for AND searches' is enabled. -* Minor fix: Relevanssi works better with soft hyphens now, removing them in indexing and excerpt-building. - -= 2.14.2 = -* Major fix: Stops more problems with ACF custom field indexing. -* Major fix: Fixes a bug in search result caching that caused Relevanssi to make lots of unnecessary database queries. -* Minor fix: Pinning didn't work correctly when the post content indexing was disabled. Now the pinned words are included in the post title, if the post content is not available. - -= 2.14.1 = -* Major fix: Stops TypeError crashes from null custom field indexing. - -= 2.14.0 = -* New feature: New filter hook `relevanssi_excerpt_gap` lets you adjust the first line of excerpt optimization. -* New feature: Phrase matching now works also for taxonomy terms and user profiles. -* New feature: New filter hook `relevanssi_phrase_queries` can be used to add phrase matching queries to support more content types. -* New feature: New WP CLI command `wp relevanssi refresh` reindexes all posts (and only posts) without truncating the index first. This is very useful for regular reindexing of production sites, as the search won't stop working during the reindexing. -* New feature: New function `relevanssi_update_words_option()` can be used to update the `relevanssi_words` option directly, in case the AJAX update action fails for some reason. -* New feature: You can now reset the `relevanssi_words` cache option from the Relevanssi debugging settings tab. -* Changed behaviour: The `relevanssi_tag_before_tokenize` filter hook parameters were changed in order to be actually useful and to match what the filter hook is supposed to do. -* Changed behaviour: Relevanssi now automatically optimizes excerpt creation in long posts. You can still use `relevanssi_optimize_excerpts` for further optimization, but it's probably not necessary. -* Changed behaviour: The `relevanssi_admin_search_element` filter hook now gets the post object as the second parameter, rendering the filter hook more useful. -* Minor fix: WPML couldn't digest post type archives in the search results. Relevanssi now handles that and also takes errors from WPML more gracefully. -* Minor fix: Taxonomy terms in WPML were not indexed correctly. Instead of the post language, the current language was used, so if your admin dashboard is in English, German posts would get English translations of the terms, not German. This is now fixed. -* Minor fix: Excerpt creation is now faster when multiple excerpts are not used. -* Minor fix: The SEO plugin noindex setting did not actually work. That has been fixed now. -* Minor fix: Multisite searching didn't work correctly in HyperDB environments. -* Minor fix: Improved fringe cases in nested taxonomy queries. -* Minor fix: Indexing would remove content where less than or greater than symbols were interpreted as HTML tags. -* Minor fix: In some cases Relevanssi wouldn't highlight the last word of the title. This is more reliable now. -* Minor fix: Relevanssi will now add the `highlight` parameter only to search results, and not to other links on the search results page. -* Minor fix: Disables stemming for words that are inside phrases to make post part targeted searches more precise. - -= 2.13.1 = -* Major fix: User and taxonomy term search did not work correctly, thanks to a complicated mix of small issues that didn't show up in the automated testing. The problem was caused be `relevanssi_premium_get_post()` returning WP_Post objects for these non-posts, so the function is now returning stdClass objects again. -* Major fix: The type hinting introduced for some functions turned out to be too strict, causing fatal errors. The type hinting has been relaxed (using nullable types would help, but that's a PHP 7.4 feature, and we don't want that). - -= 2.13.0 = -* New feature: New filter hook `relevanssi_rendered_block` filters Gutenberg block content after the block has been rendered with `render_block()`. -* New feature: New filter hook `relevanssi_log_query` can be used to filter the search query before it's logged. This can be used to log instead the query that includes synonyms (available as a parameter to the filter hook). -* New feature: New filter hook `relevanssi_add_all_results` can be used to make Relevanssi add a list of all result IDs found to `$query->relevanssi_all_results`. Just make this hook return `true`. -* New feature: New filter hook `relevanssi_acceptable_hooks` can be used to adjust where in WP admin the Relevanssi admin javascripts are enqueued. -* New feature: Support for All-in-One SEO. Posts marked as 'Robots No Index' are not indexed by Relevanssi. -* New feature: New setting in advanced indexing settings to control whether Relevanssi respects the SEO plugin 'noindex' setting or not. -* Changed behaviour: Type hinting has been added to Relevanssi functions, which may cause errors if the filter functions are sloppy with data types. -* Changed behaviour: Relevanssi no longer logs queries with the added synonyms. You can use the `relevanssi_log_query` filter hook to return to the previous behaviour of logging the synonyms too. Thanks to Jan Willem Oostendorp. -* Changed behaviour: `relevanssi_the_title()` now supports the same parameters as `the_title()`, so you can just replace `the_title()` with it and keep everything else the same. The old behaviour is still supported. -* Changed behaviour: When using ACF and custom fields indexing set to 'all', Relevanssi will no longer index the meta fields (where the content begins with `field_`). -* Minor fix: In some cases, having less than or greater than symbols in PDF content would block that PDF content from being indexed. -* Minor fix: PDF content wasn't being indexed in some cases where custom field indexing was otherwise disabled. -* Minor fix: The Oxygen compatibility made it impossible to index other custom fields than the Oxygen `ct_builder_shortcodes`. This has been improved now. -* Minor fix: In Related posts, random posts from the same category could include duplicates of posts in the related posts. -* Minor fix: Old legacy scripts that caused Javascript warnings on admin pages have been removed. -* Minor fix: relevanssi_premium_get_post() always returns WP_Post objects now, never stdClass objects. -* Minor fix: The search results log export did not do anything useful when no data was found. Now the export provides a message "No search keywords logged". Thanks to Jan Willem Oostendorp. - -= 2.12.2 = -* New feature: You can force Relevanssi to be active by setting the query variable `relevanssi` to `true`. Thanks to Jan Willem Oostendorp. -* Changed behaviour: Relevanssi has been moved from `the_posts` filter to `posts_pre_query`. This change doesn't do much, but increases performance slightly as WordPress needs to do less useless work, as now the default query is no longer run. Thanks to Jan Willem Oostendorp. -* Minor fix: Highlighting didn't work properly when highlighting something immediately following a HTML tag. -* Minor fix: WPML search results that included non-post results caused fatal errors and crashes. This fixes the crashing and makes non-post results work better in both WPML and Polylang. -* Minor fix: Pinning could cause warnings when using `fields` and non-post results. -* Minor fix: Importing options broke synonym and stopword settings. -* Minor fix: Improves the Rank Math SEO compatibility to avoid errors in plugin activation. -* Minor fix: You can no longer set the value of minimum word length to less than 1 or higher than 9 from the settings page. - -= 2.12.1 = -* Major fix: The multilingual stopwords and synonyms were used based on the global language. Now when indexing posts, the post language is used instead of the global language. -* Minor fix: Fixes the broken AND indexing for synonyms. - -= 2.12.0 = -* New feature: Relevanssi now supports multilingual synonyms and stopwords. Relevanssi now has a different set of synonyms and stopwords for each language. This feature is compatible with WPML and Polylang. -* New feature: SEO by Rank Math compatibility is added: posts marked as 'noindex' with Rank Math are not indexed by Relevanssi. -* New feature: New filter hook `relevanssi_sidebar_capability` adjusts the minimum capability required for seeing the Gutenberg sidebar and the Classic editor metabox. Default value is `manage_options`, ie. Editor. -* Minor fix: Attachment weren't affected by `relevanssi_indexing_restriction` filters when a new attachment was added. Now the filters apply as they should. -* Minor fix: With keyword matching set to 'whole words' and the 'expand highlights' disabled, words that ended with an 's' weren't highlighted correctly. -* Minor fix: The 'Post exclusion' setting didn't work correctly. It has been fixed. -* Minor fix: It's now impossible to set negative weights in searching settings. They did not work as expected anyway. -* Minor fix: Contributors could see the Relevanssi Gutenberg sidebar, but it didn't work. Now the sidebar is only shown by default to Editors and above. -* Minor fix: Relevanssi had an unnecessary index on the `doc` column in the `wp_relevanssi` database table. It is now removed to save space. Thanks to Matthew Wang. -* Minor fix: Improved Oxygen Builder support makes sure `ct_builder_shortcodes` custom field is always indexed. - -= 2.11.1 = -* Changed behaviour: The `relevanssi_excerpt_part` filter hook now gets the post ID as a second parameter. The documentation for the filter has been fixed to match actual use: this filter is applied to the excerpt part after the highlighting and the ellipsis have been added. -* Changed behaviour: The `relevanssi_index_custom_fields` filter hook is no longer used when determining which custom fields are used for phrase searching. If you have a use case where this change matters, please contact us. -* Minor fix: The `relevanssi_excerpt` filter hook was removed in 2.11.0. It is now restored and behaves the way it did before, except that when doing multi-part excerpts, this filter is applied separately for each excerpt part. -* Minor fix: The debugging tab no longer shows the 'Buy Premium' note to Premium users. -* Minor fix: Avoids undefined variable warnings from the Pretty Links compatibility code. -* Minor fix: In Premium, phrase matching in custom fields didn't work correctly when the custom field indexing setting was 'all' or 'visible'. -* Minor fix: The Oxygen Builder compatibility has been improved. Now shortcodes in Oxygen Builder content are expanded, if that setting is enabled in Relevanssi settings. -* Minor fix: Adding new redirects when there were none was impossible. This is now fixed, and in a more future-proof way. -* Minor fix: The default value for the number of excerpts was 3. It's now 1. - -= 2.11.0 = -* New feature: There's now a "Debugging" tab in the Relevanssi settings, letting you see how the Relevanssi index sees posts. This is familiar to Premium users, but is now available in the free version as well. -* New feature: The SEO Framework plugin is now supported and posts set excluded from the search in SEO Framework settings will be excluded from the index. -* New feature: There's a new option, "Expand highlights". Enabling it makes Relevanssi expand partial-word highlights to cover the full word. This is useful when doing partial matching and when using a stemmer. -* New feature: Relevanssi can now generate excerpts that show multiple snippets from the post. You can adjust the number of excerpts displayed from the excerpt settings. Individual excerpt parts are wrapped in `span` tags with the class `excerpt_part` for styling. -* New feature: New filter hook `relevanssi_excerpt_part` allows you to modify the excerpt parts before they are combined together. -* New feature: New filter hook `relevanssi_excerpts` lets you filter the array of excerpts before the highlights are added. -* New feature: Relevanssi now supports an arbitrary number of levels in the `field_%_subfield_%_subfield` notation for flexible ACF fields. -* New feature: Improved compatibility with Oxygen Builder. Relevanssi automatically indexes the Oxygen Builder content and cleans it up. New filter hooks `relevanssi_oxygen_section_filters` and `relevanssi_oxygen_section_content` allow easier filtering of Oxygen content to eg. remove unwanted sections. -* Changed behaviour: The "Uncheck this for non-ASCII highlights" option has been removed. Highlights are now done in a slightly different way that should work in all cases, including for example Cyrillic text, thus this option is no longer necessary. -* Changed behaviour: The `index_pdfs` WP CLI command has been retired. It has been replaced with two separate commands: `remove_attachment_contents` removes all read attachment contents from the database and `read_attachments` reads all attachment content from files that haven't been read yet. -* Changed behaviour: Relevanssi excerpts are now wrapped in `span` tags. -* Minor fix: Removes the warning about non-numeric values when using a redirect for the first time. -* Minor fix: Fixes phrase searching using non-US alphabet. -* Minor fix: Sometimes the `relevanssi_user_index_ok` filter would get a user ID and not the object. This is now fixed: it's always an object. -* Minor fix: Excluding posts from the block editor didn't work properly: the post would be marked excluded, but would not actually be removed from the index until the next reindexing of the whole database. This works now as expected. -* Minor fix: Relevanssi would break admin searching for hierarchical post types. This is now fixed, Relevanssi won't do that anymore. -* Minor fix: Relevanssi indexing now survives better shortcodes that change the global `$post`. -* Minor fix: Warnings about missing `relevanssi_update_counts` function are now removed. -* Minor fix: Paid Membership Pro support now takes notice of the "filter queries" setting. -* Minor fix: OR logic didn't work correctly when two phrases both had the same word (for example "freedom of speech" and "free speech"). The search would always be an AND search in those cases. That has been fixed. -* Minor fix: Relevanssi no longer blocks the Pretty Links admin page search. -* Minor fix: The "Respect 'exclude_from_search'" setting did not work if no post type parameter was included in the search parameters. -* Minor fix: The category inclusion and exclusion setting checkboxes on the Searching tab didn't work. The setting was saved, but the checkboxes wouldn't appear. - -= 2.10.3 = -* New feature: Multisite searching now supports date parameters. -* New feature: Both `relevanssi_fuzzy_query` and `relevanssi_term_where` now get the current search term as a parameter. -* New feature: New filter hook `relevanssi_tabs` can be used to adjust the tabs in Relevanssi settings page to add, modify or delete the tabs. -* Major fix: The `post_relevanssi_related` action hook did not fire at all, causing possible problems if `pre_relevanssi_related` set something that `post_relevanssi_related` was supposed clear out. The default behaviour isn't a problem, but some custom solutions may be. -* Minor fix: Relevanssi database tables don't have PRIMARY keys, only UNIQUE keys. In case this is a problem (for example on Digital Ocean servers), deactivate and activate Relevanssi to fix the problem. -* Minor fix: When `posts_per_page` was set to -1, the `max_num_pages` was incorrectly set to the number of posts found. It should, of course, be 1. -* Minor fix: Excluding from logs didn't work if user IDs had spaces between them ('user_a, user_b'). This is now fixed for good, the earlier fix didn't work. -* Minor fix: When indexing, users are now counted in a different way, so that the `relevanssi_user_indexing_args` filter hook is applied and the count reflects the actual number of users indexed. - -= 2.10.2 = -* New feature: Wildcard operators ? (any one letter) and * (zero or more letters) can be used inside words, if enabled by setting the `relevanssi_wildcard_search` filter to `true`. -* New feature: New filter hook `relevanssi_term_where` lets you filter the term WHERE conditional for the search query. -* Minor fix: Doing the document count updates asynchronously caused problems in some cases (eg. importing posts). Now the document count is only updated after a full indexing and once per week. -* Minor fix: Phrase matching has been improved to make it possible to search for phrases that include characters like the ampersand. - -= 2.10.1 = -* New feature: New filter hook `relevanssi_didyoumean_alphabet` to replace the default Latin alphabet with something more suited to your site. -* Major fix: Changes in WooCommerce 4.4.0 broke the Relevanssi searches. This makes the WooCommerce search work again. -* Minor fix: Excluding from logs didn't work if user IDs had spaces between them ('user_a, user_b'). Now the extra spaces don't matter. -* Minor fix: The asynchronous doc count action in the previous version could cause an infinite loop with the Snitch logger plugin. This is prevented now: the async action doesn't run after indexing unless a post is actually indexed. -* Minor fix: Relevanssi indexing procedure was triggered for autosaved drafts, causing possible problems with the asynchronous doc count action. -* Minor fix: The `relevanssi_index_custom_fields` filter hook was not applied when doing phrase matching, thus phrases could not be found when they were in custom fields added with the filter. -* Minor fix: Apostrophes in redirect queries didn't work. That is now fixed and saving a query with an apostrophe works and will redirect. - -= 2.10.0 = -* Changed behaviour: Relevanssi now requires PHP 7. -* Changed behaviour: Relevanssi now sorts strings with strnatcasecmp() instead of strcasecmp(), leading to a more natural results with strings that include numbers. -* Changed behaviour: Relevanssi init is now moved from priority 10 to priority 1 on the `init` hook to avoid problems with missing TablePress compatibility. -* New feature: Content wrapped in the `noindex` tags is no longer used for excerpts. -* New feature: The `[et_pb_fullwidth_code]` shortcode is now removed completely, including the contents, when Relevanssi is indexing and building excerpts. -* New feature: Relevanssi now shows a warning when a multisite site is not public, as that will lead to no search results because Relevanssi doesn't search non-public sites. -* New feature: The redirects tab now shows the number of times each redirect has been used. -* Major fix: Relevanssi didn't index new comments when they were added; when a post was indexed or the whole index rebuilt, comment content was included. We don't know how long this bug has existed, but it is now fixed. Rebuild the index to get all comment content included in the index. -* Minor fix: Phrase matching did not work correctly in visible custom fields. -* Minor fix: TablePress support could cause halting errors if posts were inserted before Relevanssi has loaded itself (on `init` priority 10). These errors will no longer happen. -* Minor fix: Relevanssi only updates doc count on `relevanssi_insert_edit()` when the post is indexed. -* Minor fix: Counting document count is a slow process that has slowed down opening the indexing tab. It's now done asynchronously. Thanks to Mike Garrett. - -= 2.9.0 = -* New feature: New function `relevanssi_get_related_post_ids()` returns an array of related post IDs for a post. -* New feature: New function `relevanssi_get_related_post_objects()` returns an array of related post objects for a post. -* New feature: New filter hook `relevanssi_related_output_objects` is the same as `relevanssi_related_output` but for `relevanssi_get_related_post_objects()`. -* New feature: New filter hook `relevanssi_get_approved_comments_args` filters the arguments to `get_approved_comments` in comment indexing. This can be used to index custom comment types, for example. -* Changed behaviour: Relevanssi related posts code has been split into separate functions. The `relevanssi_related_posts()` functions like before, but if you don't want the HTML code, check the new functions. -* Deprecated: Using relevanssi_related_posts() with `$just_objects` or `$no_template` set to `true` is deprecated. Use `relevanssi_get_related_post_objects()` and `relevanssi_get_related_post_ids()` instead. -* Minor fix: The related posts transient field uses a different name for storing objects or HTML, to avoid problems in case both styles are used at the same time. -* Minor fix: Indexing subscriber profiles from the admin interface has stopped working at some point, likely due to some changes in WordPress. It is now noticed and fixed. -* Minor fix: If running in multisite environment, `relevanssi_get_post_status()` includes the blog ID in the cache key in addition to post ID to avoid clashes where same post ID in different blogs have different statuses. -* Minor fix: General improvements to the post caching in multisite environments. -* Minor fix: Options that are used in admin backend only are no longer autoloaded on every page load. - -= 2.8.2 = -* Minor fix: Using phrases in the post part targeting didn't work. It works much better now, but may still have some oddities in some cases. -* Minor fix: Media Library searches failed if Relevanssi was enabled in the WP admin, but the `attachment` post type wasn't indexed. Relevanssi will no longer block the default Media Library search in these cases. -* Minor fix: Adds more backwards compatibility for the `relevanssi_indexing_restriction` change, there's now an alert on indexing tab if there's a problem. - -= 2.8.1 = -* New feature: New filter hook `relevanssi_post_content_after_shortcodes` filters the post content after shortcodes have been processed but before the HTML tags are stripped. -* Minor fix: Adds more backwards compatibility for the `relevanssi_indexing_restriction` change. - -= 2.8.0 = -* New feature: New filter hook `relevanssi_block_to_render` makes it possible to filter Gutenberg blocks before they are rendered to HTML. -* New feature: New filter hook `relevanssi_admin_search_blocked_post_types` makes it easy to block Relevanssi from searching a specific post type in the admin dashboard. There's built-in support for Reusable Content Blocks `rc_blocks` post type, for example. -* New feature: Relevanssi metabox and the Gutenberg sidebar now show the reason why a post is not indexed. You can find the reason at the "How Relevanssi sees this post" feature. -* New feature: When creating excerpts Relevanssi tries to remove the disabled shortcodes. -* Changed behaviour: Relevanssi has been blocked in the admin Media Library searches since 2012. There seems to be no reason not to use Relevanssi there, so Relevanssi is now used for admin Media Library searches, if admin searching is enabled in the first place. -* Changed behaviour: Relevanssi now applies minimum word length when tokenizing search query terms. -* Changed behaviour: Content stopwords are removed from the search queries when doing excerpts and highlights. When Relevanssi uses the untokenized search terms for excerpt-building, stopwords are removed from those words. This should lead to better excerpts. -* Changed behaviour: The `relevanssi_indexing_restriction` filter hook has a changed format. Instead of a string value, the filter now expects an array with the MySQL query in the index 'mysql' and a reason in string format in 'reason'. There's some temporary backwards compatibility for this. -* Minor fix: Synonym indexing for AND searches didn't work for taxonomy terms. -* Minor fix: Post part targeting didn't work well with partial matching or numeric search terms. -* Minor fix: Using `post_parent` from the URL parameters didn't work. -* Minor fix: Improves handling of content stopwords in partial matched searches. -* Minor fix: Polylang filtered out users and taxonomy terms from the results in some cases. That's still implemented in a fairly hackish way, but it's been made more robust now. -* Minor fix: Improves handling of emoji in indexing. If the database supports emoji, they are allowed, otherwise they are encoded. -* Minor fix: The `relevanssi_words` option no longer autoloads (it's a big one). - -= 2.7.0 = -* Changed behaviour: Content stopwords are now applied to the attachment content. -* Changed behaviour: Phrases in OR search are now less restrictive. A search for 'foo "bar baz"' used to only return posts with the "bar baz" phrase, but now also posts with just the word 'foo' will be returned. -* Major fix: Fixes an error message in WP 4.9. -* Minor fix: Relevanssi included results from archived blogs in the multisite search results. -* Minor fix: User Access Manager showed drafts in search results for all users. This is now fixed. - -= 2.6.1 = -* Minor fix: When using Gutenberg, pinning interface only worked for posts. Now it works for all indexed post types. - -= 2.6.0 = -* New feature: New filter hook `relevanssi_disable_stopwords` can be used to disable stopwords completely. Just add a filter function that returns `true`. -* New feature: New filter hook `relevanssi_date_query_non_posts` can be used to allow users and taxonomy terms in searches with a date query. -* Changed behaviour: The `relevanssi_related_words` filter hook didn't get the post ID as parameter, which severely constricts its usability. That's now fixed: the filter gets the post ID as the second parameter. -* Changed behaviour: Stopwords are no longer automatically restored if emptied. It's now possible to empty the stopword list. If you want to restore the stopwords from the file (or from the database, if you're upgrading from an earlier version of Premium and find your stopwords missing), just click the button on the stopwords settings page that restores the stopwords. -* Changed behaviour: Changes to post weights in the `relevanssi_results` hook did not affect the relevance scores shown in excerpts. That's changed now, and the displayed scores are now taken from the `$doc_weight` array, which is returned in the return value array from `relevanssi_search()`. -* Changed behaviour: Excerpt length and type are now checked outside the loop that goes through the posts. This reduces the number of database calls, but the most important effect is that now multisite searches will always create the excerpts with the settings of the subsite where the search is made and not with the settings of the subsite of each post. -* Minor fix: Searching for regex special characters (for example parentheses, brackets) caused problems in excerpts. -* Minor fix: Phrase matching wasn't applied to PDF content if the "Custom fields to index" setting was set to "some". -* Minor fix: Indexing taxonomies from the WP CLI could leave old taxonomy terms in the index. This is now prevented. -* Minor fix: Improvements in handling highlighting for words with apostrophes. -* Minor fix: Disregard hanging commas at the end of post exclusion settings. -* Minor fix: Relevanssi was blocking post queries in WP CLI. That's now fixed. -* Minor fix: Sometimes excerpts wouldn't have an ellipsis in the beginning even though they should. -* Minor fix: The 'Add a redirect' button did not work if there were no redirects. - -= 2.5.2 = -* Major fix: Makes Relevanssi Premium compatible with WP 4.9. - -= 2.5.1 = -* Major fix: Returns the missing stopwords. - -= 2.5.0 = -* New feature: You can now edit the read attachment content on the attachment edit pages. -* New feature: It's now possible to exclude image attachments from the index with a simple setting on the indexing settings page. -* New feature: You can now redirect empty searches to a specific page instead of the search results template. You can choose the URL from the Redirect settings page. -* New feature: Relevanssi now has a shiny new Gutenberg sidebar that replaces the old Relevanssi Post Controls metabox when using the block editor. -* New feature: When new attachments are uploaded and Relevanssi is set to automatically read new attachments, that reading is now done as an asynchronous background process, so it won't slow down the media upload. -* New feature: Page builder short codes are now removed in Relevanssi indexing. This should reduce the amount of garbage data indexed for posts in Divi, Avada and other page builder themes. -* Changed behaviour: The `relevanssi_page_builder_shortcodes` filter hook is now applied both in indexing and excerpts, and has a second parameter that will inform you of the current context. -* Minor fix: Post type archive indexing doesn't stop the WP CLI indexing if there are no post type archives to index. -* Minor fix: Did you mean could occasionally cause long delays in searches. This was especially problematic in some object cache situations, when the transient didn't last as long as it should've been. Updating the Did you mean word list, which is a slow process, now happens asynchronously. -* Minor fix: Stopwords weren't case insensitive like they should. They are now. Also, stopwords are no longer stored in the `wp_relevanssi_stopwords` database table, but are now stored in the `relevanssi_stopwords` option. -* Minor fix: A comma at the end of the custom field indexing setting made Relevanssi index all custom fields. This doesn't happen anymore and trailing commas are automatically removed, too. -* Minor fix: Post type archive indexing could ran into problems when post types are added or removed. This should fix some of those problems. -* Minor fix: Accessibility improvements all around the admin interface. Screen reader support should be better, feel free to report any further ways to make this better. -* Minor fix: Doing searches without search terms and with the throttle disabled could cause problems. Relevanssi now makes sure throttle is always on when doing termless searches. -* Minor fix: Untokenized search terms are used for building excerpts, which makes highlighting in excerpts work better. - -= 2.4.4 = -* New feature: You can now give Gutenberg blocks a CSS class `relevanssi_noindex` to exclude them from being indexed. Relevanssi will not index Gutenberg blocks that have the class. -* New feature: You can now target specific parts of the post with search terms like `{post_tag:cat}`, `{title:word}`, `{author:mikko}`, `{customfield_name:value}` and so on. See [this Knowledge Base entry for more information](https://www.relevanssi.com/knowledge-base/search-targets/). -* New feature: Relevanssi automatically skips some custom fields from common plugins that only contain unnecessary metadata. -* New feature: Related posts keywords can now be restricted by taxonomy, so tags will only match to tags and not other parts of the post. This may lead to increased precision. -* New feature: The search results breakdown is added to the post objects and can be found in $post->relevanssi_hits. The data also includes new fields and the breakdown from the excerpt settings page can now show author, excerpt, custom field and MySQL column hits. -* New feature: Relevanssi can now index Ninja Tables table content. This is something of an experimental feature right now, feedback is welcome. -* New feature: New filter hook `relevanssi_indexing_query` filters the indexing query and is mostly interesting for debugging reasons. -* Minor fix: Deleted and trashed comment contents were not deindexed when the comment was removed. That has been corrected now. -* Minor fix: Phrase matching is now applied to attachments as well, including the attachments indexed for parent post. -* Minor fix: Phrase matching only looks at custom fields that are indexed by Relevanssi. -* Minor fix: Exact match bonus now uses the original query without synonyms added for the exact match check. -* Minor fix: Paid Membership Pro filtering is only applied to published posts to prevent drafts from showing up in the search results. -* Minor fix: Indexing internal links for target documents could cause documents to go unindexed. This has now been fixed. If you use internal link indexing, rebuild the index after you update. -* Minor fix: Relevanssi could stop plugin information retrieval for other plugins fail. This has been fixed. - -= 2.4.3 = -* Major fix: Disabling `update_post_metadata_cache` seemed like a good optimization move for related posts, but it turns out it disables related posts thumbnails. We'll take weaker performance with working images. -* Major fix: Importing options caused WordPress to crash, because related posts and redirect settings were handled incorrectly in the import. -* Minor fix: The Polylang compatibility filter didn't return correct post objects if fields was set to `ids` or `id=>parent`. Now the filter function returns correct type of result. -* Minor fix: Enabling the related posts checkbox did not activate the number of months setting. - -= 2.4.2 = -* New feature: New filter hook `relevanssi_indexing_adjust` can be used to stop Relevanssi from adjusting the number of posts indexed at once during the indexing. -* New feature: New filter hook `relevanssi_acf_field_value` filters ACF field values before they are indexed. -* New feature: New filter hook `relevanssi_disabled_shortcodes` filters the array containing shortcodes that are disabled when indexing. -* Removed feature: The `relevanssi_indexing_limit` option wasn't really used anymore, so it has been removed. -* Changed behaviour: Indexing exclusions from Relevanssi settings, Yoast SEO and SEOPress are applied in a different way in the indexing, making for a smoother indexing process. -* Changed behaviour: WP Table Reloaded support has been removed; you really shouldn't be using WP Table Reloaded anymore. -* Changed behaviour: Related posts doesn't even try doing an AND search anymore, as most of the time it was a waste of time. If you need that, using the `relevanssi_related_args` filter hook to swap the operator is still possible. -* Major fix: Related posts generation performance has been improved. -* Major fix: Related posts didn't work if multisite searching was enabled. That error has been eliminated. The related posts will come from the same subsite as the original post. -* Minor fix: Relevanssi won't choke on ACF fields with array or object values anymore. -* Minor fix: While you could set the Related posts to show random posts from the same category, the setting wouldn't appear correctly on the settings page. That has been fixed. -* Minor fix: The settings export now includes couple of missing parts, like the related posts settings. -* Minor fix: Relevanssi uninstall process left couple of Relevanssi options in the database. -* Minor fix: WPML language filter didn't work when `fields` was set to `ids` or `id=>parent`. - -= 2.4.1 = -* New feature: SEOPress support, posts marked "noindex" in SEOPress are no longer indexed by Relevanssi by default. -* Removed feature: Multi-taxonomy restrictions with `&taxonomy=post_tag|category&term=tag_term|cat_term` format has stopped working, apparently long time ago. Looks like nobody missed it. -* Changed behaviour: Membership plugin compatibility is removed from `relevanssi_default_post_ok` function and has been moved to individual compatibility functions for each supported membership plugin. This makes it much easier to for example disable the membership plugin features if required. -* Minor fix: The `searchform` shortcode now works better with different kinds of search forms. -* Minor fix: Yoast SEO compatibility won't block indexing of posts with explicitly allowed indexing. -* Minor fix: The `relevanssi_the_tags()` function printed out plain text, not HTML code like it should. The function now also accepts the post ID as a parameter. -* Minor fix: Excerpt creation and highlighting have been improved a little. - -= 2.4.0 = -* New feature: Multi-phrase searches now respect AND and OR operators. If multiple phrases are included in an OR search, any posts with at least one phrase will be included. In AND search, all phrases must be included. -* New feature: Admin search has been improved: there's a post type dropdown and the search is triggered when you press enter. The debug information has a `div` tag around it with the id `debugging`, so you can hide them with CSS if you want to. The numbering of results also makes more sense. -* New feature: The date parameters (`year`, `monthnum`, `w`, `day`, `hour`, `minute`, `second`, `m`) are now supported. -* New feature: New filter hook `relevanssi_file_content` filters the file content before it's saved in the `_relevanssi_pdf_content` custom field. -* New feature: New filter hook `relevanssi_related_args` filters the related posts search arguments. -* New feature: You can now set a month restriction to show only recent posts in the related posts. For more fine-grained date control, use the `relevanssi_related_args` filter hook. -* New feature: Instead of fully random posts, you can choose to get random posts from the same category if no proper matches are found for related posts. -* New feature: New filter hook `relevanssi_indexing_limit` filters the default number of posts to index (10). If you have issues with indexing timing out, you can try adjusting this to a smaller number like 5 or 1. -* New feature: Support for Paid Membership Pro added. -* New feature: WordPress SEO support, posts marked "noindex" in WordPress SEO are no longer indexed by Relevanssi by default. -* Removed feature: qTranslate is no longer supported. -* Major fix: Updates work when API key is in single site settings in a multisite environment. In 2.3.0, it is required that the key is in the multisite settings, otherwise updates won't work in multisite. -* Major fix: Tax query searching had some bugs in it, manifesting especially into Polylang not limiting the languages correctly. Some problems with the test suites were found and fixed, and similar problems won't happen again. -* Minor fix: Admin search only shows pinning and editing options to users with enough capabilities to use them. -* Minor fix: Phrase searching now uses filterable post statuses instead of a hard-coded set of post statuses. -* Minor fix: When saving an API key on a single site in multisite environment, the key appears to be saved. (In 2.3.0 it was saved, but it didn't look like it.) -* Minor fix: The plugin action links were missing on the Plugins page list, they're back now. -* Minor fix: Synonym indexing has been fixed, it could prevent saving of posts when synonym list was empty. -* Minor fix: Setting the `post_type` parameter to `post_type` to get post type archive pages now works. -* Minor fix: In some cases, Relevanssi might complain when uploading files. -* Minor fix: Missing action links were returned to the plugins list. -* Minor fix: Wrinkles in the upgrade process from free to Premium were ironed out. -* Minor fix: Search terms with slashes won't cause errors anymore. -* Minor fix: Relevanssi admin pages have been examined for accessibility and form labels have been improved in many places. -* Deprecated: `relevanssi_get_term_taxonomy()` function is deprecated and will be removed at some point in the future. - -= 2.3.0 = -* New feature: Content stopwords are just like regular stopwords, but they are only applied to post content. They are not applied to titles, custom fields or other places. -* New feature: The search form shortcode has a new parameter `dropdown` which can be used to add a category dropdown, like this: `[searchform dropdown="category"]`. -* New feature: Relevanssi can now use the contents of the PDF files indexed with WP File Download. -* New feature: Related posts can now be used in a different way. Instead of storing rendered HTML in the transients, Relevanssi can now store just the post objects for the related posts. -* New feature: Related posts WP CLI command has new parameters: just_objects activates the post object transients, post_type only generates the related posts for a particular post type. -* New feature: You can now pin and unpin posts from the Admin search. Just do a search and you can then easily pin posts for that search term. -* New feature: Relevanssi now supports User Access Manager permission controls. -* New filter: `relevanssi_indexing_tokens` can be used to filter the tokens (individual words) before they are indexed. -* Removed filter: `relevanssi_default_meta_query_relation` did not have any effect anymore. -* Changed behaviour: The default taxonomy relation was set to AND in 2.2.5, but wasn't properly applied before. Now it is really switched. -* Changed behaviour: Relevanssi now uses the `relevanssi_indexing_tokens` filter hook to add synonyms, which means adding lots of synonyms is much faster than before, and synonyms are now applied to all indexed content. -* Changed behaviour: New post types have been added to list of forbidden post types Relevanssi won't show as indexing options (ACF, TablePress and WooCommerce). -* Changed behaviour: Related posts templates are no longer generated when posts are saved. There are cases where generating the templates in admin context cause problems. The templates will be generated the first time the post is opened. -* Major fix: Tax query processing has been completely refactored, eliminating all sorts of bugs, especially with various edge cases. -* Major fix: Gutenberg block indexing only worked with the Gutenberg plugin enabled. It now works with WP 5.0 built-in Gutenberg as well. If you use Gutenberg blocks, reindex to get all the block content in the index. -* Major fix: Excerpt-building and highlighting did not respect the "Keyword matching" setting. They do now, and the excerpts should be better now. -* Major fix: AND searches needed queries that could get too long for the database to handle. This has been fixed and optimized. -* Major fix: Post exclusion (negative pinning) didn't work properly in multisite context. -* Major fix: Taxonomy term subquery relations didn't work; now they are applied. -* Major fix: Saving related posts exclusion settings wasn't possible. -* Minor fix: Authors can search for their own private posts. -* Minor fix: API key setting field behaviour has been improved. -* Minor fix: iOS uses curly quotes by default, and that didn't work as a phrase operator. Now phrase operator works with curly quotes and straight quotes. -* Minor fix: The free version Did you mean broke with search terms longer than 255 characters. -* Minor fix: Relevanssi won't create empty pinning meta fields anymore. -* Minor fix: Phrases with numbers and one word like "team 17" didn't work, because numbers weren't counted as words. -* Minor fix: $post->relevanssi_pinned wasn't set correctly for pinned posts. -* Minor fix: Relevanssi handles errors better in multisite searching when you search for a taxonomy that doesn't exist on the current site. - -= 2.2.5 = -* EXISTS and NOT EXISTS didn't work for taxonomy terms in searches. -* WPML post type handling has been improved. If post type allows fallback for default language, Relevanssi will support that. -* Relevanssi now reminds you to set up automatic trimming for the logs. It's a really good idea, otherwise the logs will become bloated, which will hurt search performance. -* New filter: `relevanssi_user_indexing_args` lets you adjust the arguments for the user indexing query, making easy for example to adjust which user roles are indexed. -* API keys are handled better in single installations on multisites. -* The pinning query is significantly faster. -* In some cases, the related posts feature could show wrong number of posts. That's now fixed. -* The Groups posts filter is only applied to public posts to avoid drafts being shown to people who shouldn't see them. -* The `posts_per_page` query variable didn't work; it's now added to the introduced query variables so that it works. -* Relevanssi won't log empty queries anymore. -* WP CLI searches were disabled when Relevanssi is active; it should work now. -* New filter: `relevanssi_pdf_for_parent_query` lets you adjust the MySQL query for fetching PDFs to index with the parent post. -* New filter: `relevanssi_pdf_for_parent_insert_data` lets you manipulate the INSERT data for PDFs indexed with the parent post. -* The default tax query relation was switched from OR to AND to match the WP_Query default behaviour. -* Gutenberg can cause duplicated postmeta fields for pinning and unpinning. Relevanssi will now remove the duplicate post meta when the post is saved. -* When used with WP 5.1, Relevanssi will now use `wp_insert_site` instead of the now-deprecated `wpmu_new_blog`. -* Multisite blog creation is handled better in WP 5.1+. -* Relevanssi now supports Restrict Content Pro permissions. -* The Relevanssi metabox is now only shown for indexed post types. - -= 2.2.4.2 = -* Fixes couple of JS issues with the metabox scripts. -* Improves meta key sorting. -* New actions: `pre_relevanssi_related` is triggered before related posts searches and `post_relevanssi_related` after the searches. - -= 2.2.4.1 = -* It's now possible to disable thumbnails and titles for related posts. -* The related posts custom template is looked for in the right place. -* Metabox buttons work without Gutenberg. -* Drafts shouldn't appear in the related posts anymore. -* Choosing the default thumbnail for related posts is more pleasant now. -* You can now disable auto-appended related posts for a post. -* You can disable a post so that it won't appear as a related post. - -= 2.2.4 = -* New Related posts feature can be used to display related posts for your content. -* Relevanssi metabox on post edit pages is now in the sidebar by default. It doesn't move automatically on older installations, but you can drag it there. It's recommended, as from now on the look will be designed for sidebar use. -* Search performance has been improved. -* Redirects have been improved a bit. -* Multisite searching was broken when sorting posts. -* Using period as a thousands separator could cause weird results. -* Members plugin compatibility has been improved: it's only used if the 'content permissions' feature has been enabled. -* New JetPack taxonomies and post types have been added to the block list so they won't appear in Relevanssi settings. -* Attachment indexing will bypass zip files. -* New filter: `relevanssi_accept_mime_type` lets you filter attachment reading by MIME type. -* New filter: `relevanssi_do_not_read` lets you filter attachment reading by post ID. -* API key field was not shown if Relevanssi was installed on a single site in a multisite network. Now it's shown correctly. -* New filter: `relevanssi_search_form` works exactly like `get_search_form`, but only applies to the Relevanssi shortcode search forms. -* Relevanssi settings page won't let you exclude categories you have restricted the search to. - -= 2.2.3.1 = -* The new Redirects feature caused unforeseen consequences. This version should fix them. - -= 2.2.3 = -* New Redirects feature lets you redirect keywords directly to specific result pages. -* Choosing "CSS Style" for highlighting was not possible. That is now fixed. -* Gutenberg reusable block indexing was fatally broken with the latest Gutenberg version. That has been updated. -* Relevanssi now by default respects the WooCommerce "exclude from search" setting. -* `post__not_in` still didn't work properly, it does now. -* New filter: `relevanssi_comparison_order` can be used to define the sorting order when sorting the results by post type. -* English stemmer has been improved a bit. -* "Did you mean" process included a very slow query. It is now cached, leading in some cases to massive performance improvements (we're talking about several seconds here). -* Highlights inside `code` and similar blocks are handled better now. - -= 2.2.2.1 = -* Fixed broken "User searches" page. -* "How Relevanssi sees this post" is hidden by default. - -= 2.2.2 = -* Relevanssi can now index Gutenberg reusable blocks. (This functionality broke once already before release, so that can happen, since Gutenberg is still in very active development.) -* The `post__in` and `post__not_in` parameters didn't work, and are now fixed. `post_parent__in` and `post_parent__not_in` are also improved. -* You can use named meta queries for sorting posts. Meta query sorting is improved in other ways as well. -* Log export didn't work properly. -* The `relevanssi_premium_get_post()` now has a default value (-1) for the blog ID. -* Adding stopwords from the common word list has been fixed. -* The `relevanssi_get_words_having` filter hook is now also applied to the free version Did you mean queries. -* New filters: `relevanssi_1day` and `relevanssi_7days` can be used to adjust the number of days for log displays, so instead of 1, 7 and 30 days you can have anything you want. - -= 2.2.1 = -* The admin search has been moved to a separate page and made visible to editors, authors and contributors. -* New filter: `relevanssi_admin_search_capability` can be used to adjust who sees the admin search page. -* "How Relevanssi sees the post" feature on post edit screens actually works now. -* Numeric meta values (`meta_value_num`) are now sorted as numbers and not strings. - -= 2.2.0.1 = -* 2.2 claimed to be version 2.1.7. - -= 2.2 = -* New feature: Search tab on Relevanssi settings page allows you to perform searches in WP admin using Relevanssi. -* New feature: Post type archives can now be indexed. This will index the label and the description of the post type. -* New feature: Relevanssi now has a privacy mode that blocks outside connections: at the moment that means update checks and indexing attachments with Relevanssi indexing services. This helps keep your site private and can in some configurations speed up plugin page loads a lot. -* New feature: On post edit screens, you can now see how Relevanssi sees the post. This should help debugging indexing issues. -* New feature: You can now export the search log as a CSV file. -* New filter: `relevanssi_entities_inside_pre` and `relevanssi_entities_inside_code` adjust how HTML entities are handled inside `pre` and `code` tags. -* New filter: `relevanssi_attachment_server_url` allows the use of custom attachment reading server. -* User meta fields are indexed as custom fields, not as post content, and the `customfield_detail` column is also filled. -* Pinned posts have `$post->relevanssi_pinned` set to 1 for debugging purposes, but you can also use this for styling the posts in the search results templates. -* Multisite searching updates: exact match bonus and the recency bonus did not work in multisite searches. Now they work. -* Multisite search also had quite a few bugs squashed. -* The basic Did you mean feature has been toned down a bit, to make the suggestions slightly less weird in some cases. -* Post parent parameters now accept 0 as a value, making it easier to search for children of any post or posts without a parent. -* Pinning caused an error message when `fields` was set to `ids`. Now the behaviour is correct, and the pinning code also won't run, unless something is pinned. -* Taxonomy terms and users are handled better in multi-word AND searches. - -= 2.1.7 = -* The API key option in the network options wasn't very intuitive. It's better now. -* Direct attachment links in search results work better now, especially in cases where the site has moved. -* Improved handling of certain edge cases in taxonomy search. -* Home page links were getting the highlight parameter even though they shouldn't. This has been fixed. -* The Import / Export options tab was missing (very few people complained, so perhaps that feature is not very important...). -* The status of the 'Index PDF contents for parent post' option didn't show up correctly on the settings page. -* Added support for WP JV Post Reading Groups. -* Improved handling of HTML entities. -* Events Made Easy Calendar shortcodes are now removed when building excerpts. -* `set_time_limit()` was removed from the indexing; it's no longer necessary, and it can break the indexing on sites that don't allow the use of the function. -* `relevanssi_post_title_before_tokenize` filter was moved a bit so that it's the last thing that runs before tokenizing. -* When indexing custom MySQL column data, stopwords and minimum word length weren't applied properly. -* Disabled shortcodes are handled better in the indexing: the shortcode names won't be indexed anymore like they were before. -* Fix for pinning in multisite context. -* Made sure there won't be a warning for non-numeric values when searching. -* Removed unnecessary post types from the weight setting list. -* New filter: `relevanssi_clean_excerpt` lets you remove unwanted highlights from excerpts. -* Highlighting works better with `pre` and `code` tags. -* New filter: `relevanssi_comment_author_to_index` lets you filter comment author names before indexing. -* `relevanssi_comment_content_to_index` doesn't include the comment author name anymore. - -= 2.1.6.1 = -* The privacy features caused an error notice with certain Relevanssi configurations, and the plugin required WP 4.9.6. - -= 2.1.6 = -* Privacy: If you log search queries, Relevanssi will suggest some additional content to your privacy policy page. -* Privacy: Relevanssi now supports the new Privacy Policy and Personal Data tools in WordPress 4.9.6. -* Improved Polylang support. Now taxonomy terms can be language filtered as well. -* Saving synonyms with quotes worked, but the synonyms showed up wrong. -* Taxonomy term indexing had a bug where the `type` column for taxonomy terms would be set to 0. -* The `relevanssi_user_index_ok` filter is now applied when users are updated. -* Relevanssi could in some situations override navigation menu links with links to the user profiles or taxonomy terms found in the search. This update fixes that behaviour. -* Random order works again; using orderby `rand` didn't work properly. The `rand(seed)` format is also supported now. -* Fixed quotes and apostrophes in Did you mean suggestions. - -= 2.1.5 = -* New feature: WooCommerce product visibility can now be considered better in the indexing. See the filter hook 'relevanssi_woocommerce_indexing' for more details. -* Phrases were not highlighted correctly on documents. This is now fixed. -* Shortcode fix: 'wp_show_posts' shouldn't cause problems anymore. -* Fix for post tag indexing issues. -* MemberPress post controls were loose and showed drafts to searchers. That is now fixed. -* Highlighting was too loose, even if matching was set to whole words. -* Highlighting now works better in cases where there's a hyphen or an apostrophe inside a word. - -= 2.1.4 = -* Fixed cases where Relevanssi added an ellipsis even if the excerpt was from the start of the post. -* Highlighting now works with numeric search strings. -* Improved highlighting for accented words. Thanks to Paul Ryan. -* A surplus comma at the end of post exclusion setting won't break the search anymore. -* Fixed instructions for adjusting the throttle limit. -* New "Pin this post for all keywords" feature. - -= 2.1.3 = -* Recent post bonus is now applied to searches. -* Exact term setting can now be disabled. -* Users of Members plugin would have drafts appear in search results. This is now fixed. -* Pinned keywords would appear in the list of exlusion keywords, and you couldn't set exclusion keywords. That is now corrected. -* "Index unindexed posts" works better. -* Removing quotes and apostrophes in indexing didn't work properly. -* Attachment indexing progress meter fixed. -* The "Highlight from external searches" option was removed. It's not supported by Google or Bing anymore, so there's little point in keeping it. - -= 2.1.2 = -* MemberPress post control was backwards. -* Fusion Builder shortcodes are automatically removed from excerpts. -* Indexing failed, when a same word appeared in two different taxonomies. -* Internal link management had a bit of a bug in the indexing. -* User searches page reset buttons fixed. - -= 2.1.1.1 = -* Fixes an issue where you can't save taxonomy indexing settings. - -= 2.1.1 = -* Automated testing can't catch everything... There was some overzealous security in place, breaking Network options. That is now fixed. -* Attachment file name is not prepended to the excerpts automatically. - -= 2.1 = -* Relevanssi code has been reviewed and modified to follow WordPress coding standards. As a result, there have been minor improvements all around the code to make things more robust and secure. -* Attachment indexing has been extended to many more document types: now it should be able to handle most document types, including Office and OpenDocument formats. It's also slightly faster. -* There's now an option to do attachment reading in an EU-based server. -* Custom field detail is no longer serialized. It's now JSON. If you use custom field detail, rebuild the index and change your code to use json_decode() instead of unserialize(). -* `relevanssi_the_tags()` and `relevanssi_get_the_tags()` now have different set of parameters, more in line with `the_tags()` and `get_the_tags()`. -* Taxonomy indexing settings were emptied out if you saved another options tab. That is now fixed. -* Improvements to WPML support; WPML is now less likely to be confused in multisite searches. -* Updated filter: `relevanssi_search_ok` now gets the WP_Query object as a parameter, which is helpful if you're not using the global $wp_query. -* ACF Flexible Content field indexing didn't work properly, possibly due to a change in ACF. That should now work better. - -= 2.0.5 = -* Fixed a bug in "Did you mean" suggestions. -* Paid Member Subscription shortcode compatibility. -* Indexing works better when there are plenty of excluded posts. -* Ampersand handling works better in titles. -* Relevanssi won't add the `highlight` parameter to links pointing to the front page anymore (because that makes those links point to the blog page). -* There's less need for `relevanssi_get_permalink()` now, as Relevanssi can adjust the links printed out with `get_permalink()`. -* The [searchform] shortcode can now take parameters, for example: `[searchform post_types="page"]` will print out a search form that only searches pages. -* Small improvement for excerpt-building, thanks to ___ _______. - -= 2.0.4 = -* Fixed filter: `relevanssi_custom_field_value` didn't get the post ID correctly. -* Relevanssi used `sanitize_hex_color`, which isn't actually reliably available. -* Multisite searches didn't support `orderby` and `order` parameters. -* Did you mean suggestions have been improved. -* New filter: `relevanssi_do_not_index_term` lets you control whether or not taxonomy terms are indexed. -* Single-word phrases are not allowed anymore, as they do no good. They are silently converted to non-phrases now. -* `relevanssi_get_permalink` doesn't add the `highlight` parameter to URLs outside search results pages anymore. -* Setting post type or post content weight to 0 didn't work. -* Search form shortcode echoed out the search form, instead of returning it as it should. -* Gravity Forms shortcode is now disabled in Relevanssi indexing. -* ACF repeater field indexing doesn't break if you try to index multilevel repeaters (that still won't work, but it won't break everything either). -* HTML tags are stripped from post excerpts when using the excerpt to build Relevanssi excerpts. -* User indexing is now done in steps, after it turned out to be impossible to index 16,000 users at once. -* New filter: `relevanssi_excerpt_query` filters the search query before building excerpts. -* New option: if you choose to hide Relevanssi from post edit pages, you can allow admins to see the Relevanssi post controls. - -= 2.0.3.1 = -* There was a small error in the multisite installation procedure, now fixed. - -= 2.0.3 = -* Uninstalling Relevanssi was broken. That is now fixed. -* In some cases excerpt-building could take ages because of autoembed link discovery. Relevanssi now blocks the autoembed procedure in link-building. -* © and ® symbols caused problems in indexing; they are now included in the default punctuation removal. -* Fixed filter: `relevanssi_pdf_read_timeout` wasn't applied to all cases of timeouts. -* Updated filter: `relevanssi_index_custom_fields` now gets a second parameter that contains the post ID. -* New filter: `relevanssi_custom_field_value` is used to filter custom field values both before indexing and before excerpt-building. Parameters include the field name and the post ID. -* Indexing PDF content didn't work properly if Relevanssi was set to index visible custom fields. -* There was a bug in importing the options. -* New setting can be enabled to read in the contents of new PDF files as they are uploaded on the site. This is disabled by default. - -= 2.0.2 = -* New filter: `relevanssi_multisite_public_status` lets you make non-public multisite subsites available in the search. -* New filter: `relevanssi_pdf_read_timeout` lets you increase the PDF reading timeout from the default value of 45 seconds. -* Deprecated filter: `relevanssi_index_taxonomies_args` is no longer used, because Relevanssi doesn't use `get_terms()` anymore in taxonomy term indexing. -* New filter: `relevanssi_hide_empty_terms` can be used instead of `relevanssi_index_taxonomies_args` to include empty taxonomy terms in indexing. Defaults to `true`, set to `false` to include taxonomy terms that are not attached to any posts. -* Taxonomy term indexing is now done in small steps to prevent timeout issues when indexing large numbers of taxonomy terms. -* Improvements to the Polylang setting. -* PDFs were always indexed for the parent post, never mind the value of the option. - -= 2.0.1 = -* Fixes a fatal error that happened with older PHP versions. - -= 2.0 = -* Legacy code has been removed. If you have a version older than 1.16, update first to 1.16.x to guarantee smooth upgrade process. -* This version includes a small database change, so if you're updating from a previous version, after the update deactivate the plugin and then reactivate. -* Improved indexing: no more clicking "Continue indexing" again and again! -* Settings pages have been completely rewritten. -* There's documentation in the WordPress contextual help: just click Help on the top right corner. -* Better Polylang support. A new option to remove the Polylang language filter. -* Logs can be automatically trimmed. Old log entries are removed to save space. -* Finally a setting to adjust content weight! -* Excerpts can use the custom field content. -* Highlighting in documents is changed: it now requires a `highlight` query parameter. This helps getting pass caching and makes the highlighting more reliable. To get the query parameter active, use `relevanssi_get_permalink()` to print out the permalinks on the search results templates. -* Relevanssi added synonyms to highlighting even if synonyms were not used for searching. In some cases, synonyms were added twice. -* The User Searches page got a makeover, too. -* Relevanssi is automatically disabled in REST API searches. -* Groups and Simple Membership support has been improved. -* Sorting search results is now up to 300 times faster than before. -* Lots of improvements all over the place. -* New filter: `relevanssi_excerpt_custom_field_content` lets you modify custom field content that is used for excerpts. -* New filter: `relevanssi_punctuation_filter` allows for easy modification of punctuation handling. -* New filter: `relevanssi_default_punctuation_replacement` changes the default way to handle the rest of the punctuation. -* New filter: `relevanssi_search_again` lets you run the search again if no results are found and to modify the parameters between search runs. -* New filter: `relevanssi_fallback` allows you to do fallback searches. -* New filter: `relevanssi_page_builder_shortcodes` lets you control which page builder shortcodes Relevanssi removes before building the excerpts. -* New filter: `relevanssi_optimize_excerpts` makes excerpt-building faster, if you make the filter return `true`. -* New query variable: set `include_attachments` to `0`, `off` or `false` to exclude attachments from the search. - -= 1.16.2.1 = -* Fixing a bug in the sorting algorithm. - -= 1.16.2 = -* ACF repeater fields with dashes didn't work; that is now fixed. -* Simple Membership plugin is now supported automatically to restrict access to posts. -* Relevanssi can now handle orderby parameter in array format. -* Relevanssi now blocks Easy Digital Downloads shortcodes when indexing to improve compatibility with EDD. -* When using `fields` to only fetch post IDs, Relevanssi doesn't try to highlight post titles. -* New action: `relevanssi_update_options` lets you adjust Relevanssi options immediately after the defaults are set. -* Remove notices about duplicated database columns when installing the plugin. - -= 1.16.1 = -* SECURITY: This version fixes a SQL injection vulnerability, where a site admin could theoretically inject SQL code into Relevanssi search queries. Doing this required access to Relevanssi settings page and in my tests, I couldn't do any damage, just break the Relevanssi search, but in any case, this vulnerability is now fixed. -* Multisite meta queries didn't work properly. -* Search and Filter shortcode is added to the blacklist. -* Groups plugin is now supported automatically to restrict access to posts. -* The filter `relevanssi_index_custom_fields` now works even if the custom field setting is empty. -* The filter `relevanssi_tax_term_additional_content` now works even when the taxonomy description is empty. -* Relevanssi taxonomy term indexing is moved to a later priority (from 10 to 9999) to make sure all term data is available for indexing. -* The filter `relevanssi_post_to_index` now has a second parameter. For posts, it simply repeats the post object, but for taxonomy terms, it has the term object. - -= 1.16.0.1 = -* Fixes "unknown column" issues in multisite searches. -* Removes errors when trying to search a multisite subsite that doesn't have Relevanssi. -* Small fix to make automatic updates work better in a multisite environment. - -= 1.16.0 = -* Changed a bit how Relevanssi attaches itself to queries. Instead of the global $wp_query, Relevanssi now uses the query passed as the parameter to `the_posts` filter hook. This should improve compatibility in some cases, but may cause problems in some fringe cases. If you're doing something unusual with Relevanssi, try this out before deploying to public use. -* Internal link processing had some minor issues, which are now straightened out. -* Some meta queries caused major problems with the Relevanssi weighting algorithm. This has now been fixed. -* Error notices caused by trying to use a non-existing taxonomy term have been removed. - -= 1.15.4 = -* Improved performance of multisite queries. -* Copying settings between multisite sites didn't work in networks of over 100 sites. Now the limit is 2000. -* Post type exclusion didn't work as expected. -* Relevanssi couldn't handle nested tax queries (such as those generated by WooCommerce product visibility filtering) properly. -* Fake posts created for taxonomy terms now include the parent in $post->post_parent. -* Doing a quick edit cleaned out the Relevanssi post controls settings. - -= 1.15.3.1 = -* New filter: `relevanssi_allow_one_letter_highlights` lets you allow one-letter highlights. Just make the filter function return `true`. -* New filter: `relevanssi_block_one_letter_searches` by default blocks one-letter searches. If you want to enable them, add a filter function that always returns `false`. -* Fixed an undefined variable notice. - -= 1.15.3 = -* Multisite search won't attempt to search in blogs that don't exist or are deleted or marked spam. -* Synonym indexing failed if synonyms contained a forward slash. -* Highlighting HTML tags has been improved further. -* New filter: `relevanssi_tag_before_tokenize` allows you to access tag content before indexing. -* Improvements to taxonomy terms and post type parameters. Now if you set a post type parameter, taxonomy terms or user profiles are not included in the search. In order to see taxonomy terms in the search results when using `post_types` parameter, add the taxonomy name (or `user`) to the `post_types` parameter. This does not work with the default `post_type` parameter. -* Relevanssi now actively blocks one-letter search terms, as they are generally pointless and can cause "out of memory" issues. One-letter search terms are no longer highlighted, either. These are usually caused by cases like "word's" being interpreted as "word s". -* New filter: `relevanssi_disable_shortcodes_excerpt` lets you add more shortcodes to be disabled before excerpts are built. -* Relevanssi now indexes taxonomy terms whenever they are created. -* Relevanssi now supports `fieldname_%_subfieldname` notation for ACF repeater fields in "Custom fields to index" settings. - -= 1.15.2.1 = -* An extra parentheses killed the WP CLI indexing. - -= 1.15.2 = -* When a taxonomy term was saved, Relevanssi didn't record the changes correctly. -* New WP CLI commands to index only users or taxonomies. -* Improved the way highlighting handles HTML tags, especially when highlighting on post pages. -* Relevanssi didn't remove taxonomy term data from the index properly. I recommend rebuilding the taxonomy terms (which you can do easily with the new WP CLI command `wp relevanssi index --target=taxonomies`). -* The throttle limit setting was removed from the settings page for causing trouble. If you need to change it, update `relevanssi_throttle_limit` option directly. -* The "Did you mean" function should return slightly more relevant results. -* The `relevanssi_get_words_query` filter hook has been retired and replaced with new `relevanssi_get_words_having` filter hook, used to adjust the value. The default value is 1, and there's usually no reason to adjust that. -* FacetWP users ran into trouble, as `relevanssi_do_query()` started to explicitly expect a WP_Query object in version 1.15.0. That expectation is removed; it's still highly recommended for future compatibility that you use WP_Query objects. -* Small bug fix: `get_current_screen()` is now only used when it's available to avoid occasional fatal errors. -* Error messages from `DOING_AJAX` being undefined should be removed. - -= 1.15.1 = -* Enabling "Index synonyms" setting with an empty synonym list caused post content and title indexing to fail. -* Wrong pages creeping into navigation menus from multisite searches should be history now. -* Relevanssi Premium now offers WP CLI support. See `wp help relevanssi` for instructions. -* Relevanssi didn't support tax_queries with `field` set to `name`. That works now. -* Much faster way of showing the 25 most common words in the index. If you've disabled this feature because it was so slow, try enabling it - you might be surprised! - -= 1.15.0.1 = -* The network settings page was missing. - -= 1.15.0 = -* Improved ACF compatibility. -* Relevanssi was a bit too eager to index taxonomy terms it shouldn't. That is now fixed. I suggest you rebuild the index, if you haven't done that recently. -* Synonym indexing was searching and replacing too much. If you're using synonym indexing, please rebuild the index. -* It is now possible to copy Relevanssi settings from one blog in the multisite network to all other blogs. -* On multisite installations, the API key is now a network option. The network admin needs to set the value from the network admin dashboard. -* Relevanssi post controls didn't work on attachments: you couldn't save the values. That is now possible. -* Pinning didn't work on multisite searches. It does now. -* Relevanssi now stores the operator used in $wp_query->query_vars['operator'] so that it can be accessed outside Relevanssi. - -= 1.14.9 = -* Did you mean function had a XSS vulnerability, which is now removed. -* Minimum word length wasn't applied to titles in indexing. It is now fixed. If you think this is a problem, rebuild the index. -* TablePress compatibility has been improved. -* Meta query handling has been improved, thanks to Maxime Culea. -* Improved WP_Query parameter support: setting query variable `sentence` to 1 forces phrase search. - -= 1.14.8 = -* An improved version of the sorting function will not throw notices when Intuitive Custom Post Order plugin is used. -* New filter: `relevanssi_missing_sort_key` can be used to adjust the result sorting when using keys that are not present in all posts (eg. menu_order). -* Importing options now works, it was broken in 1.14.6. -* New feature: keyword-based exclusion is the opposite of the pinning feature. You can now list keywords on post edit screen, and if the search query matches those keywords, the post will not appear in results. -* Czech translation and stopwords, thanks to Michael Kucera. - -= 1.14.7.1 = -* Relevanssi threw a fatal error with PHP 7.1 thanks to a wrong variable declaration. -* The accidental PHP 5.4+ requirement has been removed. - -= 1.14.7 = -* Relevanssi broke the WP admin menu search when admin searches were enabled. -* Pinning now supports multi-word search terms. -* Relevanssi broke the admin page search under WP 4.7. Relevanssi is now disabled in admin page searches. -* The way accented characters are handled in highlighting is improved. A new filter, `relevanssi_accents_replacement_arrays`, can be used to adjust the accent replacement. - -= 1.14.6.1 = -* Fix for a fatal bug in 1.14.6. - -= 1.14.6 = -* Relevanssi option import had a arbitrary code execution vulnerability that is now blocked. -* Relevanssi admin page had a vulnerability that allowed SQL injection attacks. That is now fixed. -* Relevanssi didn't like to highlight search terms that are followed by a ?, an ! or an apostrophe. -* New filter: `relevanssi_ok_to_log` lets you control whether search queries are logged or not. - -= 1.14.5 = -* Relevanssi had problems with plus signs in search queries. -* 500 errors caused by arrays in custom fields should be gone now. -* Post type filters in multisite searching work better now, and meta_query support is now added. (Thanks to Maxime Culea.) -* Improvements to the ACF "select" field support. -* Relevanssi will not break when frontend plugins insert posts. -* Polylang support has been improved. -* WPML and Polylang filters work when "fields" is set to "ids". -* `relevanssi_match` filter has a new parameter, which contains the search term. -* `relevanssi_post_ok` filter was missing from the multisite search. - -= 1.14.4 = -* Fixed a small glitch that could happen if a highlighted term is next to a starting square bracket. -* Bug fixes in the multisite searching: post type weights work now, and relevancy scores are properly noted. -* Ensured PHP7 and WP 4.6 compatibility. -* New filter: `relevanssi_30days` can be used to adjust the 30 day logs to a different number of days. - -= 1.14.3 = -* Fix for a small bug that caused inflated relevancy values. -* `relevanssi_didyoumean_url` has two more parameters (uncorrected query and the suggestion). -* The Did you mean function didn't work properly if the search term wasn't in lowercase. -* Adding stopwords that contain apostrophes didn't work. -* Relevanssi can now index the human-readable labels of ACF "select" fields. (Thanks to Raphaël Droz.) - -= 1.14.2 = -* Fixed a fatal error when searching includes private posts. - -= 1.14.1 = -* Multisite searches had some compatibility issues with other plugins and navigation menus; those have now been fixed. -* Multisite search (which has limitations) doesn't trigger if the search only targets the current site. -* Multisite search can now return taxonomy terms. -* "Did you mean" corrections in search queries with many words work better now. -* Fixed an error if the search term was not found in content. -* Fixed an error when building excerpts from posts shorter than the excerpt length. -* Blocked the `[starpro]`, CFDB and WooCommerce shortcodes that are causing problems with Relevanssi. -* Added support for `term_tax_id` in the `fields` parameter in tax_queries. -* Excerpt-building failed if multibyte string operations were missing. It should work now. -* New filter: `relevanssi_remove_stopwords_in_titles` allows you to include stopwords in titles. -* New filter: `relevanssi_remote_addr` can be used to modify the IP address logged to Relevanssi logs. -* New filter: `relevanssi_user_searches_limit` to adjust the number of user searches shown in the logs. -* Old data check is only done on Relevanssi settings page, not on all admin pages. That should improve admin performance. - -= 1.14 = -* Tokenizer was using `strlen()` and not `mb_strlen()`, so word lengths were not calculated properly. If your site uses non-ASCII alphabet, rebuilding the index is a good idea. -* Printing out titles for taxonomy terms didn't work properly. `relevanssi_the_title()` works for that and if you don't want to echo the title, you can use it like `relevanssi_the_title(false)` to make it return the title. -* Small improvement to WPML multilanguage filtering. -* `relevanssi_user_add_data` only worked when indexing all users. -* "Undefined index" errors in multisite search were eliminated. -* The `[noindex]` shortcode now supports shortcodes inside it. -* When posts transitioned from "future" to "published" there were some issues with disappearing Relevanssi settings. That's fixed now. -* The `[watupro]` shortcode didn't work with Relevanssi, so Relevanssi will now bypass it. -* Relevanssi had `the_title` filter hook calls that were missing the second parameter; that's now fixed. -* The excerpt-building algorithm is completely rewritten based on work by Ben Boyter (http://www.boyter.org/). -* The plugin i18n features have been improved slightly. -* New filter: `relevanssi_didyoumean_suggestion` lets you modify the Did you mean? suggestion before it's displayed. -* `relevanssi_didyoumean()` has a new parameter: you can now choose whether the result is echoed out (the default value) or just returned. -* Multisite search had some problems with some Relevanssi variables not changing when the blog was switched. This is now improved, thanks to Teemu Muikku. -* In the search results breakdown, you can now use %categories% and %taxonomies% to show the number of matches in categories and taxonomies other than tags and cats, respectively. -* Search results breakdowns now work for taxonomy terms and user profiles. -* Relevanssi supports `fields` parameter (both `ids` and `id=>parent`) to return only post IDs or post IDs and post parents. - -= 1.13.5 = -* Previous version broke the multisite search. That is now fixed. -* Empty lines on synonym settings caused problems. Fixed that. -* Relevanssi didn't clean up properly on uninstall, leaving _relevanssi_pin postmeta fields. - -= 1.13.4 = -* New filter: `relevanssi_valid_admin_status` can be used to adjust post statuses that Relevanssi will handle. -* Meta query support should now be perfect; there were some limitations with complicated meta queries before. - -= 1.13.3 = -* Removes one "Undefined variable" error. -* New filter: `relevanssi_display_common_words` can be used to disable the "25 most common words" listing on the settings page, if it's too heavy to load. -* Eliminated problems where using the `relevanssi_do_not_index` filter caused error messages. -* Relevanssi was sanitizing taxonomy titles too aggressively. That is now toned down a bit. -* If Relevanssi creates an empty excerpt for a post and there's a user-set excerpt for the post, that excerpt is used. -* The `relevanssi_post_title_before_tokenize` filter now has a second parameter that contains the post object. -* No ellipsis is added to the post excerpt, if the post excerpt shows the whole post. -* Relevanssi now supports `post_parent`, `post_parent__in` and `post_parent__not_in`, though you have to set them in `relevanssi_modify_wp_query` filter for them to work. - -= 1.13.2 = -* Fixed a bug that caused the results to change depending of the order of words in a multi-word search query. -* Added `product_categories` and `recent_products` from WooCommerce to the list of blocked shortcodes. -* There are improvements in excerpt-building and highlighting, especially when fuzzy search is enabled. -* Fixed a possible (if quite unlikely) XSS vulnerability. -* Improved search performance (thanks to MikeNGarrett). -* Sometimes highlights in documents make the document content disappear. I don't know why, but I've added a fix that should make the content visible (without the highlights) if a problem appears. - -= 1.13.1 = -* Fixed a bug with numeric taxonomy terms. -* Fixed a bug in user search. -* API keys are now completely hidden on the Relevanssi settings page. -* `relevanssi_do_not_index` hook is moved a bit, so that when updating posts, posts that are not indexed because of the hook are now removed from the index. -* Pinning didn't work if the post wasn't otherwise found with the pinning term. Now pinning terms are also indexed to ensure that the posts can be found with them. - -= 1.13 = -* New feature: You can now pin posts on particular search terms. -* New feature: Synonyms can now be defined in indexing, allowing them to be used with AND searches. (Thanks to Christoph Daum.) -* Relevanssi handles taxonomy terms in search better. The change requires a reindexing. -* Fix in indexing: Relevanssi will now bypass the global $post when indexing. This should help with problems with the Cookie Law Info plugin, for example. -* Tax query relation setting didn't work properly. It is now fixed. -* Word-based excerpt building sometimes created too short excerpts. That is now fixed. -* Synonyms are now highlighted. -* Phrase matching had issues where searching for a too common phrase crashed the search. That has been fixed. -* LIKE operator didn't work properly in meta_queries. -* API key field in settings is now a password field so clients and users can't see the API key. -* Relevanssi created lots of unnecessary post_meta rows and didn't clean up properly afterwards. Now unnecessary rows are not created, and everything is cleaned up properly. -* Problems with Avatar Upload plugin are fixed. -* Offset errors with mb_stripos() shouldn't happen anymore. -* Relevanssi tables are now added to `wpmu_drop_tables` to ensure neat cleanup with WPMU. -* A small problem in taxonomy search MySQL fixed, also a small problem with AND operator in tax_queries. -* Did you mean function now handles umlauted alphabet (ä, ö, ü and å). -* Fixed a bug with WP_Date_Queries. Thanks to Charles St-Pierre. -* New filter: `relevanssi_post_to_index` lets you access the post object before the post is indexed. -* New filter: `relevanssi_orderby` lets you modify the $orderby value before Relevanssi sorts posts. -* New filter: `relevanssi_order` lets you modify the $order value before Relevanssi sorts posts. -* New filter: `relevanssi_post_title_before_tokenize` lets you modify post titles before indexing. -* New filter: `relevanssi_private_cap` lets you adjust the capability setting for private posts in custom post types. - -= 1.12.1 = -* Fixed a bug where excluding posts would cause the search to fail. -* WPML searches showed each result twice. That's fixed. -* Increased plugin safety against hackers. -* There was a bug in `relevanssi_comment_content_to_index` filter. -* Some people had problems with the log entry timestamps. Fixed that. -* New filter: `relevanssi_prevent_default_request` gives you more control over where Relevanssi prevents the default query from running. -* New filter: `relevanssi_private_cap` lets you set the correct capability for finding private posts in custom post types. -* The option to exclude categories and tags from search only worked for categories, not tags. Tags have been separated to a different option. - -= 1.12 = -* Relevanssi now automatically treats 'ß' as 'ss'. If your site has 'ß' in text, reindexing the database is a good idea. -* Query variable `post_status` is now supported. -* Improvements to excerpts: excerpts with phrases work much better now, and the excerpt creation logic has been improved: the excerpts are now better. The process takes a bit more time, though. -* Allowing HTML tags in excerpts could lead to those tags being left open. Relevanssi will now try to close open HTML tags in excerpts. -* Allowed tags were not controlled in comments. They are now. -* Highlighting in documents didn't always work; it should be more reliable now. -* Non-integer values are removed from `post__in` and `post__not_in` before processing them. -* Query variables `p` and `page_id` are now supported. -* Relevanssi now understands `date_query` variables as well. -* The original post excerpt is stored in $post->original_excerpt. -* Taxonomy search works better with term id parameters (for example from `wp_category_dropdown`). -* Errors about $wpdb->prepare() missing an argument removed. -* New functions: `relevanssi_the_title()` and `relevanssi_get_the_title()` can be used to display highlighted titles in search results. -* The old title highlighting method has been disabled, because it caused highlights in wrong places. Now the highlighted title is stored in $post->highlighted_post_title, take it from there or use the Relevanssi title functions to display it. -* Polylang and WPML support was adjusted to perform better in edge cases. -* Indexing is faster, thanks to some improved code from Tom Novelli. -* MySQL injection attack vulnerability removed. -* The cache feature is now removed. Relevanssi should automatically drop the cache tables. -* New filter: `relevanssi_indexing_data` lets you modify the data before it's indexed. -* Fix for a bug that sometimes caused multisite hits to come from the wrong site. - -= 1.11 = -* Fixed a bug in the TablePress support. -* Titles are put through the_title filter before indexing. -* relevanssi_related() function had a bug. -* New filter: `relevanssi_join` can be used to join tables in the Relevanssi search MySQL queries. Thanks to Ninos Ego. -* New filter: `relevanssi_tax_term_additional_content` can be used to add any content to taxonomy terms before indexing. -* New filter: `relevanssi_post_content` can be used to modify post content before any Relevanssi processing. -* New filter: `relevanssi_post_content_before_tokenize` can be used to modify post content just before it's tokenized. -* New filter: `relevanssi_indexing_values` can be used to modify what Relevanssi stores in the index. -* New filter: `relevanssi_default_meta_query_relation` can be used to change the default meta query relation (default value is "AND"). -* When using a meta_query, `relation` can be set to OR now. -* Phrases are now matched to excerpts. -* Number of queries Relevanssi generates is much, much lower. -* New filter: `relevanssi_didyoumean_url` lets you modify the URL generated by the did you mean feature. -* Better set of Russian stopwords. -* Relevanssi now highlights search query synonyms as well in documents. - -= 1.10.14 = -* Fix to make Relevanssi compatible with WordPress 3.7. -* Fixed a mistyped database table name. -* Relevanssi disables responsive-flipbook shortcode in indexing; it was causing problems. -* Fixed a problem with an author dropdown with no author selected. - -= 1.10.13 = -* New filter: `relevanssi_comment_content_to_index` lets you modify comment content before it's indexed by Relevanssi (to index comment meta, for example). -* Facetious support: if post_type is set to -1, Relevanssi will not hang up on it. -* Numerical search terms work better now. -* Relevanssi now handles WordPress-created tax_queries better. -* Support for Polylang broke the support for WPML. That is now fixed. -* Two deprecated $wpdb->escape() were still left; they're gone now. -* Shortcode `layerslider` was causing problems with Relevanssi; Relevanssi now disables it before building excerpts. -* Relevanssi won't break BBPress search anymore. -* Multisite searches had some issues. - -= 1.10.12 = -* Excerpt-building had issues, which are now fixed. -* Punctuation removal now replaces   with a space. -* "starrater" short code from GD Star Rating is now disabled in indexing. -* Punctuation removal now replaces invisible spaces with a normal space. -* Division by zero error caused by 0 in posts_per_page is now prevented, and -1 value for posts_per_page handled better. -* Relevanssi doesn't apply `get_the_excerpt` filters to excerpts it builds any more. -* New filter: `relevanssi_excerpt` lets you modify the excerpts Relevanssi creates. -* Relevanssi now suspends WP post cache while indexing, making indexing a lot more efficient. Thanks to Julien Mession for this one. -* Deprecated function errors in 3.6 removed. -* When search included user profiles or taxonomy terms, Relevanssi would generate lots of MySQL errors. Not anymore. -* New filter: `relevanssi_valid_status` lets you modify the post statuses Relevanssi indexes. -* New filter: `relevanssi_index_taxonomies_args` lets you modify the arguments passed to get_terms() when indexing taxonomies (for example to set 'hide_empty' to false). -* Searching by taxonomy ID could confuse two taxonomies with the same term_id. The search is now checking the taxonomy as well to see it's correct. -* Basic support for Polylang plugin. -* Russian and Italian stopwords are now included, thanks to Flector and Valerio Vendrame. -* Small fix in the way user meta fields are handled. - -= 1.10.11 = -* Previous upgrade broke AND operator in searches. Fixed that. - -= 1.10.10 = -* REBUILD THE INDEX AFTER THIS UPDATE. -* Prevented error messages relating to creation of post objects from users and taxonomies. -* Fixed MySQL errors from empty meta queries. -* Removed WP complaint about badly formed $wpdb->prepare() statement. -* Sort order (orderby and order variables) are now read from query variables instead of global variables. -* Relevanssi will not choke on bad values of orderby anymore. -* Limit searches is improved: when using AND search it is less likely to miss results. -* Phrase recognition read the whole post content (which it didn't need) from database, causing memory issues in some cases. Fixed that. -* Fuzzy searches are now a lot more efficient; they were a huge resource hog before. -* Fixed a possible MySQL injection attack. - -= 1.10.9.1 = -* OR fallback didn't actually fall back to OR, but instead got stuck in an endless loop of AND searches. -* Relevanssi was being called twice when a post was saved, on `save_post` and `wp_insert_post`. I removed the hook on `save_post`. - -= 1.10.9 = -* Fixed the auto-update problem in 1.10.8 asking to update after update was done. -* Meta queries didn't work without a key; now they work with just meta_value or meta_value_num. -* Modified the way the highlights work; now highlighting words with apostrophes should produce more meaningful results. - -= 1.10.8 = -* Major indexing problems caused by shortcodes changing the post ID during the indexing of posts are now fixed. -* Meta queries had problems with meta_value being set to null. -* Relevanssi now supports category__and. By default this sets include_children to false. -* When querying by slug, the term taxonomy is also taken into consideration, fixing problems when same slug appears in different taxonomies. -* Author search didn't work. -* Fixed an error message caused by all-number synonyms starting with zero, like 02. -* New action hook: `relevanssi_pre_indexing_query` can be used to "SET OPTION SQL_BIG_SELECTS=1" if needed. -* Synonyms are now case-insensitive. -* Highlighting should not highlight anything between & and ; or in @siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@]*?.*?@siu', - '@@siu', - ), - ' ', - $text - ); - return $text; -} - -/** - * Strips tags from contents, keeping the allowed tags. - * - * The allowable tags are read from the relevanssi_excerpt_allowable_tags - * option. Relevanssi also adds extra spaces after some tags to make sure words - * are not stuck together after the tags are removed. The function also removes - * invisible content. - * - * @uses relevanssi_strip_invisibles() Used to remove scripts and other tags. - * @see strip_tags() Used to remove tags. - * - * @param string|null $content The content. - * - * @return string The content without tags. - */ -function relevanssi_strip_tags( $content ) { - if ( ! is_string( $content ) ) { - $content = strval( $content ); - } - $content = relevanssi_strip_invisibles( $content ); - - $space_tags = array( - '/(<\/?p.*?>)/', - '/(<\/?br.*?>)/', - '/(<\/?h[1-6].*?>)/', - '/(<\/?div.*?>)/', - '/(<\/?blockquote.*?>)/', - '/(<\/?hr.*?>)/', - '/(<\/?li.*?>)/', - '/()/', - '/(<\/td>)/', - ); - - $content = preg_replace( $space_tags, '$1 ', $content ); - return strip_tags( - $content, - get_option( 'relevanssi_excerpt_allowable_tags', '' ) - ); -} - -/** - * Returns the position of substring in the string. - * - * Uses mb_stripos() if possible, falls back to mb_strpos() and mb_strtoupper() - * if that cannot be found, and falls back to just strpos() if even that is not - * possible. - * - * @param string $haystack String where to look. - * @param string $needle The string to look for. - * @param int $offset Where to start, default 0. - * - * @return mixed False, if no result or $offset outside the length of $haystack, - * otherwise the position (which can be non-false 0!). - */ -function relevanssi_stripos( $haystack, $needle, int $offset = 0 ) { - if ( ! is_string( $haystack ) ) { - $haystack = strval( $haystack ); - } - if ( ! is_string( $needle ) ) { - $needle = strval( $needle ); - } - if ( $offset > relevanssi_strlen( $haystack ) ) { - return false; - } - - if ( preg_match( '/[\?\*]/', $needle ) ) { - // There's a ? or an * in the string, which means it's a wildcard search - // query (a Premium feature) and requires some extra steps. - $needle_regex = str_replace( - array( '?', '*' ), - array( '.', '.*' ), - preg_quote( $needle, '/' ) - ); - $pos_found = false; - while ( ! $pos_found ) { - preg_match( - "/$needle_regex/i", - $haystack, - $matches, - PREG_OFFSET_CAPTURE, - $offset - ); - /** - * This trickery is necessary, because PREG_OFFSET_CAPTURE gives - * wrong offsets for multibyte strings. The mb_strlen() gives the - * correct offset, the rest of this is because the $offset received - * as a parameter can be before the first $position, leading to an - * infinite loop. - */ - $pos = isset( $matches[0][1] ) - ? mb_strlen( substr( $haystack, 0, $matches[0][1] ) ) - : false; - if ( $pos && $pos > $offset ) { - $pos_found = true; - } elseif ( $pos ) { - ++$offset; - } else { - $pos_found = true; - } - } - } elseif ( function_exists( 'mb_stripos' ) ) { - if ( '' === $haystack ) { - $pos = false; - } else { - $pos = mb_stripos( $haystack, $needle, $offset ); - } - } elseif ( function_exists( 'mb_strpos' ) && function_exists( 'mb_strtoupper' ) && function_exists( 'mb_substr' ) ) { - $pos = mb_strpos( - mb_strtoupper( $haystack ), - mb_strtoupper( $needle ), - $offset - ); - } else { - $pos = strpos( strtoupper( $haystack ), strtoupper( $needle ), $offset ); - } - return $pos; -} - -/** - * Returns the length of the string. - * - * Uses mb_strlen() if available, otherwise falls back to strlen(). - * - * @param string $s The string to measure. - * - * @return int The length of the string. - */ -function relevanssi_strlen( $s ) { - if ( ! is_string( $s ) ) { - $s = strval( $s ); - } - if ( function_exists( 'mb_strlen' ) ) { - return mb_strlen( $s ); - } - return strlen( $s ); -} - -/** - * Multibyte friendly strtolower. - * - * If multibyte string functions are available, returns mb_strtolower() and - * falls back to strtolower() if multibyte functions are not available. - * - * @param string $str The string to lowercase. - * - * @return string $str The string in lowercase. - */ -function relevanssi_strtolower( $str ) { - if ( ! is_string( $str ) ) { - $str = strval( $str ); - } - if ( ! function_exists( 'mb_strtolower' ) ) { - return strtolower( $str ); - } else { - return mb_strtolower( $str ); - } -} - -/** - * Multibyte friendly substr. - * - * If multibyte string functions are available, returns mb_substr() and falls - * back to substr() if multibyte functions are not available. - * - * @param string $str The source string. - * @param int $start If start is non-negative, the returned string will - * start at the start'th position in str, counting from zero. If start is - * negative, the returned string will start at the start'th character from the - * end of string. - * @param int|null $length Maximum number of characters to use from string. If - * omitted or null is passed, extract all characters to the end of the string. - * - * @return string $str The string in lowercase. - */ -function relevanssi_substr( $str, int $start, $length = null ) { - if ( ! is_string( $str ) ) { - $str = strval( $str ); - } - if ( ! function_exists( 'mb_substr' ) ) { - return substr( $str, $start, $length ); - } else { - return mb_substr( $str, $start, $length ); - } -} - -/** - * Prints out the post excerpt. - * - * Prints out the post excerpt from $post->post_excerpt, unless the post is - * protected. Only works in the Loop. - * - * @see post_password_required() Used to check for password requirements. - * - * @global $post The global post object. - */ -function relevanssi_the_excerpt() { - global $post; - if ( ! post_password_required( $post ) ) { - echo '

    ' . $post->post_excerpt . '

    '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } else { - esc_html_e( 'There is no excerpt because this is a protected post.', 'relevanssi' ); - } -} - -/** - * Echoes out the permalink to the current post within Loop. - * - * Uses get_permalink() to get the permalink, then adds the 'highlight' - * parameter if necessary using relevanssi_add_highlight(), then echoes it out. - * - * @param int|WP_Post $post Post ID or post object. Default is the global $post. - * - * @uses relevanssi_get_permalink() Fetches the current post permalink. - */ -function relevanssi_the_permalink( $post = 0 ) { - echo esc_url( relevanssi_get_permalink( $post ) ); -} - -/** - * Prints out a list of tags for post. - * - * Replacement for the_tags() that does the same, but applies Relevanssi search term - * highlighting on the results. - * - * @param string $before What is printed before the tags, default ''. - * @param string $separator The separator between items, default ', '. - * @param string $after What is printed after the tags, default ''. - * @param boolean $echoed If true, echo, otherwise return the result. Default true. - * @param int $post_id The post ID. Default current post ID (in the Loop). - */ -function relevanssi_the_tags( string $before = '', string $separator = ', ', string $after = '', bool $echoed = true, int $post_id = 0 ) { - $tag_list = get_the_tag_list( $before, $separator, $after, $post_id ); - $found = preg_match_all( '~~', $tag_list, $matches ); - if ( $found ) { - $originals = $matches[0]; - $tag_names = $matches[1]; - $highlighted = array(); - - $count = count( $matches[0] ); - for ( $i = 0; $i < $count; $i++ ) { - $highlighted_tag_name = relevanssi_highlight_terms( $tag_names[ $i ], get_search_query(), true ); - $highlighted[ $i ] = str_replace( '>' . $tag_names[ $i ] . '<', '>' . $highlighted_tag_name . '<', $originals[ $i ] ); - } - - $tag_list = str_replace( $originals, $highlighted, $tag_list ); - } - - if ( $echoed ) { - echo $tag_list; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } else { - return $tag_list; - } -} - -/** - * Prints out post title with highlighting. - * - * Uses the global $post object. Reads the highlighted title from - * $post->post_highlighted_title. This used to accept one parameter, the - * `$echo` boolean, but in 2.12.3 / 4.10.3 the function signature was matched - * to copy `the_title()` function in WordPress core. The original behaviour is - * still supported: `relevanssi_the_title()` without arguments works exactly as - * before and `relevanssi_the_title( false )` returns the title. - * - * @global object $post The global post object. - * - * @param boolean|string $before Markup to prepend to the title. Can also be a - * boolean for whether to echo or return the title. - * @param string $after Markup to append to the title. - * @param boolean $echoed Whether to echo or return the title. Default - * true for echo. - * - * @return void|string Void if $echoed argument is true, current post title with - * highlights if $echoed is false. - */ -function relevanssi_the_title( $before = true, string $after = '', bool $echoed = true ) { - if ( true === $before ) { - $before = ''; - $echoed = true; - } elseif ( false === $before ) { - $before = ''; - $echoed = false; - } - global $post; - if ( empty( $post->post_highlighted_title ) ) { - $post->post_highlighted_title = $post->post_title; - } - if ( relevanssi_strlen( $post->post_highlighted_title ) === 0 ) { - return; - } - $title = $before . $post->post_highlighted_title . $after; - if ( $echoed ) { - echo $title; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } else { - return $title; - } -} - -/** - * Turns off options, ie. sets them to "off". - * - * If the specified options don't exist in the request array, they are set to - * "off". - * - * @param array $request The _REQUEST array, passed as reference. - * @param array $options An array of option names. - */ -function relevanssi_turn_off_options( array &$request, array $options ) { - array_walk( - $options, - function ( $option ) use ( &$request ) { - if ( ! isset( $request[ $option ] ) ) { - $request[ $option ] = 'off'; - } - } - ); -} - -/** - * Sets an option after doing floatval. - * - * @param array $request An array of option values. - * @param string $option The key to check. - * @param boolean $autoload Should the option autoload, default true. - * @param float $def_val The default value if floatval() fails, default 0. - * @param boolean $positive If true, replace negative values and zeroes with - * $def_val. - */ -function relevanssi_update_floatval( array $request, string $option, bool $autoload = true, float $def_val = 0, bool $positive = false ) { - if ( isset( $request[ $option ] ) ) { - $value = floatval( $request[ $option ] ); - if ( ! $value ) { - $value = $def_val; - } - if ( $positive && $value <= 0 ) { - $value = $def_val; - } - update_option( $option, $value, $autoload ); - } -} - -/** - * Sets an option after doing intval. - * - * @param array $request An array of option values. - * @param string $option The key to check. - * @param boolean $autoload Should the option autoload, default true. - * @param int $def_val The default value if intval() fails, default 0. - */ -function relevanssi_update_intval( array $request, string $option, bool $autoload = true, int $def_val = 0 ) { - if ( isset( $request[ $option ] ) ) { - $value = intval( $request[ $option ] ); - if ( ! $value ) { - $value = $def_val; - } - update_option( $option, $value, $autoload ); - } -} - -/** - * Sets an option with one of the listed legal values. - * - * @param array $request An array of option values. - * @param string $option The key to check. - * @param array $values The legal values. - * @param string $def_val The default value. - * @param boolean $autoload Should the option autoload, default true. - */ -function relevanssi_update_legal_value( array $request, string $option, array $values, string $def_val, bool $autoload = true ) { - if ( isset( $request[ $option ] ) ) { - $value = $def_val; - if ( in_array( $request[ $option ], $values, true ) ) { - $value = $request[ $option ]; - } - update_option( $option, $value, $autoload ); - } -} - -/** - * Sets an on/off option according to the request value. - * - * @param array $request An array of option values. - * @param string $option The key to check. - * @param boolean $autoload Should the option autoload, default true. - */ -function relevanssi_update_off_or_on( array $request, string $option, bool $autoload = true ) { - relevanssi_update_legal_value( - $request, - $option, - array( 'off', 'on' ), - 'off', - $autoload - ); -} - -/** - * Sets an option after sanitizing and unslashing the value. - * - * @param array $request An array of option values. - * @param string $option The key to check. - * @param boolean $autoload Should the option autoload, default true. - */ -function relevanssi_update_sanitized( array $request, string $option, bool $autoload = true ) { - if ( isset( $request[ $option ] ) ) { - $value = sanitize_text_field( wp_unslash( $request[ $option ] ) ); - update_option( $option, $value, $autoload ); - } -} - -/** - * Returns true if $_SERVER['HTTP_USER_AGENT'] is on the bot block list. - * - * Looks for bot user agents in the $_SERVER['HTTP_USER_AGENT'] and returns true - * if a match is found. - * - * @return bool True if $_SERVER['HTTP_USER_AGENT'] is a bot. - */ -function relevanssi_user_agent_is_bot(): bool { - if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { - /** - * Filters the bots Relevanssi should block from search queries. - * - * Lets you filter the bots that are blocked from Relevanssi search - * queries. - * - * @param array $bots An array of bot user agents. - */ - $bots = apply_filters( 'relevanssi_bots_to_block', relevanssi_bot_block_list() ); - foreach ( array_values( $bots ) as $lookfor ) { - if ( false !== stristr( $_SERVER['HTTP_USER_AGENT'], $lookfor ) ) { - return true; - } - } - } - return false; -} - -/** - * Validates that the parameter is a valid taxonomy type. - * - * @parameter string $taxonomy The taxonomy to validate. - * - * @return string The validated taxonomy, empty string if invalid. - */ -function relevanssi_validate_taxonomy( $taxonomy ) { - $taxonomy = sanitize_text_field( $taxonomy ); - if ( taxonomy_exists( $taxonomy ) ) { - return $taxonomy; - } - return ''; -} diff --git a/relevanssi-premium/premium/admin-ajax.php b/relevanssi-premium/premium/admin-ajax.php deleted file mode 100644 index 0ed2f6e2..00000000 --- a/relevanssi-premium/premium/admin-ajax.php +++ /dev/null @@ -1,780 +0,0 @@ -delete( - $wpdb->postmeta, - array( - 'meta_key' => '_relevanssi_pdf_error', - 'meta_value' => 'R_ERR06: Server did not respond.', - ), - array( - '%s', - '%s', - ) - ); - - $response['deleted_rows'] = $result; - - echo wp_json_encode( $response ); - - wp_die(); -} - -/** - * Deletes all post meta for certain meta key unless another meta key is set. - * - * @global object $wpdb The WordPress database interface. - * - * @param string $meta_key The meta key to delete. - * @param string $exclusion_key The conditional meta key. - * @param string $value Value for the conditional meta to check. - * - * @return boolean True if something was deleted, false if not. - * - * @since 2.5.0 - */ -function relevanssi_delete_all_but( $meta_key, $exclusion_key, $value ) { - global $wpdb; - - $query = $wpdb->prepare( - "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = %s - AND post_id NOT IN ( - SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s - )", - $meta_key, - $exclusion_key, - $value - ); - - $meta_ids = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - if ( ! count( $meta_ids ) ) { - return false; - } - - $query = "DELETE FROM $wpdb->postmeta WHERE meta_id IN ( " . implode( ',', $meta_ids ) . ' )'; - - $count = $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - - if ( ! $count ) { - return false; - } - - return true; -} - -/** - * Performs the "index PDFs" AJAX action. - * - * Reads in the PDF content for PDF files fetched using the relevanssi_get_posts_with_attachments() function. - * - * @since 2.0.0 - */ -function relevanssi_index_pdfs_action() { - check_ajax_referer( 'relevanssi-index-pdfs', 'security' ); - relevanssi_current_user_can_access_options(); - - $pdfs = relevanssi_get_posts_with_attachments( 3 ); - - if ( ! isset( $_POST['completed'] ) || ! isset( $_POST['total'] ) ) { // WPCS: input var ok. - wp_die(); - } - - $post_data = $_POST; // WPCS: input var ok. - - $completed = absint( $post_data['completed'] ); - $total = absint( $post_data['total'] ); - - $response = array(); - $response['feedback'] = ''; - - if ( empty( $pdfs ) ) { - $response['feedback'] = __( 'Indexing complete!', 'relevanssi' ); - $response['completed'] = 'done'; - $response['percentage'] = 100; - } else { - foreach ( $pdfs as $post_id ) { - $echo_and_die = false; - $send_files = get_option( 'relevanssi_send_pdf_files' ); - if ( 'off' === $send_files ) { - $send_files = false; - } - - $index_response = relevanssi_index_pdf( $post_id, $echo_and_die, $send_files ); - ++$completed; - - if ( $index_response['success'] ) { - // translators: placeholder is the post ID. - $response['feedback'] .= sprintf( esc_html__( 'Successfully indexed attachment id %d.', 'relevanssi' ), esc_html( $post_id ) ) . "\n"; - } else { - // translators: the numeric placeholder is the post ID, the string is the error message. - $response['feedback'] .= sprintf( esc_html__( 'Failed to index attachment id %1$d: %2$s', 'relevanssi' ), esc_html( $post_id ), esc_html( $index_response['error'] ) ) . "\n"; - } - } - $response['completed'] = $completed; - if ( $total > 0 ) { - $response['percentage'] = round( $completed / $total * 100, 0 ); - } else { - $response['percentage'] = 0; - } - } - - echo wp_json_encode( $response ); - - wp_die(); -} - -/** - * Performs the "send PDF" AJAX action. - * - * Reads in the PDF content for one PDF file, based on the 'post_id' parameter, sending the PDF over. - * - * @since 2.0.0 - */ -function relevanssi_send_pdf() { - check_ajax_referer( 'relevanssi_send_pdf', 'security' ); - if ( ! current_user_can( 'upload_files' ) ) { - wp_die(); - } - - if ( ! isset( $_REQUEST['post_id'] ) ) { // WPCS: input var ok. - wp_die(); - } - $post_id = intval( wp_unslash( $_REQUEST['post_id'] ) ); // WPCS: input var ok. - $echo_and_die = true; - $send_file = true; - relevanssi_index_pdf( $post_id, $echo_and_die, $send_file ); - - // Just for sure; relevanssi_index_pdf() should echo necessary responses and die, so don't expect this to ever happen. - wp_die(); -} - -/** - * Performs the "send URL" AJAX action. - * - * Reads in the PDF content for one PDF file, based on the 'post_id' parameter, using the PDF URL. - * - * @since 2.0.0 - */ -function relevanssi_send_url() { - check_ajax_referer( 'relevanssi_send_pdf', 'security' ); - if ( ! current_user_can( 'upload_files' ) ) { - wp_die(); - } - - if ( ! isset( $_REQUEST['post_id'] ) ) { // WPCS: input var ok. - wp_die(); - } - $post_id = intval( wp_unslash( $_REQUEST['post_id'] ) ); // WPCS: input var ok. - $echo_and_die = true; - $send_file = false; - relevanssi_index_pdf( $post_id, $echo_and_die, $send_file ); - - // Just for sure; relevanssi_index_pdf() should echo necessary responses and die, so don't expect this to ever happen. - wp_die(); -} - -/** - * Reads all PDF errors. - * - * Gets a list of all PDF errors in the database and prints out a list of them. - * - * @global $wpdb The WordPress database interface, used to fetch the meta fields. - * - * @since 2.0.0 - */ -function relevanssi_get_pdf_errors_action() { - if ( ! current_user_can( 'upload_files' ) ) { - wp_die(); - } - - global $wpdb; - - $errors = $wpdb->get_results( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pdf_error'" ); - $error_message = array(); - foreach ( $errors as $error ) { - $row = __( 'Attachment ID', 'relevanssi' ) . ' ' . $error->post_id . ': ' . $error->meta_value; - $row = str_replace( 'PDF Processor error: ', '', $row ); - $error_message[] = $row; - } - - echo wp_json_encode( implode( "\n", $error_message ) ); - wp_die(); -} - -/** - * Reads a list of taxonomies. - * - * Gets a list of taxonomies selected for indexing from the relevanssi_list_taxonomies() function. - * - * @since 2.0.0 - */ -function relevanssi_list_taxonomies_wrapper() { - relevanssi_current_user_can_access_options(); - - $taxonomies = array(); - if ( function_exists( 'relevanssi_list_taxonomies' ) ) { - $taxonomies = relevanssi_list_taxonomies(); - } - echo wp_json_encode( $taxonomies ); - wp_die(); -} - -/** - * Indexes taxonomy terms for AJAX indexing. - * - * Reads in the parameters, indexes taxonomy terms and reports the results. - * - * @since 2.0.0 - */ -function relevanssi_index_taxonomies_ajax_wrapper() { - check_ajax_referer( 'relevanssi_taxonomy_indexing_nonce', 'security' ); - relevanssi_current_user_can_access_options(); - - if ( ! isset( $_POST['completed'] ) || ! isset( $_POST['total'] ) || ! isset( $_POST['taxonomy'] ) || ! isset( $_POST['offset'] ) || ! isset( $_POST['limit'] ) ) { // WPCS: input var ok. - wp_die(); - } - - $post_data = $_POST; // WPCS: input var ok. - - $completed = absint( $post_data['completed'] ); - $total = absint( $post_data['total'] ); - $taxonomy = relevanssi_validate_taxonomy( $post_data['taxonomy'] ); - $offset = intval( $post_data['offset'] ); - $limit = intval( $post_data['limit'] ); - - if ( empty( $taxonomy ) ) { - // Non-valid taxonomy. - wp_die(); - } - - $response = array(); - - $indexing_response = relevanssi_index_taxonomies_ajax( $taxonomy, $limit, $offset ); - - $completed += $indexing_response['indexed']; - if ( $completed === $total ) { - $response['completed'] = 'done'; - $response['total_posts'] = $completed; - $response['percentage'] = 100; - // translators: number of terms indexed on this go, total indexed terms, total number of terms. - $response['feedback'] = sprintf( _n( '%1$d taxonomy term, total %2$d / %3$d.', '%1$d taxonomy terms, total %2$d / %3$d.', $indexing_response['indexed'], 'relevanssi' ), $indexing_response['indexed'], $completed, $total ) . "\n"; - } else { - $response['completed'] = $completed; - // translators: number of terms indexed on this go, total indexed terms, total number of terms. - $response['feedback'] = sprintf( _n( '%1$d taxonomy term, total %2$d / %3$d.', '%1$d taxonomy terms, total %2$d / %3$d.', $indexing_response['indexed'], 'relevanssi' ), $indexing_response['indexed'], $completed, $total ) . "\n"; - - if ( $total > 0 ) { - $response['percentage'] = $completed / $total * 100; - } else { - $response['percentage'] = 0; - } - - $response['new_taxonomy'] = false; - if ( 'done' === $indexing_response['taxonomy_completed'] ) { - $response['new_taxonomy'] = true; - } - } - $response['offset'] = $offset + $limit; - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Indexes post type archives for AJAX indexing. - * - * Indexes post type archives and reports the results. The post type archives are - * always indexed all at one go; I don't think there's often a case where there are - * too many. - * - * @since 2.2.0 - */ -function relevanssi_index_post_type_archives_ajax_wrapper() { - check_ajax_referer( 'relevanssi_post_type_archive_indexing_nonce', 'security' ); - relevanssi_current_user_can_access_options(); - - $response = array(); - - if ( 'on' !== get_option( 'relevanssi_index_post_type_archives' ) ) { - $response['feedback'] = __( 'disabled.', 'relevanssi' ) . "\n"; - } else { - $indexing_response = relevanssi_index_post_type_archives_ajax(); - - $response['completed'] = 'done'; - $response['total_posts'] = $indexing_response['indexed']; - $response['percentage'] = 100; - // translators: number of terms indexed on this go, total indexed terms, total number of terms. - $response['feedback'] = sprintf( _n( '%1$d post type archive indexed.', '%1$d post type archives indexed.', $indexing_response['indexed'], 'relevanssi' ), $indexing_response['indexed'] ) . "\n"; - } - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Indexes users for AJAX indexing. - * - * Reads in the parameters, indexes users and reports the results. - * - * @since 2.0.0 - */ -function relevanssi_index_users_ajax_wrapper() { - check_ajax_referer( 'relevanssi_user_indexing_nonce', 'security' ); - relevanssi_current_user_can_access_options(); - - if ( ! isset( $_POST['completed'] ) || ! isset( $_POST['total'] ) || ! isset( $_POST['limit'] ) ) { // WPCS: input var ok. - wp_die(); - } - - $post_data = $_POST; // WPCS: input var ok. - - $completed = absint( $post_data['completed'] ); - $total = absint( $post_data['total'] ); - $limit = $post_data['limit']; - if ( isset( $post_data['offset'] ) ) { - $offset = $post_data['offset']; - } else { - $offset = 0; - } - - $response = array(); - - $indexing_response = relevanssi_index_users_ajax( $limit, $offset ); - - $completed += $indexing_response['indexed']; - $processed = $offset; - - if ( $completed === $total || $processed > $total ) { - $response['completed'] = 'done'; - $response['total_posts'] = $completed; - $response['percentage'] = 100; - $processed = $total; - } else { - $response['completed'] = $completed; - $offset = $offset + $limit; - - if ( $total > 0 ) { - $response['percentage'] = $completed / $total * 100; - } else { - $response['percentage'] = 0; - } - } - - // translators: number of users indexed on this go, total indexed users, total processed users, total number of users. - $response['feedback'] = sprintf( _n( 'Indexed %1$d user (total %2$d), processed %3$d / %4$d.', 'Indexed %1$d users (total %2$d), processed %3$d / %4$d.', $indexing_response['indexed'], 'relevanssi' ), $indexing_response['indexed'], $completed, $processed, $total ) . "\n"; - $response['offset'] = $offset; - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Counts the users. - * - * Counts the users for indexing purposes using the relevanssi_count_users() function. - * - * @since 2.0.0 - */ -function relevanssi_count_users_ajax_wrapper() { - relevanssi_current_user_can_access_options(); - - $count = -1; - if ( function_exists( 'relevanssi_count_users' ) ) { - $count = relevanssi_count_users(); - } - echo wp_json_encode( $count ); - wp_die(); -} - -/** - * Counts the taxonomy terms. - * - * Counts the taxonomy terms for indexing purposes using the relevanssi_count_taxonomy_terms() function. - * - * @since 2.0.0 - */ -function relevanssi_count_taxonomies_ajax_wrapper() { - relevanssi_current_user_can_access_options(); - - $count = -1; - if ( function_exists( 'relevanssi_count_taxonomy_terms' ) ) { - $count = relevanssi_count_taxonomy_terms(); - } - echo wp_json_encode( $count ); - wp_die(); -} - -/** - * Creates a list of related posts. - * - * @since 2.2.4 - */ -function relevanssi_get_related_posts() { - check_ajax_referer( 'relevanssi_metabox_nonce', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { - wp_die(); - } - - $post_id = (int) $_POST['post_id']; // WPCS: input var ok. - - if ( 0 === $post_id ) { - wp_die(); - } - - if ( isset( $_POST['keywords'] ) ) { - $keywords = sanitize_text_field( $_POST['keywords'] ); // WPCS: input var ok. - - delete_post_meta( $post_id, '_relevanssi_related_keywords' ); - add_post_meta( $post_id, '_relevanssi_related_keywords', $keywords ); - - // Keywords have changed, flush the cache. - delete_post_meta( $post_id, '_relevanssi_related_posts' ); - } - - if ( isset( $_POST['ids'] ) ) { - $include_ids_array = explode( ',', $_POST['ids'] ); - $valid_ids = array(); - foreach ( $include_ids_array as $id ) { - if ( get_post( $id ) ) { - $valid_ids[] = $id; - } - } - if ( ! empty( $valid_ids ) ) { - $id_string = implode( ',', $valid_ids ); - delete_post_meta( $post_id, '_relevanssi_related_include_ids' ); - add_post_meta( $post_id, '_relevanssi_related_include_ids', $id_string ); - } else { - delete_post_meta( $post_id, '_relevanssi_related_include_ids' ); - } - - // Included IDs have changed, flush the cache. - delete_post_meta( $post_id, '_relevanssi_related_posts' ); - } - - $list = relevanssi_generate_related_list( $post_id ); - - $response = array( - 'list' => $list, - ); - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Adds a post ID to the excluded ID list. - * - * @since 2.2.4 - */ -function relevanssi_add_to_exclude_list() { - check_ajax_referer( 'relevanssi_metabox_nonce', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { - wp_die(); - } - - $post_id = (int) $_POST['post_id']; // WPCS: input var ok. - - if ( 0 === $post_id ) { - wp_die(); - } - - if ( isset( $_POST['remove_id'] ) ) { - relevanssi_exclude_a_related_post( $post_id, $_POST['remove_id'] ); - } - - $related = relevanssi_generate_related_list( $post_id ); - $excluded = relevanssi_generate_excluded_list( $post_id ); - - $response = array( - 'related' => $related, - 'excluded' => $excluded, - ); - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Adds a post ID to the list of excluded post IDs of a post. - * - * @param int $post_id Add to this post IDs exclude list. - * @param int $excluded_post Add this post ID to the exclude list. - */ -function relevanssi_exclude_a_related_post( $post_id, $excluded_post ) { - $remove_id = (int) $excluded_post; - $excluded_ids = trim( get_post_meta( $post_id, '_relevanssi_related_exclude_ids', true ) ); - if ( $excluded_ids ) { - $excluded_ids = explode( ',', $excluded_ids ); - } else { - $excluded_ids = array(); - } - $excluded_ids[] = $remove_id; - $excluded_ids = array_keys( array_flip( $excluded_ids ) ); - $excluded_ids = implode( ',', $excluded_ids ); - update_post_meta( $post_id, '_relevanssi_related_exclude_ids', $excluded_ids ); - - // Excluded IDs have changed, flush the cache. - delete_post_meta( $post_id, '_relevanssi_related_posts' ); -} - -/** - * Removes a post ID from the excluded ID list and regenerates the lists. - * - * @since 2.2.4 - */ -function relevanssi_remove_from_exclude_list() { - check_ajax_referer( 'relevanssi_metabox_nonce', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { - wp_die(); - } - - $post_id = (int) $_POST['post_id']; // WPCS: input var ok. - - if ( 0 === $post_id ) { - wp_die(); - } - - if ( isset( $_POST['return_id'] ) ) { - relevanssi_unexclude_a_related_post( $post_id, $_POST['return_id'] ); - } - - $related = relevanssi_generate_related_list( $post_id ); - $excluded = relevanssi_generate_excluded_list( $post_id ); - - $response = array( - 'related' => $related, - 'excluded' => $excluded, - ); - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Removes a post ID from the related posts exclude list. - * - * @param int $post_id The post ID that owns the related posts exclude list. - * @param int $unexcluded_post The post ID which is removed from the exclude list. - */ -function relevanssi_unexclude_a_related_post( $post_id, $unexcluded_post ) { - $return_id = (int) $unexcluded_post; - $excluded_ids = trim( get_post_meta( $post_id, '_relevanssi_related_exclude_ids', true ) ); - $excluded_ids = array_flip( explode( ',', $excluded_ids ) ); - unset( $excluded_ids[ $return_id ] ); - $excluded_ids = array_keys( $excluded_ids ); - $excluded_ids = implode( ',', $excluded_ids ); - update_post_meta( $post_id, '_relevanssi_related_exclude_ids', $excluded_ids ); - - // Excluded IDs have changed, flush the cache. - delete_post_meta( $post_id, '_relevanssi_related_posts' ); -} - -/** - * Adds a keyword to the pinned keywords list for a post. - * - * @since 2.2.6 - */ -function relevanssi_pin_post() { - check_ajax_referer( 'relevanssi_admin_search_nonce', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { - wp_die(); - } - - $post_id = (int) $_POST['post_id']; // WPCS: input var ok. - $keyword = $_POST['keyword']; // WPCS: input var ok. - - if ( 0 === $post_id || empty( $keyword ) ) { - wp_die(); - } - - $result = false; - $already_pinned = false; - $pins = get_post_meta( $post_id, '_relevanssi_pin' ); - foreach ( $pins as $pin ) { - if ( $pin === $keyword ) { - $already_pinned = true; - break; - } - } - if ( ! $already_pinned ) { - $result = add_post_meta( $post_id, '_relevanssi_pin', $keyword ); - } - - $response = array( - 'success' => $result, - ); - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Removes a keyword from the pinned keywords list for a post. - * - * @since 2.2.6 - */ -function relevanssi_unpin_post() { - check_ajax_referer( 'relevanssi_admin_search_nonce', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { - wp_die(); - } - - $post_id = (int) $_POST['post_id']; // WPCS: input var ok. - $keyword = $_POST['keyword']; // WPCS: input var ok. - - if ( 0 === $post_id || empty( $keyword ) ) { - wp_die(); - } - - $result = delete_post_meta( $post_id, '_relevanssi_pin', $keyword ); - - $response = array( - 'success' => $result, - ); - - echo wp_json_encode( $response ); - wp_die(); -} - -/** - * Fetches database words to the relevanssi_words option. - * - * An AJAX wrapper for relevanssi_update_words_option(). - * - * @see relevanssi_update_words_option() - * - * @since 2.5.0 - */ -function relevanssi_ajax_get_words() { - if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'relevanssi_get_words' ) ) { - wp_die(); - } - - relevanssi_update_words_option(); - - wp_die(); -} - -/** - * Launches the attachment content indexing. - * - * Sets the _relevanssi_pdf_error for the post to show RELEVANSSI_ERROR_05 - * (ie. "work in progress"), then launches the indexing and dies off. - * - * @since 2.5.0 - */ -function relevanssi_ajax_index_pdf() { - if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'relevanssi_index_pdf' ) ) { - wp_die(); - } - - if ( ! current_user_can( 'upload_files' ) ) { - wp_die(); - } - - $post_id = intval( $_REQUEST['post_id'] ); - - update_post_meta( $post_id, '_relevanssi_pdf_error', RELEVANSSI_ERROR_05 ); - - relevanssi_index_pdf( $post_id ); - - wp_die(); -} diff --git a/relevanssi-premium/premium/admin_metabox_scripts.js b/relevanssi-premium/premium/admin_metabox_scripts.js deleted file mode 100644 index a4c66e7c..00000000 --- a/relevanssi-premium/premium/admin_metabox_scripts.js +++ /dev/null @@ -1,71 +0,0 @@ -jQuery(document).ready(function ($) { - $("#relevanssi_related_keywords").change(function (e) { - var post_id = $("#this_post_id").val() - var keywords = $("#relevanssi_related_keywords").val() - var data = { - action: "relevanssi_related_posts", - security: relevanssi_metabox_data.metabox_nonce, - post_id: post_id, - keywords: keywords, - } - jQuery.post(ajaxurl, data, function (response) { - response = JSON.parse(response) - $("#related_posts_list").html(response.list) - }) - }) - - $("#relevanssi_related_include_ids").change(function (e) { - var post_id = $("#this_post_id").val() - var ids = $("#relevanssi_related_include_ids").val() - var data = { - action: "relevanssi_related_posts", - security: relevanssi_metabox_data.metabox_nonce, - post_id: post_id, - ids: ids, - } - jQuery.post(ajaxurl, data, function (response) { - response = JSON.parse(response) - $("#related_posts_list").html(response.list) - }) - }) - - $("#relevanssi_hidebox").on("click", "button.removepost", function (e) { - var remove_id = $(this).data("removepost") - if (remove_id) { - var post_id = $("#this_post_id").val() - var data = { - action: "relevanssi_related_remove", - security: relevanssi_metabox_data.metabox_nonce, - post_id: post_id, - remove_id: remove_id, - } - jQuery.post(ajaxurl, data, function (response) { - response = JSON.parse(response) - - $("#related_posts_list").html(response.related) - $("#excluded_posts_list").html(response.excluded) - }) - } - }) - - $("#relevanssi_hidebox").on("click", "button.returnpost", function (e) { - var return_id = $(this).data("returnpost") - console.log(return_id) - if (return_id) { - var post_id = $("#this_post_id").val() - var data = { - action: "relevanssi_related_return", - security: relevanssi_metabox_data.metabox_nonce, - post_id: post_id, - return_id: return_id, - } - jQuery.post(ajaxurl, data, function (response) { - response = JSON.parse(response) - console.log(response) - - $("#related_posts_list").html(response.related) - $("#excluded_posts_list").html(response.excluded) - }) - } - }) -}) diff --git a/relevanssi-premium/premium/admin_pdf_scripts.js b/relevanssi-premium/premium/admin_pdf_scripts.js deleted file mode 100644 index 97f95490..00000000 --- a/relevanssi-premium/premium/admin_pdf_scripts.js +++ /dev/null @@ -1,49 +0,0 @@ -jQuery(document).ready(function () { - jQuery("#sendUrl").click(function (e) { - e.preventDefault() - var postID = jQuery("#sendUrl").data("post_id") - console.log(postID) - jQuery.ajax({ - url: ajaxurl, - type: "POST", - data: { - action: "relevanssi_send_url", - post_id: postID, - security: admin_pdf_data.send_pdf_nonce, - }, - dataType: "json", - complete: function (data) { - console.log(data) - location.reload() - }, - }) - }) - - jQuery("#sendPdf").click(function (e) { - e.preventDefault() - var postID = jQuery("#sendPdf").data("post_id") - console.log(postID) - jQuery.ajax({ - url: ajaxurl, - type: "POST", - data: { - action: "relevanssi_send_pdf", - post_id: postID, - security: admin_pdf_data.send_pdf_nonce, - }, - dataType: "json", - complete: function (data) { - console.log(data) - location.reload() - }, - }) - }) - - jQuery("textarea#relevanssi_pdf_content").focus(function () { - jQuery(this).animate({ rows: 40, cols: 120 }, 500) - }) - - jQuery("textarea#relevanssi_pdf_content").focusout(function () { - jQuery(this).animate({ rows: 4, cols: 80 }, 500) - }) -}) diff --git a/relevanssi-premium/premium/admin_scripts_premium.js b/relevanssi-premium/premium/admin_scripts_premium.js deleted file mode 100644 index 4b5e1fd0..00000000 --- a/relevanssi-premium/premium/admin_scripts_premium.js +++ /dev/null @@ -1,540 +0,0 @@ -jQuery(document).ready(function ($) { - // Show and hide the "Show Relevanssi for admins" setting on the Overview tab depending - // on whether the "Hide Relevanssi" setting is enabled. - var show_post_controls = $("#show_post_controls") - $("#relevanssi_hide_post_controls").on("change", function () { - show_post_controls.toggleClass("screen-reader-text") - }) - - // Find out the latest row ID in the redirect table. - var last_row_id = $(".redirect_table_row:last").attr("id") - var redirect_row_index = 0 - if (last_row_id) { - // There's a last row, we're on the Redirects tab. - last_row_id = last_row_id.split("_") - if (last_row_id.length > 1) { - redirect_row_index = last_row_id[1] - } - } - - // Adds a new row to the redirect table on the Redirects tab. - $("#add_redirect").on("click", function (e) { - redirect_row_index++ - $(".redirect_table_row:last") - .clone(true) - .attr("id", "row_" + redirect_row_index) - .insertAfter(".redirect_table_row:last") - - var query = $("#row_" + redirect_row_index + " input:first") - query.val("") - query.attr("name", "query_" + redirect_row_index) - query.attr("id", "query_" + redirect_row_index) - - var partial = $("#row_" + redirect_row_index + " input:checkbox") - partial.prop("checked", false) - partial.attr("name", "partial_" + redirect_row_index) - partial.attr("id", "partial_" + redirect_row_index) - - var url = $("#row_" + redirect_row_index + " input:eq(2)") - url.val("") - url.attr("id", "url_" + redirect_row_index) - url.attr("name", "url_" + redirect_row_index) - - var hits = $("#row_" + redirect_row_index + " input:last") - hits.val("") - hits.attr("name", "hits_" + redirect_row_index) - hits.attr("id", "hits_" + redirect_row_index) - - var hitsNumber = $("#row_" + redirect_row_index + " span:last") - hitsNumber.html("0") - }) - - // Related posts tab: if "Matching post types" is checked, disable and uncheck other options. - $("input.matching").on("click", function (e) { - if ($(this).is(":checked")) { - $("input.nonmatching").prop("checked", false) - $("input.nonmatching").attr("disabled", true) - } else { - $("input.nonmatching").attr("disabled", false) - } - }) - - // Related posts tab: Display default thumbnail option. - $("#relevanssi_related_thumbnails").on("click", function (e) { - $("#defaultthumbnail").toggleClass("screen-reader-text", !this.checked) - }) - - // Redirects tab redirect table row removal. - $(".remove").on("click", function (e) { - e.preventDefault() - if ($("#redirect_table >tbody >tr").length > 1) { - // If there is more than one row in the table, remove the last row. - $(this).closest("tr").remove() - } else { - // Only one row left, don't remove it (because adding rows is based on cloning). - // Instead empty out the values. - $(".redirect_table_row:last input:text").val("") - $(".redirect_table_row:last input:checkbox").prop("checked", false) - } - }) - - // Related posts tab: Toggle settings for main switch. - $("#relevanssi_related_enabled").on("click", function () { - $("#tr_relevanssi_related_append input").attr("disabled", !this.checked) - $("#tr_relevanssi_related_keyword input").attr("disabled", !this.checked) - $("#relevanssi_related_number").attr("disabled", !this.checked) - $("#relevanssi_related_months").attr("disabled", !this.checked) - $("#tr_relevanssi_related_post_types input").attr("disabled", !this.checked) - $("#relevanssi_related_nothing").attr("disabled", !this.checked) - $("#relevanssi_related_notenough").attr("disabled", !this.checked) - $("#relevanssi_related_titles").attr("disabled", !this.checked) - $("#relevanssi_related_thumbnails").attr("disabled", !this.checked) - $("#relevanssi_related_excerpts").attr("disabled", !this.checked) - $("#relevanssi_related_cache_for_admins").attr("disabled", !this.checked) - $("#relevanssi_flush_related_cache").attr("disabled", !this.checked) - }) - - // Redirects tab redirect table row cloning. - $("a.copy").on("click", function (e) { - e.preventDefault() - redirect_row_index++ - $(this) - .closest("tr") - .clone(true) - .attr("id", "row_" + redirect_row_index) - .insertAfter(".redirect_table_row:last") - - var query = $("#row_" + redirect_row_index + " input:first") - query.attr("name", "query_" + redirect_row_index) - query.attr("id", "query_" + redirect_row_index) - - var partial = $("#row_" + redirect_row_index + " input:checkbox") - partial.attr("name", "partial_" + redirect_row_index) - partial.attr("id", "partial_" + redirect_row_index) - - var url = $("#row_" + redirect_row_index + " input:eq(2)") - url.attr("name", "url_" + redirect_row_index) - url.attr("name", "url_" + redirect_row_index) - - var hits = $("#row_" + redirect_row_index + " input:last") - hits.val("") - hits.attr("name", "hits_" + redirect_row_index) - hits.attr("id", "hits_" + redirect_row_index) - - var hitsNumber = $("#row_" + redirect_row_index + " span:last") - hitsNumber.html("0") - }) - - $("#attachments_tab :input").on("change", function (e) { - $("#index").attr("disabled", "disabled") - var relevanssi_note = $("#relevanssi-note") - relevanssi_note.show() - relevanssi_note.html( - '

    ' + relevanssi.options_changed + "

    " - ) - }) - - $("#build_index").on("click", function () { - $("#relevanssi-progress").show() - $("#results").show() - $("#relevanssi-timer").show() - $("#relevanssi-indexing-instructions").show() - $("#stateoftheindex").html(relevanssi.reload_state) - $("#indexing_button_instructions").hide() - var results = document.getElementById("results") - results.value = "" - - var data = { - action: "relevanssi_truncate_index", - security: nonce.indexing_nonce, - } - - intervalID = window.setInterval(relevanssiUpdateClock, 1000) - - console.log("Truncating index.") - results.value += relevanssi.truncating_index + " " - jQuery.post(ajaxurl, data, function (response) { - truncate_response = JSON.parse(response) - console.log("Truncate index: " + truncate_response) - if (truncate_response == true) { - results.value += relevanssi.done + "\n" - } - var data = { - action: "relevanssi_index_post_type_archives", - security: nonce.post_type_archive_indexing_nonce, - } - console.log("Indexing post type archives.") - results.value += "Indexing post type archives... " - jQuery.post(ajaxurl, data, function (response) { - console.log("Done") - response = JSON.parse(response) - results.value += response.feedback - var data = { - action: "relevanssi_count_users", - } - console.log("Counting users.") - results.value += relevanssi.counting_users + " " - jQuery.post(ajaxurl, data, function (response) { - count_response = JSON.parse(response) - console.log("Counted " + count_response + " users.") - if (count_response < 0) { - results.value += relevanssi.user_disabled + "\n" - } else { - results.value += - count_response + " " + relevanssi.users_found + "\n" - } - - var user_total = count_response - - var data = { - action: "relevanssi_count_taxonomies", - } - console.log("Counting taxonomies.") - results.value += relevanssi.counting_terms + " " - jQuery.post(ajaxurl, data, function (response) { - count_response = JSON.parse(response) - console.log("Counted " + count_response + " taxonomy terms.") - if (count_response < 0) { - results.value += relevanssi.taxonomy_disabled + "\n" - } else { - results.value += - count_response + " " + relevanssi.terms_found + "\n" - } - - var taxonomy_total = count_response - - var data = { - action: "relevanssi_count_posts", - } - console.log("Counting posts.") - results.value += relevanssi.counting_posts + " " - jQuery.post(ajaxurl, data, function (response) { - count_response = JSON.parse(response) - console.log("Counted " + count_response + " posts.") - var post_total = parseInt(count_response) - results.value += - count_response + " " + relevanssi.posts_found + "\n" - - var data = { - action: "relevanssi_list_taxonomies", - } - console.log("Listing taxonomies.") - jQuery.post(ajaxurl, data, function (response) { - taxonomies_response = JSON.parse(response) - console.log("Listing taxonomies: " + taxonomies_response) - console.log("Starting indexing.") - console.log("User total " + user_total) - if (user_total > 0) { - console.log("Indexing users.") - var args = { - total: user_total, - completed: 0, - total_seconds: 0, - post_total: post_total, - limit: 10, - taxonomies: taxonomies_response, - taxonomies_total: taxonomy_total, - } - process_user_step(args) - } else if (taxonomy_total > 0) { - console.log("Indexing taxonomies.") - results.value += relevanssi.indexing_taxonomies + " " - results.value += taxonomies_response + "\n" - var args = { - taxonomies: taxonomies_response, - completed: 0, - total: taxonomy_total, - total_seconds: 0, - post_total: post_total, - current_taxonomy: "", - offset: 0, - limit: 20, - } - process_taxonomy_step(args) - } else { - console.log("Just indexing.") - var args = { - completed: 0, - total: post_total, - offset: 0, - total_seconds: 0, - limit: relevanssi_params.indexing_limit, - adjust: relevanssi_params.indexing_adjust, - extend: false, - security: nonce.indexing_nonce, - } - process_indexing_step(args) - } - }) - }) - }) - }) - }) - }) - }) -}) - -function process_user_step(args) { - var completed = args.completed - var total = args.total - var total_seconds = args.total_seconds - - console.log(completed + " / " + total) - var t0 = performance.now() - - jQuery.ajax({ - type: "POST", - url: ajaxurl, - data: { - action: "relevanssi_index_users", - limit: args.limit, - offset: args.offset, - completed: completed, - total: total, - security: nonce.user_indexing_nonce, - }, - dataType: "json", - success: function (response) { - console.log(response) - if (response.completed == "done") { - var t1 = performance.now() - var time_seconds = (t1 - t0) / 1000 - time_seconds = Math.round(time_seconds * 100) / 100 - total_seconds += time_seconds - - var results_textarea = document.getElementById("results") - results_textarea.value += response.feedback - results_textarea.scrollTop = results_textarea.scrollHeight - var percentage_rounded = Math.round(response.percentage) - - jQuery(".rpi-progress div").animate( - { - width: percentage_rounded + "%", - }, - 50, - function () { - // Animation complete. - } - ) - - console.log("Done indexing users.") - - if (args.taxonomies_total > 0) { - var new_args = { - completed: 0, - total: args.taxonomies_total, - taxonomies: args.taxonomies, - current_taxonomy: "", - post_total: args.post_total, - offset: 0, - total_seconds: total_seconds, - limit: 20, - extend: false, - } - process_taxonomy_step(new_args) - } else { - var new_args = { - security: nonce.indexing_nonce, - completed: 0, - total: args.post_total, - offset: 0, - total_seconds: 0, - limit: relevanssi_params.indexing_limit, - adjust: relevanssi_params.indexing_adjust, - extend: false, - } - process_indexing_step(new_args) - } - } else { - var t1 = performance.now() - var time_seconds = (t1 - t0) / 1000 - time_seconds = Math.round(time_seconds * 100) / 100 - total_seconds += time_seconds - - var estimated_time = rlv_format_approximate_time( - Math.round( - (total_seconds / response.percentage) * 100 - total_seconds - ) - ) - - document.getElementById("relevanssi_estimated").innerHTML = - estimated_time - - if (time_seconds < 2) { - args.limit = args.limit * 2 - // current limit can be indexed in less than two seconds; double the limit - } else if (time_seconds < 5) { - args.limit += 5 - // current limit can be indexed in less than five seconds; up the limit - } else if (time_seconds > 20) { - args.limit = Math.round(args.limit / 2) - if (args.limit < 1) args.limit = 1 - // current limit takes more than twenty seconds; halve the limit - } else if (time_seconds > 10) { - args.limit -= 5 - if (args.limit < 1) args.limit = 1 - // current limit takes more than ten seconds; reduce the limit - } - - var results_textarea = document.getElementById("results") - results_textarea.value += response.feedback - results_textarea.scrollTop = results_textarea.scrollHeight - var percentage_rounded = Math.round(response.percentage) - - jQuery(".rpi-progress div").animate( - { - width: percentage_rounded + "%", - }, - 50, - function () { - // Animation complete. - } - ) - console.log("Next step.") - var new_args = { - completed: parseInt(response.completed), - total: args.total, - total_seconds: total_seconds, - offset: response.offset, - limit: args.limit, - post_total: args.post_total, - taxonomies: args.taxonomies, - taxonomies_total: args.taxonomies_total, - } - process_user_step(new_args) - } - }, - }) -} - -function process_taxonomy_step(args) { - var completed = args.completed - var total = args.total - var total_seconds = args.total_seconds - - console.log(completed + " / " + total) - var t0 = performance.now() - - if (args.current_taxonomy == "") { - taxonomy = args.taxonomies.shift() - args.offset = 0 - args.limit = 20 - } else { - taxonomy = args.current_taxonomy - } - - if (taxonomy != undefined) { - var results_textarea = document.getElementById("results") - results_textarea.value += "Indexing " + "'" + taxonomy + "': " - jQuery.ajax({ - type: "POST", - url: ajaxurl, - data: { - action: "relevanssi_index_taxonomies", - completed: completed, - total: total, - taxonomy: taxonomy, - offset: args.offset, - limit: args.limit, - security: nonce.taxonomy_indexing_nonce, - }, - dataType: "json", - success: function (response) { - console.log(response) - if (response.completed == "done") { - var t1 = performance.now() - var time_seconds = (t1 - t0) / 1000 - time_seconds = Math.round(time_seconds * 100) / 100 - total_seconds += time_seconds - - var results_textarea = document.getElementById("results") - results_textarea.value += response.feedback - - console.log("Done indexing taxonomies.") - - var new_args = { - completed: 0, - total: args.post_total, - offset: 0, - total_seconds: 0, - limit: relevanssi_params.indexing_limit, - adjust: relevanssi_params.indexing_adjust, - extend: false, - security: nonce.indexing_nonce, - } - process_indexing_step(new_args) - } else { - var t1 = performance.now() - var time_seconds = (t1 - t0) / 1000 - time_seconds = Math.round(time_seconds * 100) / 100 - total_seconds += time_seconds - - var estimated_time = rlv_format_approximate_time( - Math.round( - (total_seconds / response.percentage) * 100 - total_seconds - ) - ) - - document.getElementById("relevanssi_estimated").innerHTML = - estimated_time - - if (time_seconds < 2) { - args.limit = args.limit * 2 - // current limit can be indexed in less than two seconds; double the limit - } else if (time_seconds < 5) { - args.limit += 5 - // current limit can be indexed in less than five seconds; up the limit - } else if (time_seconds > 20) { - args.limit = Math.round(args.limit / 2) - if (args.limit < 1) args.limit = 1 - // current limit takes more than twenty seconds; halve the limit - } else if (time_seconds > 10) { - args.limit -= 5 - if (args.limit < 1) args.limit = 1 - // current limit takes more than ten seconds; reduce the limit - } - - var results_textarea = document.getElementById("results") - results_textarea.value += response.feedback - results_textarea.scrollTop = results_textarea.scrollHeight - var percentage_rounded = Math.round(response.percentage) - - jQuery(".rpi-progress div").animate( - { - width: percentage_rounded + "%", - }, - 50, - function () { - // Animation complete. - } - ) - console.log("Next step.") - if (response.new_taxonomy) taxonomy = "" - var new_args = { - taxonomies: args.taxonomies, - completed: parseInt(response.completed), - total: args.total, - total_seconds: total_seconds, - post_total: args.post_total, - current_taxonomy: taxonomy, - offset: response.offset, - limit: args.limit, - } - process_taxonomy_step(new_args) - } - }, - }) - } else { - var new_args = { - completed: 0, - total: args.post_total, - offset: 0, - total_seconds: 0, - limit: relevanssi_params.indexing_limit, - adjust: relevanssi_params.indexing_adjust, - extend: false, - security: nonce.indexing_nonce, - } - process_indexing_step(new_args) - } -} diff --git a/relevanssi-premium/premium/body-stopwords.php b/relevanssi-premium/premium/body-stopwords.php deleted file mode 100644 index 7dacb86b..00000000 --- a/relevanssi-premium/premium/body-stopwords.php +++ /dev/null @@ -1,388 +0,0 @@ - 1 ) { - foreach ( $terms as $term ) { - ++$n; - $term = trim( $term ); - $success = relevanssi_add_single_body_stopword( $term ); - if ( $success ) { - ++$s; - } - } - if ( $verbose ) { - // translators: %1$d is the successful entries, %2$d is the total entries. - printf( "

    %s

    ", sprintf( esc_html__( 'Successfully added %1$d/%2$d terms to content stopwords!', 'relevanssi' ), intval( $s ), intval( $n ) ) ); - } - } else { - // Add to stopwords. - $success = relevanssi_add_single_body_stopword( $term ); - - $term = stripslashes( $term ); - $term = esc_html( $term ); - if ( $verbose ) { - if ( $success ) { - // Translators: %s is the stopword. - printf( "

    %s

    ", sprintf( esc_html__( "Term '%s' added to content stopwords!", 'relevanssi' ), esc_html( stripslashes( $term ) ) ) ); - } else { - // Translators: %s is the stopword. - printf( "

    %s

    ", sprintf( esc_html__( "Couldn't add term '%s' to content stopwords!", 'relevanssi' ), esc_html( stripslashes( $term ) ) ) ); - } - } - } - - return $success; -} - -/** - * Adds a single stopword to the stopword table. - * - * @global object $wpdb The WP database interface. - * @global array $relevanssi_variables The global Relevanssi variables. - * - * @param string $term The term to add. - * - * @return boolean True if success, false if not. - */ -function relevanssi_add_single_body_stopword( $term ) { - if ( empty( $term ) ) { - return false; - } - - $term = stripslashes( relevanssi_strtolower( $term ) ); - $stopwords = relevanssi_fetch_body_stopwords(); - - if ( in_array( $term, $stopwords, true ) ) { - return false; - } - - $stopwords[] = $term; - - $success = relevanssi_update_body_stopwords( $stopwords ); - - if ( ! $success ) { - return false; - } - - global $wpdb, $relevanssi_variables; - - relevanssi_delete_term_from_all_post_content( $term ); - - // Remove all lines with all zeros, ie. no matches. - $wpdb->query( - 'DELETE FROM ' - . $relevanssi_variables['relevanssi_table'] // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - . ' WHERE content + title + comment + tag + link + author + category + excerpt + taxonomy + customfield + mysqlcolumn = 0' - ); - - return true; -} - -/** - * Deletes a term from all posts in the database, language considered. - * - * If Polylang or WPML are used, deletes the term only from the posts matching - * the current language. - * - * @param string $term The term to delete. - */ -function relevanssi_delete_term_from_all_post_content( $term ) { - global $wpdb, $relevanssi_variables; - - if ( function_exists( 'pll_languages_list' ) ) { - $term_id = relevanssi_get_language_term_taxonomy_id( - relevanssi_get_current_language() - ); - - $wpdb->query( - $wpdb->prepare( - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - "UPDATE {$relevanssi_variables['relevanssi_table']} - SET content = 0 - WHERE term=%s - AND doc IN ( - SELECT object_id - FROM $wpdb->term_relationships - WHERE term_taxonomy_id = %d - )", - $term, - $term_id - ) - ); - - return; - } - - if ( function_exists( 'icl_object_id' ) && ! function_exists( 'pll_is_translated_post_type' ) ) { - $language = relevanssi_get_current_language( false ); - $wpdb->query( - $wpdb->prepare( - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - "UPDATE {$relevanssi_variables['relevanssi_table']} - SET content = 0 - WHERE term=%s - AND doc IN ( - SELECT DISTINCT(element_id) - FROM {$wpdb->prefix}icl_translations - WHERE language_code = %s - )", - $term, - $language - ) - ); - - return; - } - - // No language defined, just remove from the index. - $wpdb->query( - $wpdb->prepare( - 'UPDATE ' . $relevanssi_variables['relevanssi_table'] . ' SET content = 0 WHERE term=%s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $term - ) - ); -} - -/** - * Removes all content stopwords in specific language. - * - * Empties the relevanssi_body_stopwords option for particular language. - * - * @param string $language The language code of stopwords. If empty, removes - * the stopwords for the current language. - */ -function relevanssi_remove_all_body_stopwords( $language = null ) { - if ( ! $language ) { - $language = relevanssi_get_current_language(); - } - - $stopwords = get_option( 'relevanssi_body_stopwords', array() ); - unset( $stopwords[ $language ] ); - $success = update_option( 'relevanssi_body_stopwords', $stopwords ); - - if ( $success ) { - printf( - "

    %s

    ", - esc_html__( 'All content stopwords removed! Remember to re-index.', 'relevanssi' ) - ); - } else { - printf( - "

    %s

    ", - esc_html__( "There was a problem, and content stopwords couldn't be removed.", 'relevanssi' ) - ); - } -} - -/** - * Updates the current language content stopwords in the stopwords option. - * - * Fetches the stopwords option, replaces the current language stopwords with - * the parameter array and updates the option. - * - * @param array $stopwords An array of stopwords. - * - * @return boolean The return value from update_option(). - */ -function relevanssi_update_body_stopwords( $stopwords ) { - $current_language = relevanssi_get_current_language(); - $stopwords_option = get_option( 'relevanssi_body_stopwords', array() ); - - $stopwords_option[ $current_language ] = implode( ',', array_filter( $stopwords ) ); - return update_option( - 'relevanssi_body_stopwords', - $stopwords_option - ); -} - -/** - * Removes a single content stopword. - * - * @param string $term The stopword to remove. - * @param boolean $verbose If true, print out a notice. Default true. - * - * @return boolean True if success, false if not. - */ -function relevanssi_remove_body_stopword( $term, $verbose = true ) { - $stopwords = relevanssi_fetch_body_stopwords(); - $term = stripslashes( $term ); - $stopwords = array_filter( - $stopwords, - function ( $stopword ) use ( $term ) { - return $stopword !== $term; - } - ); - - $success = relevanssi_update_body_stopwords( $stopwords ); - - if ( $success ) { - if ( $verbose ) { - printf( - "

    %s

    ", - sprintf( - // Translators: %s is the stopword. - esc_html__( - "Term '%s' removed from content stopwords! Re-index to get it back to index.", - 'relevanssi' - ), - esc_html( stripslashes( $term ) ) - ) - ); - } - return true; - } else { - if ( $verbose ) { - printf( - "

    %s

    ", - sprintf( - // Translators: %s is the stopword. - esc_html__( - "Couldn't remove term '%s' from content stopwords!", - 'relevanssi' - ), - esc_html( stripslashes( $term ) ) - ) - ); - } - return false; - } -} - -/** - * Fetches the list of content stopwords. - * - * Gets the list of content stopwords from the options. - * - * @return array An array of stopwords. - */ -function relevanssi_fetch_body_stopwords() { - $current_language = relevanssi_get_current_language(); - $stopwords_array = get_option( 'relevanssi_body_stopwords', array() ); - $stopwords = isset( $stopwords_array[ $current_language ] ) ? $stopwords_array[ $current_language ] : ''; - $stopword_list = $stopwords ? explode( ',', $stopwords ) : array(); - - return $stopword_list; -} - -/** - * Displays a list of body stopwords. - * - * Displays the list of body stopwords and gives the controls for adding new stopwords. - */ -function relevanssi_show_body_stopwords() { - printf( - '

    %s

    ', - esc_html__( 'Post content stopwords are like stopwords, but they are only applied to the post content. These words can be used for searching and will be found in post titles, custom fields and other indexed content – just not in the post body content. Sometimes a word can be very common, but also have a more specific meaning and use on your site, and making it a content stopword will make it easier to find the specific use cases.', 'relevanssi' ) - ); - ?> - - - - - -
    - - -

    -
    -

    - - - - - - - - - - -
    - - -
      - ', esc_attr( $term ) ); - } - ); - - ?> -
    -

    -
    - - - - -

    -
    - - content - + $match_object->title - + $match_object->comment - + $match_object->link - + $match_object->author - + $match_object->excerpt - + $match_object->customfield - + $match_object->mysqlcolumn - + $match_object->tag - + $match_object->taxonomy - + $match_object->category; - if ( (int) $match_object->content === (int) $sum ) { - $match_object->weight = 0; - } - } - return $match_object; -} diff --git a/relevanssi-premium/premium/class-relevanssi-language-packs.php b/relevanssi-premium/premium/class-relevanssi-language-packs.php deleted file mode 100644 index c54bad3b..00000000 --- a/relevanssi-premium/premium/class-relevanssi-language-packs.php +++ /dev/null @@ -1,211 +0,0 @@ -type = $type; - $this->slug = $slug; - $this->api_url = $api_url; - } - - /** - * Adds a new project to load translations for. - * - * @since 1.0.0 - */ - public function add_project() { - if ( ! has_action( 'init', array( $this, 'register_clean_translations_cache' ) ) ) { - add_action( 'init', array( $this, 'register_clean_translations_cache' ), 9999 ); - } - - /** - * Short-circuits translations API requests for private projects. - */ - add_filter( - 'translations_api', - function ( $result, $requested_type, $args ) { - if ( $this->type . 's' === $requested_type && $this->slug === $args['slug'] ) { - return $this->get_translations( $this->type, $args['slug'], $this->api_url ); - } - - return $result; - }, - 10, - 3 - ); - - /** - * Filters the translations transients to include the private plugin or theme. - * - * @see wp_get_translation_updates() - */ - add_filter( - 'site_transient_update_' . $this->type . 's', - function ( $value ) { - if ( ! $value ) { - $value = new \stdClass(); - } - - if ( ! isset( $value->translations ) ) { - $value->translations = array(); - } - - $translations = $this->get_translations( $this->type, $this->slug, $this->api_url ); - - if ( ! isset( $translations['translations'] ) ) { - return $value; - } - - $installed_translations = wp_get_installed_translations( $this->type . 's' ); - - foreach ( (array) $translations['translations'] as $translation ) { - if ( in_array( $translation['language'], get_available_languages(), true ) ) { - if ( isset( $installed_translations[ $this->slug ][ $translation['language'] ] ) && $translation['updated'] ) { - $local = new DateTime( $installed_translations[ $this->slug ][ $translation['language'] ]['PO-Revision-Date'] ); - $remote = new DateTime( $translation['updated'] ); - - if ( $local >= $remote ) { - continue; - } - } - - $translation['type'] = $this->type; - $translation['slug'] = $this->slug; - - $value->translations[] = $translation; - } - } - - return $value; - } - ); - } - - /** - * Registers actions for clearing translation caches. - * - * @since 1.1.0 - */ - public function register_clean_translations_cache() { - $clear_plugin_translations = function () { - $this->clean_translations_cache( 'plugin' ); - }; - $clear_theme_translations = function () { - $this->clean_translations_cache( 'theme' ); - }; - - add_action( 'set_site_transient_update_plugins', $clear_plugin_translations ); - add_action( 'delete_site_transient_update_plugins', $clear_plugin_translations ); - - add_action( 'set_site_transient_update_themes', $clear_theme_translations ); - add_action( 'delete_site_transient_update_themes', $clear_theme_translations ); - } - - /** - * Clears existing translation cache for a given type. - * - * @since 1.1.0 - * - * @param string $type Project type. Either plugin or theme. - */ - public function clean_translations_cache( $type ) { - $transient_key = 't15s-registry-' . $this->slug . '-' . $type; - $translations = get_site_transient( $transient_key ); - - if ( ! is_object( $translations ) ) { - return; - } - - /* - * Don't delete the cache if the transient gets changed multiple times - * during a single request. Set cache lifetime to maximum 15 seconds. - */ - $cache_lifespan = 15; - $time_not_changed = isset( $translations->_last_checked ) && ( time() - $translations->_last_checked ) > $cache_lifespan; - - if ( ! $time_not_changed ) { - return; - } - - delete_site_transient( $transient_key ); - } - - /** - * Gets the translations for a given project. - * - * @since 1.0.0 - * - * @param string $type Project type. Either plugin or theme. - * @param string $slug Project directory slug. - * @param string $url Full GlotPress API URL for the project. - * - * @return array Translation data. - */ - public function get_translations( $type, $slug, $url ) { - $transient_key = 't15s-registry-' . $slug . '-' . $type; - $translations = get_site_transient( $transient_key ); - - if ( ! is_object( $translations ) ) { - $translations = new \stdClass(); - } - - if ( isset( $translations->{$slug} ) && is_array( $translations->{$slug} ) ) { - return $translations->{$slug}; - } - - $result = json_decode( - wp_remote_retrieve_body( - wp_remote_get( $url, array( 'timeout' => 2 ) ) - ), - true - ); - if ( is_array( $result ) ) { - $translations->{$slug} = $result; - $translations->_last_checked = time(); - - set_site_transient( $transient_key, $translations ); - return $result; - } - - // Nothing found. - return array(); - } -} diff --git a/relevanssi-premium/premium/class-relevanssi-spellcorrector.php b/relevanssi-premium/premium/class-relevanssi-spellcorrector.php deleted file mode 100644 index 191a45f9..00000000 --- a/relevanssi-premium/premium/class-relevanssi-spellcorrector.php +++ /dev/null @@ -1,221 +0,0 @@ - with modifications by Mikko Saari - * @see https://www.relevanssi.com/ - */ - -/* -*************************************************************************** -* Copyright (C) 2008 by Felipe Ribeiro * -* felipernb@gmail.com * -* http://www.feliperibeiro.com * -* * -* Permission is hereby granted, free of charge, to any person obtaining * -* a copy of this software and associated documentation files (the * -* "Software"), to deal in the Software without restriction, including * -* without limitation the rights to use, copy, modify, merge, publish, * -* distribute, sublicense, and/or sell copies of the Software, and to * -* permit persons to whom the Software is furnished to do so, subject to * -* the following conditions: * -* * -* The above copyright notice and this permission notice shall be * -* included in all copies or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* -* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * -* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * -* OTHER DEALINGS IN THE SOFTWARE. * -*************************************************************************** -*/ - -/** - * Spell correcting feature. - * - * This class implements the Spell correcting feature, useful for the - * "Did you mean" functionality on the search engine. Using a dictionary of - * words extracted from the product catalog. - * - * Based on the concepts of Peter Norvig: http://norvig.com/spell-correct.html - * - * @author Felipe Ribeiro - * @date September 18th, 2008 - */ -class Relevanssi_SpellCorrector { - /** - * Dictionary of words. - * - * @var array $dictionary Array of words, containing the dictionary. - */ - private static $dictionary; - - /** - * Reads a text and extracts the list of words. - * - * @param string $text Source text for the words. - * @return array The list of words - */ - private static function words( $text ) { - $matches = array(); - $text = relevanssi_strtolower( $text ); - preg_match_all( '/[a-z]+/', $text, $matches ); - return $matches[0]; - } - - /** - * Generates a list of possible "disturbances" on the passed string. - * - * @param string $word Word to disturb. - * - * @return array A list of variations. - */ - private static function edits1( $word ) { - /** - * Filters the alphabet used for Did you mean suggestions. - * - * In order to use the Did you mean suggestions with non-Latin alphabets - * (or even European languages with a wider range of characters than - * English), Relevanssi needs to be provided with the alphabet used. - * - * @param string A string containing the alphabet as a string of - * characters without spaces. - */ - $alphabet = apply_filters( - 'relevanssi_didyoumean_alphabet', - 'abcdefghijklmnopqrstuvwxyzäöåü' - ); - $alphabet = preg_split( '/(? $max ) { - $max = $value; - $word = $c; - } - } - return $word; - } -} diff --git a/relevanssi-premium/premium/class-relevanssi-wp-auto-update.php b/relevanssi-premium/premium/class-relevanssi-wp-auto-update.php deleted file mode 100644 index 78a8ac82..00000000 --- a/relevanssi-premium/premium/class-relevanssi-wp-auto-update.php +++ /dev/null @@ -1,222 +0,0 @@ -current_version = $current_version; - $this->update_path = $update_path; - $this->plugin_slug = $plugin_slug; - list ($t1, $t2) = explode( '/', $plugin_slug ); - $this->slug = str_replace( '.php', '', $t2 ); - - if ( 'on' !== get_option( 'relevanssi_do_not_call_home' ) ) { - // define the alternative API for updating checking. - add_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'check_update' ) ); - - // Define the alternative response for information checking. - add_filter( 'plugins_api', array( &$this, 'check_info' ), 10, 3 ); - } - } - - /** - * Adds our self-hosted autoupdate plugin to the filter transient. - * - * @param object $transient The filtered transient. - * - * @return object $transient - */ - public function check_update( $transient ) { - if ( ! is_object( $transient ) ) { - return $transient; - } - - // Get the remote version. - $info = $this->get_remote_information(); - $remote_version = 0; - if ( isset( $info->new_version ) ) { - $remote_version = $info->new_version; - } - - // If a newer version is available, add the update. - if ( version_compare( $this->current_version, $remote_version, '<' ) ) { - $obj = new stdClass(); - $obj->slug = $this->slug; - $obj->new_version = $remote_version; - $obj->url = $info->package; - $obj->package = $info->package; - $obj->icons = $info->icons; - $obj->banners = $info->banners; - - $transient->response[ $this->plugin_slug ] = $obj; - } else { - global $relevanssi_variables; - // No update is available. - $item = (object) array( - 'id' => 'relevanssi-premium/relevanssi.php', - 'slug' => 'relevanssi-premium', - 'plugin' => 'relevanssi-premium/relevanssi.php', - 'new_version' => $relevanssi_variables['plugin_version'], - 'url' => '', - 'package' => '', - 'icons' => array(), - 'banners' => array(), - 'banners_rtl' => array(), - 'tested' => '', - 'requires_php' => '', - 'compatibility' => new stdClass(), - ); - $transient->no_update['relevanssi-premium/relevanssi.php'] = $item; - } - - return $transient; - } - - /** - * Adds our self-hosted description to the filter. - * - * @param object $api Result object or array, should return false. - * @param array $action Type of information request. - * @param object $args Plugin API arguments. - * - * @return object $api New stdClass with plugin information on success, default response on failure. - */ - public function check_info( $api, $action, $args ) { - $plugin = ( 'plugin_information' === $action ) && isset( $args->slug ) && ( $this->slug === $args->slug ); - - if ( $plugin ) { - if ( $args->slug === $this->slug ) { - $information = $this->get_remote_information(); - return $information; - } - } - return $api; - } - - /** - * Returns the remote version. - * - * @return string $remote_version Version number at the remote end. - */ - public function get_remote_version() { - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - $request = wp_remote_post( - $this->update_path, - array( - 'body' => array( - 'api_key' => $api_key, - 'action' => 'version', - ), - ) - ); - if ( ! is_wp_error( $request ) || 200 === wp_remote_retrieve_response_code( $request ) ) { - return $request['body']; - } - return false; - } - - /** - * Get information about the remote version. - * - * @return bool|object - */ - public function get_remote_information() { - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - $request = wp_remote_post( - $this->update_path, - array( - 'body' => array( - 'api_key' => $api_key, - 'action' => 'info', - ), - ) - ); - if ( ! is_wp_error( $request ) || 200 === wp_remote_retrieve_response_code( $request ) ) { - if ( is_serialized( $request['body'] ) ) { - return unserialize( $request['body'] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions - } - } - return false; - } - - /** - * Returns the status of the plugin licensing. - * - * @return boolean $remote_license - */ - public function get_remote_license() { - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - $request = wp_remote_post( - $this->update_path, - array( - 'body' => array( - 'api_key' => $api_key, - 'action' => 'license', - ), - ) - ); - if ( ! is_wp_error( $request ) || 200 === wp_remote_retrieve_response_code( $request ) ) { - if ( 'false' === $request['body'] ) { - return false; - } - return $request['body']; - } - return false; - } -} diff --git a/relevanssi-premium/premium/class-relevanssi-wp-cli-command.php b/relevanssi-premium/premium/class-relevanssi-wp-cli-command.php deleted file mode 100644 index cb8f68b4..00000000 --- a/relevanssi-premium/premium/class-relevanssi-wp-cli-command.php +++ /dev/null @@ -1,714 +0,0 @@ -] - * : What to index. No value means everything. Valid values are - * "taxonomies" and "users" to index taxonomy terms and user profiles - * respectively. - * --- - * options: - * - post_types - * - taxonomies - * - users - * --- - * - * [--post=] - * : Post ID, if you only want to reindex one post. - * - * [--limit=] - * : Number of posts you want to index at one go. - * - * [--extend=] - * : If true, do not truncate the index or index users and taxonomies. - * If false, first truncate the index, then index user profiles and - * taxonomy terms. - * --- - * default: false - * options: - * - true - * - false - * --- - * - * [--index_debug=] - * : If true, display debugging information when indexing a single post. - * --- - * default: false - * options: - * - true - * - false - * --- - * - * ## EXAMPLES - * - * wp relevanssi index - * wp relevanssi index --post=1 - * wp relevanssi index --target=taxonomies - * wp relevanssi index --target=users - * wp relevanssi index --post=1 --index_debug=true - * wp relevanssi index --limit=100 - * wp relevanssi index --extend=true --limit=100 - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function index( $args, $assoc_args ) { - remove_filter( 'relevanssi_search_ok', '__return_true' ); - - $post_id = null; - if ( isset( $assoc_args['post'] ) ) { - $post_id = $assoc_args['post']; - } - - $limit = null; - if ( isset( $assoc_args['limit'] ) ) { - $limit = $assoc_args['limit']; - } - - $extend = false; - if ( isset( $assoc_args['extend'] ) ) { - $extend = $assoc_args['extend']; - } - - $debug = false; - if ( isset( $assoc_args['index_debug'] ) ) { - $debug = $assoc_args['index_debug']; - } - - $target = null; - if ( isset( $assoc_args['target'] ) ) { - $target = $assoc_args['target']; - } - - if ( 'taxonomies' === $target ) { - relevanssi_index_taxonomies(); - WP_CLI::success( 'Done!' ); - } elseif ( 'users' === $target ) { - relevanssi_index_users(); - WP_CLI::success( 'Done!' ); - } elseif ( 'post_types' === $target ) { - relevanssi_index_post_type_archives(); - WP_CLI::success( 'Done!' ); - } elseif ( isset( $post_id ) ) { - $n = relevanssi_index_doc( $post_id, true, relevanssi_get_custom_fields(), true, $debug ); - switch ( $n ) { - case -1: - WP_CLI::error( "No such post: $post_id!" ); - break; - case 'hide': - WP_CLI::error( "Post $post_id is excluded from indexing." ); - break; - case 'donotindex': - WP_CLI::error( "Post $post_id is excluded from indexing by the relevanssi_do_not_index filter." ); - break; - default: - WP_CLI::success( "Reindexed post $post_id!" ); - } - } else { - $verbose = false; - list( $complete, $n ) = relevanssi_build_index( $extend, $verbose, $limit ); - - $completion = 'Index is not complete yet.'; - if ( $complete ) { - $completion = 'Index is complete.'; - } - - WP_CLI::success( "$n posts indexed. $completion" ); - } - } - - /** - * Refreshes the Relevanssi index. - * - * ## EXAMPLES - * - * wp relevanssi refresh - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function refresh( $args, $assoc_args ) { - $index_post_types = get_option( 'relevanssi_index_post_types', '' ); - $index_statuses = apply_filters( - 'relevanssi_valid_status', - array( 'publish', 'private', 'draft', 'pending', 'future' ) - ); - $all_indexed_posts = get_posts( - array( - 'post_type' => $index_post_types, - 'fields' => 'ids', - 'numberposts' => -1, - 'post_status' => $index_statuses, - ) - ); - - $found_posts = count( $all_indexed_posts ); - $progress = $this->relevanssi_generate_progress_bar( 'Indexing posts', $found_posts ); - - WP_CLI::log( 'Found ' . $found_posts . ' posts to refresh.' ); - foreach ( $all_indexed_posts as $post_id ) { - relevanssi_index_doc( $post_id, true, relevanssi_get_custom_fields(), true, false ); - $progress->tick(); - } - $progress->finish(); - - WP_CLI::success( 'Index refresh done!' ); - } - - /** - * Empties the Relevanssi index. - * - * ## EXAMPLES - * - * wp relevanssi truncate_index - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function truncate_index( $args, $assoc_args ) { - $result = relevanssi_truncate_index(); - switch ( $result ) { - case false: - WP_CLI::error( "Couldn't truncate the Relevanssi database!" ); - break; - default: - WP_CLI::success( 'Relevanssi database truncated.' ); - } - } - - /** - * Adds a stopword to the list of stopwords and removes it from the index. - * - * ## OPTIONS - * - * ... - * : Stopwords to add. - * - * ## EXAMPLES - * - * wp relevanssi add_stopword stop halt seis - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function add_stopword( $args, $assoc_args ) { - if ( is_array( $args ) ) { - foreach ( $args as $stopword ) { - if ( relevanssi_add_single_stopword( $stopword ) ) { - WP_CLI::success( "Stopword added: $stopword" ); - } else { - WP_CLI::error( "Couldn't add stopword: $stopword!" ); - } - } - } else { - WP_CLI::error( 'No stopwords listed.' ); - } - } - - /** - * Removes a stopword from the list of stopwords. Reindex to get it back to the index. - * - * ## OPTIONS - * - * ... - * : Stopwords to remove. - * - * ## EXAMPLES - * - * wp relevanssi remove_stopword stop halt seis - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function remove_stopword( $args, $assoc_args ) { - $verbose = false; - if ( is_array( $args ) ) { - foreach ( $args as $stopword ) { - if ( relevanssi_remove_stopword( $stopword, $verbose ) ) { - WP_CLI::success( "Stopword removed: $stopword" ); - } else { - WP_CLI::error( "Couldn't remove stopword: $stopword!" ); - } - } - } else { - WP_CLI::error( 'No stopwords listed.' ); - } - } - - /** - * Empties the Relevanssi logs. - * - * ## EXAMPLES - * - * wp relevanssi reset_log - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function reset_log( $args, $assoc_args ) { - $verbose = false; - $result = relevanssi_truncate_logs( $verbose ); - switch ( $result ) { - case false: - WP_CLI::error( "Couldn't reset the logs!" ); - break; - default: - WP_CLI::success( 'Relevanssi log truncated.' ); - } - } - - /** - * Shows common words in the index. - * - * ## OPTIONS - * - * [--limit=] - * : How many words to show. Defaults to 25. - * - * ## EXAMPLES - * - * wp relevanssi common - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function common( $args, $assoc_args ) { - $wp_cli = true; - $limit = 25; - if ( isset( $assoc_args['limit'] ) && is_numeric( $assoc_args['limit'] ) ) { - $limit = $assoc_args['limit']; - } - - $words = relevanssi_common_words( $limit, $wp_cli ); - if ( is_array( $words ) ) { - foreach ( $words as $word ) { - WP_CLI::log( sprintf( '%s (%d)', $word->term, $word->cnt ) ); - } - } else { - WP_CLI::error( 'No words returned.' ); - } - } - - /** - * Reads the attachment content for all attachments that haven't been read - * yet. - * - * ## EXAMPLES - * - * wp relevanssi read_attachments - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function read_attachments( $args, $assoc_args ) { - $attachment_posts = relevanssi_get_posts_with_attachments( 0 ); - WP_CLI::log( 'Found ' . count( $attachment_posts ) . ' attachments to read.' ); - foreach ( $attachment_posts as $post_id ) { - $exit_and_die = false; - WP_CLI::log( 'Reading attachment ' . $post_id . '...' ); - $response = relevanssi_index_pdf( $post_id, $exit_and_die ); - if ( $response['success'] ) { - WP_CLI::log( "Successfully read the content for post $post_id." ); - } else { - WP_CLI::log( "Couldn't read the post $post_id: " . $response['error'] ); - } - } - } - - /** - * Removes all attachment content for all posts. Use with care! Does not - * reindex the posts or remove them from the index. - * - * ## EXAMPLES - * - * wp relevanssi remove_attachment_content - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array (not - * used). - */ - public function remove_attachment_content( $args, $assoc_args ) { - delete_post_meta_by_key( '_relevanssi_pdf_content' ); - delete_post_meta_by_key( '_relevanssi_pdf_error' ); - - WP_CLI::log( 'Removed all attachment content.' ); - } - - /** - * Removes all attachment errors for all posts. - * - * ## EXAMPLES - * - * wp relevanssi remove_attachment_errors - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array (not - * used). - */ - public function remove_attachment_errors( $args, $assoc_args ) { - delete_post_meta_by_key( '_relevanssi_pdf_error' ); - - WP_CLI::log( 'Removed all attachment errors.' ); - } - - /** - * Regenerates the related posts for all posts. - * - * ## OPTIONS - * - * [--post_type=] - * : A comma-separated list of post types to cover. If empty, generate the post - * types chosen in the Related posts options, or if that's empty, all public post - * types. - * - * [--post_objects=] - * : If true, doesn't generate the related posts HTML code and instead stores the - * post objects of the related posts in the transient. If false, the transient - * will contain the generated related posts HTML code. Default false. - * --- - * default: false - * options: - * - true - * - false - * --- - * - * ## EXAMPLES - * - * wp relevanssi regenerate_related - * wp relevanssi regenerate_related --post_type=post,page - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function regenerate_related( $args, $assoc_args ) { - relevanssi_flush_related_cache(); - - $settings = get_option( 'relevanssi_related_settings', relevanssi_related_default_settings() ); - - if ( isset( $settings['enabled'] ) && 'off' === $settings['enabled'] ) { - WP_CLI::error( 'Related posts feature is disabled.' ); - } - - $post_types = array(); - if ( isset( $settings['append'] ) && ! empty( $settings['append'] ) ) { - // Related posts are automatically appended to certain post types, so - // regenerate the related posts for those post types. - $post_types = explode( ',', $settings['append'] ); - } else { - // Nothing set, so regenerate for all public post types. - $pt_args = array( - 'public' => true, - ); - $post_types = get_post_types( $pt_args, 'names' ); - } - - if ( isset( $assoc_args['post_type'] ) ) { - $post_types = explode( ',', $assoc_args['post_type'] ); - } - - $post_objects = false; - if ( isset( $assoc_args['post_objects'] ) ) { - if ( filter_var( $assoc_args['post_objects'], FILTER_VALIDATE_BOOLEAN ) ) { - $post_objects = true; - } - } - - $post_args = array( - 'post_type' => $post_types, - 'fields' => 'ids', - 'posts_per_page' => -1, - ); - $posts = get_posts( $post_args ); // Get all posts for the wanted post types. - $count = count( $posts ); - WP_CLI::log( 'Regenerating related posts for post types ' . implode( ', ', $post_types ) . ", total $count posts." ); - - $progress = $this->relevanssi_generate_progress_bar( 'Regenerating', $count ); - - foreach ( $posts as $post_id ) { - relevanssi_related_posts( $post_id, $post_objects ); - $progress->tick(); - } - - $progress->finish(); - WP_CLI::success( 'Done!' ); - } - - /** - * Lists pinned posts. - * - * ## OPTIONS - * - * [--format=] - * : Format of the results. Possible values are "table", "json", "csv", - * "yaml" and "count". Default: "table". - * - * [--type=] - * : Type of the results. Possible values are "pinned", "unpinned", and - * "both". Default: "both". - * - * ## EXAMPLES - * - * wp relevanssi list_pinned_posts - * wp relevanssi list_pinned_posts --format=csv --type=pinned - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function list_pinned_posts( $args, $assoc_args ) { - global $wpdb; - - $posts = $wpdb->get_results( - "SELECT p.ID, p.post_title, pm.meta_key, pm.meta_value FROM $wpdb->posts AS p, $wpdb->postmeta AS pm - WHERE p.ID = pm.post_id - AND ( - pm.meta_key = '_relevanssi_pin' - OR pm.meta_key = '_relevanssi_unpin' - OR ( - pm.meta_key = '_relevanssi_pin_for_all' AND pm.meta_value = 'on' - ) - ) - ORDER BY p.ID ASC" - ); - - $pinned = array(); - $unpinned = array(); - - $format = $assoc_args['format'] ?? 'table'; - if ( 'ids' === $format ) { - $format = 'table'; - } - - $include_pinned = true; - $include_unpinned = true; - if ( isset( $assoc_args['type'] ) ) { - if ( 'pinned' === $assoc_args['type'] ) { - $include_unpinned = false; - } elseif ( 'unpinned' === $assoc_args['type'] ) { - $include_pinned = false; - } - } - - foreach ( $posts as $post ) { - if ( $include_pinned && '_relevanssi_pin_for_all' === $post->meta_key ) { - $pinned[] = array( - 'ID' => $post->ID, - 'Title' => $post->post_title, - 'Pinned keywords' => __( 'all keywords' ), - ); - } elseif ( $include_pinned && '_relevanssi_pin' === $post->meta_key ) { - $pinned[] = array( - 'ID' => $post->ID, - 'Title' => $post->post_title, - 'Pinned keywords' => $post->meta_value, - ); - } elseif ( $include_unpinned && '_relevanssi_unpin' === $post->meta_key ) { - $unpinned[] = array( - 'ID' => $post->ID, - 'Title' => $post->post_title, - 'Unpinned keywords' => $post->meta_value, - ); - } - } - - if ( $pinned ) { - if ( 'table' === $format || 'count' === $format ) { - $header = "\n" . __( 'Pinned posts' ) . ':'; - WP_CLI::log( $header ); - WP_CLI::log( str_pad( '', strlen( $header ), '=' ) ); - } - WP_CLI\Utils\format_items( $format, $pinned, array( 'ID', 'Title', 'Pinned keywords' ) ); - } - - if ( $unpinned ) { - if ( 'table' === $format || 'count' === $format ) { - $header = "\n" . __( 'Unpinned posts' ) . ':'; - WP_CLI::log( $header ); - WP_CLI::log( str_pad( '', strlen( $header ), '=' ) ); - } - WP_CLI\Utils\format_items( $format, $unpinned, array( 'ID', 'Title', 'Unpinned keywords' ) ); - } - - if ( ! $pinned && ! $unpinned ) { - WP_CLI::log( __( 'No pinned posts found.' ) ); - } - } - - /** - * Lists posts in or not in the index. - * - * ## OPTIONS - * - * [--format=] - * : Format of the results. Possible values are "table", "json", "csv", - * "yaml", and "count". Default: "table". - * - * [--post_type=] - * : Post type. Default: none, show all post types. - * - * [--type=] - * : Type of the results. Possible values are "post", "term", and "user". - * Default: "post". - * - * [--status=] - * : Status of the results. Possible values are "indexed" and "unindexed". - * Default: "indexed". - * - * ## EXAMPLES - * - * wp relevanssi list - * - * @param array $args Command arguments (not used). - * @param array $assoc_args Command arguments as associative array. - */ - public function list( $args, $assoc_args ) { - global $wpdb, $relevanssi_variables; - - $status = $assoc_args['status'] ?? 'indexed'; - $post_type = $assoc_args['post_type'] ?? ''; - $type = $assoc_args['type'] ?? 'post'; - - if ( 'indexed' === $status ) { - if ( 'post' === $type ) { - if ( $post_type ) { - $post_type = "AND post_type = '" . esc_sql( $post_type ) . "'"; - } - $posts = $wpdb->get_results( - "SELECT DISTINCT(p.ID), p.post_title AS Title, p.post_type AS 'Type' FROM $wpdb->posts AS p, " . - "{$relevanssi_variables['relevanssi_table']} AS r WHERE p.ID = r.doc $post_type " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'ORDER BY p.ID ASC' - ); - } elseif ( 'term' === $type ) { - $posts = $wpdb->get_results( - "SELECT DISTINCT(t.term_id) AS ID, t.name AS 'Name', tt.taxonomy AS 'Taxonomy', tt.count AS 'Count' FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt, " . - "{$relevanssi_variables['relevanssi_table']} AS r " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE tt.term_id = t.term_id AND t.term_id = r.item AND tt.taxonomy = r.type - ORDER BY t.term_id ASC' - ); - } elseif ( 'user' === $type ) { - $users_in_index = $wpdb->get_col( - "SELECT DISTINCT(r.item) FROM {$relevanssi_variables['relevanssi_table']} AS r " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - "WHERE r.type = 'user'" - ); - $users = relevanssi_get_users( - array( - 'number' => -1, - 'orderby' => 'ID', - 'order' => 'ASC', - 'include' => array_map( 'intval', $users_in_index ), - ) - ); - foreach ( $users as $user ) { - $posts[] = array( - 'ID' => $user->ID, - 'Name' => $user->display_name, - 'Login' => $user->user_login, - 'Roles' => implode( ', ', $user->roles ), - ); - } - } - } elseif ( 'unindexed' === $status ) { - if ( 'post' === $type ) { - $indexed_post_types = str_replace( 'post.', 'p.', relevanssi_post_type_restriction() ); - if ( $post_type ) { - $post_type = "AND post_type = '" . esc_sql( $post_type ) . "'"; - $indexed_post_types = ''; - } - - $posts = $wpdb->get_results( - "SELECT DISTINCT(p.ID), p.post_title AS Title, p.post_type AS 'Type' FROM $wpdb->posts AS p " . - "LEFT JOIN {$relevanssi_variables['relevanssi_table']} AS r ON p.ID = r.doc " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE r.doc IS NULL ' . - "$indexed_post_types $post_type " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'ORDER BY p.ID ASC' - ); - } elseif ( 'term' === $type ) { - $taxonomies = get_option( 'relevanssi_index_terms' ); - if ( ! is_array( $taxonomies ) ) { - $taxonomies = array(); - } - $taxonomies = "'" . implode( "', '", $taxonomies ) . "'"; - - $posts = $wpdb->get_results( - "SELECT DISTINCT(t.term_id) AS ID, t.name AS 'Name', tt.taxonomy AS 'Taxonomy', tt.count AS 'Count' " . - "FROM $wpdb->term_taxonomy AS tt, $wpdb->terms AS t " . - "LEFT JOIN {$relevanssi_variables['relevanssi_table']} AS r " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'ON t.term_id = r.item - WHERE r.item IS NULL AND tt.term_id = t.term_id AND tt.taxonomy IN (' . $taxonomies . ') ' . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'ORDER BY t.term_id ASC' - ); - } elseif ( 'user' === $type ) { - $users_in_index = $wpdb->get_col( - "SELECT DISTINCT(r.item) FROM {$relevanssi_variables['relevanssi_table']} AS r " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared - "WHERE r.type = 'user'" - ); - $users = relevanssi_get_users( - array( - 'number' => -1, - 'orderby' => 'ID', - 'order' => 'ASC', - 'exclude' => $users_in_index, - ) - ); - foreach ( $users as $user ) { - $posts[] = array( - 'ID' => $user->ID, - 'Name' => $user->display_name, - 'Login' => $user->user_login, - 'Roles' => implode( ', ', $user->roles ), - ); - } - } - } - - $format = $assoc_args['format'] ?? 'table'; - if ( 'ids' === $format ) { - $format = 'table'; - } - - if ( 'post' === $type ) { - WP_CLI\Utils\format_items( $format, $posts, array( 'ID', 'Title', 'Type' ) ); - } elseif ( 'term' === $type ) { - WP_CLI\Utils\format_items( $format, $posts, array( 'ID', 'Name', 'Taxonomy', 'Count' ) ); - } elseif ( 'user' === $type ) { - WP_CLI\Utils\format_items( $format, $posts, array( 'ID', 'Name', 'Login', 'Roles' ) ); - } elseif ( 'post_type' === $type ) { - WP_CLI\Utils\format_items( $format, $posts, array( 'Title', 'Type' ) ); - } - } - - /** - * Generates a WP CLI progress bar. - * - * If WP CLI is enabled, creates a progress bar using WP_CLI\Utils\make_progress_bar(). - * - * @param string $title Title of the progress bar. - * @param int $count Total count for the bar. - */ - public static function relevanssi_generate_progress_bar( $title, $count ) { - $progress = null; - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress = WP_CLI\Utils\make_progress_bar( $title, $count ); - } - return $progress; - } -} - -WP_CLI::add_command( 'relevanssi', 'Relevanssi_WP_Cli_Command' ); diff --git a/relevanssi-premium/premium/click-tracking.php b/relevanssi-premium/premium/click-tracking.php deleted file mode 100644 index 8444e017..00000000 --- a/relevanssi-premium/premium/click-tracking.php +++ /dev/null @@ -1,1035 +0,0 @@ -query( - $wpdb->prepare( - "INSERT IGNORE INTO {$relevanssi_variables['tracking_table']} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - '(`post_id`, `query`, `rank`, `page`, `timestamp`) VALUES (%d, %s, %d, %d, %s)', - $post->ID, - $rt['query'], - $rt['rank'], - $rt['page'], - gmdate( 'c', $rt['time'] ) - ) - ); -} - -/** - * Extracts the values from the _rt URL parameter. - * - * @param string $rt The URL parameter. - * - * @return array|WP_Error An array of values: 'rank', 'page', 'query', and - * 'time'. Returns a WP_Error if the value doesn't explode into right number of - * parts. - */ -function relevanssi_extract_rt( string $rt ) { - $rt_values = explode( '|', $rt ); - if ( count( $rt_values ) !== 4 ) { - return new WP_Error( 'invalid-rt', __( 'Invalid click tracking value format.', 'relevanssi' ) ); - } - $rank = intval( $rt_values[0] ); - $page = intval( $rt_values[1] ); - $time = intval( $rt_values[3] ); - if ( 0 === $rank || 0 === $page || 0 === $time ) { - return new WP_Error( 'invalid-rt', __( 'Invalid click tracking value format.', 'relevanssi' ) ); - } - return array( - 'rank' => $rank, - 'page' => $page, - 'query' => $rt_values[2], - 'time' => $time, - ); -} - -/** - * Adds tracking information to a permalink. - * - * Called from the `relevanssi_permalink` filter function to add the tracking - * data to the link. - * - * @param string $permalink The permalink to modify. - * @param object $link_post A post object, default null in which case the global - * $post is used. - * - * @global $relevanssi_tracking_positions An array of post ID => rank pairs used - * to get the post rankings. If a post does not appear in this array, the - * tracking data is not added to the permalink. - * @global $relevanssi_tracking_permalink A cache of permalinks to avoid doing - * work that is already done. - * - * @return string The modified permalink. - */ -function relevanssi_add_tracking( string $permalink, $link_post = null ): string { - if ( 'on' !== get_option( 'relevanssi_click_tracking', 'off' ) ) { - return $permalink; - } - if ( empty( get_search_query() ) ) { - return $permalink; - } - if ( ! relevanssi_is_ok_to_log() ) { - return $permalink; - } - if ( ! $link_post ) { - global $post; - $link_post = $post; - } - $id = relevanssi_get_post_identifier( $link_post ); - if ( ! isset( $link_post->blog_id ) || get_current_blog_id() === $link_post->blog_id ) { - if ( relevanssi_is_front_page_id( $link_post->ID ) ) { - return $permalink; - } - } - - global $relevanssi_tracking_positions, $relevanssi_tracking_permalink; - $position = $relevanssi_tracking_positions[ $id ] ?? null; - - if ( ! $position ) { - return $permalink; - } - - if ( isset( $relevanssi_tracking_permalink[ $id ] ) ) { - return $relevanssi_tracking_permalink[ $id ]; - } - - $page = get_query_var( 'paged' ) > 0 ? get_query_var( 'paged' ) : 1; - $nonce = wp_create_nonce( 'relevanssi_click_tracking_' . $id ); - $query = relevanssi_strtolower( str_replace( '|', ' ', get_search_query() ) ); - $time = time(); - $value = "$position|$page|$query|$time"; - - $permalink = esc_attr( - add_query_arg( - array( - '_rt' => relevanssi_base64url_encode( $value ), - '_rt_nonce' => $nonce, - ), - $permalink - ) - ); - - $relevanssi_tracking_permalink[ $id ] = $permalink; - - return $permalink; -} - -/** - * URL-friendly base64 encode. - * - * @param string $data String to encode. - * @return string Encoded string. - */ -function relevanssi_base64url_encode( string $data ): string { - return rtrim( - strtr( - base64_encode( $data ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions - '+/', - '-_' - ), - '=' - ); -} - -/** - * URL-friendly base64 decode. - * - * @param string $data String to decode. - * @return string Decoded string. - */ -function relevanssi_base64url_decode( string $data ): string { - return base64_decode( // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions - strtr( $data, '-_', '+/' ) - ); -} - -/** - * Records the ranking positions for the posts found. - * - * Runs as the last thing (at PHP_INT_MAX) on the `relevanssi_hits_filter` hook - * to record the ranking positions of each post. - * - * @global array $relevanssi_tracking_positions An array of post ID => rank - * pairs. - * - * @param array $hits The hits found. - * - * @return array The hits found, unmodified. - */ -function relevanssi_record_positions( array $hits ): array { - global $relevanssi_tracking_positions; - - $position = 0; - foreach ( $hits[0] as $hit ) { - ++$position; - $hit = relevanssi_get_an_object( $hit )['object']; - if ( ! $hit ) { - continue; - } - if ( $hit->ID > 0 ) { - $id = relevanssi_get_post_identifier( $hit ); - - $relevanssi_tracking_positions[ $id ] = $position; - } elseif ( isset( $hit->term_id ) ) { - $relevanssi_tracking_positions[ $hit->post_type . '_' . $hit->term_id ] = $position; - } elseif ( isset( $hit->user_id ) ) { - $relevanssi_tracking_positions[ 'user_' . $hit->user_id ] = $position; - } - } - - return $hits; -} - -/** - * Removes the undisplayed posts from the $relevanssi_tracking_positions array. - * - * Goes through the $relevanssi_tracking_positions array and only keeps the - * posts that appear on the current page of results. - * - * @global array $relevanssi_tracking_positions An array of post ID => rank - * pairs. - * - * @param array $hits The hits displayed. - * - * @return array The hits displayed, unmodified. - */ -function relevanssi_current_page_hits( array $hits ): array { - global $relevanssi_tracking_positions; - - $all_positions = $relevanssi_tracking_positions; - $relevanssi_tracking_positions = array(); - - foreach ( $hits as $hit ) { - $hit = relevanssi_get_an_object( $hit )['object']; - $id = relevanssi_get_post_identifier( $hit ); - - if ( $hit->ID > 0 ) { - $relevanssi_tracking_positions[ $id ] = $all_positions[ $id ]; - } elseif ( isset( $hit->term_id ) ) { - $id = $hit->post_type . '_' . $hit->term_id; - - $relevanssi_tracking_positions[ $id ] = $all_positions[ $id ]; - } elseif ( isset( $hit->user_id ) ) { - $id = 'user_' . $hit->user_id; - - $relevanssi_tracking_positions[ $id ] = $all_positions[ $id ]; - } - } - - return $hits; -} - -/** - * Creates the tracking table. - * - * @param string $charset_collate Character set collation. - * - * @return void - */ -function relevanssi_create_tracking_table( string $charset_collate ) { - global $wpdb; - - $sql = 'CREATE TABLE ' . $wpdb->prefix . 'relevanssi_tracking ' . - "(`id` int(11) NOT NULL AUTO_INCREMENT, - `post_id` int(11) NOT NULL DEFAULT '0', - `query` varchar(200) NOT NULL, - `rank` int(11) NOT NULL DEFAULT '0', - `page` int(11) NOT NULL DEFAULT '0', - `timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY id (id), - UNIQUE INDEX post_id_timestamp (post_id, timestamp)) $charset_collate"; - - dbDelta( $sql ); -} - -/** - * Generates an array with date indices and 0 values for each date. - * - * Uses the `relevanssi_trim_click_logs` option to determine the length of the - * date range. - * - * @param string $type The type of date count: 'clicks', 'log' or 'both'. - * - * @return array An array of 'Y-m-d' date indices. - */ -function relevanssi_default_date_count( string $type ): array { - global $wpdb, $relevanssi_variables; - - if ( 'clicks' === $type ) { - $amount_of_days = get_option( 'relevanssi_trim_click_logs', 90 ); - } - if ( 'log' === $type ) { - $amount_of_days = get_option( 'relevanssi_trim_logs', 30 ); - if ( 0 === $amount_of_days ) { - $amount_of_days = abs( $wpdb->get_var( "SELECT TIMESTAMPDIFF(DAY, NOW(), time) FROM {$relevanssi_variables['log_table']} ORDER BY time ASC LIMIT 1" ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared. - } - } - if ( 'both' === $type ) { - $click_days = get_option( 'relevanssi_trim_click_logs', 90 ); - $log_days = get_option( 'relevanssi_trim_logs', 30 ); - - if ( '0' === $log_days ) { - $log_days = abs( $wpdb->get_var( "SELECT TIMESTAMPDIFF(DAY, NOW(), time) FROM {$relevanssi_variables['log_table']} ORDER BY time ASC LIMIT 1" ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared. - } - $amount_of_days = max( $click_days, $log_days ); - } - $date_counts = array(); - $start_date = gmdate( 'Y-m-d', strtotime( intval( $amount_of_days ) . ' days ago' ) ); - $end_date = gmdate( 'Y-m-d' ); - - while ( strtotime( $start_date ) <= strtotime( $end_date ) ) { - $date_counts[ $start_date ] = 0; - - $start_date = gmdate( - 'Y-m-d', - strtotime( '+1 days', strtotime( $start_date ) ) - ); - } - - return $date_counts; -} - -/** - * Determines what happens when a request for a post insights screen is made. - * - * @param array $request The $_REQUEST array to dig for parameters. - * - * @return bool True, if a screen was displayed and false if not. - */ -function relevanssi_handle_insights_screens( array $request ): bool { - if ( isset( $request['insights'] ) ) { - if ( isset( $request['action'] ) && isset( $request['query'] ) && 'delete_query' === $request['action'] ) { - check_admin_referer( 'relevanssi_delete_query' ); - relevanssi_delete_query( $request['query'] ); - } - if ( isset( $request['action'] ) && isset( $request['query'] ) && 'delete_query_from_log' === $request['action'] ) { - check_admin_referer( 'relevanssi_delete_query' ); - relevanssi_delete_query_from_log( $request['query'] ); - } - relevanssi_show_insights( stripslashes( $request['insights'] ) ); - return true; - } - - if ( isset( $request['post_insights'] ) ) { - relevanssi_show_post_insights( $request['post_insights'] ); - return true; - } - - return false; -} - -/** - * Deletes a query from the click tracking database. - * - * @param string $query The query to delete. - */ -function relevanssi_delete_query( string $query ) { - global $wpdb, $relevanssi_variables; - - $deleted = $wpdb->query( - $wpdb->prepare( - "DELETE FROM {$relevanssi_variables['tracking_table']} WHERE query = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - stripslashes( $query ) - ) - ); - - if ( $deleted ) { - printf( - "

    %s

    ", - sprintf( - // Translators: %s is the stopword. - esc_html__( - "The query '%s' deleted from the click tracking log.", - 'relevanssi' - ), - esc_html( stripslashes( $query ) ) - ) - ); - } else { - printf( - "

    %s

    ", - sprintf( - // Translators: %s is the stopword. - esc_html__( - "Couldn't remove the query '%s' from the click tracking log.", - 'relevanssi' - ), - esc_html( stripslashes( $query ) ) - ) - ); - - } -} - -/** - * Displays the search query insights screen. - * - * Prints out the display for a single search query insights screen. - * - * @param string $query The search query. - */ -function relevanssi_show_insights( string $query ) { - global $wpdb, $relevanssi_variables; - - ?> - - ' . - // Translators: %s is the search query string. - esc_html__( 'Search insights for %s', 'relevanssi' ) . - '', - esc_html( '"' . $query . '"' ) - ); - - $results = $wpdb->get_results( - $wpdb->prepare( - 'SELECT * FROM ' . $relevanssi_variables['tracking_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE query = %s', - $query - ) - ); - - $posts = array(); - $post_average_rank = array(); - $post_average_page = array(); - $date_counts = relevanssi_default_date_count( 'both' ); - $oldest_date = array_keys( $date_counts )[0]; - foreach ( $results as $row ) { - if ( $row->timestamp < $oldest_date ) { - continue; - } - relevanssi_increase_value( $posts[ $row->post_id ] ); - relevanssi_increase_value( $post_average_rank[ $row->post_id ], $row->rank ); - relevanssi_increase_value( $post_average_page[ $row->post_id ], $row->page ); - relevanssi_increase_value( $date_counts[ gmdate( 'Y-m-d', strtotime( $row->timestamp ) ) ] ); - } - - relevanssi_average_array( $post_average_rank, $posts ); - relevanssi_average_array( $post_average_page, $posts ); - - $results = $wpdb->get_results( - $wpdb->prepare( - 'SELECT * FROM ' . $relevanssi_variables['log_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE query = %s', - $query - ) - ); - - $date_numbers = relevanssi_default_date_count( 'both' ); - - foreach ( $results as $row ) { - relevanssi_increase_value( $date_numbers[ gmdate( 'Y-m-d', strtotime( $row->time ) ) ] ); - } - ksort( $date_numbers ); - arsort( $posts ); - - $dates_array = $date_counts + $date_numbers; - ksort( $dates_array ); - $dates = array_map( - function ( $v ) { - return gmdate( 'M j', strtotime( $v ) ); - }, - array_keys( $dates_array ) - ); - - relevanssi_create_line_chart( - $dates, - array( - __( '# of Searches', 'relevanssi' ) => array_values( $date_numbers ), - __( '# of Clicks', 'relevanssi' ) => array_values( $date_counts ), - ) - ); - if ( count( $posts ) > 0 ) { - ?> - -

    - - - - - - - - - - - - $count ) { - $insights_url = relevanssi_get_insights_url( intval( $post_id ) ); - $insights = sprintf( "%s", esc_url( $insights_url ), get_the_title( $post_id ) ); - - $link = get_permalink( $post_id ); - $edit = get_edit_post_link( $post_id ); - ?> - - - - - - - - -
    - ( - | )
    - -
    -

    - -
    - - - - -
    -
    - -
    -

    - -
    - - - - -
    -
    - - - ' . - // Translators: %s is the search query string. - esc_html__( 'Search insights for %s', 'relevanssi' ) . - '', - esc_html( '"' . $title . '"' ) - ); - - $link = get_permalink( $post_id ); - $edit = get_edit_post_link( $post_id ); - ?> -

    - | -

    - get_results( - $wpdb->prepare( - 'SELECT * FROM ' . $relevanssi_variables['tracking_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE post_id = %d', - $post_id - ) - ); - - $queries = array(); - $query_average_rank = array(); - $query_average_page = array(); - $date_counts = relevanssi_default_date_count( 'clicks' ); - - foreach ( $results as $row ) { - relevanssi_increase_value( $queries[ $row->query ] ); - relevanssi_increase_value( $query_average_rank[ $row->query ], $row->rank ); - relevanssi_increase_value( $query_average_page[ $row->query ], $row->page ); - relevanssi_increase_value( $date_counts[ gmdate( 'Y-m-d', strtotime( $row->timestamp ) ) ] ); - } - - relevanssi_average_array( $query_average_rank, $queries ); - relevanssi_average_array( $query_average_page, $queries ); - - arsort( $queries ); - - $dates = array_map( - function ( $v ) { - return gmdate( 'M j', strtotime( $v ) ); - }, - array_keys( $date_counts ) - ); - - relevanssi_create_line_chart( - $dates, - array( - __( '# of Clicks', 'relevanssi' ) => array_values( $date_counts ), - ) - ); - - ?> - -

    - - - - - - - - - - - - $count ) { - $insights_url = relevanssi_get_insights_url( $query ); - $insights = sprintf( "%s", esc_url( $insights_url ), $query ); - ?> - - - - - - - - -
    - get_results( - 'SELECT LOWER(query) AS query, COUNT(*) AS count ' - . "FROM {$relevanssi_variables['tracking_table']} " // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . 'GROUP BY query' - ); - - $relevanssi_variables['query_clicks'] = array_combine( - wp_list_pluck( $data, 'query' ), - wp_list_pluck( $data, 'count' ) - ); - - return $relevanssi_variables['query_clicks'][ $query ] ?? 0; -} - -/** - * Prints out the user interface for setting the click tracking options. - */ -function relevanssi_click_tracking_interface() { - $click_tracking = relevanssi_check( get_option( 'relevanssi_click_tracking' ) ); - $trim_click_logs = get_option( 'relevanssi_trim_click_logs' ); - - ?> -

    - -

    - -

    - - - - - - - - - - - - - - - - - - - get_var( - $wpdb->prepare( - 'SELECT COUNT(*) FROM ' . $click_table . ' ' . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE timestamp >= %s AND timestamp <= %s', - $from . ' 00:00:00', - $to . ' 23:59:59' - ) - ); - - $click_ratio = 0; - if ( $total > 0 ) { - $click_ratio = round( 100 * $total_clicks / $total, 1 ); - } - ?> -
    -
    -
    - -
    -
    - - () -
    -
    -
    - -

    - get_results( - $wpdb->prepare( - "SELECT post_id, COUNT(*) AS hits, AVG(`rank`) AS average - FROM $click_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE timestamp >= %s AND timestamp <= %s - GROUP BY post_id ORDER BY hits DESC', - $from . ' 00:00:00', - $to . ' 23:59:59' - ) - ); - - $top_ten = array_slice( $results, 0, 10 ); - - $list = array(); - foreach ( $top_ten as $result ) { - $title = get_the_title( $result->post_id ); - $insights_url = relevanssi_get_insights_url( intval( $result->post_id ) ); - - $list[] = '
  • ' - . wp_kses_post( $title ) . ' (' . intval( $result->hits ) - . ')
  • '; - } - - if ( count( $list ) > 0 ) { - ?> -
    -

    -
      - ' . implode( "\n", $list ) . '
    '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - $something_printed = true; - ?> -
    - average - $a->average; - } - ); - - $top_ten = array_slice( $results, 0, 10 ); - - $list = array(); - foreach ( $top_ten as $result ) { - $title = get_the_title( $result->post_id ); - $insights_url = relevanssi_get_insights_url( intval( $result->post_id ) ); - - $list[] = '
  • ' . wp_kses_post( $title ) . ' (' - . round( $result->average, 0 ) . ')
  • '; - } - if ( count( $list ) > 0 ) { - ?> -
    -

    -
      - ' . implode( "\n", $list ) . '
    '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - $something_printed = true; - ?> -
    - get_results( - $wpdb->prepare( - "SELECT query, COUNT(DISTINCT(post_id)) AS posts - FROM $click_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE timestamp >= %s AND timestamp <= %s - GROUP BY query ORDER BY posts DESC LIMIT 10', - $from . ' 00:00:00', - $to . ' 23:59:59' - ) - ); - - $list = array(); - foreach ( $results as $result ) { - if ( $result->posts < 3 ) { - continue; - } - $insights_url = relevanssi_get_insights_url( $result->query ); - - $list[] = '
  • ' - . esc_html( $result->query ) . ' (' - // Translators: %1$s is the number of posts. - . sprintf( __( '%1$s posts', 'relevanssi' ), intval( $result->posts ) ) - . ')
  • '; - } - if ( count( $list ) > 0 ) { - ?> -

    - ' . implode( "\n", $list ) . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - $something_printed = true; - } - - if ( ! $something_printed ) { - ?> -

    - - - query. - * - * @return string The HTML link tag to link to the insights page. - */ -function relevanssi_insights_link( $query ): string { - global $relevanssi_variables; - $insights_url = admin_url( 'admin.php?page=' . rawurlencode( $relevanssi_variables['plugin_basename'] ) ) - . '&insights=' . rawurlencode( $query->query ); - $insights = sprintf( "%s", esc_url( $insights_url ), esc_html( relevanssi_hyphenate( $query->query ) ) ); - return $insights; -} - -/** - * Trims Relevanssi click tracking table. - * - * Trims Relevanssi click tracking table, using the day interval setting from - * 'relevanssi_trim_click_logs'. - * - * @global object $wpdb The WordPress database interface. - * @global array $relevanssi_variables The global Relevanssi variables, used - * for database table names. - * - * @return int|bool Number of rows deleted, or false on error. - */ -function relevanssi_trim_click_logs() { - global $wpdb, $relevanssi_variables; - $interval = intval( get_option( 'relevanssi_trim_click_logs' ) ); - return $wpdb->query( - $wpdb->prepare( - 'DELETE FROM ' . $relevanssi_variables['tracking_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - ' WHERE timestamp < TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))', - $interval - ) - ); -} - -/** - * Sets up the Relevanssi click tracking log trimming action. - */ -function relevanssi_schedule_click_tracking_trim() { - if ( get_option( 'relevanssi_trim_click_logs' ) > 0 ) { - if ( ! wp_next_scheduled( 'relevanssi_trim_click_logs' ) ) { - wp_schedule_event( time(), 'daily', 'relevanssi_trim_click_logs' ); - } - } elseif ( wp_next_scheduled( 'relevanssi_trim_click_logs' ) ) { - wp_clear_scheduled_hook( 'relevanssi_trim_click_logs' ); - } -} - -/** - * Prints out the Relevanssi click tracking log as a CSV file. - * - * Exports the whole Relevanssi click tracking log as a CSV file. - * - * @uses relevanssi_output_exported_log - */ -function relevanssi_export_click_log() { - global $wpdb, $relevanssi_variables; - - $data = $wpdb->get_results( 'SELECT * FROM ' . $relevanssi_variables['tracking_table'], ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - relevanssi_output_exported_log( - 'relevanssi_click_log.csv', - $data, - __( 'No search clicks logged.', 'relevanssi' ) - ); -} - -/** - * Returns the post ID prefixed with the blog ID. - * - * @param object $post_object The post object. - * - * @return string Post ID or "blog ID-post ID". - */ -function relevanssi_get_post_identifier( $post_object ) { - if ( is_multisite() ) { - if ( isset( $post_object->blog_id ) ) { - return $post_object->blog_id . '-' . $post_object->ID; - } else { - return get_current_blog_id() . '-' . $post_object->ID; - } - } else { - return $post_object->ID; - } -} diff --git a/relevanssi-premium/premium/common.php b/relevanssi-premium/premium/common.php deleted file mode 100644 index fe28df91..00000000 --- a/relevanssi-premium/premium/common.php +++ /dev/null @@ -1,1268 +0,0 @@ -Related Searches:
    • ', '
    • ', '
    ' ); - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param string $query The search query (get_search_query() is a good way to get the current query). - * @param string $pre What is printed before the results, default '
    • '. - * @param string $sep The separator between individual results, default '
    • '. - * @param string $post What is printed after the results, default '
    '. - * @param int $number Number of related searches to show, default 5. - * - * @author John Blackbourn - */ -function relevanssi_related( $query, $pre = '
    • ', $sep = '
    • ', $post = '
    ', $number = 5 ) { - global $wpdb, $relevanssi_variables; - - $output = array(); - $related = array(); - $tokens = relevanssi_tokenize( $query, true, -1, 'search_query' ); - if ( empty( $tokens ) ) { - return; - } - - $query_slug = sanitize_title( $query ); - $related = get_transient( 'related-' . $query_slug ); - if ( ! $related ) { - $related = array(); - /** - * Loop over each token in the query and return logged queries which: - * - * - Contain a matching token - * - Don't match the query or the token exactly - * - Have at least 2 hits - * - Have been queried at least twice - * - * then order by most queried with a max of $number results. - */ - foreach ( $tokens as $token => $count ) { - $escaped_token = '%' . $wpdb->esc_like( "$token" ) . '%'; - $log_table = $relevanssi_variables['log_table']; - $results = $wpdb->get_results( - $wpdb->prepare( - 'SELECT query ' . - "FROM $log_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - 'WHERE query LIKE %s - AND query NOT IN (%s, %s) - AND hits > 1 - GROUP BY query - HAVING count(query) > 1 - ORDER BY count(query) DESC - LIMIT %d', - $escaped_token, - $token, - $query, - $number - ) - ); - if ( is_array( $results ) ) { - foreach ( $results as $result ) { - $related[] = $result->query; - } - } - } - if ( empty( $related ) ) { - return; - } else { - set_transient( 'related-' . $query_slug, $related, 60 * 60 * 24 * 7 ); - } - } - - // Order results by most matching tokens then slice to a maximum of $number results. - $related = array_keys( array_count_values( $related ) ); - $related = array_slice( $related, 0, $number ); - foreach ( $related as $rel ) { - $url = add_query_arg( - array( - 's' => rawurlencode( $rel ), - ), - home_url() - ); - $rel = esc_attr( $rel ); - $output[] = "$rel"; - } - - echo $pre . implode( $sep, $output ) . $post; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -} - -/** - * Replaces get_posts() in a way that handles users and taxonomy terms. - * - * Custom-made get_posts() replacement that creates post objects for users and - * taxonomy terms. For regular posts, the function uses get_posts() and a - * caching mechanism. - * - * @global array $relevanssi_post_array The global Relevanssi post array used as - * a cache. - * - * @param int|string $id The post ID to fetch. If the ID is a string and - * begins with 'u_', it's considered a user ID and if it begins with '**', it's - * considered a taxonomy term. - * @param int $blog_id The blog ID, used to make caching work in - * multisite environment. Defaults to -1, which means the blog id is not used. - * - * @return object|WP_Error $post The post object for the post ID or a WP_Error - * object if the post ID is not found. - */ -function relevanssi_premium_get_post( $id, int $blog_id = -1 ) { - global $relevanssi_post_array; - $type = substr( $id, 0, 2 ); - switch ( $type ) { - case 'u_': - list( , $id ) = explode( '_', $id ); - - $user = get_userdata( $id ); - $post = new stdClass(); - $post->post_title = $user->display_name; - $post->post_content = $user->description; - $post->post_type = 'user'; - $post->ID = $id; - $post->relevanssi_link = get_author_posts_url( $id ); - $post->post_status = 'publish'; - $post->post_date = gmdate( 'Y-m-d H:i:s' ); - $post->post_author = 0; - $post->post_name = ''; - $post->post_excerpt = ''; - $post->comment_status = ''; - $post->ping_status = ''; - $post->user_id = $id; - - /** - * Filters the user profile post object. - * - * After a post object is created from the user profile, it is - * passed through this filter so it can be modified. - * - * @param object $post The post object. - */ - $post = apply_filters( 'relevanssi_user_profile_to_post', $post ); - break; - case 'p_': - list( , $id ) = explode( '_', $id ); - - $post_type_name = relevanssi_get_post_type_by_id( $id ); - $post_type = get_post_type_object( $post_type_name ); - $post = new stdClass(); - $post->post_title = $post_type->label; - $post->post_content = $post_type->description; - $post->post_type = 'post_type'; - $post->ID = $id; - $post->relevanssi_link = get_post_type_archive_link( $post_type_name ); - $post->post_status = 'publish'; - $post->post_date = gmdate( 'Y-m-d H:i:s' ); - $post->post_author = 0; - $post->post_name = ''; - $post->post_excerpt = ''; - $post->comment_status = ''; - $post->ping_status = ''; - $post->post_type_id = $post_type_name; - - /** - * Filters the post type post object. - * - * After a post object is created from a post type, it is passed - * through this filter so it can be modified. - * - * @param stdClass $post The post object. - */ - $post = apply_filters( 'relevanssi_post_type_to_post', $post ); - break; - case '**': - list( , $taxonomy, $id ) = explode( '**', $id ); - - $term = get_term( $id, $taxonomy ); - if ( is_wp_error( $term ) ) { - return new WP_Error( 'term_not_found', "Taxonomy term wasn't found." ); - } - $post = new stdClass(); - $post->post_title = $term->name; - $post->post_content = $term->description; - $post->post_type = $taxonomy; - $post->ID = -1; - $post->post_status = 'publish'; - $post->post_date = gmdate( 'Y-m-d H:i:s' ); - $post->relevanssi_link = get_term_link( $term, $taxonomy ); - $post->post_author = 0; - $post->post_name = ''; - $post->post_excerpt = ''; - $post->comment_status = ''; - $post->ping_status = ''; - $post->term_id = $id; - $post->post_parent = $term->parent; - - /** - * Filters the taxonomy term post object. - * - * After a post object is created from the taxonomy term, it is - * passed through this filter so it can be modified. - * - * @param Object $post The post object. - */ - $post = apply_filters( 'relevanssi_taxonomy_term_to_post', $post ); - break; - default: - $cache_id = $id; - if ( -1 !== $blog_id ) { - $cache_id = $blog_id . '|' . $id; - } - if ( isset( $relevanssi_post_array[ $cache_id ] ) ) { - // Post exists in the cache. - $post = $relevanssi_post_array[ $cache_id ]; - } else { - $post = get_post( $id ); - - $relevanssi_post_array[ $cache_id ] = $post; - } - if ( - 'on' === get_option( 'relevanssi_link_pdf_files' ) - && ! empty( $post->post_mime_type ) - ) { - /** - * Filters the URL to the attachment file. - * - * If you set the attachment indexing to index attachments that - * are stored outside the WP attachment system, use this filter - * to provide a link to the attachment. - * - * @param string The URL to the attachment file. - * @param int The attachment post ID number. - */ - $post->relevanssi_link = apply_filters( - 'relevanssi_get_attachment_url', - wp_get_attachment_url( $post->ID ), - $post->ID - ); - } - } - - if ( ! $post ) { - $post = new WP_Error( 'post_not_found', __( 'The requested post does not exist.' ) ); - } - - return $post; -} - -/** - * Returns a list of indexed taxonomies. - * - * This will also include "user", if user profiles are indexed, and "post_type", if - * post type archives are indexed. - * - * @return array $non_post_post_types_array An array of taxonomies Relevanssi is set - * to index (and "user" or "post_type"). - */ -function relevanssi_get_non_post_post_types() { - // These post types are not posts, ie. they are taxonomy terms and user profiles. - $non_post_post_types_array = array(); - if ( get_option( 'relevanssi_index_taxonomies' ) ) { - $taxonomies = get_option( 'relevanssi_index_terms' ); - if ( is_array( $taxonomies ) ) { - $non_post_post_types_array = $taxonomies; - } - } - if ( get_option( 'relevanssi_index_users' ) ) { - $non_post_post_types_array[] = 'user'; - } - if ( get_option( 'relevanssi_index_post_type_archives' ) ) { - $non_post_post_types_array[] = 'post_type'; - } - return $non_post_post_types_array; -} - -/** - * Gets the PDF content for the child posts of the post. - * - * @global $wpdb The WordPress database interface. - * - * @param int $post_id The post ID of the parent post. - * - * @return array $pdf_content The PDF content of the child posts. - */ -function relevanssi_get_child_pdf_content( $post_id ): array { - global $wpdb; - - $post_id = intval( $post_id ); - $pdf_content = ''; - - if ( $post_id > 0 ) { - /** - * Filters the custom field value before indexing. - * - * @param array Custom field values. - * @param string $field The custom field name. - * @param int $post_id The post ID. - */ - return apply_filters( - 'relevanssi_custom_field_value', - $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta AS pm, $wpdb->posts AS p WHERE pm.post_id = p.ID AND p.post_parent = $post_id AND meta_key = '_relevanssi_pdf_content'" ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - '_relevanssi_pdf_content', - $post_id - ); - // Only user-provided variable is $post_id, and that's from Relevanssi and sanitized as an int. - } - - return array(); -} - -/** - * Provides the Premium version "Did you mean" recommendations. - * - * Provides a better version of "Did you mean" recommendations, using the - * spelling corrector class to generate a correct spelling. - * - * @global WP_Query $wp_query The query object, used to check the number of - * posts found. - * - * @param string $query The search query to correct. - * @param string $pre Text printed out before the suggestion. - * @param string $post Text printed out after the suggestion. - * @param int $n Maximum number of hits before the suggestions are shown, - * default 5. - * - * @return string Empty string if there's nothing to correct; otherwise a string - * with the HTML link to the corrected search. - */ -function relevanssi_premium_didyoumean( $query, $pre, $post, $n = 5 ) { - global $wp_query; - - $total_results = $wp_query->found_posts; - $result = ''; - - if ( $total_results > $n ) { - return $result; - } - - $suggestion = relevanssi_premium_generate_suggestion( $query ); - if ( true === $suggestion ) { - return $result; - } - if ( empty( $suggestion ) ) { - $suggestion = relevanssi_simple_generate_suggestion( $query ); - } - - $result = null; - if ( $suggestion ) { - $url = trailingslashit( get_bloginfo( 'url' ) ); - $url = esc_attr( - add_query_arg( - array( - 's' => rawurlencode( $suggestion ), - ), - $url - ) - ); - /** This filter is documented in lib/didyoumean.php */ - $url = apply_filters( 'relevanssi_didyoumean_url', $url, $query, $suggestion ); - - // Escape the suggestion to avoid XSS attacks. - $suggestion = htmlspecialchars( $suggestion ); - - /** This filter is documented in lib/didyoumean.php */ - $result = apply_filters( 'relevanssi_didyoumean_suggestion', "$pre$suggestion$post" ); - } - return $result; -} - -/** - * Generates the "Did you mean" suggestion. - * - * Generates "Did you mean" suggestions given a query to correct, using the - * spelling corrector method. - * - * @param string $query The search query to correct. - * - * @return string $query Corrected query, empty string if there are no - * corrections available and true if the query was already correct. - */ -function relevanssi_premium_generate_suggestion( $query ) { - $corrected_query = ''; - - if ( class_exists( 'Relevanssi_SpellCorrector' ) ) { - $query = htmlspecialchars_decode( $query, ENT_QUOTES ); - $tokens = relevanssi_tokenize( $query, true, -1, 'search_query' ); - - $sc = new Relevanssi_SpellCorrector(); - - $correct = array(); - $exact_matches = 0; - foreach ( array_keys( $tokens ) as $token ) { - /** - * Filters the tokens for Did you mean suggestions. - * - * You can use this filter hook to modify the tokens before Relevanssi - * tries to come up with Did you mean suggestions for them. If you - * return an empty string, the token will be skipped and no suggestion - * will be made for the token. - * - * @param string $token An individual word from the search query. - * - * @return string The token. - */ - $token = apply_filters( 'relevanssi_didyoumean_token', trim( $token ) ); - if ( ! $token ) { - continue; - } - $c = $sc->correct( $token ); - if ( true === $c ) { - ++$exact_matches; - } elseif ( ! empty( $c ) && strval( $token ) !== $c ) { - array_push( $correct, $c ); - $query = str_ireplace( $token, $c, $query ); // Replace misspelled word in query with suggestion. - } - } - if ( count( $tokens ) === $exact_matches ) { - // All tokens are correct. - return true; - } - if ( count( $correct ) > 0 ) { - // Strip quotes, because they are likely incorrect. - $query = str_replace( '"', '', $query ); - $corrected_query = $query; - } - } - - return $corrected_query; -} - -/** - * Multisite-friendly get_post(). - * - * Gets a post using relevanssi_get_post() from the specified subsite. - * - * @param int $blogid The blog ID. - * @param int $id The post ID. - * - * @return object|WP_Error $post The post object or a WP_Error if the post - * cannot be found. - */ -function relevanssi_get_multisite_post( $blogid, $id ) { - switch_to_blog( $blogid ); - if ( ! is_numeric( mb_substr( $id, 0, 1 ) ) ) { - // The post ID does not start with a number; this is a user or a - // taxonomy term, so suspend cache addition to avoid getting garbage in - // the cache. - wp_suspend_cache_addition( true ); - } - $post = relevanssi_get_post( $id, $blogid ); - restore_current_blog(); - return $post; -} - -/** - * Initializes things for Relevanssi Premium. - * - * Adds metaboxes, depending on settings; adds synonym indexing filter if - * necessary and removes an unnecessary action. - */ -function relevanssi_premium_init() { - $show_post_controls = true; - if ( 'on' === get_option( 'relevanssi_hide_post_controls' ) ) { - $show_post_controls = false; - /** - * Adjusts the capability required to show the Relevanssi post controls - * for admins. - * - * @param string $capability The minimum capability required, default - * 'manage_options'. - */ - if ( - 'on' === get_option( 'relevanssi_show_post_controls' ) && - current_user_can( apply_filters( 'relevanssi_options_capability', 'manage_options' ) ) - ) { - $show_post_controls = true; - } - } - if ( $show_post_controls ) { - add_action( 'add_meta_boxes', 'relevanssi_add_metaboxes' ); - } - - if ( 'on' === get_option( 'relevanssi_index_synonyms' ) ) { - add_filter( 'relevanssi_indexing_tokens', 'relevanssi_add_indexing_synonyms', 10 ); - } - - // If the relevanssi_save_postdata is not disabled, scheduled publication - // will swipe out the Relevanssi post controls settings. - add_action( - 'future_to_publish', - function () { - remove_action( 'save_post', 'relevanssi_save_postdata' ); - } - ); - - if ( function_exists( 'do_blocks' ) ) { - add_action( 'init', 'relevanssi_register_gutenberg_actions', 11 ); - } - - global $pagenow, $relevanssi_variables; - $on_relevanssi_page = false; - if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification - $page = sanitize_file_name( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification - $base = sanitize_file_name( wp_unslash( plugin_basename( $relevanssi_variables['file'] ) ) ); - if ( $base === $page ) { - $on_relevanssi_page = true; - } - } - - if ( function_exists( 'is_multisite' ) && is_multisite() && function_exists( 'get_blog_status' ) ) { - $public = (bool) get_blog_status( get_current_blog_id(), 'public' ); - if ( ! $public && 'options-general.php' === $pagenow && $on_relevanssi_page ) { - add_action( - 'admin_notices', - function () { - printf( - "

    %s

    ", - esc_html__( 'Your site is not public. By default, Relevanssi does not search private sites. If you want to be able to search on this site, either make it public or add a filter function that returns true on \'relevanssi_multisite_public_status\' filter hook.', 'relevanssi' ) - ); - } - ); - } - } - - add_filter( 'relevanssi_remove_punctuation', 'relevanssi_wildcards_pre', 8 ); - add_filter( 'relevanssi_remove_punctuation', 'relevanssi_wildcards_post', 12 ); - add_filter( 'relevanssi_term_where', 'relevanssi_query_wildcards', 10, 2 ); - - add_filter( 'relevanssi_indexing_restriction', 'relevanssi_hide_post_restriction' ); - - if ( defined( 'RELEVANSSI_API_KEY' ) ) { - add_filter( - 'pre_option_relevanssi_api_key', - function () { - return RELEVANSSI_API_KEY; - } - ); - add_filter( - 'pre_site_option_relevanssi_api_key', - function () { - return RELEVANSSI_API_KEY; - } - ); - } - - $update_translations = false; - if ( 'on' === get_option( 'relevanssi_update_translations' ) ) { - $update_translations = true; - } - if ( 'on' === get_option( 'relevanssi_do_not_call_home' ) ) { - $update_translations = false; - } - /** - * Filters whether to update the Relevanssi translations. - * - * @param boolean $update_translations If false, don't update translations. - */ - $update_translations = apply_filters( 'relevanssi_update_translations', $update_translations ); - - if ( $update_translations ) { - $t15s_updater = new Relevanssi_Language_Packs( - 'plugin', - 'relevanssi', - 'https://packages.translationspress.com/relevanssi/relevanssi/packages.json' - ); - $t15s_updater->add_project(); - } - - add_action( - 'in_plugin_update_message-' . $relevanssi_variables['plugin_basename'], - 'relevanssi_premium_modify_plugin_update_message' - ); - - // Add the related posts filters if necessary. - relevanssi_related_init(); -} - -/** - * Adds the Relevanssi Premium hide post filter to the indexing restrictions. - * - * @global object $wpdb The WP database interface. - * - * @param array $restrictions The current set of restrictions. - * - * @return array The updated restrictions. - */ -function relevanssi_hide_post_restriction( $restrictions ) { - global $wpdb; - - $restrictions['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')"; - $restrictions['reason'] .= ' ' . __( 'Relevanssi index exclude', 'relevanssi' ); - - return $restrictions; -} - -/** - * Replaces the standard permalink with $post->relevanssi_link if it exists. - * - * Relevanssi adds a link to the user profile or taxonomy term page to - * $post->relevanssi_link. This function replaces permalink with that link, if - * it exists. - * - * @param string $permalink The permalink to filter. - * @param int $post_id The post ID. - * - * @return string $permalink Modified permalink. - */ -function relevanssi_post_link_replace( $permalink, $post_id ) { - $post = relevanssi_get_post( $post_id ); - if ( property_exists( $post, 'relevanssi_link' ) ) { - $permalink = $post->relevanssi_link; - } - return $permalink; -} - -/** - * Fetches a list of words from the Relevanssi database for spelling corrector. - * - * A helper function for the spelling corrector. Gets the word list from the - * 'relevanssi_words' option. If the data is expired (more than a month old), - * this function triggers an asynchronous refresh action that fetches new words - * from the Relevanssi database to use as a source material for spelling - * suggestions. - * - * @return array $words An array of words, with the word as the key and number - * of occurrances as the value. - */ -function relevanssi_get_words() { - $data = get_option( - 'relevanssi_words', - array( - 'expire' => 0, - 'words' => array(), - ) - ); - - if ( time() > $data['expire'] ) { - relevanssi_launch_ajax_action( 'relevanssi_get_words' ); - } - - return $data['words']; -} - -/** - * Adds the Premium options. - * - * @global array $relevanssi_variables The global Relevanssi variables, used to set the link boost default. - */ -function relevanssi_premium_install() { - global $relevanssi_variables; - - add_option( 'relevanssi_api_key', '' ); - add_option( 'relevanssi_click_tracking', 'on' ); - add_option( 'relevanssi_disable_shortcodes', '' ); - add_option( 'relevanssi_do_not_call_home', 'off' ); - add_option( 'relevanssi_hide_post_controls', 'off' ); - add_option( 'relevanssi_index_pdf_parent', 'off' ); - add_option( 'relevanssi_index_post_type_archives', 'off' ); - add_option( 'relevanssi_index_subscribers', 'off' ); - add_option( 'relevanssi_index_synonyms', 'off' ); - add_option( 'relevanssi_index_taxonomies', 'off' ); - add_option( 'relevanssi_index_terms', array() ); - add_option( 'relevanssi_index_users', 'off' ); - add_option( 'relevanssi_internal_links', 'noindex' ); - add_option( 'relevanssi_link_boost', $relevanssi_variables['link_boost_default'] ); - add_option( 'relevanssi_link_pdf_files', 'on' ); - add_option( 'relevanssi_max_excerpts', 1 ); - add_option( 'relevanssi_mysql_columns', '' ); - add_option( 'relevanssi_post_type_weights', '' ); - add_option( 'relevanssi_read_new_files', 'off' ); - add_option( 'relevanssi_redirects', array() ); - add_option( 'relevanssi_related_settings', relevanssi_related_default_settings() ); - add_option( 'relevanssi_related_style', relevanssi_related_default_styles() ); - add_option( 'relevanssi_send_pdf_files', 'off' ); - add_option( 'relevanssi_server_location', relevanssi_default_server_location() ); - add_option( 'relevanssi_show_post_controls', 'off' ); - add_option( 'relevanssi_spamblock', array() ); - add_option( 'relevanssi_thousand_separator', '' ); - add_option( 'relevanssi_trim_click_logs', '180' ); - add_option( 'relevanssi_update_translations', 'off' ); - add_option( - 'relevanssi_recency_bonus', - array( - 'bonus' => '', - 'days' => '', - ) - ); -} - -/** - * Makes an educated guess whether the default attachment server location should - * be US or EU, based on the site locale setting. - * - * @uses get_locale() - * - * @return string 'eu' or 'us', depending on the locale. - */ -function relevanssi_default_server_location(): string { - $server = 'us'; - $locale = get_locale(); - - if ( strpos( $locale, '_' ) === false ) { - $language = $locale; - } else { - list( $language, $country ) = explode( '_', $locale ); - } - - $eu_languages = array( 'ast', 'bel', 'ca', 'cy', 'el', 'et', 'eu', 'fi', 'fur', 'gd', 'hr', 'hsb', 'lv', 'oci', 'roh', 'sq', 'uk' ); - $eu_countries = array( 'AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CY', 'DE', 'EE', 'ES', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IL', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'ME', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK', 'UA' ); - - if ( in_array( strtolower( $language ), $eu_languages, true ) || - in_array( strtoupper( $country ), $eu_countries, true ) ) { - $server = 'eu'; - } - - return $server; -} - -/** - * Returns the attachment reading server URL. - * - * Checks the correct server from 'relevanssi_server_location' option and returns the - * correct URL from the constants. - * - * @return string The attachment reading server URL. - */ -function relevanssi_get_server_url() { - $server = RELEVANSSI_US_SERVICES_URL; - if ( 'eu' === get_option( 'relevanssi_server_location' ) ) { - $server = RELEVANSSI_EU_SERVICES_URL; - } - /** - * Allows changing the attachment reading server URL. - * - * @param string The server URL. - */ - return apply_filters( 'relevanssi_attachment_server_url', $server ); -} - -/** - * Extracts taxonomy specifiers from the search query. - * - * Finds all {taxonomy:search term} specifiers from the query. If any are - * found, they are stored in $relevanssi_variables global variable and the - * filtering function is activated. - * - * @global array $relevanssi_variables Used to store the target data. - * - * @param string $query The query. - * - * @return string The query with the specifier tags removed. - */ -function relevanssi_extract_specifier( $query ) { - global $relevanssi_variables; - - $targets = array(); - - if ( preg_match_all( '/{(.*?):(.*?)}/', $query, $matches, PREG_SET_ORDER ) ) { - foreach ( $matches as $match ) { - list( $whole, $target, $keyword ) = $match; - - $phrases = relevanssi_extract_phrases( $keyword ); - if ( ! empty( $phrases ) ) { - foreach ( $phrases as $phrase ) { - $relevanssi_variables['phrase_targets'][ $phrase ] = $target; - } - } else { - if ( is_numeric( $keyword ) ) { - $keyword = ' ' . $keyword; - } - $targets[ $keyword ][] = $target; - } - - $query = str_replace( $whole, $keyword, $query ); - } - } - - if ( ! empty( $targets ) ) { - $relevanssi_variables['targets'] = $targets; - add_filter( 'relevanssi_match', 'relevanssi_target_matches' ); - } - - return $query; -} - -/** - * Filters posts by taxonomy specifiers. - * - * If taxonomy specifiers are found in the query, this filtering function is - * activated and will set the post weight to 0 in the cases where the post - * matches the search term, but not the specifiers. - * - * @global array $relevanssi_variables Used to store the target data. - * - * @param object $match_object The Relevanssi match object. - * - * @return object The match object, with the weight modified if necessary. - */ -function relevanssi_target_matches( $match_object ) { - global $relevanssi_variables; - - if ( is_numeric( $match_object->term ) ) { - $match_object->term = ' ' . $match_object->term; - } - - $fuzzy = get_option( 'relevanssi_fuzzy' ); - if ( 'always' === $fuzzy || 'sometimes' === $fuzzy ) { - foreach ( $relevanssi_variables['targets'] as $term => $target ) { - if ( - substr( $match_object->term, 0, strlen( $term ) ) === $term || - substr( strrev( $match_object->term ), 0, strlen( $term ) ) === strrev( $term ) - ) { - $relevanssi_variables['targets'][ $match_object->term ] = - $relevanssi_variables['targets'][ $term ]; - } - } - } - - $no_matches = false; - if ( isset( $relevanssi_variables['targets'][ $match_object->term ] ) ) { - $no_matches = true; - foreach ( $relevanssi_variables['targets'][ $match_object->term ] as $target ) { - if ( isset( $match_object->$target ) && '0' !== $match_object->$target ) { - $no_matches = false; - break; - } - if ( $match_object->customfield_detail && ! is_object( $match_object->customfield_detail ) ) { - $match_object->customfield_detail = json_decode( $match_object->customfield_detail ); - } - if ( - ! empty( $match_object->customfield_detail ) && - isset( $match_object->customfield_detail->$target ) && - '0' !== $match_object->customfield_detail->$target - ) { - $no_matches = false; - break; - } - if ( ! is_object( $match_object->taxonomy_detail ) ) { - $match_object->taxonomy_detail = json_decode( $match_object->taxonomy_detail ); - } - if ( - ! empty( $match_object->taxonomy_detail ) && - isset( $match_object->taxonomy_detail->$target ) && - '0' !== $match_object->taxonomy_detail->$target - ) { - $no_matches = false; - break; - } - if ( ! is_object( $match_object->mysqlcolumn_detail ) ) { - $match_object->mysqlcolumn_detail = json_decode( $match_object->mysqlcolumn_detail ); - } - if ( - ! empty( $match_object->mysqlcolumn_detail ) && - isset( $match_object->mysqlcolumn_detail->$target ) && - '0' !== $match_object->mysqlcolumn_detail->$target - ) { - $no_matches = false; - break; - } - } - } - if ( $no_matches ) { - $match_object->weight = 0; - } - - if ( is_object( $match_object->customfield_detail ) ) { - $match_object->customfield_detail = wp_json_encode( $match_object->customfield_detail ); - } - if ( is_object( $match_object->taxonomy_detail ) ) { - $match_object->taxonomy_detail = wp_json_encode( $match_object->taxonomy_detail ); - } - if ( is_object( $match_object->mysqlcolumn_detail ) ) { - $match_object->mysqlcolumn_detail = wp_json_encode( $match_object->mysqlcolumn_detail ); - } - - return $match_object; -} - -/** - * Generates queries for targeted phrases. - * - * Goes through the targeted phrases from the Relevanssi global variable - * $relevanssi_variables['phrase_targets'] and generates the queries for the - * phrases taking note of the target restrictions. Some of this is slightly - * hacky, as some default inclusions generated by the - * relevanssi_generate_phrase_queries() are simply removed. - * - * @see relevanssi_generate_phrase_queries() - * - * @global array $relevanssi_variables The global Relevanssi variables. - * - * @param string $phrase The source phrase for the queries. - * - * @return array An array of queries per phrase. - */ -function relevanssi_targeted_phrases( $phrase ) { - global $relevanssi_variables; - - $target = $relevanssi_variables['phrase_targets'][ $phrase ]; - - $taxonomies = array(); - $excerpt = 'off'; - $fields = array(); - - if ( 'excerpt' === $target ) { - $excerpt = 'on'; - } - if ( 'tag' === $target ) { - $target = 'post_tag'; - } - if ( taxonomy_exists( $target ) ) { - $taxonomies = array( $target ); - } else { - $fields = array( $target ); - } - - $queries = relevanssi_generate_phrase_queries( - array( $phrase ), - $taxonomies, - $fields, - $excerpt - ); - - if ( 'excerpt' === $target ) { - $find = array( - "post_content LIKE '%$phrase%' OR ", - "post_title LIKE '%$phrase%' OR ", - ); - $queries[ $phrase ][0] = str_replace( $find, '', $queries[ $phrase ][0] ); - } elseif ( 'title' === $target ) { - $find = array( - "post_content LIKE '%$phrase%' OR ", - ); - $queries[ $phrase ][0] = str_replace( $find, '', $queries[ $phrase ][0] ); - } else { - unset( $queries[ $phrase ][0] ); // Remove the generic post content or title query. - } - if ( $fields ) { - // Custom field targeting, remove PDF content custom frield from the list. - $queries[ $phrase ][1] = str_replace( - ",'_relevanssi_pdf_content'", - '', - $queries[ $phrase ][1] - ); - } - - return $queries; -} - -/** - * Adds the Relevanssi Premium phrase filters for PDF content, terms and users. - * - * Hooks on to `relevanssi_phrase_queries` to include the phrase queries for - * Relevanssi Premium features: looking for phrases in PDF content, taxonomy - * term names and user fields. - * - * @param array $queries The array of queries where the new queries are added. - * @param string $phrase The current phrase, already MySQL escaped. - * @param string $status MySQL escaped post status value to use in queries. - * - * @return array The queries, with new queries added. - */ -function relevanssi_premium_phrase_queries( $queries, $phrase, $status ) { - global $wpdb; - - $index_post_types = get_option( 'relevanssi_index_post_types', array() ); - if ( in_array( 'attachment', $index_post_types, true ) ) { - $query = "(SELECT ID - FROM $wpdb->posts AS p, $wpdb->postmeta AS m - WHERE p.ID = m.post_id - AND m.meta_key = '_relevanssi_pdf_content' - AND m.meta_value LIKE '%$phrase%' - AND p.post_status IN ($status))"; - - $queries[] = array( - 'query' => $query, - 'target' => 'doc', - ); - } - - if ( 'on' === get_option( 'relevanssi_index_pdf_parent' ) ) { - $query = "(SELECT parent.ID - FROM $wpdb->posts AS p, $wpdb->postmeta AS m, $wpdb->posts AS parent - WHERE p.ID = m.post_id - AND p.post_parent = parent.ID - AND m.meta_key = '_relevanssi_pdf_content' - AND m.meta_value LIKE '%$phrase%' - AND p.post_status = 'inherit')"; - - $queries[] = array( - 'query' => $query, - 'target' => 'doc', - ); - } - - $index_taxonomies = get_option( 'relevanssi_index_terms', array() ); - if ( ! empty( $index_taxonomies ) ) { - $taxonomies_escaped = implode( "','", array_map( 'esc_sql', $index_taxonomies ) ); - $taxonomies_sql = "AND tt.taxonomy IN ('$taxonomies_escaped')"; - - $query = "(SELECT t.term_id - FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt - WHERE t.term_id = tt.term_id - AND t.name LIKE '%$phrase%' - $taxonomies_sql)"; - - $queries[] = array( - 'query' => $query, - 'target' => 'item', - ); - } - - $index_users = get_option( 'relevanssi_index_users', 'off' ); - if ( 'on' === $index_users ) { - $extra_fields = get_option( 'relevanssi_index_user_fields' ); - $meta_keys = array( 'description', 'first_name', 'last_name' ); - if ( $extra_fields ) { - $meta_keys = array_merge( $meta_keys, explode( ',', $extra_fields ) ); - } - $meta_keys_escaped = implode( "','", array_map( 'esc_sql', $meta_keys ) ); - $meta_keys_sql = "um.meta_key IN ('$meta_keys_escaped')"; - - $query = "(SELECT DISTINCT(u.ID) - FROM $wpdb->users AS u LEFT JOIN $wpdb->usermeta AS um - ON u.ID = um.user_id - WHERE ($meta_keys_sql AND meta_value LIKE '%$phrase%') - OR u.display_name LIKE '%$phrase%')"; - - $queries[] = array( - 'query' => $query, - 'target' => 'item', - ); - } - - return $queries; -} - -/** - * Fetches database words to the relevanssi_words option. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the - * database table names. - */ -function relevanssi_update_words_option() { - global $wpdb, $relevanssi_variables; - - /** - * The minimum limit of occurrances to include a word. - * - * To save resources, only words with more than this many occurrances are - * fed to the spelling corrector. If there are problems with the spelling - * corrector, increasing this value may fix those problems. - * - * @param int $number The number of occurrances must be more than this - * value, default 2. - */ - $count = apply_filters( 'relevanssi_get_words_having', 2 ); - if ( ! is_numeric( $count ) ) { - $count = 2; - } - $q = 'SELECT term, - SUM(title + content + comment + tag + link + author + category + excerpt + taxonomy + customfield) - AS c FROM ' . $relevanssi_variables['relevanssi_table'] . - " GROUP BY term HAVING c > $count"; // Safe: $count is numeric. - - $results = $wpdb->get_results( $q ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - $words = array(); - foreach ( $results as $result ) { - $words[ $result->term ] = $result->c; - } - - $expire = time() + MONTH_IN_SECONDS; - $data = array( - 'expire' => $expire, - 'words' => $words, - ); - - update_option( 'relevanssi_words', $data, false ); -} - -/** - * Adds the "Must have" part for the missing terms list. - * - * Assumes there's just one missing term (this is checked outside this - * function). - * - * @param WP_Post $post The post object. - * - * @return string A string containing the "Must have" link. - */ -function relevanssi_add_must_have( $post ) { - $query_string = $GLOBALS['wp']->query_string ?? ''; - $request = $GLOBALS['request'] ?? '/'; - $search_term = implode( '', $post->relevanssi_hits['missing_terms'] ); - $search_page_url = add_query_arg( $query_string, '', home_url( $request ) ); - $search_page_url = str_replace( rawurlencode( $search_term ), '%2B' . $search_term, $search_page_url ); - - return apply_filters( - 'relevanssi_missing_terms_must_have', - ' | ' . __( 'Must have', 'relevanssi' ) . ': ' . $search_term . '' - ); -} - -/** - * Updates the $term_hits array used for showing how many hits were found for - * each term. - * - * @param array $term_hits The term hits array (passed as reference). - * @param array $match_arrays The matches array (passed as reference). - * @param stdClass $match_object The match object. - * @param string $term The search term. - */ -function relevanssi_premium_update_term_hits( &$term_hits, &$match_arrays, $match_object, $term ) { - relevanssi_increase_value( $match_arrays['mysqlcolumn'][ $match_object->doc ], $match_object->mysqlcolumn ); - - $match_arrays['customfield_detail'][ $match_object->doc ] = array(); - $match_arrays['taxonomy_detail'][ $match_object->doc ] = array(); - $match_arrays['mysqlcolumn_detail'][ $match_object->doc ] = array(); - - if ( ! empty( $match_object->customfield_detail ) ) { - $match_arrays['customfield_detail'][ $match_object->doc ][ $term ] = $match_object->customfield_detail; - } - if ( ! empty( $match_object->taxonomy_detail ) ) { - $match_arrays['taxonomy_detail'][ $match_object->doc ][ $term ] = $match_object->taxonomy_detail; - } - if ( ! empty( $match_object->mysqlcolumn_detail ) ) { - $match_arrays['mysqlcolumn_detail'][ $match_object->doc ][ $term ] = $match_object->mysqlcolumn_detail; - } -} - -/** - * Adds Premium features to the $return array from $match_arrays. - * - * @param array $return_value The search return value array, passed as a - * reference. - * @param array $match_arrays The match array for source data. - */ -function relevanssi_premium_update_return_array( &$return_value, $match_arrays ) { - $match_arrays['mysqlcolumn_matches'] = $match_arrays['mysqlcolumn_matches'] ?? ''; - $match_arrays['customfield_detail'] = $match_arrays['customfield_detail'] ?? ''; - $match_arrays['taxonomy_detail'] = $match_arrays['taxonomy_detail'] ?? ''; - $match_arrays['mysqlcolumn_detail'] = $match_arrays['mysqlcolumn_detail'] ?? ''; - - $additions = array( - 'mysqlcolumn' => $match_arrays['mysqlcolumn_matches'], - 'customfield_detail' => $match_arrays['customfield_detail'], - 'taxonomy_detail' => $match_arrays['taxonomy_detail'], - 'mysqlcolumn_detail' => $match_arrays['mysqlcolumn_detail'], - ); - - $return_value = array_merge( $return_value, $additions ); -} - -/** - * Adds Premium features to the $post->relevanssi_hits source array. - * - * @param array $hits The search hits array. - * @param array $data The source data. - * @param int $post_id The post ID. - */ -function relevanssi_premium_add_matches( &$hits, $data, $post_id ) { - $hits['mysqlcolumn'] = $data['mysqlcolumn_matches'][ $post_id ] ?? 0; - $hits['customfield_detail'] = $data['customfield_detail'][ $post_id ] ?? array(); - $hits['taxonomy_detail'] = $data['taxonomy_detail'][ $post_id ] ?? array(); - $hits['mysqlcolumn_detail'] = $data['mysqlcolumn_detail'][ $post_id ] ?? array(); - - $hits['customfield_detail'] = array_map( - function ( $value ) { - return (array) json_decode( $value ); - }, - $hits['customfield_detail'] - ); -} - -/** - * Returns a string of custom field content for the user. - * - * Fetches the user custom field content based on the field indexing settings - * and concatenates it as a single space-separated string. - * - * @uses relevanssi_get_user_field_content - * - * @param string $user_id The ID of the user. - * - * @return string The custom field content. - */ -function relevanssi_get_user_custom_field_content( $user_id ): string { - $custom_field_content = ''; - - $fields = relevanssi_get_user_field_content( $user_id ); - if ( ! empty( $fields ) ) { - $custom_field_content = implode( ' ', array_values( $fields ) ); - } - - return $custom_field_content; -} - -/** - * Returns an array of user custom field names. - * - * Gets the indexed user field names from relevanssi_index_user_fields and - * relevanssi_index_user_meta options and returns an array of field names. - * - * @return array Array of user custom field names. - */ -function relevanssi_generate_list_of_user_fields(): array { - $user_fields = array(); - - $user_fields_option = get_option( 'relevanssi_index_user_fields' ); - if ( $user_fields_option ) { - $user_fields = explode( ',', $user_fields_option ); - } - - $user_meta = get_option( 'relevanssi_index_user_meta' ); - if ( $user_meta ) { - $user_fields = array_merge( $user_fields, explode( ',', $user_meta ) ); - } - - $user_fields = array_map( 'trim', $user_fields ); - - return $user_fields; -} - -/** - * Returns an array of user custom field content. - * - * Gets the indexed user field content from the fields specified in the user - * field indexing options. - * - * @uses relevanssi_generate_list_of_user_fields - * - * @param string $user_id The ID of the user. - * - * @return array An array of (field, value) pairs. - */ -function relevanssi_get_user_field_content( $user_id ): array { - $fields = relevanssi_generate_list_of_user_fields(); - $user = get_user_by( 'id', $user_id ); - $user_vars = get_object_vars( $user ); - $values = array(); - foreach ( $fields as $field ) { - $field_value = ''; - if ( isset( $user_vars[ $field ] ) ) { - $field_value = $user_vars[ $field ]; - } - if ( empty( $field_value ) && isset( $user_vars['data']->$field ) ) { - $field_value = $user_vars['data']->$field; - } - if ( empty( $field_value ) ) { - $field_value = get_user_meta( $user_id, $field, true ); - } - $values[ $field ] = $field_value; - } - return $values; -} diff --git a/relevanssi-premium/premium/contextual-help.php b/relevanssi-premium/premium/contextual-help.php deleted file mode 100644 index 1e47e9ad..00000000 --- a/relevanssi-premium/premium/contextual-help.php +++ /dev/null @@ -1,103 +0,0 @@ -add_help_tab( - array( - 'id' => 'relevanssi-boolean', - 'title' => __( 'Boolean operators', 'relevanssi' ), - 'content' => '
      ' . - '
    • ' . __( 'Relevanssi Premium offers limited support for Boolean logic. In addition of setting the default operator from Relevanssi settings, you can use AND and NOT operators in searches.', 'relevanssi' ) . '
    • ' . - '
    • ' . __( 'To use the NOT operator, prefix the search term with a minus sign:', 'relevanssi' ) . - sprintf( '
      %s
      ', __( 'cats -dogs', 'relevanssi' ) ) . - __( "This would only show posts that have the word 'cats' but not the word 'dogs'.", 'relevanssi' ) . '
    • ' . - '
    • ' . __( 'To use the AND operator, set the default operator to OR and prefix the search term with a plus sign:', 'relevanssi' ) . - sprintf( '
      %s
      ', __( '+cats dogs mice', 'relevanssi' ) ) . - __( "This would show posts that have the word 'cats' and either 'dogs' or 'mice' or both, and would prioritize posts that have all three.", 'relevanssi' ) . '
    • ' . - '
    ', - ) - ); - - /* Translators: first placeholder is the_permalink(), the second is relevanssi_the_permalink() */ - $permalinks_to_users = sprintf( esc_html__( "Permalinks to user profiles may not always work on search results templates. %1\$s should work, but if it doesn't, you can replace it with %2\$s.", 'relevanssi' ), 'the_permalink()', 'relevanssi_the_permalink()' ); - /* Translators: the placeholder is the name of the relevanssi_index_user_fields option */ - $index_user_fields = sprintf( esc_html__( 'To control which user meta fields are indexed, you can use the %s option. It should have a comma-separated list of user meta fields. It can be set like this (you only need to run this code once):', 'relevanssi' ), 'relevanssi_index_user_fields' ); - /* Translators: the first placeholder opens the link, the second closes the link */ - $knowledge_base = sprintf( esc_html__( 'For more details on user profiles and search results templates, see %1$sthis knowledge base entry%2$s.', 'relevanssi' ), "", '' ); - - $screen->add_help_tab( - array( - 'id' => 'relevanssi-title-user-profiles', - 'title' => __( 'User profiles', 'relevanssi' ), - 'content' => '
      ' . - "
    • $permalinks_to_users
    • " . - "
    • $index_user_fields" . - "
      update_option( 'relevanssi_index_user_fields', 'field_a,field_b,field_c' );
    • " . - "
    • $knowledge_base
    • " . - '
    ', - ) - ); - $screen->add_help_tab( - array( - 'id' => 'relevanssi-internal-links', - 'title' => __( 'Internal links', 'relevanssi' ), - 'content' => '
      ' . - '
    • ' . __( 'This option sets how Relevanssi handles internal links that point to your own site.', 'relevanssi' ) . '
    • ' . - '
    • ' . __( "If you choose 'No special processing', Relevanssi doesn’t care about links and indexes the link anchor (the text of the link) like it is any other text.", 'relevanssi' ) . '
    • ' . - '
    • ' . __( "If you choose 'Index internal links for target documents only', then the link is indexed like the link anchor text were the part of the link target, not the post where the link is.", 'relevanssi' ) . '
    • ' . - '
    • ' . __( "If you choose 'Index internal links for target and source', the link anchor text will count for both posts.", 'relevanssi' ) . '
    • ' . - '
    ', - ) - ); - $screen->add_help_tab( - array( - 'id' => 'relevanssi-stemming', - 'title' => __( 'Stemming', 'relevanssi' ), - 'content' => '
      ' . - '
    • ' . __( "By default Relevanssi doesn't understand anything about singular word forms, plurals or anything else. You can, however, add a stemmer that will stem all the words to their basic form, making all different forms equal in searching.", 'relevanssi' ) . '
    • ' . - '
    • ' . __( 'To enable the English-language stemmer, add this to the theme functions.php:', 'relevanssi' ) . - "
      add_filter( 'relevanssi_stemmer', 'relevanssi_simple_english_stemmer' );
      " . '
    • ' . - '
    • ' . __( 'After you add the code, rebuild the index to get correct results.', 'relevanssi' ) . '
    • ' . - '
    ', - ) - ); - - /* Translators: the placeholder has the WP CLI command */ - $wp_cli_command = sprintf( esc_html__( 'If you have WP CLI installed, Relevanssi Premium has some helpful commands. Use %s to get a list of available commands.', 'relevanssi' ), 'wp help relevanssi' ); - /* Translators: the first placeholder opens the link, the second closes the link */ - $wp_cli_manual = sprintf( esc_html__( 'You can also see %1$sthe user manual page%2$s.', 'relevanssi' ), "", '' ); - - $screen->add_help_tab( - array( - 'id' => 'relevanssi-wpcli', - 'title' => __( 'WP CLI', 'relevanssi' ), - 'content' => "
      -
    • $wp_cli_command
    • -
    • $wp_cli_manual
    • -
    ", - ) - ); - - $screen->set_help_sidebar( - '

    ' . __( 'For more information:', 'relevanssi' ) . '

    ' . - '

    ' . __( 'Plugin support page', 'relevanssi' ) . '

    ' . - '

    ' . __( 'WordPress.org forum', 'relevanssi' ) . '

    ' . - '

    Support email

    ' . - '

    ' . __( 'Plugin knowledge base', 'relevanssi' ) . '

    ' - ); -} diff --git a/relevanssi-premium/premium/excerpts-highlights.php b/relevanssi-premium/premium/excerpts-highlights.php deleted file mode 100644 index 3c23c241..00000000 --- a/relevanssi-premium/premium/excerpts-highlights.php +++ /dev/null @@ -1,217 +0,0 @@ - 0, adds the excerpt to the list - * of excerpts. To avoid overlapping excerpts, similarity is calculated against - * other excerpts and only those excerpts with a similarity percentage of less - * than 50 are accepted. - * - * @param array $terms An array of relevant words. - * @param string $content The source text. - * @param int $excerpt_length The length of the excerpt, default 30 words. - * - * @return array An array of excerpts. In each excerpt, there are following - * parts: 'text' has the excerpt text, 'hits' the number of keyword matches in - * the excerpt, 'start' is true if the excerpt is from the beginning of the - * content. - */ -function relevanssi_extract_multiple_excerpts( $terms, $content, $excerpt_length = 30 ) { - if ( $excerpt_length < 1 ) { - return array( '', 0, false ); - } - - $words = array_filter( explode( ' ', $content ) ); - $offset = 0; - $tries = 0; - $count_words = count( $words ); - $start = false; - $gap = 0; - - $excerpts = array(); - - $excerpt_candidates = $count_words / $excerpt_length; - if ( $excerpt_candidates > 200 ) { - /** - * Adjusts the gap between excerpt candidates. - * - * The default value for the gap is number of words / 200 minus the - * excerpt length, which means Relevanssi tries to create 200 excerpts. - * - * @param int The gap between excerpt candidates. - * @param int $count_words The number of words in the content. - * @param int $excerpt_length The length of the excerpt. - */ - $gap = apply_filters( - 'relevanssi_excerpt_gap', - floor( $count_words / 200 - $excerpt_length ), - $count_words, - $excerpt_length - ); - } - - while ( $offset < $count_words ) { - if ( $offset + $excerpt_length > $count_words ) { - $offset = $count_words - $excerpt_length; - if ( $offset < 0 ) { - $offset = 0; - } - } - $excerpt_slice = array_slice( $words, $offset, $excerpt_length ); - $excerpt_slice = ' ' . implode( ' ', $excerpt_slice ); - $count_matches = relevanssi_count_matches( $terms, $excerpt_slice ); - if ( $count_matches > 0 ) { - if ( 0 === $offset ) { - $start = true; - } else { - $start = false; - } - - $similarity = 0; - array_walk( - $excerpts, - function ( $item ) use ( &$similarity, $excerpt_slice ) { - similar_text( $item['text'], $excerpt_slice, $percentage ); - if ( $percentage > $similarity ) { - $similarity = $percentage; - } - } - ); - if ( $similarity < 50 ) { - $excerpt = array( - 'hits' => $count_matches, - 'text' => trim( $excerpt_slice ), - 'start' => $start, - ); - $excerpts[] = $excerpt; - } - } - ++$tries; - - /** - * Enables the excerpt optimization. - * - * If your posts are very long, building excerpts can be really slow. - * To speed up the process, you can enable optimization, which means - * Relevanssi only creates 50 excerpt candidates. - * - * @param boolean Return true to enable optimization, default false. - */ - if ( apply_filters( 'relevanssi_optimize_excerpts', false ) ) { - if ( $tries > 50 ) { - // An optimization trick: try only 50 times. - break; - } - } - - $offset += $excerpt_length + $gap; - } - - if ( empty( $excerpts ) && $gap > 0 ) { - $result = relevanssi_get_first_match( $words, $terms, $excerpt_length ); - - if ( ! empty( $result['excerpt'] ) ) { - $excerpts[] = array( - 'text' => $result['excerpt'], - 'hits' => $result['best_excerpt_term_hits'], - 'start' => $result['start'], - ); - } - } - - if ( empty( $excerpts ) ) { - /** - * Nothing found, take the beginning of the post. +2, because the first - * index is an empty space and the last index is the rest of the post. - */ - $words = explode( ' ', $content, $excerpt_length + 2 ); - array_pop( $words ); - $text = implode( ' ', $words ); - $excerpt = array( - 'text' => $text, - 'hits' => 0, - 'start' => true, - ); - $excerpts[] = $excerpt; - } - - return $excerpts; -} - -/** - * Adds the "source" attribute to the excerpts in the array. - * - * @param array $excerpts The excerpts array, passed as a reference. - * @param string $source The source value to add to the excerpts. - */ -function relevanssi_add_source_to_excerpts( &$excerpts, $source ) { - if ( ! is_array( $excerpts ) ) { - return; - } - array_walk( - $excerpts, - function ( &$item ) use ( $source ) { - $item['source'] = $source; - } - ); -} - -/** - * Combines multiple arrays of excerpts together, sorts them and slices them. - * - * Returns a slice with the n excerpts with most term hits. - * - * @param int $post_id The current post ID. - * @param array ...$excerpt_sources Arrays containing excerpts. - * - * @return array An array containing the n best excerpts. - */ -function relevanssi_combine_excerpts( $post_id, ...$excerpt_sources ) { - $excerpts = array_merge( ...$excerpt_sources ); - usort( - $excerpts, - function ( $a, $b ) { - return $b['hits'] - $a['hits']; - } - ); - $number_of_excerpts = get_option( 'relevanssi_max_excerpts', 1 ); - - $excerpts_with_hits = array_filter( - $excerpts, - function ( $excerpt ) { - return $excerpt['hits'] > 0; - } - ); - - if ( count( $excerpts_with_hits ) > 0 ) { - $excerpts = $excerpts_with_hits; - } - - $excerpts = array_slice( - /** - * Filters the excerpt. - * - * Filters the post excerpts generated by Relevanssi before the - * highlighting is applied. - * - * @param array $excerpt An array of excerpts. - * @param int $post->ID The post ID. - */ - apply_filters( 'relevanssi_excerpts', $excerpts, $post_id ), - 0, - $number_of_excerpts - ); - - return $excerpts; -} diff --git a/relevanssi-premium/premium/gutenberg-sidebar.php b/relevanssi-premium/premium/gutenberg-sidebar.php deleted file mode 100644 index a786fa81..00000000 --- a/relevanssi-premium/premium/gutenberg-sidebar.php +++ /dev/null @@ -1,412 +0,0 @@ - '_relevanssi_hide_post', - 'description' => 'Hide this post', - ), - array( - 'meta_key' => '_relevanssi_hide_content', - 'description' => 'Hide post content', - ), - array( - 'meta_key' => '_relevanssi_pin_for_all', - 'description' => 'Pin for all searches', - ), - array( - 'meta_key' => '_relevanssi_pin_keywords', - 'description' => 'Pin for these keywords', - ), - array( - 'meta_key' => '_relevanssi_unpin_keywords', - 'description' => 'Block for these keywords', - ), - array( - 'meta_key' => '_relevanssi_related_keywords', - 'description' => 'Keywords for related posts searches', - ), - array( - 'meta_key' => '_relevanssi_related_include_ids', - 'description' => 'Post IDs for included related posts', - ), - array( - 'meta_key' => '_relevanssi_related_exclude_ids', - 'description' => 'Post IDs for excluded related posts', - ), - array( - 'meta_key' => '_relevanssi_related_no_append', - 'description' => "Don't append related posts to this post", - ), - array( - 'meta_key' => '_relevanssi_related_not_related', - 'description' => 'Disable related posts for this post', - ), - array( - 'meta_key' => '_relevanssi_related_posts', - 'description' => 'Related posts for this post', - ), - array( - 'meta_key' => '_relevanssi_noindex_reason', - 'description' => 'Reason this post is not indexed', - ), - ); - - foreach ( $relevanssi_meta_fields as $meta_field ) { - register_meta( - 'post', - $meta_field['meta_key'], - array( - 'type' => 'string', - 'description' => $meta_field['description'], - 'single' => true, - 'show_in_rest' => true, - 'auth_callback' => '__return_true', - ) - ); - } -} - -/** - * Registers the Gutenberg sidebar script. - * - * Registers the Gutenberg sidebar script, exact version depending on whether - * the RELEVANSSI_DEVELOP constant is set or not, includes the dependencies and - * the translations. - * - * @since 2.5.0 - */ -function relevanssi_register_gutenberg_script() { - global $relevanssi_variables; - - if ( ! function_exists( 'wp_set_script_translations' ) ) { - return; - } - - global $post; - if ( ! $post ) { - return; - } - if ( $post && ! post_type_supports( $post->post_type, 'custom-fields' ) ) { - return; - } - - if ( ! current_user_can( - /** - * Filters the capability required to access the Relevanssi sidebar. - * - * @param string The capability required, default 'edit_others_posts'. - */ - apply_filters( 'relevanssi_sidebar_capability', $relevanssi_variables['sidebar_capability'] ) - ) - ) { - return; - } - - $file_location = 'premium/gutenberg-sidebar/'; - if ( RELEVANSSI_DEVELOP ) { - $file_location = 'build/'; - } - wp_register_script( - 'relevanssi-sidebar', - plugin_dir_url( $relevanssi_variables['plugin_basename'] ) . $file_location . 'index.js', - array( 'wp-api-fetch', 'wp-i18n', 'wp-blocks', 'wp-edit-post', 'wp-element', 'wp-editor', 'wp-components', 'wp-data', 'wp-plugins', 'wp-edit-post' ), - 1, - true - ); - wp_set_script_translations( 'relevanssi-sidebar', 'relevanssi', WP_CONTENT_DIR . '/languages/plugins' ); -} - -/** - * Enqueues the Gutenberg sidebar script. - * - * @since 2.5.0 - */ -function relevanssi_block_editor_assets() { - relevanssi_register_gutenberg_script(); - wp_enqueue_script( 'relevanssi-sidebar' ); -} - -/** - * Adds a REST API endpoint for "How Relevanssi sees this post". - * - * Takes in a post ID and returns the "How Relevanssi sees this post" data for - * that post. - * - * @param array $data The post ID in $data['id']. - * - * @return array The indexed terms for various parts of the post in an - * associative array. - * - * @uses relevanssi_fetch_sees_data() - * - * @since 2.5.0 - */ -function relevanssi_sees_post_endpoint( $data ) { - return relevanssi_fetch_sees_data( $data['id'] ); -} - -/** - * Adds a REST API endpoint for listing the related posts. - * - * @param array $data The post ID in $data['id']. - * - * @return array The related posts in an array format (id, URL and title). - * - * @since 2.5.0 - */ -function relevanssi_list_related_posts_endpoint( $data ) { - return relevanssi_generate_related_list( $data['id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for listing the excluded related posts. - * - * @param array $data The post ID in $data['id']. - * - * @return array The excluded posts in an array format (id, URL and title). - * - * @since 2.5.0 - */ -function relevanssi_list_excluded_posts_endpoint( $data ) { - return relevanssi_generate_excluded_list( $data['id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for excluding a post from related posts. - * - * @param array $data The post ID in $data['post_id'], the ID of the post to - * exclude in $data['exclude']. - * - * @return array The excluded posts in an array format (id, URL and title). - * - * @since 2.5.0 - */ -function relevanssi_exclude_related_post_endpoint( $data ) { - relevanssi_exclude_a_related_post( $data['post_id'], $data['exclude'] ); - return relevanssi_generate_excluded_list( $data['post_id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for unexcluding a post from related posts. - * - * @param array $data The post ID in $data['post_id'], the ID of the post to - * return in $data['return']. - * - * @return array The excluded posts in an array format (id, URL and title). - * - * @since 2.5.0 - */ -function relevanssi_unexclude_related_post_endpoint( $data ) { - relevanssi_unexclude_a_related_post( $data['post_id'], $data['return'] ); - return relevanssi_generate_excluded_list( $data['post_id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for regenerating the related posts list. - * - * This is triggered when either the keywords or the post ID list for the - * related posts is changed. This will get the key and the value of the changed - * meta field as a parameter and will either empty or update the meta field and - * then trigger related posts list regeneration. - * - * @param array $data The post ID in $data['id'], the meta key name in - * $data['meta_key'] and the new value in $data['meta_value']. - * - * @return array The related posts in an array format (id, URL and title). - * - * @since 2.5.0 - */ -function relevanssi_regenerate_related_endpoint( $data ) { - if ( 0 === $data['meta_value'] ) { - delete_post_meta( $data['id'], $data['meta_key'] ); - } else { - update_post_meta( $data['id'], $data['meta_key'], $data['meta_value'] ); - } - delete_post_meta( $data['id'], '_relevanssi_related_posts' ); - return relevanssi_generate_related_list( $data['id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for listing common search terms. - * - * @param array $data The post ID in $data['id']. - * - * @return array The common terms in an array format (id, query, and count). - * - * @since 2.5.0 - */ -function relevanssi_list_insights_common_terms( $data ) { - return relevanssi_generate_tracking_insights_most_common( $data['id'], 'ARRAY' ); -} - -/** - * Adds a REST API endpoint for listing low-ranking search terms. - * - * @param array $data The post ID in $data['id']. - * - * @return array The terms in an array format (id, query, rank). - * - * @since 2.5.0 - */ -function relevanssi_list_insights_low_ranking_terms( $data ) { - return relevanssi_generate_tracking_insights_low_ranking( $data['id'], 'ARRAY' ); -} - -/** - * Registers the REST API endpoints. - * - * @see register_rest_route() - * - * @since 2.5.0 - */ -function relevanssi_register_gutenberg_rest_routes() { - $routes = array( - array( - 'path' => '/excluderelatedpost/(?P\d+)/(?P\d+)', - 'callback' => 'relevanssi_exclude_related_post_endpoint', - 'args' => array( - 'exclude' => 'numeric', - 'post_id' => 'numeric', - ), - ), - array( - 'path' => '/unexcluderelatedpost/(?P\d+)/(?P\d+)', - 'callback' => 'relevanssi_unexclude_related_post_endpoint', - 'args' => array( - 'return' => 'numeric', - 'post_id' => 'numeric', - ), - ), - array( - 'path' => '/listexcluded/(?P\d+)', - 'callback' => 'relevanssi_list_excluded_posts_endpoint', - 'args' => array( - 'id' => 'numeric', - ), - ), - array( - 'path' => '/listrelated/(?P\d+)', - 'callback' => 'relevanssi_list_related_posts_endpoint', - 'args' => array( - 'id' => 'numeric', - ), - ), - array( - 'path' => '/sees/(?P\d+)', - 'callback' => 'relevanssi_sees_post_endpoint', - 'args' => array( - 'id' => 'numeric', - ), - ), - array( - 'path' => '/regeneraterelatedposts/(?P\d+)/(?P\w+)/(?P[^/]+)', - 'callback' => 'relevanssi_regenerate_related_endpoint', - 'args' => array( - 'id' => 'numeric', - 'meta_key' => 'metakey', - 'meta_value' => 'urldecode', - ), - ), - array( - 'path' => '/listinsightscommon/(?P\d+)', - 'callback' => 'relevanssi_list_insights_common_terms', - 'args' => array( - 'id' => 'numeric', - ), - ), - array( - 'path' => '/listinsightslowranking/(?P\d+)', - 'callback' => 'relevanssi_list_insights_low_ranking_terms', - 'args' => array( - 'id' => 'numeric', - ), - ), - ); - - foreach ( $routes as $route ) { - $args = array(); - foreach ( $route['args'] as $name => $type ) { - switch ( $type ) { - case 'metakey': - $args[ $name ] = array( - 'validate_callback' => function ( $param ) { - return in_array( $param, array( '_relevanssi_related_keywords', '_relevanssi_related_include_ids' ), true ); - }, - ); - break; - case 'urldecode': - $args[ $name ] = array( - 'sanitize_callback' => function ( $param ) { - return urldecode( $param ); - }, - ); - break; - case 'numeric': - default: - $args[ $name ] = array( - 'validate_callback' => function ( $param ) { - return is_numeric( $param ); - }, - ); - } - } - - register_rest_route( - 'relevanssi/v1', - $route['path'], - array( - 'methods' => 'GET', - 'callback' => $route['callback'], - 'args' => $args, - 'permission_callback' => function () { - global $relevanssi_variables; - // Filter documented in /premium/gutenberg-sidebar.php. - return current_user_can( apply_filters( 'relevanssi_sidebar_capability', $relevanssi_variables['sidebar_capability'] ) ); - }, - ) - ); - } -} - -/** - * Rename the Relevanssi Gutenberg sidebar translation file. - * - * WordPress assumes the file name is relevanssi-LOCALE-relevanssi-sidebar.json, - * but the file from TranslationsPress is relevanssi-LOCALE.json. We rename the - * file WP is looking for here. - * - * @param string $file The original file name. - * @param string $handle The script handle. - * - * @return string The corrected filename. - */ -function relevanssi_rename_translation_file( $file, $handle ) { - if ( 'relevanssi-sidebar' !== $handle ) { - return $file; - } - return str_replace( '-relevanssi-sidebar', '', $file ); -} diff --git a/relevanssi-premium/premium/gutenberg-sidebar/index.asset.php b/relevanssi-premium/premium/gutenberg-sidebar/index.asset.php deleted file mode 100644 index e02dc370..00000000 --- a/relevanssi-premium/premium/gutenberg-sidebar/index.asset.php +++ /dev/null @@ -1 +0,0 @@ - array('wp-components', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-polyfill'), 'version' => 'b81b50e9375d8f85569a43863b885812'); \ No newline at end of file diff --git a/relevanssi-premium/premium/gutenberg-sidebar/index.js b/relevanssi-premium/premium/gutenberg-sidebar/index.js deleted file mode 100644 index b929afaa..00000000 --- a/relevanssi-premium/premium/gutenberg-sidebar/index.js +++ /dev/null @@ -1,832 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./node_modules/@babel/runtime/helpers/arrayLikeToArray.js": -/*!*****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/arrayLikeToArray.js ***! - \*****************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - - for (var i = 0, arr2 = new Array(len); i < len; i++) { - arr2[i] = arr[i]; - } - - return arr2; -} - -module.exports = _arrayLikeToArray; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/arrayWithHoles.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; -} - -module.exports = _arrayWithHoles; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js": -/*!**********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/assertThisInitialized.js ***! - \**********************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return self; -} - -module.exports = _assertThisInitialized; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/classCallCheck.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/classCallCheck.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -} - -module.exports = _classCallCheck; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/createClass.js": -/*!************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/createClass.js ***! - \************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } -} - -function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; -} - -module.exports = _createClass; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/defineProperty.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/defineProperty.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - -module.exports = _defineProperty; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/getPrototypeOf.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _getPrototypeOf(o) { - module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { - return o.__proto__ || Object.getPrototypeOf(o); - }; - return _getPrototypeOf(o); -} - -module.exports = _getPrototypeOf; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/inherits.js": -/*!*********************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/inherits.js ***! - \*********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var setPrototypeOf = __webpack_require__(/*! ./setPrototypeOf */ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js"); - -function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function"); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - writable: true, - configurable: true - } - }); - if (superClass) setPrototypeOf(subClass, superClass); -} - -module.exports = _inherits; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js": -/*!*********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js ***! - \*********************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _iterableToArrayLimit(arr, i) { - if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; -} - -module.exports = _iterableToArrayLimit; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/nonIterableRest.js": -/*!****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/nonIterableRest.js ***! - \****************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - -module.exports = _nonIterableRest; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js": -/*!**************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js ***! - \**************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var _typeof = __webpack_require__(/*! @babel/runtime/helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js"); - -var assertThisInitialized = __webpack_require__(/*! ./assertThisInitialized */ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js"); - -function _possibleConstructorReturn(self, call) { - if (call && (_typeof(call) === "object" || typeof call === "function")) { - return call; - } - - return assertThisInitialized(self); -} - -module.exports = _possibleConstructorReturn; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js": -/*!***************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/setPrototypeOf.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _setPrototypeOf(o, p) { - module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - - return _setPrototypeOf(o, p); -} - -module.exports = _setPrototypeOf; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/slicedToArray.js": -/*!**************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/slicedToArray.js ***! - \**************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var arrayWithHoles = __webpack_require__(/*! ./arrayWithHoles */ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js"); - -var iterableToArrayLimit = __webpack_require__(/*! ./iterableToArrayLimit */ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js"); - -var unsupportedIterableToArray = __webpack_require__(/*! ./unsupportedIterableToArray */ "./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js"); - -var nonIterableRest = __webpack_require__(/*! ./nonIterableRest */ "./node_modules/@babel/runtime/helpers/nonIterableRest.js"); - -function _slicedToArray(arr, i) { - return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest(); -} - -module.exports = _slicedToArray; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/typeof.js": -/*!*******************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/typeof.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -function _typeof(obj) { - "@babel/helpers - typeof"; - - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - module.exports = _typeof = function _typeof(obj) { - return typeof obj; - }; - } else { - module.exports = _typeof = function _typeof(obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); -} - -module.exports = _typeof; - -/***/ }), - -/***/ "./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js": -/*!***************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js ***! - \***************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var arrayLikeToArray = __webpack_require__(/*! ./arrayLikeToArray */ "./node_modules/@babel/runtime/helpers/arrayLikeToArray.js"); - -function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen); -} - -module.exports = _unsupportedIterableToArray; - -/***/ }), - -/***/ "./src/index.js": -/*!**********************!*\ - !*** ./src/index.js ***! - \**********************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"); -/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"); -/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"); -/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @babel/runtime/helpers/inherits */ "./node_modules/@babel/runtime/helpers/inherits.js"); -/* harmony import */ var _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @babel/runtime/helpers/possibleConstructorReturn */ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js"); -/* harmony import */ var _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @babel/runtime/helpers/getPrototypeOf */ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js"); -/* harmony import */ var _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__); -/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"); -/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6__); -/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); -/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__); -/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); -/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__); -/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @wordpress/plugins */ "@wordpress/plugins"); -/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__); -/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @wordpress/edit-post */ "@wordpress/edit-post"); -/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__); -/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n"); -/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__); -/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @wordpress/data */ "@wordpress/data"); -/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__); -/* harmony import */ var _wordpress_compose__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @wordpress/compose */ "@wordpress/compose"); -/* harmony import */ var _wordpress_compose__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_wordpress_compose__WEBPACK_IMPORTED_MODULE_13__); - - - - - - - - - -function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default()(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5___default()(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4___default()(this, result); }; } - -function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } - - - - - - - - -var relevanssiIcon = wp.element.createElement("svg", { - width: 20, - height: 20 -}, wp.element.createElement("path", { - d: "M5.644 20.665 C6.207 20.545 6.612 20.029 6.574 19.438 6.469 17.784 6.492 16.554 6.617 15.602 L7.388 19.228 C7.454 19.538 7.576 19.815 7.737 20.058 7.742 20.12 7.749 20.181 7.763 20.243 L8.444 23.384 C10.112 23.233 11.311 22.775 11.214 23.077 L10.82 21.227 C10.875 21.218 10.929 21.211 10.984 21.199 10.995 21.197 11.004 21.193 11.015 21.191 L11.35 22.766 C11.571 22.305 13.613 22.092 14.187 21.891 L13.42 19.11 C13.529 18.742 13.553 18.346 13.466 17.936 L12.445 13.134 C12.535 13.088 12.62 13.03 12.698 12.959 12.737 12.929 12.786 12.899 12.84 12.864 13.25 12.596 14.097 12.042 14.433 10.839 L20.429 12.98 C20.642 13.056 20.862 13.067 21.069 13.023 21.456 12.941 21.792 12.667 21.934 12.267 22.154 11.655 21.835 10.981 21.222 10.763 L14.393 8.324 C14.385 8.291 14.379 8.26 14.37 8.226 14.212 7.595 13.573 7.212 12.94 7.372 12.887 7.385 12.838 7.402 12.789 7.422 12.873 6.845 12.859 6.245 12.731 5.643 12.145 2.884 9.422 1.118 6.661 1.705 3.901 2.292 2.132 5.012 2.718 7.771 3.304 10.529 6.027 12.295 8.788 11.708 10.041 11.442 11.088 10.735 11.805 9.786 11.917 9.894 12.05 9.981 12.203 10.04 12.148 10.37 11.997 10.56 11.811 10.71 10.72 11.467 10.238 11.826 9.318 12.07 L8.678 12.167 C7.581 12.344 6.407 12.307 5.457 11.871 4.141 13.689 3.972 15.683 4.221 19.589 4.263 20.238 4.823 20.73 5.473 20.688 5.531 20.685 5.589 20.677 5.644 20.665 Z M8.568 10.67 C6.38 11.135 4.222 9.735 3.758 7.55 3.293 5.364 4.695 3.208 6.883 2.743 9.07 2.278 11.229 3.677 11.693 5.863 12.158 8.049 10.755 10.205 8.568 10.67 Z" -}), wp.element.createElement("path", { - d: "M8.009 5.745 C7.25 5.906 6.576 5.754 6.502 5.406 6.496 5.377 6.496 5.348 6.498 5.318 6.012 5.752 5.765 6.429 5.911 7.115 6.127 8.132 7.122 8.783 8.132 8.568 9.142 8.353 9.786 7.354 9.57 6.338 9.483 5.928 9.269 5.58 8.98 5.323 8.755 5.503 8.411 5.66 8.009 5.745 Z" -})); -var Fragment = wp.element.Fragment; -Object(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_9__["registerPlugin"])("relevanssi-premium", { - render: function render() { - var _useState = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState2 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState, 2), - relevanssiSees = _useState2[0], - setRelevanssiSees = _useState2[1]; - - var _useState3 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState4 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState3, 2), - relevanssiRelated = _useState4[0], - setRelevanssiRelated = _useState4[1]; - - var _useState5 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState6 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState5, 2), - relevanssiExcluded = _useState6[0], - setRelevanssiExcluded = _useState6[1]; - - var _useState7 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState8 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState7, 2), - relevanssiExcludedIds = _useState8[0], - setRelevanssiExcludedIds = _useState8[1]; - - var _useState9 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState10 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState9, 2), - relevanssiCommonTerms = _useState10[0], - setRelevanssiCommonTerms = _useState10[1]; - - var _useState11 = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useState"])([]), - _useState12 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_6___default()(_useState11, 2), - relevanssiLowRankingTerms = _useState12[0], - setRelevanssiLowRankingTerms = _useState12[1]; - - var regenerateRelatedPosts = function regenerateRelatedPosts(postId, metaKey, metaValue) { - if (!metaValue) metaValue = "0"; - wp.apiFetch({ - path: "/relevanssi/v1/regeneraterelatedposts/".concat(postId, "/").concat(metaKey, "/").concat(metaValue) - }).then(function (data) { - setRelevanssiRelated(createRelatedList(data)); - }); - }; - - var RelatedPostControl = Object(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["withFocusOutside"])( /*#__PURE__*/function (_React$Component) { - _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3___default()(_class, _React$Component); - - var _super = _createSuper(_class); - - function _class() { - _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default()(this, _class); - - return _super.apply(this, arguments); - } - - _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default()(_class, [{ - key: "handleFocusOutside", - value: function handleFocusOutside() { - regenerateRelatedPosts(wp.data.select("core/editor").getCurrentPostId(), this.props.metaKey, wp.data.select("core/editor").getEditedPostAttribute("meta")[this.props.metaKey]); - } - }, { - key: "render", - value: function render() { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: this.props.control, - title: this.props.title, - metaKey: this.props.metaKey - }); - } - }]); - - return _class; - }(React.Component)); - var MetaControl = Object(_wordpress_compose__WEBPACK_IMPORTED_MODULE_13__["compose"])(Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["withDispatch"])(function (dispatch, props) { - return { - setMetaValue: function setMetaValue(metaValue) { - dispatch("core/editor").editPost({ - meta: _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default()({}, props.metaKey, metaValue) - }); - } - }; - }), Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["withSelect"])(function (select, props) { - var metaValue = select("core/editor").getEditedPostAttribute("meta")[props.metaKey]; - if (metaValue === "0") metaValue = ""; - return { - metaValue: metaValue - }; - }))(function (props) { - var args = { - label: props.title, - value: props.metaValue, - onChange: function onChange(content) { - props.setMetaValue(content); - } - }; - - if (props.control == _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"]) { - var checked = props.metaValue == "on" ? true : false; - args.value = ""; - args.checked = checked; - - args.onChange = function (content) { - content = content ? "on" : "off"; - props.setMetaValue(content); - }; - } - - return wp.element.createElement(props.control, args); - }); - - var excludeRelatedPost = function excludeRelatedPost(excludedPostId, postId) { - wp.apiFetch({ - path: "/relevanssi/v1/excluderelatedpost/".concat(excludedPostId, "/").concat(postId) - }).then(function (data) { - setRelevanssiExcludedIds(data); - }); - }; - - var unExcludeRelatedPost = function unExcludeRelatedPost(excludedPostId, postId) { - wp.apiFetch({ - path: "/relevanssi/v1/unexcluderelatedpost/".concat(excludedPostId, "/").concat(postId) - }).then(function (data) { - setRelevanssiExcludedIds(data); - }); - }; - - var postId = Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_12__["select"])("core/editor").getCurrentPostId(); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/sees/".concat(postId) - }).then(function (data) { - setRelevanssiSees(data); - }); - }, [postId]); - /* - */ - - var createRelatedList = function createRelatedList(data) { - return data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("a", { - href: row.link - }, row.title), " ", Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Button"], { - onClick: function onClick() { - return excludeRelatedPost(row.id, postId); - } - }, "(", Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("not this", "relevanssi"), ")")); - }); - }; - - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listrelated/".concat(postId) - }).then(function (data) { - setRelevanssiRelated(createRelatedList(data)); - }); - }, [postId, relevanssiExcludedIds]); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listexcluded/".concat(postId) - }).then(function (data) { - var list = data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("a", { - href: row.link - }, row.title), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Button"], { - onClick: function onClick() { - return unExcludeRelatedPost(row.id, postId); - } - }, "(", Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("use this", "relevanssi"), ")")); - }); - setRelevanssiExcluded(list); - }); - }, [postId, relevanssiExcludedIds]); - - var createTermsList = function createTermsList(data) { - return data.map(function (row) { - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("li", { - key: row.id - }, row.query, " (", row.count, ")"); - }); - }; - - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listinsightscommon/".concat(postId) - }).then(function (data) { - setRelevanssiCommonTerms(createTermsList(data)); - }); - }, [postId]); - Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["useEffect"])(function () { - wp.apiFetch({ - path: "/relevanssi/v1/listinsightslowranking/".concat(postId) - }).then(function (data) { - setRelevanssiLowRankingTerms(createTermsList(data)); - }); - }, [postId]); - return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(Fragment, null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__["PluginSidebarMoreMenuItem"], { - target: "relevanssi-premium", - icon: relevanssiIcon - }, "Relevanssi Premium"), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_10__["PluginSidebar"], { - name: "relevanssi-premium", - icon: relevanssiIcon, - title: "Relevanssi Premium" - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("How Relevanssi sees this post", "relevanssi") - }, relevanssiSees.title && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Title:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.title), relevanssiSees.content && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Content:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.content), relevanssiSees.author && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Author:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.author), relevanssiSees.category && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Categories:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.category), relevanssiSees.tag && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Tags:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.tag), relevanssiSees.taxonomy && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Other taxonomies:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.taxonomy), relevanssiSees.comment && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Comments:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.comment), relevanssiSees.customfield && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Custom fields:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.customfield), relevanssiSees.excerpt && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Excerpt:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.excerpt), relevanssiSees.link && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Links to this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.link), relevanssiSees.mysql && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("MySQL columns:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.mysql), relevanssiSees.reason && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("strong", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Reason this post is not indexed:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("br", null), relevanssiSees.reason))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Pinning", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Pin this post for all searches it appears in.", "relevanssi"), - metaKey: "_relevanssi_pin_for_all" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of single word keywords or multi-word phrases.", "relevanssi"), - metaKey: "_relevanssi_pin_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("If any of these keywords are present in the search query, this post will be moved on top of the search results.", "relevanssi"))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("You can add weights to pinned keywords like this: 'keyword (100)'. The post with the highest weight will be sorted first if there are multiple posts pinned to the same keyword.", "relevanssi")))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Exclusion", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Exclude this post or page from the index.", "relevanssi"), - metaKey: "_relevanssi_hide_post" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Ignore post content in the indexing.", "relevanssi"), - metaKey: "_relevanssi_hide_content" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of single word keywords or multi-word phrases.", "relevanssi"), - metaKey: "_relevanssi_unpin_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("If any of these keywords are present in the search query, this post will be removed from the search results.", "relevanssi"))))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Related posts", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Don't append the related posts to this page.", "relevanssi"), - metaKey: "_relevanssi_related_no_append" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(MetaControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["CheckboxControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Don't show this as a related post for any post.", "relevanssi"), - metaKey: "_relevanssi_related_not_related" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(RelatedPostControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextareaControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of keywords to use for the Related Posts feature.", "relevanssi"), - metaKey: "_relevanssi_related_keywords" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Anything entered here will used when searching for related posts. Using phrases with quotes is allowed, but will restrict the related posts to posts including that phrase.", "relevanssi"))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(RelatedPostControl, { - control: _wordpress_components__WEBPACK_IMPORTED_MODULE_8__["TextControl"], - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("A comma-separated list of post IDs to use as related posts for this post", "relevanssi"), - metaKey: "_relevanssi_related_include_ids" - })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Related posts for this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiRelated), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Excluded posts for this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiExcluded))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["Panel"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_8__["PanelBody"], { - initialOpen: false, - title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Insights", "relevanssi") - }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("The most common search terms used to find this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiCommonTerms), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("p", null, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_11__["__"])("Low-ranking search terms used to find this post:", "relevanssi")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_7__["createElement"])("ol", null, relevanssiLowRankingTerms))))); - } -}); - -/***/ }), - -/***/ "@wordpress/components": -/*!************************************!*\ - !*** external ["wp","components"] ***! - \************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["components"]; }()); - -/***/ }), - -/***/ "@wordpress/compose": -/*!*********************************!*\ - !*** external ["wp","compose"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["compose"]; }()); - -/***/ }), - -/***/ "@wordpress/data": -/*!******************************!*\ - !*** external ["wp","data"] ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["data"]; }()); - -/***/ }), - -/***/ "@wordpress/edit-post": -/*!**********************************!*\ - !*** external ["wp","editPost"] ***! - \**********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["editPost"]; }()); - -/***/ }), - -/***/ "@wordpress/element": -/*!*********************************!*\ - !*** external ["wp","element"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["element"]; }()); - -/***/ }), - -/***/ "@wordpress/i18n": -/*!******************************!*\ - !*** external ["wp","i18n"] ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["i18n"]; }()); - -/***/ }), - -/***/ "@wordpress/plugins": -/*!*********************************!*\ - !*** external ["wp","plugins"] ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -(function() { module.exports = window["wp"]["plugins"]; }()); - -/***/ }) - -/******/ }); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/relevanssi-premium/premium/gutenberg-sidebar/index.js.map b/relevanssi-premium/premium/gutenberg-sidebar/index.js.map deleted file mode 100644 index 98a1e00d..00000000 --- a/relevanssi-premium/premium/gutenberg-sidebar/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/@babel/runtime/helpers/arrayLikeToArray.js","webpack:///./node_modules/@babel/runtime/helpers/arrayWithHoles.js","webpack:///./node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack:///./node_modules/@babel/runtime/helpers/classCallCheck.js","webpack:///./node_modules/@babel/runtime/helpers/createClass.js","webpack:///./node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///./node_modules/@babel/runtime/helpers/getPrototypeOf.js","webpack:///./node_modules/@babel/runtime/helpers/inherits.js","webpack:///./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js","webpack:///./node_modules/@babel/runtime/helpers/nonIterableRest.js","webpack:///./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js","webpack:///./node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack:///./node_modules/@babel/runtime/helpers/slicedToArray.js","webpack:///./node_modules/@babel/runtime/helpers/typeof.js","webpack:///./node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js","webpack:///./src/index.js","webpack:///external [\"wp\",\"components\"]","webpack:///external [\"wp\",\"compose\"]","webpack:///external [\"wp\",\"data\"]","webpack:///external [\"wp\",\"editPost\"]","webpack:///external [\"wp\",\"element\"]","webpack:///external [\"wp\",\"i18n\"]","webpack:///external [\"wp\",\"plugins\"]"],"names":["relevanssiIcon","wp","element","createElement","width","height","d","Fragment","registerPlugin","render","useState","relevanssiSees","setRelevanssiSees","relevanssiRelated","setRelevanssiRelated","relevanssiExcluded","setRelevanssiExcluded","relevanssiExcludedIds","setRelevanssiExcludedIds","relevanssiCommonTerms","setRelevanssiCommonTerms","relevanssiLowRankingTerms","setRelevanssiLowRankingTerms","regenerateRelatedPosts","postId","metaKey","metaValue","apiFetch","path","then","data","createRelatedList","RelatedPostControl","withFocusOutside","select","getCurrentPostId","props","getEditedPostAttribute","control","title","React","Component","MetaControl","compose","withDispatch","dispatch","setMetaValue","editPost","meta","withSelect","args","label","value","onChange","content","CheckboxControl","checked","excludeRelatedPost","excludedPostId","unExcludeRelatedPost","useEffect","map","row","id","link","__","list","createTermsList","query","count","author","category","tag","taxonomy","comment","customfield","excerpt","mysql","reason","TextareaControl","TextControl"],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA;AACA;;AAEA,wCAAwC,SAAS;AACjD;AACA;;AAEA;AACA;;AAEA,mC;;;;;;;;;;;ACVA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACJA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wC;;;;;;;;;;;ACRA;AACA;AACA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACNA;AACA,iBAAiB,kBAAkB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,8B;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;;AAEA;AACA;;AAEA,iC;;;;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;;AAEA,iC;;;;;;;;;;;ACPA,qBAAqB,mBAAO,CAAC,iFAAkB;;AAE/C;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA,2B;;;;;;;;;;;ACjBA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6CAA6C,+BAA+B;AAC5E;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA,uC;;;;;;;;;;;AC3BA;AACA;AACA;;AAEA,kC;;;;;;;;;;;ACJA,cAAc,mBAAO,CAAC,sFAA+B;;AAErD,4BAA4B,mBAAO,CAAC,+FAAyB;;AAE7D;AACA;AACA;AACA;;AAEA;AACA;;AAEA,4C;;;;;;;;;;;ACZA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,iC;;;;;;;;;;;ACTA,qBAAqB,mBAAO,CAAC,iFAAkB;;AAE/C,2BAA2B,mBAAO,CAAC,6FAAwB;;AAE3D,iCAAiC,mBAAO,CAAC,yGAA8B;;AAEvE,sBAAsB,mBAAO,CAAC,mFAAmB;;AAEjD;AACA;AACA;;AAEA,gC;;;;;;;;;;;ACZA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA,yB;;;;;;;;;;;AChBA,uBAAuB,mBAAO,CAAC,qFAAoB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,6C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACXA;AAUA;AACA;AACA;AACA;AACA;AACA;AAEA,IAAMA,cAAc,GAAGC,EAAE,CAACC,OAAH,CAAWC,aAAX,CACtB,KADsB,EAEtB;AACCC,OAAK,EAAE,EADR;AAECC,QAAM,EAAE;AAFT,CAFsB,EAMtBJ,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyB,MAAzB,EAAiC;AAChCG,GAAC,EAAE;AAD6B,CAAjC,CANsB,EAStBL,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyB,MAAzB,EAAiC;AAChCG,GAAC,EAAE;AAD6B,CAAjC,CATsB,CAAvB;AAcA,IAAQC,QAAR,GAAqBN,EAAE,CAACC,OAAxB,CAAQK,QAAR;AAEAC,yEAAc,CAAC,oBAAD,EAAuB;AACpCC,QAAM,EAAE,kBAAY;AACnB,oBAA4CC,mEAAQ,CAAC,EAAD,CAApD;AAAA;AAAA,QAAOC,cAAP;AAAA,QAAuBC,iBAAvB;;AACA,qBAAkDF,mEAAQ,CAAC,EAAD,CAA1D;AAAA;AAAA,QAAOG,iBAAP;AAAA,QAA0BC,oBAA1B;;AACA,qBAAoDJ,mEAAQ,CAAC,EAAD,CAA5D;AAAA;AAAA,QAAOK,kBAAP;AAAA,QAA2BC,qBAA3B;;AACA,qBAA0DN,mEAAQ,CAAC,EAAD,CAAlE;AAAA;AAAA,QAAOO,qBAAP;AAAA,QAA8BC,wBAA9B;;AACA,qBAA0DR,mEAAQ,CAAC,EAAD,CAAlE;AAAA;AAAA,QAAOS,qBAAP;AAAA,QAA8BC,wBAA9B;;AACA,sBAAkEV,mEAAQ,CACzE,EADyE,CAA1E;AAAA;AAAA,QAAOW,yBAAP;AAAA,QAAkCC,4BAAlC;;AAIA,QAAMC,sBAAsB,GAAG,SAAzBA,sBAAyB,CAACC,MAAD,EAASC,OAAT,EAAkBC,SAAlB,EAAgC;AAC9D,UAAI,CAACA,SAAL,EAAgBA,SAAS,GAAG,GAAZ;AAChBzB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,kDAA2CJ,MAA3C,cAAqDC,OAArD,cAAgEC,SAAhE;AADO,OAAZ,EAEGG,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBhB,4BAAoB,CAACiB,iBAAiB,CAACD,IAAD,CAAlB,CAApB;AACA,OAJD;AAKA,KAPD;;AASA,QAAME,kBAAkB,GAAGC,8EAAgB;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,eAEzC,8BAAqB;AACpBV,gCAAsB,CACrBtB,EAAE,CAAC6B,IAAH,CAAQI,MAAR,CAAe,aAAf,EAA8BC,gBAA9B,EADqB,EAErB,KAAKC,KAAL,CAAWX,OAFU,EAGrBxB,EAAE,CAAC6B,IAAH,CAAQI,MAAR,CAAe,aAAf,EAA8BG,sBAA9B,CAAqD,MAArD,EACC,KAAKD,KAAL,CAAWX,OADZ,CAHqB,CAAtB;AAOA;AAVwC;AAAA;AAAA,eAYzC,kBAAS;AACR,iBACC,yEAAC,WAAD;AACC,mBAAO,EAAE,KAAKW,KAAL,CAAWE,OADrB;AAEC,iBAAK,EAAE,KAAKF,KAAL,CAAWG,KAFnB;AAGC,mBAAO,EAAE,KAAKH,KAAL,CAAWX;AAHrB,YADD;AAOA;AApBwC;;AAAA;AAAA,MAC5Be,KAAK,CAACC,SADsB,EAA3C;AAwBA,QAAMC,WAAW,GAAGC,mEAAO,CAC1BC,qEAAY,CAAC,UAACC,QAAD,EAAWT,KAAX,EAAqB;AACjC,aAAO;AACNU,oBAAY,EAAE,sBAAUpB,SAAV,EAAqB;AAClCmB,kBAAQ,CAAC,aAAD,CAAR,CAAwBE,QAAxB,CAAiC;AAChCC,gBAAI,EAAE,iFAAGZ,KAAK,CAACX,OAAX,EAAqBC,SAArB;AAD4B,WAAjC;AAGA;AALK,OAAP;AAOA,KARW,CADc,EAU1BuB,mEAAU,CAAC,UAACf,MAAD,EAASE,KAAT,EAAmB;AAC7B,UAAIV,SAAS,GACZQ,MAAM,CAAC,aAAD,CAAN,CAAsBG,sBAAtB,CAA6C,MAA7C,EAAqDD,KAAK,CAACX,OAA3D,CADD;AAEA,UAAIC,SAAS,KAAK,GAAlB,EAAuBA,SAAS,GAAG,EAAZ;AACvB,aAAO;AACNA,iBAAS,EAATA;AADM,OAAP;AAGA,KAPS,CAVgB,CAAP,CAkBlB,UAACU,KAAD,EAAW;AACZ,UAAIc,IAAI,GAAG;AACVC,aAAK,EAAEf,KAAK,CAACG,KADH;AAEVa,aAAK,EAAEhB,KAAK,CAACV,SAFH;AAGV2B,gBAAQ,EAAE,kBAAUC,OAAV,EAAmB;AAC5BlB,eAAK,CAACU,YAAN,CAAmBQ,OAAnB;AACA;AALS,OAAX;;AAOA,UAAIlB,KAAK,CAACE,OAAN,IAAiBiB,qEAArB,EAAsC;AACrC,YAAMC,OAAO,GAAGpB,KAAK,CAACV,SAAN,IAAmB,IAAnB,GAA0B,IAA1B,GAAiC,KAAjD;AACAwB,YAAI,CAACE,KAAL,GAAa,EAAb;AACAF,YAAI,CAACM,OAAL,GAAeA,OAAf;;AACAN,YAAI,CAACG,QAAL,GAAgB,UAAUC,OAAV,EAAmB;AAClCA,iBAAO,GAAGA,OAAO,GAAG,IAAH,GAAU,KAA3B;AACAlB,eAAK,CAACU,YAAN,CAAmBQ,OAAnB;AACA,SAHD;AAIA;;AACD,aAAOrD,EAAE,CAACC,OAAH,CAAWC,aAAX,CAAyBiC,KAAK,CAACE,OAA/B,EAAwCY,IAAxC,CAAP;AACA,KApCmB,CAApB;;AAsCA,QAAMO,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC,cAAD,EAAiBlC,MAAjB,EAA4B;AACtDvB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,8CAAuC8B,cAAvC,cAAyDlC,MAAzD;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBZ,gCAAwB,CAACY,IAAD,CAAxB;AACA,OAJD;AAKA,KAND;;AAQA,QAAM6B,oBAAoB,GAAG,SAAvBA,oBAAuB,CAACD,cAAD,EAAiBlC,MAAjB,EAA4B;AACxDvB,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,gDAAyC8B,cAAzC,cAA2DlC,MAA3D;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBZ,gCAAwB,CAACY,IAAD,CAAxB;AACA,OAJD;AAKA,KAND;;AAQA,QAAMN,MAAM,GAAGU,+DAAM,CAAC,aAAD,CAAN,CAAsBC,gBAAtB,EAAf;AACAyB,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,gCAAyBJ,MAAzB;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBlB,yBAAiB,CAACkB,IAAD,CAAjB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAQA;AACF;;AAIE,QAAMO,iBAAiB,GAAG,SAApBA,iBAAoB,CAACD,IAAD,EAAU;AACnC,aAAOA,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AACxB,eACC;AAAI,aAAG,EAAEA,GAAG,CAACC;AAAb,WACC;AAAG,cAAI,EAAED,GAAG,CAACE;AAAb,WAAoBF,GAAG,CAACvB,KAAxB,CADD,EACoC,GADpC,EAEC,yEAAC,4DAAD;AAAQ,iBAAO,EAAE;AAAA,mBAAMkB,kBAAkB,CAACK,GAAG,CAACC,EAAL,EAASvC,MAAT,CAAxB;AAAA;AAAjB,gBACGyC,2DAAE,CAAC,UAAD,EAAa,YAAb,CADL,MAFD,CADD;AAQA,OATM,CAAP;AAUA,KAXD;;AAYAL,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,uCAAgCJ,MAAhC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBhB,4BAAoB,CAACiB,iBAAiB,CAACD,IAAD,CAAlB,CAApB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,EAASP,qBAAT,CANM,CAAT;AAQA2C,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,wCAAiCJ,MAAjC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjB,YAAMoC,IAAI,GAAGpC,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AAC9B,iBACC;AAAI,eAAG,EAAEA,GAAG,CAACC;AAAb,aACC;AAAG,gBAAI,EAAED,GAAG,CAACE;AAAb,aAAoBF,GAAG,CAACvB,KAAxB,CADD,EAEC,yEAAC,4DAAD;AAAQ,mBAAO,EAAE;AAAA,qBAAMoB,oBAAoB,CAACG,GAAG,CAACC,EAAL,EAASvC,MAAT,CAA1B;AAAA;AAAjB,kBACGyC,2DAAE,CAAC,UAAD,EAAa,YAAb,CADL,MAFD,CADD;AAQA,SATY,CAAb;AAUAjD,6BAAqB,CAACkD,IAAD,CAArB;AACA,OAdD;AAeA,KAhBQ,EAgBN,CAAC1C,MAAD,EAASP,qBAAT,CAhBM,CAAT;;AAkBA,QAAMkD,eAAe,GAAG,SAAlBA,eAAkB,CAACrC,IAAD,EAAU;AACjC,aAAOA,IAAI,CAAC+B,GAAL,CAAS,UAACC,GAAD,EAAS;AACxB,eACC;AAAI,aAAG,EAAEA,GAAG,CAACC;AAAb,WACED,GAAG,CAACM,KADN,QACeN,GAAG,CAACO,KADnB,MADD;AAKA,OANM,CAAP;AAOA,KARD;;AASAT,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,8CAAuCJ,MAAvC;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBV,gCAAwB,CAAC+C,eAAe,CAACrC,IAAD,CAAhB,CAAxB;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAOAoC,wEAAS,CAAC,YAAM;AACf3D,QAAE,CAAC0B,QAAH,CAAY;AACXC,YAAI,kDAA2CJ,MAA3C;AADO,OAAZ,EAEGK,IAFH,CAEQ,UAACC,IAAD,EAAU;AACjBR,oCAA4B,CAAC6C,eAAe,CAACrC,IAAD,CAAhB,CAA5B;AACA,OAJD;AAKA,KANQ,EAMN,CAACN,MAAD,CANM,CAAT;AAQA,WACC,yEAAC,QAAD,QACC,yEAAC,+EAAD;AACC,YAAM,EAAC,oBADR;AAEC,UAAI,EAAExB;AAFP,4BADD,EAOC,yEAAC,mEAAD;AACC,UAAI,EAAC,oBADN;AAEC,UAAI,EAAEA,cAFP;AAGC,WAAK,EAAC;AAHP,OAKC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEiE,2DAAE,CAAC,+BAAD,EAAkC,YAAlC;AAFV,OAIEtD,cAAc,CAAC4B,KAAf,IACA,oFACC,yFAAS0B,2DAAE,CAAC,QAAD,EAAW,YAAX,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC4B,KAHjB,CALF,EAWE5B,cAAc,CAAC2C,OAAf,IACA,oFACC,yFAASW,2DAAE,CAAC,UAAD,EAAa,YAAb,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC2C,OAHjB,CAZF,EAkBE3C,cAAc,CAAC2D,MAAf,IACA,oFACC,yFAASL,2DAAE,CAAC,SAAD,EAAY,YAAZ,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC2D,MAHjB,CAnBF,EAyBE3D,cAAc,CAAC4D,QAAf,IACA,oFACC,yFAASN,2DAAE,CAAC,aAAD,EAAgB,YAAhB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC4D,QAHjB,CA1BF,EAgCE5D,cAAc,CAAC6D,GAAf,IACA,oFACC,yFAASP,2DAAE,CAAC,OAAD,EAAU,YAAV,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC6D,GAHjB,CAjCF,EAuCE7D,cAAc,CAAC8D,QAAf,IACA,oFACC,yFAASR,2DAAE,CAAC,mBAAD,EAAsB,YAAtB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC8D,QAHjB,CAxCF,EA8CE9D,cAAc,CAAC+D,OAAf,IACA,oFACC,yFAAST,2DAAE,CAAC,WAAD,EAAc,YAAd,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAAC+D,OAHjB,CA/CF,EAqDE/D,cAAc,CAACgE,WAAf,IACA,oFACC,yFAASV,2DAAE,CAAC,gBAAD,EAAmB,YAAnB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACgE,WAHjB,CAtDF,EA4DEhE,cAAc,CAACiE,OAAf,IACA,oFACC,yFAASX,2DAAE,CAAC,UAAD,EAAa,YAAb,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACiE,OAHjB,CA7DF,EAmEEjE,cAAc,CAACqD,IAAf,IACA,oFACC,yFAASC,2DAAE,CAAC,qBAAD,EAAwB,YAAxB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACqD,IAHjB,CApEF,EA0EErD,cAAc,CAACkE,KAAf,IACA,oFACC,yFAASZ,2DAAE,CAAC,gBAAD,EAAmB,YAAnB,CAAX,CADD,EAEC,oFAFD,EAGEtD,cAAc,CAACkE,KAHjB,CA3EF,EAiFElE,cAAc,CAACmE,MAAf,IACA,oFACC,yFACEb,2DAAE,CAAC,kCAAD,EAAqC,YAArC,CADJ,CADD,EAIC,oFAJD,EAKEtD,cAAc,CAACmE,MALjB,CAlFF,CADD,CALD,EAkGC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AAAW,iBAAW,EAAE,KAAxB;AAA+B,WAAK,EAAEb,2DAAE,CAAC,SAAD,EAAY,YAAZ;AAAxC,OACC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,+CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CADD,EAWC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,uEADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAXD,EAqBC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,iHAAD,EAAoH,YAApH,CADJ,CADD,CArBD,EA0BC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,kLAAD,EAAqL,YAArL,CADJ,CADD,CA1BD,CADD,EAiCC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEA,2DAAE,CAAC,WAAD,EAAc,YAAd;AAFV,OAIC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,2CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAJD,EAcC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,sCADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAdD,EAwBC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,uEADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAxBD,EAkCC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,8GAAD,EAAiH,YAAjH,CADJ,CADD,CAlCD,CAjCD,CAlGD,EA4KC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AACC,iBAAW,EAAE,KADd;AAEC,WAAK,EAAEA,2DAAE,CAAC,eAAD,EAAkB,YAAlB;AAFV,OAIC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,8CADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAJD,EAcC,yEAAC,8DAAD,QACC,yEAAC,WAAD;AACC,aAAO,EAAEV,qEADV;AAEC,WAAK,EAAEU,2DAAE,CACR,iDADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAdD,EAwBC,yEAAC,8DAAD,QACC,yEAAC,kBAAD;AACC,aAAO,EAAEc,qEADV;AAEC,WAAK,EAAEd,2DAAE,CACR,0EADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAxBD,EAkCC,yEAAC,8DAAD,QACC,oFACEA,2DAAE,CAAC,6KAAD,EAAgL,YAAhL,CADJ,CADD,CAlCD,EAuCC,yEAAC,8DAAD,QACC,yEAAC,kBAAD;AACC,aAAO,EAAEe,iEADV;AAEC,WAAK,EAAEf,2DAAE,CACR,0EADQ,EAER,YAFQ,CAFV;AAMC,aAAO,EAAC;AANT,MADD,CAvCD,EAiDC,oFAAIA,2DAAE,CAAC,8BAAD,EAAiC,YAAjC,CAAN,CAjDD,EAkDC,qFAAKpD,iBAAL,CAlDD,EAoDC,oFAAIoD,2DAAE,CAAC,+BAAD,EAAkC,YAAlC,CAAN,CApDD,EAqDC,qFAAKlD,kBAAL,CArDD,CADD,CA5KD,EAqOC,yEAAC,2DAAD,QACC,yEAAC,+DAAD;AAAW,iBAAW,EAAE,KAAxB;AAA+B,WAAK,EAAEkD,2DAAE,CAAC,UAAD,EAAa,YAAb;AAAxC,OACC,oFACEA,2DAAE,CACF,sDADE,EAEF,YAFE,CADJ,CADD,EAOC,qFAAK9C,qBAAL,CAPD,EAQC,oFACE8C,2DAAE,CACF,kDADE,EAEF,YAFE,CADJ,CARD,EAcC,qFAAK5C,yBAAL,CAdD,CADD,CArOD,CAPD,CADD;AAkQA;AAhbmC,CAAvB,CAAd,C;;;;;;;;;;;ACjCA,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I;;;;;;;;;;;ACAtD,aAAa,2CAA2C,EAAE,I;;;;;;;;;;;ACA1D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I;;;;;;;;;;;ACAtD,aAAa,0CAA0C,EAAE,I","file":"index.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/index.js\");\n","function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n\n for (var i = 0, arr2 = new Array(len); i < len; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n}\n\nmodule.exports = _arrayLikeToArray;","function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nmodule.exports = _arrayWithHoles;","function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n\n return self;\n}\n\nmodule.exports = _assertThisInitialized;","function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nmodule.exports = _classCallCheck;","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nmodule.exports = _createClass;","function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nmodule.exports = _defineProperty;","function _getPrototypeOf(o) {\n module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}\n\nmodule.exports = _getPrototypeOf;","var setPrototypeOf = require(\"./setPrototypeOf\");\n\nfunction _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}\n\nmodule.exports = _inherits;","function _iterableToArrayLimit(arr, i) {\n if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nmodule.exports = _iterableToArrayLimit;","function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\n\nmodule.exports = _nonIterableRest;","var _typeof = require(\"@babel/runtime/helpers/typeof\");\n\nvar assertThisInitialized = require(\"./assertThisInitialized\");\n\nfunction _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n }\n\n return assertThisInitialized(self);\n}\n\nmodule.exports = _possibleConstructorReturn;","function _setPrototypeOf(o, p) {\n module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}\n\nmodule.exports = _setPrototypeOf;","var arrayWithHoles = require(\"./arrayWithHoles\");\n\nvar iterableToArrayLimit = require(\"./iterableToArrayLimit\");\n\nvar unsupportedIterableToArray = require(\"./unsupportedIterableToArray\");\n\nvar nonIterableRest = require(\"./nonIterableRest\");\n\nfunction _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();\n}\n\nmodule.exports = _slicedToArray;","function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n module.exports = _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n module.exports = _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nmodule.exports = _typeof;","var arrayLikeToArray = require(\"./arrayLikeToArray\");\n\nfunction _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}\n\nmodule.exports = _unsupportedIterableToArray;","import {\n\tPanel,\n\tPanelBody,\n\tPanelRow,\n\tTextControl,\n\tTextareaControl,\n\tCheckboxControl,\n\tButton,\n\twithFocusOutside,\n} from \"@wordpress/components\"\nimport { registerPlugin } from \"@wordpress/plugins\"\nimport { PluginSidebar, PluginSidebarMoreMenuItem } from \"@wordpress/edit-post\"\nimport { __ } from \"@wordpress/i18n\"\nimport { select, withSelect, withDispatch } from \"@wordpress/data\"\nimport { compose } from \"@wordpress/compose\"\nimport { useState, useEffect } from \"@wordpress/element\"\n\nconst relevanssiIcon = wp.element.createElement(\n\t\"svg\",\n\t{\n\t\twidth: 20,\n\t\theight: 20,\n\t},\n\twp.element.createElement(\"path\", {\n\t\td: \"M5.644 20.665 C6.207 20.545 6.612 20.029 6.574 19.438 6.469 17.784 6.492 16.554 6.617 15.602 L7.388 19.228 C7.454 19.538 7.576 19.815 7.737 20.058 7.742 20.12 7.749 20.181 7.763 20.243 L8.444 23.384 C10.112 23.233 11.311 22.775 11.214 23.077 L10.82 21.227 C10.875 21.218 10.929 21.211 10.984 21.199 10.995 21.197 11.004 21.193 11.015 21.191 L11.35 22.766 C11.571 22.305 13.613 22.092 14.187 21.891 L13.42 19.11 C13.529 18.742 13.553 18.346 13.466 17.936 L12.445 13.134 C12.535 13.088 12.62 13.03 12.698 12.959 12.737 12.929 12.786 12.899 12.84 12.864 13.25 12.596 14.097 12.042 14.433 10.839 L20.429 12.98 C20.642 13.056 20.862 13.067 21.069 13.023 21.456 12.941 21.792 12.667 21.934 12.267 22.154 11.655 21.835 10.981 21.222 10.763 L14.393 8.324 C14.385 8.291 14.379 8.26 14.37 8.226 14.212 7.595 13.573 7.212 12.94 7.372 12.887 7.385 12.838 7.402 12.789 7.422 12.873 6.845 12.859 6.245 12.731 5.643 12.145 2.884 9.422 1.118 6.661 1.705 3.901 2.292 2.132 5.012 2.718 7.771 3.304 10.529 6.027 12.295 8.788 11.708 10.041 11.442 11.088 10.735 11.805 9.786 11.917 9.894 12.05 9.981 12.203 10.04 12.148 10.37 11.997 10.56 11.811 10.71 10.72 11.467 10.238 11.826 9.318 12.07 L8.678 12.167 C7.581 12.344 6.407 12.307 5.457 11.871 4.141 13.689 3.972 15.683 4.221 19.589 4.263 20.238 4.823 20.73 5.473 20.688 5.531 20.685 5.589 20.677 5.644 20.665 Z M8.568 10.67 C6.38 11.135 4.222 9.735 3.758 7.55 3.293 5.364 4.695 3.208 6.883 2.743 9.07 2.278 11.229 3.677 11.693 5.863 12.158 8.049 10.755 10.205 8.568 10.67 Z\",\n\t}),\n\twp.element.createElement(\"path\", {\n\t\td: \"M8.009 5.745 C7.25 5.906 6.576 5.754 6.502 5.406 6.496 5.377 6.496 5.348 6.498 5.318 6.012 5.752 5.765 6.429 5.911 7.115 6.127 8.132 7.122 8.783 8.132 8.568 9.142 8.353 9.786 7.354 9.57 6.338 9.483 5.928 9.269 5.58 8.98 5.323 8.755 5.503 8.411 5.66 8.009 5.745 Z\",\n\t})\n)\n\nconst { Fragment } = wp.element\n\nregisterPlugin(\"relevanssi-premium\", {\n\trender: function () {\n\t\tconst [relevanssiSees, setRelevanssiSees] = useState([])\n\t\tconst [relevanssiRelated, setRelevanssiRelated] = useState([])\n\t\tconst [relevanssiExcluded, setRelevanssiExcluded] = useState([])\n\t\tconst [relevanssiExcludedIds, setRelevanssiExcludedIds] = useState([])\n\t\tconst [relevanssiCommonTerms, setRelevanssiCommonTerms] = useState([])\n\t\tconst [relevanssiLowRankingTerms, setRelevanssiLowRankingTerms] = useState(\n\t\t\t[]\n\t\t)\n\n\t\tconst regenerateRelatedPosts = (postId, metaKey, metaValue) => {\n\t\t\tif (!metaValue) metaValue = \"0\"\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/regeneraterelatedposts/${postId}/${metaKey}/${metaValue}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiRelated(createRelatedList(data))\n\t\t\t})\n\t\t}\n\n\t\tconst RelatedPostControl = withFocusOutside(\n\t\t\tclass extends React.Component {\n\t\t\t\thandleFocusOutside() {\n\t\t\t\t\tregenerateRelatedPosts(\n\t\t\t\t\t\twp.data.select(\"core/editor\").getCurrentPostId(),\n\t\t\t\t\t\tthis.props.metaKey,\n\t\t\t\t\t\twp.data.select(\"core/editor\").getEditedPostAttribute(\"meta\")[\n\t\t\t\t\t\t\tthis.props.metaKey\n\t\t\t\t\t\t]\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\n\t\tconst MetaControl = compose(\n\t\t\twithDispatch((dispatch, props) => {\n\t\t\t\treturn {\n\t\t\t\t\tsetMetaValue: function (metaValue) {\n\t\t\t\t\t\tdispatch(\"core/editor\").editPost({\n\t\t\t\t\t\t\tmeta: { [props.metaKey]: metaValue },\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}),\n\t\t\twithSelect((select, props) => {\n\t\t\t\tlet metaValue =\n\t\t\t\t\tselect(\"core/editor\").getEditedPostAttribute(\"meta\")[props.metaKey]\n\t\t\t\tif (metaValue === \"0\") metaValue = \"\"\n\t\t\t\treturn {\n\t\t\t\t\tmetaValue,\n\t\t\t\t}\n\t\t\t})\n\t\t)((props) => {\n\t\t\tlet args = {\n\t\t\t\tlabel: props.title,\n\t\t\t\tvalue: props.metaValue,\n\t\t\t\tonChange: function (content) {\n\t\t\t\t\tprops.setMetaValue(content)\n\t\t\t\t},\n\t\t\t}\n\t\t\tif (props.control == CheckboxControl) {\n\t\t\t\tconst checked = props.metaValue == \"on\" ? true : false\n\t\t\t\targs.value = \"\"\n\t\t\t\targs.checked = checked\n\t\t\t\targs.onChange = function (content) {\n\t\t\t\t\tcontent = content ? \"on\" : \"off\"\n\t\t\t\t\tprops.setMetaValue(content)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn wp.element.createElement(props.control, args)\n\t\t})\n\n\t\tconst excludeRelatedPost = (excludedPostId, postId) => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/excluderelatedpost/${excludedPostId}/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiExcludedIds(data)\n\t\t\t})\n\t\t}\n\n\t\tconst unExcludeRelatedPost = (excludedPostId, postId) => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/unexcluderelatedpost/${excludedPostId}/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiExcludedIds(data)\n\t\t\t})\n\t\t}\n\n\t\tconst postId = select(\"core/editor\").getCurrentPostId()\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/sees/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiSees(data)\n\t\t\t})\n\t\t}, [postId])\n\n\t\t/*\n\n\n\t\t\t\t\t\t\t*/\n\n\t\tconst createRelatedList = (data) => {\n\t\t\treturn data.map((row) => {\n\t\t\t\treturn (\n\t\t\t\t\t
  • \n\t\t\t\t\t\t{row.title}{\" \"}\n\t\t\t\t\t\t\n\t\t\t\t\t
  • \n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listrelated/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiRelated(createRelatedList(data))\n\t\t\t})\n\t\t}, [postId, relevanssiExcludedIds])\n\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listexcluded/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tconst list = data.map((row) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t
  • \n\t\t\t\t\t\t\t{row.title}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
  • \n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t\tsetRelevanssiExcluded(list)\n\t\t\t})\n\t\t}, [postId, relevanssiExcludedIds])\n\n\t\tconst createTermsList = (data) => {\n\t\t\treturn data.map((row) => {\n\t\t\t\treturn (\n\t\t\t\t\t
  • \n\t\t\t\t\t\t{row.query} ({row.count})\n\t\t\t\t\t
  • \n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listinsightscommon/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiCommonTerms(createTermsList(data))\n\t\t\t})\n\t\t}, [postId])\n\t\tuseEffect(() => {\n\t\t\twp.apiFetch({\n\t\t\t\tpath: `/relevanssi/v1/listinsightslowranking/${postId}`,\n\t\t\t}).then((data) => {\n\t\t\t\tsetRelevanssiLowRankingTerms(createTermsList(data))\n\t\t\t})\n\t\t}, [postId])\n\n\t\treturn (\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tRelevanssi Premium\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{relevanssiSees.title && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Title:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.title}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.content && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Content:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.content}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.author && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Author:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.author}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.category && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Categories:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.category}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.tag && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Tags:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.tag}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.taxonomy && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Other taxonomies:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.taxonomy}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.comment && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Comments:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.comment}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.customfield && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Custom fields:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.customfield}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.excerpt && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Excerpt:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.excerpt}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.link && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Links to this post:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.link}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.mysql && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"MySQL columns:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.mysql}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{relevanssiSees.reason && (\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{__(\"Reason this post is not indexed:\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t\t{relevanssiSees.reason}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"If any of these keywords are present in the search query, this post will be moved on top of the search results.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"You can add weights to pinned keywords like this: 'keyword (100)'. The post with the highest weight will be sorted first if there are multiple posts pinned to the same keyword.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"If any of these keywords are present in the search query, this post will be removed from the search results.\", \"relevanssi\" )}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t\t{__(\"Anything entered here will used when searching for related posts. Using phrases with quotes is allowed, but will restrict the related posts to posts including that phrase.\", \"relevanssi\")}\n\t\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t

    {__(\"Related posts for this post:\", \"relevanssi\")}

    \n\t\t\t\t\t\t\t
      {relevanssiRelated}
    \n\n\t\t\t\t\t\t\t

    {__(\"Excluded posts for this post:\", \"relevanssi\")}

    \n\t\t\t\t\t\t\t
      {relevanssiExcluded}
    \n\t\t\t\t\t\t\n\t\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t{__(\n\t\t\t\t\t\t\t\t\t\"The most common search terms used to find this post:\",\n\t\t\t\t\t\t\t\t\t\"relevanssi\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
      {relevanssiCommonTerms}
    \n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t\t{__(\n\t\t\t\t\t\t\t\t\t\"Low-ranking search terms used to find this post:\",\n\t\t\t\t\t\t\t\t\t\"relevanssi\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t

    \n\t\t\t\t\t\t\t
      {relevanssiLowRankingTerms}
    \n\t\t\t\t\t\t
    \n\t\t\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t)\n\t},\n})\n","(function() { module.exports = window[\"wp\"][\"components\"]; }());","(function() { module.exports = window[\"wp\"][\"compose\"]; }());","(function() { module.exports = window[\"wp\"][\"data\"]; }());","(function() { module.exports = window[\"wp\"][\"editPost\"]; }());","(function() { module.exports = window[\"wp\"][\"element\"]; }());","(function() { module.exports = window[\"wp\"][\"i18n\"]; }());","(function() { module.exports = window[\"wp\"][\"plugins\"]; }());"],"sourceRoot":""} \ No newline at end of file diff --git a/relevanssi-premium/premium/indexing.php b/relevanssi-premium/premium/indexing.php deleted file mode 100644 index e537ead6..00000000 --- a/relevanssi-premium/premium/indexing.php +++ /dev/null @@ -1,1833 +0,0 @@ -ID ); - } - } -} - -/** - * Indexes taxonomy terms when term is updated. - * - * @param string $term The term. - * @param int $taxonomy_term_id The term taxonomy ID (not used here). - * @param string $taxonomy The taxonomy. - */ -function relevanssi_edit_term( $term, $taxonomy_term_id, $taxonomy ) { - $update = true; - relevanssi_do_term_indexing( $term, $taxonomy, $update ); -} - -/** - * Indexes taxonomy terms when term is added. - * - * @param string $term The term. - * @param int $taxonomy_term_id The term taxonomy ID (not used here). - * @param string $taxonomy The taxonomy. - */ -function relevanssi_add_term( $term, $taxonomy_term_id, $taxonomy ) { - $update = false; - relevanssi_do_term_indexing( $term, $taxonomy, $update ); -} - -/** - * Indexes taxonomy term, if taxonomy term indexing is enabled. - * - * @param string $term The term. - * @param string $taxonomy The taxonomy. - * @param boolean $update If true, term is updated; if false, it is added. - */ -function relevanssi_do_term_indexing( $term, $taxonomy, $update ) { - if ( 'on' === get_option( 'relevanssi_index_taxonomies' ) ) { - $taxonomies = get_option( 'relevanssi_index_terms' ); - if ( in_array( $taxonomy, $taxonomies, true ) ) { - relevanssi_index_taxonomy_term( $term, $taxonomy, $update ); - } - } -} - -/** - * Deletes an user from Relevanssi index. - * - * Deletes an user from the Relevanssi index. Attached to the 'delete_user' action. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param int $user User ID to delete. - */ -function relevanssi_delete_user( int $user ) { - global $wpdb, $relevanssi_variables; - $user = intval( $user ); - $wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE item = $user AND type = 'user'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -} - -/** - * Deletes a taxonomy term from Relevanssi index. - * - * Deletes a taxonomy term from the Relevanssi index. Attached to the 'delete_term' action. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param int $term Term ID to remove. - * @param int $term_taxonomy_id Term taxonomy ID (not used). - * @param string $taxonomy The taxonomy. - */ -function relevanssi_delete_taxonomy_term( $term, $term_taxonomy_id, $taxonomy ) { - global $wpdb, $relevanssi_variables; - $wpdb->query( - $wpdb->prepare( - 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE item = %d AND type = %s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $term, - $taxonomy - ) - ); -} - -/** - * Generates the custom field detail field for indexing. - * - * Premium stores more detail about custom field indexing. This function - * generates the custom field detail. - * - * @param array $insert_data Data used to generate the INSERT queries. - * @param string $token The indexed token. - * @param int $count The number of matches. - * @param string $field Name of the custom field. - * - * @return array $insert_data New source data for the INSERT queries added. - */ -function relevanssi_customfield_detail( $insert_data, $token, $count, $field ) { - if ( isset( $insert_data[ $token ]['customfield_detail'] ) ) { - // Custom field detail for this token already exists. - $custom_field_detail = json_decode( $insert_data[ $token ]['customfield_detail'], true ); - } else { - // Nothing yet, create new. - $custom_field_detail = array(); - } - - relevanssi_increase_value( $custom_field_detail[ $field ], $count ); - - $insert_data[ $token ]['customfield_detail'] = wp_json_encode( $custom_field_detail ); - return $insert_data; -} - -/** - * Indexes custom MySQL column content. - * - * Generates the INSERT query base data for MySQL column content. - * - * @global $wpdb The WordPress database interface. - * - * @param array $insert_data Data used to generate the INSERT queries. - * @param string $post_id Post ID. - * - * @return array $insert_data New source data for the INSERT queries added. - */ -function relevanssi_index_mysql_columns( $insert_data, $post_id ) { - $custom_columns = get_option( 'relevanssi_mysql_columns' ); - if ( ! empty( $custom_columns ) ) { - global $wpdb; - - // Get a list of possible column names. - $column_list = wp_cache_get( 'relevanssi_column_list' ); - if ( false === $column_list ) { - $column_list = $wpdb->get_results( "SHOW COLUMNS FROM $wpdb->posts" ); - wp_cache_set( 'relevanssi_column_list', $column_list ); - } - $valid_columns = array(); - foreach ( $column_list as $column ) { - array_push( $valid_columns, $column->Field ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - } - - // This is to remove problems where the list ends in a comma. - $custom_column_array = explode( ',', $custom_columns ); - $custom_column_list_array = array(); - foreach ( $custom_column_array as $column ) { - $column = trim( $column ); - if ( in_array( $column, $valid_columns, true ) ) { - $custom_column_list_array[] = $column; - } - } - $custom_column_list = implode( ', ', $custom_column_list_array ); - - $custom_column_data = $wpdb->get_row( "SELECT $custom_column_list FROM $wpdb->posts WHERE ID=$post_id", ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $remove_stopwords = true; - $minimum_word_length = get_option( 'relevanssi_min_word_length', 3 ); - if ( is_array( $custom_column_data ) ) { - foreach ( $custom_column_data as $column => $data ) { - /** This filter is documented in common/indexing.php */ - $data = apply_filters( - 'relevanssi_indexing_tokens', - relevanssi_tokenize( $data, $remove_stopwords, $minimum_word_length, 'indexing' ), - 'mysql-content' - ); - if ( count( $data ) > 0 ) { - foreach ( $data as $term => $count ) { - if ( isset( $insert_data[ $term ]['mysqlcolumn'] ) ) { - $insert_data[ $term ]['mysqlcolumn'] += $count; - } else { - $insert_data[ $term ]['mysqlcolumn'] = $count; - } - $insert_data = relevanssi_mysqlcolumn_detail( $insert_data, $term, $count, $column ); - } - } - } - } - } - return $insert_data; -} - -/** - * Generates the MySQL column detail field for indexing. - * - * This function generates the MySQL column detail. - * - * @param array $insert_data Data used to generate the INSERT queries. - * @param string $token The indexed token. - * @param int $count The number of matches. - * @param string $column Name of the column. - * - * @return array $insert_data New source data for the INSERT queries added. - */ -function relevanssi_mysqlcolumn_detail( $insert_data, $token, $count, $column ) { - if ( isset( $insert_data[ $token ]['mysqlcolumn_detail'] ) ) { - // Custom field detail for this token already exists. - $mysqlcolumn_detail = json_decode( $insert_data[ $token ]['mysqlcolumn_detail'], true ); - } else { - // Nothing yet, create new. - $mysqlcolumn_detail = array(); - } - - relevanssi_increase_value( $mysqlcolumn_detail[ $column ], $count ); - - $insert_data[ $token ]['mysqlcolumn_detail'] = wp_json_encode( $mysqlcolumn_detail ); - - return $insert_data; -} - -/** - * Processes internal links. - * - * Process the internal links the way user wants: no indexing, indexing, or stripping. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param string $contents Post content. - * @param int $post_id Post ID. - * - * @return string $contents Contents, modified. - */ -function relevanssi_process_internal_links( $contents, $post_id ) { - $internal_links_behaviour = get_option( 'relevanssi_internal_links', 'noindex' ); - - if ( 'noindex' !== $internal_links_behaviour ) { - global $relevanssi_variables, $wpdb; - $min_word_length = get_option( 'relevanssi_min_word_length', 3 ); - - // Index internal links. - $internal_links = relevanssi_get_internal_links( $contents ); - - if ( ! empty( $internal_links ) ) { - foreach ( $internal_links as $link => $text ) { - $link_id = url_to_postid( $link ); - if ( ! empty( $link_id ) ) { - /** This filter is documented in common/indexing.php */ - $link_words = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $text, true, $min_word_length, 'indexing' ), 'internal-links' ); - if ( count( $link_words ) > 0 ) { - foreach ( $link_words as $word => $count ) { - $wpdb->query( - $wpdb->prepare( - 'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . ' (doc, term, term_reverse, link, item) VALUES (%d, %s, REVERSE(%s), %d, %d)', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $link_id, - $word, - $word, - $count, - $post_id - ) - ); - } - } - } - } - - if ( 'strip' === $internal_links_behaviour ) { - $contents = relevanssi_strip_internal_links( $contents ); - } - } - } - - return $contents; -} - -/** - * Finds internal links. - * - * A function to find all internal links in the parameter text. - * - * @param string $text Text where the links are extracted from. - * - * @return array $links All links in the post, or false if fails. - */ -function relevanssi_get_internal_links( $text ) { - $links = array(); - if ( preg_match_all( '@]*?href="(' . home_url() . '[^"]*?)"[^>]*?>(.*?)@siu', $text, $m ) ) { - foreach ( $m[1] as $i => $link ) { - if ( ! isset( $links[ $link ] ) ) { - $links[ $link ] = ''; - } - $links[ $link ] .= ' ' . $m[2][ $i ]; - } - } - if ( preg_match_all( '@]*?href="(/[^"]*?)"[^>]*?>(.*?)@siu', $text, $m ) ) { - foreach ( $m[1] as $i => $link ) { - if ( ! isset( $links[ $link ] ) ) { - $links[ $link ] = ''; - } - $links[ $link ] .= ' ' . $m[2][ $i ]; - } - } - if ( count( $links ) > 0 ) { - return $links; - } - return false; -} - -/** - * Strips internal links. - * - * A function to strip all internal links from the parameter text. - * - * @param string $text Text where the links are extracted from. - * - * @return array $links The text without the links. - */ -function relevanssi_strip_internal_links( $text ) { - $text = preg_replace( - array( - '@]*?href="' . home_url() . '[^>]*?>.*?@siu', - ), - ' ', - $text - ); - $text = preg_replace( - array( - '@]*?href="/[^>]*?>.*?@siu', - ), - ' ', - $text - ); - return $text; -} - -/** - * Applies the thousands separator rule to text. - * - * Finds numbers separated by the chosen thousand separator and combine them. - * - * @param string $str The string to fix. - * - * @return string $str The fixed string. - */ -function relevanssi_apply_thousands_separator( $str ) { - $thousands_separator = get_option( 'relevanssi_thousand_separator', '' ); - if ( ! empty( $thousands_separator ) ) { - $pattern = '/(\d+)' . preg_quote( $thousands_separator, '/' ) . '(\d+)/u'; - $str = preg_replace( $pattern, '$1$2', $str ); - } - return $str; -} - -/** - * Adds a stemmer-enabling filter. - * - * This filter introduces a new filter hook that runs the stemmers. - * - * @param string $str The string that is stemmed. - * - * @return string $str The string after stemming. - */ -function relevanssi_enable_stemmer( $str ) { - add_filter( 'pre_option_relevanssi_implicit_operator', 'relevanssi_return_or' ); - /** - * Applies stemmer to document content and search terms. - * - * @param string $str The string that is stemmed. - * - * @return string $str The string after stemming. - */ - $str = apply_filters( 'relevanssi_stemmer', $str ); - remove_filter( 'pre_option_relevanssi_implicit_operator', 'relevanssi_return_or' ); - return $str; -} - -/** - * Does simple English stemming. - * - * A simple suffix stripper that can be used to stem English texts. - * - * @param string $term Search term to stem. - * - * @return string $term The stemmed term. - */ -function relevanssi_simple_english_stemmer( $term ) { - $len = strlen( $term ); - - $end1 = substr( $term, -1, 1 ); - if ( 's' === $end1 && $len > 3 ) { - $term = substr( $term, 0, -1 ); - --$len; - } - $end = substr( $term, -3, 3 ); - - if ( 'ing' === $end && $len > 5 ) { - return substr( $term, 0, -3 ); - } - if ( 'est' === $end && $len > 5 ) { - return substr( $term, 0, -3 ); - } - - $end = substr( $end, 1 ); - if ( 'es' === $end && $len > 3 ) { - return substr( $term, 0, -2 ); - } - if ( 'ie' === $end && $len > 3 ) { - return substr( $term, 0, -1 ); - } - if ( 'ed' === $end && $len > 3 ) { - return substr( $term, 0, -2 ); - } - if ( 'en' === $end && $len > 3 ) { - return substr( $term, 0, -2 ); - } - if ( 'er' === $end && $len > 3 ) { - return substr( $term, 0, -2 ); - } - if ( 'ly' === $end && $len > 4 ) { - return substr( $term, 0, -2 ); - } - - $end = substr( $end, -1 ); - if ( 'y' === $end && $len > 3 ) { - return substr( $term, 0, -1 ) . 'i'; - } - - return $term; -} - -/** - * Creates the synonym replacement array. - * - * A helper function that generates a synonym replacement array. The array - * is then stored in a global variable, so that it only needs to generated - * once per running the script. - * - * @global $relevanssi_variables The global Relevanssi variables, used to - * store the synonym database. - */ -function relevanssi_create_synonym_replacement_array() { - global $relevanssi_variables; - - $synonym_data = get_option( 'relevanssi_synonyms' ); - $current_language = relevanssi_get_current_language(); - $synonyms = array(); - - if ( isset( $synonym_data[ $current_language ] ) ) { - $synonym_data = relevanssi_strtolower( $synonym_data[ $current_language ] ); - $pairs = explode( ';', $synonym_data ); - - foreach ( $pairs as $pair ) { - if ( empty( $pair ) ) { - continue; - } - $parts = explode( '=', $pair ); - $key = strval( trim( $parts[0] ) ); - $value = trim( $parts[1] ); - if ( ! isset( $synonyms[ $value ] ) ) { - $synonyms[ $value ] = "$value $key"; - } else { - $synonyms[ $value ] .= " $key"; - } - } - } - $relevanssi_variables['synonyms'] = $synonyms; -} - -/** - * Adds synonyms to post content and titles for indexing. - * - * In order to use synonyms in AND searches, the synonyms must be indexed within the posts. - * This function adds synonyms for post content and titles when indexing posts. - * - * @global $relevanssi_variables The global Relevanssi variables, used for the synonym database. - * - * @param array $tokens An array of tokens and their frequencies. - * - * @return array An array of filtered token-frequency pairs. - */ -function relevanssi_add_indexing_synonyms( $tokens ) { - global $relevanssi_variables; - - if ( ! isset( $relevanssi_variables['synonyms'] ) ) { - relevanssi_create_synonym_replacement_array(); - } - - $new_tokens = array(); - $synonyms = $relevanssi_variables['synonyms']; - - foreach ( $tokens as $token => $tf ) { - if ( isset( $synonyms[ $token ] ) ) { - $token_and_the_synonyms = explode( ' ', $synonyms[ $token ] ); - foreach ( $token_and_the_synonyms as $new_token ) { - $new_tokens[ $new_token ] = $tf; - } - } else { - $new_tokens[ $token ] = $tf; - } - } - - return $new_tokens; -} - -/** - * Adds synonyms to a content. - * - * @global $relevanssi_variables The global Relevanssi variables, used for the synonym database. - * - * @param string $content The content to add synonyms to. - * - * @return string $content The content with synonyms. - */ -function relevanssi_prepare_indexing_content( $content ) { - global $relevanssi_variables; - - if ( ! isset( $relevanssi_variables['synonyms'] ) ) { - relevanssi_create_synonym_replacement_array(); - } - - $synonyms = $relevanssi_variables['synonyms']; - $content = relevanssi_strtolower( $content ); - $content = preg_split( '/[\s,.()!?]/', $content ); - $ret = array(); - $len = count( $content ); - for ( $i = 0; $i < $len; ++$i ) { - $val = $content[ $i ]; - if ( 0 === strlen( $val ) ) { - continue; - } - - if ( isset( $synonyms[ $val ] ) ) { - $ret[] = $synonyms[ $val ]; - } else { - $ret[] = $val; - } - } - - return implode( ' ', $ret ); -} - - -/** - * Adds ACF repeater fields to the list of custom fields. - * - * Goes through custom fields, finds fields that match the fieldname_%_subfieldname - * pattern, finds the number of fields from the fieldname custom field and then - * adds the fieldname_0_subfieldname... fields to the list of custom fields. Only - * works one level deep. - * - * @param array $custom_fields The list of custom fields, used as a reference. - * @param int $post_id The post ID of the current post. - */ -function relevanssi_add_repeater_fields( &$custom_fields, $post_id ) { - global $wpdb; - - /** - * Filters the list of custom fields to index before the repeater fields - * are expanded. If you want to add repeater fields using the - * field_%_subfield notation from code, you can use this filter hook. - * - * @param array $custom_fields The list of custom fields. This array - * includes all custom fields that are to be indexed, so make sure you add - * new fields here and don't remove anything you want included in the index. - */ - $custom_fields = apply_filters( 'relevanssi_custom_fields_before_repeaters', $custom_fields ); - $repeater_fields = array(); - foreach ( $custom_fields as $field ) { - $number_of_levels = substr_count( $field, '%' ); - if ( $number_of_levels > 0 ) { - $field = str_replace( '\%', '%', $wpdb->esc_like( $field ) ); - $fields = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM $wpdb->postmeta WHERE meta_key LIKE %s AND post_id = %d", $field, $post_id ) ); - - $repeater_fields = array_merge( $repeater_fields, $fields ); - } else { - continue; - } - } - - $custom_fields = array_merge( $custom_fields, $repeater_fields ); -} - -/** - * Adds the PDF data from child posts to parent posts. - * - * Takes the PDF content data from child posts for indexing purposes. - * - * @global $wpdb The WordPress database interface. - * - * @param array $insert_data The base data for INSERT queries. - * @param int $post_id The post ID. - * - * @return array $insert_data The INSERT data with new content added. - */ -function relevanssi_index_pdf_for_parent( $insert_data, $post_id ) { - $option = get_option( 'relevanssi_index_pdf_parent', '' ); - if ( empty( $option ) || 'off' === $option ) { - return $insert_data; - } - - global $wpdb; - - $post_id = intval( $post_id ); - $query = "SELECT meta_value FROM $wpdb->postmeta AS pm, $wpdb->posts AS p WHERE pm.post_id = p.ID AND p.post_parent = $post_id AND meta_key = '_relevanssi_pdf_content'"; - /** - * Filters the database query that fetches the PDF content for the parent post. - * - * @param string $query The MySQL query. - * @param int $post_id The parent post ID. - */ - $query = apply_filters( 'relevanssi_pdf_for_parent_query', $query, $post_id ); - $pdf_content = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - if ( is_array( $pdf_content ) ) { - /** - * Filters the custom field value before indexing. - * - * @param array Custom field values. - * @param string $field The custom field name. - * @param int $post_id The post ID. - */ - $pdf_content = apply_filters( 'relevanssi_custom_field_value', $pdf_content, '_relevanssi_pdf_content', $post_id ); - foreach ( $pdf_content as $row ) { - /** This filter is documented in common/indexing.php */ - $data = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $row, true, get_option( 'relevanssi_min_word_length', 3 ), 'indexing' ), 'pdf-content' ); - if ( count( $data ) > 0 ) { - foreach ( $data as $term => $count ) { - if ( isset( $insert_data[ $term ]['customfield'] ) ) { - $insert_data[ $term ]['customfield'] += $count; - } else { - $insert_data[ $term ]['customfield'] = $count; - } - $insert_data = relevanssi_customfield_detail( $insert_data, $term, $count, '_relevanssi_pdf_content' ); - } - } - } - } - - /** - * Filters the index data for the PDF contents. - * - * @param array $insert_data The data for INSERT clauses, format is - * $insert_data[ term ][ column ] = frequency. - * @param int $post_id The parent post ID. - */ - return apply_filters( 'relevanssi_pdf_for_parent_insert_data', $insert_data, $post_id ); -} - -/** - * Indexes all users. - * - * Runs indexing on all users. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - */ -function relevanssi_index_users() { - global $wpdb, $relevanssi_variables; - - // Delete all users from the Relevanssi index first. - $wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE type = 'user'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - $users = relevanssi_get_users( array() ); - - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress = WP_CLI\Utils\make_progress_bar( 'Indexing users', count( $users ) ); - } - - $update = false; - foreach ( $users as $user ) { - /** - * Checks if the user can be indexed. - * - * @param boolean $index Should the user be indexed, default true. - * @param object $user The user object. - * - * @return boolean $index If false, do not index the user. - */ - $index_this_user = apply_filters( 'relevanssi_user_index_ok', true, $user ); - - if ( $index_this_user ) { - relevanssi_index_user( $user, $update ); - } - - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->tick(); - } - } - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->finish(); - } -} - -/** - * Indexes users in AJAX context. - * - * Runs indexing on all users in AJAX context. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param int $limit Number of users to index on one go. - * @param int $offset Indexing offset. - * - * @return array $response AJAX response, number of users indexed in the $response['indexed']. - */ -function relevanssi_index_users_ajax( $limit, $offset ) { - $args = array( - 'number' => intval( $limit ), - 'offset' => intval( $offset ), - ); - - $users = relevanssi_get_users( $args ); - - $indexed_users = 0; - $update = false; - foreach ( $users as $user ) { - /** - * Checks if the user can be indexed. - * - * @param boolean $index Should the user be indexed, default true. - * @param object $user The user object. - * - * @return boolean $index If false, do not index the user. - */ - $index_this_user = apply_filters( 'relevanssi_user_index_ok', true, $user ); - if ( $index_this_user ) { - relevanssi_index_user( $user, $update ); - ++$indexed_users; - } - } - - $response = array( - 'indexed' => $indexed_users, - ); - - return $response; -} - -/** - * Gets the list of users. - * - * @param array $args The user indexing arguments. - * - * @return array An array of user profiles. - */ -function relevanssi_get_users( array $args ) { - $index_subscribers = get_option( 'relevanssi_index_subscribers' ); - if ( 'on' !== $index_subscribers ) { - $args['role__not_in'] = array( 'subscriber' ); - } - - /** - * Filters the user fetching arguments. - * - * Useful to control the user role, for example: just set 'role__in' to whatever - * you need. - * - * @param array User fetching arguments. - */ - $users_list = get_users( apply_filters( 'relevanssi_user_indexing_args', $args ) ); - $users = array(); - foreach ( $users_list as $user ) { - $users[] = get_userdata( $user->ID ); - } - - return $users; -} - -/** - * Indexes one user. - * - * Indexes one user profile. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param object|int $user The user object or user ID. - * @param boolean $remove_first Should the user be deleted first or not, default false. - */ -function relevanssi_index_user( $user, $remove_first = false ) { - global $wpdb, $relevanssi_variables; - - if ( is_numeric( $user ) ) { - // Not an object, make it an object. - $user = get_userdata( $user ); - if ( false === $user ) { - // Invalid user ID given, no user found. Exit. - return; - } - } - - if ( $remove_first ) { - relevanssi_delete_user( $user->ID ); - } - - /** - * Allows manipulating the user object before indexing. - * - * This filter can be used to manipulate the user object before it is - * processed for indexing. It's possible to add extra data (for example to - * user description field) or to change the existing data. - * - * @param object $user The user object. - */ - $user = apply_filters( 'relevanssi_user_add_data', $user ); - - $insert_data = array(); - $min_length = get_option( 'relevanssi_min_word_length', 3 ); - $remove_stopwords = true; - - $values = relevanssi_get_user_field_content( $user->ID ); - foreach ( $values as $field => $value ) { - /** This filter is documented in common/indexing.php */ - $tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, $remove_stopwords, $min_length, 'indexing' ), 'user-fields' ); - foreach ( $tokens as $term => $tf ) { - if ( isset( $insert_data[ $term ]['customfield'] ) ) { - $insert_data[ $term ]['customfield'] += $tf; - } else { - $insert_data[ $term ]['customfield'] = $tf; - } - $insert_data = relevanssi_customfield_detail( $insert_data, $term, $tf, $field ); - } - } - - if ( isset( $user->description ) && '' !== $user->description ) { - /** This filter is documented in common/indexing.php */ - $tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $user->description, $remove_stopwords, $min_length, 'indexing' ), 'user-description' ); - foreach ( $tokens as $term => $tf ) { - if ( isset( $insert_data[ $term ]['content'] ) ) { - $insert_data[ $term ]['content'] += $tf; - } else { - $insert_data[ $term ]['content'] = $tf; - } - } - } - - if ( isset( $user->first_name ) && '' !== $user->first_name ) { - $parts = explode( ' ', strtolower( $user->first_name ) ); - foreach ( $parts as $part ) { - if ( empty( $part ) ) { - continue; - } - if ( isset( $insert_data[ $part ]['title'] ) ) { - ++$insert_data[ $part ]['title']; - } else { - $insert_data[ $part ]['title'] = 1; - } - } - } - - if ( isset( $user->last_name ) && ' ' !== $user->last_name ) { - $parts = explode( ' ', strtolower( $user->last_name ) ); - foreach ( $parts as $part ) { - if ( empty( $part ) ) { - continue; - } - if ( isset( $insert_data[ $part ]['title'] ) ) { - ++$insert_data[ $part ]['title']; - } else { - $insert_data[ $part ]['title'] = 1; - } - } - } - - if ( isset( $user->display_name ) && ' ' !== $user->display_name ) { - $parts = explode( ' ', strtolower( $user->display_name ) ); - foreach ( $parts as $part ) { - if ( empty( $part ) ) { - continue; - } - if ( isset( $insert_data[ $part ]['title'] ) ) { - ++$insert_data[ $part ]['title']; - } else { - $insert_data[ $part ]['title'] = 1; - } - } - } - - /** - * Allows the user insert data to be manipulated. - * - * This function manipulates the user insert data used to create the INSERT queries. - * - * @param array $insert_data The source data for the INSERT queries. - * @param object $user The user object. - */ - $insert_data = apply_filters( 'relevanssi_user_data_to_index', $insert_data, $user ); - - foreach ( $insert_data as $term => $data ) { - $fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield', 'customfield_detail' ); - foreach ( $fields as $field ) { - if ( ! isset( $data[ $field ] ) ) { - $data[ $field ] = 0; - } - } - - $content = $data['content']; - $title = $data['title']; - $comment = $data['comment']; - $tag = $data['tag']; - $link = $data['link']; - $author = $data['author']; - $category = $data['category']; - $excerpt = $data['excerpt']; - $taxonomy = $data['taxonomy']; - $customfield = $data['customfield']; - $cf_detail = $data['customfield_detail']; - - $wpdb->query( - $wpdb->prepare( - 'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - ' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail) - VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)', - $user->ID, - -1, - $term, - $term, - $content, - $title, - $comment, - $tag, - $link, - $author, - $category, - $excerpt, - $taxonomy, - $customfield, - 'user', - $cf_detail, - '', - '' - ) - ); - } -} - -/** - * Counts users. - * - * Figures out how many users there are to index. - * - * @global $wpdb The WordPress database interface. - * - * @return int $count_users Number of users, -1 if user indexing is disabled. - */ -function relevanssi_count_users() { - $index_users = get_option( 'relevanssi_index_users' ); - if ( empty( $index_users ) || 'off' === $index_users ) { - return -1; - } - - $args = array( - 'fields' => 'ID', - ); - - $index_subscribers = get_option( 'relevanssi_index_subscribers' ); - if ( 'on' !== $index_subscribers ) { - $args['role__not_in'] = array( 'subscriber' ); - } - - $users = get_users( - /** - * Documented in /premium/indexing.php. - */ - apply_filters( 'relevanssi_user_indexing_args', $args ) - ); - $count_users = count( $users ); - - return $count_users; -} - -/** - * Counts taxonomy terms. - * - * Figures out how many taxonomy terms there are to index. - * - * @global $wpdb The WordPress database interface. - * - * @return int $count_terms Number of taxonomy terms, -1 if taxonomy term indexing is disabled. - */ -function relevanssi_count_taxonomy_terms() { - $index_taxonomies = get_option( 'relevanssi_index_taxonomies' ); - if ( empty( $index_taxonomies ) || 'off' === $index_taxonomies ) { - return -1; - } - - global $wpdb; - - $taxonomies = get_option( 'relevanssi_index_terms' ); - if ( empty( $taxonomies ) ) { - // No taxonomies chosen for indexing. - return -1; - } - $count_terms = 0; - foreach ( $taxonomies as $taxonomy ) { - if ( ! taxonomy_exists( $taxonomy ) ) { - // Non-existing taxonomy. Shouldn't be possible, but better be sure. - continue; - } - - /** - * Determines whether empty terms are indexed or not. - * - * @param boolean $hide_empty_terms If true, empty terms are not indexed. Default true. - */ - $hide_empty = apply_filters( 'relevanssi_hide_empty_terms', true ); - - $count = ''; - if ( $hide_empty ) { - $count = 'AND tt.count > 0'; - } - - $terms = $wpdb->get_col( "SELECT t.term_id FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt WHERE t.term_id = tt.term_id $count AND tt.taxonomy = '$taxonomy'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - $count_terms += count( $terms ); - } - return $count_terms; -} - -/** - * Returns the list of taxonomies chosen for indexing. - * - * Returns the list of taxonomies chosen for indexing from the 'relevanssi_index_terms' option. - * - * @return array $taxonomies A list of taxonomies chosen to be indexed. - */ -function relevanssi_list_taxonomies() { - return get_option( 'relevanssi_index_terms' ); -} - -/** - * Indexes taxonomy terms in AJAX context. - * - * Runs indexing on taxonomy terms in one taxonomy in AJAX context. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param string $taxonomy The taxonomy to index. - * @param int $limit Number of users to index on one go. - * @param int $offset Indexing offset. - * - * @return array $response AJAX response, number of taxonomy terms indexed in the - * $response['indexed'] and a boolean value in $response['taxonomy_completed'] that - * tells whether the taxonomy is indexed completely or not. - */ -function relevanssi_index_taxonomies_ajax( $taxonomy, $limit, $offset ) { - global $wpdb; - - $indexed_terms = 0; - $end_reached = false; - - $terms = relevanssi_get_terms( $taxonomy, intval( $limit ), intval( $offset ) ); - - if ( count( $terms ) < $limit ) { - $end_reached = true; - } - - do_action( 'relevanssi_pre_index_taxonomies' ); - - foreach ( $terms as $term_id ) { - $update = false; - $term = get_term( $term_id, $taxonomy ); - relevanssi_index_taxonomy_term( $term, $taxonomy, $update ); - ++$indexed_terms; - } - - do_action( 'relevanssi_post_index_taxonomies' ); - - $response = array( - 'indexed' => $indexed_terms, - 'taxonomy_completed' => 'not', - ); - if ( $end_reached ) { - $response['taxonomy_completed'] = 'done'; - } - - return $response; -} - -/** - * Indexes all taxonomies. - * - * Runs indexing on all taxonomies. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param boolean $is_ajax Whether indexing is done in the AJAX context, default false. - * - * @return array $response If $is_ajax is true, the function returns indexing status in an array. - */ -function relevanssi_index_taxonomies( $is_ajax = false ) { - global $wpdb, $relevanssi_variables; - - $wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE doc = -1 AND type NOT IN ('user', 'post_type')" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - do_action( 'relevanssi_pre_index_taxonomies' ); - - $taxonomies = get_option( 'relevanssi_index_terms' ); - $indexed_terms = 0; - foreach ( $taxonomies as $taxonomy ) { - $terms = relevanssi_get_terms( $taxonomy, 0, 0 ); - - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress = WP_CLI\Utils\make_progress_bar( "Indexing $taxonomy", count( $terms ) ); - } - - $update = false; - foreach ( $terms as $term ) { - relevanssi_index_taxonomy_term( $term, $taxonomy, $update ); - ++$indexed_terms; - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->tick(); - } - } - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->finish(); - } - } - - do_action( 'relevanssi_post_index_taxonomies' ); - - if ( $is_ajax ) { - if ( $indexed_terms > 0 ) { - // translators: the number of taxonomy terms. - return sprintf( __( 'Indexed %d taxonomy terms.', 'relevanssi' ), $indexed_terms ); - } else { - return __( 'No taxonomies to index.', 'relevanssi' ); - } - } -} - -/** - * Gets a list of taxonomy terms. - * - * @param string $taxonomy The taxonomy to index. - * @param int $limit Number of users to index on one go. - * @param int $offset Indexing offset. - * - * @return array A list of taxonomy terms. - */ -function relevanssi_get_terms( string $taxonomy, int $limit = 0, int $offset = 0 ): array { - global $wpdb; - - /** - * Determines whether empty terms are indexed or not. - * - * @param boolean $hide_empty_terms If true, empty terms are not indexed. Default true. - */ - $hide_empty = apply_filters( 'relevanssi_hide_empty_terms', true ); - $count = ''; - if ( $hide_empty ) { - $count = 'AND tt.count > 0'; - } - - $limit_sql = ''; - if ( $limit && $offset ) { - $limit_sql = $wpdb->prepare( 'LIMIT %d OFFSET %d', $limit, $offset ); - } - - $terms = $wpdb->get_col( - $wpdb->prepare( - "SELECT t.term_id FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt - WHERE t.term_id = tt.term_id $count AND tt.taxonomy = %s $limit_sql ", // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $taxonomy - ) - ); - - return $terms; -} - -/** - * Indexes one taxonomy term. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param object|int $term The term object or term ID. - * @param string $taxonomy The name of the taxonomy. - * @param boolean $remove_first Should the term be deleted first or not, default false. - * @param boolean $debug If true, print out debug information, default false. - */ -function relevanssi_index_taxonomy_term( $term, $taxonomy, $remove_first = false, $debug = false ) { - global $wpdb, $relevanssi_variables; - - if ( is_numeric( $term ) ) { - // Not an object, so let's get the object. - $term = get_term( $term, $taxonomy ); - } - - /** - * Allows the term object to be handled before indexing. - * - * This filter can be used to add data to term objects before indexing, or to manipulate the object somehow. - * - * @param object $term The term object. - * @param string $taxonomy The taxonomy. - */ - $term = apply_filters( 'relevanssi_term_add_data', $term, $taxonomy ); - - $temp_post = new stdClass(); - $temp_post->post_content = $term->description; - $temp_post->post_title = $term->name; - - /** - * Allows modifying the fake post for the taxonomy term. - * - * In order to index taxonomy terms, Relevanssi generates fake posts from the - * terms. This filter lets you modify the post object. The term description - * is in the post_content and the term name in the post_title. - * - * @param object $temp_post The post object. - * @param object $term The term object. - */ - $temp_post = apply_filters( 'relevanssi_post_to_index', $temp_post, $term ); - - $term->description = $temp_post->post_content; - $term->name = $temp_post->post_title; - - $index_this_post = true; - - /** - * Determines whether a term is indexed or not. - * - * If this filter returns true, this term should not be indexed. - * - * @param boolean $block If true, do not index this post. Default false. - * @param WP_Term $term The term object. - * @param string $taxonomy The term taxonomy. - */ - if ( true === apply_filters( 'relevanssi_do_not_index_term', false, $term, $taxonomy ) ) { - // Filter says no. - if ( $debug ) { - relevanssi_debug_echo( 'relevanssi_do_not_index_term returned true.' ); - } - $index_this_post = false; - } - - if ( $remove_first ) { - // The 0 doesn't mean anything, but because of WP hook parameters, it needs to be there - // so the taxonomy can be passed as the third parameter. - relevanssi_delete_taxonomy_term( $term->term_id, 0, $taxonomy ); - } - - // This needs to be here, after the call to relevanssi_delete_taxonomy_term(), because otherwise - // a post that's in the index but shouldn't be there won't get removed. - if ( ! $index_this_post ) { - return 'donotindex'; - } - - $insert_data = array(); - $remove_stopwords = true; - - $min_length = get_option( 'relevanssi_min_word_length', 3 ); - if ( ! isset( $term->description ) ) { - $term->description = ''; - } - /** - * Allows adding extra content to the term before indexing. - * - * The term description is passed through this filter, so if you want to add - * extra content to the description, you can use this filter. - * - * @param string $term->description The term description. - * @param object $term The term object. - */ - $description = apply_filters( 'relevanssi_tax_term_additional_content', $term->description, $term ); - if ( ! empty( $description ) ) { - /** This filter is documented in common/indexing.php */ - $tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $description, $remove_stopwords, $min_length, 'indexing' ), 'term-description' ); - foreach ( $tokens as $t_term => $tf ) { - if ( ! isset( $insert_data[ $t_term ]['content'] ) ) { - $insert_data[ $t_term ]['content'] = 0; - } - $insert_data[ $t_term ]['content'] += $tf; - } - } - - if ( isset( $term->name ) && ! empty( $term->name ) ) { - /** This filter is documented in common/indexing.php */ - $tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $term->name, $remove_stopwords, $min_length, 'indexing' ), 'term-name' ); - foreach ( $tokens as $t_term => $tf ) { - if ( ! isset( $insert_data[ $t_term ]['title'] ) ) { - $insert_data[ $t_term ]['title'] = 0; - } - $insert_data[ $t_term ]['title'] += $tf; - } - } - - foreach ( $insert_data as $t_term => $data ) { - $fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield' ); - foreach ( $fields as $field ) { - if ( ! isset( $data[ $field ] ) ) { - $data[ $field ] = 0; - } - } - - $content = $data['content']; - $title = $data['title']; - $comment = $data['comment']; - $tag = $data['tag']; - $link = $data['link']; - $author = $data['author']; - $category = $data['category']; - $excerpt = $data['excerpt']; - $customfield = $data['customfield']; - $t_term = trim( $t_term ); // Numeric terms start with a space. - - $wpdb->query( - $wpdb->prepare( - 'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - ' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail) - VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)', - $term->term_id, - -1, - $t_term, - $t_term, - $content, - $title, - $comment, - $tag, - $link, - $author, - $category, - $excerpt, - '', - $customfield, - $taxonomy, - '', - '', - '' - ) - ); - } -} - -/** - * Removes a document from the index. - * - * This Premium version also takes care of internal linking keywords, either keeping them (in case of - * an update) or removing them (if the post is removed). - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param int $post_id The post ID. - * @param boolean $keep_internal_linking If true, do not remove internal link keywords from this post. - */ -function relevanssi_premium_remove_doc( $post_id, $keep_internal_linking ) { - global $wpdb, $relevanssi_variables; - - $post_id = intval( $post_id ); - if ( empty( $post_id ) ) { - // No post ID specified. - return; - } - - $internal_links = ''; - if ( $keep_internal_linking ) { - $internal_links = 'AND link = 0'; - } - - $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE doc=%s $internal_links", $post_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - - if ( ! $keep_internal_linking ) { - $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE link > 0 AND doc=%s', $post_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - } -} - -/** - * Deletes an item (user or taxonomy term) from the index. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the database table names. - * - * @param int $item_id The item ID number. - * @param string $type The item type. - */ -function relevanssi_remove_item( $item_id, $type ) { - global $wpdb, $relevanssi_variables; - - $item_id = intval( $item_id ); - - if ( 0 === $item_id && 'post' === $type ) { - // Security measures. - return; - } - - $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE item = %d AND type = %s', $item_id, $type ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -} - -/** - * Checks if post is hidden. - * - * Used in indexing process to check if post is hidden. Checks the - * '_relevanssi_hide_post' custom field. - * - * @param int $post_id The post ID to check. - * - * @return boolean $hidden Is the post hidden? - */ -function relevanssi_hide_post( $post_id ) { - $hidden = false; - $field_value = get_post_meta( $post_id, '_relevanssi_hide_post', true ); - if ( 'on' === $field_value ) { - $hidden = true; - } - return $hidden; -} - -/** - * Indexes post type archive pages. - * - * Goes through all the post type archive pages and indexes them using - * relevanssi_index_post_type_archive(). - * - * @see relevanssi_index_post_type_archive() - * @since 2.2 - * - * @global object $wpdb The WordPress database object. - */ -function relevanssi_index_post_type_archives() { - if ( 'on' === get_option( 'relevanssi_index_post_type_archives' ) ) { - global $wpdb, $relevanssi_variables; - - // Delete all post types from the Relevanssi index first. - $wpdb->query( - 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - " WHERE type = 'post_type'" - ); - - $post_types = relevanssi_get_indexed_post_type_archives(); - if ( ! empty( $post_types ) ) { - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress = WP_CLI\Utils\make_progress_bar( - 'Indexing post type archives', - count( $post_types ) - ); - } - foreach ( $post_types as $post_type ) { - relevanssi_index_post_type_archive( $post_type ); - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->tick(); - } - } - if ( defined( 'WP_CLI' ) && WP_CLI ) { - $progress->finish(); - } - } elseif ( defined( 'WP_CLI' ) && WP_CLI ) { - WP_CLI::log( 'No post types available for post type archive indexing.' ); - } - } elseif ( defined( 'WP_CLI' ) && WP_CLI ) { - WP_CLI::error( 'Post type archive indexing disabled.' ); - } -} - -/** - * Indexes post type archive pages in AJAX context. - * - * Runs indexing on all post type archives in AJAX context. - * - * @return array $response AJAX response, number of post type archives indexed - * in the$response['indexed']. - */ -function relevanssi_index_post_type_archives_ajax() { - $post_types = relevanssi_get_indexed_post_type_archives(); - - if ( empty( $post_types ) ) { - $response = array( - 'indexed' => 0, - ); - return $response; - } - - $indexed_post_types = 0; - foreach ( $post_types as $post_type ) { - relevanssi_index_post_type_archive( $post_type ); - ++$indexed_post_types; - } - - $response = array( - 'indexed' => $indexed_post_types, - ); - - return $response; -} - -/** - * Assigns numeric IDs for post types. - * - * Relevanssi requires numeric IDs for post types for indexing purposes. This - * function assigns numbers for each post type, in alphabetical order. This is a - * bit of a hack, and fails if new post types are added, but hopefully that - * doesn't happen too often. The assigned numbers are stored in the option - * relevanssi_post_type_ids. - * - * @since 2.2 - * - * @return array The post type ID arrays (by ID and by name). - */ -function relevanssi_assign_post_type_ids() { - $post_types = relevanssi_get_indexed_post_type_archives(); - sort( $post_types ); - - $post_type_ids_by_id = array(); - $post_type_ids_by_name = array(); - - $id = 1; - foreach ( $post_types as $post_type ) { - $post_type_ids_by_id[ $id ] = $post_type; - $post_type_ids_by_name[ $post_type ] = $id; - ++$id; - } - update_option( - 'relevanssi_post_type_ids', - array( - 'by_id' => $post_type_ids_by_id, - 'by_name' => $post_type_ids_by_name, - ) - ); - - return array( - 'by_id' => $post_type_ids_by_id, - 'by_name' => $post_type_ids_by_name, - ); -} - -/** - * Gets the post type ID by post type name. - * - * Fetches the post type ID from the relevanssi_post_type_ids option by the post - * type name. If the option is empty, will populate it with values. If the post - * type can't be found in the list, the function tries to regenerate the list in - * case there's a new post type Relevanssi doesn't know. - * - * @see relevanssi_assign_post_type_ids() - * @see relevanssi_get_post_type_by_id() - * @since 2.2 - * - * @param string $post_type The name of the post type. - * - * @return integer|null The post type ID number or null if not a valid post - * type. - */ -function relevanssi_get_post_type_by_name( $post_type ) { - $post_type_ids = get_option( 'relevanssi_post_type_ids', false ); - if ( empty( $post_type_ids ) ) { - $post_type_ids = relevanssi_assign_post_type_ids(); - } - if ( ! isset( $post_type_ids['by_name'][ $post_type ] ) ) { - $post_type_ids = relevanssi_assign_post_type_ids(); - } - if ( isset( $post_type_ids['by_name'][ $post_type ] ) ) { - return $post_type_ids['by_name'][ $post_type ]; - } else { - return null; - } -} - -/** - * Gets the post type name by post type ID. - * - * Fetches the post type name from the relevanssi_post_type_ids option by the - * post type ID. If the option is empty, will populate it with values. If the - * post type can't be found in the list, the function tries to regenerate the - * list in case there's a new post type Relevanssi doesn't know. - * - * @see relevanssi_assign_post_type_ids() - * @see relevanssi_get_post_type_by_name() - * @since 2.2 - * - * @param integer $id The ID number of the post type. - * - * @return string|null The post type name or null if not a valid post type. - */ -function relevanssi_get_post_type_by_id( $id ) { - $post_type_ids = get_option( 'relevanssi_post_type_ids', false ); - if ( empty( $post_type_ids ) ) { - $post_type_ids = relevanssi_assign_post_type_ids(); - } - if ( ! isset( $post_type_ids['by_id'][ $id ] ) ) { - $post_type_ids = relevanssi_assign_post_type_ids(); - } - if ( isset( $post_type_ids['by_id'][ $id ] ) ) { - return $post_type_ids['by_id'][ $id ]; - } else { - return null; - } -} - -/** - * Indexes a post type archive page. - * - * Indexes a post type archive page, indexing the archive label and the - * description which can be set when the post type is registered. The filter - * hook relevanssi_post_type_additional_content can be used to add additional - * content to the post type archive description. - * - * @since 2.2 - * - * @param string $post_type The name of the post type. - * @param boolean $remove_first Should the post type be removed first from the - * index. - * - * @global object $wpdb The WordPress database object. - * @global array $relevanssi_variables The Relevanssi global variables. - */ -function relevanssi_index_post_type_archive( $post_type, $remove_first = true ) { - $post_type_object = get_post_type_object( $post_type ); - global $wpdb, $relevanssi_variables; - - /** - * Allows excluding post type archives from the index. - * - * If this filter hook returns false, the post type archive won't be - * indexed and if it's already indexed, it will be removed from the index. - * - * @param boolean If true, index the archive. Default true. - * @param object The post type object. - */ - if ( ! apply_filters( 'relevanssi_post_type_archive_ok', true, $post_type ) ) { - relevanssi_delete_post_type_object( $post_type ); - return; - } - - $temp_post = new stdClass(); - $temp_post->post_content = $post_type_object->description; - $temp_post->post_title = $post_type_object->name; - - /** - * Allows modifying the fake post for the post type archive. - * - * In order to index post type archives, Relevanssi generates fake posts - * from the post types. This filter lets you modify the post object. The - * post type description is in the post_content and the post type name in - * the post_title. - * - * @param object $temp_post The post object. - * @param object $post_type The post type object. - */ - $temp_post = apply_filters( - 'relevanssi_post_to_index', - $temp_post, - $post_type_object - ); - - $post_type_object->description = $temp_post->post_content; - $post_type_object->name = $temp_post->post_title; - - if ( $remove_first ) { - relevanssi_delete_post_type_object( $post_type ); - } - - $insert_data = array(); - $remove_stopwords = true; - - $min_length = get_option( 'relevanssi_min_word_length', 3 ); - if ( ! isset( $post_type_object->description ) ) { - $post_type_object->description = ''; - } - /** - * Allows adding extra content to the post type before indexing. - * - * The post type description is passed through this filter, so if you want - * to add extra content to the description, you can use this filter. - * - * @param string $post_type_object->description The post type description. - * @param object $post_type_object The post type object. - */ - $description = apply_filters( - 'relevanssi_post_type_additional_content', - $post_type_object->description, - $post_type_object - ); - if ( ! empty( $description ) ) { - /** This filter is documented in lib/indexing.php */ - $tokens = apply_filters( - 'relevanssi_indexing_tokens', - relevanssi_tokenize( $description, $remove_stopwords, $min_length, 'indexing' ), - 'posttype-description' - ); - foreach ( $tokens as $t_term => $tf ) { - if ( ! isset( $insert_data[ $t_term ]['content'] ) ) { - $insert_data[ $t_term ]['content'] = 0; - } - $insert_data[ $t_term ]['content'] += $tf; - } - } - - if ( isset( $post_type_object->name ) && ! empty( $post_type_object->name ) ) { - /** This filter is documented in lib/indexing.php */ - $tokens = apply_filters( - 'relevanssi_indexing_tokens', - relevanssi_tokenize( $post_type_object->label, $remove_stopwords, $min_length, 'indexing' ), - 'posttype-name' - ); - foreach ( $tokens as $t_term => $tf ) { - if ( ! isset( $insert_data[ $t_term ]['title'] ) ) { - $insert_data[ $t_term ]['title'] = 0; - } - $insert_data[ $t_term ]['title'] += $tf; - } - } - - $post_type_id = relevanssi_get_post_type_by_name( $post_type ); - foreach ( $insert_data as $t_term => $data ) { - $fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield' ); - foreach ( $fields as $field ) { - if ( ! isset( $data[ $field ] ) ) { - $data[ $field ] = 0; - } - } - - $content = $data['content']; - $title = $data['title']; - $comment = $data['comment']; - $tag = $data['tag']; - $link = $data['link']; - $author = $data['author']; - $category = $data['category']; - $excerpt = $data['excerpt']; - $customfield = $data['customfield']; - $t_term = trim( $t_term ); // Numeric terms start with a space. - - $wpdb->query( - $wpdb->prepare( - 'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - ' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail) - VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)', - $post_type_id, - -1, - $t_term, - $t_term, - $content, - $title, - $comment, - $tag, - $link, - $author, - $category, - $excerpt, - '', - $customfield, - 'post_type', - '', - '', - '' - ) - ); - } -} - -/** - * Deletes a post type archive from Relevanssi index. - * - * @global $wpdb The WordPress database interface. - * @global $relevanssi_variables The global Relevanssi variables, used for the - * database table names. - * - * @param string $post_type Name of the post type to remove. - */ -function relevanssi_delete_post_type_object( $post_type ) { - global $wpdb, $relevanssi_variables; - $id = relevanssi_get_post_type_by_name( $post_type ); - if ( $id ) { - $wpdb->query( - 'DELETE FROM ' . - $relevanssi_variables['relevanssi_table'] . " WHERE item = $id " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared - "AND type = 'post_type'" - ); - } -} - -/** - * Returns the list of post type archives indexed. - * - * Returns a list of post types that have _builtin set to false and has_archive - * set to true. The list can be adjusted with the - * relevanssi_indexed_post_type_archives filter hook. - * - * @return array An array of post types. - */ -function relevanssi_get_indexed_post_type_archives() { - $args = array( - '_builtin' => false, - 'has_archive' => true, - ); - $post_types = get_post_types( $args ); - /** - * Filters the list of post type archives that are indexed by Relevanssi. - * - * @param array An array of post types. - * - * @return array An array of post types. - */ - return apply_filters( 'relevanssi_indexed_post_type_archives', $post_types ); -} - -/** - * Runs taxonomy, user and post type archive indexing if necessary. - */ -function relevanssi_premium_indexing() { - if ( 'on' === get_option( 'relevanssi_index_taxonomies' ) ) { - relevanssi_index_taxonomies(); - } - if ( 'on' === get_option( 'relevanssi_index_users' ) ) { - relevanssi_index_users(); - } - if ( 'on' === get_option( 'relevanssi_index_post_type_archives' ) ) { - relevanssi_index_post_type_archives(); - } -} diff --git a/relevanssi-premium/premium/interface.php b/relevanssi-premium/premium/interface.php deleted file mode 100644 index e3c5abcc..00000000 --- a/relevanssi-premium/premium/interface.php +++ /dev/null @@ -1,1612 +0,0 @@ - - - - - - - .
    - -

    - - - - - - - - - -

    - - - - - - - - - -

    - - - - - - - - - - -

    - Deutsch (de_DE), español (es_ES), français (fr_FR), suomi (fi)

    - - - - - - - - - - -

    - - - - - - - - - -

    - - - - - - - -
    - - -
    - -

    manage_options', 'relevanssi_options_capability' ); ?>

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - - - - - - - - -
    - - - -
    - - - - - - - - - -

    - - - - - - - - - -

    - - - get_results( "SHOW COLUMNS FROM $wpdb->posts" ); - wp_cache_set( 'relevanssi_column_list', $column_list ); - } - $columns = array(); - foreach ( $column_list as $column ) { - array_push( $columns, $column->Field ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - } - $columns = implode( ', ', $columns ); - - ?> - - - - - - -

    - wp_posts' ); - echo esc_html( $columns ); - ?> -

    - - - - - - - - -
    - - -

    -
    - - - - - - - - - /> -

    - - - -

    - - - - - - - > - - - - - > - - - -
    - - -
    - - -

    -

    -
    -
    - - -
    - - -

    -
    -
    - - -
    -

    -
    - -

    - - - - - -
    - - -
    - - -
    -

    - dog = hound to the synonym list and enable this feature, every time the indexer sees hound in post content or post title, it will index it as hound dog. Thus, the post will be found when searching with either word. This makes it possible to use synonyms with AND searches, but will slow down indexing, especially with large databases and large lists of synonyms. You can use multi-word values, but phrases do not work.', 'relevanssi' ); // phpcs:ignore WordPress.Security.EscapeOutput.UnsafePrintingFunction - ?> -

    -
    - - -

    - - - - - - - - -

    - - - - - - - > - - - - - - - - - - -
    - - - -

    relevanssi_post_type_additional_content' ); ?>

    -
    - - - > - - - - - ' . esc_html( implode( ', ', $post_types ) ) . '

    '; - ?> - -

    has_archive', 'relevanssi_indexed_post_type_archives' ); ?>

    - - - - - - - - - - /> -

    - - - post_type, $post->post_type ) ) { - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - wp_enqueue_script( - 'relevanssi_admin_pdf_js', - $plugin_dir_url . 'premium/admin_pdf_scripts.js', - array( 'jquery' ), - $relevanssi_variables['plugin_version'], - true - ); - wp_localize_script( - 'relevanssi_admin_pdf_js', - 'admin_pdf_data', - array( - 'send_pdf_nonce' => wp_create_nonce( 'relevanssi_send_pdf' ), - ) - ); - } - wp_enqueue_script( - 'relevanssi_metabox_js', - $plugin_dir_url . 'premium/admin_metabox_scripts.js', - array( 'jquery' ), - $relevanssi_variables['plugin_version'], - true - ); - wp_localize_script( - 'relevanssi_metabox_js', - 'relevanssi_metabox_data', - array( - 'metabox_nonce' => wp_create_nonce( 'relevanssi_metabox_nonce' ), - ) - ); - wp_enqueue_style( - 'relevanssi_metabox_css', - $plugin_dir_url . 'premium/metabox_styles.css', - array(), - $relevanssi_variables['plugin_version'] - ); - - } - - $nonce = array( - 'taxonomy_indexing_nonce' => wp_create_nonce( 'relevanssi_taxonomy_indexing_nonce' ), - 'user_indexing_nonce' => wp_create_nonce( 'relevanssi_user_indexing_nonce' ), - 'indexing_nonce' => wp_create_nonce( 'relevanssi_indexing_nonce' ), - 'post_type_archive_indexing_nonce' => wp_create_nonce( 'relevanssi_post_type_archive_indexing_nonce' ), - 'searching_nonce' => wp_create_nonce( 'relevanssi_admin_search_nonce' ), - ); - - wp_localize_script( 'relevanssi_admin_js_premium', 'nonce', $nonce ); -} - -/** - * Imports Relevanssi Premium options. - * - * Takes the options array and does the actual updating of options using - * update_options(). - * - * @param string $options JSON-formatted array. Key has the option name, value - * the option value. - */ -function relevanssi_import_options( $options ) { - $unserialized = json_decode( stripslashes( $options ) ); - foreach ( $unserialized as $key => $value ) { - if ( in_array( - $key, - array( - 'relevanssi_post_type_weights', - 'relevanssi_recency_bonus', - 'relevanssi_punctuation', - 'relevanssi_related_style', - 'relevanssi_related_settings', - 'relevanssi_synonyms', - 'relevanssi_body_stopwords', - 'relevanssi_stopwords', - 'relevanssi_spamblock', - ), - true - ) ) { - // The options are associative arrays that are translated to - // objects in JSON and need to be changed back to arrays. - $value = (array) $value; - } - if ( 'relevanssi_redirects' === $key ) { - $value = json_decode( wp_json_encode( $value ), true ); - } - update_option( $key, $value ); - } - - echo "
    " . esc_html__( 'Options updated!', 'relevanssi' ) . '
    '; -} - -/** - * Updates Relevanssi Premium options. - * - * @global array $relevanssi_variables Relevanssi global variables, used to - * access the plugin file name. - * - * Reads in the options from $_REQUEST and updates the correct options, - * depending on which tab has been active. - */ -function relevanssi_update_premium_options() { - global $relevanssi_variables; - check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' ); - - $request = $_REQUEST; // WPCS: Input var okay. - if ( ! isset( $request['tab'] ) ) { - $request['tab'] = ''; - } - - relevanssi_update_floatval( $request, 'relevanssi_link_boost', true, '0.75' ); - - if ( empty( $request['relevanssi_api_key'] ) ) { - unset( $request['relevanssi_api_key'] ); - } - - if ( 'overview' === $request['tab'] ) { - relevanssi_turn_off_options( - $request, - array( - 'relevanssi_do_not_call_home', - 'relevanssi_update_translations', - 'relevanssi_hide_post_controls', - 'relevanssi_show_post_controls', - ) - ); - } - - if ( 'indexing' === $request['tab'] ) { - relevanssi_turn_off_options( - $request, - array( - 'relevanssi_index_pdf_parent', - 'relevanssi_index_post_type_archives', - 'relevanssi_index_subscribers', - 'relevanssi_index_synonyms', - 'relevanssi_index_taxonomies', - 'relevanssi_index_users', - ) - ); - } - - if ( 'attachments' === $request['tab'] ) { - relevanssi_turn_off_options( - $request, - array( - 'relevanssi_link_pdf_files', - 'relevanssi_read_new_files', - 'relevanssi_send_pdf_files', - ) - ); - } - - if ( 'searching' === $request['tab'] ) { - if ( isset( $request['relevanssi_recency_bonus'] ) && isset( $request['relevanssi_recency_days'] ) ) { - $relevanssi_recency_bonus = array(); - $relevanssi_recency_bonus['bonus'] = floatval( $request['relevanssi_recency_bonus'] ); - $relevanssi_recency_bonus['days'] = intval( $request['relevanssi_recency_days'] ); - update_option( 'relevanssi_recency_bonus', $relevanssi_recency_bonus ); - } - - if ( ! isset( $request['relevanssi_searchblogs_all'] ) ) { - $request['relevanssi_searchblogs_all'] = 'off'; - } - } - - if ( 'logging' === $request['tab'] ) { - relevanssi_turn_off_options( - $request, - array( - 'relevanssi_click_tracking', - 'relevanssi_hide_branding', - ) - ); - relevanssi_update_intval( $request, 'relevanssi_trim_click_logs', true, 180 ); - } - - if ( 'excerpts' === $request['tab'] ) { - relevanssi_update_intval( $request, 'relevanssi_max_excerpts', true, 1 ); - relevanssi_update_intval( $request, 'relevanssi_trim_click_logs', true, 180 ); - } - - if ( 'related' === $request['tab'] ) { - $settings = get_option( 'relevanssi_related_settings', relevanssi_related_default_settings() ); - - $settings['enabled'] = relevanssi_off_or_on( $request, 'relevanssi_related_enabled' ); - $settings['number'] = relevanssi_intval( $request, 'relevanssi_related_number' ); - $settings['months'] = relevanssi_intval( $request, 'relevanssi_related_months' ); - $settings['nothing'] = relevanssi_legal_value( - $request, - 'relevanssi_related_nothing', - array( 'random', 'random_cat' ), - 'nothing' - ); - $settings['notenough'] = relevanssi_legal_value( - $request, - 'relevanssi_related_notenough', - array( 'random', 'random_cat' ), - 'nothing' - ); - $settings['append'] = relevanssi_implode( $request, 'relevanssi_related_append' ); - $settings['post_types'] = ''; - if ( isset( $request['relevanssi_related_post_types'] ) && is_array( $request['relevanssi_related_post_types'] ) ) { - $settings['post_types'] = implode( ',', $request['relevanssi_related_post_types'] ); - if ( false !== stripos( $settings['post_types'], 'matching_post_type' ) ) { - $settings['post_types'] = 'matching_post_type'; - } - } - $settings['keyword'] = relevanssi_implode( $request, 'relevanssi_related_keyword' ); - $settings['restrict'] = relevanssi_implode( $request, 'relevanssi_related_restrict' ); - $settings['cache_for_admins'] = relevanssi_off_or_on( $request, 'relevanssi_related_cache_for_admins' ); - - update_option( 'relevanssi_related_settings', $settings ); - - if ( 'off' === $settings['enabled'] ) { - relevanssi_flush_related_cache(); - } - if ( isset( $request['relevanssi_flush_related_cache'] ) && 'off' !== $request['relevanssi_flush_related_cache'] ) { - relevanssi_flush_related_cache(); - } - - $style = get_option( 'relevanssi_related_style', relevanssi_related_default_styles() ); - - $style['width'] = relevanssi_intval( $request, 'relevanssi_related_width' ); - $style['excerpts'] = relevanssi_off_or_on( $request, 'relevanssi_related_excerpts' ); - $style['titles'] = relevanssi_off_or_on( $request, 'relevanssi_related_titles' ); - $style['thumbnails'] = relevanssi_off_or_on( $request, 'relevanssi_related_thumbnails' ); - $style['default_thumbnail'] = relevanssi_intval( $request, 'relevanssi_default_thumbnail' ); - - if ( isset( $request['relevanssi_remove_default_thumbnail'] ) && 'off' !== $request['relevanssi_remove_default_thumbnail'] ) { - $style['default_thumbnail'] = 0; - } - update_option( 'relevanssi_related_style', $style ); - } - - if ( 'spamblock' === $request['tab'] ) { - $settings['keywords'] = stripslashes( $request['relevanssi_spamblock_keywords'] ); - $settings['regex'] = stripslashes( $request['relevanssi_spamblock_regex'] ); - - $settings['chinese'] = relevanssi_off_or_on( $request, 'relevanssi_spamblock_chinese' ); - $settings['cyrillic'] = relevanssi_off_or_on( $request, 'relevanssi_spamblock_cyrillic' ); - $settings['emoji'] = relevanssi_off_or_on( $request, 'relevanssi_spamblock_emoji' ); - $settings['bots'] = relevanssi_off_or_on( $request, 'relevanssi_spamblock_bots' ); - - update_option( 'relevanssi_spamblock', $settings ); - } - - if ( isset( $request['relevanssi_remove_api_key'] ) ) { - update_option( 'relevanssi_api_key', '', false ); - } - relevanssi_update_off_or_on( $request, 'relevanssi_click_tracking', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_do_not_call_home', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_hide_branding', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_hide_post_controls', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_pdf_parent', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_post_type_archives', true ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_subscribers', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_synonyms', true ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_taxonomies', true ); - relevanssi_update_off_or_on( $request, 'relevanssi_index_users', true ); - relevanssi_update_off_or_on( $request, 'relevanssi_link_pdf_files', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_read_new_files', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_searchblogs_all', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_send_pdf_files', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_show_post_controls', false ); - relevanssi_update_off_or_on( $request, 'relevanssi_update_translations', false ); - relevanssi_update_sanitized( $request, 'relevanssi_api_key', true ); - relevanssi_update_sanitized( $request, 'relevanssi_disable_shortcodes', false ); - relevanssi_update_sanitized( $request, 'relevanssi_index_user_fields', false ); - relevanssi_update_sanitized( $request, 'relevanssi_internal_links', false ); - relevanssi_update_sanitized( $request, 'relevanssi_mysql_columns', false ); - relevanssi_update_sanitized( $request, 'relevanssi_searchblogs', false ); - relevanssi_update_sanitized( $request, 'relevanssi_thousand_separator', false ); - - relevanssi_update_legal_value( - $request, - 'relevanssi_server_location', - array( 'us', 'eu' ), - 'us', - false - ); - - if ( 'redirects' === $request['tab'] ) { - $value = relevanssi_process_redirects( $request ); - update_option( 'relevanssi_redirects', $value ); - } -} - -/** - * Adds Relevanssi Premium tabs to Relevanssi settings page. - * - * @global array $relevanssi_variables Used for the plugin path. - * - * @param array $tabs The array of tab items. - * - * @return array The tab array with Premium tabs added. - */ -function relevanssi_premium_add_tabs( $tabs ) { - global $relevanssi_variables; - - $slugs = wp_list_pluck( $tabs, 'slug' ); - $redirects_id = array_search( 'redirects', $slugs, true ); - $attachments_id = array_search( 'attachments', $slugs, true ); - - $tabs[ $redirects_id ] = array( - 'slug' => 'redirects', - 'name' => __( 'Redirects', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/redirects-tab.php', - 'callback' => 'relevanssi_redirects_tab', - 'save' => true, - ); - $tabs[ $attachments_id ] = array( - 'slug' => 'attachments', - 'name' => __( 'Attachments', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/attachments-tab.php', - 'callback' => 'relevanssi_attachments_tab', - 'save' => true, - ); - - $tabs[] = array( - 'slug' => 'importexport', - 'name' => __( 'Import / Export options', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/import-export-tab.php', - 'callback' => 'relevanssi_import_export_tab', - 'save' => true, - ); - $tabs[] = array( - 'slug' => 'related', - 'name' => __( 'Related', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/related-tab.php', - 'callback' => 'relevanssi_related_tab', - 'save' => true, - ); - $tabs[] = array( - 'slug' => 'spamblock', - 'name' => __( 'Spam Block', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/spamblock-tab.php', - 'callback' => 'relevanssi_spamblock_tab', - 'save' => true, - ); - $tabs[] = array( - 'slug' => 'support', - 'name' => __( 'Support', 'relevanssi' ), - 'require' => dirname( $relevanssi_variables['file'] ) - . '/premium/tabs/support-tab.php', - 'callback' => 'relevanssi_support_tab', - 'save' => false, - ); - return $tabs; -} - -/** - * Handles the "Reset relevanssi_words" functionality on the debugging tab. - */ -function relevanssi_form_reset_words() { - $text = esc_attr__( 'Reset the option', 'relevanssi' ); - $reset = << - -

    -EOH; - - if ( isset( $_REQUEST['relevanssi_words'] ) ) { - wp_verify_nonce( '_relevanssi_nonce', 'relevanssi_how_relevanssi_sees' ); - $success = delete_option( 'relevanssi_words' ); - if ( $success ) { - $reset = '

    ' . esc_html__( 'Option successfully reset!', 'relevanssi' ) . '

    '; - } else { - $reset = '

    ' . esc_html__( "Couldn't reset the option, reload the page to try again.", 'relevanssi' ) . '

    '; - } - } - - $words = get_option( 'relevanssi_words', false ); - if ( ! $words ) { - $word_text = sprintf( - // Translators: %1$s is relevanssi_words. - esc_html__( 'The %1$s option doesn\'t exist. You can\'t reset it; it should be regenerated when you search for something.', 'relevanssi' ), - 'relevanssi_words' - ); - } elseif ( isset( $words['words'] ) && isset( $words['expire'] ) ) { - $word_count = count( $words['words'] ); - $word_text = sprintf( - // Translators: %1$s is relevanssi_words, %2$d is the number of words in the option, %3$s is the expiration date of the option. - esc_html__( 'The %1$s option has %2$d words in it and the cache expires on %3$s.', 'relevanssi' ), - 'relevanssi_words', - $word_count, - date_i18n( get_option( 'date_format' ), $words['expire'] ) - ); - } else { - $word_text = sprintf( - // Translators: %1$s is relevanssi_words. - esc_html__( 'The %1$s option is empty.', 'relevanssi' ), - 'relevanssi_words' - ); - } - - ?> -

    - -

    - -

    - -

    - relevanssi_words. - esc_html__( - 'If you are having problems with the Did you mean? feature, you can reset the %1$s option that keeps a cache. Next time the Did you mean? suggestions are needed the option is regenerated.', - 'relevanssi' - ), - 'relevanssi_words' - ); - ?> -

    - -
    ' . $message; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -} - -/** - * Generates a message giving the reason for API key and license problems. - * - * @return string The message. - */ -function relevanssi_get_api_key_notification() { - global $relevanssi_variables; - - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - - if ( ! $api_key ) { - $url = add_query_arg( - 'page', - 'relevanssi-premium%2Frelevanssi.php', - get_admin_url() . 'options-general.php' - ); - if ( is_plugin_active_for_network( plugin_basename( $relevanssi_variables['file'] ) ) ) { - $url = network_admin_url( 'admin.php?page=relevanssi-premium%2Frelevanssi.php' ); - } - $message = sprintf( - // Translators: %1$s opens the link to the Relevanssi Premium settings page, %3$s opens the link to the Relevanssi Premium license purchase page. %2$s closes the links. - esc_html__( "The API key is not set. Please enter your API key in the %1\$sthe Relevanssi settings%2\$s. If you don't have one, %3\$syou can buy a new license here%2\$s.", 'relevanssi' ), - '', - '', - '' - ); - } else { - $message = sprintf( - // Translators: %1$s opens the link to the Relevanssi Premium license purchase page. %2$s closes the link. - esc_html__( "Your API key is set, but it looks like you don't have a valid license. %1\$sYou can buy a new license here%2\$s.", 'relevanssi' ), - '', - '' - ); - } - return $message; -} - -/** - * Adds the Relevanssi columns to the post list. - * - * @param array $columns The columns. - * @param string $post_type The post type. - */ -function relevanssi_manage_columns( $columns, $post_type = 'page' ) { - $post_types = get_option( 'relevanssi_index_post_types', array() ); - if ( ! in_array( $post_type, $post_types, true ) ) { - return $columns; - } - - $columns['pinned_keywords'] = __( 'Pinned keywords', 'relevanssi' ); - $columns['unpinned_keywords'] = __( 'Excluded keywords', 'relevanssi' ); - $columns['pin_for_all'] = __( 'Pin for all searches', 'relevanssi' ); - $columns['exclude_post'] = __( 'Exclude post', 'relevanssi' ); - $columns['ignore_content'] = __( 'Ignore post content', 'relevanssi' ); - return $columns; -} - -/** - * Adds the Relevanssi Premium columns to the post list. - * - * @param array $column The column name. - * @param int $post_id The post ID. - */ -function relevanssi_manage_custom_column( $column, $post_id ) { - switch ( $column ) { - case 'pinned_keywords': - $keywords = get_post_meta( $post_id, '_relevanssi_pin_keywords', true ); - if ( ! empty( $keywords ) ) { - echo esc_html( $keywords ); - } - break; - case 'unpinned_keywords': - $keywords = get_post_meta( $post_id, '_relevanssi_unpin_keywords', true ); - if ( ! empty( $keywords ) ) { - echo esc_html( $keywords ); - } - break; - case 'pin_for_all': - $pin_for_all = get_post_meta( $post_id, '_relevanssi_pin_for_all', true ); - if ( ! empty( $pin_for_all ) ) { - echo '✓'; - } else { - echo '✗'; - } - break; - case 'exclude_post': - $hide_post = get_post_meta( $post_id, '_relevanssi_hide_post', true ); - if ( ! empty( $hide_post ) ) { - echo '✓'; - } else { - echo '✗'; - } - break; - case 'ignore_content': - $hide_content = get_post_meta( $post_id, '_relevanssi_hide_content', true ); - if ( ! empty( $hide_content ) ) { - echo '✓'; - } else { - echo '✗'; - } - break; - } -} - -/** - * Adds the Relevanssi custom fields to the quick edit box. - * - * @param string $column The column name. - */ -function relevanssi_quick_edit_custom_box( $column ) { - switch ( $column ) { - case 'pinned_keywords': - ?> - -
    - -
    -
    - - - -
    -
    -
    - -
    -
    - - - - - -
    -
    - - -

    %s

    ', esc_html__( 'Relevanssi network options', 'relevanssi' ) ); - - if ( ! empty( $_POST ) ) { // WPCS: Input var okay. - if ( isset( $_REQUEST['submit'] ) ) { // WPCS: Input var okay. - check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_network_options' ); - relevanssi_update_network_options(); - } - if ( isset( $_REQUEST['copytoall'] ) ) { // WPCS: Input var okay. - check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_network_options' ); - relevanssi_copy_options_to_subsites( $_REQUEST ); // WPCS: Input var okay. - } - } - - $this_page = '?page=relevanssi/relevanssi.php'; - if ( RELEVANSSI_PREMIUM ) { - $this_page = '?page=relevanssi-premium/relevanssi.php'; - } - - printf( "
    ", esc_attr( $this_page ) ); - - wp_nonce_field( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_network_options' ); - - ?> - - -
    - ' class='button button-primary' /> -
    - -

    -

    - -
    - - - - - - - -
    - 2000 ) ); - $blog_list = array(); - foreach ( $raw_blog_list as $blog ) { - $details = get_blog_details( $blog->blog_id ); - $blog_list[ $details->blogname ] = $blog->blog_id; - } - ksort( $blog_list ); - echo "'; - - ?> - ' class='button button-primary' /> -
    -
    - - ' . esc_html__( 'Copying options from blog %s', 'relevanssi' ) . '', esc_html( $sourceblog ) ); - global $wpdb; - switch_to_blog( $sourceblog ); - $q = "SELECT * FROM $wpdb->options WHERE option_name LIKE 'relevanssi%'"; - restore_current_blog(); - - $results = $wpdb->get_results( $q ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - - $blog_list = get_sites( array( 'number' => 2000 ) ); - foreach ( $blog_list as $blog ) { - if ( $blog->blog_id === $sourceblog ) { - continue; - } - switch_to_blog( $blog->blog_id ); - - /* translators: %s is the blog ID */ - printf( '

    ' . esc_html__( 'Processing blog %s:', 'relevanssi' ) . '
    ', esc_html( $blog->blog_id ) ); - if ( ! is_plugin_active( 'relevanssi-premium/relevanssi.php' ) ) { - echo esc_html__( 'Relevanssi is not active in this blog.', 'relevanssi' ) . '

    '; - continue; - } - foreach ( $results as $option ) { - if ( is_serialized( $option->option_value ) ) { - $value = unserialize( $option->option_value ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions - } else { - $value = $option->option_value; - } - update_option( $option->option_name, $value ); - } - echo esc_html__( 'Options updated.', 'relevanssi' ) . '

    '; - restore_current_blog(); - } -} diff --git a/relevanssi-premium/premium/pdf-upload.php b/relevanssi-premium/premium/pdf-upload.php deleted file mode 100644 index 7ea28487..00000000 --- a/relevanssi-premium/premium/pdf-upload.php +++ /dev/null @@ -1,920 +0,0 @@ - $post_id ) - ); - // Remove the usual relevanssi_publish action because - // relevanssi_index_pdf() already indexes the post. - remove_action( 'add_attachment', 'relevanssi_publish', 12 ); - } -} - -/** - * Checks the MIME type of the attachment to determine if it's allowed or not. - * - * By default this function blocks all images, all video, and zip files. - * - * @param string $mime_type The attachment MIME type. - * - * @return boolean True, if ok to read the attachment, false if not. - */ -function relevanssi_mime_type_ok( $mime_type ) { - $read_this = true; - $mime_parts = explode( '/', $mime_type ); - if ( in_array( $mime_parts[0], array( 'image', 'video' ), true ) ) { - $read_this = false; - } - if ( isset( $mime_parts[1] ) && in_array( $mime_parts[1], array( 'zip', 'octet-stream', 'x-zip-compressed', 'x-zip' ), true ) ) { - $read_this = false; - } - /** - * Allows the filtering of attachment reading based on MIME type. - * - * @param boolean $read_this True, if ok to read the attachment, false if not. - * @param string $mime_type The attachment MIME type. - * - * @return boolean True, if ok to read the attachment, false if not. - */ - $read_this = apply_filters( 'relevanssi_accept_mime_type', $read_this, $mime_type ); - return $read_this; -} - -/** - * Includes the PDF content custom field in the list of custom fields. - * - * This function works on 'relevanssi_index_custom_fields' filter and makes sure the - * '_relevanssi_pdf_content' custom field is included. - * - * @since 2.0.0 - * - * @param array $custom_fields The custom fields array. - * - * @return array $custom_fields The custom fields array. - */ -function relevanssi_add_pdf_customfield( $custom_fields ) { - if ( ! is_array( $custom_fields ) ) { - $custom_fields = array(); - } - if ( ! in_array( '_relevanssi_pdf_content', $custom_fields, true ) ) { - $custom_fields[] = '_relevanssi_pdf_content'; - } - return $custom_fields; -} - -/** - * Reads in all _relevanssi_pdf_content for found posts to avoid database calls. - * - * @global array An array of the PDF content. - * - * @param array $hits An array of posts found. - * @param WP_Query $query The WP_Query object. - * - * @return array The posts found, untouched. - */ -function relevanssi_prime_pdf_content( $hits, $query ) { - global $relevanssi_pdf_content; - - if ( ! isset( $query->query_vars['fields'] ) || empty( $query->query_vars['fields'] ) ) { - $relevanssi_pdf_content = relevanssi_get_post_meta_for_all_posts( - wp_list_pluck( $hits, 'ID' ), - '_relevanssi_pdf_content' - ); - } - - return $hits; -} - - -/** - * Includes the PDF content custom field for excerpt-building. - * - * This function works on 'relevanssi_pre_excerpt_content' filter and makes sure - * the '_relevanssi_pdf_content' custom field content is included when excerpts - * are built. - * - * @since 2.0.0 - * - * @see relevanssi_prime_pdf_content - * - * @param string $content The post content. - * @param object $post The post object. - * - * @return string $content The post content. - */ -function relevanssi_add_pdf_content_to_excerpt( $content, $post ) { - global $relevanssi_pdf_content; - $pdf_content = $relevanssi_pdf_content[ $post->ID ] ?? ''; - $content .= ' ' . $pdf_content; - return $content; -} - -/** - * Adds the PDF control metabox. - * - * Adds the PDF control metaboxes on post edit pages for posts in the - * 'attachment' post type, with a MIME type that is not 'image/*' or - * 'video/*'. - * - * @since 2.0.0 - * - * @param object $post The post object. - */ -function relevanssi_add_pdf_metaboxes( $post ) { - // Do not display on image pages. - $mime_parts = explode( '/', $post->post_mime_type ); - if ( in_array( $mime_parts[0], array( 'image', 'video' ), true ) ) { - return; - } - - add_meta_box( - 'relevanssi_pdf_box', - __( 'Relevanssi attachment controls', 'relevanssi' ), - 'relevanssi_attachment_metabox', - $post->post_type - ); -} - -/** - * Prints out the attachment control metabox. - * - * Prints out the attachment control metabox used for reading attachments and - * examining the read attachment content. - * - * @global object $post The global post object. - * @global array $relevanssi_variables The Relevanssi global variables array, - * used to get the file name for nonce. - * - * @since 2.0.0 - */ -function relevanssi_attachment_metabox() { - global $post, $relevanssi_variables; - wp_nonce_field( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_pdfcontent' ); - - $pdf_modified = get_post_meta( $post->ID, '_relevanssi_pdf_modified', true ); - - /** - * Filters the attachment URL. - * - * If you want to make Relevanssi index attached file content from - * files that are stored outside the WP attachment system, use this - * filter to provide the URL of the file. - * - * @param string The URL of the attached file. - * @param int The post ID of the attachment post. - */ - $url = apply_filters( - 'relevanssi_get_attachment_url', - wp_get_attachment_url( $post->ID ), - $post->ID - ); - $id = $post->ID; - $button_text = $pdf_modified ? __( 'Reread the attachment content', 'relevanssi' ) : __( 'Read the attachment content', 'relevanssi' ); - $api_key = get_network_option( null, 'relevanssi_api_key' ); - $action = 'sendUrl'; - $explanation = __( 'Indexer will fetch the file from your server.', 'relevanssi' ); - if ( 'on' === get_option( 'relevanssi_send_pdf_files' ) ) { - $action = 'sendPdf'; - $explanation = __( 'The file will be uploaded to the indexer.', 'relevanssi' ); - } - - if ( ! $api_key ) { - // get_network_option() falls back to get_option(), but if this is a single - // install on a multisite, it won't work correctly. - $api_key = get_option( 'relevanssi_api_key' ); - } - - if ( ! $api_key ) { - printf( '

    %s

    ', esc_html__( 'No API key set. API key is required for attachment indexing.', 'relevanssi' ) ); - } else { - printf( - '

    ', - esc_attr( $action ), - esc_attr( $button_text ), - esc_attr( $api_key ), - intval( $id ), - esc_attr( $url ), - esc_attr( $explanation ) - ); - - if ( $pdf_modified ) { - esc_html_e( "The attachment content has been modified and won't be reread from the file when doing a general rereading. If you want to reread the attachment contents from the file, you can force rereading here.", 'relevanssi' ); - } - - $pdf_content = get_post_meta( $post->ID, '_relevanssi_pdf_content', true ); - if ( $pdf_content ) { - $pdf_content_title = __( 'Attachment content', 'relevanssi' ); - printf( - '

    ', - esc_html( $pdf_content_title ), - esc_html( $pdf_content ) - ); - } - - $pdf_error = get_post_meta( $post->ID, '_relevanssi_pdf_error', true ); - if ( false !== strpos( $pdf_error, 'R_ERR05' ) ) { - printf( - '

    %s

    ', - esc_html__( 'Relevanssi is currently in process of reading the file contents, please return here later.', 'relevanssi' ) - ); - } elseif ( $pdf_error ) { - $pdf_error_title = __( 'Attachment error message', 'relevanssi' ); - printf( - '

    ', - esc_html( $pdf_error_title ), - esc_html( $pdf_error ) - ); - } - - if ( empty( $pdf_content ) && empty( $pdf_error ) ) { - printf( - '

    %s

    ', - esc_html__( 'No attachment content found for this post at the moment.', 'relevanssi' ) - ); - } - } -} - -/** - * Reads in attachment content from a attachment file. - * - * Reads in the attachment content, either by sending an URL or the file itself to - * the Relevanssi attachment reading service. - * - * @param int $post_id The attachment post ID. - * @param boolean $ajax Is this in AJAX context? Default false. - * @param string $send_file Should the file be sent ('on'), or just the URL ('off')? - * Default null. - * - * @return array An array with two items: boolean 'success' and 'error' - * containing the possible error message. - * - * @since 2.0.0 - */ -function relevanssi_index_pdf( $post_id, $ajax = false, $send_file = null ) { - $hide_post = get_post_meta( $post_id, '_relevanssi_hide_post', true ); - /** - * Filters whether the attachment should be read or not. - * - * @param boolean $hide_post True if the attachment shouldn't be read, - * false if it should. - * @param int $post_id The attachment post ID. - */ - $hide_post = apply_filters( 'relevanssi_do_not_read', $hide_post, $post_id ); - if ( $hide_post ) { - delete_post_meta( $post_id, '_relevanssi_pdf_content' ); - update_post_meta( $post_id, '_relevanssi_pdf_error', RELEVANSSI_ERROR_01 ); - - $result = array( - 'success' => false, - 'error' => RELEVANSSI_ERROR_01, - ); - - return $result; - } - - $mime_type = get_post_mime_type( $post_id ); - if ( ! relevanssi_mime_type_ok( $mime_type ) ) { - delete_post_meta( $post_id, '_relevanssi_pdf_content' ); - update_post_meta( $post_id, '_relevanssi_pdf_error', RELEVANSSI_ERROR_03 ); - - $result = array( - 'success' => false, - 'error' => RELEVANSSI_ERROR_03, - ); - - return $result; - } - - if ( is_null( $send_file ) ) { - $send_file = get_option( 'relevanssi_send_pdf_files' ); - } elseif ( $send_file ) { - $send_file = 'on'; - } - - /** - * Filters whether the PDF files are uploaded for indexing or not. - * - * If you have some files that need to be uploaded and some where it's - * better if the indexer reads them from a URL, you can use this filter - * hook to adjust the setting on a per-file basis. - * - * @param string $sendfile If 'on', upload the file, otherwise the file - * will be read from the URL. - * @param int $post_id The post ID of the attachment post. - */ - $send_file = apply_filters( 'relevanssi_send_pdf_files', $send_file, $post_id ); - - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - $server_url = relevanssi_get_server_url(); - - if ( 'on' === get_option( 'relevanssi_do_not_call_home' ) ) { - if ( in_array( $server_url, array( RELEVANSSI_EU_SERVICES_URL, RELEVANSSI_US_SERVICES_URL ), true ) ) { - delete_post_meta( $post_id, '_relevanssi_pdf_content' ); - update_post_meta( $post_id, '_relevanssi_pdf_error', RELEVANSSI_ERROR_02 ); - - $result = array( - 'success' => false, - 'error' => RELEVANSSI_ERROR_02, - ); - - return $result; - } - } - if ( 'on' === $send_file ) { - /** - * Filters the attachment file name. - * - * If you want to make Relevanssi index attached file content from - * files that are stored outside the WP attachment system, use this - * filter to provide the name of the file. - * - * @param string The filename of the attached file. - * @param int The post ID of the attachment post. - */ - $file_name = apply_filters( - 'relevanssi_get_attached_file', - get_attached_file( $post_id ), - $post_id - ); - - $file = fopen( $file_name, 'r' ); // phpcs:ignore WordPress.WP.AlternativeFunctions - if ( false === $file ) { - $response = new WP_Error( 'fopen', 'Could not open the file for reading.' ); - } else { - $file_size = filesize( $file_name ); - $file_data = fread( $file, $file_size ); // phpcs:ignore WordPress.WP.AlternativeFunctions - $args = array( - 'headers' => array( - 'accept' => 'application/json', // The API returns JSON. - 'content-type' => 'application/binary', // Set content type to binary. - ), - 'body' => $file_data, - /** - * Changes the default reading timeout. - * - * By default, the timeout period is 45 seconds. If that's not - * enough, you can adjust the timeout period with this filter. - * - * @param int $timeout The timeout in seconds, default 45. - */ - 'timeout' => apply_filters( 'relevanssi_pdf_read_timeout', 45 ), - ); - $response = wp_safe_remote_post( - $server_url . 'index.php?key=' . $api_key . '&upload=true', - $args - ); - } - } else { - /** - * Filters the attachment URL. - * - * If you want to make Relevanssi index attached file content from - * files that are stored outside the WP attachment system, use this - * filter to provide the URL of the file. - * - * @param string The URL of the attached file. - * @param int The post ID of the attachment post. - */ - $url = apply_filters( - 'relevanssi_get_attachment_url', - wp_get_attachment_url( $post_id ), - $post_id - ); - - $args = array( - 'body' => array( - 'key' => $api_key, - 'url' => $url, - ), - 'method' => 'POST', - /** - * Changes the default reading timeout. - * - * By default, the timeout period is 45 seconds. If that's not - * enough, you can adjust the timeout period with this filter. - * - * @param int $timeout The timeout in seconds, default 45. - */ - 'timeout' => apply_filters( 'relevanssi_pdf_read_timeout', 45 ), - ); - - $response = wp_safe_remote_post( $server_url, $args ); - } - - $result = relevanssi_process_server_response( $response, $post_id ); - - if ( $ajax ) { - echo wp_json_encode( $result ); - wp_die(); - } - - // The PDF count is cached because the query is slow; delete the cache now, as - // the value just changed. - wp_cache_delete( 'relevanssi_pdf_count' ); - wp_cache_delete( 'relevanssi_pdf_error_count' ); - - return $result; -} - -/** - * Processes the attachment reading server response. - * - * Takes in the response from the attachment reading server and stores the attachment - * content or the error message to the appropriate custom fields. - * - * @param array|object $response The server response. - * @param int $post_id The attachment post ID. - * - * @since 2.0.0 - */ -function relevanssi_process_server_response( $response, $post_id ) { - $success = null; - $response_error = ''; - if ( is_wp_error( $response ) ) { - $error_message = $response->get_error_message(); - $response_error .= $error_message . '\n'; - - delete_post_meta( $post_id, '_relevanssi_pdf_content' ); - delete_post_meta( $post_id, '_relevanssi_pdf_modified' ); - update_post_meta( $post_id, '_relevanssi_pdf_error', $error_message ); - $success = false; - } elseif ( isset( $response['body'] ) ) { - $content = $response['body']; - $content = json_decode( $content ); - - $content_error = ''; - - if ( 413 === $response['response']['code'] ) { - $content_error = RELEVANSSI_ERROR_04; - } - - if ( 504 === $response['response']['code'] ) { - $content_error = RELEVANSSI_ERROR_06; - } - - if ( isset( $content->error ) ) { - $content_error = $content->error; - $content = $content->error; - } - - if ( $content && stristr( $content, 'java.lang.OutOfMemoryError' ) ) { - $content_error = RELEVANSSI_ERROR_04; - } - - if ( $content && stristr( $content, 'Tika server returned error code' ) ) { - $content_error = RELEVANSSI_ERROR_06; - } - - if ( empty( $content ) ) { - $content_error = RELEVANSSI_ERROR_06; - } - - if ( ! empty( $content_error ) ) { - delete_post_meta( $post_id, '_relevanssi_pdf_content' ); - delete_post_meta( $post_id, '_relevanssi_pdf_modified' ); - update_post_meta( $post_id, '_relevanssi_pdf_error', $content_error ); - - $response_error .= $content_error; - $success = false; - } else { - delete_post_meta( $post_id, '_relevanssi_pdf_error' ); - delete_post_meta( $post_id, '_relevanssi_pdf_modified' ); - /** - * Filters the read file content before it is saved. - * - * @param string $content The file content as a string. - * @param int $post_id The post ID of the attachment post. - */ - $success = update_post_meta( $post_id, '_relevanssi_pdf_content', apply_filters( 'relevanssi_file_content', $content, $post_id ) ); - relevanssi_index_doc( $post_id, false, relevanssi_get_custom_fields(), true ); - if ( 'on' === get_option( 'relevanssi_index_pdf_parent' ) ) { - if ( function_exists( 'get_post_parent' ) ) { - $parent = get_post_parent( $post_id ); - } else { - // For WP < 5.7 compatibility, remove eventually. - $_post = get_post( $post_id ); - $parent = ! empty( $_post->post_parent ) ? get_post( $_post->post_parent ) : null; - } - if ( $parent ) { - relevanssi_index_doc( $parent->ID, true, relevanssi_get_custom_fields(), true ); - } - } - - if ( ! $success ) { - $response_error = __( 'Could not save the file content to the custom field.', 'relevanssi' ); - } - } - } - - $response = array( - 'success' => $success, - 'error' => $response_error, - ); - - return $response; -} - -/** - * Gets the posts with attachments. - * - * Finds the posts with non-image attachments that don't have read content or - * errors. The posts that have timeout or connection errors (cURL error 7 and - * 28, R_ERR06) and those that haven't been read for privacy mode issues - * (R_ERR02) will be included for indexing, but the posts with other errors - * (R_ERR01: post excluded by user, R_ERR03: blocked MIME type and R_ERR04: file - * too large) will not be indexed. - * - * @since 2.0.0 - * - * @param int $limit The number of posts to fetch, default 1. - * - * @return array The posts with attachments. - */ -function relevanssi_get_posts_with_attachments( $limit = 1 ) { - global $wpdb; - - $meta_query_args = array( - 'relation' => 'AND', - array( - 'key' => '_relevanssi_pdf_content', - 'compare' => 'NOT EXISTS', - ), - array( - 'relation' => 'OR', - array( - 'key' => '_relevanssi_pdf_error', - 'compare' => 'NOT EXISTS', - ), - array( - 'key' => '_relevanssi_pdf_error', - 'compare' => 'LIKE', - 'value' => 'R_ERR02:', - ), - array( - 'key' => '_relevanssi_pdf_error', - 'compare' => 'LIKE', - 'value' => 'cURL error 7:', - ), - array( - 'key' => '_relevanssi_pdf_error', - 'compare' => 'LIKE', - 'value' => 'cURL error 28:', - ), - array( - 'key' => '_relevanssi_pdf_error', - 'compare' => 'LIKE', - 'value' => 'is not valid.', - ), - ), - ); - $meta_query = new WP_Meta_Query( $meta_query_args ); - $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' ); - $meta_join = ''; - $meta_where = ''; - if ( $meta_query_sql ) { - $meta_join = $meta_query_sql['join']; - $meta_where = $meta_query_sql['where']; - } - - // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - if ( $limit > 0 ) { - $query = $wpdb->prepare( - /** - * Filters the SQL query that fetches posts with attachments. - * - * If you want to make Relevanssi index attachments that are not in - * the WP Media Library, you need to adjust this filter to change - * the SQL query so that it fetches the correct posts. - * - * @param string The SQL query - * @param int $limit The number of posts to fetch. - * @param string $meta_join The SQL query join clause. - * @param string $meta_where The SQL query where clause. - */ - apply_filters( - 'relevanssi_get_attachment_posts_query', - "SELECT DISTINCT(ID) FROM $wpdb->posts $meta_join WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type LIKE %s $meta_where LIMIT %d", - $limit, - $meta_join, - $meta_where - ), - 'application/%', - $limit - ); - } else { - $query = $wpdb->prepare( - /** Filter documented in /premium/pdf-upload.php. */ - apply_filters( - 'relevanssi_get_attachment_posts_query', - "SELECT DISTINCT(ID) FROM $wpdb->posts $meta_join WHERE post_type = 'attachment' AND post_status = 'inherit' AND post_mime_type LIKE %s $meta_where", - 0, - $meta_join, - $meta_where - ), - 'application/%' - ); - } - /** - * Filters the final SQL query that fetches posts with attachments. - * - * @param string $query The SQL query. - * @param int $limit The number of posts to fetch. - * @param string $meta_join The SQL query join clause. - * @param string $meta_where The SQL query where clause. - */ - $query = apply_filters( 'relevanssi_get_attachment_posts_query_final', $query, $limit, $meta_join, $meta_where ); - // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - $posts = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - - return $posts; -} - -/** - * Prints out the Javascript for PDF content reading. - * - * @since 2.0.0 - */ -function relevanssi_pdf_action_javascript() { - $list_pdfs_nonce = wp_create_nonce( 'relevanssi-list-pdfs' ); - $wipe_pdfs_nonce = wp_create_nonce( 'relevanssi-wipe-pdfs' ); - $wipe_errors_nonce = wp_create_nonce( 'relevanssi-wipe-errors' ); - $index_pdfs_nonce = wp_create_nonce( 'relevanssi-index-pdfs' ); - - $server_error = __( 'Server error', 'relevanssi' ); - - ?> - - get_results( "SELECT * FROM $wpdb->postmeta WHERE ( meta_key = '_relevanssi_pin' OR meta_key = '_relevanssi_unpin' OR meta_key = '_relevanssi_pin_for_all' ) AND meta_value != '' LIMIT 1" ); - if ( ! is_multisite() && empty( $results ) ) { - // No, nothing is pinned. - return $hits; - } - - // Disable all filter functions on 'relevanssi_stemmer'. - if ( isset( $wp_filter['relevanssi_stemmer'] ) ) { - $callbacks = $wp_filter['relevanssi_stemmer']->callbacks; - $wp_filter['relevanssi_stemmer']->callbacks = null; - } - - $terms = relevanssi_tokenize( $hits[1], false, -1, 'search_query' ); - - // Re-enable the removed filters. - if ( isset( $wp_filter['relevanssi_stemmer'] ) ) { - $wp_filter['relevanssi_stemmer']->callbacks = $callbacks; - } - - $escaped_terms = array(); - foreach ( array_keys( $terms ) as $term ) { - $escaped_terms[] = esc_sql( trim( $term ) ); - } - - $term_list = array(); - $count_escaped_terms = count( $escaped_terms ); - for ( $length = 1; $length <= $count_escaped_terms; $length++ ) { - for ( $offset = 0; $offset <= $count_escaped_terms - $length; $offset++ ) { - $slice = array_slice( $escaped_terms, $offset, $length ); - $term_list[] = implode( ' ', $slice ); - } - } - - $full_search_phrase = esc_sql( trim( $hits[1] ) ); - if ( ! in_array( $full_search_phrase, $term_list, true ) ) { - $term_list[] = $full_search_phrase; - } - - /** - * Doing this instead of individual get_post_meta() calls can cut hundreds - * of database queries! - */ - $posts_pinned_for_all = array_flip( - $wpdb->get_col( - "SELECT post_id FROM $wpdb->postmeta - WHERE meta_key = '_relevanssi_pin_for_all' - AND meta_value = 'on'" - ) - ); - - $pin_weights_sql = $wpdb->get_results( - "SELECT post_id, meta_value FROM $wpdb->postmeta - WHERE meta_key = '_relevanssi_pin_weights'" - ); - - $pin_weights = array(); - foreach ( $pin_weights_sql as $row ) { - $pin_weights[ $row->post_id ] = $row->meta_value; - } - unset( $pin_weights_sql ); - - /** - * If the search query is "foo bar baz", $term_list now contains "foo", "bar", - *"baz", "foo bar", "bar baz", and "foo bar baz". - */ - if ( is_array( $term_list ) ) { - $term_list_array = $term_list; - - array_multisort( array_map( 'relevanssi_strlen', $term_list_array ), SORT_DESC, $term_list_array ); - - $term_list = implode( "','", $term_list ); - $term_list = "'$term_list'"; - - $positive_ids = array(); - $negative_ids = array(); - - $pins_fetched = false; - $pinned_posts = array(); - $other_posts = array(); - foreach ( $hits[0] as $hit ) { - $object_array = relevanssi_get_an_object( $hit ); - $hit = $object_array['object']; - $return_value = $object_array['format']; - - $blog_id = 0; - if ( isset( $hit->blog_id ) && function_exists( 'switch_to_blog' ) ) { - // Multisite, so switch_to_blog() to correct blog and process - // the pinned hits per blog. - $blog_id = $hit->blog_id; - switch_to_blog( $blog_id ); - if ( ! isset( $pins_fetched[ $blog_id ] ) ) { - $positive_ids[ $blog_id ] = $wpdb->get_col( 'SELECT post_id FROM ' . $wpdb->prefix . "postmeta WHERE meta_key = '_relevanssi_pin' AND meta_value IN ( $term_list )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $negative_ids[ $blog_id ] = $wpdb->get_col( 'SELECT post_id FROM ' . $wpdb->prefix . "postmeta WHERE meta_key = '_relevanssi_unpin' AND meta_value IN ( $term_list )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - if ( ! is_array( $pins_fetched ) ) { - $pins_fetched = array(); - } - $pins_fetched[ $blog_id ] = true; - } - restore_current_blog(); - } elseif ( ! $pins_fetched ) { // Single site. - $positive_ids[0] = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pin' AND meta_value IN ( $term_list )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $negative_ids[0] = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_unpin' AND meta_value IN ( $term_list )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared - $pins_fetched = true; - } - $hit_id = strval( $hit->ID ); // The IDs from the database are strings, the one from the post is an integer in some contexts. - - $positive_match = isset( $positive_ids[ $blog_id ] ) - && is_array( $positive_ids[ $blog_id ] ) - && in_array( $hit_id, $positive_ids[ $blog_id ], true ); - $negative_match = isset( $negative_ids[ $blog_id ] ) - && is_array( $negative_ids[ $blog_id ] ) - && in_array( $hit_id, $negative_ids[ $blog_id ], true ); - $pinned_for_all = isset( $hit->ID ) && isset( $posts_pinned_for_all[ $hit->ID ] ); - - $pin_weight = 0; - $weights = unserialize( $pin_weights[ $hit->ID ] ?? '' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize - foreach ( $term_list_array as $term ) { - if ( isset( $weights[ $term ] ) ) { - $pin_weight = $weights[ $term ]; - break; - } - } - - if ( 0 === $pin_weight ) { - $term = $term_list_array[0]; - $pin_weight = 1; - } - - if ( $hit_id && $positive_match && ! $negative_match ) { - $hit->relevanssi_pinned = 1; - $pinned_posts[ $term ][ $pin_weight ][] = relevanssi_return_value( $hit, $return_value ); - } elseif ( $pinned_for_all && ! $negative_match ) { - $hit->relevanssi_pinned = 1; - $pinned_posts[0][0][] = relevanssi_return_value( $hit, $return_value ); - } elseif ( ! $negative_match ) { - $other_posts[] = relevanssi_return_value( $hit, $return_value ); - } - } - array_multisort( array_map( 'relevanssi_strlen', array_keys( $pinned_posts ) ), SORT_DESC, $pinned_posts ); - - $all_pinned_posts = array(); - foreach ( $pinned_posts as $term => $posts_for_term ) { - krsort( $posts_for_term, SORT_NUMERIC ); - $posts_for_term = call_user_func_array( 'array_merge', $posts_for_term ); - $all_pinned_posts = array_merge( $all_pinned_posts, $posts_for_term ); - } - - $hits[0] = array_merge( $all_pinned_posts, $other_posts ); - } - return $hits; -} - -/** - * Adds pinned words to post content. - * - * Adds pinned terms to post content to make sure posts are found with the - * pinned terms. - * - * @param string $content Post content. - * @param object $post The post object. - */ -function relevanssi_add_pinned_words_to_post_content( $content, $post ) { - $pin_words = get_post_meta( $post->ID, '_relevanssi_pin', false ); - foreach ( $pin_words as $word ) { - $content .= " $word"; - } - return $content; -} - -/** - * Adds pinned words to post title. - * - * If the `relevanssi_index_content` filter hook returns `false`, ie. post - * content is not indexed, this function will add the pinned words to the post - * title instead to guarantee they are found in the search. - * - * @param string $content Titlecontent. - * @param object $post The post object. - */ -function relevanssi_pinning_backup( $content, $post ) { - if ( false === apply_filters( 'relevanssi_index_content', true ) ) { - $content = relevanssi_add_pinned_words_to_post_content( $content, $post ); - } - return $content; -} - -/** - * Provides the pinning functionality for the admin search. - * - * @param object $post The post object. - * @param string $query The search query. - * - * @return array First item is a string containing the pinning buttons, the second - * item is a string containing the "pinned" notice if the post is - * pinned. - */ -function relevanssi_admin_search_pinning( $post, $query ) { - $pinned = ''; - $pinning_buttons = array(); - - $pinned_words = array(); - if ( isset( $post->relevanssi_pinned ) ) { - $pinned_words = get_post_meta( $post->ID, '_relevanssi_pin' ); - $pinned = '' . __( '(pinned)', 'relevanssi' ) . ''; - } - - if ( ! current_user_can( 'edit_post', $post->ID ) ) { - return array( '', $pinned ); - } - - $tokens = relevanssi_tokenize( $query, true, -1, 'search_query' ); - foreach ( array_keys( $tokens ) as $token ) { - if ( ! in_array( $token, $pinned_words, true ) ) { - /* Translators: %s is the search term. */ - $pinning_button = sprintf( '', $post->ID, $token, sprintf( __( "Pin for '%s'", 'relevanssi' ), $token ) ); - $pinning_buttons[] = $pinning_button; - } else { - /* Translators: %s is the search term. */ - $pinning_button = sprintf( '', $post->ID, $token, sprintf( __( "Unpin for '%s'", 'relevanssi' ), $token ) ); - $pinning_buttons[] = $pinning_button; - } - } - $pinning_buttons = implode( ' ', $pinning_buttons ); - - return array( $pinning_buttons, $pinned ); -} diff --git a/relevanssi-premium/premium/post-metabox.php b/relevanssi-premium/premium/post-metabox.php deleted file mode 100644 index 71bf222e..00000000 --- a/relevanssi-premium/premium/post-metabox.php +++ /dev/null @@ -1,607 +0,0 @@ -post_type, $indexed_post_types, true ) ) { - return; - } - add_meta_box( - 'relevanssi_hidebox', - __( 'Relevanssi', 'relevanssi' ), - 'relevanssi_post_metabox', - array( $post->post_type, 'edit-category' ), - 'side', - 'default', - array( '__back_compat_meta_box' => true ) - ); - add_thickbox(); // Make sure Thickbox is enabled. -} - -/** - * Prints out the Relevanssi Post Controls meta box. - * - * Prints out the Relevanssi Post Controls meta box that is displayed on the post edit pages. - * - * @global array $relevanssi_variables The Relevanssi global variables array, used to get the file name for nonce. - * @global object $post The global post object. - */ -function relevanssi_post_metabox() { - global $relevanssi_variables, $post; - wp_nonce_field( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_hidepost' ); - - $hide_post = checked( 'on', get_post_meta( $post->ID, '_relevanssi_hide_post', true ), false ); - $hide_content = checked( 'on', get_post_meta( $post->ID, '_relevanssi_hide_content', true ), false ); - $pin_for_all = checked( 'on', get_post_meta( $post->ID, '_relevanssi_pin_for_all', true ), false ); - - $pins = get_post_meta( $post->ID, '_relevanssi_pin', false ); - $pin_weights = get_post_meta( $post->ID, '_relevanssi_pin_weights', true ); - $weighted_pins = array(); - foreach ( $pins as $pin ) { - if ( isset( $pin_weights[ $pin ] ) ) { - $pin .= ' (' . $pin_weights[ $pin ] . ')'; - } - $weighted_pins[] = $pin; - } - $pin = implode( ', ', $weighted_pins ); - - $unpins = get_post_meta( $post->ID, '_relevanssi_unpin', false ); - $unpin = implode( ', ', $unpins ); - - // The actual fields for data entry. - ?> - - -

    - -

    -

    - - - -

    - - -

    - - -

    /> -

    - -

    -

    - - - -

    /> -

    - -

    /> -

    - - ID ); - } - - $display = false; - $element = relevanssi_generate_how_relevanssi_sees( $post->ID, $display ); - echo $element; // phpcs:ignore WordPress.Security.EscapeOutput -} - -/** - * Saves the Relevanssi Gutenberg sidebar meta data. - * - * When a post is saved in Gutenberg, this function saves the Relevanssi - * sidebar meta data. - * - * @param object $post The post object. - */ -function relevanssi_save_gutenberg_postdata( $post ) { - // Verify if this is an auto save routine. - // If it is, our form has not been submitted, so we dont want to do anything. - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { - return; - } - - // Check nonce here? - - $keywords = get_post_meta( $post->ID, '_relevanssi_pin_keywords', true ); - relevanssi_update_pin_fields( $post->ID, $keywords ); - - $keywords = get_post_meta( $post->ID, '_relevanssi_unpin_keywords', true ); - relevanssi_update_unpin_fields( $post->ID, $keywords ); -} - -/** - * Updates the _relevanssi_pin custom fields based on a list of keywords. - * - * @param int $post_id The post ID. - * @param string $keywords The keywords. - */ -function relevanssi_update_pin_fields( $post_id, $keywords ) { - $pin_weights = array(); - if ( $keywords ) { - delete_post_meta( $post_id, '_relevanssi_pin' ); - $pins = explode( ',', sanitize_text_field( wp_unslash( $keywords ) ) ); - foreach ( $pins as $pin ) { - list( $pin, $weight ) = array_pad( explode( '(', $pin, 2 ), 2, '1' ); - - $weight = str_replace( ')', '', $weight ); - $weight = intval( $weight ); - if ( $weight < 1 ) { - $weight = 1; - } - $pin = trim( $pin ); - - if ( $weight > 1 ) { - $pin_weights[ $pin ] = $weight; - } - - if ( ! empty( $pin ) ) { - add_post_meta( $post_id, '_relevanssi_pin', $pin ); - } - } - } else { - delete_post_meta( $post_id, '_relevanssi_pin' ); - } - if ( ! empty( $pin_weights ) ) { - update_post_meta( $post_id, '_relevanssi_pin_weights', $pin_weights ); - } else { - delete_post_meta( $post_id, '_relevanssi_pin_weights' ); - } -} - -/** - * Updates the _relevanssi_unpin custom fields based on a list of keywords. - * - * @param int $post_id The post ID. - * @param string $keywords The keywords. - */ -function relevanssi_update_unpin_fields( $post_id, $keywords ) { - if ( $keywords ) { - delete_post_meta( $post_id, '_relevanssi_unpin' ); - $pins = explode( ',', sanitize_text_field( wp_unslash( $keywords ) ) ); - foreach ( $pins as $pin ) { - $pin = trim( $pin ); - if ( ! empty( $pin ) ) { - add_post_meta( $post_id, '_relevanssi_unpin', $pin ); - } - } - } else { - delete_post_meta( $post_id, '_relevanssi_unpin' ); - } -} - -/** - * Saves Relevanssi metabox data. - * - * When a post is saved in the Classic Editor, this function saves the - * Relevanssi Post Controls metabox data. - * - * @param int $post_id The post ID that is being saved. - */ -function relevanssi_save_postdata( $post_id ) { - global $relevanssi_variables; - // Verify if this is an auto save routine. If it is, our form has not been - // submitted, so we dont want to do anything. - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { - return; - } - - // Verify the nonce. - if ( isset( $_POST['relevanssi_hidepost'] ) ) { // WPCS: input var okey. - if ( ! wp_verify_nonce( - sanitize_key( $_POST['relevanssi_hidepost'] ), - plugin_basename( $relevanssi_variables['file'] ) - ) - ) { // WPCS: input var okey. - return; - } - } - - $post = $_POST; // WPCS: input var okey. - - // If relevanssi_metabox is not set, it's a quick edit. - if ( ! isset( $post['relevanssi_metabox'] ) ) { - return; - } - - // Check permissions. - if ( isset( $post['post_type'] ) ) { - if ( 'page' === $post['post_type'] ) { - if ( ! current_user_can( 'edit_page', $post_id ) ) { - return; - } - } elseif ( ! current_user_can( 'edit_post', $post_id ) ) { - return; - } - } - - $hide = ''; - if ( isset( $post['relevanssi_hide_post'] ) && 'on' === $post['relevanssi_hide_post'] ) { - $hide = 'on'; - } - - if ( 'on' === $hide ) { - // Post is marked hidden, so remove it from the index. - relevanssi_remove_doc( $post_id ); - } - - if ( 'on' === $hide ) { - update_post_meta( $post_id, '_relevanssi_hide_post', $hide ); - } else { - delete_post_meta( $post_id, '_relevanssi_hide_post' ); - } - - $hide_content = ''; - if ( isset( $post['relevanssi_hide_content'] ) && 'on' === $post['relevanssi_hide_content'] ) { - $hide_content = 'on'; - } - - if ( 'on' === $hide_content ) { - update_post_meta( $post_id, '_relevanssi_hide_content', $hide_content ); - } else { - delete_post_meta( $post_id, '_relevanssi_hide_content' ); - } - - $pin_for_all = ''; - if ( isset( $post['relevanssi_pin_for_all'] ) && 'on' === $post['relevanssi_pin_for_all'] ) { - $pin_for_all = 'on'; - } - - if ( 'on' === $pin_for_all ) { - update_post_meta( $post_id, '_relevanssi_pin_for_all', $pin_for_all ); - } else { - delete_post_meta( $post_id, '_relevanssi_pin_for_all' ); - } - - if ( isset( $post['relevanssi_pin'] ) ) { - relevanssi_update_pin_fields( $post_id, $post['relevanssi_pin'] ); - } else { - delete_post_meta( $post_id, '_relevanssi_pin' ); - } - - if ( isset( $post['relevanssi_unpin'] ) ) { - delete_post_meta( $post_id, '_relevanssi_unpin' ); - $pins = explode( ',', sanitize_text_field( wp_unslash( $post['relevanssi_unpin'] ) ) ); - foreach ( $pins as $pin ) { - $pin = trim( $pin ); - if ( ! empty( $pin ) ) { - add_post_meta( $post_id, '_relevanssi_unpin', $pin ); - } - } - } else { - delete_post_meta( $post_id, '_relevanssi_unpin' ); - } - - $no_append = ''; - if ( isset( $post['relevanssi_related_no_append'] ) && 'on' === $post['relevanssi_related_no_append'] ) { - $no_append = 'on'; - } - - if ( 'on' === $no_append ) { - update_post_meta( $post_id, '_relevanssi_related_no_append', $no_append ); - } else { - delete_post_meta( $post_id, '_relevanssi_related_no_append' ); - } - - $not_related = ''; - if ( isset( $post['relevanssi_related_not_related'] ) && 'on' === $post['relevanssi_related_not_related'] ) { - $not_related = 'on'; - } - - if ( 'on' === $not_related ) { - update_post_meta( $post_id, '_relevanssi_related_not_related', $not_related ); - } else { - delete_post_meta( $post_id, '_relevanssi_related_not_related' ); - } - - if ( isset( $post['relevanssi_related_keywords'] ) ) { - delete_post_meta( $post_id, '_relevanssi_related_keywords' ); - $keywords = sanitize_text_field( $post['relevanssi_related_keywords'] ); - if ( $keywords ) { - add_post_meta( $post_id, '_relevanssi_related_keywords', $keywords ); - } - } else { - delete_post_meta( $post_id, '_relevanssi_related_keywords' ); - } - - if ( isset( $post['relevanssi_related_include_ids'] ) ) { - delete_post_meta( $post_id, '_relevanssi_related_include_ids' ); - $include_ids_array = explode( ',', $post['relevanssi_related_include_ids'] ); - $valid_ids = array(); - foreach ( $include_ids_array as $id ) { - $id = (int) trim( $id ); - if ( is_int( $id ) ) { - if ( get_post( $id ) ) { - $valid_ids[] = $id; - } - } - } - if ( ! empty( $valid_ids ) ) { - $id_string = implode( ',', $valid_ids ); - add_post_meta( $post_id, '_relevanssi_related_include_ids', $id_string ); - } - } else { - delete_post_meta( $post_id, '_relevanssi_related_include_ids' ); - } - - // Clear the related posts cache for this post. - delete_post_meta( $post_id, '_relevanssi_related_posts' ); -} - -/** - * Prints out the metabox part for related posts. - * - * @param int $post_id The post ID. - */ -function relevanssi_related_posts_metabox( $post_id ) { - $related = get_post_meta( $post_id, '_relevanssi_related_keywords', true ); - $include_ids = get_post_meta( $post_id, '_relevanssi_related_include_ids', true ); - $no_append = checked( 'on', get_post_meta( $post_id, '_relevanssi_related_no_append', true ), false ); - $not_related = checked( 'on', get_post_meta( $post_id, '_relevanssi_related_not_related', true ), false ); - - if ( '0' === $include_ids ) { - $include_ids = ''; - } - ?> -

    - -

    - -

    - -

    -

    - -

    - -

    :

    -

    - -

    - - - - -

    :

    -
      - -
    - -

    -

    The most common search terms for this post:

    -
      - -
    - -

    Low-ranking search terms for this post:

    -
      - -
    - get_results( - $wpdb->prepare( - "SELECT DISTINCT(query), COUNT(*) AS `count` FROM $table" . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - ' WHERE post_id = %d - GROUP BY query - ORDER BY count DESC - LIMIT 5', - $post_id - ) - ); - - if ( $common_terms ) { - if ( $output_html ) { - $list = '
  • ' . implode( - '
  • ', - array_map( - function ( $v ) { - return "$v->query ($v->count)"; - }, - $common_terms - ) - ) . '
  • '; - } else { - $list = $common_terms; - } - } - - return $list; -} - -/** - * Generates tracking insights. - * - * @param int $post_id The post ID. - * @param string $output If 'HTML', output HTML code. If 'ARRAY', output an - * array. Default value is 'HTML'. - */ -function relevanssi_generate_tracking_insights_low_ranking( int $post_id, string $output = 'HTML' ) { - global $wpdb, $relevanssi_variables; - $table = $relevanssi_variables['tracking_table']; - - $output_html = 'ARRAY' !== $output ? true : false; - if ( $output_html ) { - $list = ''; - } else { - $list = array(); - } - - $low_ranking_terms = $wpdb->get_results( - $wpdb->prepare( - "SELECT `query`, `rank` FROM $table" . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - ' WHERE post_id = %d - AND `rank` > 1 - ORDER BY `rank` DESC - LIMIT 5', - $post_id - ) - ); - - if ( $low_ranking_terms ) { - if ( $output_html ) { - $list = '
  • ' . implode( - '
  • ', - array_map( - function ( $v ) { - return "$v->query ($v->rank)"; - }, - $low_ranking_terms - ) - ) . '
  • '; - } else { - $list = $low_ranking_terms; - } - } - - return $list; -} - -/** - * Generates a list of related posts for the related posts metabox. - * - * @param int $post_id The post ID. - * @param string $output If 'HTML', output HTML code. If 'ARRAY', output an - * array. Default value is 'HTML'. - */ -function relevanssi_generate_related_list( $post_id, $output = 'HTML' ) { - $output_html = 'ARRAY' !== $output ? true : false; - if ( $output_html ) { - $list = ''; - } else { - $list = array(); - } - $related_posts = relevanssi_get_related_post_ids( $post_id ); - foreach ( $related_posts as $related_post_id ) { - $title = get_the_title( $related_post_id ); - $link = get_permalink( $related_post_id ); - if ( $output_html ) { - $list .= '
  • ' - . esc_html( $title ) . ' ' - . '()
  • '; - } else { - $list[] = array( - 'id' => $related_post_id, - 'title' => $title, - 'link' => $link, - ); - } - } - return $list; -} - -/** - * Generates a list of excluded posts for the related posts metabox. - * - * @param int $post_id The post ID. - * @param string $output If 'HTML', output HTML code. If 'ARRAY', output an - * array. Default value is 'HTML'. - */ -function relevanssi_generate_excluded_list( $post_id, $output = 'HTML' ) { - $output_html = 'ARRAY' !== $output ? true : false; - if ( $output_html ) { - $list = ''; - } else { - $list = array(); - } - $excluded_posts = get_post_meta( $post_id, '_relevanssi_related_exclude_ids', true ); - if ( $excluded_posts ) { - $excluded_array = explode( ',', $excluded_posts ); - foreach ( $excluded_array as $excluded_post_id ) { - $title = get_the_title( $excluded_post_id ); - $link = get_permalink( $excluded_post_id ); - if ( $output_html ) { - $list .= '
  • ' . esc_html( $title ) . ' ()
  • '; - } else { - $list[] = array( - 'id' => $excluded_post_id, - 'title' => $title, - 'link' => $link, - ); - } - } - } elseif ( $output_html ) { - $list .= '
  • ' . esc_html__( 'Nothing excluded.', 'relevanssi' ) . '
  • '; - } - return $list; -} diff --git a/relevanssi-premium/premium/proximity.php b/relevanssi-premium/premium/proximity.php deleted file mode 100644 index 351d27c8..00000000 --- a/relevanssi-premium/premium/proximity.php +++ /dev/null @@ -1,189 +0,0 @@ - weight pairs. This function - * ignores the weight and only cares about the post ID. - * - * @return array The $doc_weight array untouched. - */ -function relevanssi_add_distance( $doc_weight ) { - global $relevanssi_coordinates; - - /** - * Filters the comparison coordinates Relevanssi uses. - * - * @param string The coordinates in "latitude, longitude" format. - */ - $compare_coordinates = apply_filters( - 'relevanssi_proximity_comparison', - $relevanssi_coordinates // // phpcs:ignore WordPress.Security.NonceVerification - ); - - if ( ! $compare_coordinates ) { - return $doc_weight; - } - - list( $latitude_from, $longitude_from ) = explode( ',', $compare_coordinates ); - - $latitude_from = floatval( $latitude_from ); - $longitude_from = floatval( $longitude_from ); - - global $relevanssi_distance; - $relevanssi_distance = array(); - - foreach ( array_keys( $doc_weight ) as $post_id ) { - /** - * Filters the coordinates for each post. - * - * @param string The coordinates. - * @param int The post ID. - */ - $hit_coordinates = apply_filters( - 'relevanssi_proximity_coordinates', - '', - $post_id - ); - if ( ! $hit_coordinates ) { - /** - * Filters the default distance for posts without coordinates. - * - * @param int The default distance, default PHP_INT_MAX. - */ - $default_distance = apply_filters( - 'relevanssi_proximity_default_distance', - PHP_INT_MAX - ); - $relevanssi_distance[ $post_id ] = $default_distance; - } - - list( $latitude_to, $longitude_to ) = explode( ',', $hit_coordinates ); - - $latitude_to = floatval( $latitude_to ); - $longitude_to = floatval( $longitude_to ); - - $distance = relevanssi_get_distance( - $latitude_from, - $longitude_from, - $latitude_to, - $longitude_to - ); - - $relevanssi_distance[ $post_id ] = $distance; - } - - return $doc_weight; -} - -/** - * Calculates the great-circle distance between two points. - * - * Uses the Haversine formula. - * - * @param float $latitude_from Latitude of start point in [deg decimal]. - * @param float $longitude_from Longitude of start point in [deg decimal]. - * @param float $latitude_to Latitude of target point in [deg decimal]. - * @param float $longitude_to Longitude of target point in [deg decimal]. - * - * @return float Distance between points in kilometers. - */ -function relevanssi_get_distance( float $latitude_from, float $longitude_from, float $latitude_to, float $longitude_to ): float { - $earth_radius = 6371; - - $lat_from = deg2rad( $latitude_from ); - $lon_from = deg2rad( $longitude_from ); - $lat_to = deg2rad( $latitude_to ); - $lon_to = deg2rad( $longitude_to ); - - $lat_delta = $lat_to - $lat_from; - $lon_delta = $lon_to - $lon_from; - - $angle = 2 * asin( - sqrt( - pow( sin( $lat_delta / 2 ), 2 ) - + cos( $lat_from ) * cos( $lat_to ) - * pow( sin( $lon_delta / 2 ), 2 ) - ) - ); - - return $angle * $earth_radius; -} - -/** - * Returns the distances for compared posts. - * - * Gets the distances from the $relevanssi_distance global array. - * - * @param object $post_a The first post object. - * @param object $post_b The second post object. - * - * @return array Array containing the distance to post A and to post B. Default - * value is 0. - */ -function relevanssi_get_proximity_values( $post_a, $post_b ) { - global $relevanssi_distance; - - $distance_to_a = $relevanssi_distance[ $post_a->ID ] ?? 0; - $distance_to_b = $relevanssi_distance[ $post_b->ID ] ?? 0; - return array( $distance_to_a, $distance_to_b ); -} - -/** - * Takes the 'coordinates' query variable and stores it to a global variable. - * - * Stores the comparison coordinates from the 'coordinates' query variable in - * the $relevanssi_coordinates global variable, because that is the easiest way - * to access that data in the relevanssi_add_distance() function. - * - * @see relevanssi_add_distance(). - * - * @param array $params The search parameters; ignored. - * @param WP_Query $query The query object. - * - * @return array The search parameters untouched. - */ -function relevanssi_pick_up_coordinates( $params, $query ) { - global $relevanssi_coordinates; - $relevanssi_coordinates = $query->query_vars['coordinates']; - return $params; -} diff --git a/relevanssi-premium/premium/redirects.php b/relevanssi-premium/premium/redirects.php deleted file mode 100644 index 6bb60590..00000000 --- a/relevanssi-premium/premium/redirects.php +++ /dev/null @@ -1,216 +0,0 @@ -is_search && ! $url ) { - if ( empty( $query ) && isset( $redirects['no_terms'] ) ) { - $url = $redirects['no_terms']; - } elseif ( 0 === $wp_query->found_posts && isset( $redirects['empty'] ) ) { - $url = $redirects['empty']; - } - } - - if ( $url ) { - if ( wp_redirect( $url ) ) { // phpcs:ignore WordPress.Security.SafeRedirect - exit(); - } - } -} - -/** - * Helper function to update the redirect for the hit counting. - * - * Takes the new redirect, finds the old one by the `query` field and replaces - * the redirect in the option. - * - * @param array $redirect The redirect array to be added to the option. - */ -function relevanssi_update_redirect( $redirect ) { - $redirects = get_option( 'relevanssi_redirects', array() ); - $key = array_search( - $redirect['query'], - array_column( $redirects, 'query' ), - true - ); - - update_option( - 'relevanssi_redirects', - array_replace( $redirects, array( $key => $redirect ) ) - ); -} - -/** - * Makes relatives URLs absolute and validates all URLs. - * - * Uses site_url() to make relative URLs absolute and then passes all URLs - * through wp_http_validate_url(). - * - * @see wp_http_validate_url() - * - * @param string $value A relative or absolute URL to validate. - * - * @return string|false The URL, converted to absolute if necessary, and - * validated. Returns false on failure. - */ -function relevanssi_validate_url( $value ) { - if ( 'http' !== substr( $value, 0, 4 ) ) { - // Relative URL, make absolute. - if ( '/' !== substr( $value, 0, 1 ) ) { - $value = '/' . $value; - } - $value = site_url() . $value; - } - return wp_http_validate_url( $value ); -} - -/** - * Reads the redirects from the request array and validates the URLs. - * - * All relative URLs are converted to absolute URLs for validation and redirects - * with both the query and URL parameters are kept. - * - * @param array $request The options request array. - * - * @return array The redirect array. - * - * @since 2.2.3 - */ -function relevanssi_process_redirects( $request ) { - $redirects = array(); - foreach ( $request as $key => $value ) { - if ( 'redirect_empty_searches' === $key && ! empty( $value ) ) { - $url = relevanssi_validate_url( $value ); - if ( ! empty( $url ) ) { - $redirects['empty'] = $url; - } - } - if ( 'redirect_no_terms' === $key && ! empty( $value ) ) { - $url = relevanssi_validate_url( $value ); - if ( ! empty( $url ) ) { - $redirects['no_terms'] = $url; - } - } - if ( 'query' !== substr( $key, 0, 5 ) ) { - continue; - } - $suffix = substr( $key, 5 ); - $query = stripslashes( relevanssi_strtolower( $value ) ); - $partial = false; - if ( isset( $request[ 'partial' . $suffix ] ) ) { - $partial = true; - } - $url = null; - if ( isset( $request[ 'url' . $suffix ] ) ) { - $url = relevanssi_validate_url( $request[ 'url' . $suffix ] ); - } - $hits = $request[ 'hits' . $suffix ] ?? 0; - if ( ! empty( $url ) && ! empty( $query ) ) { - $redirect = array( - 'query' => $query, - 'partial' => $partial, - 'url' => $url, - 'hits' => $hits, - ); - $redirects[] = $redirect; - } - } - return $redirects; -} - -/** - * Gets the search query for FacetWP searches. - * - * @return string The search query, empty string if nothing is found. - * - * @author Jan Willem Oostendorp - */ -function relevanssi_get_facetwp_query() { - $query = ''; - - if ( ! empty( FWP()->helper->settings['facets'] ) && ! empty( FWP()->request->url_vars ) ) { - $facet_searches = array(); - $url_vars = FWP()->request->url_vars; - foreach ( FWP()->helper->settings['facets'] as $facet ) { - if ( 'search' === $facet['type'] && 'relevanssi' === $facet['search_engine'] && ! empty( $url_vars[ $facet['name'] ] ) ) { - $facet_searches = array_merge( $facet_searches, $url_vars[ $facet['name'] ] ); - } - } - - // If there are multiple search queries we won't even try. - if ( 1 === count( $facet_searches ) ) { - $query = $facet_searches[0]; - } - } - - return strtolower( $query ); -} diff --git a/relevanssi-premium/premium/related.php b/relevanssi-premium/premium/related.php deleted file mode 100644 index 3054cf6a..00000000 --- a/relevanssi-premium/premium/related.php +++ /dev/null @@ -1,763 +0,0 @@ -'; - } - /** - * Filters the related posts output. - * - * @param string The output, ready to be displayed. - */ - return apply_filters( 'relevanssi_related_output', $related ); - } else { - // Post ID custom field returned results, but the transient has - // expired. Let's refresh the custom field as well. - $use_cache = false; - } - } - - $related_posts = relevanssi_get_related_post_ids( $post_id, $use_cache ); - - if ( $just_objects ) { - // Deprecated, remove this functionality eventually. - $related_post_objects = array(); - foreach ( $related_posts as $related_id ) { - array_push( $related_post_objects, get_post( $related_id ) ); - } - set_transient( $transient_name, $related_post_objects, WEEK_IN_SECONDS * 2 ); - } elseif ( ! $no_template ) { - $template = locate_template( 'templates/relevanssi-related.php', false ); - if ( ! $template ) { - $template = $relevanssi_variables['plugin_dir'] . 'premium/templates/relevanssi-related.php'; - } - - ob_start(); - include $template; - $related = ob_get_clean(); - - set_transient( $transient_name, $related, WEEK_IN_SECONDS * 2 ); - } - - /** - * Filters the related posts output. - * - * @param string The output, ready to be displayed. - */ - return apply_filters( 'relevanssi_related_output', $related ); -} - -/** - * Returns related post objects for the specific post. - * - * @param int $post_id The post ID. Default null, in which case global $post - * is used. - * - * @return WP_Post[] An array of WordPress post objects. - */ -function relevanssi_get_related_post_objects( $post_id ) { - if ( ! $post_id ) { - $post_id = get_the_ID(); - if ( ! $post_id ) { - return array(); - } - } - - $settings = get_option( - 'relevanssi_related_settings', - relevanssi_related_default_settings() - ); - - $transient_name = apply_filters( 'relevanssi_related_posts_cache_id', 'relevanssi_related_posts_' . $post_id . '_jo' ); - $use_cache = relevanssi_related_cache_available( $post_id, $settings ); - - if ( $use_cache ) { - $related = get_transient( $transient_name ); - if ( $related ) { - return $related; - } else { - $use_cache = false; - } - } - - $related_posts = relevanssi_get_related_post_ids( $post_id, $use_cache ); - - $related_post_objects = array(); - foreach ( $related_posts as $related_id ) { - array_push( $related_post_objects, get_post( $related_id ) ); - } - set_transient( $transient_name, $related_post_objects, WEEK_IN_SECONDS * 2 ); - - return $related_post_objects; -} - -/** - * Returns true if related post cache is available for the current post. - * - * @param int $post_id The post ID. - * @param array $settings The Relevanssi related posts settings. - * - * @return boolean True, if related post IDs have been cached for the post. - */ -function relevanssi_related_cache_available( $post_id, $settings ) { - $use_cache = true; - /** - * Disables the caching for related posts. Do not use unless you know - * what you are doing. - * - * @param boolean Set true to disable caching. Default false. - */ - if ( apply_filters( 'relevanssi_disable_related_cache', false ) ) { - $use_cache = false; - } elseif ( 'on' !== $settings['cache_for_admins'] && current_user_can( 'manage_options' ) ) { - $use_cache = false; - } else { - // For cache control: if the meta field is empty, cache has been flushed. - $post_ids = get_post_meta( $post_id, '_relevanssi_related_posts', true ); - if ( empty( $post_ids ) ) { - $use_cache = false; - } - } - - return $use_cache; -} - -/** - * Fetches related post IDs. - * - * @param int $post_id The post ID. - * @param boolean $use_cache If false, discard cached results. Default true. - * - * @return int[] An array of related post IDs. - */ -function relevanssi_get_related_post_ids( $post_id, $use_cache = true ) { - global $wpdb; - - $settings = get_option( - 'relevanssi_related_settings', - relevanssi_related_default_settings() - ); - - $related_posts_string = get_post_meta( - $post_id, - '_relevanssi_related_posts', - true - ); - - if ( ! empty( $related_posts_string ) && $use_cache ) { - $related_posts = explode( ',', $related_posts_string ); - return $related_posts; - } - - $post_types = explode( ',', $settings['post_types'] ); - - if ( 'matching_post_type' === $settings['post_types'] || empty( $post_types ) ) { - $post_types = array( get_post_type( $post_id ) ); - } - - /** - * Runs before the related posts searches and can be used to adjust the - * Relevanssi settings. By default disables query logging. - */ - do_action( 'pre_relevanssi_related' ); - - $words = relevanssi_related_generate_keywords( $post_id ); - $related_posts = array(); - - $include_ids = get_post_meta( - $post_id, - '_relevanssi_related_include_ids', - true - ); - if ( $include_ids ) { - $related_posts = explode( ',', $include_ids ); - } - - $exclude_ids = get_post_meta( - $post_id, - '_relevanssi_related_exclude_ids', - true - ); - if ( $exclude_ids ) { - $exclude_ids = explode( ',', $exclude_ids ); - } - if ( ! is_array( $exclude_ids ) ) { - $exclude_ids = array(); - } - $exclude_ids[] = $post_id; // Always exclude the current post. - - // These posts are marked as "not related to anything". - $global_exclude_ids = $wpdb->get_col( - "SELECT post_id FROM $wpdb->postmeta - WHERE meta_key = '_relevanssi_related_not_related' - AND meta_value <> ''" - ); - - $exclude_ids = array_merge( $exclude_ids, $global_exclude_ids ); - $exclude_ids = array_merge( $exclude_ids, $related_posts ); - $exclude_ids = array_keys( array_flip( $exclude_ids ) ); - - $date_query = array(); - if ( isset( $settings['months'] ) && intval( $settings['months'] ) > 0 ) { - $date_query = array( - 'after' => '-' . $settings['months'] . ' months', - ); - } - if ( ! empty( $words ) ) { - $count = count( $related_posts ); - if ( $settings['number'] - $count > 0 ) { - $args = array( - 's' => $words, - 'posts_per_page' => $settings['number'] - $count, - 'post_type' => $post_types, - 'post__not_in' => $exclude_ids, - 'fields' => 'ids', - 'operator' => 'OR', - 'post_status' => 'publish', - ); - if ( $date_query ) { - $args['date_query'] = $date_query; - } - $related_posts_query = new WP_Query(); - $related_posts_query->parse_query( - /** - * Filters the related posts search arguments. - * - * Notice that the defaults vary depending on which related posts - * query is done. Avoid overriding default values; preferably just - * add extra criteria. - * - * @param array The related posts arguments. - * @param string Which query is run. Values include "or", - * "random fill", "random". - */ - apply_filters( - 'relevanssi_related_args', - $args, - 'or' - ) - ); - relevanssi_do_query( $related_posts_query ); - $related_posts = array_merge( $related_posts, $related_posts_query->posts ); - - // There may be null results in the set and those may cause problems - // further down the line. - $related_posts = array_filter( - $related_posts, - function ( $value ) { - return $value; - } - ); - } - } - - /** - * Runs after the related posts searches and can be used to adjust the - * Relevanssi settings. - */ - do_action( 'post_relevanssi_related' ); - - $tax_query = array(); - if ( 'random_cat' === $settings['notenough'] || 'random_cat' === $settings['nothing'] ) { - $cats = get_the_category( $post_id ); - $cat_ids = array_map( - function ( $cat ) { - return $cat->term_id; - }, - $cats - ); - $tax_query = array( - 'relation' => 'OR', - array( - 'taxonomy' => 'category', - 'field' => 'term_id', - 'terms' => $cat_ids, - 'operator' => 'IN', - ), - ); - } - $random_fill = in_array( - $settings['notenough'], - array( 'random', 'random_cat' ), - true - ) ? true : false; - if ( $random_fill && ( null === $related_posts || count( $related_posts ) < $settings['number'] ) ) { - // Not enough results and user wants a random fillup. - if ( null === $related_posts ) { - $related_posts = array(); - } - $count = count( $related_posts ); - - $exclude_ids = array_merge( $exclude_ids, $related_posts ); - $exclude_ids = array_keys( array_flip( $exclude_ids ) ); - - $args = array( - 'posts_per_page' => $settings['number'] - $count, - 'post_type' => $post_types, - 'post__not_in' => $exclude_ids, - 'fields' => 'ids', - 'orderby' => 'rand', - 'post_status' => 'publish', - ); - if ( $date_query ) { - $args['date_query'] = $date_query; - } - if ( 'random_cat' === $settings['notenough'] ) { - $args['tax_query'] = $tax_query; - } - /** Documented in premium/related.php */ - $more_related_posts = new WP_Query( - apply_filters( - 'relevanssi_related_args', - $args, - 'random fill' - ) - ); - $related_posts = array_merge( - $related_posts, - $more_related_posts->posts - ); - } - $all_random = in_array( - $settings['nothing'], - array( 'random', 'random_cat' ), - true - ) ? true : false; - if ( empty( $related_posts ) && $all_random ) { - $query = new WP_Query(); - // No related posts found, user has requested random posts. - $args = array( - 'posts_per_page' => $settings['number'], - 'post_type' => $post_types, - 'post__not_in' => $exclude_ids, - 'fields' => 'ids', - 'orderby' => 'rand', - 'post_status' => 'publish', - ); - if ( $date_query ) { - $args['date_query'] = $date_query; - } - if ( 'random_cat' === $settings['nothing'] ) { - $args['tax_query'] = $tax_query; - } - $query->query( - /** Documented in premium/related.php */ - apply_filters( - 'relevanssi_related_args', - $args, - 'random' - ) - ); - $related_posts = $query->posts; - } - - /* - * Sometimes a thoughtless relevanssi_hits_filter filter function may - * cause the $related_posts array to contain post objects instead of - * post IDs. This step makes sure the array has post IDs. - */ - $related_posts = array_map( - function ( $item ) { - if ( is_object( $item ) && isset( $item->ID ) ) { - return $item->ID; - } else { - return $item; - } - }, - $related_posts - ); - - if ( ! $related_posts ) { - // For some reason nothing was found. - $related_posts = array(); - } - - $related_posts_string = implode( ',', $related_posts ); - update_post_meta( $post_id, '_relevanssi_related_posts', $related_posts_string ); - - return $related_posts; -} - -/** - * Echoes out the related posts. - * - * @param int $post_id The post ID. Default null, in which case global $post is used. - */ -function relevanssi_the_related_posts( $post_id = null ) { - echo relevanssi_related_posts( $post_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -} - -/** - * Returns the related posts for the relevanssi_related_posts shortcode. - * - * @param array $atts The shortcode parameters; only one used is post_id, which - * defaults to null and global $post. - */ -function relevanssi_related_posts_shortcode( $atts ) { - $post_id = null; - if ( isset( $atts['post_id'] ) && is_int( $atts['post_id'] ) ) { - $post_id = $atts['post_id']; - } - return relevanssi_related_posts( $post_id ); -} -add_shortcode( 'relevanssi_related_posts', 'relevanssi_related_posts_shortcode' ); - -/** - * Sets the default settings for related posts. - * - * @return array Array containing the default settings. - */ -function relevanssi_related_default_settings() { - return array( - 'enabled' => 'off', - 'number' => 6, - 'nothing' => 'nothing', - 'notenough' => 'random', - 'post_types' => 'post', - 'keyword' => 'title', - 'append' => '', - 'cache_for_admins' => 'off', - 'months' => 0, - 'restrict' => '', - ); -} - -/** - * Sets the default styles for related posts. - * - * @return array Array containing the default styles. - */ -function relevanssi_related_default_styles() { - return array( - 'width' => 250, - 'titles' => 'on', - 'excerpts' => 'off', - 'thumbnails' => 'on', - 'default_thumbnail' => '', - ); -} - -/** - * A wrapper function to attach the related posts to the_content. - * - * @param string $content The post content. - * - * @return string The post content with the related posts appended. - */ -function relevanssi_related_posts_the_content_wrapper( $content ) { - $settings = get_option( - 'relevanssi_related_settings', - relevanssi_related_default_settings() - ); - $post_types = explode( ',', $settings['append'] ); - if ( is_singular() && in_the_loop() && in_array( get_post_type(), $post_types, true ) ) { - global $post; - if ( 'on' !== get_post_meta( $post->ID, '_relevanssi_related_no_append', true ) ) { - $content .= relevanssi_related_posts(); - } - } - return $content; -} - -/** - * Generates keywords from the post. - * - * @param int $post_id The post ID. - */ -function relevanssi_related_generate_keywords( $post_id ) { - global $wpdb, $relevanssi_variables; - - $settings = get_option( - 'relevanssi_related_settings', - relevanssi_related_default_settings() - ); - $keywords = explode( ',', $settings['keyword'] ); - $restrict = explode( ',', $settings['restrict'] ); - - $title_words = array(); - $tag_words = array(); - $cat_words = array(); - $tax_words = array(); - - foreach ( $keywords as $keyword ) { - if ( empty( $keyword ) ) { - continue; - } - if ( 'title' === $keyword ) { - $title_words = $wpdb->get_col( - $wpdb->prepare( - 'SELECT term FROM ' - . $relevanssi_variables['relevanssi_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE doc = %d AND title > 0', - $post_id - ) - ); - } elseif ( 'post_tag' === $keyword ) { - $tag_words = $wpdb->get_col( - $wpdb->prepare( - 'SELECT term FROM ' - . $relevanssi_variables['relevanssi_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE doc = %d AND tag > 0 ORDER BY tag DESC', - $post_id - ) - ); - } elseif ( 'category' === $keyword ) { - $cat_words = $wpdb->get_col( - $wpdb->prepare( - 'SELECT term FROM ' - . $relevanssi_variables['relevanssi_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE doc = %d AND category > 0 ORDER BY category DESC', - $post_id - ) - ); - } else { - $new_tax_words = $wpdb->get_col( - $wpdb->prepare( - 'SELECT term FROM ' - . $relevanssi_variables['relevanssi_table'] // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - . ' WHERE doc = %d AND taxonomy > 0 AND taxonomy_detail LIKE %s ORDER BY taxonomy DESC', - $post_id, - '%' . $keyword . '%' - ) - ); - $new_tax_words = array_map( - function ( $a ) use ( $keyword ) { - return array( - 'word' => $a, - 'taxonomy' => $keyword, - ); - }, - $new_tax_words - ); - $tax_words = array_merge( $tax_words, $new_tax_words ); - } - } - - $custom_words = get_post_meta( $post_id, '_relevanssi_related_keywords', true ); - if ( $custom_words ) { - $custom_words = explode( ',', $custom_words ); - } else { - $custom_words = array(); - } - - $tax_words = array_map( - function ( $word ) use ( $restrict ) { - return in_array( - $word['taxonomy'], - $restrict, - true - ) ? '{' . $word['taxonomy'] . ':' . $word['word'] . '}' : $word['word']; - }, - $tax_words - ); - if ( in_array( 'post_tag', $restrict, true ) ) { - $tag_words = array_map( - function ( $word ) { - return '{post_tag:' . $word . '}'; - }, - $tag_words - ); - } - if ( in_array( 'category', $restrict, true ) ) { - $cat_words = array_map( - function ( $word ) { - return '{category:' . $word . '}'; - }, - $cat_words - ); - } - - $words = array_merge( - $title_words, - $tag_words, - $cat_words, - $tax_words, - $custom_words - ); - $words = array_keys( array_flip( $words ) ); - - /** - * Filters the source words for related posts. - * - * This filter sees the words right before they are fed into Relevanssi to - * find the related posts. - * - * @param string A space-separated list of keywords for related posts. - * @param int The post ID. - */ - return apply_filters( - 'relevanssi_related_words', - implode( ' ', $words ), - $post_id - ); -} - -/** - * Flushes the related post caches. - * - * Deletes all the _relevanssi_related_posts meta fields. This flushes the - * cache. The actual cache is stored in transients, but we don't have a list of - * all the transient names and one shouldn't simply remove the transients from - * the wp_options database table, because it's possible they're not there. - * - * So, instead of deleting the transients, Relevanssi deletes the meta fields - * which contain a list of post IDs (this is helpful for other uses as well), - * which then forces a cache flush. - * - * @global object $wpdb The WordPress database object. - * - * @param int $clean_id If specified, only remove meta fields that contain this - * ID. Default null, which flushes all caches. - */ -function relevanssi_flush_related_cache( $clean_id = null ) { - global $wpdb; - - if ( is_int( $clean_id ) ) { - $clean_id = '%' . $clean_id . '%'; - $wpdb->query( - $wpdb->prepare( - "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_posts' AND meta_value LIKE %s", - $clean_id - ) - ); - // Not perfect, since this will match also rows where post ID contains the - // wanted ID, but it's an acceptable minor cost for a simple solution. - } else { - $wpdb->query( - "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_posts'" - ); - } -} - -/** - * Flushes the caches when a post is made a draft or deleted. - * - * Called from 'transition_post_status' action hook when a post is made into a draft, - * or deleted. Will flush the related post caches where that post appears. - * - * @global object $wpdb The WP database interface. - * - * @param string $new_status The new status. - * @param string $old_status The old status. - * @param object $post The post object. - */ -function relevanssi_flush_caches_on_transition( $new_status, $old_status, $post ) { - // Safety check, for WordPress Editorial Calendar incompatibility. - if ( ! isset( $post ) || ! isset( $post->ID ) ) { - return; - } - - if ( 'publish' !== $new_status ) { - // The post isn't public anymore. - relevanssi_flush_related_cache( $post->ID ); - } -} - -add_action( 'pre_relevanssi_related', 'relevanssi_pre_related_posts' ); -/** - * Runs before the related posts queries and disables logging. - */ -function relevanssi_pre_related_posts() { - // We don't want to log these queries. - add_filter( 'relevanssi_ok_to_log', '__return_false' ); - add_filter( 'pre_option_relevanssi_searchblogs', '__return_false' ); - add_filter( 'pre_option_relevanssi_searchblogs_all', 'relevanssi_return_off' ); -} - -add_action( 'post_relevanssi_related', 'relevanssi_post_related_posts' ); -/** - * Runs after the related posts queries and enables logging. - */ -function relevanssi_post_related_posts() { - remove_filter( 'relevanssi_ok_to_log', '__return_false' ); - remove_filter( 'pre_option_relevanssi_searchblogs', '__return_false' ); - remove_filter( 'pre_option_relevanssi_searchblogs_all', 'relevanssi_return_off' ); -} diff --git a/relevanssi-premium/premium/search-multi.php b/relevanssi-premium/premium/search-multi.php deleted file mode 100644 index f1291b78..00000000 --- a/relevanssi-premium/premium/search-multi.php +++ /dev/null @@ -1,511 +0,0 @@ - 2000 ) ); // There's likely flaming death with even lower values of 'number'. - $blog_list = array(); - foreach ( $raw_blog_list as $blog ) { - $blog_list[] = $blog->blog_id; - } - $search_blogs = implode( ',', $blog_list ); - } - - $search_blogs = explode( ',', $search_blogs ); - if ( ! is_array( $search_blogs ) ) { - // No blogs to search, so let's quit. - return $hits; - } - - $post_type_weights = get_option( 'relevanssi_post_type_weights' ); - - foreach ( $search_blogs as $blogid ) { - $search_again = false; - - if ( ! relevanssi_is_blog_ok( $blogid ) ) { - continue; - } - - // Ok, we should have a valid blog. - switch_to_blog( $blogid ); - $relevanssi_table = $wpdb->prefix . 'relevanssi'; - - $list_of_tables = $wpdb->get_col( 'SHOW TABLES' ); - if ( ! in_array( $relevanssi_table, $list_of_tables, true ) ) { - restore_current_blog(); - continue; - } - - $query_data = relevanssi_process_multi_query_args( $filtered_args ); - $query_restrictions = $query_data['query_restrictions']; - $query_join = $query_data['query_join']; - $q = $query_data['query_query']; - $q_no_synonyms = $query_data['query_no_synonyms']; - $phrase_queries = $query_data['phrase_queries']; - - if ( 'OR' === $operator ) { - $q = relevanssi_add_synonyms( $q ); - } - - $remove_stopwords = false; - $terms = relevanssi_tokenize( $q, $remove_stopwords, 1, 'search_query' ); - - if ( count( $terms ) < 1 ) { - // Tokenizer killed all the search terms. - restore_current_blog(); - continue; - } - $terms = array_keys( $terms ); // Don't care about tf in query. - - /** - * Filters the query restrictions in Relevanssi. - * - * Approximately the same purpose as the default 'posts_where' filter hook. - * Can be used to add additional query restrictions to the Relevanssi query. - * - * @param string $query_restrictions MySQL added to the Relevanssi query. - * - * @author Charles St-Pierre. - */ - $query_restrictions = apply_filters( 'relevanssi_where', $query_restrictions ); - - // Go get the count from the options, but run the full query if it's not available. - $doc_count = get_option( 'relevanssi_doc_count' ); - if ( ! $doc_count || $doc_count < 1 ) { - $doc_count = relevanssi_update_doc_count(); - } - - $no_matches = true; - $doc_weight = array(); - $term_hits = array(); - - do { - $df_counts = relevanssi_generate_df_counts( - $terms, - array( - 'no_terms' => false, - 'operator' => $operator, - 'phrase_queries' => $phrase_queries, - 'query_join' => $query_join, - 'query_restrictions' => $query_restrictions, - 'search_again' => $search_again, - ) - ); - - foreach ( $df_counts as $term => $df ) { - $this_query_restrictions = relevanssi_add_phrase_restrictions( - $query_restrictions, - $phrase_queries, - $term, - $operator - ); - - $query = relevanssi_generate_search_query( $term, $search_again, false, $query_join, $this_query_restrictions ); - $matches = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared - if ( count( $matches ) < 1 ) { - continue; - } else { - $no_matches = false; - } - - $total_hits += count( $matches ); - - $idf = log( $doc_count / ( 1 + $df ) ); - foreach ( $matches as $match ) { - $match->doc = relevanssi_adjust_match_doc( $match ); - $match->tf = relevanssi_calculate_tf( $match, $post_type_weights ); - $match->weight = relevanssi_calculate_weight( $match, $idf, $post_type_weights, $q ); - - /** - * Documented in /lib/search.php. - */ - $match = apply_filters( 'relevanssi_match', $match, $idf, $term ); - - if ( $match->weight <= 0 ) { - continue; // The filters killed the match. - } - - $post_ok = true; - /** - * Filters whether the user is allowed to see the post. - * - * Can this post be included in the search results? This is the hook - * you’ll use if you want to add support for a membership plugin, for - * example. Based on the post ID, your function needs to return true - * or false. - * - * @param boolean $post_ok Can the post be shown in results? - * @param int $doc The post ID. - */ - $post_ok = apply_filters( 'relevanssi_post_ok', $post_ok, $match->doc ); - if ( ! $post_ok ) { - continue; - } - - relevanssi_update_term_hits( $term_hits, $match_arrays, $match, $term ); - - $doc_id = $blogid . '|' . $match->doc; - - $doc_terms[ $match->doc ][ $term ] = true; // Count how many terms are matched to a doc. - if ( ! isset( $doc_weight[ $doc_id ] ) ) { - $doc_weight[ $match->doc ] = 0; - } - $doc_weight[ $match->doc ] += $match->weight; - } - } - - if ( $no_matches ) { - if ( $search_again ) { - // No hits even with partial matching. - $search_again = false; - } elseif ( 'sometimes' === get_option( 'relevanssi_fuzzy' ) ) { - $search_again = true; - } - } else { - $search_again = false; - } - } while ( $search_again ); - - $strip_stopwords = true; - $terms_without_stops = array_keys( relevanssi_tokenize( implode( ' ', $terms ), $strip_stopwords, -1, 'search_query' ) ); - $total_terms = count( $terms_without_stops ); - - if ( isset( $doc_weight ) ) { - /** - * Filters the results Relevanssi finds for one site in multisite - * search. - * - * This is similar to 'relevanssi_results' in single site searching, - * but only applies to results fetched from one subsite, the ID of - * which can be found in the filter parameters. - * - * @param array $doc_weight An array of (post ID, weight) pairs. - * @param int $blogid The blog ID. - */ - $doc_weight = apply_filters( 'relevanssi_site_results', $doc_weight, $blogid ); - } - - if ( isset( $doc_weight ) && count( $doc_weight ) > 0 && ! $no_matches ) { - arsort( $doc_weight ); - $i = 0; - foreach ( $doc_weight as $doc => $weight ) { - if ( count( $doc_terms[ $doc ] ) < $total_terms && 'AND' === $operator ) { - // AND operator in action: $doc didn't match all terms, so it's discarded. - continue; - } - - $post_object = relevanssi_get_multisite_post( $blogid, $doc ); - $post_object->blog_id = $blogid; - - $object_id = $blogid . '|' . $doc; - $hitsbyweight[ $object_id ] = $weight; - $post_objects[ $object_id ] = $post_object; - } - } - restore_current_blog(); - } - - /** - * Filters all results found in the multisite search. - * - * This is similar to 'relevanssi_results', but is applied to multisite - * searches (where 'relevanssi_results' is not used). This filter hook - * filters an array of ID => weight pairs, where ID is in the format - * '[blog ID]|[post ID]'. - * - * You can also use 'relevanssi_site_results', which is more like the - * original 'relevanssi_results'; it's applied to results from a single - * site. - * - * @param array $hitsbyweight The ID => weight pairs. - */ - $hitsbyweight = apply_filters( 'relevanssi_multi_results', $hitsbyweight ); - arsort( $hitsbyweight ); - - $i = 0; - foreach ( $hitsbyweight as $hit => $weight ) { - $hit = $post_objects[ $hit ]; - $hits[ intval( $i ) ] = $hit; - $hits[ intval( $i ) ]->relevance_score = round( $weight, 2 ); - ++$i; - } - - if ( count( $hits ) < 1 ) { - if ( 'AND' === $operator && 'on' !== get_option( 'relevanssi_disable_or_fallback' ) ) { - $or_args = $multi_args; - $or_args['operator'] = 'OR'; - $return = relevanssi_search_multi( $or_args ); - $hits = $return['hits']; - $match_arrays['body'] = $return['body_matches']; - $match_arrays['title'] = $return['title_matches']; - $match_arrays['tag'] = $return['tag_matches']; - $match_arrays['category'] = $return['category_matches']; - $match_arrays['taxonomy'] = $return['taxonomy_matches']; - $match_arrays['comment'] = $return['comment_matches']; - $match_arrays['link'] = $return['link_matches']; - $match_arrays['author'] = $return['author_matches']; - $match_arrays['customfield'] = $return['customfield_matches']; - $match_arrays['mysqlcolumn'] = $return['mysqlcolumn_matches']; - $match_arrays['excerpt'] = $return['excerpt_matches']; - $term_hits = $return['term_hits']; - $query = $return['query']; - } - } - - relevanssi_sort_results( $hits, $orderby, $order, $meta_query ); - - $return = array( - 'hits' => $hits, - 'body_matches' => $match_arrays['body'], - 'title_matches' => $match_arrays['title'], - 'tag_matches' => $match_arrays['tag'], - 'category_matches' => $match_arrays['category'], - 'comment_matches' => $match_arrays['comment'], - 'taxonomy_matches' => $match_arrays['taxonomy'], - 'link_matches' => $match_arrays['link'], - 'customfield_matches' => $match_arrays['customfield'], - 'mysqlcolumn_matches' => $match_arrays['mysqlcolumn'], - 'author_matches' => $match_arrays['author'], - 'excerpt_matches' => $match_arrays['excerpt'], - 'term_hits' => $term_hits, - 'query' => $q, - 'query_no_synonyms' => $q_no_synonyms, - ); - - return $return; -} - -/** - * Collects the multisite search arguments from the query variables. - * - * @param object $query The WP_Query object that contains the parameters. - * @param string $searchblogs A list of blogs to search, or 'all'. - * @param string $q The search query. - * - * @return array The multisite search parameters. - */ -function relevanssi_compile_multi_args( $query, $searchblogs, $q ) { - $multi_args = relevanssi_compile_common_args( $query ); - - $multi_args['q_no_synonyms'] = $q; - $multi_args['q'] = $q; - - if ( isset( $query->query_vars['searchblogs'] ) ) { - $multi_args['search_blogs'] = $query->query_vars['searchblogs']; - } else { - $multi_args['search_blogs'] = $searchblogs; - } - - $query->query_vars['operator'] = $multi_args['operator']; - - return $multi_args; -} - -/** - * Checks which blogs should be searched. - * - * @param object $query The WP Query object to check for the - * $query->query_vars['searchblogs'] query variable. - * - * @return boolean|string False, if not a multisite search; list of blogs or - * 'all' otherwise. - */ -function relevanssi_is_multisite_search( $query ) { - $searchblogs = false; - $search_multisite = false; - if ( isset( $query->query_vars['searchblogs'] ) - && (string) get_current_blog_id() !== $query->query_vars['searchblogs'] ) { - $search_multisite = true; - $searchblogs = $query->query_vars['searchblogs']; - } - - if ( ! isset( $query->query_vars['searchblogs'] ) && ! $search_multisite ) { - // Is searching all blogs enabled? - $searchblogs_all = get_option( 'relevanssi_searchblogs_all', 'off' ); - if ( 'off' === $searchblogs_all ) { - $searchblogs_all = false; - } - if ( $searchblogs_all ) { - $search_multisite = true; - $searchblogs = 'all'; - } - } - - if ( ! isset( $query->query_vars['searchblogs'] ) && ! $search_multisite ) { - // Searchblogs is not set from the query variables, check the option. - $searchblogs_setting = get_option( 'relevanssi_searchblogs' ); - if ( $searchblogs_setting ) { - $search_multisite = true; - $searchblogs = $searchblogs_setting; - } - } - return $searchblogs; -} - -/** - * Checks to see if a blog is good to use. - * - * Blog must exist, it has to be public and not archived, spam or deleted. The - * filter hook `relevanssi_multisite_public_status` can be used to allow - * Relevanssi to search non-public blogs. - * - * @param int $blogid The blog ID. - * - * @return bool True, if blog is public. - */ -function relevanssi_is_blog_ok( $blogid ): bool { - // Only search blogs that are publicly available (unless filter says otherwise). - $public_status = (bool) get_blog_status( $blogid, 'public' ); - if ( null === $public_status ) { - // Blog doesn't actually exist. - return false; - } - - /** - * Adjusts the possible values of blog public status. - * - * By default Relevanssi requires blogs to be public so they can be searched. - * If you want a non-public blog in the search results, make this filter - * return true. - * - * @param boolean $public_status Is the blog public? - * @param int $blogid Blog ID. - */ - if ( false === apply_filters( 'relevanssi_multisite_public_status', $public_status, $blogid ) ) { - return false; - } - - // Don't search blogs that are marked "archived", "spam" or "deleted". - if ( get_blog_status( $blogid, 'archived' ) ) { - return false; - } - if ( get_blog_status( $blogid, 'spam' ) ) { - return false; - } - if ( get_blog_status( $blogid, 'delete' ) ) { - return false; - } - return true; -} - -/** - * Processes the arguments to create the query restrictions for multisite - * searches. - * - * All individual parts are tested. - * - * @param array $args The query arguments. - * - * @return array An array containing `query_restriction` and `query_join`. - */ -function relevanssi_process_multi_query_args( $args ) { - $query_restrictions = ''; - $query_join = ''; - $query = ''; - $query_no_synonyms = ''; - - $phrase_query_restrictions = array( - 'and' => '', - 'or' => array(), - ); - - if ( function_exists( 'wp_encode_emoji' ) ) { - $query = wp_encode_emoji( $args['q'] ); - $query_no_synonyms = wp_encode_emoji( $args['q_no_synonyms'] ); - } - - if ( $args['sentence'] ) { - $query = relevanssi_remove_quotes( $query ); - $query = '"' . $query . '"'; - } - - if ( is_array( $args['meta_query'] ) ) { - $processed_meta = relevanssi_process_meta_query( $args['meta_query'] ); - $query_restrictions .= $processed_meta['where']; - $query_join .= $processed_meta['join']; - } - - if ( $args['date_query'] instanceof WP_Date_Query ) { - $query_restrictions .= relevanssi_process_date_query( $args['date_query'] ); - } - - if ( $args['by_date'] ) { - $query_restrictions .= relevanssi_process_by_date( $args['by_date'] ); - } - - $phrases = relevanssi_recognize_phrases( $query, $args['operator'] ); - if ( $phrases ) { - $phrase_query_restrictions = $phrases; - } - - $query_restrictions .= relevanssi_process_post_type( - $args['post_type'], - $args['admin_search'], - $args['include_attachments'] - ); - - if ( $args['post_status'] ) { - $query_restrictions .= relevanssi_process_post_status( $args['post_status'] ); - } - - return array( - 'query_restrictions' => $query_restrictions, - 'query_join' => $query_join, - 'query_query' => $query, - 'query_no_synonyms' => $query_no_synonyms, - 'phrase_queries' => $phrase_query_restrictions, - ); -} diff --git a/relevanssi-premium/premium/search.php b/relevanssi-premium/premium/search.php deleted file mode 100644 index 397c95b3..00000000 --- a/relevanssi-premium/premium/search.php +++ /dev/null @@ -1,244 +0,0 @@ - $recency_bonus, - 'cutoff' => $recency_cutoff_date, - ); -} - -/** - * Introduces the query variables for Relevanssi Premium. - * - * @param array $qv The WordPress query variable array. - */ -function relevanssi_premium_query_vars( $qv ) { - $qv[] = 'searchblogs'; - $qv[] = 'customfield_key'; - $qv[] = 'customfield_value'; - $qv[] = 'operator'; - $qv[] = 'include_attachments'; - $qv[] = 'coordinates'; - return $qv; -} - -/** - * Sets the operator parameter. - * - * The operator parameter is taken from $query->query_vars['operator'], - * or from the implicit operator setting. - * - * @param object $query The query object. - */ -function relevanssi_set_operator( $query ) { - if ( isset( $query->query_vars['operator'] ) ) { - $operator = $query->query_vars['operator']; - } else { - $operator = get_option( 'relevanssi_implicit_operator' ); - } - return $operator; -} - -/** - * Processes the negative and positive terms (ie. local AND and NOT operators). - * - * If negative terms are present, will remove them from the $terms array. If negative - * or positive terms are present, will return the query restrictions MySQL for them. - * - * @param array $terms An array of search terms. - * @param array $original_terms An array of unstemmed search terms. - * @param string $query The search query as a string. - * - * @return array An array containing the updated terms and the query restrictions. - */ -function relevanssi_process_terms( $terms, $original_terms, $query ) { - $negative_terms = relevanssi_recognize_negatives( $query ); - $positive_terms = relevanssi_recognize_positives( $query ); - - if ( $negative_terms ) { - $terms = array_diff( $terms, $negative_terms ); - $original_terms = array_diff( $original_terms, $negative_terms ); - } - - // Clean: escaped in the function. - $query_restrictions = relevanssi_negatives_positives( $negative_terms, $positive_terms ); - - return array( - 'terms' => $terms, - 'original_terms' => $original_terms, - 'query_restrictions' => $query_restrictions, - ); -} - -/** - * Replaces the wildcards (?, *) with strings to let them pass intact. - * - * The wildcards are only allowed inside words, so they must have a word - * character on both sides of them. - * - * @param string $str The query or content string to modify. - * - * @return string The parameter string modified. - */ -function relevanssi_wildcards_pre( $str ) { - /** - * If true, enables wildcard operators (*, ?). - * - * @param boolean If true, enable wildcard operator. Default false. - */ - if ( apply_filters( 'relevanssi_wildcard_search', false ) ) { - $str = preg_replace( '/(\w)\?(\w)/', '\1SINGLEWILDCARDSYMBOL\2', $str ); - $str = preg_replace( '/(\w)\*(\w)/', '\1MULTIWILDCARDSYMBOL\2', $str ); - } - return $str; -} - -/** - * Replaces the wildcard strings with wildcards (?, *). - * - * @param string $str The query or content string to modify. - * - * @return string The parameter string modified. - */ -function relevanssi_wildcards_post( $str ) { - /** - * Documented in /premium/search.php. - */ - if ( apply_filters( 'relevanssi_wildcard_search', false ) ) { - $str = preg_replace( '/SINGLEWILDCARDSYMBOL/', '?', $str ); - $str = preg_replace( '/MULTIWILDCARDSYMBOL/', '*', $str ); - } - return $str; -} - -/** - * Replaces the wildcards (?, *) with their MySQL equivalents (_, %). - * - * The ? is converted to _ (single character), while * is converted to % - * (zero or more). Hooks to the relevanssi_term_where filter hook to only - * apply this to the term WHERE condition part of the query. - * - * @see relevanssi_term_where - * - * @param string $query MySQL query to modify. - * @param string $term The search term. - * - * @return string The modified MySQL query. - */ -function relevanssi_query_wildcards( $query, $term ) { - /** - * Documented in /premium/search.php. - */ - if ( apply_filters( 'relevanssi_wildcard_search', false ) ) { - $query = str_replace( "= '$term'", "LIKE '$term'", $query ); - $query = str_replace( array( '?', '*' ), array( '_', '%' ), $query ); - } - return $query; -} diff --git a/relevanssi-premium/premium/spamblock.php b/relevanssi-premium/premium/spamblock.php deleted file mode 100644 index 80366678..00000000 --- a/relevanssi-premium/premium/spamblock.php +++ /dev/null @@ -1,139 +0,0 @@ - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -

    - -

    - - - - - - - - -

    - -

    - -

    - -

    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - | - -
    -
    0
    - - -
    - | - -
    -
    - - /> - - - - - - -
    - - - -

    - -

    - -

    - - -

    wp relevanssi regenerate_related' ); ?>

    - -

    - - - - - - - - - - - - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - -

    - -

    - ' . esc_html( $relevanssi_variables['plugin_dir'] ) . 'premium/templates/relevanssi-related.php', '' . esc_html( get_stylesheet_directory() ) . '/templates/' ); - ?> -

    - - - - - - - - - - - - > - - - - - - - - - - - - - - - -

    - -

    - - - - - - - - - - - - - - - - -

    - -

    - -

    - ?s=', - '/search/', - 'relevanssi_search_url_prefix', - 'highlight' - ); - ?> -

    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - -

    - -

    -add_action( 'do_robots', 'rlv_block_bots_robots_txt' );
    -function rlv_block_bots_robots_txt() {
    -	?>
    -User-agent: *
    -Disallow: /search/
    -Disallow: /?s=
    -	<?php
    -}
    -

    - -

    - -

    - - - get_remote_license(); - - ?> -

    - -

    - -

    - ', - '', - '' . esc_html( $support_email ) . '' - ); - ?> -

    - -

    - ', '' ); - ?> -

    - -

    - -

    - -
    - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    -

    -
    - -
    -

    -
    - - - - 0 ) { - $width = $style['width']; - } - - ?> - - posts ). diff --git a/relevanssi-premium/premium/uninstall.php b/relevanssi-premium/premium/uninstall.php deleted file mode 100644 index 81a3e346..00000000 --- a/relevanssi-premium/premium/uninstall.php +++ /dev/null @@ -1,159 +0,0 @@ -query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_content'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pin_for_all'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pin'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pin_weights'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_unpin'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pdf_content'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pdf_error'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_pdf_modified'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_keywords'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_posts'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_include_ids'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_exclude_ids'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_no_append'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_related_not_related'" ); - $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_noindex_reason'" ); - - // Unused options, removed in case they are still left. - delete_option( 'relevanssi_cache_seconds' ); - delete_option( 'relevanssi_custom_types' ); - delete_option( 'relevanssi_enable_cache' ); - delete_option( 'relevanssi_hidesponsor' ); - delete_option( 'relevanssi_index_attachments' ); - delete_option( 'relevanssi_index_drafts' ); - delete_option( 'relevanssi_index_limit' ); - delete_option( 'relevanssi_index_type' ); - delete_option( 'relevanssi_show_matches_txt' ); - delete_option( 'relevanssi_tag_boost' ); - delete_option( 'relevanssi_include_cats' ); - delete_option( 'relevanssi_include_tags' ); - delete_option( 'relevanssi_custom_taxonomies' ); - delete_option( 'relevanssi_taxonomies_to_index' ); - delete_option( 'relevanssi_highlight_docs_external' ); - delete_option( 'relevanssi_word_boundaries' ); - - if ( ! defined( 'UNINSTALLING_RELEVANSSI_PREMIUM' ) ) { - // The if clause is required to avoid nagging from testing. - define( 'UNINSTALLING_RELEVANSSI_PREMIUM', true ); - } - - wp_clear_scheduled_hook( 'relevanssi_update_counts' ); - - relevanssi_drop_database_tables(); -} diff --git a/relevanssi-premium/readme.txt b/relevanssi-premium/readme.txt deleted file mode 100644 index e6880ac9..00000000 --- a/relevanssi-premium/readme.txt +++ /dev/null @@ -1,437 +0,0 @@ -=== Relevanssi Premium - A Better Search === -Contributors: msaari -Donate link: https://www.relevanssi.com/ -Tags: search, relevance, better search -Requires at least: 4.9 -Requires PHP: 7.0 -Tested up to: 6.5 -Stable tag: 2.25.2 - -Relevanssi Premium replaces the default search with a partial-match search that sorts results by relevance. It also indexes comments and shortcode content. - -== Description == - -Relevanssi replaces the standard WordPress search with a better search engine, with lots of features and configurable options. You'll get better results, better presentation of results - your users will thank you. - -= Key features = -* Search results sorted in the order of relevance, not by date. -* Fuzzy matching: match partial words, if complete words don't match. -* Find documents matching either just one search term (OR query) or require all words to appear (AND query). -* Search for phrases with quotes, for example "search phrase". -* Create custom excerpts that show where the hit was made, with the search terms highlighted. -* Highlight search terms in the documents when user clicks through search results. -* Search comments, tags, categories and custom fields. - -= Advanced features = -* Adjust the weighting for titles, tags and comments. -* Log queries, show most popular queries and recent queries with no hits. -* Restrict searches to categories and tags using a hidden variable or plugin settings. -* Index custom post types and custom taxonomies. -* Index the contents of shortcodes. -* Google-style "Did you mean?" suggestions based on successful user searches. -* Automatic support for [WPML multi-language plugin](http://wpml.org/). -* Automatic support for various membership plugins. -* Advanced filtering to help hacking the search results the way you want. -* Search result throttling to improve performance on large databases. -* Disable indexing of post content and post titles with a simple filter hook. -* Multisite support. - -= Premium features (only in Relevanssi Premium) = -* PDF content indexing. -* Search result throttling to improve performance on large databases. -* Improved spelling correction in "Did you mean?" suggestions. -* Searching over multiple subsites in one multisite installation. -* Indexing and searching user profiles. -* Weights for post types, including custom post types. -* Limit searches with custom fields. -* Index internal links for the target document (sort of what Google does). -* Search using multiple taxonomies at the same time. - -Relevanssi is available in two versions, regular and Premium. Regular Relevanssi is and will remain free to download and use. Relevanssi Premium comes with a cost, but will get all the new features. Standard Relevanssi will be updated to fix bugs, but new features will mostly appear in Premium. Also, support for standard Relevanssi depends very much on my mood and available time. Premium pricing includes support. - -= Other search plugins = -Relevanssi owes a lot to [wpSearch](https://wordpress.org/extend/plugins/wpsearch/) by Kenny Katzgrau. Relevanssi was built to replace wpSearch, when it started to fail. - - -== Installation == - -1. Extract all files from the ZIP file, and then upload the plugin's folder to /wp-content/plugins/. -1. If your blog is in English, skip to the next step. If your blog is in other language, rename the file *stopwords* in the plugin directory as something else or remove it. If there is *stopwords.yourlanguage*, rename it to *stopwords*. -1. Activate the plugin through the 'Plugins' menu in WordPress. -1. Go to the plugin settings and build the index following the instructions there. - -To update your installation, simply overwrite the old files with the new, activate the new version and if the new version has changes in the indexing, rebuild the index. - -= Note on updates = -If it seems the plugin doesn't work after an update, the first thing to try is deactivating and reactivating the plugin. If there are changes in the database structure, those changes do not happen without a deactivation, for some reason. - -= Changes to templates = -None necessary! Relevanssi uses the standard search form and doesn't usually need any changes in the search results template. - -If the search does not bring any results, your theme probably has a query_posts() call in the search results template. That throws Relevanssi off. For more information, see [The most important Relevanssi debugging trick](http://www.relevanssi.com/knowledge-base/query_posts/). - -= How to index = -Check the options to make sure they're to your liking, then click "Save indexing options and build the index". If everything's fine, you'll see the Relevanssi options screen again with a message "Indexing successful!" - -If something fails, usually the result is a blank screen. The most common problem is a timeout: server ran out of time while indexing. The solution to that is simple: just return to Relevanssi screen (do not just try to reload the blank page) and click "Continue indexing". Indexing will continue. Most databases will get indexed in just few clicks of "Continue indexing". You can follow the process in the "State of the Index": if the amount of documents is growing, the indexing is moving along. - -If the indexing gets stuck, something's wrong. I've had trouble with some plugins, for example Flowplayer video player stopped indexing. I had to disable the plugin, index and then activate the plugin again. Try disabling plugins, especially those that use shortcodes, to see if that helps. Relevanssi shows the highest post ID in the index - start troubleshooting from the post or page with the next highest ID. Server error logs may be useful, too. - -= Using custom search results = -If you want to use the custom search results, make sure your search results template uses `the_excerpt()` to display the entries, because the plugin creates the custom snippet by replacing the post excerpt. - -If you're using a plugin that affects excerpts (like Advanced Excerpt), you may run into some problems. For those cases, I've included the function `relevanssi_the_excerpt()`, which you can use instead of `the_excerpt()`. It prints out the excerpt, but doesn't apply `wp_trim_excerpt()` filters (it does apply `the_content()`, `the_excerpt()`, and `get_the_excerpt()` filters). - -To avoid trouble, use the function like this: - -`` - -See Frequently Asked Questions for more instructions on what you can do with Relevanssi. - -= The advanced hacker option = -If you're doing something unusual with your search and Relevanssi doesn't work, try using `relevanssi_do_query()`. See [Knowledge Base](http://www.relevanssi.com/knowledge-base/relevanssi_do_query/). - -= Uninstalling = -To uninstall the plugin remove the plugin using the normal WordPress plugin management tools (from the Plugins page, first Deactivate, then Delete). If you remove the plugin files manually, the database tables and options will remain. - -= Combining with other plugins = -Relevanssi doesn't work with plugins that rely on standard WP search. Those plugins want to access the MySQL queries, for example. That won't do with Relevanssi. [Search Light](http://wordpress.org/extend/plugins/search-light/), for example, won't work with Relevanssi. - -Some plugins cause problems when indexing documents. These are generally plugins that use shortcodes to do something somewhat complicated. One such plugin is [MapPress Easy Google Maps](http://wordpress.org/extend/plugins/mappress-google-maps-for-wordpress/). When indexing, you'll get a white screen. To fix the problem, disable either the offending plugin or shortcode expansion in Relevanssi while indexing. After indexing, you can activate the plugin again. - -== Frequently Asked Questions == - -= Where is the Relevanssi search box widget? = -There is no Relevanssi search box widget. - -Just use the standard search box. - -= Where are the user search logs? = -See the top of the admin menu. There's 'User searches'. There. If the logs are empty, please note showing the results needs at least MySQL 5. - -= Displaying the number of search results found = - -The typical solution to showing the number of search results found does not work with Relevanssi. However, there's a solution that's much easier: the number of search results is stored in a variable within $wp_query. Just add the following code to your search results template: - -`found_posts . ' hits'; ?>` - -= Advanced search result filtering = - -If you want to add extra filters to the search results, you can add them using a hook. Relevanssi searches for results in the _relevanssi table, where terms and post_ids are listed. The various filtering methods work by listing either allowed or forbidden post ids in the query WHERE clause. Using the `relevanssi_where` hook you can add your own restrictions to the WHERE clause. - -These restrictions must be in the general format of ` AND doc IN (' . {a list of post ids, which could be a subquery} . ')` - -For more details, see where the filter is applied in the `relevanssi_search()` function. This is stricly an advanced hacker option for those people who're used to using filters and MySQL WHERE clauses and it is possible to break the search results completely by doing something wrong here. - -There's another filter hook, `relevanssi_hits_filter`, which lets you modify the hits directly. The filter passes an array, where index 0 gives the list of hits in the form of an array of post objects and index 1 has the search query as a string. The filter expects you to return an array containing the array of post objects in index 0 (`return array($your_processed_hit_array)`). - -= Direct access to query engine = -Relevanssi can't be used in any situation, because it checks the presence of search with the `is_search()` function. This causes some unfortunate limitations and reduces the general usability of the plugin. - -You can now access the query engine directly. There's a new function `relevanssi_do_query()`, which can be used to do search queries just about anywhere. The function takes a WP_Query object as a parameter, so you need to store all the search parameters in the object (for example, put the search terms in `$your_query_object->query_vars['s']`). Then just pass the WP_Query object to Relevanssi with `relevanssi_do_query($your_wp_query_object);`. - -Relevanssi will process the query and insert the found posts as `$your_query_object->posts`. The query object is passed as reference and modified directly, so there's no return value. The posts array will contain all results that are found. - -= Sorting search results = -If you want something else than relevancy ranking, you can use orderby and order parameters. Orderby accepts $post variable attributes and order can be "asc" or "desc". The most relevant attributes here are most likely "post_date" and "comment_count". - -If you want to give your users the ability to sort search results by date, you can just add a link to http://www.yourblogdomain.com/?s=search-term&orderby=post_date&order=desc to your search result page. - -Order by relevance is either orderby=relevance or no orderby parameter at all. - -= Filtering results by date = -You can specify date limits on searches with `by_date` search parameter. You can use it your search result page like this: http://www.yourblogdomain.com/?s=search-term&by_date=1d to offer your visitor the ability to restrict their search to certain time limit (see [RAPLIQ](http://www.rapliq.org/) for a working example). - -The date range is always back from the current date and time. Possible units are hour (h), day (d), week (w), month (m) and year (y). So, to see only posts from past week, you could use by_date=7d or by_date=1w. - -Using wrong letters for units or impossible date ranges will lead to either defaulting to date or no results at all, depending on case. - -Thanks to Charles St-Pierre for the idea. - -= Displaying the relevance score = -Relevanssi stores the relevance score it uses to sort results in the $post variable. Just add something like - -`echo $post->relevance_score` - -to your search results template inside a PHP code block to display the relevance score. - -= Did you mean? suggestions = -To use Google-style "did you mean?" suggestions, first enable search query logging. The suggestions are based on logged queries, so without good base of logged queries, the suggestions will be odd and not very useful. - -To use the suggestions, add the following line to your search result template, preferably before the have_posts() check: - -`Did you mean: ", "?

    ", 5); }?>` - -The first parameter passes the search term, the second is the text before the result, the third is the text after the result and the number is the amount of search results necessary to not show suggestions. With the default value of 5, suggestions are not shown if the search returns more than 5 hits. - -= Search shortcode = -Relevanssi also adds a shortcode to help making links to search results. That way users can easily find more information about a given subject from your blog. The syntax is simple: - -`[search]John Doe[/search]` - -This will make the text John Doe a link to search results for John Doe. In case you want to link to some other search term than the anchor text (necessary in languages like Finnish), you can use: - -`[search term="John Doe"]Mr. John Doe[/search]` - -Now the search will be for John Doe, but the anchor says Mr. John Doe. - -One more parameter: setting `[search phrase="on"]` will wrap the search term in quotation marks, making it a phrase. This can be useful in some cases. - -= Restricting searches to categories and tags = -Relevanssi supports the hidden input field `cat` to restrict searches to certain categories (or tags, since those are pretty much the same). Just add a hidden input field named `cat` in your search form and list the desired category or tag IDs in the `value` field - positive numbers include those categories and tags, negative numbers exclude them. - -This input field can only take one category or tag id (a restriction caused by WordPress, not Relevanssi). If you need more, use `cats` and use a comma-separated list of category IDs. - -You can also set the restriction from general plugin settings (and then override it in individual search forms with the special field). This works with custom taxonomies as well, just replace `cat` with the name of your taxonomy. - -If you want to restrict the search to categories using a dropdown box on the search form, use a code like this: - -`
    -
    - - 'All categories')); -?> - -
    -
    ` - -This produces a search form with a dropdown box for categories. Do note that this code won't work when placed in a Text widget: either place it directly in the template or use a PHP widget plugin to get a widget that can execute PHP code. - -= Restricting searches with taxonomies = - -You can use taxonomies to restrict search results to posts and pages tagged with a certain taxonomy term. If you have a custom taxonomy of "People" and want to search entries tagged "John" in this taxonomy, just use `?s=keyword&people=John` in the URL. You should be able to use an input field in the search form to do this, as well - just name the input field with the name of the taxonomy you want to use. - -It's also possible to do a dropdown for custom taxonomies, using the same function. Just adjust the arguments like this: - -`wp_dropdown_categories(array('show_option_all' => 'All people', 'name' => 'people', 'taxonomy' => 'people'));` - -This would do a dropdown box for the "People" taxonomy. The 'name' must be the keyword used in the URL, while 'taxonomy' has the name of the taxonomy. - -= Automatic indexing = -Relevanssi indexes changes in documents as soon as they happen. However, changes in shortcoded content won't be registered automatically. If you use lots of shortcodes and dynamic content, you may want to add extra indexing. Here's how to do it: - -`if (!wp_next_scheduled('relevanssi_build_index')) { - wp_schedule_event( time(), 'daily', 'relevanssi_build_index' ); -}` - -Add the code above in your theme functions.php file so it gets executed. This will cause WordPress to build the index once a day. This is an untested and unsupported feature that may cause trouble and corrupt index if your database is large, so use at your own risk. This was presented at [forum](http://wordpress.org/support/topic/plugin-relevanssi-a-better-search-relevanssi-chron-indexing?replies=2). - -= Highlighting terms = -Relevanssi search term highlighting can be used outside search results. You can access the search term highlighting function directly. This can be used for example to highlight search terms in structured search result data that comes from custom fields and isn't normally highlighted by Relevanssi. - -Just pass the content you want highlighted through `relevanssi_highlight_terms()` function. The content to highlight is the first parameter, the search query the second. The content with highlights is then returned by the function. Use it like this: - -`if (function_exists('relevanssi_highlight_terms')) { - echo relevanssi_highlight_terms($content, get_search_query()); -} -else { echo $content; }` - -= Multisite searching = -To search multiple blogs in the same WordPress network, use the `searchblogs` argument. You can add a hidden input field, for example. List the desired blog ids as the value. For example, searchblogs=1,2,3 would search blogs 1, 2, and 3. - -The features are very limited in the multiblog search, none of the advanced filtering works, and there'll probably be fairly serious performance issues if searching common words from multiple blogs. - -= What is tf * idf weighing? = - -It's the basic weighing scheme used in information retrieval. Tf stands for *term frequency* while idf is *inverted document frequency*. Term frequency is simply the number of times the term appears in a document, while document frequency is the number of documents in the database where the term appears. - -Thus, the weight of the word for a document increases the more often it appears in the document and the less often it appears in other documents. - -= What are stop words? = - -Each document database is full of useless words. All the little words that appear in just about every document are completely useless for information retrieval purposes. Basically, their inverted document frequency is really low, so they never have much power in matching. Also, removing those words helps to make the index smaller and searching faster. - -== Known issues and To-do's == -* Known issue: In general, multiple Loops on the search page may cause surprising results. Please make sure the actual search results are the first loop. -* Known issue: Relevanssi doesn't necessarily play nice with plugins that modify the excerpt. If you're having problems, try using relevanssi_the_excerpt() instead of the_excerpt(). -* Known issue: When a tag is removed, Relevanssi index isn't updated until the post is indexed again. - -== Thanks == -* Cristian Damm for tag indexing, comment indexing, post/page exclusion and general helpfulness. -* Marcus Dalgren for UTF-8 fixing. -* Warren Tape. -* Mohib Ebrahim for relentless bug hunting. -* John Blackbourn for amazing internal link feature and other fixes. -* John Calahan for extensive 2.0 beta testing. - -== Changelog == -= 2.25.2 = -* Security fix: Prevent CSV injection attack in log export. -* Security fix: Restrict access to doc count updates. -* Minor fix: Product variations check the parent product for access restrictions, to avoid situations where variations of a draft product appear in the results. -* Minor fix: Improved TablePress compatibility. -* Minor fix: Added error handling to the Ninja Table compatibility code. - -= 2.25.1 = -* Security fix: Relevanssi had a vulnerability where anyone could access the search logs and click logs. The log export is now protected. -* Minor fix: Relevanssi had problems with Polylang when a post or term didn't have language specified. Now Relevanssi handles those situations better. -* Minor fix: Post date throttling had a MySQL error that made it replace JOINs instead of concatenating. -* Minor fix: The log database table now has an index on session_id, as not having that index can slow down the search a lot. - -= 2.25.0 = -* New feature: New filter hook `relevanssi_searchform_dropdown_args` filters the arguments for `wp_dropdown_categories()` in search forms. -* Changed behaviour: Search form shortcode taxonomy dropdowns are now sorted alphabetically and not by term ID. -* Minor fix: Caught a bug in excerpt-building with empty words. -* Minor fix: It's now possible to set both `post__in` and `post__not_in` and likewise for `parent__in` and `parent__not_in`. -* Minor fix: The `post_status` is no longer available as a query parameter. - -= 2.24.4 = -* Minor fix: Fixes broken taxonomy indexing. - -= 2.24.3 = -* Security fix: Relevanssi had a vulnerability for SQL injections. Exploiting the vulnerability does require WP admin access. This vulnerability is now fixed. -* Security fix: Relevanssi had a vulnerability for error log injections. Exploiting this vulnerability requires file upload access to the site. This vulnerability is now fixed. -* New feature: New filter hook 'relevanssi_get_attachment_posts_query_final' filters the final SQL query for attachment post fetching. -* Changed behaviour: Relevanssi now skips attachments with 'Server did not respond' errors when reading attachments. This should help with problems coming from attachments that are too big read. -* Minor fix: Improved server timeout error handling for attachment reading. -* Minor fix: Relevanssi didn't strip tags from custom field specific excerpts, and could show zero-hit excerpts for the content. -* Minor fix: Multisite search failed when the search term resolved to nothing in the tokenizer. - -= 2.24.2 = -* Minor fix: Fixes broken WP CLI progress bars. -* Minor fix: Meta query boolean to array conversion. -* Minor fix: For indexing, stemmer is always in OR mode so that both stemmed word and the original word is indexed. - -= 2.24.1 = -* New feature: The debugging tab now shows the status of the 'relevanssi_words' option. -* Changed behaviour: The 'relevanssi_index_content' and 'relevanssi_index_titles' filter hooks now get the post object as a second parameter. -* Minor fix: Stop Relevanssi from blocking the feed searches. -* Minor fix: Remove warning from missing blog_id parameter. -* Minor fix: Improve exact match boosts with accented letters. -* Minor fix: Entering synonyms in Polylang all languages mode was possible; it shouldn't be. -* Minor fix: Relevanssi is now blocked in the reusable content block search. - -= 2.24.0 = -* New feature: New filter hook `relevanssi_highlight_regex` makes it possible to adjust the regex used for highlighting. -* New feature: New filter hook `relevanssi_excerpt_custom_fields` filters the list of custom fields used for creating the excerpt. -* New feature: New filter hook `relevanssi_phrase_custom_fields` filters the list of custom fields used for phrase matching. Return an empty array to disable phrase matching in custom fields. -* New feature: New filter hook `relevanssi_phrase_taxonomies` filters the list of taxonomies used for phrase matching. Return an empty array to disable phrase matching in taxonomies. -* New feature: If RELEVANSSI_DEBUG, WP_DEBUG and WP_DEBUG_DISPLAY are all true, Relevanssi will print out indexing debugging messages to the error log (PHP error log or whatever is defined in WP_DEBUG_LOG). -* Changed behaviour: If the `relevanssi_accents_replacement_arrays` returns an empty array, the accent variation feature is disabled. -* Minor fix: Term indexing with WPML only indexed the terms in the current admin language. Now the terms are indexed in all languages. -* Minor fix: Some ACF fields change the global $post, leading to indexing problems. Relevanssi tries to prevent that now. -* Minor fix: Relevanssi couldn't create the click tracking table on subsites during the multisite installation. -* Minor fix: Safety features for post-part targeting to avoid fatal errors from wrong variable types. -* Minor fix: Pinning failed in multisite if the search site didn't have any pinned posts. -* Minor fix: The `relevanssi_custom_field_value` filter hook is now applied to `_relevanssi_pdf_content` field when the PDF content is indexed for the parent post. -* Minor fix: The `relevanssi_premium_get_post()` now returns a `WP_Error` when the post is not found. -* Minor fix: The "Did you mean" feature now makes less suggestions for words that are already correct. -* Minor fix: Trigger reindexing of the parent post when an attachment is attached or detached from the Media Library. -* Minor fix: Click tracking now works much better in multisite searches and counts the clicks for the correct subsite. - -= 2.23.0 = -* New feature: Relevanssi can now create custom field specific excerpts that come from one custom field only and know which field that is. -* New feature: You can see the list of indexed custom field names in the indexing and excerpt settings. -* New feature: New filter hook `relevanssi_excerpt_specific_custom_field_content` filters the excerpt custom field content if `relevanssi_excerpt_specific_fields` is enabled. -* Changed behaviour: The `relevanssi_get_custom_field_content()` function now returns an array instead of string. If `relevanssi_excerpt_specific_fields` is off, the previous string return value is returned as a single-item array with the string in index 0. If the setting is on, the array keys are the field names. -* Changed behaviour: The `relevanssi_get_child_pdf_content()` function now returns an array. -* Minor fix: The "none" value in category dropdowns from the searchform shortcode is changed from -1 to 0. -* Minor fix: The stopword population during the multisite installation used the wrong database table, leading to failed population. -* Minor fix: Multisite installation is moved from `wp_insert_site` (priority 10) to `wp_initialize_site` (priority 200) in order to avoid trouble. -* Minor fix: Wildcard search now works in whole word matching, not only in partial matching. -* Minor fix: The Gutenberg sidebar translations didn't show up. Now you should be able to see the sidebar in the right language. - -= 2.22.0 = -* New feature: Logging now includes a session ID (based on user ID for logged-in users, HTTP user agent for others, and current time, stable for 10 minutes per user). This is used to remove duplicate searches from live searches, keeping only the final search query. -* Minor fix: The pin weights did not appear in the classic editor Relevanssi metabox, despite being stored in the database. - -= 2.21.0 = -* New feature: You can now add weights to pinned terms to control the order of the pinned posts. -* New feature: New filter hook `relevanssi_add_attachment_scripts` lets you add the attachment javascripts to other post types than `attachment`. -* New feature: New filter hook `relevanssi_highlight_query` lets you modify the search query for highlighting. -* Changed behavior: Relevanssi no longer searches in feed searches by default. -* Minor fix: The filter `relevanssi_get_attachment_url` is now also used when adding the attachment metabox. -* Minor fix: No more crashes from Polylang forced plugin updates. -* Minor fix: PHP 8.1 deprecated FILTER_SANITIZE_STRING, those are now replaced. - -= 2.20.4 = -* New feature: New filter hook `relevanssi_blocked_field_types` can be used to control which ACF field types are excluded from the index. By default, this includes 'repeater', 'flexible_content', and 'group'. -* New feature: New filter hook `relevanssi_acf_field_object` can be used to filter the ACF field object before Relevanssi indexes it. Return false to have Relevanssi ignore the field type. -* Minor fix: ACF field exclusion is now recursive. If a parent field is excluded, all sub fields will also be excluded. -* Minor fix: The indexing settings tab now checks if the wp_relevanssi database table exists and will create the table if it doesn't. -* Minor fix: Pinning code has been foolproofed to cover some situations that would lead to errors. -* Minor fix: Handling of data attributes in in-document highlighting had a bug that caused problems with third-party plugins. - -= 2.20.3 = -* New feature: Relevanssi now has a debug mode that will help troubleshooting and support. -* Minor fix: Using the_permalink() caused problems with search result links. That is now fixed. Relevanssi no longer hooks onto `the_permalink` hook and instead uses `post_link` and other similar hooks. -* Minor fix: Click tracking parameters have more control to avoid problems from malformed click tracking data. - -= 2.20.2 = -* Fixes the persistent update nag. - -= 2.20.1 = -* New feature: New filter hook `relevanssi_add_highlight_and_tracking` can be used to force Relevanssi to add the `highlight` and tracking parameters to permalinks. -* Changed behaviour: Exclusions now override pinning. If a post is pinned for 'foo' and excluded for 'foo bar', it will now be excluded when someone searches for 'foo bar'. Previously pinning overrode the exclusion. -* Changed behaviour: The 'relevanssi_wpml_filter' filter function now runs on priority 9 instead of 10 to avoid problems with custom filters on relevanssi_hits_filter. -* Minor fix: Page links didn't get the click tracking tags. This is fixed now. -* Minor fix: Including posts in the Related posts could cause duplicates. Now Relevanssi excludes the included posts from the search so that there won't be duplicates. -* Minor fix: Handle cases of missing posts better; relevanssi_get_post() now returns a WP_Error if no post is found. -* Minor fix: Avoid a slow query on the searching tab when the throttle is not enabled. -* Minor fix: Search queries that contain apostrophes and quotes can now be deleted from the log. - -= 2.20.0 = -* New feature: Relevanssi now shows the MySQL `max_allowed_packet` size on the debug tab. -* New feature: Relevanssi now shows the indexing query on the debug tab. -* New feature: You can now edit pinning and exclusions from Quick Edit. -* New feature: You can now remove queries from the search log from the query insights page. -* New feature: ACF field settings now include a 'Exclude from Relevanssi index' setting. You can use that to exclude ACF fields from the Relevanssi index. -* Changed behaviour: Click tracking is disabled in multisite searches. It causes problems with wrong links and isn't very reliable in the best case. -* Changed behaviour: Plugin translation updates are disabled, unless explicitly enabled either from the Overview settings or with the `relevanssi_update_translations` filter hook. -* Minor fix: Relevanssi was adding extra quotes around search terms in the `highlight` parameter. -* Minor fix: Metabox fields look nicer on Firefox. -* Minor fix: Adds the `relevanssi_related_posts_cache_id` filter to the relevanssi_related_posts() function. -* Minor fix: Yet another update to data attributes in highlighting. Thanks to Faeddur. -* Minor fix: Taxonomy query handling was improved. This should help in particular Polylang users who've had problems with Relevanssi ignoring Polylang language restrictions. -* Minor fix: Negative search terms in AND searches caused problems, but now work better. -* Minor fix: Pinning phrases that had the same word more than once (e.g. 'word by word') didn't work. Now it works better. - -== Upgrade notice == -= 2.25.2 = -* Security hardening, improved WooCommerce, TablePress and Ninja Table compatibility. - -= 2.25.1 = -* Security hardening, better Polylang support. - -= 2.25.0 = -* Improvements to search form shortcode. - -= 2.24.4 = -* Fix broken taxonomy indexing. - -= 2.24.3 = -* Security hardening, attachment handling improvements. - -= 2.24.2 = -* Meta query errors, WP CLI progress bars, stemmer indexing. - -= 2.24.1 = -* Fix for the blog_id bug, small improvements. - -= 2.24.0 = -* Improved debugging, bug fixes and new filter hooks. - -= 2.23.0 = -* Better method for handling custom fields in excerpts, bug fixes. - -= 2.22.0 = -* Logs now include a session ID. - -= 2.21.0 = -* You can now assign weights to pinned keywords. - -= 2.20.4 = -* Better ACF field controls, bug fixes. - -= 2.20.3 = -* Fixes a bug with broken permalinks. - -= 2.20.2 = -* Fixes the persistent update nag. - -= 2.20.1 = -* Bug fixes and small improvements. - -= 2.20.0 = -* New features, performance improvements, bug fixes. \ No newline at end of file diff --git a/relevanssi-premium/relevanssi.php b/relevanssi-premium/relevanssi.php deleted file mode 100644 index 092dfabe..00000000 --- a/relevanssi-premium/relevanssi.php +++ /dev/null @@ -1,189 +0,0 @@ -. -*/ - -add_action( 'init', 'relevanssi_premium_init' ); -add_action( 'init', 'relevanssi_activate_auto_update' ); -add_action( 'profile_update', 'relevanssi_profile_update', 9999 ); -add_action( 'edit_user_profile_update', 'relevanssi_profile_update', 9999 ); -add_action( 'user_register', 'relevanssi_profile_update', 9999 ); -add_action( 'delete_user', 'relevanssi_delete_user' ); -add_action( 'created_term', 'relevanssi_add_term', 9999, 3 ); -add_action( 'edited_term', 'relevanssi_edit_term', 9999, 3 ); -add_action( 'delete_term', 'relevanssi_delete_taxonomy_term', 9999, 3 ); -add_action( 'save_post', 'relevanssi_save_postdata', 10 ); -add_action( 'edit_attachment', 'relevanssi_save_postdata' ); -add_action( 'edit_attachment', 'relevanssi_save_pdf_postdata' ); -add_action( 'plugins_loaded', 'relevanssi_spamblock' ); -add_filter( 'wpmu_drop_tables', 'relevanssi_wpmu_drop' ); -add_action( 'network_admin_menu', 'relevanssi_network_menu' ); -add_filter( 'attachment_link', 'relevanssi_post_link_replace', 10, 2 ); -add_action( 'admin_enqueue_scripts', 'relevanssi_premium_add_admin_scripts', 11 ); -add_filter( 'relevanssi_premium_tokenizer', 'relevanssi_enable_stemmer' ); -add_filter( 'query_vars', 'relevanssi_premium_query_vars' ); -add_filter( 'relevanssi_tabs', 'relevanssi_premium_add_tabs', 10 ); -add_filter( 'relevanssi_phrase_queries', 'relevanssi_premium_phrase_queries', 10, 3 ); - -global $wp_version; -if ( version_compare( $wp_version, '5.1', '>=' ) ) { - add_action( 'wp_initialize_site', 'relevanssi_new_blog', 200, 1 ); -} else { - add_action( 'wpmu_new_blog', 'relevanssi_new_blog', 10, 1 ); -} - -global $wpdb; -global $relevanssi_variables; - -$relevanssi_variables['relevanssi_table'] = $wpdb->prefix . 'relevanssi'; -$relevanssi_variables['stopword_table'] = $wpdb->prefix . 'relevanssi_stopwords'; -$relevanssi_variables['log_table'] = $wpdb->prefix . 'relevanssi_log'; -$relevanssi_variables['tracking_table'] = $wpdb->prefix . 'relevanssi_tracking'; // Note: this is also hardcoded in /premium/click-tracking.php. -$relevanssi_variables['post_type_weight_defaults']['post_tag'] = 0.5; -$relevanssi_variables['post_type_weight_defaults']['category'] = 0.5; -$relevanssi_variables['content_boost_default'] = 5; -$relevanssi_variables['title_boost_default'] = 5; -$relevanssi_variables['link_boost_default'] = 0.75; -$relevanssi_variables['comment_boost_default'] = 0.75; -$relevanssi_variables['database_version'] = 23; -$relevanssi_variables['plugin_version'] = '2.25.2'; -$relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ ); -$relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ ); -$relevanssi_variables['file'] = __FILE__; -$relevanssi_variables['sidebar_capability'] = 'edit_others_posts'; - -define( 'RELEVANSSI_PREMIUM', true ); -define( 'RELEVANSSI_EU_SERVICES_URL', 'https://eu.relevanssiservices.com/' ); -define( 'RELEVANSSI_US_SERVICES_URL', 'https://us.relevanssiservices.com/' ); -if ( ! defined( 'RELEVANSSI_DEVELOP' ) ) { - define( 'RELEVANSSI_DEVELOP', false ); -} - -require_once 'lib/admin-ajax.php'; -require_once 'lib/common.php'; -require_once 'lib/debug.php'; -require_once 'lib/didyoumean.php'; -require_once 'lib/excerpts-highlights.php'; -require_once 'lib/indexing.php'; -require_once 'lib/init.php'; -require_once 'lib/install.php'; -require_once 'lib/interface.php'; -require_once 'lib/log.php'; -require_once 'lib/options.php'; -require_once 'lib/phrases.php'; -require_once 'lib/privacy.php'; -require_once 'lib/search.php'; -require_once 'lib/search-tax-query.php'; -require_once 'lib/search-query-restrictions.php'; -require_once 'lib/shortcodes.php'; -require_once 'lib/stopwords.php'; -require_once 'lib/sorting.php'; -require_once 'lib/user-searches.php'; -require_once 'lib/utils.php'; - -require_once 'premium/admin-ajax.php'; -require_once 'premium/body-stopwords.php'; -require_once 'premium/class-relevanssi-language-packs.php'; -require_once 'premium/class-relevanssi-spellcorrector.php'; -require_once 'premium/class-relevanssi-wp-auto-update.php'; -require_once 'premium/click-tracking.php'; -require_once 'premium/common.php'; -require_once 'premium/excerpts-highlights.php'; -require_once 'premium/indexing.php'; -require_once 'premium/interface.php'; -require_once 'premium/network-options.php'; -require_once 'premium/pdf-upload.php'; -require_once 'premium/pinning.php'; -require_once 'premium/post-metabox.php'; -require_once 'premium/proximity.php'; -require_once 'premium/redirects.php'; -require_once 'premium/related.php'; -require_once 'premium/search.php'; -require_once 'premium/search-multi.php'; -require_once 'premium/spamblock.php'; - -if ( version_compare( $wp_version, '5.0', '>=' ) ) { - require_once 'premium/gutenberg-sidebar.php'; -} - -if ( defined( 'WP_CLI' ) && WP_CLI ) { - require_once 'premium/class-relevanssi-wp-cli-command.php'; - add_filter( 'relevanssi_search_ok', 'relevanssi_cli_query_ok', 10, 2 ); -} - -/** - * Sets the relevanssi_search_ok true for searches. - * - * @param boolean $ok Whether it's ok to do a Relevanssi search or not. - * @param WP_Query $query The query object. - * - * @return boolean Whether it's ok to do a Relevanssi search or not. - */ -function relevanssi_cli_query_ok( $ok, $query ) { - if ( $query->is_search() ) { - return true; - } - return $ok; -} - -/** - * Activates the auto update mechanism. - * - * @global array $relevanssi_variables Relevanssi global variables, used for plugin file name and version number. - * - * Hooks into 'init' filter hook to activate the auto update mechanism. - */ -function relevanssi_activate_auto_update() { - global $relevanssi_variables; - $api_key = get_network_option( null, 'relevanssi_api_key' ); - if ( ! $api_key ) { - $api_key = get_option( 'relevanssi_api_key' ); - } - if ( 'su9qtC30xCLLA' === crypt( $api_key, 'suolaa' ) ) { - $relevanssi_plugin_remote_path = 'https://www.relevanssi.com/update/update-development-2022.php'; - } else { - $relevanssi_plugin_remote_path = 'https://www.relevanssi.com/update/update-2022.php'; - } - $relevanssi_variables['autoupdate'] = new Relevanssi_WP_Auto_Update( - $relevanssi_variables['plugin_version'], - $relevanssi_plugin_remote_path, - $relevanssi_variables['plugin_basename'] - ); -} diff --git a/relevanssi-premium/relevanssi.po b/relevanssi-premium/relevanssi.po deleted file mode 100644 index 06872cf3..00000000 --- a/relevanssi-premium/relevanssi.po +++ /dev/null @@ -1,4490 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Relevanssi Premium\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-11 06:12+0300\n" -"PO-Revision-Date: \n" -"Last-Translator: Mikko Saari \n" -"Language-Team: \n" -"Language: en\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-KeywordsList: _e;__;esc_attr__;esc_attr_e;esc_html__;_n;esc_html_e;" -"esc_html_x;esc_attr_x;_x;__ngettext;__ngettext_noop;_n_noop;_nx;_nx_noop;_ex;" -"_c;_nc\n" -"X-Poedit-Basepath: .\n" -"X-Generator: Poedit 3.3\n" -"X-Poedit-SearchPath-0: .\n" -"X-Poedit-SearchPath-1: premium\n" -"X-Poedit-SearchPath-2: lib\n" -"X-Poedit-SearchPathExcluded-0: src\n" -"X-Poedit-SearchPathExcluded-1: release\n" -"X-Poedit-SearchPathExcluded-2: build\n" -"X-Poedit-SearchPathExcluded-3: node_modules\n" -"X-Poedit-SearchPathExcluded-4: coverage\n" -"X-Poedit-SearchPathExcluded-5: vendor\n" - -#: lib/admin-ajax.php:36 lib/admin-ajax.php:190 -msgid "You do not have sufficient permissions to access this page." -msgstr "" - -#: lib/admin-ajax.php:115 -#, php-format -msgid "Indexed %1$d post (total %2$d), processed %3$d / %4$d." -msgstr "" - -#: lib/admin-ajax.php:252 lib/tabs/indexing-tab.php:135 -#: premium/tabs/attachments-tab.php:63 -msgid "Results" -msgstr "" - -#: lib/admin-ajax.php:256 -#, php-format -msgid "Found a total of %1$d posts, showing posts %2$d–%3$s." -msgstr "" - -#: lib/admin-ajax.php:258 -msgid "Previous page" -msgstr "" - -#: lib/admin-ajax.php:261 -msgid "Next page" -msgstr "" - -#: lib/admin-ajax.php:265 -msgid "Score:" -msgstr "" - -#: lib/admin-ajax.php:290 -msgid "Edit" -msgstr "" - -#: lib/admin-ajax.php:338 -msgid "Query variables" -msgstr "" - -#: lib/admin-ajax.php:407 -msgid "Filters" -msgstr "" - -#: lib/admin-ajax.php:408 -msgid "show" -msgstr "" - -#: lib/admin-ajax.php:409 -msgid "hide" -msgstr "" - -#: lib/common.php:147 -msgid "Missing" -msgstr "" - -#: lib/common.php:1143 -msgid "25 most common words in the index" -msgstr "" - -#: lib/common.php:1144 -msgid "" -"These words are excellent stopword material. A word that appears in most of " -"the posts in the database is quite pointless when searching. This is also an " -"easy way to create a completely new stopword list, if one isn't available in " -"your language. Click the word to add the word to the stopword list. The word " -"will also be removed from the index, so rebuilding the index is not " -"necessary." -msgstr "" - -#: lib/common.php:1150 -msgid "Stopword Candidates" -msgstr "" - -#: lib/common.php:1155 -msgid "Add to stopwords" -msgstr "" - -#: lib/common.php:1158 -msgid "Add to content stopwords" -msgstr "" - -#: lib/common.php:1525 -#, php-format -msgid "Nothing found for ID %d." -msgstr "" - -#: lib/common.php:1532 -msgid "Possible reasons this post is not indexed" -msgstr "" - -#: lib/common.php:1536 -msgid "The title" -msgstr "" - -#: lib/common.php:1540 -msgid "The content" -msgstr "" - -#: lib/common.php:1544 lib/tabs/indexing-tab.php:325 -msgid "Comments" -msgstr "" - -#: lib/common.php:1548 -msgid "Tags" -msgstr "" - -#: lib/common.php:1552 -msgid "Categories" -msgstr "" - -#: lib/common.php:1556 -msgid "Other taxonomies" -msgstr "" - -#: lib/common.php:1560 -msgid "Links" -msgstr "" - -#: lib/common.php:1564 -msgid "Authors" -msgstr "" - -#: lib/common.php:1568 -msgid "Excerpt" -msgstr "" - -#: lib/common.php:1572 lib/tabs/indexing-tab.php:339 -msgid "Custom fields" -msgstr "" - -#: lib/common.php:1576 -msgid "MySQL content" -msgstr "" - -#: lib/compatibility/acf.php:131 -msgid "Exclude from Relevanssi index" -msgstr "" - -#: lib/compatibility/acf.php:132 -msgid "" -"If this setting is enabled, Relevanssi will not index the value of this " -"field for posts." -msgstr "" - -#: lib/compatibility/aioseo.php:88 -msgid "Use All-in-One SEO noindex" -msgstr "" - -#: lib/compatibility/aioseo.php:93 -msgid "Use All-in-One SEO noindex." -msgstr "" - -#: lib/compatibility/aioseo.php:95 -msgid "" -"If checked, Relevanssi will not index posts marked as \"No index\" in All-in-" -"One SEO settings." -msgstr "" - -#: lib/compatibility/rankmath.php:80 -msgid "Use Rank Math SEO noindex" -msgstr "" - -#: lib/compatibility/rankmath.php:85 -msgid "Use Rank Math SEO noindex." -msgstr "" - -#: lib/compatibility/rankmath.php:87 -msgid "" -"If checked, Relevanssi will not index posts marked as \"No index\" in Rank " -"Math SEO settings." -msgstr "" - -#: lib/compatibility/seoframework.php:76 -msgid "Use SEO Framework noindex" -msgstr "" - -#: lib/compatibility/seoframework.php:81 -msgid "Use SEO Framework noindex." -msgstr "" - -#: lib/compatibility/seoframework.php:83 -msgid "" -"If checked, Relevanssi will not index posts marked as \"No index\" in SEO " -"Framework settings." -msgstr "" - -#: lib/compatibility/seopress.php:82 -msgid "Use SEOPress noindex" -msgstr "" - -#: lib/compatibility/seopress.php:87 -msgid "Use SEOPress noindex." -msgstr "" - -#: lib/compatibility/seopress.php:89 -msgid "" -"If checked, Relevanssi will not index posts marked as \"No index\" in " -"SEOPress settings." -msgstr "" - -#: lib/compatibility/yoast-seo.php:82 -msgid "Use Yoast SEO noindex" -msgstr "" - -#: lib/compatibility/yoast-seo.php:87 -msgid "Use Yoast SEO noindex." -msgstr "" - -#: lib/compatibility/yoast-seo.php:89 -msgid "" -"If checked, Relevanssi will not index posts marked as \"No index\" in Yoast " -"SEO settings." -msgstr "" - -#: lib/contextual-help.php:24 -#, php-format -msgid "" -"To adjust the post order, you can use the %1$s query parameter. With %1$s, " -"you can use multiple layers of different sorting methods. See WordPress Codex for more details on using arrays for orderby." -msgstr "" - -#: lib/contextual-help.php:26 -#, php-format -msgid "" -"To get inside-word highlights, uncheck the \"%s\" option. That has a side-" -"effect of enabling the inside-word highlights." -msgstr "" - -#: lib/contextual-help.php:26 -msgid "Uncheck this if you use non-ASCII characters" -msgstr "" - -#: lib/contextual-help.php:28 -#, php-format -msgid "In order to adjust the throttle limit, you can use the %s filter hook." -msgstr "" - -#: lib/contextual-help.php:33 lib/interface.php:198 -#: lib/tabs/overview-tab.php:59 -msgid "Searching" -msgstr "" - -#: lib/contextual-help.php:36 -msgid "" -"Inside-word matching is disabled by default, because it increases garbage " -"results that don't really match the search term. If you want to enable it, " -"add the following function to your theme functions.php:" -msgstr "" - -#: lib/contextual-help.php:44 -msgid "" -"It's not usually necessary to adjust the limit from 500, but in some cases " -"performance gains can be achieved by setting a lower limit. We don't suggest " -"going under 200, as low values will make the results worse." -msgstr "" - -#: lib/contextual-help.php:50 -#, php-format -msgid "For all the possible options, see the Codex documentation for %s." -msgstr "" - -#: lib/contextual-help.php:55 -msgid "Restrictions" -msgstr "" - -#: lib/contextual-help.php:57 -msgid "" -"If you want the general search to target all posts, but have a single search " -"form target only certain posts, you can add a hidden input variable to the " -"search form." -msgstr "" - -#: lib/contextual-help.php:58 -msgid "" -"For example in order to restrict the search to categories 10, 14 and 17, you " -"could add this to the search form:" -msgstr "" - -#: lib/contextual-help.php:60 -msgid "" -"To restrict the search to posts tagged with alfa AND beta, you could add " -"this to the search form:" -msgstr "" - -#: lib/contextual-help.php:67 -#, php-format -msgid "" -"For more exclusion options, see the Codex documentation for %s. For example, " -"to exclude tag ID 10, use" -msgstr "" - -#: lib/contextual-help.php:69 -#, php-format -msgid "" -"To exclude posts from the index and not just from the search, you can use " -"the %s filter hook. This would not index posts that have a certain taxonomy " -"term:" -msgstr "" - -#: lib/contextual-help.php:71 lib/contextual-help.php:153 -#, php-format -msgid "" -"For more examples, see the related knowledge base posts." -msgstr "" - -#: lib/contextual-help.php:76 -msgid "Exclusions" -msgstr "" - -#: lib/contextual-help.php:95 -#, php-format -msgid "" -"By default, the User searches page shows 20 most common keywords. In order " -"to see more, you can adjust the value with the %s filter hook, like this:" -msgstr "" - -#: lib/contextual-help.php:97 -#, php-format -msgid "" -"The complete logs are stored in the %s database table, where you can access " -"them if you need more information than what the User searches page provides." -msgstr "" - -#: lib/contextual-help.php:102 -msgid "Logs" -msgstr "" - -#: lib/contextual-help.php:112 -#, php-format -msgid "" -"Custom snippets require that the search results template uses %s to print " -"out the excerpts." -msgstr "" - -#: lib/contextual-help.php:114 -#, php-format -msgid "" -"If you want more control over what content Relevanssi uses to create the " -"excerpts, you can use the %1$s and %2$s filter hooks to adjust the content." -msgstr "" - -#: lib/contextual-help.php:116 -#, php-format -msgid "" -"Some shortcode do not work well with Relevanssi excerpt-generation. " -"Relevanssi disables some shortcodes automatically to prevent problems. This " -"can be adjusted with the %s filter hook." -msgstr "" - -#: lib/contextual-help.php:118 -#, php-format -msgid "" -"If you want Relevanssi to build excerpts faster and don't mind that they may " -"be less than perfect in quality, add a filter that returns true on hook %s." -msgstr "" - -#: lib/contextual-help.php:123 lib/tabs/indexing-tab.php:398 -msgid "Excerpts" -msgstr "" - -#: lib/contextual-help.php:125 -msgid "" -"Building custom excerpts can be slow. If you are not actually using the " -"excerpts, make sure you disable the option." -msgstr "" - -#: lib/contextual-help.php:127 -msgid "" -"Generally, Relevanssi generates the excerpts from post content. If you want " -"to include custom field content in the excerpt-building, this can be done " -"with a simple setting from the excerpt settings." -msgstr "" - -#: lib/contextual-help.php:137 -#, php-format -msgid "" -"In order to see title highlights from Relevanssi, replace %1$s in the search " -"results template with %2$s. It does the same thing, but supports Relevanssi " -"title highlights." -msgstr "" - -#: lib/contextual-help.php:142 -msgid "Highlights" -msgstr "" - -#: lib/contextual-help.php:144 -msgid "" -"Title highlights don't appear automatically, because that led to problems " -"with highlights appearing in wrong places and messing up navigation menus, " -"for example." -msgstr "" - -#: lib/contextual-help.php:151 -#, php-format -msgid "" -"For more fine-tuned changes, you can use %1$s filter hook to adjust what is " -"replaced with what, and %2$s filter hook to completely override the default " -"punctuation control." -msgstr "" - -#: lib/contextual-help.php:158 -msgid "Punctuation" -msgstr "" - -#: lib/contextual-help.php:160 -msgid "" -"Relevanssi removes punctuation. Some punctuation is removed, some replaced " -"with spaces. Advanced indexing settings include some of the more common " -"settings people want to change." -msgstr "" - -#: lib/contextual-help.php:168 -#, php-format -msgid "" -"If you have content that you don't want indexed, you can wrap that content " -"in a %s shortcode." -msgstr "" - -#: lib/contextual-help.php:170 -#, php-format -msgid "" -"If you need a search form on some page on your site, you can use the %s " -"shortcode to print out a basic search form." -msgstr "" - -#: lib/contextual-help.php:172 -#, php-format -msgid "" -"If you need to add query variables to the search form, the shortcode takes " -"parameters, which are then printed out as hidden input fields. To get a " -"search form with a post type restriction, you can use %1$s. To restrict the " -"search to categories 10, 14 and 17, you can use %2$s and so on." -msgstr "" - -#: lib/contextual-help.php:174 -#, php-format -msgid "" -"You can use the %1$s parameter to add a taxonomy dropdown to the search " -"form. Just use the name of the taxonomy, like %2$s. This works best with " -"hierarchical taxonomies like categories with relatively few options " -"available." -msgstr "" - -#: lib/contextual-help.php:179 -msgid "Helpful shortcodes" -msgstr "" - -#: lib/contextual-help.php:190 -#, php-format -msgid "" -"For more details how to fix that issue, see WooCommerce tips in " -"Relevanssi user manual." -msgstr "" - -#: lib/contextual-help.php:195 -msgid "WooCommerce" -msgstr "" - -#: lib/contextual-help.php:197 -msgid "" -"If your SKUs include hyphens or other punctuation, do note that Relevanssi " -"replaces most punctuation with spaces. That's going to cause issues with SKU " -"searches." -msgstr "" - -#: lib/contextual-help.php:199 -msgid "" -"If you don't want to index products that are out of stock, excluded from the " -"catalog or excluded from the search, there's a product visibility filtering " -"method that is described in the user manual (see link above)." -msgstr "" - -#: lib/contextual-help.php:205 -#, php-format -msgid "" -"To adjust the amount of the exact match bonus, you can use the %s filter " -"hook. It works like this:" -msgstr "" - -#: lib/contextual-help.php:207 -#, php-format -msgid "The default values are %1$s for titles and %2$s for content." -msgstr "" - -#: lib/contextual-help.php:212 -msgid "Exact match bonus" -msgstr "" - -#: lib/contextual-help.php:223 premium/contextual-help.php:97 -msgid "For more information:" -msgstr "" - -#: lib/contextual-help.php:224 premium/contextual-help.php:101 -msgid "Plugin knowledge base" -msgstr "" - -#: lib/contextual-help.php:225 premium/contextual-help.php:99 -msgid "WordPress.org forum" -msgstr "" - -#: lib/debug.php:122 -msgid "Post not found" -msgstr "" - -#: lib/indexing.php:31 -msgid "Relevanssi image attachment filter" -msgstr "" - -#: lib/indexing.php:480 premium/common.php:575 -msgid "Relevanssi index exclude" -msgstr "" - -#: lib/indexing.php:509 -msgid "Blocked by a filter function" -msgstr "" - -#: lib/init.php:125 -msgid "" -"You do not have an index! Remember to build the index (click the \"Build the " -"index\" button), otherwise searching won't work." -msgstr "" - -#: lib/init.php:137 -msgid "" -"Multibyte string functions are not available. Relevanssi may not work well " -"without them. Please install (or ask your host to install) the mbstring " -"extension." -msgstr "" - -#: lib/init.php:222 lib/init.php:223 lib/tabs/logging-tab.php:47 -#: lib/user-searches.php:18 -msgid "User searches" -msgstr "" - -#: lib/init.php:234 lib/init.php:235 lib/tabs/searching-tab.php:258 -msgid "Admin search" -msgstr "" - -#: lib/init.php:462 -msgid "Settings" -msgstr "" - -#: lib/init.php:465 -msgid "Go Premium!" -msgstr "" - -#: lib/interface.php:18 -msgid "Relevanssi Search Options" -msgstr "" - -#: lib/interface.php:20 -msgid "Relevanssi Premium Search Options" -msgstr "" - -#: lib/interface.php:108 -msgid "Admin Search" -msgstr "" - -#: lib/interface.php:137 -msgid "Logs clear!" -msgstr "" - -#: lib/interface.php:139 -msgid "Clearing the logs failed." -msgstr "" - -#: lib/interface.php:177 -msgid "Overview" -msgstr "" - -#: lib/interface.php:184 lib/tabs/overview-tab.php:47 -msgid "Indexing" -msgstr "" - -#: lib/interface.php:191 premium/interface.php:1199 -msgid "Attachments" -msgstr "" - -#: lib/interface.php:205 -msgid "Logging" -msgstr "" - -#: lib/interface.php:212 lib/tabs/overview-tab.php:63 -msgid "Excerpts and highlights" -msgstr "" - -#: lib/interface.php:219 lib/tabs/synonyms-tab.php:41 -#: lib/tabs/synonyms-tab.php:67 lib/tabs/synonyms-tab.php:98 -msgid "Synonyms" -msgstr "" - -#: lib/interface.php:226 lib/tabs/stopwords-tab.php:22 -#: lib/tabs/stopwords-tab.php:144 -msgid "Stopwords" -msgstr "" - -#: lib/interface.php:233 lib/tabs/redirects-tab.php:18 -#: premium/interface.php:1191 premium/tabs/redirects-tab.php:26 -msgid "Redirects" -msgstr "" - -#: lib/interface.php:240 lib/tabs/debugging-tab.php:54 -msgid "Debugging" -msgstr "" - -#: lib/interface.php:284 lib/tabs/indexing-tab.php:115 -#: premium/network-options.php:75 -msgid "Save the options" -msgstr "" - -#: lib/interface.php:348 -msgid "Click OK to copy Relevanssi options to all subsites" -msgstr "" - -#: lib/interface.php:349 -msgid "Are you sure you want to remove all stopwords?" -msgstr "" - -#: lib/interface.php:350 -msgid "Are you sure you want to delete the query?" -msgstr "" - -#: lib/interface.php:351 -msgid "Wiping out the index..." -msgstr "" - -#: lib/interface.php:352 -msgid "Done." -msgstr "" - -#: lib/interface.php:353 -msgid "Indexing users..." -msgstr "" - -#: lib/interface.php:354 -msgid "Indexing the following taxonomies:" -msgstr "" - -#: lib/interface.php:355 -msgid "Indexing attachments..." -msgstr "" - -#: lib/interface.php:356 -msgid "Counting posts..." -msgstr "" - -#: lib/interface.php:357 -msgid "Counting taxonomy terms..." -msgstr "" - -#: lib/interface.php:358 -msgid "Counting users..." -msgstr "" - -#: lib/interface.php:359 -msgid "Counting attachments..." -msgstr "" - -#: lib/interface.php:360 -msgid "posts found." -msgstr "" - -#: lib/interface.php:361 -msgid "taxonomy terms found." -msgstr "" - -#: lib/interface.php:362 -msgid "users found." -msgstr "" - -#: lib/interface.php:363 -msgid "attachments found." -msgstr "" - -#: lib/interface.php:364 -msgid "Taxonomy term indexing is disabled." -msgstr "" - -#: lib/interface.php:365 -msgid "User indexing is disabled." -msgstr "" - -#: lib/interface.php:366 -msgid "Indexing complete." -msgstr "" - -#: lib/interface.php:367 -msgid "posts excluded." -msgstr "" - -#: lib/interface.php:368 -msgid "Settings have changed, please save the options before indexing." -msgstr "" - -#: lib/interface.php:369 -msgid "Reload the page to refresh the state of the index." -msgstr "" - -#: lib/interface.php:370 -msgid "Are you sure you want to delete all attachment content from the index?" -msgstr "" - -#: lib/interface.php:371 -msgid "Relevanssi attachment data wiped clean." -msgstr "" - -#: lib/interface.php:372 -msgid "There were problems wiping the Relevanssi attachment data clean." -msgstr "" - -#: lib/interface.php:373 -msgid "hour" -msgstr "" - -#: lib/interface.php:374 -msgid "hours" -msgstr "" - -#: lib/interface.php:375 -msgid "about" -msgstr "" - -#: lib/interface.php:376 -msgid "about an hour" -msgstr "" - -#: lib/interface.php:377 -msgid "about an hour and a half" -msgstr "" - -#: lib/interface.php:378 -msgid "minute" -msgstr "" - -#: lib/interface.php:379 -msgid "minutes" -msgstr "" - -#: lib/interface.php:380 -msgid "less than a minute" -msgstr "" - -#: lib/interface.php:381 -msgid "we're done!" -msgstr "" - -#: lib/interface.php:448 -msgid "Tag weight" -msgstr "" - -#: lib/interface.php:456 -msgid "Category weight" -msgstr "" - -#: lib/log.php:202 -msgid "Logged searches" -msgstr "" - -#: lib/log.php:205 -msgid "Time" -msgstr "" - -#: lib/log.php:209 lib/user-searches.php:319 lib/user-searches.php:333 -#: premium/click-tracking.php:641 premium/tabs/redirects-tab.php:52 -msgid "Query" -msgstr "" - -#: lib/log.php:213 -msgid "Hits found" -msgstr "" - -#: lib/log.php:217 -msgid "IP address" -msgstr "" - -#: lib/log.php:221 -msgid "Session ID" -msgstr "" - -#: lib/log.php:307 -msgid "No search keywords logged." -msgstr "" - -#: lib/log.php:402 -#, php-format -msgid "The query '%s' deleted from the log." -msgstr "" - -#: lib/log.php:414 -#, php-format -msgid "Couldn't remove the query '%s' from the log." -msgstr "" - -#: lib/privacy.php:34 -msgid "What personal data we collect and why we collect it" -msgstr "" - -#: lib/privacy.php:36 -msgid "IP address for searches" -msgstr "" - -#: lib/privacy.php:37 -msgid "" -"All searches performed using the internal site search are logged in the " -"database, including the following information: the search query, the number " -"of hits found, user ID for users who are logged in, date and time and the IP " -"address. The IP address is stored for security and auditing purposes." -msgstr "" - -#: lib/privacy.php:39 -msgid "" -"All searches performed using the internal site search are logged in the " -"database, including the following information: the search query, the number " -"of hits found, user ID for users who are logged in and date and time." -msgstr "" - -#: lib/privacy.php:42 -msgid "How long we retain your data" -msgstr "" - -#: lib/privacy.php:45 -#, php-format -msgid "" -"The search logs are stored for %d days before they are automatically removed." -msgstr "" - -#: lib/privacy.php:47 -msgid "The search logs are stored indefinitely." -msgstr "" - -#: lib/privacy.php:64 lib/privacy.php:81 -msgid "Relevanssi Search Logs" -msgstr "" - -#: lib/shortcodes.php:166 -msgid "None" -msgstr "" - -#: lib/stopwords.php:42 -msgid "Added stopwords from the database." -msgstr "" - -#: lib/stopwords.php:57 -#, php-format -msgid "The stopword file for the language '%s' doesn't exist." -msgstr "" - -#: lib/stopwords.php:73 -msgid "Couldn't read the stopwords from the file." -msgstr "" - -#: lib/stopwords.php:83 -msgid "Added stopwords from the stopword file." -msgstr "" - -#: lib/stopwords.php:142 -#, php-format -msgid "Successfully added %1$d/%2$d terms to stopwords!" -msgstr "" - -#: lib/stopwords.php:161 -#, php-format -msgid "Term '%s' added to stopwords!" -msgstr "" - -#: lib/stopwords.php:170 -#, php-format -msgid "Couldn't add term '%s' to stopwords!" -msgstr "" - -#: lib/stopwords.php:321 -msgid "All stopwords removed! Remember to re-index." -msgstr "" - -#: lib/stopwords.php:329 -msgid "There was a problem, and stopwords couldn't be removed." -msgstr "" - -#: lib/stopwords.php:366 -#, php-format -msgid "Term '%s' removed from stopwords! Re-index to get it back to index." -msgstr "" - -#: lib/stopwords.php:379 -#, php-format -msgid "Couldn't remove term '%s' from stopwords!" -msgstr "" - -#: lib/tabs/attachments-tab.php:18 -msgid "Indexing attachment content" -msgstr "" - -#: lib/tabs/attachments-tab.php:20 -msgid "" -"With Relevanssi Premium, you can index the text contents of attachments " -"(PDFs, Word documents, Open Office documents and many other types). The " -"contents of the attachments are processed on an external service, which " -"makes the feature reliable and light on your own server performance." -msgstr "" - -#: lib/tabs/attachments-tab.php:22 lib/tabs/redirects-tab.php:22 -#, php-format -msgid "" -"In order to access this and many other delightful Premium features, %1$sbuy " -"Relevanssi Premium here%2$s." -msgstr "" - -#: lib/tabs/debugging-tab.php:56 -msgid "" -"In order to figure out problems with indexing posts, you can test how " -"Relevanssi sees the post by entering the post ID number in the field below." -msgstr "" - -#: lib/tabs/debugging-tab.php:60 -msgid "" -"You can also check user profiles and taxonomy terms by choosing the type " -"from the dropdown." -msgstr "" - -#: lib/tabs/debugging-tab.php:65 -#, php-format -msgid "" -"In Relevanssi Premium, you can find this feature for each post on the post " -"edit page. %1$sBuy Relevanssi Premium here%2$s." -msgstr "" - -#: lib/tabs/debugging-tab.php:68 lib/tabs/debugging-tab.php:110 -msgid "The ID" -msgstr "" - -#: lib/tabs/debugging-tab.php:83 premium/click-tracking.php:487 -msgid "Post" -msgstr "" - -#: lib/tabs/debugging-tab.php:87 -msgid "Taxonomy term" -msgstr "" - -#: lib/tabs/debugging-tab.php:91 -msgid "User" -msgstr "" - -#: lib/tabs/debugging-tab.php:100 lib/tabs/debugging-tab.php:122 -msgid "Check the post" -msgstr "" - -#: lib/tabs/debugging-tab.php:106 -msgid "What does the post look like in the database?" -msgstr "" - -#: lib/tabs/debugging-tab.php:108 -msgid "" -"This feature will show you how the post looks like in the database. It can " -"sometimes be very helpful for debugging why a post isn't indexed the way you " -"expect it to be." -msgstr "" - -#: lib/tabs/debugging-tab.php:128 -msgid "Debugging information" -msgstr "" - -#: lib/tabs/debugging-tab.php:143 -msgid "Indexing query" -msgstr "" - -#: lib/tabs/debugging-tab.php:150 -msgid "Debugging mode" -msgstr "" - -#: lib/tabs/debugging-tab.php:157 lib/tabs/debugging-tab.php:160 -msgid "Enable the debugging mode." -msgstr "" - -#: lib/tabs/debugging-tab.php:162 -msgid "" -"Relevanssi support may ask you to enable the debugging mode. When you check " -"this box, it's possible to see debugging information from the front-end." -msgstr "" - -#: lib/tabs/excerpts-tab.php:86 -msgid "Custom excerpts/snippets" -msgstr "" - -#: lib/tabs/excerpts-tab.php:91 -msgid "Custom search result snippets" -msgstr "" - -#: lib/tabs/excerpts-tab.php:96 -msgid "Create custom search result snippets" -msgstr "" - -#: lib/tabs/excerpts-tab.php:98 -msgid "Only enable this if you actually use the custom excerpts." -msgstr "" - -#: lib/tabs/excerpts-tab.php:105 -#, php-format -msgid "" -"Looks like you are using Divi. In order to use custom excerpts with Divi, " -"you need to make some changes to your templates. %1$sSee instructions " -"here%2$s." -msgstr "" - -#: lib/tabs/excerpts-tab.php:117 -msgid "Length of the snippet" -msgstr "" - -#: lib/tabs/excerpts-tab.php:127 -msgid "Excerpt length type" -msgstr "" - -#: lib/tabs/excerpts-tab.php:135 -msgid "characters" -msgstr "" - -#: lib/tabs/excerpts-tab.php:136 -msgid "words" -msgstr "" - -#: lib/tabs/excerpts-tab.php:138 -msgid "" -"Using words is much faster than characters. Don't use characters, unless you " -"have a really good reason and your posts are short." -msgstr "" - -#: lib/tabs/excerpts-tab.php:154 -msgid "Allowable tags in excerpts" -msgstr "" - -#: lib/tabs/excerpts-tab.php:164 -msgid "" -"List all tags you want to allow in excerpts. For example: <p><a>" -"<strong>." -msgstr "" - -#: lib/tabs/excerpts-tab.php:175 -msgid "Use custom fields for excerpts" -msgstr "" - -#: lib/tabs/excerpts-tab.php:186 -msgid "Use custom field content for building excerpts" -msgstr "" - -#: lib/tabs/excerpts-tab.php:188 -msgid "" -"Use the custom fields setting for indexing for excerpt-making as well. " -"Enabling this option will show custom field content in Relevanssi-generated " -"excerpts." -msgstr "" - -#: lib/tabs/excerpts-tab.php:191 -msgid "Enable this option to use PDF content for excerpts." -msgstr "" - -#: lib/tabs/excerpts-tab.php:204 -msgid "Create custom field specific excerpts" -msgstr "" - -#: lib/tabs/excerpts-tab.php:206 -msgid "" -"The default method of adding custom field content to excerpts cannot tell " -"which custom fields is the source of the excerpts. Using custom field " -"specific excerpts is slower, but you can tell which custom field was the " -"source of the excerpt." -msgstr "" - -#: lib/tabs/excerpts-tab.php:208 -msgid "Current custom field setting" -msgstr "" - -#: lib/tabs/excerpts-tab.php:211 -msgid "all visible custom fields" -msgstr "" - -#: lib/tabs/excerpts-tab.php:213 -msgid "all custom fields" -msgstr "" - -#: lib/tabs/excerpts-tab.php:217 -msgid "Just PDF content" -msgstr "" - -#: lib/tabs/excerpts-tab.php:219 -msgid "None selected" -msgstr "" - -#: lib/tabs/excerpts-tab.php:228 lib/tabs/excerpts-tab.php:231 -msgid "List custom fields" -msgstr "" - -#: lib/tabs/excerpts-tab.php:232 -msgid "Click the button above to see the list of indexed custom fields." -msgstr "" - -#: lib/tabs/excerpts-tab.php:235 -msgid "" -"Fields excluded from ACF settings and with filter functions are included " -"here." -msgstr "" - -#: lib/tabs/excerpts-tab.php:242 -msgid "Search hit highlighting" -msgstr "" - -#: lib/tabs/excerpts-tab.php:253 -msgid "Highlight type" -msgstr "" - -#: lib/tabs/excerpts-tab.php:263 -msgid "No highlighting" -msgstr "" - -#: lib/tabs/excerpts-tab.php:267 lib/tabs/excerpts-tab.php:277 -msgid "Text color" -msgstr "" - -#: lib/tabs/excerpts-tab.php:268 lib/tabs/excerpts-tab.php:291 -msgid "Background color" -msgstr "" - -#: lib/tabs/excerpts-tab.php:269 -msgid "CSS Style" -msgstr "" - -#: lib/tabs/excerpts-tab.php:270 -msgid "CSS Class" -msgstr "" - -#: lib/tabs/excerpts-tab.php:272 lib/tabs/excerpts-tab.php:435 -msgid "Requires custom snippets to work." -msgstr "" - -#: lib/tabs/excerpts-tab.php:305 -msgid "CSS style for highlights" -msgstr "" - -#: lib/tabs/excerpts-tab.php:316 -#, php-format -msgid "" -"The highlights will be wrapped in a %s with this CSS in the style parameter." -msgstr "" - -#: lib/tabs/excerpts-tab.php:321 -msgid "CSS class for highlights" -msgstr "" - -#: lib/tabs/excerpts-tab.php:332 -#, php-format -msgid "The highlights will be wrapped in a %s with this class." -msgstr "" - -#: lib/tabs/excerpts-tab.php:337 -msgid "Highlight in titles" -msgstr "" - -#: lib/tabs/excerpts-tab.php:348 -msgid "Highlight query terms in titles" -msgstr "" - -#: lib/tabs/excerpts-tab.php:351 -#, php-format -msgid "" -"Highlights in titles require changes to the search results template. You " -"need to replace %1$s in the search results template with %2$s. For more " -"information, see the contextual help." -msgstr "" - -#: lib/tabs/excerpts-tab.php:356 -msgid "Highlight in documents" -msgstr "" - -#: lib/tabs/excerpts-tab.php:367 -msgid "Highlight query terms in documents" -msgstr "" - -#: lib/tabs/excerpts-tab.php:370 -#, php-format -msgid "" -"Highlights hits when user opens the post from search results. This requires " -"an extra parameter (%s) to the links from the search results pages, which " -"Relevanssi should add automatically." -msgstr "" - -#: lib/tabs/excerpts-tab.php:375 -msgid "Highlight in comments" -msgstr "" - -#: lib/tabs/excerpts-tab.php:386 -msgid "Highlight query terms in comments" -msgstr "" - -#: lib/tabs/excerpts-tab.php:388 -msgid "" -"Highlights hits in comments when user opens the post from search results." -msgstr "" - -#: lib/tabs/excerpts-tab.php:393 -msgid "Expand highlights" -msgstr "" - -#: lib/tabs/excerpts-tab.php:404 -msgid "Expand highlights to cover full words" -msgstr "" - -#: lib/tabs/excerpts-tab.php:406 -msgid "" -"When a highlight matches part of the word, if this option is enabled, the " -"highlight will be expanded to highlight the whole word." -msgstr "" - -#: lib/tabs/excerpts-tab.php:411 -msgid "Breakdown of search results" -msgstr "" - -#: lib/tabs/excerpts-tab.php:422 -msgid "Breakdown of search hits in excerpts" -msgstr "" - -#: lib/tabs/excerpts-tab.php:433 -msgid "Show the breakdown of search hits in the excerpts." -msgstr "" - -#: lib/tabs/excerpts-tab.php:440 -msgid "The breakdown format" -msgstr "" - -#: lib/tabs/excerpts-tab.php:450 -msgid "" -"Use %body%, %title%, %categories%, %tags%, %taxonomies%, %comments%, " -"%customfields%, %author%, %excerpt% and %mysqlcolumns% to display the number " -"of hits (in different parts of the post), %total% for total hits, %score% to " -"display the document weight and %terms% to show how many hits each search " -"term got." -msgstr "" - -#: lib/tabs/indexing-tab.php:116 lib/tabs/indexing-tab.php:122 -msgid "Build the index" -msgstr "" - -#: lib/tabs/indexing-tab.php:117 lib/tabs/indexing-tab.php:124 -msgid "Index unindexed posts" -msgstr "" - -#: lib/tabs/indexing-tab.php:122 -#, php-format -msgid "%s empties the existing index and rebuilds it from scratch." -msgstr "" - -#: lib/tabs/indexing-tab.php:124 -#, php-format -msgid "" -"%s doesn't empty the index and only indexes those posts that are not " -"indexed. You can use it if you have to interrupt building the index." -msgstr "" - -#: lib/tabs/indexing-tab.php:127 -msgid "This doesn't index any taxonomy terms or users." -msgstr "" - -#: lib/tabs/indexing-tab.php:134 premium/tabs/attachments-tab.php:62 -msgid "Time elapsed" -msgstr "" - -#: lib/tabs/indexing-tab.php:134 premium/tabs/attachments-tab.php:62 -msgid "Time remaining" -msgstr "" - -#: lib/tabs/indexing-tab.php:134 premium/tabs/attachments-tab.php:62 -msgid "some time" -msgstr "" - -#: lib/tabs/indexing-tab.php:136 -msgid "" -"Indexing should respond quickly. If nothing happens in couple of minutes, " -"it's probably stuck. The most common reasons for indexing issues are " -"incompatible shortcodes, so try disabling the shortcode expansion setting " -"and try again. Also, if you've just updated Relevanssi, doing a hard refresh " -"in your browser will make sure your browser is not trying to use an outdated " -"version of the Relevanssi scripts." -msgstr "" - -#: lib/tabs/indexing-tab.php:140 -msgid "State of the index" -msgstr "" - -#: lib/tabs/indexing-tab.php:141 -msgid "document in the index." -msgstr "" - -#: lib/tabs/indexing-tab.php:143 -msgid "user in the index." -msgstr "" - -#: lib/tabs/indexing-tab.php:144 -msgid "taxonomy term in the index." -msgstr "" - -#: lib/tabs/indexing-tab.php:147 -msgid "term in the index." -msgstr "" - -#: lib/tabs/indexing-tab.php:148 -msgid "is the lowest post ID indexed." -msgstr "" - -#: lib/tabs/indexing-tab.php:150 -#, php-format -msgid "" -"These values may be inaccurate. If you need exact values, %1$supdate the " -"counts%2$s" -msgstr "" - -#: lib/tabs/indexing-tab.php:160 -msgid "" -"WARNING: You've chosen no post types to index. Nothing will be indexed. " -"Choose some post types to index." -msgstr "" - -#: lib/tabs/indexing-tab.php:165 -msgid "Indexing options" -msgstr "" - -#: lib/tabs/indexing-tab.php:167 -msgid "" -"Any changes to the settings on this page require reindexing before they take " -"effect." -msgstr "" - -#: lib/tabs/indexing-tab.php:171 -msgid "Post types" -msgstr "" - -#: lib/tabs/indexing-tab.php:175 -msgid "Post types to index" -msgstr "" - -#: lib/tabs/indexing-tab.php:179 -msgid "Type" -msgstr "" - -#: lib/tabs/indexing-tab.php:180 lib/tabs/indexing-tab.php:272 -#: premium/interface.php:720 -msgid "Index" -msgstr "" - -#: lib/tabs/indexing-tab.php:181 -msgid "Excluded from search?" -msgstr "" - -#: lib/tabs/indexing-tab.php:198 -#, php-format -msgid "Index post type %s" -msgstr "" - -#: lib/tabs/indexing-tab.php:200 lib/tabs/indexing-tab.php:294 -#: premium/interface.php:737 premium/interface.php:748 -msgid "yes" -msgstr "" - -#: lib/tabs/indexing-tab.php:202 -#, php-format -msgid "Post type %s is excluded from search" -msgstr "" - -#: lib/tabs/indexing-tab.php:204 lib/tabs/indexing-tab.php:290 -#: premium/interface.php:739 premium/interface.php:744 -msgid "no" -msgstr "" - -#: lib/tabs/indexing-tab.php:206 -#, php-format -msgid "Post type %s can be searched" -msgstr "" - -#: lib/tabs/indexing-tab.php:237 -msgid "" -"If you want to index a post type that's marked 'Excluded from search', you " -"can do that without worrying about it – but you need to uncheck the 'Respect " -"exclude_from_search' setting from the Searching tab." -msgstr "" - -#: lib/tabs/indexing-tab.php:249 -msgid "Index image files" -msgstr "" - -#: lib/tabs/indexing-tab.php:254 -msgid "Index image attachments" -msgstr "" - -#: lib/tabs/indexing-tab.php:256 -msgid "" -"If this option is enabled, Relevanssi will include image attachments in the " -"index. If the option is disabled, only other attachment types are included." -msgstr "" - -#: lib/tabs/indexing-tab.php:258 -#, php-format -msgid "" -"For more detailed control over the attachment type indexing, see " -"%1$sControlling attachment types in the Knowledge base%2$s." -msgstr "" - -#: lib/tabs/indexing-tab.php:264 premium/interface.php:713 -msgid "Taxonomies" -msgstr "" - -#: lib/tabs/indexing-tab.php:271 premium/interface.php:719 -msgid "Taxonomy" -msgstr "" - -#: lib/tabs/indexing-tab.php:273 premium/interface.php:721 -msgid "Public?" -msgstr "" - -#: lib/tabs/indexing-tab.php:289 -#, php-format -msgid "Index taxonomy %s" -msgstr "" - -#: lib/tabs/indexing-tab.php:292 premium/interface.php:746 -#, php-format -msgid "Taxonomy %s is not public" -msgstr "" - -#: lib/tabs/indexing-tab.php:296 premium/interface.php:750 -#, php-format -msgid "Taxonomy %s is public" -msgstr "" - -#: lib/tabs/indexing-tab.php:318 -msgid "" -"If you check a taxonomy here, the terms for that taxonomy are indexed with " -"the posts. If you for example choose \"post_tag\", searching for a tag will " -"find all posts that have the tag." -msgstr "" - -#: lib/tabs/indexing-tab.php:329 lib/tabs/indexing-tab.php:343 -msgid "none" -msgstr "" - -#: lib/tabs/indexing-tab.php:330 -msgid "comments" -msgstr "" - -#: lib/tabs/indexing-tab.php:331 -msgid "comments and pingbacks" -msgstr "" - -#: lib/tabs/indexing-tab.php:333 -msgid "" -"If you choose to index comments, you can choose if you want to index just " -"comments, or everything including comments and track- and pingbacks." -msgstr "" - -#: lib/tabs/indexing-tab.php:344 -msgid "all" -msgstr "" - -#: lib/tabs/indexing-tab.php:345 -msgid "visible" -msgstr "" - -#: lib/tabs/indexing-tab.php:346 lib/tabs/indexing-tab.php:378 -msgid "some" -msgstr "" - -#: lib/tabs/indexing-tab.php:350 -msgid "'All' indexes all custom fields for posts." -msgstr "" - -#: lib/tabs/indexing-tab.php:352 -msgid "" -"'Visible' only includes the custom fields that are visible in the user " -"interface (with names that don't start with an underscore)." -msgstr "" - -#: lib/tabs/indexing-tab.php:354 -msgid "'Some' lets you choose individual custom fields to index." -msgstr "" - -#: lib/tabs/indexing-tab.php:360 -msgid "" -"Advanced Custom Fields has lots of invisible custom fields with meta data. " -"Selecting \"all\" will include lots of garbage in the index and excerpts. " -"\"Visible\" is usually a better option with ACF." -msgstr "" - -#: lib/tabs/indexing-tab.php:371 -msgid "Custom fields to index" -msgstr "" - -#: lib/tabs/indexing-tab.php:373 -msgid "" -"Enter a comma-separated list of custom fields to include in the index. With " -"Relevanssi Premium, you can also use 'fieldname_%_subfieldname' notation for " -"ACF repeater fields." -msgstr "" - -#: lib/tabs/indexing-tab.php:374 -msgid "" -"You can use 'relevanssi_index_custom_fields' filter hook to adjust which " -"custom fields are indexed." -msgstr "" - -#: lib/tabs/indexing-tab.php:378 -#, php-format -msgid "" -"If you want the SKU included, choose %1$s and enter %2$s. Also see the " -"contextual help for more details." -msgstr "" - -#: lib/tabs/indexing-tab.php:385 -msgid "Author display names" -msgstr "" - -#: lib/tabs/indexing-tab.php:390 -msgid "Index the post author display name" -msgstr "" - -#: lib/tabs/indexing-tab.php:392 -msgid "" -"Searching for the post author display name will return posts by that author." -msgstr "" - -#: lib/tabs/indexing-tab.php:403 -msgid "Index the post excerpt" -msgstr "" - -#: lib/tabs/indexing-tab.php:405 -msgid "Relevanssi will find posts by the content in the excerpt." -msgstr "" - -#: lib/tabs/indexing-tab.php:407 -msgid "" -"WooCommerce stores the product short description in the excerpt, so it's a " -"good idea to index excerpts." -msgstr "" - -#: lib/tabs/indexing-tab.php:414 -msgid "Shortcodes" -msgstr "" - -#: lib/tabs/indexing-tab.php:419 -msgid "Expand shortcodes" -msgstr "" - -#: lib/tabs/indexing-tab.php:424 -msgid "Expand shortcodes when indexing" -msgstr "" - -#: lib/tabs/indexing-tab.php:427 -msgid "" -"WooCommerce has shortcodes that don't work well with Relevanssi. With " -"WooCommerce, make sure the option is disabled." -msgstr "" - -#: lib/tabs/indexing-tab.php:429 -msgid "" -"If checked, Relevanssi will expand shortcodes in post content before " -"indexing. Otherwise shortcodes will be stripped." -msgstr "" - -#: lib/tabs/indexing-tab.php:430 -msgid "" -"If you use shortcodes to include dynamic content, Relevanssi will not keep " -"the index updated, the index will reflect the status of the shortcode " -"content at the moment of indexing." -msgstr "" - -#: lib/tabs/indexing-tab.php:444 -msgid "Advanced indexing settings" -msgstr "" - -#: lib/tabs/indexing-tab.php:446 -msgid "Show advanced settings" -msgstr "" - -#: lib/tabs/indexing-tab.php:451 -msgid "Minimum word length" -msgstr "" - -#: lib/tabs/indexing-tab.php:455 -msgid "Words shorter than this many letters will not be indexed." -msgstr "" - -#: lib/tabs/indexing-tab.php:457 -#, php-format -msgid "" -"To enable one-letter searches, you need to add a filter function on the " -"filter hook %1$s that returns %2$s." -msgstr "" - -#: lib/tabs/indexing-tab.php:461 -msgid "Punctuation control" -msgstr "" - -#: lib/tabs/indexing-tab.php:462 -msgid "" -"Here you can adjust how the punctuation is controlled. For more information, " -"see help. Remember that any changes here require reindexing, otherwise " -"searches will fail to find posts they should." -msgstr "" - -#: lib/tabs/indexing-tab.php:466 -msgid "Hyphens and dashes" -msgstr "" - -#: lib/tabs/indexing-tab.php:470 lib/tabs/indexing-tab.php:497 -#: lib/tabs/indexing-tab.php:511 -msgid "Keep" -msgstr "" - -#: lib/tabs/indexing-tab.php:471 lib/tabs/indexing-tab.php:484 -#: lib/tabs/indexing-tab.php:498 lib/tabs/indexing-tab.php:512 -msgid "Replace with spaces" -msgstr "" - -#: lib/tabs/indexing-tab.php:472 lib/tabs/indexing-tab.php:485 -#: lib/tabs/indexing-tab.php:499 lib/tabs/indexing-tab.php:513 -#: premium/tabs/redirects-tab.php:66 premium/tabs/redirects-tab.php:108 -msgid "Remove" -msgstr "" - -#: lib/tabs/indexing-tab.php:474 -msgid "" -"How Relevanssi should handle hyphens and dashes (en and em dashes)? " -"Replacing with spaces is generally the best option, but in some cases " -"removing completely is the best option. Keeping them is rarely the best " -"option." -msgstr "" - -#: lib/tabs/indexing-tab.php:480 -msgid "Apostrophes and quotes" -msgstr "" - -#: lib/tabs/indexing-tab.php:487 -msgid "" -"How Relevanssi should handle apostrophes and quotes? It's not possible to " -"keep them; that would lead to problems. Default behaviour is to replace with " -"spaces, but sometimes removing makes sense." -msgstr "" - -#: lib/tabs/indexing-tab.php:493 -msgid "Ampersands" -msgstr "" - -#: lib/tabs/indexing-tab.php:501 -msgid "" -"How Relevanssi should handle ampersands? Replacing with spaces is generally " -"the best option, but if you talk a lot about D&D, for example, keeping " -"the ampersands is useful." -msgstr "" - -#: lib/tabs/indexing-tab.php:507 -msgid "Decimal separators" -msgstr "" - -#: lib/tabs/indexing-tab.php:515 -msgid "" -"How Relevanssi should handle periods between decimals? Replacing with spaces " -"is the default option, but that often leads to the numbers being removed " -"completely. If you need to search decimal numbers a lot, keep the periods." -msgstr "" - -#: lib/tabs/indexing-tab.php:525 -msgid "Hide advanced settings" -msgstr "" - -#: lib/tabs/logging-tab.php:32 -msgid "Enable logs" -msgstr "" - -#: lib/tabs/logging-tab.php:36 lib/tabs/logging-tab.php:39 -msgid "Keep a log of user queries." -msgstr "" - -#: lib/tabs/logging-tab.php:46 -#, php-format -msgid "" -"If enabled, Relevanssi will log user queries. The logs can be examined under " -"'%1$s' on the Dashboard admin menu and are stored in the %2$s database table." -msgstr "" - -#: lib/tabs/logging-tab.php:56 -msgid "Log user IP" -msgstr "" - -#: lib/tabs/logging-tab.php:60 lib/tabs/logging-tab.php:63 -msgid "Log the user's IP with the queries." -msgstr "" - -#: lib/tabs/logging-tab.php:66 -msgid "" -"If enabled, Relevanssi will log user's IP adress with the queries. Note that " -"this may be illegal where you live, and in EU will create a person registry " -"that falls under the GDPR." -msgstr "" - -#: lib/tabs/logging-tab.php:71 -msgid "Exclude users" -msgstr "" - -#: lib/tabs/logging-tab.php:75 -msgid "" -"Comma-separated list of numeric user IDs or user login names that will not " -"be logged." -msgstr "" - -#: lib/tabs/logging-tab.php:85 premium/click-tracking.php:735 -msgid "Trim logs" -msgstr "" - -#: lib/tabs/logging-tab.php:89 -msgid "How many days of logs to keep in the database." -msgstr "" - -#: lib/tabs/logging-tab.php:93 -msgid "" -"Big log database table will eventually start to slow down the search, so " -"it's a good idea to use some level of automatic log trimming." -msgstr "" - -#: lib/tabs/logging-tab.php:98 -#, php-format -msgid "Set to %d for no trimming." -msgstr "" - -#: lib/tabs/logging-tab.php:107 -msgid "Export logs" -msgstr "" - -#: lib/tabs/logging-tab.php:110 -msgid "Export the log as a CSV file" -msgstr "" - -#: lib/tabs/logging-tab.php:111 -msgid "Push the button to export the search log as a CSV file." -msgstr "" - -#: lib/tabs/logging-tab.php:122 premium/click-tracking.php:709 -msgid "Click tracking" -msgstr "" - -#: lib/tabs/logging-tab.php:123 -msgid "" -"Relevanssi Premium has a click tracking feature where you can track which " -"posts are clicked from the search results. That way you can tell what is " -"your most interesting content and how the search is actually used to access " -"posts." -msgstr "" - -#: lib/tabs/overview-tab.php:22 -msgid "Welcome to Relevanssi!" -msgstr "" - -#: lib/tabs/overview-tab.php:41 -msgid "Getting started" -msgstr "" - -#: lib/tabs/overview-tab.php:43 -msgid "" -"You've already installed Relevanssi. That's a great first step towards good " -"search experience!" -msgstr "" - -#: lib/tabs/overview-tab.php:47 -#, php-format -msgid "" -"Now, you need an index. Head over to the %1$s%2$s%3$s tab to set up the " -"basic indexing options and to build the index." -msgstr "" - -#: lib/tabs/overview-tab.php:48 -msgid "You need to check at least the following options:" -msgstr "" - -#: lib/tabs/overview-tab.php:49 -msgid "Make sure the post types you want to include in the index are indexed." -msgstr "" - -#: lib/tabs/overview-tab.php:51 -#, php-format -msgid "" -"Do you use custom fields to store content you want included? If so, add " -"those too. WooCommerce user? You probably want to include %s." -msgstr "" - -#: lib/tabs/overview-tab.php:52 -msgid "" -"Then just save the options and build the index. First time you have to do it " -"manually, but after that, it's fully automatic: all changes are reflected in " -"the index without reindexing. (That said, it's a good idea to rebuild the " -"index once a year.)" -msgstr "" - -#: lib/tabs/overview-tab.php:55 -msgid "Great, you already have an index!" -msgstr "" - -#: lib/tabs/overview-tab.php:59 -#, php-format -msgid "" -"On the %1$s%2$s%3$s tab, choose whether you want the default operator to be " -"AND (less results, but more precise) or OR (more results, less precise)." -msgstr "" - -#: lib/tabs/overview-tab.php:63 -#, php-format -msgid "" -"The next step is the %1$s%2$s%3$s tab, where you can enable the custom " -"excerpts that show the relevant part of post in the search results pages." -msgstr "" - -#: lib/tabs/overview-tab.php:64 -msgid "" -"There are couple of options related to that, so if you want highlighting in " -"the results, you can adjust the styles for that to suit the look of your " -"site." -msgstr "" - -#: lib/tabs/overview-tab.php:67 -msgid "" -"That's about it! Now you should have Relevanssi up and running. The rest of " -"the options is mostly fine-tuning." -msgstr "" - -#: lib/tabs/overview-tab.php:70 -msgid "" -"Relevanssi doesn't have a separate search widget. Instead, Relevanssi uses " -"the default search widget. Any standard search form will do!" -msgstr "" - -#: lib/tabs/overview-tab.php:74 -msgid "Relevanssi Live Ajax Search" -msgstr "" - -#: lib/tabs/overview-tab.php:77 -#, php-format -msgid "" -"If you want a live search results, you can use the Relevanssi Live Ajax " -"Search plugin. %1$sYou can find it in the plugin repository%2$s. It will " -"make your search forms show instant results, powered by Relevanssi." -msgstr "" - -#: lib/tabs/overview-tab.php:81 -msgid "Privacy and GDPR compliance" -msgstr "" - -#: lib/tabs/overview-tab.php:84 -#, php-format -msgid "" -"%1$sGDPR Compliance at Relevanssi knowledge base%2$s explains how using " -"Relevanssi affects the GDPR compliance and the privacy policies of your " -"site. Relevanssi also supports the %3$sprivacy policy tool%2$s and the " -"WordPress user data export and erase tools." -msgstr "" - -#: lib/tabs/overview-tab.php:88 -msgid "For more information" -msgstr "" - -#: lib/tabs/overview-tab.php:90 -msgid "" -"Relevanssi uses the WordPress contextual help. Click 'Help' on the top right " -"corner for more information on many Relevanssi topics." -msgstr "" - -#: lib/tabs/overview-tab.php:92 -#, php-format -msgid "" -"%1$sRelevanssi knowledge base%2$s has lots of information about advanced " -"Relevanssi use, including plenty of code samples." -msgstr "" - -#: lib/tabs/overview-tab.php:96 -msgid "Do you like Relevanssi?" -msgstr "" - -#: lib/tabs/overview-tab.php:98 -msgid "" -"If you do, the best way to show your appreciation is to spread the word and " -"perhaps give us a good review on WordPress.org." -msgstr "" - -#: lib/tabs/overview-tab.php:100 -#, php-format -msgid "" -"If you like Relevanssi, leaving a five-star review on WordPress.org will " -"help others discover Relevanssi. %1$sYou can add your review here%2$s." -msgstr "" - -#: lib/tabs/overview-tab.php:106 -msgid "Buy Relevanssi Premium" -msgstr "" - -#: lib/tabs/overview-tab.php:109 -msgid "Buy Relevanssi Premium now" -msgstr "" - -#: lib/tabs/overview-tab.php:111 -#, php-format -msgid "" -"use coupon code %1$s for 20%% discount (valid at least until the end of %2$s)" -msgstr "" - -#: lib/tabs/overview-tab.php:112 -msgid "Here are some improvements Relevanssi Premium offers:" -msgstr "" - -#: lib/tabs/overview-tab.php:114 -msgid "PDF content indexing" -msgstr "" - -#: lib/tabs/overview-tab.php:115 -msgid "A Related posts feature" -msgstr "" - -#: lib/tabs/overview-tab.php:116 -msgid "Index and search user profile pages" -msgstr "" - -#: lib/tabs/overview-tab.php:117 -msgid "Index and search taxonomy term pages" -msgstr "" - -#: lib/tabs/overview-tab.php:118 -msgid "Multisite searches across many subsites" -msgstr "" - -#: lib/tabs/overview-tab.php:119 -msgid "WP CLI commands" -msgstr "" - -#: lib/tabs/overview-tab.php:120 -msgid "Adjust weights separately for each post type and taxonomy" -msgstr "" - -#: lib/tabs/overview-tab.php:121 -msgid "Internal link anchors can be search terms for the target posts" -msgstr "" - -#: lib/tabs/overview-tab.php:122 -msgid "Index and search any columns in the wp_posts database" -msgstr "" - -#: lib/tabs/overview-tab.php:123 -msgid "" -"Hide Relevanssi branding from the User Searches page on a client installation" -msgstr "" - -#: lib/tabs/overview-tab.php:124 -msgid "Redirect search queries to custom URLs" -msgstr "" - -#: lib/tabs/redirects-tab.php:20 -msgid "" -"With Relevanssi Premium, you can set up redirects. These are keywords that " -"automatically redirect the user to certain page, without going through the " -"usual search process. For example, you could set it up so that all searches " -"for \"job\" automatically lead to your \"Careers\" page." -msgstr "" - -#: lib/tabs/search-page.php:18 -msgid "" -"You can use this search to perform Relevanssi searches without any " -"restrictions from WordPress. You can search all post types here." -msgstr "" - -#: lib/tabs/search-page.php:24 -msgid "Search terms" -msgstr "" - -#: lib/tabs/search-page.php:32 -msgid "Post type" -msgstr "" - -#: lib/tabs/search-page.php:36 -msgid "Any" -msgstr "" - -#: lib/tabs/search-page.php:55 -msgid "Users" -msgstr "" - -#: lib/tabs/search-page.php:64 -msgid "Posts per page" -msgstr "" - -#: lib/tabs/search-page.php:68 -msgid "All" -msgstr "" - -#: lib/tabs/search-page.php:77 -msgid "Search parameters" -msgstr "" - -#: lib/tabs/search-page.php:82 -#, php-format -msgid "" -"Use query parameter formatting here, the same that would appear on search " -"page results URL. For example %s." -msgstr "" - -#: lib/tabs/search-page.php:89 -msgid "Search" -msgstr "" - -#: lib/tabs/searching-tab.php:76 -msgid "Default operator" -msgstr "" - -#: lib/tabs/searching-tab.php:80 -msgid "AND - require all terms" -msgstr "" - -#: lib/tabs/searching-tab.php:81 -msgid "OR - any term present is enough" -msgstr "" - -#: lib/tabs/searching-tab.php:83 -msgid "This setting determines the default operator for the search." -msgstr "" - -#: lib/tabs/searching-tab.php:87 -#, php-format -msgid "" -"You can override this setting with the %1$s query parameter, like this: %2$s" -msgstr "" - -#: lib/tabs/searching-tab.php:94 -msgid "Fallback to OR" -msgstr "" - -#: lib/tabs/searching-tab.php:98 lib/tabs/searching-tab.php:101 -msgid "Disable the OR fallback." -msgstr "" - -#: lib/tabs/searching-tab.php:104 -msgid "" -"By default, if AND search fails to find any results, Relevanssi will switch " -"the operator to OR and run the search again. You can prevent that by " -"checking this option." -msgstr "" - -#: lib/tabs/searching-tab.php:109 -msgid "Default order" -msgstr "" - -#: lib/tabs/searching-tab.php:113 -msgid "Relevance (highly recommended)" -msgstr "" - -#: lib/tabs/searching-tab.php:114 -msgid "Post date" -msgstr "" - -#: lib/tabs/searching-tab.php:117 -#, php-format -msgid "" -"If you want to override this or use multi-layered ordering (eg. first order " -"by relevance, but sort ties by post title), you can use the %s query " -"variable. See Help for more information." -msgstr "" - -#: lib/tabs/searching-tab.php:119 -msgid "" -"If you want date-based results, see the recent post bonus in the Weights " -"section." -msgstr "" - -#: lib/tabs/searching-tab.php:125 -msgid "Keyword matching" -msgstr "" - -#: lib/tabs/searching-tab.php:129 -msgid "Whole words" -msgstr "" - -#: lib/tabs/searching-tab.php:130 lib/tabs/searching-tab.php:135 -msgid "Partial words" -msgstr "" - -#: lib/tabs/searching-tab.php:131 -msgid "Partial words if no hits for whole words" -msgstr "" - -#: lib/tabs/searching-tab.php:135 -#, php-format -msgid "" -"Choosing the \"%1$s\" option may lead to unexpected results. Most of the " -"time the \"%2$s\" option is the better choice." -msgstr "" - -#: lib/tabs/searching-tab.php:135 -msgid "Partial words if not hits for whole words" -msgstr "" - -#: lib/tabs/searching-tab.php:137 -msgid "" -"Whole words means Relevanssi only finds posts that include the whole search " -"term." -msgstr "" - -#: lib/tabs/searching-tab.php:138 -msgid "" -"Partial words also includes cases where the word in the index begins or ends " -"with the search term (searching for 'ana' will match 'anaconda' or 'banana', " -"but not 'banal'). See Help, if you want to make Relevanssi match also inside " -"words." -msgstr "" - -#: lib/tabs/searching-tab.php:143 -msgid "Weights" -msgstr "" - -#: lib/tabs/searching-tab.php:146 -msgid "" -"All the weights in the table are multipliers. To increase the weight of an " -"element, use a higher number. To make an element less significant, use a " -"number lower than 1." -msgstr "" - -#: lib/tabs/searching-tab.php:150 -msgid "Element" -msgstr "" - -#: lib/tabs/searching-tab.php:151 -msgid "Weight" -msgstr "" - -#: lib/tabs/searching-tab.php:156 -msgid "Content" -msgstr "" - -#: lib/tabs/searching-tab.php:164 -msgid "Titles" -msgstr "" - -#: lib/tabs/searching-tab.php:177 -msgid "Comment text" -msgstr "" - -#: lib/tabs/searching-tab.php:206 -msgid "Boost exact matches" -msgstr "" - -#: lib/tabs/searching-tab.php:210 lib/tabs/searching-tab.php:213 -msgid "Give boost to exact matches." -msgstr "" - -#: lib/tabs/searching-tab.php:217 -#, php-format -msgid "" -"If you enable this option, matches where the search query appears in title " -"or content as a phrase will get a weight boost. To adjust the boost, you can " -"use the %s filter hook. See Help for more details." -msgstr "" - -#: lib/tabs/searching-tab.php:225 -msgid "WPML" -msgstr "" - -#: lib/tabs/searching-tab.php:229 lib/tabs/searching-tab.php:232 -msgid "Limit results to current language." -msgstr "" - -#: lib/tabs/searching-tab.php:235 -msgid "" -"Enabling this option will restrict the results to the currently active " -"language. If the option is disabled, results will include posts in all " -"languages." -msgstr "" - -#: lib/tabs/searching-tab.php:242 -msgid "Polylang" -msgstr "" - -#: lib/tabs/searching-tab.php:246 lib/tabs/searching-tab.php:249 -msgid "Allow results from all languages." -msgstr "" - -#: lib/tabs/searching-tab.php:252 -msgid "" -"By default Polylang restricts the search to the current language. Enabling " -"this option will lift this restriction." -msgstr "" - -#: lib/tabs/searching-tab.php:262 lib/tabs/searching-tab.php:265 -msgid "Use Relevanssi for admin searches." -msgstr "" - -#: lib/tabs/searching-tab.php:268 -msgid "" -"If checked, Relevanssi will be used for searches in the admin interface. The " -"page search doesn't use Relevanssi, because WordPress works like that." -msgstr "" - -#: lib/tabs/searching-tab.php:274 -#, php-format -msgid "Respect %s" -msgstr "" - -#: lib/tabs/searching-tab.php:278 -msgid "Respect exclude_from_search for custom post types" -msgstr "" - -#: lib/tabs/searching-tab.php:282 -#, php-format -msgid "Respect %s for custom post types" -msgstr "" - -#: lib/tabs/searching-tab.php:284 -msgid "" -"If checked, Relevanssi won't display posts of custom post types that have " -"'exclude_from_search' set to true." -msgstr "" - -#: lib/tabs/searching-tab.php:296 -msgid "" -"You probably should uncheck this option, because you've set Relevanssi to " -"index the following non-public post types:" -msgstr "" - -#: lib/tabs/searching-tab.php:309 -msgid "Throttle searches" -msgstr "" - -#: lib/tabs/searching-tab.php:314 lib/tabs/searching-tab.php:317 -msgid "Throttle searches." -msgstr "" - -#: lib/tabs/searching-tab.php:321 -msgid "Your database is so small that you don't need to enable this." -msgstr "" - -#: lib/tabs/searching-tab.php:323 -msgid "" -"If this option is checked, Relevanssi will limit search results to at most " -"500 results per term. This will improve performance, but may cause some " -"relevant documents to go unfound. See Help for more details." -msgstr "" - -#: lib/tabs/searching-tab.php:325 -msgid "" -"You have the default ordering set to post date and have enabled user or " -"taxonomy term indexing. If you enable the throttle, the search results will " -"only include posts. Users and taxonomy terms will be excluded. Either keep " -"the throttle disabled or set the post ordering to relevance." -msgstr "" - -#: lib/tabs/searching-tab.php:332 lib/tabs/searching-tab.php:338 -msgid "Category restriction" -msgstr "" - -#: lib/tabs/searching-tab.php:358 -msgid "" -"You can restrict search results to a category for all searches. For " -"restricting on a per-search basis and more options (eg. tag restrictions), " -"see Help." -msgstr "" - -#: lib/tabs/searching-tab.php:363 lib/tabs/searching-tab.php:369 -msgid "Category exclusion" -msgstr "" - -#: lib/tabs/searching-tab.php:389 -msgid "" -"Posts in these categories are not included in search results. To exclude the " -"posts completely from the index, see Help." -msgstr "" - -#: lib/tabs/searching-tab.php:394 -msgid "Post exclusion" -msgstr "" - -#: lib/tabs/searching-tab.php:398 -msgid "" -"Enter a comma-separated list of post or page ID's to exclude those pages " -"from the search results." -msgstr "" - -#: lib/tabs/searching-tab.php:400 -msgid "" -"With Relevanssi Premium, it's better to use the check box on post edit " -"pages. That will remove the posts completely from the index, and will work " -"with multisite searches unlike this setting." -msgstr "" - -#: lib/tabs/stopwords-tab.php:29 -msgid "Content stopwords" -msgstr "" - -#: lib/tabs/stopwords-tab.php:38 -msgid "" -"Content stopwords are a premium feature where you can set stopwords that " -"only apply to the post content. Those stopwords will still be indexed if " -"they appear in post titles, tags, categories, custom fields or other parts " -"of the post. To use content stopwords, you need Relevanssi Premium." -msgstr "" - -#: lib/tabs/stopwords-tab.php:68 -msgid "" -"Enter a word here to add it to the list of stopwords. The word will " -"automatically be removed from the index, so re-indexing is not necessary. " -"You can enter many words at the same time, separate words with commas." -msgstr "" - -#: lib/tabs/stopwords-tab.php:76 -msgid "Stopword(s) to add" -msgstr "" - -#: lib/tabs/stopwords-tab.php:80 premium/body-stopwords.php:311 -msgid "Add" -msgstr "" - -#: lib/tabs/stopwords-tab.php:84 -msgid "" -"Here's a list of stopwords in the database. Click a word to remove it from " -"stopwords. Removing stopwords won't automatically return them to index, so " -"you need to re-index all posts after removing stopwords to get those words " -"back to index." -msgstr "" - -#: lib/tabs/stopwords-tab.php:89 -msgid "Current stopwords" -msgstr "" - -#: lib/tabs/stopwords-tab.php:111 -msgid "Remove all stopwords" -msgstr "" - -#: lib/tabs/stopwords-tab.php:118 -msgid "Add default stopwords" -msgstr "" - -#: lib/tabs/stopwords-tab.php:126 lib/tabs/stopwords-tab.php:129 -msgid "Exportable list of stopwords" -msgstr "" - -#: lib/tabs/stopwords-tab.php:131 -msgid "" -"You can copy the list of stopwords here if you want to back up the list, " -"copy it to a different blog or otherwise need the list." -msgstr "" - -#: lib/tabs/stopwords-tab.php:146 -msgid "" -"You are using Polylang and are in \"Show all languages\" mode. Please select " -"a language before adjusting the stopword settings." -msgstr "" - -#: lib/tabs/synonyms-tab.php:54 -msgid "No synonyms!" -msgstr "" - -#: lib/tabs/synonyms-tab.php:57 -msgid "" -"Synonyms are disabled because the searching operator is set to AND. Enable " -"OR searching to use the synonyms." -msgstr "" - -#: lib/tabs/synonyms-tab.php:59 -msgid "" -"If you want to use synonyms in AND searches, enable synonym indexing on the " -"Indexing tab. Also, any changes to the synonyms won't take effect until you " -"rebuild the index." -msgstr "" - -#: lib/tabs/synonyms-tab.php:61 -msgid "" -"Relevanssi Premium has a feature that allows you to include the synonyms in " -"the indexing. This makes it possible to use synonyms in AND searches." -msgstr "" - -#: lib/tabs/synonyms-tab.php:70 -msgid "" -"Add synonyms here to make the searches find better results. If you notice " -"your users frequently misspelling a product name, or for other reasons use " -"many names for one thing, adding synonyms will make the results better." -msgstr "" - -#: lib/tabs/synonyms-tab.php:72 -msgid "" -"Do not go overboard, though, as too many synonyms can make the search " -"confusing: users understand if a search query doesn't match everything, but " -"they get confused if the searches match to unexpected things." -msgstr "" - -#: lib/tabs/synonyms-tab.php:82 -msgid "" -"The format here is key = value. If you add dog = hound to the list of synonyms, searches for dog automatically " -"become a search for dog hound and will thus match to posts that " -"include either dog or hound. This only works in OR " -"searches: in AND searches the synonyms only restrict the search, as now the " -"search only finds posts that contain both dog " -"and hound." -msgstr "" - -#: lib/tabs/synonyms-tab.php:84 -msgid "" -"The synonyms are one direction only. If you want both directions, add the " -"synonym again, reversed: hound = dog." -msgstr "" - -#: lib/tabs/synonyms-tab.php:86 -msgid "" -"It's possible to use phrases for the value, but not for the key. dog = " -"\"great dane\" works, but \"great dane\" = dog doesn't." -msgstr "" - -#: lib/tabs/synonyms-tab.php:100 -msgid "" -"You are using Polylang and are in \"Show all languages\" mode. Please select " -"a language before adjusting the synonym settings." -msgstr "" - -#: lib/user-searches.php:20 -msgid "Relevanssi User Searches" -msgstr "" - -#: lib/user-searches.php:44 -msgid "Enable query logging to see stats here." -msgstr "" - -#: lib/user-searches.php:91 -msgid "From:" -msgstr "" - -#: lib/user-searches.php:92 -msgid "To:" -msgstr "" - -#: lib/user-searches.php:93 -msgid "Filter" -msgstr "" - -#: lib/user-searches.php:96 -msgid "Year so far" -msgstr "" - -#: lib/user-searches.php:97 -msgid "This month" -msgstr "" - -#: lib/user-searches.php:98 -msgid "Last month" -msgstr "" - -#: lib/user-searches.php:99 -msgid "30 days" -msgstr "" - -#: lib/user-searches.php:100 -msgid "This week" -msgstr "" - -#: lib/user-searches.php:101 -msgid "Last week" -msgstr "" - -#: lib/user-searches.php:102 -msgid "7 days" -msgstr "" - -#: lib/user-searches.php:103 -msgid "All history" -msgstr "" - -#: lib/user-searches.php:112 premium/click-tracking.php:475 -msgid "# of Searches" -msgstr "" - -#: lib/user-searches.php:120 -msgid "Total searches" -msgstr "" - -#: lib/user-searches.php:125 -msgid "Searches that found nothing" -msgstr "" - -#: lib/user-searches.php:137 -msgid "Successful searches" -msgstr "" - -#: lib/user-searches.php:138 -msgid "\"Hits\" is the average hits this search query has found." -msgstr "" - -#: lib/user-searches.php:142 -msgid "In order to see the clicks, you need Relevanssi Premium." -msgstr "" - -#: lib/user-searches.php:146 -msgid "" -"In order to see the clicks, you need to enable click tracking. Click " -"tracking is not currently enabled, and you're not collecting new clicks." -msgstr "" - -#: lib/user-searches.php:153 -msgid "Unsuccessful searches" -msgstr "" - -#: lib/user-searches.php:154 -msgid "These queries have found no results." -msgstr "" - -#: lib/user-searches.php:163 -msgid "Reset Logs" -msgstr "" - -#: lib/user-searches.php:169 -msgid "" -"To reset the logs, type \"reset\" into the box here and click the Reset " -"button" -msgstr "" - -#: lib/user-searches.php:176 -msgid "" -"To reset the logs, type \"reset\" into the box here and click the Reset " -"button. This will reset both the search log and the click tracking log." -msgstr "" - -#: lib/user-searches.php:186 -msgid "Reset" -msgstr "" - -#: lib/user-searches.php:320 premium/tabs/redirects-tab.php:55 -msgid "Hits" -msgstr "" - -#: lib/user-searches.php:321 -msgid "Clicks" -msgstr "" - -#: lib/utils.php:540 -msgid "The requested post does not exist." -msgstr "" - -#: lib/utils.php:1391 -msgid "There is no excerpt because this is a protected post." -msgstr "" - -#: premium/admin-ajax.php:158 -msgid "Indexing complete!" -msgstr "" - -#: premium/admin-ajax.php:174 -#, php-format -msgid "Successfully indexed attachment id %d." -msgstr "" - -#: premium/admin-ajax.php:177 -#, php-format -msgid "Failed to index attachment id %1$d: %2$s" -msgstr "" - -#: premium/admin-ajax.php:262 -msgid "Attachment ID" -msgstr "" - -#: premium/admin-ajax.php:322 premium/admin-ajax.php:326 -#, php-format -msgid "%1$d taxonomy term, total %2$d / %3$d." -msgstr "" - -#: premium/admin-ajax.php:361 -msgid "disabled." -msgstr "" - -#: premium/admin-ajax.php:369 -#, php-format -msgid "%1$d post type archive indexed." -msgstr "" - -#: premium/admin-ajax.php:426 -#, php-format -msgid "Indexed %1$d user (total %2$d), processed %3$d / %4$d." -msgstr "" - -#: premium/body-stopwords.php:42 -#, php-format -msgid "Successfully added %1$d/%2$d terms to content stopwords!" -msgstr "" - -#: premium/body-stopwords.php:53 -#, php-format -msgid "Term '%s' added to content stopwords!" -msgstr "" - -#: premium/body-stopwords.php:56 -#, php-format -msgid "Couldn't add term '%s' to content stopwords!" -msgstr "" - -#: premium/body-stopwords.php:193 -msgid "All content stopwords removed! Remember to re-index." -msgstr "" - -#: premium/body-stopwords.php:198 -msgid "There was a problem, and content stopwords couldn't be removed." -msgstr "" - -#: premium/body-stopwords.php:251 -#, php-format -msgid "" -"Term '%s' removed from content stopwords! Re-index to get it back to index." -msgstr "" - -#: premium/body-stopwords.php:266 -#, php-format -msgid "Couldn't remove term '%s' from content stopwords!" -msgstr "" - -#: premium/body-stopwords.php:301 -msgid "" -"Post content stopwords are like stopwords, but they are only applied to the " -"post content. These words can be used for searching and will be found in " -"post titles, custom fields and other indexed content – just not in the post " -"body content. Sometimes a word can be very common, but also have a more " -"specific meaning and use on your site, and making it a content stopword will " -"make it easier to find the specific use cases." -msgstr "" - -#: premium/body-stopwords.php:307 -msgid "Content stopword(s) to add" -msgstr "" - -#: premium/body-stopwords.php:315 -msgid "" -"Here's a list of content stopwords in the database. Click a word to remove " -"it from content stopwords. You need to reindex the database to get the words " -"back in to the index." -msgstr "" - -#: premium/body-stopwords.php:320 -msgid "Current content stopwords" -msgstr "" - -#: premium/body-stopwords.php:337 -msgid "Remove all content stopwords" -msgstr "" - -#: premium/body-stopwords.php:342 premium/body-stopwords.php:345 -msgid "Exportable list of content stopwords" -msgstr "" - -#: premium/body-stopwords.php:347 -msgid "" -"You can copy the list of content stopwords from here if you want to back up " -"the list, copy it to a different blog or otherwise need the list." -msgstr "" - -#: premium/class-relevanssi-wp-cli-command.php:516 -msgid "all keywords" -msgstr "" - -#: premium/class-relevanssi-wp-cli-command.php:535 -msgid "Pinned posts" -msgstr "" - -#: premium/class-relevanssi-wp-cli-command.php:544 -msgid "Unpinned posts" -msgstr "" - -#: premium/class-relevanssi-wp-cli-command.php:552 -msgid "No pinned posts found." -msgstr "" - -#: premium/click-tracking.php:72 premium/click-tracking.php:78 -msgid "Invalid click tracking value format." -msgstr "" - -#: premium/click-tracking.php:376 -#, php-format -msgid "The query '%s' deleted from the click tracking log." -msgstr "" - -#: premium/click-tracking.php:388 -#, php-format -msgid "Couldn't remove the query '%s' from the click tracking log." -msgstr "" - -#: premium/click-tracking.php:410 premium/click-tracking.php:576 -msgid "Back to the User Searches page" -msgstr "" - -#: premium/click-tracking.php:416 premium/click-tracking.php:582 -#, php-format -msgid "Search insights for %s" -msgstr "" - -#: premium/click-tracking.php:476 premium/click-tracking.php:630 -msgid "# of Clicks" -msgstr "" - -#: premium/click-tracking.php:482 -msgid "Posts found with this search term" -msgstr "" - -#: premium/click-tracking.php:488 premium/click-tracking.php:642 -msgid "Times clicked" -msgstr "" - -#: premium/click-tracking.php:489 premium/click-tracking.php:643 -msgid "Avg rank" -msgstr "" - -#: premium/click-tracking.php:490 premium/click-tracking.php:644 -msgid "Avg page" -msgstr "" - -#: premium/click-tracking.php:504 premium/click-tracking.php:590 -msgid "View post" -msgstr "" - -#: premium/click-tracking.php:505 premium/click-tracking.php:591 -msgid "Edit post" -msgstr "" - -#: premium/click-tracking.php:517 -msgid "Remove this query from the click log" -msgstr "" - -#: premium/click-tracking.php:523 premium/click-tracking.php:536 -msgid "Delete" -msgstr "" - -#: premium/click-tracking.php:530 -msgid "Remove this query from the search log" -msgstr "" - -#: premium/click-tracking.php:636 -msgid "Search queries for this post" -msgstr "" - -#: premium/click-tracking.php:711 -msgid "" -"Enabling this option will add click tracking information to the post URLs on " -"Relevanssi search results pages, allowing to you see stats on which posts " -"are clicked and what their rankings are. You can find the stats on " -"individual post edit pages in the Relevanssi sidebar, or from the User " -"searches page by clicking the search term." -msgstr "" - -#: premium/click-tracking.php:713 -msgid "" -"Click tracking stores post ID, the search query and ranking information for " -"the post. No personal information about the user doing the search are stored." -msgstr "" - -#: premium/click-tracking.php:718 -msgid "Enable click tracking" -msgstr "" - -#: premium/click-tracking.php:728 -msgid "Enable click tracking on Relevanssi search results pages." -msgstr "" - -#: premium/click-tracking.php:739 -msgid "How many days of click tracking logs to keep in the database." -msgstr "" - -#: premium/click-tracking.php:743 -#, php-format -msgid "" -"Set to %d for no trimming. The click tracking logs will be smaller than the " -"search logs, so this value can be bigger than the value for regular logs." -msgstr "" - -#: premium/click-tracking.php:751 -msgid "Export click logs" -msgstr "" - -#: premium/click-tracking.php:754 -msgid "Export the click tracking log as a CSV file" -msgstr "" - -#: premium/click-tracking.php:755 -msgid "Push the button to export the click tracking log as a CSV file." -msgstr "" - -#: premium/click-tracking.php:794 -msgid "Total clicks" -msgstr "" - -#: premium/click-tracking.php:801 -#, php-format -msgid "%s %% of all queries" -msgstr "" - -#: premium/click-tracking.php:806 -msgid "Click tracking insights" -msgstr "" - -#: premium/click-tracking.php:837 -msgid "These posts got the most clicks. This is content users like!" -msgstr "" - -#: premium/click-tracking.php:866 -msgid "" -"These posts were got clicks from a low ranking. Should they be boosted " -"higher?" -msgstr "" - -#: premium/click-tracking.php:897 -#, php-format -msgid "%1$s posts" -msgstr "" - -#: premium/click-tracking.php:902 -msgid "" -"You have search queries that generate clicks to many posts. Perhaps more " -"focus would be good?" -msgstr "" - -#: premium/click-tracking.php:910 -msgid "Sorry, no clicks recorded for this period!" -msgstr "" - -#: premium/click-tracking.php:1004 -msgid "No search clicks logged." -msgstr "" - -#: premium/common.php:502 -msgid "" -"Your site is not public. By default, Relevanssi does not search private " -"sites. If you want to be able to search on this site, either make it public " -"or add a filter function that returns true on " -"'relevanssi_multisite_public_status' filter hook." -msgstr "" - -#: premium/common.php:1074 -msgid "Must have" -msgstr "" - -#: premium/contextual-help.php:23 -msgid "Boolean operators" -msgstr "" - -#: premium/contextual-help.php:25 -msgid "" -"Relevanssi Premium offers limited support for Boolean logic. In addition of " -"setting the default operator from Relevanssi settings, you can use AND and " -"NOT operators in searches." -msgstr "" - -#: premium/contextual-help.php:26 -msgid "To use the NOT operator, prefix the search term with a minus sign:" -msgstr "" - -#: premium/contextual-help.php:27 -msgid "cats -dogs" -msgstr "" - -#: premium/contextual-help.php:28 -msgid "" -"This would only show posts that have the word 'cats' but not the word 'dogs'." -msgstr "" - -#: premium/contextual-help.php:29 -msgid "" -"To use the AND operator, set the default operator to OR and prefix the " -"search term with a plus sign:" -msgstr "" - -#: premium/contextual-help.php:30 -msgid "+cats dogs mice" -msgstr "" - -#: premium/contextual-help.php:31 -msgid "" -"This would show posts that have the word 'cats' and either 'dogs' or 'mice' " -"or both, and would prioritize posts that have all three." -msgstr "" - -#: premium/contextual-help.php:37 -#, php-format -msgid "" -"Permalinks to user profiles may not always work on search results templates. " -"%1$s should work, but if it doesn't, you can replace it with %2$s." -msgstr "" - -#: premium/contextual-help.php:39 -#, php-format -msgid "" -"To control which user meta fields are indexed, you can use the %s option. It " -"should have a comma-separated list of user meta fields. It can be set like " -"this (you only need to run this code once):" -msgstr "" - -#: premium/contextual-help.php:41 -#, php-format -msgid "" -"For more details on user profiles and search results templates, see %1$sthis " -"knowledge base entry%2$s." -msgstr "" - -#: premium/contextual-help.php:46 -msgid "User profiles" -msgstr "" - -#: premium/contextual-help.php:58 premium/interface.php:156 -#: premium/interface.php:231 -msgid "Internal links" -msgstr "" - -#: premium/contextual-help.php:60 -msgid "" -"This option sets how Relevanssi handles internal links that point to your " -"own site." -msgstr "" - -#: premium/contextual-help.php:61 -msgid "" -"If you choose 'No special processing', Relevanssi doesn’t care about links " -"and indexes the link anchor (the text of the link) like it is any other text." -msgstr "" - -#: premium/contextual-help.php:62 -msgid "" -"If you choose 'Index internal links for target documents only', then the " -"link is indexed like the link anchor text were the part of the link target, " -"not the post where the link is." -msgstr "" - -#: premium/contextual-help.php:63 -msgid "" -"If you choose 'Index internal links for target and source', the link anchor " -"text will count for both posts." -msgstr "" - -#: premium/contextual-help.php:70 -msgid "Stemming" -msgstr "" - -#: premium/contextual-help.php:72 -msgid "" -"By default Relevanssi doesn't understand anything about singular word forms, " -"plurals or anything else. You can, however, add a stemmer that will stem all " -"the words to their basic form, making all different forms equal in searching." -msgstr "" - -#: premium/contextual-help.php:73 -msgid "" -"To enable the English-language stemmer, add this to the theme functions.php:" -msgstr "" - -#: premium/contextual-help.php:75 -msgid "After you add the code, rebuild the index to get correct results." -msgstr "" - -#: premium/contextual-help.php:81 -#, php-format -msgid "" -"If you have WP CLI installed, Relevanssi Premium has some helpful commands. " -"Use %s to get a list of available commands." -msgstr "" - -#: premium/contextual-help.php:83 -#, php-format -msgid "You can also see %1$sthe user manual page%2$s." -msgstr "" - -#: premium/contextual-help.php:88 -msgid "WP CLI" -msgstr "" - -#: premium/contextual-help.php:98 -msgid "Plugin support page" -msgstr "" - -#: premium/indexing.php:1123 -#, php-format -msgid "Indexed %d taxonomy terms." -msgstr "" - -#: premium/indexing.php:1125 -msgid "No taxonomies to index." -msgstr "" - -#: premium/interface.php:67 premium/interface.php:80 -msgid "API key" -msgstr "" - -#: premium/interface.php:70 -msgid "API key is set" -msgstr "" - -#: premium/interface.php:71 -msgid "Remove the API key." -msgstr "" - -#: premium/interface.php:72 premium/interface.php:85 -msgid "" -"A valid API key is required to use the automatic update feature and the PDF " -"indexing. Otherwise the plugin will work just fine without an API key. Get " -"your API key from Relevanssi.com." -msgstr "" - -#: premium/interface.php:83 -msgid "Set the API key:" -msgstr "" - -#: premium/interface.php:103 -msgid "Disable outside connections" -msgstr "" - -#: premium/interface.php:108 -msgid "Disable update version checking and attachment indexing" -msgstr "" - -#: premium/interface.php:110 -msgid "" -"If you check this box, Relevanssi will stop all outside connections. This " -"means the plugin won't check for updates from Relevanssi.com, won't read " -"attachment contents using Relevanssiservices.com attachment reader (using " -"custom attachment reader is still allowed), or update plugin translations. " -"Do not check this box unless you know what you're doing, because this will " -"disable Relevanssi updates." -msgstr "" - -#: premium/interface.php:126 -msgid "Update translations" -msgstr "" - -#: premium/interface.php:131 -msgid "Check for plugin translation updates" -msgstr "" - -#: premium/interface.php:133 -msgid "" -"If you check this box, Relevanssi will check for updates to the plugin " -"translations. At the moment, translations are available for:" -msgstr "" - -#: premium/interface.php:160 -msgid "No special processing for internal links" -msgstr "" - -#: premium/interface.php:161 -msgid "Index internal links for target documents only" -msgstr "" - -#: premium/interface.php:162 -msgid "Index internal links for both target and source" -msgstr "" - -#: premium/interface.php:164 -msgid "" -"Internal link anchor tags can be indexed for target document, both target " -"and source or source only. See Help for more details." -msgstr "" - -#: premium/interface.php:192 -msgid "Hide Relevanssi" -msgstr "" - -#: premium/interface.php:197 -msgid "Hide Relevanssi on edit pages" -msgstr "" - -#: premium/interface.php:199 -msgid "Enabling this option hides Relevanssi on all post edit pages." -msgstr "" - -#: premium/interface.php:204 -msgid "Show Relevanssi for admins" -msgstr "" - -#: premium/interface.php:208 -msgid "Show Relevanssi for admins on edit pages" -msgstr "" - -#: premium/interface.php:211 -msgid "Show Relevanssi on edit pages for admins" -msgstr "" - -#: premium/interface.php:215 -#, php-format -msgid "" -"If Relevanssi is hidden on post edit pages, enabling this option will show " -"Relevanssi features for admin-level users. Admin-level users are those with " -"%1$s capabilities, but if you want to use a different capability, you can " -"use the %2$s filter to modify that." -msgstr "" - -#: premium/interface.php:262 -#, php-format -msgid "Post type '%s':" -msgstr "" - -#: premium/interface.php:301 -#, php-format -msgid "Posts tagged with taxonomy '%s':" -msgstr "" - -#: premium/interface.php:331 -#, php-format -msgid "Terms in the taxonomy '%s':" -msgstr "" - -#: premium/interface.php:357 -msgid "Recent posts bonus weight:" -msgstr "" - -#: premium/interface.php:377 -msgid "Recent posts bonus cutoff" -msgstr "" - -#: premium/interface.php:380 -msgid "days" -msgstr "" - -#: premium/interface.php:381 -msgid "" -"Posts newer than the day cutoff specified here will have their weight " -"multiplied with the bonus above." -msgstr "" - -#: premium/interface.php:399 -msgid "Hide Relevanssi branding" -msgstr "" - -#: premium/interface.php:404 premium/interface.php:408 -#, php-format -msgid "Don't show Relevanssi branding on the '%s' screen." -msgstr "" - -#: premium/interface.php:404 premium/interface.php:408 -msgid "User Searches" -msgstr "" - -#: premium/interface.php:426 -msgid "Thousands separator" -msgstr "" - -#: premium/interface.php:430 -msgid "" -"If Relevanssi sees this character between numbers, it'll stick the numbers " -"together no matter how the character would otherwise be handled. Especially " -"useful if a space is used as a thousands separator." -msgstr "" - -#: premium/interface.php:446 -msgid "Disable these shortcodes" -msgstr "" - -#: premium/interface.php:450 -msgid "" -"Enter a comma-separated list of shortcodes. These shortcodes will not be " -"expanded if expand shortcodes above is enabled. This is useful if a " -"particular shortcode is causing problems in indexing." -msgstr "" - -#: premium/interface.php:480 -msgid "MySQL columns" -msgstr "" - -#: premium/interface.php:487 -#, php-format -msgid "" -"A comma-separated list of %s MySQL table columns to include in the index. " -"Following columns are available: " -msgstr "" - -#: premium/interface.php:510 premium/interface.php:517 -msgid "Search all subsites" -msgstr "" - -#: premium/interface.php:514 -msgid "Search all subsites." -msgstr "" - -#: premium/interface.php:519 -msgid "" -"If this option is checked, multisite searches will include all subsites. " -"Warning: if you have dozens of sites in your network, the searches may " -"become too slow. This can be overridden from the search form." -msgstr "" - -#: premium/interface.php:525 -msgid "Search some subsites" -msgstr "" - -#: premium/interface.php:535 -msgid "" -"Add a comma-separated list of blog ID values to have all search forms on " -"this site search these multisite subsites. This can be overridden from the " -"search form." -msgstr "" - -#: premium/interface.php:559 -msgid "Indexing user profiles" -msgstr "" - -#: premium/interface.php:564 -msgid "Index user profiles" -msgstr "" - -#: premium/interface.php:568 premium/interface.php:571 -msgid "Index user profiles." -msgstr "" - -#: premium/interface.php:573 -msgid "" -"Relevanssi will index user profiles. This includes first name, last name, " -"display name and user description." -msgstr "" - -#: premium/interface.php:574 -msgid "" -"This may require changes to search results template, see the contextual help." -msgstr "" - -#: premium/interface.php:580 -msgid "Index subscribers" -msgstr "" - -#: premium/interface.php:584 premium/interface.php:587 -msgid "Index also subscriber profiles." -msgstr "" - -#: premium/interface.php:589 -msgid "" -"By default, Relevanssi indexes authors, editors, contributors and admins, " -"but not subscribers. You can change that with this option." -msgstr "" - -#: premium/interface.php:596 -msgid "Extra fields" -msgstr "" - -#: premium/interface.php:600 -msgid "" -"A comma-separated list of extra user fields to include in the index. These " -"can be user fields or user meta." -msgstr "" - -#: premium/interface.php:616 -msgid "Indexing synonyms" -msgstr "" - -#: premium/interface.php:620 -msgid "Index synonyms" -msgstr "" - -#: premium/interface.php:624 premium/interface.php:627 -msgid "Index synonyms for AND searches." -msgstr "" - -#: premium/interface.php:632 -msgid "" -"If checked, Relevanssi will use the synonyms in indexing. If you add " -"dog = hound to the synonym list and enable this feature, every " -"time the indexer sees hound in post content or post title, it " -"will index it as hound dog. Thus, the post will be found when " -"searching with either word. This makes it possible to use synonyms with AND " -"searches, but will slow down indexing, especially with large databases and " -"large lists of synonyms. You can use multi-word values, but phrases do not " -"work." -msgstr "" - -#: premium/interface.php:652 -msgid "Indexing PDF content" -msgstr "" - -#: premium/interface.php:657 -msgid "Index for parent" -msgstr "" - -#: premium/interface.php:662 -msgid "Index PDF contents for parent post" -msgstr "" - -#: premium/interface.php:665 -#, php-format -msgid "" -"If checked, Relevanssi indexes the PDF content both for the attachment post " -"and the parent post. You can control the attachment post visibility by " -"indexing or not indexing the post type %s." -msgstr "" - -#: premium/interface.php:668 -#, php-format -msgid "" -"You have not chosen to index the post type %s. You won't see any PDF content " -"in the search results, unless you check this option." -msgstr "" - -#: premium/interface.php:672 -msgid "" -"Searching for PDF contents will now return both the attachment itself and " -"the parent post. Are you sure you want both in the results?" -msgstr "" - -#: premium/interface.php:696 -msgid "Indexing taxonomy terms" -msgstr "" - -#: premium/interface.php:701 -msgid "Index taxonomy terms" -msgstr "" - -#: premium/interface.php:706 -msgid "Index taxonomy terms." -msgstr "" - -#: premium/interface.php:708 -msgid "" -"Relevanssi will index taxonomy terms (categories, tags and custom " -"taxonomies). Searching for taxonomy term name will return the taxonomy term " -"page." -msgstr "" - -#: premium/interface.php:743 -#, php-format -msgid "Index terms for taxonomy %s" -msgstr "" - -#: premium/interface.php:795 -msgid "Index post type archives" -msgstr "" - -#: premium/interface.php:799 premium/interface.php:802 -msgid "Index post type archives." -msgstr "" - -#: premium/interface.php:805 -#, php-format -msgid "" -"Relevanssi will index post type archive pages. By default Relevanssi indexes " -"the post type label and the description set when the post type is " -"registered. If you want to index some other content, you can use the %s " -"filter hook to adjust the content." -msgstr "" - -#: premium/interface.php:811 -msgid "Post types indexed" -msgstr "" - -#: premium/interface.php:819 -#, php-format -msgid "" -"This list includes all post types that are not built in and have %1$s set to " -"true. If you want to adjust the list, you can use the %2$s filter hook." -msgstr "" - -#: premium/interface.php:836 -msgid "Number of excerpt snippets" -msgstr "" - -#: premium/interface.php:848 -msgid "" -"The maximum number of excerpt snippets Relevanssi will create for each post." -msgstr "" - -#: premium/interface.php:974 -msgid "Options updated!" -msgstr "" - -#: premium/interface.php:1208 -msgid "Import / Export options" -msgstr "" - -#: premium/interface.php:1216 -msgid "Related" -msgstr "" - -#: premium/interface.php:1224 -msgid "Spam Block" -msgstr "" - -#: premium/interface.php:1232 premium/tabs/support-tab.php:26 -msgid "Support" -msgstr "" - -#: premium/interface.php:1245 -msgid "Reset the option" -msgstr "" - -#: premium/interface.php:1259 -msgid "Option successfully reset!" -msgstr "" - -#: premium/interface.php:1261 -msgid "Couldn't reset the option, reload the page to try again." -msgstr "" - -#: premium/interface.php:1266 -msgid "Reset the relevanssi_words option" -msgstr "" - -#: premium/interface.php:1273 -#, php-format -msgid "" -"If you are having problems with the Did you mean? feature, you can reset the " -"%1$s option that keeps a cache. Next time the Did you mean? suggestions are " -"needed the option is regenerated." -msgstr "" - -#: premium/interface.php:1323 -#, php-format -msgid "" -"The API key is not set. Please enter your API key in the %1$sthe Relevanssi " -"settings%2$s. If you don't have one, %3$syou can buy a new license here%2$s." -msgstr "" - -#: premium/interface.php:1331 -#, php-format -msgid "" -"Your API key is set, but it looks like you don't have a valid license. " -"%1$sYou can buy a new license here%2$s." -msgstr "" - -#: premium/interface.php:1351 premium/interface.php:1437 -msgid "Pinned keywords" -msgstr "" - -#: premium/interface.php:1352 premium/interface.php:1446 -msgid "Excluded keywords" -msgstr "" - -#: premium/interface.php:1353 -msgid "Pin for all searches" -msgstr "" - -#: premium/interface.php:1354 -msgid "Exclude post" -msgstr "" - -#: premium/interface.php:1355 -msgid "Ignore post content" -msgstr "" - -#: premium/interface.php:1433 -msgid "Relevanssi pinning" -msgstr "" - -#: premium/interface.php:1460 premium/post-metabox.php:106 -msgid "Pin this post for all searches it appears in." -msgstr "" - -#: premium/interface.php:1468 premium/post-metabox.php:116 -msgid "Exclude this post or page from the index." -msgstr "" - -#: premium/interface.php:1476 premium/post-metabox.php:121 -msgid "Ignore post content in the indexing." -msgstr "" - -#: premium/network-options.php:47 -msgid "Relevanssi network options" -msgstr "" - -#: premium/network-options.php:78 -msgid "Copy options from one site to other sites" -msgstr "" - -#: premium/network-options.php:79 -msgid "" -"Choose a blog and copy all the options from that blog to all other blogs " -"that have active Relevanssi Premium. Be careful! There's no way to undo the " -"procedure!" -msgstr "" - -#: premium/network-options.php:86 -msgid "Copy options" -msgstr "" - -#: premium/network-options.php:104 -msgid "Copy options to all other subsites" -msgstr "" - -#: premium/network-options.php:154 -#, php-format -msgid "Copying options from blog %s" -msgstr "" - -#: premium/network-options.php:170 -#, php-format -msgid "Processing blog %s:" -msgstr "" - -#: premium/network-options.php:172 -msgid "Relevanssi is not active in this blog." -msgstr "" - -#: premium/network-options.php:183 -msgid "Options updated." -msgstr "" - -#: premium/pdf-upload.php:17 -msgid "Post excluded from the index by the user." -msgstr "" - -#: premium/pdf-upload.php:18 -msgid "" -"Relevanssi is in privacy mode and not allowed to contact Relevanssiservices." -"com." -msgstr "" - -#: premium/pdf-upload.php:19 -msgid "Attachment MIME type blocked." -msgstr "" - -#: premium/pdf-upload.php:20 -msgid "Attachment file size is too large." -msgstr "" - -#: premium/pdf-upload.php:21 -msgid "Attachment reading in process, please try again later." -msgstr "" - -#: premium/pdf-upload.php:22 -msgid "Server did not respond." -msgstr "" - -#: premium/pdf-upload.php:176 -msgid "Relevanssi attachment controls" -msgstr "" - -#: premium/pdf-upload.php:216 -msgid "Reread the attachment content" -msgstr "" - -#: premium/pdf-upload.php:216 -msgid "Read the attachment content" -msgstr "" - -#: premium/pdf-upload.php:219 -msgid "Indexer will fetch the file from your server." -msgstr "" - -#: premium/pdf-upload.php:222 -msgid "The file will be uploaded to the indexer." -msgstr "" - -#: premium/pdf-upload.php:232 -msgid "No API key set. API key is required for attachment indexing." -msgstr "" - -#: premium/pdf-upload.php:245 -msgid "" -"The attachment content has been modified and won't be reread from the file " -"when doing a general rereading. If you want to reread the attachment " -"contents from the file, you can force rereading here." -msgstr "" - -#: premium/pdf-upload.php:250 -msgid "Attachment content" -msgstr "" - -#: premium/pdf-upload.php:262 -msgid "" -"Relevanssi is currently in process of reading the file contents, please " -"return here later." -msgstr "" - -#: premium/pdf-upload.php:265 -msgid "Attachment error message" -msgstr "" - -#: premium/pdf-upload.php:276 -msgid "No attachment content found for this post at the moment." -msgstr "" - -#: premium/pdf-upload.php:547 -msgid "Could not save the file content to the custom field." -msgstr "" - -#: premium/pinning.php:243 -msgid "(pinned)" -msgstr "" - -#: premium/pinning.php:254 -#, php-format -msgid "Pin for '%s'" -msgstr "" - -#: premium/pinning.php:258 -#, php-format -msgid "Unpin for '%s'" -msgstr "" - -#: premium/post-metabox.php:43 -msgid "Relevanssi" -msgstr "" - -#: premium/post-metabox.php:87 -msgid "How Relevanssi sees this post" -msgstr "" - -#: premium/post-metabox.php:89 -msgid "Pin this post" -msgstr "" - -#: premium/post-metabox.php:90 -msgid "" -"A comma-separated list of single word keywords or multi-word phrases. If any " -"of these keywords are present in the search query, this post will be moved " -"on top of the search results." -msgstr "" - -#: premium/post-metabox.php:91 -msgid "Pinned keywords for this post" -msgstr "" - -#: premium/post-metabox.php:94 -msgid "" -"You can add weights to pinned keywords like this: 'keyword (100)'. The post " -"with the highest weight will be sorted first if there are multiple posts " -"pinned to the same keyword." -msgstr "" - -#: premium/post-metabox.php:99 -msgid "" -"NOTE: You have set the post content weight to 0. This means that keywords " -"that don't appear elsewhere in the post won't work, because they are indexed " -"as part of the post content. If you set the post content weight to any " -"positive value, the pinned keywords will work again." -msgstr "" - -#: premium/post-metabox.php:109 -msgid "Exclude this post" -msgstr "" - -#: premium/post-metabox.php:110 -msgid "" -"A comma-separated list of single word keywords or multi-word phrases. If any " -"of these keywords are present in the search query, this post will be removed " -"from the search results." -msgstr "" - -#: premium/post-metabox.php:111 -msgid "Excluded keywords for this post" -msgstr "" - -#: premium/post-metabox.php:394 premium/tabs/related-tab.php:103 -#: premium/templates/relevanssi-related.php:25 -msgid "Related Posts" -msgstr "" - -#: premium/post-metabox.php:397 -msgid "Don't append the related posts to this page." -msgstr "" - -#: premium/post-metabox.php:400 -msgid "Don't show this as a related post for any post." -msgstr "" - -#: premium/post-metabox.php:402 -msgid "Related Posts keywords" -msgstr "" - -#: premium/post-metabox.php:403 -msgid "" -"A comma-separated list of keywords to use for the Related Posts feature. " -"Anything entered here will used when searching for related posts. Using " -"phrases with quotes is allowed, but will restrict the related posts to posts " -"including that phrase." -msgstr "" - -#: premium/post-metabox.php:404 -msgid "Related posts keywords for this post" -msgstr "" - -#: premium/post-metabox.php:407 -msgid "" -"A comma-separated list of post IDs to use as related posts for this post" -msgstr "" - -#: premium/post-metabox.php:410 -msgid "" -"These are the related posts Relevanssi currently will show for this post:" -msgstr "" - -#: premium/post-metabox.php:419 -msgid "These posts are excluded from related posts for this post" -msgstr "" - -#: premium/post-metabox.php:426 -msgid "Insights" -msgstr "" - -#: premium/post-metabox.php:562 -msgid "not this" -msgstr "" - -#: premium/post-metabox.php:596 -msgid "use this" -msgstr "" - -#: premium/post-metabox.php:607 -msgid "Nothing excluded." -msgstr "" - -#: premium/tabs/attachments-tab.php:53 -msgid "Read all unread attachments" -msgstr "" - -#: premium/tabs/attachments-tab.php:58 -#, php-format -msgid "" -"Clicking the button will read the contents of all the unread attachments " -"files and store the contents to the %s custom field for future indexing. " -"Attachments with errors will be skipped, except for the files with timeout " -"and connection related errors: those will be attempted again." -msgstr "" - -#: premium/tabs/attachments-tab.php:68 -msgid "State of the attachments" -msgstr "" - -#: premium/tabs/attachments-tab.php:83 -msgid "document has read attachment content." -msgstr "" - -#: premium/tabs/attachments-tab.php:84 -msgid "document has an attachment reading error." -msgstr "" - -#: premium/tabs/attachments-tab.php:86 -msgid "Show errors" -msgstr "" - -#: premium/tabs/attachments-tab.php:88 -msgid "Attachment reading errors" -msgstr "" - -#: premium/tabs/attachments-tab.php:93 -msgid "Server location" -msgstr "" - -#: premium/tabs/attachments-tab.php:96 -msgid "United States" -msgstr "" - -#: premium/tabs/attachments-tab.php:97 -msgid "European Union" -msgstr "" - -#: premium/tabs/attachments-tab.php:102 -msgid "Reset attachment content" -msgstr "" - -#: premium/tabs/attachments-tab.php:104 -msgid "Reset all attachment data from posts" -msgstr "" - -#: premium/tabs/attachments-tab.php:106 -#, php-format -msgid "" -"This will remove all %1$s and %2$s custom fields from all posts. If you want " -"to reread all attachment files, use this to clean up; clicking the reading " -"button doesn't wipe the slate clean like it does in regular indexing." -msgstr "" - -#: premium/tabs/attachments-tab.php:107 -msgid "" -"If you have posts where you have modified the attachment content after " -"reading it, this will leave those posts untouched." -msgstr "" - -#: premium/tabs/attachments-tab.php:112 -msgid "Read new files" -msgstr "" - -#: premium/tabs/attachments-tab.php:116 premium/tabs/attachments-tab.php:119 -msgid "Read new files automatically" -msgstr "" - -#: premium/tabs/attachments-tab.php:121 -msgid "" -"If this option is enabled, Relevanssi will automatically read the contents " -"of new attachments as they are uploaded. This may cause unexpected delays in " -"uploading posts. If this is not enabled, new attachments are not read " -"automatically and need to be manually read and reindexed." -msgstr "" - -#: premium/tabs/attachments-tab.php:127 -msgid "Upload files" -msgstr "" - -#: premium/tabs/attachments-tab.php:131 premium/tabs/attachments-tab.php:134 -msgid "Upload files for reading" -msgstr "" - -#: premium/tabs/attachments-tab.php:136 -msgid "" -"By default, Relevanssi only sends a link to the attachment to the attachment " -"reader. If your files are not accessible (for example your site is inside an " -"intranet, password protected, or a local dev site, and the files can't be " -"downloaded if given the URL of the file), check this option to upload the " -"whole file to the reader." -msgstr "" - -#: premium/tabs/attachments-tab.php:142 -msgid "Link to files" -msgstr "" - -#: premium/tabs/attachments-tab.php:146 premium/tabs/attachments-tab.php:149 -msgid "Link search results directly to the files" -msgstr "" - -#: premium/tabs/attachments-tab.php:151 -msgid "" -"If this option is checked, attachment results in search results will link " -"directly to the file. Otherwise the results will link to the attachment page." -msgstr "" - -#: premium/tabs/attachments-tab.php:154 -#, php-format -msgid "" -"You're not indexing the %s post type, so this setting doesn't have any " -"effect." -msgstr "" - -#: premium/tabs/attachments-tab.php:158 -#, php-format -msgid "" -"You're not indexing the %s post type and haven't connected the files to the " -"parent posts in the indexing settings. You won't be seeing any files in the " -"results." -msgstr "" - -#: premium/tabs/attachments-tab.php:164 -msgid "Instructions" -msgstr "" - -#: premium/tabs/attachments-tab.php:167 -#, php-format -msgid "" -"When Relevanssi reads attachment content, the text is extracted and saved in " -"the %s custom field for the attachment post. This alone does not add the " -"attachment content in the Relevanssi index; it just makes the contents of " -"the attachments easily available for the regular Relevanssi indexing process." -msgstr "" - -#: premium/tabs/attachments-tab.php:169 -#, php-format -msgid "" -"There are two ways to index the attachment content. If you choose to index " -"the %s post type, Relevanssi will show the attachment posts in the results." -msgstr "" - -#: premium/tabs/attachments-tab.php:170 -msgid "" -"You can also choose to index the attachment content for the parent post, in " -"which case Relevanssi will show the parent post in the results (this setting " -"can be found on the indexing settings). Obviously this does not find the " -"content in attachments that are not attached to another post – if you just " -"upload a file to the WordPress Media Library, it is not attached and won't " -"be found unless you index the attachment posts." -msgstr "" - -#: premium/tabs/attachments-tab.php:171 -msgid "" -"If you need to reread a file, you can do read individual files from Media " -"Library. Choose an attachment and click 'Edit more details' to read the " -"content." -msgstr "" - -#: premium/tabs/attachments-tab.php:175 -msgid "Key not valid?" -msgstr "" - -#: premium/tabs/attachments-tab.php:177 -msgid "" -"Are you a new Relevanssi customer and seeing 'Key xxxxxx is not valid' error " -"messages? New API keys are delivered to the server once per hour, so if try " -"again an hour later, the key should work." -msgstr "" - -#: premium/tabs/attachments-tab.php:178 -msgid "" -"A 'Key 0 is not valid' error message means you're on a multisite, but have " -"only entered the API key in the subsite settings. Set the API key in the " -"network settings to fix that." -msgstr "" - -#: premium/tabs/attachments-tab.php:182 -msgid "Important!" -msgstr "" - -#: premium/tabs/attachments-tab.php:184 -msgid "" -"In order to read the contents of the files, the files are sent over to " -"Relevanssiservices.com, a processing service hosted on a Digital Ocean " -"Droplet. There are two servers: one in the US and another in the EU. The " -"service creates a working copy of the files. The copy is removed after the " -"file has been processed, but there are no guarantees that someone with an " -"access to the server couldn't see the files. Do not read files with " -"confidential information in them. In order to block individual files from " -"reading, use the Relevanssi post controls on attachment edit page to exclude " -"attachment posts from indexing." -msgstr "" - -#: premium/tabs/import-export-tab.php:19 -msgid "Import or export options" -msgstr "" - -#: premium/tabs/import-export-tab.php:21 -msgid "" -"Here you find the current Relevanssi Premium options in a text format. Copy " -"the contents of the text field to make a backup of your settings. You can " -"also paste new settings here to change all settings at the same time. This " -"is useful if you have default settings you want to use on every system." -msgstr "" - -#: premium/tabs/import-export-tab.php:25 -msgid "Current Settings" -msgstr "" - -#: premium/tabs/import-export-tab.php:39 -msgid "Import settings" -msgstr "" - -#: premium/tabs/import-export-tab.php:46 -msgid "" -"Note! Make sure you've got correct settings from a right version of " -"Relevanssi. Settings from a different version of Relevanssi may or may not " -"work and may or may not mess your settings." -msgstr "" - -#: premium/tabs/redirects-tab.php:28 -msgid "" -"If you want a particular search to always lead to a specific page, you can " -"use the redirects. Whenever the search query matches a redirect, the search " -"is automatically bypassed and the user is redirected to the target page." -msgstr "" - -#: premium/tabs/redirects-tab.php:30 -msgid "" -"Enter the search term and the target URL, which may be relative to your site " -"home page or an absolute URL. If \"Partial match\" is checked, the redirect " -"happens if the query word appears anywhere in the search query, even inside " -"a word, so use it with care. If the search query matches multiple " -"redirections, the first one it matches will trigger." -msgstr "" - -#: premium/tabs/redirects-tab.php:32 -msgid "The \"Hits\" column shows how many times each redirect has been used." -msgstr "" - -#: premium/tabs/redirects-tab.php:37 -msgid "Redirect empty searches" -msgstr "" - -#: premium/tabs/redirects-tab.php:39 -msgid "" -"Enter an URL here to redirect all searches that find nothing to this URL." -msgstr "" - -#: premium/tabs/redirects-tab.php:42 -msgid "Redirect searches without terms" -msgstr "" - -#: premium/tabs/redirects-tab.php:44 -msgid "Enter an URL here to redirect all searches without any search terms." -msgstr "" - -#: premium/tabs/redirects-tab.php:53 premium/tabs/redirects-tab.php:115 -msgid "Partial match" -msgstr "" - -#: premium/tabs/redirects-tab.php:54 -msgid "URL" -msgstr "" - -#: premium/tabs/redirects-tab.php:65 premium/tabs/redirects-tab.php:107 -msgid "Copy" -msgstr "" - -#: premium/tabs/redirects-tab.php:98 -msgid "Query string" -msgstr "" - -#: premium/tabs/redirects-tab.php:127 -msgid "Target URL" -msgstr "" - -#: premium/tabs/redirects-tab.php:153 -msgid "Add a redirect" -msgstr "" - -#: premium/tabs/redirects-tab.php:155 -msgid "Once you're done, remember to click the save button below!" -msgstr "" - -#: premium/tabs/related-tab.php:105 -msgid "" -"Relevanssi Related Posts feature shows related posts on posts pages, based " -"on keywords like post title, tags and categories. This feature uses the " -"Relevanssi index to find the best-matching related posts. All results are " -"cached, so your site performance won't suffer." -msgstr "" - -#: premium/tabs/related-tab.php:108 -#, php-format -msgid "" -"A pro tip: you can regenerate related posts for all posts with the WP CLI " -"command %s." -msgstr "" - -#: premium/tabs/related-tab.php:110 -msgid "Displaying the related posts" -msgstr "" - -#: premium/tabs/related-tab.php:115 -msgid "Enable related posts" -msgstr "" - -#: premium/tabs/related-tab.php:120 -msgid "If this is unchecked, related posts will be completely disabled." -msgstr "" - -#: premium/tabs/related-tab.php:125 premium/tabs/related-tab.php:128 -msgid "Automatically add to these post types" -msgstr "" - -#: premium/tabs/related-tab.php:153 -#, php-format -msgid "" -"The related posts will be automatically displayed for these post types. The " -"element is added using %1$s filter hook with priority 99 (you can adjust " -"that with the %2$s filter hook)." -msgstr "" - -#: premium/tabs/related-tab.php:155 -#, php-format -msgid "" -"If you don't choose to display the related posts automatically, you need to " -"add them manually to your template. You can use the template function %1$s " -"or the shortcode %2$s to display the related posts." -msgstr "" - -#: premium/tabs/related-tab.php:160 -msgid "Choosing the related posts" -msgstr "" - -#: premium/tabs/related-tab.php:164 premium/tabs/related-tab.php:167 -msgid "Keyword sources" -msgstr "" - -#: premium/tabs/related-tab.php:174 -msgid "Title" -msgstr "" - -#: premium/tabs/related-tab.php:213 -msgid "Restrict to taxonomy " -msgstr "" - -#: premium/tabs/related-tab.php:225 -msgid "" -"The sources Relevanssi uses for related post keywords. Keywords from these " -"sources are then used to search the Relevanssi index to find related posts. " -"Make sure you choose something, otherwise you won't see results or will see " -"random results. In addition of these sources, you can also define your own " -"keywords for each post from the post edit screen." -msgstr "" - -#: premium/tabs/related-tab.php:226 -msgid "" -"If you choose to restrict to the taxonomy, those keywords will only match in " -"the same category. For example restricted category search terms will only " -"match to category, not to post content. This may lead to better precision, " -"depending on how the taxonomy terms are used." -msgstr "" - -#: premium/tabs/related-tab.php:232 -msgid "" -"These taxonomies are missing here, because Relevanssi isn't set to index " -"them:" -msgstr "" - -#: premium/tabs/related-tab.php:242 -msgid "Number of posts" -msgstr "" - -#: premium/tabs/related-tab.php:245 -msgid "The number of related posts to show." -msgstr "" - -#: premium/tabs/related-tab.php:249 -msgid "Months to use" -msgstr "" - -#: premium/tabs/related-tab.php:252 -msgid "" -"Use only posts published within this many months. (For more fine-grained " -"date controls, use filters.)" -msgstr "" - -#: premium/tabs/related-tab.php:256 premium/tabs/related-tab.php:259 -msgid "Post types to use" -msgstr "" - -#: premium/tabs/related-tab.php:270 -msgid "Matching post type" -msgstr "" - -#: premium/tabs/related-tab.php:271 -msgid "Uncheck this option to choose other post types." -msgstr "" - -#: premium/tabs/related-tab.php:303 -msgid "" -"The post types to use for related posts. Matching post type means that for " -"each post type, only posts from the same post type are used for related " -"posts." -msgstr "" - -#: premium/tabs/related-tab.php:307 -msgid "No related posts found" -msgstr "" - -#: premium/tabs/related-tab.php:310 -msgid "Show nothing" -msgstr "" - -#: premium/tabs/related-tab.php:311 -msgid "Random posts" -msgstr "" - -#: premium/tabs/related-tab.php:312 -msgid "Random posts from same category" -msgstr "" - -#: premium/tabs/related-tab.php:314 -msgid "" -"What to do when no related posts are found? The options are to show nothing " -"and just disable the whole element, or to show random posts (either fully " -"random, or from the same category). Do note that the related posts are " -"cached, so the random posts do not change on every page load." -msgstr "" - -#: premium/tabs/related-tab.php:318 -msgid "Not enough related posts found" -msgstr "" - -#: premium/tabs/related-tab.php:321 -msgid "Show the found posts" -msgstr "" - -#: premium/tabs/related-tab.php:322 -msgid "Fill with random posts" -msgstr "" - -#: premium/tabs/related-tab.php:323 -msgid "Fill with random posts from same category" -msgstr "" - -#: premium/tabs/related-tab.php:325 -msgid "" -"What to do when not enough related posts are found? The options are to show " -"what was found, or to fill up the display with random posts. Do note that " -"the related posts are cached, so the random posts do not change on every " -"page load." -msgstr "" - -#: premium/tabs/related-tab.php:330 -msgid "Style options" -msgstr "" - -#: premium/tabs/related-tab.php:332 -msgid "" -"When you add the related posts to your site, Relevanssi will use a template " -"to print out the results. These settings control how that template displays " -"the posts. If you need to modify the related posts in a way these settings " -"do not allow, you can always create your own template." -msgstr "" - -#: premium/tabs/related-tab.php:337 -#, php-format -msgid "" -"To create your own template, it's best if you begin with the default " -"Relevanssi template, which can be found in the file %1$s. Copy the template " -"in the %2$s folder in your theme and make the necessary changes. Relevanssi " -"will then use your template file to display the related posts." -msgstr "" - -#: premium/tabs/related-tab.php:344 -msgid "Display titles" -msgstr "" - -#: premium/tabs/related-tab.php:349 -msgid "Display titles for related posts." -msgstr "" - -#: premium/tabs/related-tab.php:355 -msgid "Display thumbnails" -msgstr "" - -#: premium/tabs/related-tab.php:360 -msgid "Display thumbnails for related posts." -msgstr "" - -#: premium/tabs/related-tab.php:362 -msgid "" -"If enabled, this will show the featured image for the post if the post has " -"one." -msgstr "" - -#: premium/tabs/related-tab.php:368 -msgid "Default thumbnail" -msgstr "" - -#: premium/tabs/related-tab.php:374 -msgid "Select image" -msgstr "" - -#: premium/tabs/related-tab.php:376 -msgid "" -"If a post doesn't have a featured image, this image will be used instead." -msgstr "" - -#: premium/tabs/related-tab.php:380 -msgid "Check this post to remove the default thumbnail." -msgstr "" - -#: premium/tabs/related-tab.php:387 -msgid "Display excerpts" -msgstr "" - -#: premium/tabs/related-tab.php:392 -msgid "Display excerpts for related posts." -msgstr "" - -#: premium/tabs/related-tab.php:395 -#, php-format -msgid "" -"This uses the manually created post excerpt if one exists, otherwise the " -"beginning of the post is used. Default length is 50 characters, use the %s " -"filter hook to adjust that." -msgstr "" - -#: premium/tabs/related-tab.php:401 -msgid "Minimum width" -msgstr "" - -#: premium/tabs/related-tab.php:402 -msgid "in pixels" -msgstr "" - -#: premium/tabs/related-tab.php:407 -msgid "The minimum width of the related post element." -msgstr "" - -#: premium/tabs/related-tab.php:412 -msgid "Caching" -msgstr "" - -#: premium/tabs/related-tab.php:414 -msgid "" -"The related posts are cached using WordPress transients. The related posts " -"for each post are stored in a transient that is stored for two weeks. The " -"cache for each post is flushed whenever the post is saved. When a post is " -"made non-public (returned to draft, trashed), Relevanssi automatically " -"flushes all related post caches where that post appears." -msgstr "" - -#: premium/tabs/related-tab.php:419 -msgid "Use cache for admins" -msgstr "" - -#: premium/tabs/related-tab.php:424 -msgid "Use the cache for admin users." -msgstr "" - -#: premium/tabs/related-tab.php:426 -msgid "" -"Disable this option when adjusting the settings to see changes on the site." -msgstr "" - -#: premium/tabs/related-tab.php:432 -msgid "Flush cache" -msgstr "" - -#: premium/tabs/related-tab.php:437 -msgid "Flush the caches." -msgstr "" - -#: premium/tabs/related-tab.php:439 -msgid "Check this box to flush all related posts caches." -msgstr "" - -#: premium/tabs/spamblock-tab.php:42 -msgid "Spam Blocking" -msgstr "" - -#: premium/tabs/spamblock-tab.php:44 -msgid "" -"These tools can be used to block spam searches on your site. It's best if " -"the spam searches can be blocked earlier on server level before WordPress " -"starts at all, but if that's not possible, this is a fine option." -msgstr "" - -#: premium/tabs/spamblock-tab.php:50 -#, php-format -msgid "" -"These filters are applied to all searches done using the %1$s parameter, the " -"%2$s pretty URLs (if your pretty URLs are using a different prefix, you can " -"use the %3$s filter hook to adjust the spam block) and also on page views " -"with the %4$s parameter." -msgstr "" - -#: premium/tabs/spamblock-tab.php:59 -msgid "" -"You can figure out the suitable keywords from your User searches page. Look " -"for common terms. Often spam queries contain URLs, and the top level domain " -"names are good keywords, things like '.shop', '.online', '.com' – those " -"appear rarely in legitimate searches." -msgstr "" - -#: premium/tabs/spamblock-tab.php:64 -msgid "Keyword spam blocking" -msgstr "" - -#: premium/tabs/spamblock-tab.php:66 -msgid "" -"Enter keywords, one per line. If these keywords appear anywhere in the " -"search string, the search will be stopped. Use as short keywords as " -"possible, but be careful to avoid blocking legitimate searches. The keywords " -"are case insensitive." -msgstr "" - -#: premium/tabs/spamblock-tab.php:69 -msgid "Regex keywords" -msgstr "" - -#: premium/tabs/spamblock-tab.php:72 -#, php-format -msgid "" -"These keywords support the use of regular expressions with preg_match(). The " -"keywords will be wrapped with %1$s." -msgstr "" - -#: premium/tabs/spamblock-tab.php:75 -msgid "Block Chinese queries" -msgstr "" - -#: premium/tabs/spamblock-tab.php:77 -msgid "Block queries that contain Chinese characters." -msgstr "" - -#: premium/tabs/spamblock-tab.php:80 -msgid "Block Cyrillic queries" -msgstr "" - -#: premium/tabs/spamblock-tab.php:82 -msgid "Block queries that contain Cyrillic characters." -msgstr "" - -#: premium/tabs/spamblock-tab.php:85 -msgid "Block emoji queries" -msgstr "" - -#: premium/tabs/spamblock-tab.php:87 -msgid "Block queries that contain emoji characters." -msgstr "" - -#: premium/tabs/spamblock-tab.php:90 -msgid "Block bot queries" -msgstr "" - -#: premium/tabs/spamblock-tab.php:92 -msgid "" -"Block queries from bots. Only applied to searches, not to page views with " -"highlights." -msgstr "" - -#: premium/tabs/spamblock-tab.php:95 -msgid "Current list of bots: " -msgstr "" - -#: premium/tabs/spamblock-tab.php:101 -#, php-format -msgid "You can add new bots to the list with the filter hook %1$s." -msgstr "" - -#: premium/tabs/spamblock-tab.php:108 -msgid "Blocking bots" -msgstr "" - -#: premium/tabs/spamblock-tab.php:110 -msgid "" -"You can use the Relevanssi spam block to also block requests from bots. In " -"general there's very little reason to allow bots to crawl search results " -"pages. They can create lots of really quite pointless traffic. On one of my " -"sites, out of 20.000 search queries, 16.000 were useless queries by the Bing " -"bot. Nice bots will obey the robots.txt instructions. This code snippet adds " -"robots.txt rules that block rule-obeying bots from accessing search results " -"pages:" -msgstr "" - -#: premium/tabs/spamblock-tab.php:123 -msgid "Blocking at the server level" -msgstr "" - -#: premium/tabs/spamblock-tab.php:125 -msgid "" -"It's best if the blocking is done before WordPress starts up in the first " -"place: that will increase security and will save server resources. These " -"tools can be used to block bot traffic on your site, but using them requires " -"expertise on server settings. Use them only if you know what you're doing, " -"or have a professional help you." -msgstr "" - -#: premium/tabs/support-tab.php:38 -#, php-format -msgid "" -"This form sends out an email to the Relevanssi support. If you have a " -"question, please fill in the form below and we will get back to you as soon " -"as possible. If you don't hear from us in a day or two, it's possible your " -"email has gone astray. In that case, please contact us again and use %1$sthe " -"support form at Relevanssi.com%2$s. You can also email us directly at %3$s. " -"Expect slower response times during June and July." -msgstr "" - -#: premium/tabs/support-tab.php:49 -#, php-format -msgid "" -"We have a large knowledge base. %1$sTake a look there%2$s, perhaps your " -"question is already answered there." -msgstr "" - -#: premium/tabs/support-tab.php:53 -msgid "" -"Instead of telling us \"X doesn't work\", please try be as specific as " -"possible. Please tell us what you expect to happen and what actually happens." -msgstr "" - -#: premium/tabs/support-tab.php:55 -msgid "" -"Feel free to ask questions in English or Finnish. Please do not send us " -"video questions." -msgstr "" - -#: premium/tabs/support-tab.php:62 -msgid "Your email address" -msgstr "" - -#: premium/tabs/support-tab.php:66 -msgid "Subject" -msgstr "" - -#: premium/tabs/support-tab.php:70 -msgid "Message" -msgstr "" - -#: premium/tabs/support-tab.php:75 -msgid "Send" -msgstr "" - -#: premium/tabs/support-tab.php:111 -msgid "Email sent!" -msgstr "" - -#: premium/tabs/support-tab.php:117 -msgid "Email failed!" -msgstr "" diff --git a/relevanssi-premium/stopwords/stopwords.cs_CZ b/relevanssi-premium/stopwords/stopwords.cs_CZ deleted file mode 100644 index 9e8b426a..00000000 --- a/relevanssi-premium/stopwords/stopwords.cs_CZ +++ /dev/null @@ -1,327 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.de_DE b/relevanssi-premium/stopwords/stopwords.de_DE deleted file mode 100644 index be4105ea..00000000 --- a/relevanssi-premium/stopwords/stopwords.de_DE +++ /dev/null @@ -1,1037 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.en_CA b/relevanssi-premium/stopwords/stopwords.en_CA deleted file mode 100644 index 86215bda..00000000 --- a/relevanssi-premium/stopwords/stopwords.en_CA +++ /dev/null @@ -1,323 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.en_GB b/relevanssi-premium/stopwords/stopwords.en_GB deleted file mode 100644 index 86215bda..00000000 --- a/relevanssi-premium/stopwords/stopwords.en_GB +++ /dev/null @@ -1,323 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.en_US b/relevanssi-premium/stopwords/stopwords.en_US deleted file mode 100644 index 86215bda..00000000 --- a/relevanssi-premium/stopwords/stopwords.en_US +++ /dev/null @@ -1,323 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.es_ES b/relevanssi-premium/stopwords/stopwords.es_ES deleted file mode 100644 index 4dbeea01..00000000 --- a/relevanssi-premium/stopwords/stopwords.es_ES +++ /dev/null @@ -1,386 +0,0 @@ - diff --git a/relevanssi-premium/stopwords/stopwords.fi b/relevanssi-premium/stopwords/stopwords.fi deleted file mode 100644 index c9e56028..00000000 --- a/relevanssi-premium/stopwords/stopwords.fi +++ /dev/null @@ -1,365 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.fr_FR b/relevanssi-premium/stopwords/stopwords.fr_FR deleted file mode 100644 index 87290ad5..00000000 --- a/relevanssi-premium/stopwords/stopwords.fr_FR +++ /dev/null @@ -1,72 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.it_IT b/relevanssi-premium/stopwords/stopwords.it_IT deleted file mode 100644 index 10aa1b0f..00000000 --- a/relevanssi-premium/stopwords/stopwords.it_IT +++ /dev/null @@ -1,666 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.pt_BR b/relevanssi-premium/stopwords/stopwords.pt_BR deleted file mode 100644 index b0798a02..00000000 --- a/relevanssi-premium/stopwords/stopwords.pt_BR +++ /dev/null @@ -1,173 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/stopwords/stopwords.zh_TW b/relevanssi-premium/stopwords/stopwords.zh_TW deleted file mode 100644 index 5e13ccad..00000000 --- a/relevanssi-premium/stopwords/stopwords.zh_TW +++ /dev/null @@ -1,769 +0,0 @@ - \ No newline at end of file diff --git a/relevanssi-premium/uninstall.php b/relevanssi-premium/uninstall.php deleted file mode 100644 index ff56fb0c..00000000 --- a/relevanssi-premium/uninstall.php +++ /dev/null @@ -1,32 +0,0 @@ -get_col( "SELECT blog_id FROM $wpdb->blogs" ); - $old_blogid = $wpdb->blogid; - foreach ( $blogids as $uninstall_blog_id ) { - switch_to_blog( $uninstall_blog_id ); - relevanssi_uninstall(); - restore_current_blog(); - } - - delete_site_option( 'relevanssi_api_key' ); -} else { - relevanssi_uninstall(); -}