Search Meter - Version 2.7

Version Description

  • Don't show duplicated recent searches
  • Add filter list so that search terms with certain words will not show up in recent and popular search lists
  • Search links work whether or not fancy permalinks are enabled
  • Administrator can decide who is allowed to see full statistics
  • Requires WordPress 2.3 or later
Download this release

Release Info

Developer bennettmcelwee
Plugin Icon 128x128 Search Meter
Version 2.7
Comparing to
See all releases

Code changes from version 2.6 to 2.7

Files changed (2) hide show
  1. readme.txt +11 -4
  2. search-meter.php +108 -21
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: bennettmcelwee
3
  Donate link: http://www.thunderguy.com/semicolon/wordpress/search-meter-wordpress-plugin/
4
  Tags: search, meter, search-meter, statistics, widget, admin
5
- Requires at least: 1.5
6
- Tested up to: 2.8.4
7
- Stable tag: 2.6
8
 
9
  Search Meter tracks what your readers are searching for on your blog. View full details of recent searches or stats for the last day, week or month.
10
 
@@ -22,7 +22,7 @@ To see your search statistics, Log in to WordPress Admin, go to the Dashboard se
22
 
23
  = Manage Statistics =
24
 
25
- There are a couple of management option available if you go to the Settings section and click Search Meter. Use the Reset Statistics button to clear all past search statistics; Search Meter will immediately start gathering fresh statistics. If you're technically-minded, you might want to check the "Keep detailed information" checkbox to make Search Meter save technical information about every search (the information is taken from the HTTP headers).
26
 
27
  == Installation ==
28
 
