diff --git a/assets/css/jumper.css b/assets/css/jumper.css
deleted file mode 100644
index 865f20b8..00000000
--- a/assets/css/jumper.css
+++ /dev/null
@@ -1,408 +0,0 @@
-#wu-jumper {
- box-sizing: border-box;
- position: fixed;
- top: 25%;
- left: 50%;
- width: 500px;
- margin-left: -250px;
- background: #f9f9f9;
- z-index: 99999;
- border-radius: 5px;
- border: solid 1px #ccc;
- -webkit-box-shadow: 0 0 5000px 5000px rgba(0, 0, 0, 0.2);
- -moz-box-shadow: 0 0 5000px 5000px rgba(0, 0, 0, 0.2);
- box-shadow: 0 0 5000px 5000px rgba(0, 0, 0, 0.2);
- /* @group Base */
- /* @end */
- /* @group Single Chosen */
- /* @end */
- /* @group Results */
- /* @end */
- /* @group Multi Chosen */
- /* @end */
- /* @end */
- /* @group Disabled Support */
- /* @end */
- /* @group Retina compatibility */
- /* @end */
-}
-#wu-jumper .wu-jumper-icon-container::before {
- font-family: dashicons-wu, sans-serif !important;
- content: "\e900";
- position: absolute;
- top: 50%;
- right: 15px;
- font-size: 36px;
- margin-top: -18px;
- height: 36px;
- line-height: 36px;
-}
-#wu-jumper * {
- box-sizing: border-box;
-}
-#wu-jumper label {
- display: block;
- text-transform: uppercase;
- padding: 20px;
-}
-#wu-jumper .selectize-control {
- width: 100%;
-}
-#wu-jumper .wu-chosen-container {
- position: relative;
- display: inline-block;
- vertical-align: middle;
- font-size: 13px;
- zoom: 1;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-drop {
- margin-top: -1px;
- border-radius: 0 0 4px 4px;
- background-clip: padding-box;
- border: solid 1px #ccc;
- border-top: none;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-drop {
- position: absolute;
- top: 100%;
- left: -9999px;
- z-index: 1010;
- width: 100%;
- border-top: 0;
- background: #fff;
-}
-#wu-jumper .wu-chosen-container.wu-chosen-with-drop .wu-chosen-drop {
- left: 0;
-}
-#wu-jumper .wu-chosen-container * {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-#wu-jumper .wu-chosen-container a {
- cursor: pointer;
-}
-#wu-jumper .wu-chosen-container .search-choice .group-name,
-#wu-jumper .wu-chosen-container .wu-chosen-single .group-name {
- margin-right: 4px;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- font-weight: normal;
- color: #999;
-}
-#wu-jumper .wu-chosen-container .search-choice .group-name::after,
-#wu-jumper .wu-chosen-container .wu-chosen-single .group-name::after {
- content: ":";
- padding-left: 2px;
- vertical-align: top;
-}
-#wu-jumper .selectize-control.single .selectize-input::after {
- display: none !important;
-}
-#wu-jumper .selectize-dropdown {
- margin-top: 0 !important;
- background-color: #fcfcfc;
- border: solid 1px #ddd;
-}
-#wu-jumper .selectize-input {
- margin-bottom: -7px;
- position: relative;
- display: block;
- overflow: hidden;
- color: #444;
- border: none;
- box-shadow: none;
- background: none;
- text-decoration: none;
- white-space: nowrap;
- line-height: 70px;
- padding: 0 15px;
-}
-#wu-jumper .selectize-input .item {
- font-size: 18pt;
-}
-#wu-jumper .selectize-input input {
- font-size: 18pt;
-}
-#wu-jumper .selectize-input.single::after {
- display: none !important;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-default {
- color: #999;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single span {
- display: block;
- overflow: hidden;
- margin-right: 26px;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single-with-deselect span {
- margin-right: 38px;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single abbr {
- position: absolute;
- top: 6px;
- right: 26px;
- display: block;
- width: 12px;
- height: 12px;
- font-size: 1px;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single abbr:hover {
- background-position: -42px -10px;
-}
-#wu-jumper .wu-chosen-container-single.wu-chosen-disabled .wu-chosen-single abbr:hover {
- background-position: -42px -10px;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single div {
- position: absolute;
- top: 0;
- right: 0;
- display: block;
- width: 18px;
- height: 100%;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-single div b {
- display: block;
- width: 100%;
- height: 100%;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-search {
- position: relative;
- z-index: 1010;
- margin: 0;
- white-space: nowrap;
-}
-#wu-jumper .wu-chosen-container-single .wu-chosen-search input[type=text] {
- margin: 0;
- padding: 4px 20px 4px 5px;
- width: 100%;
- height: auto;
- outline: 0;
- box-shadow: none !important;
- background-color: #fcfcfc;
- border: none;
- border-bottom: solid 1px #ddd;
- border-top: solid 1px #ddd;
- font-size: 1em;
- font-family: sans-serif;
- line-height: normal;
- border-radius: 0;
-}
-#wu-jumper .wu-chosen-container-single.wu-chosen-container-single-nosearch .wu-chosen-search {
- position: absolute;
- left: -9999px;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results {
- color: #444;
- position: relative;
- overflow-x: hidden;
- overflow-y: auto;
- margin: 0 4px 4px 0;
- padding: 0 0 0 4px;
- max-height: 240px;
- -webkit-overflow-scrolling: touch;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li {
- display: none;
- margin: 0;
- padding: 15px 6px;
- list-style: none;
- line-height: 15px;
- word-wrap: break-word;
- -webkit-touch-callout: none;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.active-result {
- display: list-item;
- cursor: pointer;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.disabled-result {
- display: list-item;
- color: #ccc;
- cursor: default;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.highlighted {
- color: #fff;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.no-results {
- color: #777;
- display: list-item;
- background: #f4f4f4;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.group-result {
- display: list-item;
- font-weight: bold;
- cursor: default;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li.group-option {
- padding-left: 15px;
-}
-#wu-jumper .wu-chosen-container .wu-chosen-results li em {
- font-style: normal;
- text-decoration: underline;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices {
- position: relative;
- overflow: hidden;
- margin: 0;
- padding: 0 5px;
- width: 100%;
- height: auto !important;
- height: 1%;
- background-color: #fff;
- cursor: text;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li {
- float: left;
- list-style: none;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-field {
- margin: 0;
- padding: 0;
- white-space: nowrap;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-field input[type=text] {
- margin: 1px 0;
- padding: 0;
- height: 25px;
- outline: 0;
- background: transparent !important;
- color: #999;
- font-size: 100%;
- font-family: sans-serif;
- line-height: normal;
- border-radius: 0;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice {
- position: relative;
- margin: 3px 5px 3px 0;
- padding: 3px 20px 3px 5px;
- max-width: 100%;
- border-radius: 3px;
- background-color: #eee;
- background-size: 100% 19px;
- background-repeat: repeat-x;
- background-clip: padding-box;
- color: #333;
- line-height: 13px;
- cursor: default;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice span {
- word-wrap: break-word;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice-focus .search-choice-close {
- background-position: -42px -10px;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice .search-choice-close {
- position: absolute;
- top: 4px;
- right: 3px;
- display: block;
- width: 12px;
- height: 12px;
- font-size: 1px;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice .search-choice-close:hover {
- background-position: -42px -10px;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice-disabled {
- padding-right: 5px;
- background-color: #e4e4e4;
- color: #666;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-choices li.search-choice-focus {
- background: #d4d4d4;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-results {
- margin: 0;
- padding: 0;
-}
-#wu-jumper .wu-chosen-container-multi .wu-chosen-drop .result-selected {
- display: list-item;
- color: #ccc;
- cursor: default;
-}
-#wu-jumper .wu-chosen-disabled .wu-chosen-single {
- cursor: default;
-}
-#wu-jumper .wu-chosen-container-active.wu-chosen-with-drop .wu-chosen-single {
- -moz-border-radius-bottomright: 0;
- border-bottom-right-radius: 0;
- -moz-border-radius-bottomleft: 0;
- border-bottom-left-radius: 0;
-}
-#wu-jumper .wu-chosen-container-active.wu-chosen-with-drop .wu-chosen-single div {
- border-left: none;
- background: transparent;
-}
-#wu-jumper .wu-chosen-container-active.wu-chosen-with-drop .wu-chosen-single div b {
- background-position: -18px 2px;
-}
-#wu-jumper .wu-chosen-container-active .wu-chosen-choices li.search-field input[type=text] {
- color: #222 !important;
-}
-#wu-jumper .wu-chosen-disabled {
- opacity: 0.5 !important;
- cursor: default;
-}
-#wu-jumper .wu-chosen-disabled .wu-chosen-container-multi.wu-chosen-choices li.search-choice .search-choice-close {
- cursor: default;
-}
-@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) {
- #wu-jumper .wu-chosen-rtl .wu-chosen-search input[type=text],
- #wu-jumper .wu-chosen-container-single .wu-chosen-single abbr,
- #wu-jumper .wu-chosen-container-single .wu-chosen-single div b,
- #wu-jumper .wu-chosen-container-single .wu-chosen-search input[type=text],
- #wu-jumper .wu-chosen-container-multi .wu-chosen-choices .search-choice .search-choice-close,
- #wu-jumper .wu-chosen-container .wu-chosen-results-scroll-down span,
- #wu-jumper .wu-chosen-container .wu-chosen-results-scroll-up span {
- background-size: 52px 37px !important;
- background-repeat: no-repeat !important;
- }
-}
-
-#wu_jumper_select_chosen { /* stylelint-disable-line selector-id-pattern */
- margin: 0;
- width: 100% !important;
- padding: 0;
-}
-
-#wu_jumper_select_chosen input { /* stylelint-disable-line selector-id-pattern */
- outline: none;
- width: 100%;
- padding: 20px !important;
-}
-
-span.wu-keys {
- margin-right: 20px;
-}
-
-span.wu-keys-key {
- display: inline-block;
- padding: 0 5px 1px;
- border: solid 2px #999;
- border-radius: 3px;
- margin: 0 2px;
-}
-
-.wu-jumper-loading,
-.wu-jumper-redirecting {
- border-top: solid 1px #cecece;
- padding: 10px;
- text-align: center;
- display: none;
-}
-
-body.rtl #wu-jumper .wu-chosen-container-single .wu-chosen-single::after {
- right: auto;
- left: 15px;
-}
-body.rtl #wu-jumper .wu-chosen-container-single .wu-chosen-single span {
- margin-right: 0;
- margin-left: 26px;
-}
\ No newline at end of file
diff --git a/assets/js/command-palette.js b/assets/js/command-palette.js
index 86356908..04a56a5f 100644
--- a/assets/js/command-palette.js
+++ b/assets/js/command-palette.js
@@ -286,7 +286,7 @@
label: entity.label_plural || entity.label + 's',
callback: ({ close }) => {
close();
- window.location.href = networkAdminUrl + 'admin.php?page=wu-' + slug.replace(/_/g, '-') + 's';
+ window.location.href = networkAdminUrl + 'admin.php?page=wu-' + slug.replaceAll('_', '-') + 's';
}
};
diff --git a/assets/js/jumper.js b/assets/js/jumper.js
deleted file mode 100644
index a9ed0067..00000000
--- a/assets/js/jumper.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/* eslint-disable no-undef */
-(function($) {
-
- $(document).ready(function() {
-
- // Adds WUChosen.js to our custom select input
- const $jumper = $('#wu-jumper-select').selectize({
- create: false,
- maxItems: 1,
- optgroupField: 'group',
- optgroupValueField: 'value',
- searchField: ['text', 'name', 'display_name', 'domain', 'title', 'desc', 'code'],
- render: {
- option(option) {
-
- if (typeof option.model === 'undefined') {
-
- option.model = 'jumper-link';
-
- } // end if;
-
- if (typeof option.text === 'undefined') {
-
- option.text = option.reference_code || option.name || option.title || option.display_name || option.code;
-
- } // end if;
-
- if (typeof option.group === 'undefined') {
-
- option.group = option.model;
-
- } // end if;
-
- const template_html = jQuery('#wu-template-' + option.model).length ?
- jQuery('#wu-template-' + option.model).html() :
- jQuery('#wu-template-default').html();
-
- const template = _.template(template_html, {
- interpolate: /\{\{(.+?)\}\}/g,
- });
-
- return template(option);
-
- },
- },
- load(query, callback) {
-
- if (! query.length) {
-
- return callback();
-
- } // end if;
-
- $('#wu-jumper .wu-jumper-loading').show();
-
- jQuery.ajax({
- // eslint-disable-next-line no-undef
- url: wu_jumper_vars.ajaxurl,
- type: 'POST',
- data: {
- action: 'wu_search',
- model: 'all',
- number: 99,
- query: {
- search: '*' + query + '*',
- },
- },
- error() {
-
- callback();
-
- },
- success(res) {
-
- $('#wu-jumper .wu-jumper-loading').hide();
-
- callback(res);
-
- },
- });
-
- },
- });
-
- const is_local_url = function(url) {
-
- return url.toLowerCase().indexOf(wu_jumper_vars.base_url) >= 0 || url.toLowerCase().indexOf(wu_jumper_vars.network_base_url) >= 0;
-
- }; // end is_local_url
-
- // Every time the value changes, we need to redirect the user
- $jumper.on('change', function() {
-
- // Check if we need to open this in a new tab
- if (is_local_url($(this).val())) {
-
- window.location.href = $(this).val();
-
- $(this).parent().parent().find('.wu-jumper-redirecting').show();
-
- } else {
-
- window.open($(this).val(), '_blank');
-
- $($jumper.parent()).hide();
-
- } // end if;
-
- });
-
- // Closes on clicking other elements
- $(document).on('click', ':not(#wu-jumper-button-trigger)', function(e) {
-
- const target = e.target;
-
- if ($(target).attr('id') === 'wu-jumper-button-trigger' || $(target).parent().attr('id') === 'wu-jumper-button-trigger') {
-
- return;
-
- } // end if;
-
- if (! $(target).is($jumper.parent()) && ! $(target).parents().is($jumper.parent())) {
-
- $($jumper.parent().parent()).hide();
-
- } // end if;
-
- });
-
- const trigger_key = wu_jumper_vars.trigger_key.charAt(0);
-
- // Our bar is hidden by default, we need to display it when a certain shortcut is pressed
- Mousetrap.bind(['command+option+' + trigger_key, 'ctrl+alt+' + trigger_key], function(e) {
-
- e.preventDefault();
-
- open_jumper();
-
- }); // end mousetrap;
-
- $(document).on('click', '#wu-jumper-button-trigger', function(e) {
-
- e.preventDefault();
-
- open_jumper();
-
- });
-
- /**
- * Actually opens the jumper.
- */
- function open_jumper() {
-
- $('#wu-jumper').show();
-
- $('#wu-jumper').find('input').focus();
-
- return false;
-
- } // end open_jumper;
-
- });
-
-}(jQuery));
-
diff --git a/inc/class-ajax.php b/inc/class-ajax.php
index 1b621e80..0af45ac0 100644
--- a/inc/class-ajax.php
+++ b/inc/class-ajax.php
@@ -27,16 +27,6 @@ class Ajax implements \WP_Ultimo\Interfaces\Singleton {
* @since 2.0.0
*/
public function init(): void {
- /*
- * Load search endpoints.
- */
- add_action('wu_ajax_wu_search', [$this, 'search_models']);
-
- /*
- * Adds the Selectize templates to the admin_footer.
- */
- add_action('in_admin_footer', [$this, 'render_selectize_templates']);
-
/*
* Load search endpoints.
*/
@@ -77,371 +67,4 @@ public function refresh_list_table(): void {
do_action('wu_list_table_fetch_ajax_results', $table_id);
}
-
- /**
- * Search models using our ajax endpoint.
- *
- * @since 2.0.0
- * @return void
- */
- public function search_models(): void {
-
- /**
- * Fires before the processing of the search request.
- *
- * @since 2.0.0
- */
- do_action('wu_before_search_models');
-
- if (wu_request('model') === 'all') {
- $this->search_all_models();
-
- return;
- }
-
- $args = wp_parse_args(
- $_REQUEST, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
- [
- 'model' => 'membership',
- 'query' => [],
- 'number' => 100,
- 'exclude' => [], // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
- ]
- );
-
- // Number can be in the query array or it's own. Code uses both.
- if (empty($args['query']['number'])) {
- $args['query']['number'] = $args['number'];
- }
-
- if ($args['exclude']) {
- if (is_string($args['exclude'])) {
- $args['exclude'] = explode(',', $args['exclude']); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
-
- $args['exclude'] = array_map('trim', $args['exclude']); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
- }
-
- $query['id__not_in'] = $args['exclude'];
- }
-
- if (wu_get_isset($args, 'include')) {
- if (is_string($args['include'])) {
- $args['include'] = explode(',', $args['include']);
-
- $args['include'] = array_map('trim', $args['include']);
- }
-
- $query['id__in'] = $args['include'];
- }
-
- /*
- * Deal with site
- */
- if ('site' === $args['model']) {
- if (wu_get_isset($query, 'id__in')) {
- $query['blog_id__in'] = $query['id__in'];
-
- unset($query['id__in']);
- }
-
- if (wu_get_isset($query, 'id__not_in')) {
- $query['blog_id__not_in'] = $query['id__not_in'];
-
- unset($query['id__not_in']);
- }
- }
-
- $results = [];
-
- // Merge the caller's query params (search term, etc.) with locally-built params.
- $query = array_merge($args['query'], $query ?? []);
-
- if ('user' === $args['model']) {
- $results = $this->search_wordpress_users($query);
- } elseif ('page' === $args['model']) {
- $results = get_posts(
- [
- 'post_type' => 'page',
- 'post_status' => 'publish',
- 'numberposts' => -1,
- 'exclude' => $query['id__not_in'] ?? '', // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
- ]
- );
- } elseif ('setting' === $args['model']) {
- $results = $this->search_wp_ultimo_setting($query);
- } else {
- $model_func = 'wu_get_' . strtolower((string) $args['model']) . 's';
-
- if (function_exists($model_func)) {
- $results = $model_func($query);
- }
- }
-
- // Try search by hash if do not have any result
- if (empty($results)) {
- $model_func = 'wu_get_' . strtolower((string) $args['model']) . '_by_hash';
-
- if (function_exists($model_func)) {
- $result = $model_func(trim((string) $query['search'], '*'));
-
- $results = $result ? [$result] : [];
- }
- }
-
- wp_send_json($results);
-
- exit;
- }
-
- /**
- * Search all models for Jumper.
- *
- * @since 2.0.0
- * @return void
- */
- public function search_all_models(): void {
-
- $query = array_merge(
- wu_request('query', []),
- [
- 'number' => 10000,
- ]
- );
-
- $results_user = array_map(
- function ($item) {
-
- $item->model = 'user';
-
- $item->group = 'Users';
-
- $item->value = network_admin_url("user-edit.php?user_id={$item->ID}");
-
- return $item;
- },
- $this->search_wordpress_users($query)
- );
-
- $results_settings = array_map(
- function ($item) {
-
- $item['model'] = 'setting';
-
- $item['group'] = 'Settings';
-
- $item['value'] = $item['url'];
-
- return $item;
- },
- $this->search_wp_ultimo_setting($query)
- );
-
- $data = array_merge($results_user, $results_settings);
-
- /**
- * Allow plugin developers to add more search models functions.
- *
- * @since 2.0.0
- */
- $data_sources = apply_filters(
- 'wu_search_models_functions',
- [
- 'wu_get_customers',
- 'wu_get_products',
- 'wu_get_plans',
- 'wu_get_domains',
- 'wu_get_sites',
- 'wu_get_memberships',
- 'wu_get_payments',
- 'wu_get_broadcasts',
- 'wu_get_checkout_forms',
- ]
- );
-
- foreach ($data_sources as $function) {
- $results = call_user_func($function, $query);
-
- $results = array_map(
- function ($item) {
-
- $row = $item->to_array();
-
- $url = str_replace('_', '-', (string) $row['model']);
-
- $row['value'] = wu_network_admin_url(
- "wp-ultimo-edit-{$url}",
- [
- 'id' => $item->get_id(),
- ]
- );
-
- $row['group'] = ucwords((string) $row['model']) . 's';
-
- return $row;
- },
- $results
- );
-
- $discount_codes = array_map(
- function ($item) {
-
- $discount = $item->to_array();
-
- $discount['value'] = wu_network_admin_url(
- 'wp-ultimo-edit-discount-code',
- [
- 'id' => $discount['id'],
- ]
- );
-
- $discount['group'] = 'Discount Codes';
-
- return $discount;
- },
- wu_get_discount_codes($query)
- );
-
- $data = array_merge($data, $results, $discount_codes);
- }
-
- wp_send_json($data);
- }
-
- /**
- * Search for Ultimate Multisite settings to help customers find them.
- *
- * @since 2.0.0
- *
- * @param array $query Query arguments.
- */
- public function search_wp_ultimo_setting($query): array {
-
- $sections = \WP_Ultimo\Settings::get_instance()->get_sections();
-
- $all_fields = [];
-
- foreach ($sections as $section_slug => $section) {
- $section['fields'] = array_map(
- function ($item) use ($section, $section_slug) {
-
- $item['section'] = $section_slug;
-
- $item['section_title'] = wu_get_isset($section, 'title', '');
-
- $item['url'] = wu_network_admin_url(
- 'wp-ultimo-settings',
- [
- 'tab' => $section_slug,
- ]
- ) . '#' . $item['setting_id'];
-
- return $item;
- },
- $section['fields']
- );
-
- $all_fields = array_merge($all_fields, $section['fields']);
- }
-
- $search_term = strtolower(trim((string) $query['search'], '*'));
-
- /*
- * Filter settings that match the search term against setting_id, title,
- * or desc fields (case-insensitive), excluding header-type fields.
- * The previous implementation only searched setting_id, which meant users
- * could not find settings by their human-readable titles.
- */
- $_settings = array_filter(
- $all_fields,
- function ($item) use ($search_term) {
-
- if (wu_get_isset($item, 'type') === 'header') {
- return false;
- }
-
- $setting_id = strtolower((string) wu_get_isset($item, 'setting_id', ''));
- $title = strtolower((string) wu_get_isset($item, 'title', ''));
- $desc = strtolower((string) wu_get_isset($item, 'desc', ''));
-
- return str_contains($setting_id, $search_term)
- || str_contains($title, $search_term)
- || str_contains($desc, $search_term);
- }
- );
-
- usort(
- $_settings,
- function ($a, $b) {
-
- return strcmp(
- (string) wu_get_isset($a, 'title', ''),
- (string) wu_get_isset($b, 'title', '')
- );
- }
- );
-
- return array_values($_settings);
- }
-
- /**
- * Handles the special case of searching native WP users.
- *
- * @since 2.0.0
- *
- * @param array $query Query arguments.
- * @return array
- */
- public function search_wordpress_users($query) {
-
- $results = get_users(
- [
- 'blog_id' => 0,
- 'search' => '*' . $query['search'] . '*',
- 'search_columns' => [
- 'ID',
- 'user_login',
- 'user_email',
- 'user_url',
- 'user_nicename',
- 'display_name',
- ],
- ]
- );
-
- $results = array_map(
- function ($item) {
-
- $item->data->user_pass = '';
-
- $item->data->avatar = get_avatar(
- $item->data->user_email,
- 40,
- 'identicon',
- '',
- [
- 'force_display' => true,
- 'class' => 'wu-rounded-full wu-mr-3',
- ]
- );
-
- return $item->data;
- },
- $results
- );
-
- return $results;
- }
-
- /**
- * Adds the selectize templates to the admin footer.
- *
- * @since 2.0.0
- * @return void
- */
- public function render_selectize_templates(): void {
-
- if (current_user_can('manage_network')) {
- wu_get_template('ui/selectize-templates');
- }
- }
}
diff --git a/inc/ui/class-jumper.php b/inc/ui/class-jumper.php
deleted file mode 100644
index 298201b5..00000000
--- a/inc/ui/class-jumper.php
+++ /dev/null
@@ -1,570 +0,0 @@
- $page,
- 'jumper' => $this,
- ]
- );
- }
-
- /**
- * Loads the necessary elements to display the Jumper.
- *
- * @since 2.0.0
- * @return void
- */
- public function load_jumper(): void {
-
- if ($this->is_jumper_enabled() && is_admin()) {
- add_action('wu_header_right', [$this, 'add_jumper_trigger']);
-
- add_action('admin_init', [$this, 'rebuild_menu']);
-
- add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
-
- add_action('admin_enqueue_scripts', [$this, 'enqueue_styles']);
-
- add_action('admin_footer', [$this, 'output']);
-
- add_filter('update_footer', [$this, 'add_jumper_footer_message'], 200);
-
- add_action('wu_after_save_settings', [$this, 'clear_jump_cache_on_save']);
-
- add_filter('wu_link_list', [$this, 'add_wp_ultimo_extra_links']);
-
- add_filter('wu_link_list', [$this, 'add_user_custom_links']);
- }
- }
-
- /**
- * Clear the jumper menu cache on settings save
- *
- * We need to do this to make sure that we clear the menu when the admin
- * adds a new custom menu item.
- *
- * @since 2.0.0
- *
- * @param array $settings Settings being saved.
- * @return void
- */
- public function clear_jump_cache_on_save($settings): void {
-
- if (isset($settings['jumper_custom_links'])) {
- delete_site_transient($this->transient_key);
- }
- }
-
- /**
- * Rebuilds the jumper menu via a trigger URL.
- *
- * @since 2.0.0
- * @return void
- */
- public function rebuild_menu(): void {
-
- if (isset($_GET[ $this->reset_slug ]) && isset($_GET['nonce']) && current_user_can('manage_network') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['nonce'])), 'reset_password')) {
- delete_site_transient($this->transient_key);
-
- wp_safe_redirect(network_admin_url());
-
- exit;
- }
- }
-
- /**
- * Retrieves the custom links added by the super admin
- *
- * @since 2.0.0
- * @return array
- */
- public function get_user_custom_links() {
-
- $treated_lines = [];
-
- $saved_links = wu_get_setting('jumper_custom_links', '');
-
- $lines = explode(PHP_EOL, (string) $saved_links);
-
- foreach ($lines as $line) {
- $link_elements = explode(':', $line, 2);
-
- if (count($link_elements) === 2) {
- $title = trim($link_elements[1]);
-
- $treated_lines[ $title ] = trim($link_elements[0]);
- }
- }
-
- return $treated_lines;
- }
-
- /**
- * Add the custom links to the Jumper menu
- *
- * @since 2.0.0
- *
- * @param array $links Jumper links already saved.
- * @return array
- */
- public function add_user_custom_links($links) {
-
- $custom_links = $this->get_user_custom_links();
-
- if ( ! empty($custom_links)) {
- $links[ __('Custom Links', 'ultimate-multisite') ] = $custom_links;
- }
-
- return $links;
- }
-
- /**
- * Add Ultimate Multisite settings links to the Jumper menu.
- *
- * @since 2.0.0
- *
- * @param array $links Ultimate Multisite settings array.
- * @return array
- */
- public function add_wp_ultimo_extra_links($links) {
-
- if (isset($links['WP Ultimo'])) {
- $settings_tabs = [
- 'general' => __('General', 'ultimate-multisite'),
- 'network' => __('Network Settings', 'ultimate-multisite'),
- 'gateways' => __('Payment Gateways', 'ultimate-multisite'),
- 'domain_mapping' => __('Domain Mapping & SSL', 'ultimate-multisite'),
- 'emails' => __('Emails', 'ultimate-multisite'),
- 'styling' => __('Styling', 'ultimate-multisite'),
- 'tools' => __('Tools', 'ultimate-multisite'),
- 'advanced' => __('Advanced', 'ultimate-multisite'),
- 'activation' => __('Activation & Support', 'ultimate-multisite'),
- ];
-
- foreach ($settings_tabs as $tab => $tab_label) {
- $url = network_admin_url('admin.php?page=wp-ultimo-settings&wu-tab=' . $tab);
-
- // translators: The placeholder represents the title of the Settings tab.
- $links['WP Ultimo'][ $url ] = sprintf(__('Settings: %s', 'ultimate-multisite'), $tab_label);
- }
-
- $links['WP Ultimo'][ network_admin_url('admin.php?page=wp-ultimo-settings&wu-tab=tools') ] = __('Settings: Webhooks', 'ultimate-multisite');
-
- $links['WP Ultimo'][ network_admin_url('admin.php?page=wp-ultimo-system-info&wu-tab=logs') ] = __('System Info: Logs', 'ultimate-multisite');
-
- /**
- * Adds Main Site Dashboard
- */
- if (isset($links[ __('Sites') ])) { // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
- $main_site_url = get_admin_url(get_current_site()->site_id);
-
- $links[ __('Sites') ][ $main_site_url ] = __('Main Site Dashboard', 'ultimate-multisite'); // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
- }
- }
-
- return $links;
- }
-
- /**
- * Get the trigger key defined by the user.
- *
- * @since 2.0.0
- */
- public function get_defined_trigger_key(): string {
-
- return substr((string) wu_get_setting('jumper_key', 'g'), 0, 1);
- }
-
- /**
- * Get the trigger key combination depending on the OS
- *
- * - For Win & Linux: ctrl + alt + key defined by user;
- * - For Mac: command + option + key defined by user.
- *
- * @since 2.0.0
- *
- * @param string $os OS to get the key combination for. Options: win or osx.
- * @return array
- */
- public function get_keys($os = 'win') {
-
- $trigger_key = $this->get_defined_trigger_key();
-
- $keys = [
- 'win' => ['ctrl', 'alt', $trigger_key],
- 'osx' => ['command', 'option', $trigger_key],
- ];
-
- return $keys[ $os ] ?? $keys['win'];
- }
-
- /**
- * Changes the helper footer message about the Jumper and its trigger
- *
- * @since 2.0.0
- *
- * @param string $text The default WordPress right footer message.
- * @return string
- */
- public function add_jumper_footer_message($text) {
-
- if ( ! wu_get_setting('jumper_display_tip', true)) {
- return $text;
- }
-
- $os = isset($_SERVER['HTTP_USER_AGENT']) && stristr(sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])), 'mac') ? 'osx' : 'win';
-
- $keys = $this->get_keys($os);
-
- $html = '';
-
- foreach ($keys as $key) {
- $html .= '' . $key . '+';
- }
-
- $html = trim($html, '+');
-
- // translators: the %s placeholder is the key combination to trigger the Jumper.
- return '' . sprintf(__('Quick Tip: Use %s to jump between pages.', 'ultimate-multisite'), $html) . '' . $text;
- }
-
- /**
- * Enqueues the JavaScript files necessary to make the jumper work.
- *
- * @since 2.0.0
- * @return void
- */
- public function enqueue_scripts(): void {
-
- wp_register_script('wu-mousetrap', wu_get_asset('mousetrap.js', 'js/lib'), ['jquery'], wu_get_version(), true);
-
- wp_register_script('wu-jumper', wu_get_asset('jumper.js', 'js'), ['jquery', 'wu-selectize', 'wu-mousetrap', 'underscore'], wu_get_version(), true);
-
- wp_localize_script(
- 'wu-jumper',
- 'wu_jumper_vars',
- [
- 'not_found_message' => __('Nothing found for', 'ultimate-multisite'),
- 'trigger_key' => $this->get_defined_trigger_key(),
- 'network_base_url' => network_admin_url(),
- 'ajaxurl' => wu_ajax_url(),
- 'base_url' => get_admin_url(get_current_site()->site_id),
- ]
- );
-
- wp_enqueue_script('wu-jumper');
-
- wp_enqueue_style('wu-admin');
- }
-
- /**
- * Enqueues the CSS files necessary to make the jumper work.
- *
- * @since 2.0.0
- * @return void
- */
- public function enqueue_styles(): void {
-
- wp_enqueue_style('wu-jumper', wu_get_asset('jumper.css', 'css'), [], wu_get_version());
- }
-
- /**
- * Outputs the actual HTML markup of the Jumper.
- *
- * @since 2.0.0
- * @return void
- */
- public function output(): void {
-
- wu_get_template(
- 'ui/jumper',
- [
- 'menu_groups' => $this->get_link_list(),
- ]
- );
- }
-
- /**
- * Get the full page URL for admin pages.
- *
- * @since 2.0.0
- *
- * @param string $url URL of the menu item.
- */
- public function get_menu_page_url($url): string {
-
- $final_url = menu_page_url($url, false);
-
- return str_replace(admin_url(), network_admin_url(), $final_url);
- }
-
- /**
- * Returns the URL of a jumper menu item
- *
- * If the URL is an absolute URL, returns the full-url.
- * If the URL is relative, we return the full URL using WordPress url functions.
- *
- * @since 2.0.0
- *
- * @param string $url URL of the menu item.
- * @return string
- */
- public function get_target_url($url) {
-
- if (str_contains($url, 'http')) {
- return $url;
- }
-
- if (str_contains($url, '.php')) {
- return network_admin_url($url);
- }
-
- return $this->get_menu_page_url($url);
- }
-
- /**
- * Builds the list of links based on the $menu and $submenu globals.
- *
- * @since 2.0.0
- *
- * @return array
- */
- public function build_link_list() {
-
- return Logger::track_time(
- 'jumper',
- __('Regenerating Jumper menu items', 'ultimate-multisite'),
- function () {
-
- global $menu, $submenu;
-
- // This variable is going to carry our options
- $choices = [];
-
- // Prevent first run bug
- if ( ! is_array($menu) || ! is_array($submenu)) {
- return [];
- }
-
- // Loop all submenus so que can get our final
- foreach ($submenu as $menu_name => $submenu_items) {
- $title = $this->search_recursive($menu_name, $menu);
-
- $string = wu_get_isset($title, 0, '');
-
- $title = preg_replace('/[0-9]+/', '', wp_strip_all_tags($string));
-
- // If parent does not exists, skip
- if ( ! empty($title) && is_array($submenu_items)) {
-
- // We have to loop now each submenu
- foreach ($submenu_items as $submenu_item) {
- $url = $this->get_target_url($submenu_item[2]);
-
- // Add to our choices the admin urls
- }
- }
- }
-
- $choices = apply_filters('wu_link_list', $choices);
-
- set_site_transient($this->transient_key, $choices, 10 * MINUTE_IN_SECONDS);
-
- return $choices;
- }
- );
- }
-
- /**
- * Gets the cached menu list saved.
- *
- * @since 2.0.0
- * @return array
- */
- public function get_saved_menu() {
-
- $saved_menu = get_site_transient($this->transient_key);
-
- return $saved_menu ?: [];
- }
-
- /**
- * Returns the link list.
- *
- * @since 2.0.0
- * @return array
- */
- public function get_link_list() {
-
- $should_rebuild_menu = ! get_site_transient($this->transient_key);
-
- return $should_rebuild_menu && is_network_admin() ? $this->build_link_list() : $this->get_saved_menu();
- }
-
- /**
- * Filter the Ultimate Multisite settings to add Jumper options
- *
- * @since 2.0.0
- *
- * @return void
- */
- public function add_settings(): void {
-
- wu_register_settings_section(
- 'tools',
- [
- 'title' => __('Tools', 'ultimate-multisite'),
- 'desc' => __('Tools', 'ultimate-multisite'),
- 'icon' => 'dashicons-wu-tools',
- ]
- );
-
- wu_register_settings_field(
- 'tools',
- 'tools_header',
- [
- 'title' => __('Jumper', 'ultimate-multisite'),
- 'desc' => __('Spotlight-like search bar that allows you to easily access everything on your network.', 'ultimate-multisite'),
- 'type' => 'header',
- ]
- );
-
- wu_register_settings_field(
- 'tools',
- 'enable_jumper',
- [
- 'title' => __('Enable Jumper', 'ultimate-multisite'),
- 'desc' => __('Turn this option on to make the Jumper available on your network.', 'ultimate-multisite'),
- 'type' => 'toggle',
- 'default' => 1,
- ]
- );
-
- wu_register_settings_field(
- 'tools',
- 'jumper_key',
- [
- 'title' => __('Trigger Key', 'ultimate-multisite'),
- 'desc' => __('Change the keyboard key used in conjunction with ctrl + alt (or cmd + option), to trigger the Jumper box.', 'ultimate-multisite'),
- 'type' => 'text',
- 'default' => 'g',
- 'require' => [
- 'enable_jumper' => 1,
- ],
- ]
- );
-
- wu_register_settings_field(
- 'tools',
- 'jumper_custom_links',
- [
- 'title' => __('Custom Links', 'ultimate-multisite'),
- 'desc' => __('Use this textarea to add custom links to the Jumper. Add one per line, with the format "Title : url".', 'ultimate-multisite'),
- 'placeholder' => __('Tile of Custom Link : http://link.com', 'ultimate-multisite'),
- 'type' => 'textarea',
- 'html_attr' => [
- 'rows' => 4,
- ],
- 'require' => [
- 'enable_jumper' => 1,
- ],
- ]
- );
- }
-
- /**
- * Helper function to recursively seach an array.
- *
- * @since 2.0.0
- *
- * @param string $needle String to seach recursively.
- * @param array $haystack Array to search.
- * @return mixed
- */
- public function search_recursive($needle, $haystack) {
-
- foreach ($haystack as $key => $value) {
- $current_key = $key;
-
- if ($needle === $value || (is_array($value) && $this->search_recursive($needle, $value) !== false)) {
- return $value;
- }
- }
-
- return false;
- }
-}