PluginProbe
Filter Everything — WordPress & WooCommerce Filters / trunk
Filter Everything — WordPress & WooCommerce Filters vtrunk
1.9.6 1.9.5 1.9.4 1.9.3 1.9.2.2 1.9.2.1 trunk 1.2.1 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.1 1.4.4 1.4.5 1.4.8 1.4.9 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 All 51 releases
filter-everything / src / Settings / Tabs / SettingsTab.php

SettingsTab.php in Filter Everything — WordPress & WooCommerce Filters trunk, at src/Settings/Tabs/SettingsTab.php

285 lines 16.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FilterEverything\Filter;
4
5 if ( ! defined('ABSPATH') ) {
6 exit;
7 }
8
9 class SettingsTab extends BaseSettings
10 {
11 protected $page = 'wpc-filter-admin-settings';
12
13 protected $group = 'wpc_filter';
14
15 protected $optionName = 'wpc_filter_settings';
16
17 public function init()
18 {
19 add_action('admin_init', array($this, 'initSettings'));
20 }
21
22 public function initSettings()
23 {
24 register_setting($this->group, $this->optionName);
25 /**
26 * @see https://developer.wordpress.org/reference/functions/add_settings_field/
27 */
28 $defaultPostsContainer = flrt_default_posts_container();
29 $defaultPrimaryColor = flrt_default_theme_color();
30
31 $settings = array(
32 'mobile_devices' => array(
33 'label' => esc_html__('Mobile devices', 'filter-everything'),
34 'fields' => array(
35 'mobile_filter_settings' => array(
36 'type' => 'select',
37 'title' => esc_html__('Filters widget on mobile should be', 'filter-everything'),
38 'options' => array(
39 'nothing' => esc_html__('The same as on a desktop', 'filter-everything'),
40 'show_open_close_button' => esc_html__('Collapsed and expanded', 'filter-everything'),
41 ),
42 'default' => 'no',
43 'id' => 'mobile_filter_settings',
44 ),
45 /*'show_open_close_button' => array(
46 'type' => 'checkbox',
47 'title' => esc_html__('Collapse Filters Widget on Mobile devices', 'filter-everything'),
48 'id' => 'show_open_close_button',
49 'label' => esc_html__('Collapse the widget and show the Filters opening button', 'filter-everything'),
50 ),*/
51 'try_move_to_top_sidebar' => array(
52 'type' => 'checkbox',
53 'title' => esc_html__('Sidebar on top', 'filter-everything'),
54 'id' => 'try_move_to_top_sidebar',
55 'label' => esc_html__('Try to move the sidebar to the top on mobile devices', 'filter-everything'),
56 )
57 ),
58 ),
59 'ajax' => array(
60 'label' => esc_html__('AJAX', 'filter-everything'),
61 'fields' => array(
62 'enable_ajax' => array(
63 'type' => 'checkbox',
64 'title' => esc_html__('AJAX for Filters', 'filter-everything'),
65 'id' => 'enable_ajax',
66 'label' => esc_html__('Try to use AJAX', 'filter-everything'),
67 'description' => esc_html__( 'Please enable this option only after you have ensured that the filtering is working correctly', 'filter-everything' ),
68 ),
69 'posts_container' => array(
70 'type' => 'text',
71 'title' => esc_html__('Results container', 'filter-everything'),
72 'id' => 'posts_container',
73 'default' => $defaultPostsContainer,
74 'description' => esc_html__( 'e.g. #primary or .main-content', 'filter-everything' ),
75 'label' => '',
76 'tooltip' => wp_kses(
77 __( 'The part of the page where your posts or products are listed. When AJAX is enabled, the plugin refreshes only this area after each filter click, without reloading the whole page.<br /><br />Click «Select visually» and simply click the area with your posts, or enter its CSS id or class if you know it.', 'filter-everything' ),
78 array( 'br' => array() )
79 ),
80 'additional_link' => [
81 'label' => esc_html__( 'Select visually', 'filter-everything' ),
82 'url' => add_query_arg(
83 [
84 'flrt_get_html_selector' => 1,
85 'flrt_set_id' => 'global_posts_container',
86 ],
87 flrt_default_selector_page_link()
88 ),
89 ],
90 ),
91 'apply_button_instant_recount' => array(
92 'type' => (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO) ? 'checkbox' : 'inProButton',
93 'pro_label' => (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO) ? '' : flrt_pro_promo_label(),
94 'title' => esc_html__('Instant recount for the «Apply Button» mode', 'filter-everything'),
95 'id' => 'apply_button_instant_recount',
96 'label' => esc_html__('Instantly recalculate filter counters in the browser', 'filter-everything'),
97 'description' => (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO)
98 ? esc_html__( 'When disabled, Filter Sets in the «Apply Button» mode recalculate counters on the server with an AJAX request on every filter click.', 'filter-everything' )
99 // Free: promo wording — sells what the PRO option does
100 : esc_html__( 'When enabled, Filter Sets in the «Apply Button» mode recalculate counters instantly in the browser, without an AJAX request on every filter click.', 'filter-everything' ),
101 'tooltip' => wp_kses(
102 __( 'This option greatly speeds up filtering, but the recount runs in the visitor\'s browser and may be heavy on sites with a large amount of content. If you filter more than 30,000 posts, make sure filtering does not freeze — especially on mobile devices.', 'filter-everything' ),
103 array( 'br' => array() )
104 ),
105 )
106 )
107 ),
108 'crawlers' => array(
109 'label' => esc_html__('Crawlers and bots', 'filter-everything'),
110 'fields' => $this->crawlerFields(),
111 ),
112 'common_settings' => array(
113 'label' => esc_html__('Other', 'filter-everything'),
114 'fields' => array(
115 'primary_color' => array(
116 'type' => 'text',
117 'title' => esc_html__('Widget Primary Color', 'filter-everything'),
118 'id' => 'wpc_primary_color',
119 'default' => $defaultPrimaryColor,
120 'label' => '',
121 ),
122 'container_height' => array(
123 'type' => 'text',
124 'title' => esc_html__('Filter Container max height, px', 'filter-everything'),
125 'id' => 'container_height',
126 'label' => '',
127 ),
128 'show_terms_in_content' => array(
129 'type' => 'select',
130 'title' => esc_html__('Selected Filters (Chips) integration', 'filter-everything'),
131 'id' => 'show_terms_in_content',
132 'label' => esc_html__('Try to show selected terms above the Results container', 'filter-everything'),
133 'options' => array(),
134 'multiple' => true,
135 'description' => esc_html__( 'Select where to show Chips on your site. Or enter your theme\'s hooks. For example: before_main_content', 'filter-everything' )
136 ),
137 'widget_debug_messages' => array(
138 'type' => 'checkbox',
139 'title' => esc_html__('Debug mode', 'filter-everything'),
140 'id' => 'widget_debug_messages',
141 'label' => esc_html__('Enable debugging messages to help to configure filters', 'filter-everything'),
142 )
143 )
144 )
145 );
146
147 if (!defined('FLRT_FILTERS_PRO')) {
148 $settings['mobile_devices']['fields']['mobile_filter_settings']['options'][''] = esc_html__('Appear as a Pop-up', 'filter-everything') . ' &mdash; ' . esc_html__('Available in PRO', 'filter-everything');
149 $settings['mobile_devices']['fields']['mobile_filter_settings']['disabled'][] = '';
150 }
151
152 $settings = apply_filters('wpc_general_filters_settings', $settings);
153
154 $this->registerSettings($settings, $this->page, $this->optionName);
155 }
156
157 /**
158 * «Crawlers and bots» section.
159 *
160 * Hiding the filter links is available in both builds since 1.9.6: in free every
161 * filter link becomes a <span> (filter pages are noindex there by design, so the
162 * links only feed crawler traps); PRO keeps a real <a> for the targets its SEO
163 * Rules index (smart spans). The robots.txt helper (both builds; the PRO rule
164 * set names only never-indexable URL classes) follows
165 * flrt_robots_helper_available() — see src/RobotsTxt.php.
166 */
167 protected function crawlerFields()
168 {
169 $is_pro = defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO;
170
171 $fields = array(
172 'disable_filter_links_for_bots' => array(
173 'type' => 'checkbox',
174 'title' => esc_html__('Disable filter links for crawlers', 'filter-everything'),
175 'id' => 'disable_filter_links_for_bots',
176 'description' => esc_html__( 'Replaces &lt;a&gt; tags with &lt;span&gt; in filters to prevent crawlers from following filter links and overloading your site.', 'filter-everything' ),
177 'tooltip' => $is_pro
178 ? wp_kses(
179 __( 'Filter combinations produce thousands of URLs, and crawlers may waste your crawl budget and server resources trying to follow them all. This option renders filter links as &lt;span&gt; tags — they keep working for visitors, but crawlers no longer see them as links.<br /><br />Links to pages that your SEO Rules define as indexed always keep the real &lt;a&gt; tag, so search engines can still discover and rank those pages.<br /><br />You can also block unwanted pages and specific bots in the robots.txt file.', 'filter-everything' ),
180 array( 'br' => array() )
181 )
182 : wp_kses(
183 __( 'Filter combinations produce thousands of URLs, and crawlers may waste your crawl budget and server resources trying to follow them all. This option renders filter links as &lt;span&gt; tags — they keep working for visitors, but crawlers no longer see them as links.<br /><br />Filtering result pages are marked noindex in the free version anyway, so hiding the links costs nothing in search visibility. The PRO version keeps the real &lt;a&gt; tag for the filter pages that its SEO Rules make indexable.<br /><br />Crawlers that already know your filter URLs may keep requesting them for a while — the robots.txt rules below stop that too.', 'filter-everything' ),
184 array( 'br' => array() )
185 ),
186 ),
187 );
188
189 if ( function_exists( 'flrt_robots_helper_available' ) && flrt_robots_helper_available() ) {
190 $fields['robots_txt_block_filters'] = array(
191 'type' => 'checkbox',
192 'title' => esc_html__('Block filter URLs in robots.txt', 'filter-everything'),
193 'id' => 'robots_txt_block_filters',
194 'label' => esc_html__('Add Disallow rules for all filter URLs to the robots.txt file', 'filter-everything'),
195 'description' => esc_html__( 'Tells search engines and other well-behaved crawlers not to request filtering result pages at all. Bots that ignore robots.txt are not affected.', 'filter-everything' ),
196 'tooltip' => $is_pro
197 ? wp_kses(
198 __( 'Hiding the filter links stops crawlers from discovering new filter URLs, but the URLs they already know stay in their queues for weeks or months. A Disallow rule in robots.txt is the only signal that also stops compliant crawlers — Google, Bing and most AI bots — from requesting those pages at all, which frees both your server and your crawl budget.<br /><br />With pretty permalinks the rules name only the filter URLs that are never indexable: several values of one filter (…/color-red-or-blue/), more filters in one URL than your Indexing Depth allows, and numeric or date ranges. Single-filter pages stay crawlable, so the pages your SEO Rules index are never touched. Review the list before enabling: a product or category slug that starts with one of your filter prefixes would match the same pattern.<br /><br />When your site has a physical robots.txt file, WordPress cannot add the rules for you — copy them into that file yourself.', 'filter-everything' ),
199 array( 'br' => array() )
200 )
201 : wp_kses(
202 __( 'Hiding the filter links stops crawlers from discovering new filter URLs, but the URLs they already know stay in their queues for weeks or months. A Disallow rule in robots.txt is the only signal that also stops compliant crawlers — Google, Bing and most AI bots — from requesting those pages at all, which frees both your server and your crawl budget.<br /><br />The rules are generated from your filters and stay in sync automatically. When your site has a physical robots.txt file, WordPress cannot add them for you — copy the rules shown below into that file yourself.', 'filter-everything' ),
203 array( 'br' => array() )
204 ),
205 );
206 $fields['robots_txt_rules'] = array(
207 'type' => 'html',
208 'title' => esc_html__('Rules for robots.txt', 'filter-everything'),
209 'id' => 'robots_txt_rules',
210 'render' => array( $this, 'renderRobotsRules' ),
211 );
212 }
213
214 return $fields;
215 }
216
217 /**
218 * The generated robots.txt block plus a status line saying whether WordPress
219 * adds it automatically (virtual robots.txt) or the user has to paste it.
220 */
221 public function renderRobotsRules( $args )
222 {
223 $rules = function_exists( 'flrt_robots_txt_rules' ) ? flrt_robots_txt_rules() : '';
224
225 if ( $rules === '' ) {
226 printf(
227 '<p class="description">%s</p>',
228 esc_html__( 'No filters are configured yet — the rules will appear here as soon as you create a Filter Set.', 'filter-everything' )
229 );
230 return;
231 }
232
233 $rows = min( 20, substr_count( $rules, "\n" ) + 2 );
234
235 printf(
236 '<textarea class="large-text code" rows="%d" id="%s" readonly onclick="this.select()">%s</textarea>',
237 (int) $rows,
238 esc_attr( $args['id'] ),
239 esc_textarea( $rules )
240 );
241
242 if ( flrt_robots_txt_is_physical() ) {
243 printf(
244 '<p class="wpc-warning">%s</p>',
245 esc_html__( 'Your site has a physical robots.txt file, so WordPress cannot add these rules automatically. Copy them into that file yourself.', 'filter-everything' )
246 );
247 } elseif ( ! get_option( 'permalink_structure' ) ) {
248 printf(
249 '<p class="wpc-warning">%s</p>',
250 esc_html__( 'WordPress serves its robots.txt only when pretty permalinks are enabled (Settings → Permalinks). Until then, copy these rules into a physical robots.txt file.', 'filter-everything' )
251 );
252 } elseif ( flrt_get_option( 'robots_txt_block_filters' ) === 'on' ) {
253 printf(
254 '<p class="description">%s</p>',
255 sprintf(
256 /* translators: %s: link to the site's robots.txt */
257 esc_html__( 'These rules are added to %s automatically.', 'filter-everything' ),
258 '<a href="' . esc_url( home_url( '/robots.txt' ) ) . '" target="_blank" rel="noopener">robots.txt</a>'
259 )
260 );
261 } else {
262 printf(
263 '<p class="description">%s</p>',
264 esc_html__( 'Enable the option above to add these rules to robots.txt automatically, or copy them into your own robots.txt file.', 'filter-everything' )
265 );
266 }
267 }
268
269 public function getLabel()
270 {
271 return esc_html__('General', 'filter-everything');
272 }
273
274 public function getName()
275 {
276 return 'settings';
277 }
278
279 public function valid()
280 {
281 return true;
282 }
283 }
284
285