@@ -69,6 +69,13 @@ The [Search Meter home page](http://www.thunderguy.com/semicolon/wordpress/searc
69
 
70
  == Changelog ==
71
 
 
 
 
 
 
 
 
72
  = 2.6 =
73
  * Use UTF8 when creating tables
74
  * Fix PHP 5.3 incompatibility
2
  Contributors: bennettmcelwee
3
  Donate link: http://www.thunderguy.com/semicolon/wordpress/search-meter-wordpress-plugin/
4
  Tags: search, meter, search-meter, statistics, widget, admin
5
+ Requires at least: 2.3
6
+ Tested up to: 2.9.2
7
+ Stable tag: 2.7
8
 
9
  Search Meter tracks what your readers are searching for on your blog. View full details of recent searches or stats for the last day, week or month.
10
 
22
 
23
  = Manage Statistics =
24
 
25
+ There are a few management option available if you go to the Settings section and click Search Meter. Use the radio buttons to determine who will be allowed to see the full search statistics. Use the Reset Statistics button to clear all past search statistics; Search Meter will immediately start gathering fresh statistics. If you're technically-minded, you might want to check the "Keep detailed information" checkbox to make Search Meter save technical information about every search (the information is taken from the HTTP headers).
26
 
27
  == Installation ==
28
 
69
 
70
  == Changelog ==
71
 
72
+ = 2.7 =
73
+ * Don't show duplicated recent searches
74
+ * Add filter list so that search terms with certain words will not show up in recent and popular search lists
75
+ * Search links work whether or not fancy permalinks are enabled
76
+ * Administrator can decide who is allowed to see full statistics
77
+ * Requires WordPress 2.3 or later
78
+
79
  = 2.6 =
80
  * Use UTF8 when creating tables
81
  * Fix PHP 5.3 incompatibility
search-meter.php CHANGED
@@ -3,11 +3,11 @@
3
  Plugin Name: Search Meter
4
  Plugin URI: http://www.thunderguy.com/semicolon/wordpress/search-meter-wordpress-plugin/
5
  Description: Keeps track of what your visitors are searching for. After you have activated this plugin, you can check the Search Meter section in the Dashboard to see what your visitors are searching for on your blog.
6
- Version: 2.6
7
  Author: Bennett McElwee
8
  Author URI: http://www.thunderguy.com/semicolon/
9
 
10
- $Revision: 159273 $
11
 
12
 
13
  INSTRUCTIONS
@@ -29,7 +29,7 @@ INSTRUCTIONS
29
  Thanks to Kaufman (http://www.terrik.com/wordpress/) and the many others who have offered suggestions.
30
 
31
 
32
- Copyright (C) 2005-09 Bennett McElwee (bennett at thunderguy dotcom)
33
 
34
  This program is free software; you can redistribute it and/or
35
  modify it under the terms of version 2 of the GNU General Public
@@ -66,11 +66,11 @@ define('TGUY_SM_ALLOW_DUPLICATE_SAVES', false);
66
  // in the details). This will mess up the stats, but could be useful
67
  // for troubleshooting.
68
 
69
- define('TGUY_SM_STATS_CAPABILITY_LEVEL', 1);
70
- // Minimum user capability level for users to be able to see stats.
71
 
72
- define('TGUY_SM_OPTIONS_CAPABILITY_LEVEL', 10);
73
- // Minimum user capability level for users to be able to set options.
74
 
75
 
76
  // Template Tags
@@ -78,50 +78,92 @@ define('TGUY_SM_OPTIONS_CAPABILITY_LEVEL', 10);
78
 
79
  function sm_list_popular_searches($before = '', $after = '', $count = 5) {
80
  // List the most popular searches in the last month in decreasing order of popularity.
81
- global $wpdb, $table_prefix;
82
  $count = intval($count);
 
 
83
  // This is a simpler query than the report query, and may produce
84
  // slightly different results. This query returns searches if they
85
  // have ever had any hits, even if the last search yielded no hits.
86
  // This makes for a more efficient search -- important if this
87
  // function will be used in a sidebar.
88
  $results = $wpdb->get_results(
89
- "SELECT `terms`,
90
- SUM( `count` ) AS countsum
91
  FROM `{$table_prefix}searchmeter`
92
  WHERE DATE_SUB( CURDATE( ) , INTERVAL 30 DAY ) <= `date`
93
  AND 0 < `last_hits`
 
94
  GROUP BY `terms`
95
  ORDER BY countsum DESC, `terms` ASC
96
  LIMIT $count");
97
  if (count($results)) {
98
  echo "$before\n<ul>\n";
 
99
  foreach ($results as $result) {
100
- echo '<li><a href="'. get_settings('home') . '/search/' . urlencode($result->terms) . '">'. htmlspecialchars($result->terms) .'</a></li>'."\n";
101
  }
102
  echo "</ul>\n$after\n";
103
  }
104
  }
105
 
106
  function sm_list_recent_searches($before = '', $after = '', $count = 5) {
107
- // List the most recent successful searches.
108
  global $wpdb, $table_prefix;
109
  $count = intval($count);
 
 
110
  $results = $wpdb->get_results(
111
- "SELECT `terms`, `datetime`
112
  FROM `{$table_prefix}searchmeter_recent`
113
  WHERE 0 < `hits`
114
- ORDER BY `datetime` DESC
 
 
115
  LIMIT $count");
116
  if (count($results)) {
117
  echo "$before\n<ul>\n";
 
118
  foreach ($results as $result) {
119
- echo '<li><a href="'. get_settings('home') . '/search/' . urlencode($result->terms) . '">'. htmlspecialchars($result->terms) .'</a></li>'."\n";
120
  }
121
  echo "</ul>\n$after\n";
122
  }
123
  }
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  // Hooks
127
 
@@ -426,8 +468,13 @@ function tguy_sm_reset_stats() {
426
  }
427
 
428
  function tguy_sm_add_admin_pages() {
429
- add_submenu_page('index.php', 'Search Meter Statistics', 'Search Meter', TGUY_SM_STATS_CAPABILITY_LEVEL, __FILE__, 'tguy_sm_stats_page');
430
- add_options_page('Search Meter', 'Search Meter', TGUY_SM_OPTIONS_CAPABILITY_LEVEL, __FILE__, 'tguy_sm_options_page');
 
 
 
 
 
431
  }
432
 
433
 
@@ -555,7 +602,7 @@ function tguy_sm_summary_page() {
555
 
556
  <h2>Notes</h2>
557
 
558
- <?php if (current_user_can(TGUY_SM_OPTIONS_CAPABILITY_LEVEL)) : ?>
559
  <p>To manage your search statistics, go to the <strong>Settings</strong> section and choose <strong>Search Meter</strong>.</p>
560
  <?php endif; ?>
561
 
@@ -700,7 +747,7 @@ function tguy_sm_recent_page($max_lines, $do_show_details) {
700
 
701
  <h2>Notes</h2>
702
 
703
- <?php if (current_user_can(TGUY_SM_OPTIONS_CAPABILITY_LEVEL)) : ?>
704
  <p>To manage your search statistics, go to the <strong>Settings</strong> section and choose <strong>Search Meter</strong>.</p>
705
  <?php endif; ?>
706
 
@@ -720,6 +767,12 @@ function tguy_sm_options_page() {
720
  if (isset($_POST['submitted'])) {
721
  check_admin_referer('search-meter-update-options_all');
722
  $options = get_option('tguy_search_meter');
 
 
 
 
 
 
723
  $options['sm_details_verbose'] = (bool)($_POST['sm_details_verbose']);
724
  $options['sm_disable_donation'] = (bool)($_POST['sm_disable_donation']);
725
  update_option('tguy_search_meter', $options);
@@ -730,6 +783,10 @@ function tguy_sm_options_page() {
730
  echo '<div id="message" class="updated fade"><p><strong>Statistics have been reset.</strong></p></div>';
731
  }
732
  $options = get_option('tguy_search_meter');
 
 
 
 
733
  ?>
734
  <div class="wrap">
735
 
@@ -746,7 +803,37 @@ function tguy_sm_options_page() {
746
 
747
  <table class="form-table">
748
  <tr>
749
- <th class="th-full" scope="row">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  <label for="sm_details_verbose">
751
  <input type="checkbox" id="sm_details_verbose" name="sm_details_verbose" <?php echo ($options['sm_details_verbose']==true?"checked=\"checked\"":"") ?> />
752
  Keep detailed information about recent searches (taken from HTTP headers)
@@ -754,7 +841,7 @@ function tguy_sm_options_page() {
754
  </th>
755
  </tr>
756
  <tr>
757
- <th class="th-full" scope="row">
758
  <label for="sm_disable_donation">
759
  <input type="checkbox" id="sm_disable_donation" name="sm_disable_donation" <?php echo ($options['sm_disable_donation']==true?"checked=\"checked\"":"") ?> />
760
  Hide the &#8220;Do you find this plugin useful?&#8221; box
3
  Plugin Name: Search Meter
4
  Plugin URI: http://www.thunderguy.com/semicolon/wordpress/search-meter-wordpress-plugin/
5
  Description: Keeps track of what your visitors are searching for. After you have activated this plugin, you can check the Search Meter section in the Dashboard to see what your visitors are searching for on your blog.
6
+ Version: 2.7
7
  Author: Bennett McElwee
8
  Author URI: http://www.thunderguy.com/semicolon/
9
 
10
+ $Revision: 244424 $
11
 
12
 
13
  INSTRUCTIONS
29
  Thanks to Kaufman (http://www.terrik.com/wordpress/) and the many others who have offered suggestions.
30
 
31
 
32
+ Copyright (C) 2005-10 Bennett McElwee (bennett at thunderguy dotcom)
33
 
34
  This program is free software; you can redistribute it and/or
35
  modify it under the terms of version 2 of the GNU General Public
66
  // in the details). This will mess up the stats, but could be useful
67
  // for troubleshooting.
68
 
69
+ define('TGUY_SM_DEFAULT_VIEW_STATS_CAPABILITY', 'publish_posts');
70
+ // Default capability users must have in order to see stats.
71
 
72
+ define('TGUY_SM_OPTIONS_CAPABILITY', 'manage_options');
73
+ // Capability users must have in order to set options.
74
 
75
 
76
  // Template Tags
78
 
79
  function sm_list_popular_searches($before = '', $after = '', $count = 5) {
80
  // List the most popular searches in the last month in decreasing order of popularity.
81
+ global $wpdb, $table_prefix, $wp_rewrite;
82
  $count = intval($count);
83
+ $escaped_filter_regex = sm_get_escaped_filter_regex();
84
+ $filter_term = ($escaped_filter_regex == "" ? "" : "AND NOT `terms` REGEXP '{$escaped_filter_regex}'");
85
  // This is a simpler query than the report query, and may produce
86
  // slightly different results. This query returns searches if they
87
  // have ever had any hits, even if the last search yielded no hits.
88
  // This makes for a more efficient search -- important if this
89
  // function will be used in a sidebar.
90
  $results = $wpdb->get_results(
91
+ "SELECT `terms`, SUM(`count`) AS countsum
 
92
  FROM `{$table_prefix}searchmeter`
93
  WHERE DATE_SUB( CURDATE( ) , INTERVAL 30 DAY ) <= `date`
94
  AND 0 < `last_hits`
95
+ {$filter_term}
96
  GROUP BY `terms`
97
  ORDER BY countsum DESC, `terms` ASC
98
  LIMIT $count");
99
  if (count($results)) {
100
  echo "$before\n<ul>\n";
101
+ $home_url_slash = get_settings('home') . '/';
102
  foreach ($results as $result) {
103
+ echo '<li><a href="'. $home_url_slash . sm_get_relative_search_url($result->terms) . '">'. htmlspecialchars($result->terms) .'</a></li>'."\n";
104
  }
105
  echo "</ul>\n$after\n";
106
  }
107
  }
108
 
109
  function sm_list_recent_searches($before = '', $after = '', $count = 5) {
110
+ // List the most recent successful searches, ignoring duplicates
111
  global $wpdb, $table_prefix;
112
  $count = intval($count);
113
+ $escaped_filter_regex = sm_get_escaped_filter_regex();
114
+ $filter_term = ($escaped_filter_regex == "" ? "" : "AND NOT `terms` REGEXP '{$escaped_filter_regex}'");
115
  $results = $wpdb->get_results(
116
+ "SELECT `terms`, MAX(`datetime`) `maxdatetime`
117
  FROM `{$table_prefix}searchmeter_recent`
118
  WHERE 0 < `hits`
119
+ {$filter_term}
120
+ GROUP BY `terms`
121
+ ORDER BY `maxdatetime` DESC
122
  LIMIT $count");
123
  if (count($results)) {
124
  echo "$before\n<ul>\n";
125
+ $home_url_slash = get_settings('home') . '/';
126
  foreach ($results as $result) {
127
+ echo '<li><a href="'. $home_url_slash . sm_get_relative_search_url($result->terms) . '">'. htmlspecialchars($result->terms) .'</a></li>'."\n";
128
  }
129
  echo "</ul>\n$after\n";
130
  }
131
  }
132
 
133
+ function sm_get_relative_search_url($term) {
134
+ // Return the URL for a search term, relative to the home directory.
135
+ global $wp_rewrite;
136
+ $relative_url = null;
137
+ if ($wp_rewrite->using_permalinks()) {
138
+ $structure = $wp_rewrite->get_search_permastruct();
139
+ if (strpos($structure, '%search%') !== false) {
140
+ $relative_url = str_replace('%search%', urlencode($term), $structure);
141
+ }
142
+ }
143
+ if ( ! $relative_url) {
144
+ $relative_url = '?s=' . urlencode($term);
145
+ }
146
+ return $relative_url;
147
+ }
148
+
149
+
150
+ function sm_get_escaped_filter_regex() {
151
+ // Return a regular expression, escaped to go into a DB query, that will match any terms to be filtered out
152
+ global $sm_escaped_filter_regex, $wpdb;
153
+ if ( ! isset($sm_escaped_filter_regex)) {
154
+ $options = get_option('tguy_search_meter');
155
+ $filter_words = $options['sm_filter_words'];
156
+ if ($filter_words == "") {
157
+ $sm_escaped_filter_regex = "";
158
+ } else {
159
+ $filter_regex = str_replace(' ', '|', preg_quote($filter_words));
160
+ $wpdb->escape_by_ref($filter_regex);
161
+ $sm_escaped_filter_regex = $filter_regex;
162
+ }
163
+ }
164
+ return $sm_escaped_filter_regex;
165
+ }
166
+ $sm_escaped_filter_regex = null;
167
 
168
  // Hooks
169
 
468
  }
469
 
470
  function tguy_sm_add_admin_pages() {
471
+ $options = get_option('tguy_search_meter');
472
+ $view_stats_capability = $options['sm_view_stats_capability'];
473
+ if ($view_stats_capability == '') {
474
+ $view_stats_capability = TGUY_SM_DEFAULT_VIEW_STATS_CAPABILITY;
475
+ }
476
+ add_submenu_page('index.php', 'Search Meter Statistics', 'Search Meter', $view_stats_capability, __FILE__, 'tguy_sm_stats_page');
477
+ add_options_page('Search Meter', 'Search Meter', TGUY_SM_OPTIONS_CAPABILITY, __FILE__, 'tguy_sm_options_page');
478
  }
479
 
480
 
602
 
603
  <h2>Notes</h2>
604
 
605
+ <?php if (current_user_can(TGUY_SM_OPTIONS_CAPABILITY)) : ?>
606
  <p>To manage your search statistics, go to the <strong>Settings</strong> section and choose <strong>Search Meter</strong>.</p>
607
  <?php endif; ?>
608
 
747
 
748
  <h2>Notes</h2>
749
 
750
+ <?php if (current_user_can(TGUY_SM_OPTIONS_CAPABILITY)) : ?>
751
  <p>To manage your search statistics, go to the <strong>Settings</strong> section and choose <strong>Search Meter</strong>.</p>
752
  <?php endif; ?>
753
 
767
  if (isset($_POST['submitted'])) {
768
  check_admin_referer('search-meter-update-options_all');
769
  $options = get_option('tguy_search_meter');
770
+ $options['sm_view_stats_capability'] = ($_POST['sm_view_stats_capability']);
771
+ $sm_filter_words = $_POST['sm_filter_words'];
772
+ if (get_magic_quotes_gpc()) {
773
+ $sm_filter_words = stripslashes($sm_filter_words);
774
+ }
775
+ $options['sm_filter_words'] = preg_replace('/\\s+/', ' ', trim($sm_filter_words));
776
  $options['sm_details_verbose'] = (bool)($_POST['sm_details_verbose']);
777
  $options['sm_disable_donation'] = (bool)($_POST['sm_disable_donation']);
778
  update_option('tguy_search_meter', $options);
783
  echo '<div id="message" class="updated fade"><p><strong>Statistics have been reset.</strong></p></div>';
784
  }
785
  $options = get_option('tguy_search_meter');
786
+ $view_stats_capability = $options['sm_view_stats_capability'];
787
+ if ($view_stats_capability == '') {
788
+ $view_stats_capability = TGUY_SM_DEFAULT_VIEW_STATS_CAPABILITY;
789
+ }
790
  ?>
791
  <div class="wrap">
792
 
803
 
804
  <table class="form-table">
805
  <tr>
806
+ <th scope="row">Show statistics to</th>
807
+ <td>
808
+ <fieldset>
809
+ <label title='Users with "read" capability'>
810
+ <input type="radio" name="sm_view_stats_capability" value="read"
811
+ <?php echo ($view_stats_capability=='read'?"checked=\"checked\"":"") ?> />
812
+ All logged-in users</label><br>
813
+ <label title='Users with "publish_posts" capability'>
814
+ <input type="radio" name="sm_view_stats_capability" value="publish_posts"
815
+ <?php echo ($view_stats_capability=='publish_posts'?"checked=\"checked\"":"") ?> />
816
+ Post authors and administrators</label><br>
817
+ <label title='Users with "manage_options" capability'>
818
+ <input type="radio" name="sm_view_stats_capability" value="activate_plugins"
819
+ <?php echo ($view_stats_capability=='manage_options'?"checked=\"checked\"":"") ?> />
820
+ Administrators only</label>
821
+ </fieldset>
822
+ </td>
823
+ </tr>
824
+ <tr valign="top">
825
+ <th scope="row">Search filter</th>
826
+ <td>
827
+ <fieldset>
828
+ <label for="sm_filter_words">When a search term contains any of these words, it will be filtered
829
+ and will not show up in the Recent Searches or Popular Searches widgets. This will match inside words,
830
+ so &#8220;press&#8221; will match &#8220;WordPress&#8221;.</label>
831
+ <textarea name="sm_filter_words" rows="3" cols="40" id="sm_filter_words" class="large-text code"><?php echo esc_html($options['sm_filter_words']); ?></textarea>
832
+ </fieldset>
833
+ </td>
834
+ </tr>
835
+ <tr>
836
+ <th class="th-full" scope="row" colspan="2">
837
  <label for="sm_details_verbose">
838
  <input type="checkbox" id="sm_details_verbose" name="sm_details_verbose" <?php echo ($options['sm_details_verbose']==true?"checked=\"checked\"":"") ?> />
839
  Keep detailed information about recent searches (taken from HTTP headers)
841
  </th>
842
  </tr>
843
  <tr>
844
+ <th class="th-full" scope="row" colspan="2">
845
  <label for="sm_disable_donation">
846
  <input type="checkbox" id="sm_disable_donation" name="sm_disable_donation" <?php echo ($options['sm_disable_donation']==true?"checked=\"checked\"":"") ?> />
847
  Hide the &#8220;Do you find this plugin useful?&#8221; box