Search & Filter - Version 1.2.0

Version Description

  • WARNING - this update includes some major changes to shortcode construction, do not upgrade until you have read how this will affect your setup - updating should be easy.
  • Renamed the taxonomies argument to fields - taxonomies is now no longer appropriate as this list contains field types other than taxonomies - this list now contains taxonomies, post_type, post_date and search - taxonomies as an argument is still supported however will be deprecated
  • Search box can now be positioned anywhere, simply include search in the fields list in the position desired. Upgrading from previous versions will cause you to lose your search box, simply include search in the fields list to show it again
  • Drop support for search argument as no longer relevant - control display of search input by adding it to the fields list
  • Labels have been completely rewritten - label has been renamed to headings to avoid confusion with internal taxonomy labels - the headings argument now allows for any text to be added and displayed as a heading for each field - this allows for much more flexibility and no longer uses internal taxonomy labels - to hide a label simply leave blank
  • Added support for hierarchical taxonomies for all input types - checkbox, radio & select
  • Added support for ordering of taxonomies - use order_by argument - allowed values are id, name, slug, count, term_group
  • Added support for ordering direction of taxonomies - use order_dir argument - allowed values are 'asc' or 'desc'
  • Added support to show or hide empty taxonomies - use hide_empty argument
  • Added support for search_placeholder
  • Updated post_date functionality to work with older versions of WP - can be displayed either as date or daterange - the post_date field uses the HTML 5 input type of date - browsers that do not support it will simply show a text box - a tutorial of integrating jquery for graceful degredation is in the works
  • Renamed submitlabel to submit_label - submitlabel still works for now.
  • Renamed type to types - type still works for now.
  • Updated display of checkboxes and radio buttons, inputs are now wrapped in an unordered list which may affect your styling
  • Various bug fixes
  • Thanks to bradaric for help with hierarchical dropdown lists and date input types - https://github.com/bradaric
Download this release

Release Info

Developer DesignsAndCode
Plugin Icon 128x128 Search & Filter
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.1.2 to 1.2.0

Files changed (6) hide show
  1. admin/style.css +2 -2
  2. of-admin.php +4 -4
  3. of-list-table.php +117 -84
  4. readme.txt +29 -20
  5. search-filter.php +873 -376
  6. style.css +5 -0
admin/style.css CHANGED
@@ -42,12 +42,12 @@ pre code
42
 
43
  .column-info
44
  {
45
- width:65%;
46
  }
47
 
48
  .column-options
49
  {
50
- width:15%;
51
  }
52
 
53
  pre .keyword
42
 
43
  .column-info
44
  {
45
+ width:40%;
46
  }
47
 
48
  .column-options
49
  {
50
+ width:40%;
51
  }
52
 
53
  pre .keyword
of-admin.php CHANGED
@@ -51,10 +51,10 @@
51
  </div>';
52
  echo "<h3>Documentation</h3>";
53
  echo '<div class="of-caption">
54
- Advanced documentation and examples has now moved - <a href="http://docs.designsandcode.com/search-filter/" target="_blank">find it on our official Search &amp; Filter Plugin Documentation page</a>.<br /><br />
55
- Please find below documentation to get you started, more examples can be found at the above link.
56
  </div>';
57
-
58
  echo "<h3>How To Use</h3>";
59
  echo '<div class="of-caption">
60
  To display Search &amp; Filter all you need to do is a use a shortcode:<br />
@@ -70,7 +70,7 @@
70
 
71
 
72
  echo "<h3>Arguments</h3>";
73
-
74
  //display table
75
  $ofVarListTable = new OF_Variable_List_Table();
76
  $ofVarListTable->prepare_items();
51
  </div>';
52
  echo "<h3>Documentation</h3>";
53
  echo '<div class="of-caption">
54
+ Advanced documentation and examples has now moved - find it on our <a href="http://docs.designsandcode.com/search-filter/" target="_blank">Search &amp; Filter Plugin Documentation</a>.<br /><br />
55
+ Please find below limited documentation to get you started.
56
  </div>';
57
+
58
  echo "<h3>How To Use</h3>";
59
  echo '<div class="of-caption">
60
  To display Search &amp; Filter all you need to do is a use a shortcode:<br />
70
 
71
 
72
  echo "<h3>Arguments</h3>";
73
+ echo '<div class="of-caption">Examples for most of the arguments below can be found over on the <a href="http://docs.designsandcode.com/search-filter/#examples" target="_blank">Search &amp; Filter Plugin Documentation</a>.</div>';
74
  //display table
75
  $ofVarListTable = new OF_Variable_List_Table();
76
  $ofVarListTable->prepare_items();
of-list-table.php CHANGED
@@ -10,7 +10,7 @@ if(!class_exists('WP_List_Table')){
10
  class OF_Taxonomy_List_Table extends WP_List_Table {
11
 
12
  private $taxonomy_data = array();
13
-
14
  function __construct()
15
  {
16
  global $status, $page;
@@ -19,16 +19,16 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
19
  'plural' => 'wp_list_of_taxonomies', //plural label, also this well be one of the table css class
20
  'ajax' => false //We won't support Ajax for this table
21
  ));
22
-
23
  $args = array(
24
  'public' => true,
25
- );
26
  $output = 'object'; // or objects
27
  $operator = 'and'; // 'and' or 'or'
28
- $taxonomies = get_taxonomies( $args, $output, $operator );
29
-
30
  //var_dump($taxonomies['post_tag']['labels']['all_items']); - all items should be used in the drop downs
31
-
32
  $counter = 0;
33
  if ( $taxonomies )
34
  {
@@ -40,12 +40,12 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
40
  "label" => $taxonomy->labels->name,
41
  "posttypes" => implode(', ', $taxonomy->object_type)
42
  );
43
-
44
  $this->taxonomy_data[] = $ttaxonomydata;
45
  }
46
  }
47
  }
48
-
49
  function get_columns(){
50
  $columns = array(
51
  'name' => 'Name',
@@ -54,7 +54,7 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
54
  );
55
  return $columns;
56
  }
57
-
58
  function prepare_items() {
59
  $columns = $this->get_columns();
60
  $hidden = array();
@@ -62,10 +62,10 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
62
  $this->_column_headers = array($columns, $hidden, $sortable);
63
  $this->items = $this->taxonomy_data;
64
  }
65
-
66
  function column_default( $item, $column_name ) {
67
  switch( $column_name )
68
- {
69
  case 'name':
70
  case 'label':
71
  case 'posttypes':
@@ -74,8 +74,8 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
74
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
75
  }
76
  }
77
-
78
-
79
  function get_sortable_columns()
80
  {
81
  $sortable_columns = array(
@@ -87,7 +87,7 @@ class OF_Taxonomy_List_Table extends WP_List_Table {
87
  class OF_Post_Type_Table extends WP_List_Table {
88
 
89
  private $post_types = array();
90
-
91
  function __construct()
92
  {
93
  global $status, $page;
@@ -96,19 +96,19 @@ class OF_Post_Type_Table extends WP_List_Table {
96
  'plural' => 'wp_list_of_post_types', //plural label, also this well be one of the table css class
97
  'ajax' => false //We won't support Ajax for this table
98
  ));
99
-
100
  $args = array('public' => true);
101
  $output = 'object'; // names or objects, note names is the default
102
  $operator = 'and'; // 'and' or 'or'
103
-
104
- $post_types_objs = get_post_types( $args, $output, $operator );
105
-
106
-
107
-
108
  if($post_types_objs)
109
  {
110
  $counter = 0;
111
-
112
  foreach ( $post_types_objs as $post_type )
113
  {
114
  if($post_type->name!="attachment")
@@ -120,12 +120,12 @@ class OF_Post_Type_Table extends WP_List_Table {
120
  );
121
 
122
  $this->post_types[] = $tempobject;
123
-
124
  }
125
  }
126
  }
127
  }
128
-
129
  function get_columns(){
130
  $columns = array(
131
  'name' => 'Name',
@@ -133,7 +133,7 @@ class OF_Post_Type_Table extends WP_List_Table {
133
  );
134
  return $columns;
135
  }
136
-
137
  function prepare_items() {
138
  $columns = $this->get_columns();
139
  $hidden = array();
@@ -141,10 +141,10 @@ class OF_Post_Type_Table extends WP_List_Table {
141
  $this->_column_headers = array($columns, $hidden, $sortable);
142
  $this->items = $this->post_types;
143
  }
144
-
145
  function column_default( $item, $column_name ) {
146
  switch( $column_name )
147
- {
148
  case 'name':
149
  case 'label':
150
  return $item[ $column_name ];
@@ -152,8 +152,8 @@ class OF_Post_Type_Table extends WP_List_Table {
152
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
153
  }
154
  }
155
-
156
-
157
  function get_sortable_columns()
158
  {
159
  $sortable_columns = array(
@@ -167,7 +167,7 @@ class OF_Post_Type_Table extends WP_List_Table {
167
  class OF_Variable_List_Table extends WP_List_Table {
168
 
169
  private $taxonomy_data = array();
170
-
171
  function __construct()
172
  {
173
  parent::__construct(array(
@@ -175,79 +175,103 @@ class OF_Variable_List_Table extends WP_List_Table {
175
  'plural' => 'wp_list_of_variables', //plural label, also this well be one of the table css class
176
  'ajax' => false //We won't support Ajax for this table
177
  ));
178
-
179
  //var_dump($taxonomies['post_tag']['labels']['all_items']); - all items should be used in the drop downs
180
  $counter = 0;
181
  $args = array(
182
  'public' => true,
183
- );
184
  $output = 'names'; // or objects
185
- $taxonomies = get_taxonomies( $args, $output );
186
  $fulltaxonomylist = implode(",",$taxonomies);
187
-
188
  $this->taxonomy_data[] = array(
189
  "ID" => $counter,
190
- "name" => "taxonomies",
191
  "defaultval" => "&nbsp;",
192
- "options" => "<em>Comma seperated list of any taxonomy names found in the Public Taxonomies table below.</em><br /><br /><strong>Update:</strong> You can now also add <code class='string'>post_type</code> to this list to display options for post types.",
193
- "info" => "Example using all your public taxonomies (copy &amp; paste!):<pre><code class='string'>[searchandfilter taxonomies=\"".$fulltaxonomylist."\"]</code></pre>"
194
  );
195
  $counter++;
196
-
197
-
198
  $this->taxonomy_data[] = array(
199
  "ID" => $counter,
200
- "name" => "type",
201
  "defaultval" => "<code class='string large'>select</code>",
202
- "options" => "<em>Comma seperated list of any of the types found below:</em><br /><br /><code class='string large'>select</code><br /><code class='string large'>checkbox</code><br /><code class='string large'>radio</code>",
203
- "info" => "The order of values in this comma seperated list needs to match the taxonomies list. <br /><br />To display categories, tags and post formats, as a `select` dropdown, radio buttons and checkboxes, we must put them in the order we need:
204
- <br /><pre><code class='string'>[searchandfilter taxonomies=\"category,post_tag,post_format\" type=\"select,checkbox,radio\"]</code></pre>
205
- If any taxonomies are left unspecified they well default to `select` dropdowns:
206
- <br /><pre><code class='string'>[searchandfilter taxonomies=\"category,post_tag,post_format\" type=\"select,checkbox\"]</code></pre>
207
- With this example using just \"select,checkbox\", the post format (being the third, not provided parameter) will be displayed as a `select` dropdown.<br /><br />
208
-
209
- If the `type` argument is ommited completely all taxonomies will be displayed as `select` dropdowns."
210
  );
211
  $counter++;
212
-
213
  $this->taxonomy_data[] = array(
214
  "ID" => $counter,
215
- "name" => "label",
216
- "defaultval" => "<code class='string large'>name</code>",
217
- "options" => "<code class='string large'>0</code> - hide all labels<br /><br /> or <br /><br /><em>Comma seperated list of any of the types found below:</em><br /><br /><code class='string large'>name</code><br /><code class='string large'>singular_name</code><br /><code class='string large'>search_items</code><br /><code class='string large'>all_items</code><br /><em><code class='string large'>*blank value</code></em>",
218
- "info" => "This list works the same as the `type` example above.<br /><br />
219
- The different values that can be used are taken directly from the labels within a taxonomy object - so make sure you set these in your taxonomies if you wish to use them below.
220
- <br /><br />Examples:<br /><br />
221
- <strong>Hide all labels:</strong>
222
- <pre><code class='string'>[searchandfilter taxonomies=\"category,post_tag,post_format\" label=\"0\"]</code></pre>
223
- <strong>Mixture of different label types:</strong>
224
- <pre><code class='string'>[searchandfilter taxonomies=\"category,post_tag,post_format\" label=\"singular_name,search_items,all_items\"]</code></pre>
225
- <strong>Hiding the label for category and tag, and set `name` for the post format:</strong>
226
- <pre><code class='string'>[searchandfilter taxonomies=\"category,post_tag,post_format\" label=\",,name\"]</code></pre>
227
- *In this last example, a blank value (ie, comma's with no data in between) tells Search &amp; Filter to hide the label for the particular taxonomy.<br /><br />
228
- If the `label` argument is ommited completely all labels will be shown by default and will be set to use the `name` label for a taxonomy.
229
- "
230
  );
231
  $counter++;
232
 
233
  $this->taxonomy_data[] = array(
234
  "ID" => $counter,
235
- "name" => "post_types",
236
- "defaultval" => "&nbsp;",
237
- "options" => "<em>Comma seperated list of any post types (names) in the Public Post Types table below.</em><br /><br /> or set to: <br /><br /><code class='string large'>all</code>",
238
- "info" => "List all post types you want the widget to search. Leave blank for default behavious without any post type restrictions. This will use the default setting for post types you have in place which is often just <code>post</code> and <code>page</code><br /><br />
239
-
240
- All searches will be constrained to the post types you add here.<br /><br />
241
- If <code>post_type</code> has been added to <code>taxonomies</code> list above, then it will pull its data from this list, a user will be able to choose from all post types listed here."
242
  );
243
  $counter++;
244
 
 
245
  $this->taxonomy_data[] = array(
246
  "ID" => $counter,
247
- "name" => "search",
248
  "defaultval" => "<code class='string large'>1</code>",
249
- "options" => "<code class='string large'>0</code> - hide the search box<br /><code class='string large'>1</code> - display search box",
250
- "info" => "The search box is shown by default, ommit from shortcode unless you specifically want to hide it - then set it with a value of 0."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  );
252
  $counter++;
253
 
@@ -259,19 +283,28 @@ class OF_Variable_List_Table extends WP_List_Table {
259
  "info" => "Enter a class name here, or class names seperated by spaces to have them added to Search &amp; Filter form. This allows individual styling of each Search &amp; Filter instance.<br /><br />Ommit to ignore."
260
  );
261
  $counter++;
262
-
263
-
264
  $this->taxonomy_data[] = array(
265
  "ID" => $counter,
266
- "name" => "submitlabel",
267
- "defaultval" => "<code class='string large'>Submit",
268
  "options" => "<em>Any string</em>",
269
  "info" => "This is the text label on the submit button."
270
  );
271
  $counter++;
272
-
 
 
 
 
 
 
 
 
 
273
  }
274
-
275
  function get_columns(){
276
  $columns = array(
277
  'name' => 'Name',
@@ -281,7 +314,7 @@ class OF_Variable_List_Table extends WP_List_Table {
281
  );
282
  return $columns;
283
  }
284
-
285
  function prepare_items() {
286
  $columns = $this->get_columns();
287
  $hidden = array();
@@ -292,7 +325,7 @@ class OF_Variable_List_Table extends WP_List_Table {
292
  function column_default( $item, $column_name )
293
  {
294
  switch( $column_name )
295
- {
296
  case 'name':
297
  case 'defaultval':
298
  case 'options':
@@ -302,9 +335,9 @@ class OF_Variable_List_Table extends WP_List_Table {
302
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
303
  }
304
  }
305
-
306
-
307
-
308
  }
309
 
310
 
10
  class OF_Taxonomy_List_Table extends WP_List_Table {
11
 
12
  private $taxonomy_data = array();
13
+
14
  function __construct()
15
  {
16
  global $status, $page;
19
  'plural' => 'wp_list_of_taxonomies', //plural label, also this well be one of the table css class
20
  'ajax' => false //We won't support Ajax for this table
21
  ));
22
+
23
  $args = array(
24
  'public' => true,
25
+ );
26
  $output = 'object'; // or objects
27
  $operator = 'and'; // 'and' or 'or'
28
+ $taxonomies = get_taxonomies( $args, $output, $operator );
29
+
30
  //var_dump($taxonomies['post_tag']['labels']['all_items']); - all items should be used in the drop downs
31
+
32
  $counter = 0;
33
  if ( $taxonomies )
34
  {
40
  "label" => $taxonomy->labels->name,
41
  "posttypes" => implode(', ', $taxonomy->object_type)
42
  );
43
+
44
  $this->taxonomy_data[] = $ttaxonomydata;
45
  }
46
  }
47
  }
48
+
49
  function get_columns(){
50
  $columns = array(
51
  'name' => 'Name',
54
  );
55
  return $columns;
56
  }
57
+
58
  function prepare_items() {
59
  $columns = $this->get_columns();
60
  $hidden = array();
62
  $this->_column_headers = array($columns, $hidden, $sortable);
63
  $this->items = $this->taxonomy_data;
64
  }
65
+
66
  function column_default( $item, $column_name ) {
67
  switch( $column_name )
68
+ {
69
  case 'name':
70
  case 'label':
71
  case 'posttypes':
74
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
75
  }
76
  }
77
+
78
+
79
  function get_sortable_columns()
80
  {
81
  $sortable_columns = array(
87
  class OF_Post_Type_Table extends WP_List_Table {
88
 
89
  private $post_types = array();
90
+
91
  function __construct()
92
  {
93
  global $status, $page;
96
  'plural' => 'wp_list_of_post_types', //plural label, also this well be one of the table css class
97
  'ajax' => false //We won't support Ajax for this table
98
  ));
99
+
100
  $args = array('public' => true);
101
  $output = 'object'; // names or objects, note names is the default
102
  $operator = 'and'; // 'and' or 'or'
103
+
104
+ $post_types_objs = get_post_types( $args, $output, $operator );
105
+
106
+
107
+
108
  if($post_types_objs)
109
  {
110
  $counter = 0;
111
+
112
  foreach ( $post_types_objs as $post_type )
113
  {
114
  if($post_type->name!="attachment")
120
  );
121
 
122
  $this->post_types[] = $tempobject;
123
+
124
  }
125
  }
126
  }
127
  }
128
+
129
  function get_columns(){
130
  $columns = array(
131
  'name' => 'Name',
133
  );
134
  return $columns;
135
  }
136
+
137
  function prepare_items() {
138
  $columns = $this->get_columns();
139
  $hidden = array();
141
  $this->_column_headers = array($columns, $hidden, $sortable);
142
  $this->items = $this->post_types;
143
  }
144
+
145
  function column_default( $item, $column_name ) {
146
  switch( $column_name )
147
+ {
148
  case 'name':
149
  case 'label':
150
  return $item[ $column_name ];
152
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
153
  }
154
  }
155
+
156
+
157
  function get_sortable_columns()
158
  {
159
  $sortable_columns = array(
167
  class OF_Variable_List_Table extends WP_List_Table {
168
 
169
  private $taxonomy_data = array();
170
+
171
  function __construct()
172
  {
173
  parent::__construct(array(
175
  'plural' => 'wp_list_of_variables', //plural label, also this well be one of the table css class
176
  'ajax' => false //We won't support Ajax for this table
177
  ));
178
+
179
  //var_dump($taxonomies['post_tag']['labels']['all_items']); - all items should be used in the drop downs
180
  $counter = 0;
181
  $args = array(
182
  'public' => true,
183
+ );
184
  $output = 'names'; // or objects
185
+ $taxonomies = get_taxonomies( $args, $output );
186
  $fulltaxonomylist = implode(",",$taxonomies);
187
+
188
  $this->taxonomy_data[] = array(
189
  "ID" => $counter,
190
+ "name" => "fields",
191
  "defaultval" => "&nbsp;",
192
+ "options" => "<em>Comma seperated list of any field names and Public Taxonomies:</em><br /><br />search<br />post_date<br />post_types<br /><em>*public taxonomy names</em>",
193
+ "info" => "Example using all your public taxonomies (copy &amp; paste!):<pre><code class='string'>[searchandfilter taxonomies=\"search,".$fulltaxonomylist."\"]</code></pre>"
194
  );
195
  $counter++;
196
+
197
+
198
  $this->taxonomy_data[] = array(
199
  "ID" => $counter,
200
+ "name" => "types",
201
  "defaultval" => "<code class='string large'>select</code>",
202
+ "options" => "<em>Comma seperated list of any of the types found below:</em><br /><br />select<br />checkbox<br />radio<br /><br />
203
+ <em>These types should only be used when the field is `post_date`:</em><br /><br />date<br />daterange",
204
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
 
 
 
 
 
205
  );
206
  $counter++;
207
+
208
  $this->taxonomy_data[] = array(
209
  "ID" => $counter,
210
+ "name" => "headings",
211
+ "defaultval" => "&nbsp;",
212
+ "options" => "<em>Comma seperated list containing any string value. Blank values are ommited completely and the heading will not display.</em>",
213
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
 
 
 
 
 
 
 
 
 
 
 
214
  );
215
  $counter++;
216
 
217
  $this->taxonomy_data[] = array(
218
  "ID" => $counter,
219
+ "name" => "hierarchical",
220
+ "defaultval" => "<code class='string large'>0</code>",
221
+ "options" => "<em>Comma seperated list.</em><br /><br />
222
+ 1 - display as hierarchical<br />
223
+ <em>*Any other value is ignored</em>",
224
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
 
225
  );
226
  $counter++;
227
 
228
+
229
  $this->taxonomy_data[] = array(
230
  "ID" => $counter,
231
+ "name" => "hide_empty",
232
  "defaultval" => "<code class='string large'>1</code>",
233
+ "options" => "<em>Comma seperated list.</em><br /><br />
234
+ 0 - Shows empty taxonomies<br />
235
+ 1 - Hides empty taxonomies<br />
236
+ <em>*Any other value is ignored</em>",
237
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
238
+ );
239
+ $counter++;
240
+
241
+ $this->taxonomy_data[] = array(
242
+ "ID" => $counter,
243
+ "name" => "order_by",
244
+ "defaultval" => "<code class='string large'>name</code>",
245
+ "options" => "<em>Comma seperated list of the following possible values:</em><br /><br />
246
+ ID<br />
247
+ name<br />
248
+ slug<br />
249
+ count<br />
250
+ term_group<br /><br />
251
+
252
+ <em>This uses the values of \"orderby\" as <a href=\"http://codex.wordpress.org/Template_Tags/wp_list_categories\" target=\"_blank\">defined on the WordPress site</a></em>.",
253
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
254
+ );
255
+ $counter++;
256
+
257
+ $this->taxonomy_data[] = array(
258
+ "ID" => $counter,
259
+ "name" => "order_dir",
260
+ "defaultval" => "<code class='string large'>ASC</code>",
261
+ "options" => "<em>Comma seperated list containing:</em><br /><br />
262
+ ASC - ascending<br />
263
+ DESC - descending<br /><br />
264
+ <em>This sets the order of taxonomies terms for a given taxonomy and can be used in conjunction with `order_by`.</em>",
265
+ "info" => "The order of values in this comma seperated list needs to match the fields list."
266
+ );
267
+ $counter++;
268
+
269
+ $this->taxonomy_data[] = array(
270
+ "ID" => $counter,
271
+ "name" => "post_types",
272
+ "defaultval" => "&nbsp;",
273
+ "options" => "<em>Comma seperated list of any post types (names) in the Public Post Types table below.</em><br /><br /> or set to: <br /><br /><code class='string large'>all</code>",
274
+ "info" => "This can be used with or without `post_type` appearing in the field list.<br /><br />When `post_type` appears in the field list, the post types listed here will be selectable in the `post_type` field.<br /><br />When `post_type` does not appear in the field list, then all searches are retricted to the post types here."
275
  );
276
  $counter++;
277
 
283
  "info" => "Enter a class name here, or class names seperated by spaces to have them added to Search &amp; Filter form. This allows individual styling of each Search &amp; Filter instance.<br /><br />Ommit to ignore."
284
  );
285
  $counter++;
286
+
287
+
288
  $this->taxonomy_data[] = array(
289
  "ID" => $counter,
290
+ "name" => "submit_label",
291
+ "defaultval" => "<code class='string large'>Submit</code>",
292
  "options" => "<em>Any string</em>",
293
  "info" => "This is the text label on the submit button."
294
  );
295
  $counter++;
296
+
297
+ $this->taxonomy_data[] = array(
298
+ "ID" => $counter,
299
+ "name" => "search_placeholder",
300
+ "defaultval" => "<code class='string large'>Search &hellip;</code>",
301
+ "options" => "<em>Any string</em>",
302
+ "info" => "This is the placeholder text that appears when no search term has been entered in the search field."
303
+ );
304
+ $counter++;
305
+
306
  }
307
+
308
  function get_columns(){
309
  $columns = array(
310
  'name' => 'Name',
314
  );
315
  return $columns;
316
  }
317
+
318
  function prepare_items() {
319
  $columns = $this->get_columns();
320
  $hidden = array();
325
  function column_default( $item, $column_name )
326
  {
327
  switch( $column_name )
328
+ {
329
  case 'name':
330
  case 'defaultval':
331
  case 'options':
335
  return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes
336
  }
337
  }
338
+
339
+
340
+
341
  }
342
 
343
 
readme.txt CHANGED
@@ -1,14 +1,14 @@
1
  === Search & Filter ===
2
  Contributors: DesignsAndCode
3
- Donate link:
4
- Tags: category, filter, taxonomy, search, wordpress, post type
5
  Requires at least: 3.5
6
- Tested up to: 3.6
7
- Stable tag: 1.1.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Search and Filtering for Custom Posts, Categories, Tags and Taxonomies
12
 
13
  == Installation ==
14
 
@@ -21,21 +21,9 @@ For basic usage, you can also have a look at the [plugin homepage](http://www.de
21
 
22
  == Frequently Asked Questions ==
23
 
24
- = Some text/headings/labels for my different Taxonomies seem to be broken or don't appear correctly =
25
-
26
- Search & Filter uses the Taxonomy object and its label properly, this means when registering custom taxonomies make sure you fill out valid values for the following labels:
27
-
28
- * name
29
- * singular_name
30
- * search_items
31
- * all_items
32
-
33
- If you have used a plugin to register a custom taxonomy this info can normally be found under advanced settings.
34
-
35
- = When using the checkboxes for Post Types =
36
-
37
- Search & Filter uses the Taxonomy object and its label properly, this means when registering custom taxonomies make sure you fill out valid values for the following labels:
38
 
 
39
 
40
  == Screenshots ==
41
 
@@ -46,6 +34,27 @@ Search & Filter uses the Taxonomy object and its label properly, this means when
46
 
47
  == Changelog ==
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  = 1.1.2 =
50
  * Added support for all public and custom post types (the `attachment` post type is excluded) - all post types can be user searchable or predfined and hidden from the user. This allows for users to add multiple search widgets to their site which work on specific post types independantly from eachother.
51
  * Added offical updated documentation, created and moved to [Search & Filter Docs](http://docs.designsandcode.com/search-filter/)
@@ -75,7 +84,7 @@ Search & Filter uses the Taxonomy object and its label properly, this means when
75
 
76
  == Upgrade Notice ==
77
 
78
- Upgrade should be fully compatible with previous versions. A previous update however automatically added headings to dropdowns, refer to usage and examples on how to disable them if this is not the required behaviour.
79
 
80
  == Description ==
81
 
1
  === Search & Filter ===
2
  Contributors: DesignsAndCode
3
+ Donate link:
4
+ Tags: category, filter, taxonomy, search, wordpress, post type, post date
5
  Requires at least: 3.5
6
+ Tested up to: 3.8
7
+ Stable tag: 1.2.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Search and Filtering for Custom Posts, Categories, Tags, Taxonomies, Post Dates and Post Types
12
 
13
  == Installation ==
14
 
21
 
22
  == Frequently Asked Questions ==
23
 
24
+ = How can I xxxxx ? =
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ The documentation has been updated to include examples almost all configurable options with screenshots - please refer to the [Search & Filter Docs](http://docs.designsandcode.com/search-filter/).
27
 
28
  == Screenshots ==
29
 
34
 
35
  == Changelog ==
36
 
37
+ = 1.2.0 =
38
+ * WARNING - this update includes some major changes to shortcode construction, do not upgrade until you have read how this will affect your setup - updating should be easy.
39
+ * Renamed the `taxonomies` argument to `fields` - `taxonomies` is now no longer appropriate as this list contains field types other than taxonomies - this list now contains taxonomies, `post_type`, `post_date` and `search` - `taxonomies` as an argument is still supported however will be deprecated
40
+ * Search box can now be positioned anywhere, simply include `search` in the fields list in the position desired. Upgrading from previous versions will cause you to lose your search box, simply include `search` in the fields list to show it again
41
+ * Drop support for `search` argument as no longer relevant - control display of search input by adding it to the `fields` list
42
+ * Labels have been completely rewritten - `label` has been renamed to `headings` to avoid confusion with internal taxonomy labels - the `headings` argument now allows for any text to be added and displayed as a heading for each field - this allows for much more flexibility and no longer uses internal taxonomy labels - to hide a label simply leave blank
43
+ * Added support for hierarchical taxonomies for all input types - checkbox, radio & select
44
+ * Added support for ordering of taxonomies - use `order_by` argument - allowed values are `id`, `name`, `slug`, `count`, `term_group`
45
+ * Added support for ordering direction of taxonomies - use `order_dir` argument - allowed values are 'asc' or 'desc'
46
+ * Added support to show or hide empty taxonomies - use `hide_empty` argument
47
+ * Added support for `search_placeholder`
48
+ * Updated `post_date` functionality to work with older versions of WP - can be displayed either as `date` or `daterange` - the `post_date` field uses the HTML 5 input type of `date` - browsers that do not support it will simply show a text box - a tutorial of integrating jquery for graceful degredation is in the works
49
+ * Renamed `submitlabel` to `submit_label` - `submitlabel` still works for now.
50
+ * Renamed `type` to `types` - `type` still works for now.
51
+ * Updated display of checkboxes and radio buttons, inputs are now wrapped in an unordered list which may affect your styling
52
+ * Various bug fixes
53
+ * Thanks to `bradaric` for help with hierarchical dropdown lists and date input types - https://github.com/bradaric
54
+
55
+ = 1.1.3 =
56
+ * Added support for post_date to be displayed either as `date` or `daterange` (WP 3.7+) type
57
+
58
  = 1.1.2 =
59
  * Added support for all public and custom post types (the `attachment` post type is excluded) - all post types can be user searchable or predfined and hidden from the user. This allows for users to add multiple search widgets to their site which work on specific post types independantly from eachother.
60
  * Added offical updated documentation, created and moved to [Search & Filter Docs](http://docs.designsandcode.com/search-filter/)
84
 
85
  == Upgrade Notice ==
86
 
87
+ * WARNING - this update includes some major changes to shortcode construction, do not upgrade until you have read the changelog and how this will affect your setup - updating should be easy.
88
 
89
  == Description ==
90
 
search-filter.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://www.designsandcode.com/447/wordpress-search-filter-plugin-for
5
  Description: Search and Filtering system for Pages, Posts, Categories, Tags and Taxonomies
6
  Author: Designs & Code
7
  Author URI: http://www.designsandcode.com/
8
- Version: 1.1.2
9
  Text Domain: searchandfilter
10
  License: GPLv2
11
  */
@@ -16,8 +16,8 @@ License: GPLv2
16
  * Set up Plugin Globals
17
  */
18
  if (!defined('SEARCHANDFILTER_VERSION_NUM'))
19
- define('SEARCHANDFILTER_VERSION_NUM', '1.1.2');
20
-
21
  if (!defined('SEARCHANDFILTER_THEME_DIR'))
22
  define('SEARCHANDFILTER_THEME_DIR', ABSPATH . 'wp-content/themes/' . get_template());
23
 
@@ -29,7 +29,7 @@ if (!defined('SEARCHANDFILTER_PLUGIN_DIR'))
29
 
30
  if (!defined('SEARCHANDFILTER_PLUGIN_URL'))
31
  define('SEARCHANDFILTER_PLUGIN_URL', WP_PLUGIN_URL . '/' . SEARCHANDFILTER_PLUGIN_NAME);
32
-
33
  if (!defined('SEARCHANDFILTER_BASENAME'))
34
  define('SEARCHANDFILTER_BASENAME', plugin_basename(__FILE__));
35
 
@@ -39,8 +39,8 @@ if (!defined('SEARCHANDFILTER_VERSION_KEY'))
39
 
40
 
41
  //form prefix for plugin
42
- if (!defined('SEARCHANDFILTER_FPRE'))
43
- define('SEARCHANDFILTER_FPRE', 'of');
44
 
45
  add_option(SEARCHANDFILTER_VERSION_KEY, SEARCHANDFILTER_VERSION_NUM);
46
 
@@ -60,38 +60,38 @@ if ( ! class_exists( 'SearchAndFilter' ) )
60
  private $defaults = array();
61
  private $frmreserved = array();
62
  private $taxonomylist = array();
63
-
64
  public function __construct()
65
  {
66
- // Set up reserved taxonomies
67
- $this->frmreserved = array(SEARCHANDFILTER_FPRE."category", SEARCHANDFILTER_FPRE."search", SEARCHANDFILTER_FPRE."post_tag", SEARCHANDFILTER_FPRE."submitted", SEARCHANDFILTER_FPRE."post_types");
68
- $this->frmqreserved = array(SEARCHANDFILTER_FPRE."category_name", SEARCHANDFILTER_FPRE."s", SEARCHANDFILTER_FPRE."tag", SEARCHANDFILTER_FPRE."submitted", SEARCHANDFILTER_FPRE."post_types"); //same as reserved
69
 
70
  //add query vars
71
  add_filter('query_vars', array($this,'add_queryvars') );
72
 
73
- //filter post type if it is set
74
  add_filter('pre_get_posts', array($this,'filter_query_post_types'));
 
75
 
76
- // Add shortcode support for widgets
77
- add_shortcode('searchandfilter', array($this, 'shortcode'));
78
- add_filter('widget_text', 'do_shortcode');
79
 
80
  // Check the header to see if the form has been submitted
81
  add_action( 'get_header', array( $this, 'check_posts' ) );
82
 
83
- // Add styles
84
  add_action( 'wp_enqueue_scripts', array($this, 'of_enqueue_styles') );
85
  add_action( 'admin_enqueue_scripts', array($this, 'of_enqueue_admin_ss') );
86
  }
87
-
88
  public function of_enqueue_styles()
89
  {
90
  wp_enqueue_style( 'searchandfilter', SEARCHANDFILTER_PLUGIN_URL . '/style.css', false, 1.0, 'all' );
91
  }
92
  public function of_enqueue_admin_ss($hook)
93
  {
94
-
95
  if( 'toplevel_page_searchandfilter-settings' == $hook )
96
  {
97
  wp_enqueue_style( 'of_syntax_style', SEARCHANDFILTER_PLUGIN_URL.'/admin/github.css', false, 1.0, 'all' ); //more highlight styles http://softwaremaniacs.org/media/soft/highlight/test.html
@@ -99,75 +99,194 @@ if ( ! class_exists( 'SearchAndFilter' ) )
99
  wp_enqueue_script( 'of_syntax_script', SEARCHANDFILTER_PLUGIN_URL.'/admin/syntax.highlight.min.js' );
100
  }
101
  }
102
-
103
  public function shortcode($atts, $content = null)
104
  {
105
  // extract the attributes into variables
106
  extract(shortcode_atts(array(
107
- 'search' => 1,
108
- 'taxonomies' => null,
109
- 'submitlabel' => "Submit",
110
- 'type' => "",
111
- 'label' => "default",
 
 
 
 
112
  'class' => "",
113
  'post_types' => "",
114
- 'show_post_types' => "0"
 
 
 
115
  ), $atts));
 
 
 
 
 
 
 
 
 
 
116
 
 
 
117
 
118
- $taxonomies = explode(",",$taxonomies);
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  if($post_types!="")
121
  {
122
  $post_types = explode(",",$post_types);
123
  }
 
 
 
 
 
 
 
 
124
 
125
- $this->taxonomylist = $taxonomies;
126
- $notaxonomies = count($taxonomies);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
 
 
 
 
 
 
 
 
 
128
 
129
- //set default types for each taxonomy
130
- $types = explode(",",$type);
131
- if(!is_array($types))
132
  {
133
- $types = array();
 
 
 
 
134
  }
135
 
136
- $labels = explode(",",$label);
 
 
137
  $showlabels = true;
138
  $labeldefault = "name";
139
-
140
  if(!is_array($labels))
141
  {
142
  $labels = array("default");
143
  }
144
 
145
- for($i=0; $i<$notaxonomies; $i++)
146
- {//loop through all taxonomies
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  //set up types
149
  if(isset($types[$i]))
150
  {
151
-
152
- if(($types[$i]=="select")||($types[$i]=="checkbox")||($types[$i]=="radio"))
153
- {
154
- $types[$i] = $types[$i];
 
 
 
 
 
 
 
155
  }
156
  else
157
- {
158
- $types[$i] = "select";
 
 
 
 
 
 
 
159
  }
160
  }
161
  else
162
- {
163
- $types[$i] = "select";
 
 
 
 
 
 
 
 
164
  }
165
 
166
-
167
-
168
  if(isset($labels[0]))
169
  {//these means at least one option has been set
170
-
171
  if(($labels[0]=="0")||($labels[0]=="none"))
172
  {
173
  if($i!=0)
@@ -175,67 +294,76 @@ if ( ! class_exists( 'SearchAndFilter' ) )
175
  $labels[$i] = ""; //then set all fields to blank ("no label").
176
  }
177
  }
178
- else if($labels[0]=="default")
179
- {
180
- $labels[$i] = $labeldefault;
181
- }
182
  else
183
  {//then one or more options were passed, and the value wasn't "0" or "none"
184
 
185
  if(isset($labels[$i]))
186
- {
187
- if(($labels[$i]=="name")||($labels[$i]=="singular_name")||($labels[$i]=="search_items")||($labels[$i]=="all_items"))
188
- {//enforce the use of only above mentioned labels, don't support the other ones or just any data supplied by the user
189
-
190
- $labels[$i] = $labels[$i];
191
- }
192
- else if($labels[$i]=="")
193
- {//if it is blank no label should be shown for this taxonomy
194
-
195
- $labels[$i] = "";
196
- }
197
- else
198
- {//this normally means a typos or unrecognised type, so use default
199
-
200
- $labels[$i] = $labeldefault;
201
- }
202
  }
203
  else
204
  {
205
- $labels[$i] = $labeldefault;
206
  }
207
  }
208
  }
209
  else
210
  {//then it has been completely omitted so use default display
211
- $labels[$i] = $labeldefault;
212
  }
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
 
215
- }
216
-
217
- //if we have a value of 0 or "none" in teh first part of the array, the we need to set it to blanks so it doesn't display
218
- if(isset($labels[0]))
219
- {
220
- if(($labels[0]=="0")||($labels[0]=="none"))
 
 
 
 
 
 
 
221
  {
222
- $labels[0] = ""; //then set all fields to blank ("no label").
223
  }
 
224
  }
225
 
226
  //set all form defaults / dropdowns etc
227
  $this->set_defaults();
228
-
229
- return $this->get_search_filter_form($search, $submitlabel, $taxonomies, $types, $labels, $post_types, $class);
230
  }
231
-
232
-
233
  function add_queryvars( $qvars )
234
  {
235
  $qvars[] = 'post_types';
 
236
  return $qvars;
237
  }
238
-
239
  function filter_query_post_types($query)
240
  {
241
  global $wp_query;
@@ -243,7 +371,7 @@ if ( ! class_exists( 'SearchAndFilter' ) )
243
  if(isset($wp_query->query['post_types']))
244
  {
245
  $search_all = false;
246
-
247
  $post_types = explode("+",esc_attr(urlencode($wp_query->query['post_types'])));
248
  if(isset($post_types[0]))
249
  {
@@ -257,7 +385,7 @@ if ( ! class_exists( 'SearchAndFilter' ) )
257
  }
258
  if($search_all)
259
  {
260
- $post_types = get_post_types( '', 'names' );
261
  $query->set('post_type', $post_types); //here we set the post types that we want WP to search
262
  }
263
  else
@@ -265,31 +393,116 @@ if ( ! class_exists( 'SearchAndFilter' ) )
265
  $query->set('post_type', $post_types); //here we set the post types that we want WP to search
266
  }
267
  }
268
-
269
  return $query;
270
  }
271
 
272
- /*
273
- * check to set defaults - to be called after the shortcodes have been init so we can grab the wanted list of taxonomies
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  */
275
  public function set_defaults()
276
  {
277
  global $wp_query;
278
 
279
- /*var_dump($wp_query->query['category_name']);
280
- var_dump($wp_query->query['tag']);*/
281
- /*echo "<pre>";
282
- var_dump($wp_query->query);
283
- echo "</pre>";*/
284
-
285
  $categories = array();
286
  //if(is_category())
287
  //{
288
  if(isset($wp_query->query['category_name']))
289
  {
290
-
291
  $category_params = explode("+",esc_attr($wp_query->query['category_name']));
292
-
293
  foreach($category_params as $category_param)
294
  {
295
  $category = get_category_by_slug( $category_param );
@@ -300,104 +513,114 @@ if ( ! class_exists( 'SearchAndFilter' ) )
300
  }
301
  }
302
  //}
303
- $this->defaults[SEARCHANDFILTER_FPRE.'category'] = $categories;
304
-
305
-
306
  //grab search term for prefilling search input
307
  if(isset($wp_query->query['s']))
308
  {//!"�$%^&*()
309
  $this->searchterm = get_search_query();
310
  }
311
-
312
  //check to see if tag is set
313
-
314
  $tags = array();
315
- //if(is_tag())
316
- //{
317
- if(isset($wp_query->query['tag']))
 
 
 
318
  {
319
- $tag_params = explode("+",esc_attr($wp_query->query['tag']));
320
-
321
- foreach($tag_params as $tag_param)
322
  {
323
- $tag = get_term_by("slug",$tag_param, "post_tag");
324
- if(isset($tag->term_id))
325
- {
326
- $tags[] = $tag->term_id;
327
- }
328
  }
329
  }
330
- //}
331
- $this->defaults[SEARCHANDFILTER_FPRE.'post_tag'] = $tags;
332
 
 
 
333
  $taxs = array();
334
  //loop through all the query vars
335
  foreach($wp_query->query as $key=>$val)
336
  {
337
- if(!in_array(SEARCHANDFILTER_FPRE.$key, $this->frmqreserved))
338
  {//make sure the get is not a reserved get as they have already been handled above
339
-
340
  //now check it is a desired key
341
  if(in_array($key, $this->taxonomylist))
342
  {
343
  $taxslug = ($val);
344
  $tax_params = explode("+",esc_attr($taxslug));
345
-
346
  foreach($tax_params as $tax_param)
347
  {
348
  $tax = get_term_by("slug",$tax_param, $key);
349
-
350
  if(isset($tax->term_id))
351
  {
352
  $taxs[] = $tax->term_id;
353
  }
354
  }
355
-
356
- $this->defaults[SEARCHANDFILTER_FPRE.$key] = $taxs;
357
  }
358
  }
359
  }
 
 
 
 
 
 
 
 
 
 
 
 
360
 
361
  $post_types = array();
362
  if(isset($wp_query->query['post_types']))
363
  {
364
  $post_types = explode("+",esc_attr(urlencode($wp_query->query['post_types'])));
365
  }
366
- $this->defaults[SEARCHANDFILTER_FPRE.'post_types'] = $post_types;
367
-
368
-
369
  //now we may be on a taxonomy page
370
  /*if(is_tax())
371
  {
372
  $taxobj = get_queried_object();
373
  $taxid = $taxobj->term_id;
374
- $this->defaults[SEARCHANDFILTER_FPRE.$taxobj->taxonomy] = $taxobj->term_id;
375
  }*/
376
-
377
  }
378
-
379
- /*
380
  * check to see if form has been submitted and handle vars
381
  */
382
 
383
  public function check_posts()
384
  {
385
- if(isset($_POST[SEARCHANDFILTER_FPRE.'submitted']))
386
  {
387
- if($_POST[SEARCHANDFILTER_FPRE.'submitted']==="1")
388
  {
389
  //set var to confirm the form was posted
390
  $this->has_search_posted = true;
391
  }
392
  }
393
-
394
  /* CATEGORIES */
395
- if((isset($_POST[SEARCHANDFILTER_FPRE.'category']))&&($this->has_search_posted))
396
  {
397
- $the_post_cat = ($_POST[SEARCHANDFILTER_FPRE.'category']);
398
-
399
  //make the post an array for easy looping
400
- if(!is_array($_POST[SEARCHANDFILTER_FPRE.'category']))
401
  {
402
  $post_cat[] = $the_post_cat;
403
  }
@@ -406,19 +629,19 @@ if ( ! class_exists( 'SearchAndFilter' ) )
406
  $post_cat = $the_post_cat;
407
  }
408
  $catarr = array();
409
-
410
  foreach ($post_cat as $cat)
411
  {
412
  $cat = esc_attr($cat);
413
  $catobj = get_category($cat);
414
-
415
  if(isset($catobj->slug))
416
  {
417
  $catarr[] = $catobj->slug;
418
  //$catarr[] = $catobj->term_id;
419
  }
420
  }
421
-
422
  if(count($catarr)>0)
423
  {
424
  $categories = implode("+",$catarr);
@@ -445,12 +668,12 @@ if ( ! class_exists( 'SearchAndFilter' ) )
445
  }
446
  }
447
  }
448
-
449
  /* SEARCH BOX */
450
- if((isset($_POST[SEARCHANDFILTER_FPRE.'search']))&&($this->has_search_posted))
451
  {
452
- $this->searchterm = stripslashes($_POST[SEARCHANDFILTER_FPRE.'search']);
453
-
454
  if($this->searchterm!="")
455
  {
456
  if(!$this->hasqmark)
@@ -465,14 +688,14 @@ if ( ! class_exists( 'SearchAndFilter' ) )
465
  $this->urlparams .= "s=".urlencode($this->searchterm);
466
  }
467
  }
468
-
469
  /* TAGS */
470
- if((isset($_POST[SEARCHANDFILTER_FPRE.'post_tag']))&&($this->has_search_posted))
471
  {
472
- $the_post_tag = ($_POST[SEARCHANDFILTER_FPRE.'post_tag']);
473
-
474
  //make the post an array for easy looping
475
- if(!is_array($_POST[SEARCHANDFILTER_FPRE.'post_tag']))
476
  {
477
  $post_tag[] = $the_post_tag;
478
  }
@@ -481,18 +704,18 @@ if ( ! class_exists( 'SearchAndFilter' ) )
481
  $post_tag = $the_post_tag;
482
  }
483
  $tagarr = array();
484
-
485
  foreach ($post_tag as $tag)
486
  {
487
  $tag = esc_attr($tag);
488
  $tagobj = get_tag($tag);
489
-
490
  if(isset($tagobj->slug))
491
  {
492
  $tagarr[] = $tagobj->slug;
493
  }
494
  }
495
-
496
  if(count($tagarr)>0)
497
  {
498
  $tags = implode("+",$tagarr);
@@ -507,29 +730,145 @@ if ( ! class_exists( 'SearchAndFilter' ) )
507
  $this->urlparams .= "&";
508
  }
509
  $this->urlparams .= "tag=".$tags;
510
-
511
  }
512
  }
513
 
514
- //now we have dealt with the all the special case variables - search, tags, categories
515
 
516
- /* TAXONOMIES */
517
- //loop through the posts - double check that it is the search form that has been posted, otherwise we could be looping through the posts submitted from an entirely unrelated form
518
- if($this->has_search_posted)
519
  {
520
- foreach($_POST as $key=>$val)
 
 
 
 
521
  {
522
- if(!in_array($key, $this->frmreserved))
523
- {//if the key is not in the reserved array (ie, on a custom taxonomy - not tags, categories, search term)
524
-
525
- // strip off all prefixes for custom taxonomies - we just want to do a redirect - no processing
526
- if (strpos($key, SEARCHANDFILTER_FPRE) === 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  {
528
- $key = substr($key, strlen(SEARCHANDFILTER_FPRE));
529
  }
530
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  $the_post_tax = $val;
532
-
533
  //make the post an array for easy looping
534
  if(!is_array($val))
535
  {
@@ -540,18 +879,18 @@ if ( ! class_exists( 'SearchAndFilter' ) )
540
  $post_tax = $the_post_tax;
541
  }
542
  $taxarr = array();
543
-
544
  foreach ($post_tax as $tax)
545
  {
546
  $tax = esc_attr($tax);
547
  $taxobj = get_term_by('id',$tax,$key);
548
-
549
  if(isset($taxobj->slug))
550
  {
551
  $taxarr[] = $taxobj->slug;
552
  }
553
  }
554
-
555
  if(count($taxarr)>0)
556
  {
557
  $tags = implode("+",$taxarr);
@@ -566,85 +905,41 @@ if ( ! class_exists( 'SearchAndFilter' ) )
566
  $this->urlparams .= "&";
567
  }
568
  $this->urlparams .= $key."=".$tags;
569
-
570
  }
571
  }
572
  }
573
  }
574
 
575
- /* POST TYPES */
576
- if((isset($_POST[SEARCHANDFILTER_FPRE.'post_types']))&&($this->has_search_posted))
577
- {
578
-
579
- $the_post_types = ($_POST[SEARCHANDFILTER_FPRE.'post_types']);
580
-
581
- //make the post an array for easy looping
582
- if(!is_array($the_post_types))
583
- {
584
- $post_types_arr[] = $the_post_types;
585
- }
586
- else
587
- {
588
- $post_types_arr = $the_post_types;
589
- }
590
-
591
- $num_post_types = count($post_types_arr);
592
-
593
- for($i=0; $i<$num_post_types; $i++)
594
- {
595
- if($post_types_arr[$i]=="0")
596
- {
597
- $post_types_arr[$i] = "all";
598
- }
599
- }
600
-
601
- if(count($post_types_arr)>0)
602
- {
603
- $post_types = implode("+",$post_types_arr);
604
-
605
- if(!$this->hasqmark)
606
- {
607
- $this->urlparams .= "?";
608
- $this->hasqmark = true;
609
- }
610
- else
611
- {
612
- $this->urlparams .= "&";
613
- }
614
- $this->urlparams .= "post_types=".$post_types;
615
-
616
- }
617
- }
618
 
619
  if($this->has_search_posted)
620
  {//if the search has been posted, redirect to the newly formed url with all the right params
621
-
622
  if($this->urlparams=="/")
623
  {//check to see if url params are set, if not ("/") then add "?s=" to force load search results, without this it would redirect to the homepage, which may be a custom page with no blog items/results
624
  $this->urlparams .= "?s=";
625
  }
626
  wp_redirect( (home_url().$this->urlparams) );
627
  }
628
-
629
  }
630
-
631
- public function get_search_filter_form($search, $submitlabel, $taxonomies, $types, $labels, $post_types, $class)
632
  {
633
  $returnvar = '';
634
-
635
  $addclass = "";
636
  if($class!="")
637
  {
638
  $addclass = ' '.$class;
639
  }
640
-
641
  $returnvar .= '
642
- <form action="" method="post" class="searchandfilter'.$addclass.'">
643
  <div>';
644
-
645
- if(!in_array("post_types", $taxonomies))
646
- {//then the user has not added it to the taxonomies list so the user does not want a post types drop down... so add (if any) the post types to a hidden attribute
647
-
648
  if(($post_types!="")&&(is_array($post_types)))
649
  {
650
  foreach($post_types as $post_type)
@@ -655,187 +950,342 @@ if ( ! class_exists( 'SearchAndFilter' ) )
655
  }
656
  $returnvar .= '
657
  <ul>';
658
-
659
- if($search==1)
660
- {
661
-
662
- $clean_searchterm = (esc_attr($this->searchterm));
663
- $returnvar .= '<li><input type="text" name="ofsearch" placeholder="Search &hellip;" value="'.$clean_searchterm.'"></li>';
664
- }
665
-
666
  $i = 0;
667
 
668
- foreach($taxonomies as $taxonomy)
669
  {
 
670
 
671
- if($taxonomy == "post_types")
672
- {//build taxonomy array
673
-
674
- $taxonomychildren = array();
675
- $post_type_count = count($post_types);
676
-
677
- //then check the post types array
678
- if(is_array($post_types))
679
- {
680
- if(($post_type_count==1)&&($post_types[0]=="all"))
681
- {
682
- $args = array('public' => true);
683
- $output = 'object'; // names or objects, note names is the default
684
- $operator = 'and'; // 'and' or 'or'
685
-
686
- $post_types_objs = get_post_types( $args, $output, $operator );
687
-
688
- $post_types = array();
689
-
690
- foreach ( $post_types_objs as $post_type )
691
- {
692
- if($post_type->name!="attachment")
693
- {
694
- $tempobject = array();
695
- $tempobject['term_id'] = $post_type->name;
696
- $tempobject['cat_name'] = $post_type->labels->name;
697
-
698
- $taxonomychildren[] = (object)$tempobject;
699
-
700
- $post_types[] = $post_type->name;
701
-
702
- }
703
- }
704
- $post_type_count = count($post_types_objs);
705
-
706
- }
707
- else
708
- {
709
- foreach($post_types as $post_type)
710
- {
711
- //var_dump(get_post_type_object( $post_type ));
712
- $post_type_data = get_post_type_object( $post_type );
713
-
714
- if($post_type_data)
715
- {
716
- $tempobject = array();
717
- $tempobject['term_id'] = $post_type;
718
- $tempobject['cat_name'] = $post_type_data->labels->name;
719
-
720
- $taxonomychildren[] = (object)$tempobject;
721
- }
722
- }
723
- }
724
- }
725
- $taxonomychildren = (object)$taxonomychildren;
726
-
727
- $returnvar .= "<li>";
728
-
729
- $post_type_labels = array();
730
- $post_type_labels['name'] = "Post Types";
731
- $post_type_labels['singular_name'] = "Post Type";
732
- $post_type_labels['search_items'] = "Search Post Types";
733
- $post_type_labels['all_items'] = "All Post Types";
734
-
735
- $post_type_labels = (object)$post_type_labels;
736
-
737
  if($labels[$i]!="")
738
  {
739
- $returnvar .= "<h4>".$post_type_labels->name."</h4>";
740
- }
741
-
742
- if($post_type_count>0)
743
- {
744
- $defaultval = implode("+",$post_types);
745
- }
746
- else
747
- {
748
- $defaultval = "all";
749
- }
750
-
751
- if($types[$i]=="select")
752
- {
753
- $returnvar .= $this->generate_select($taxonomychildren, $taxonomy, $this->tagid, $post_type_labels, $defaultval);
754
- }
755
- else if($types[$i]=="checkbox")
756
- {
757
- $returnvar .= $this->generate_checkbox($taxonomychildren, $taxonomy, $this->tagid);
758
- }
759
- else if($types[$i]=="radio")
760
- {
761
- $returnvar .= $this->generate_radio($taxonomychildren, $taxonomy, $this->tagid, $post_type_labels, $defaultval);
762
  }
763
- $returnvar .= "</li>";
 
 
 
 
 
764
 
 
 
 
 
 
 
765
  }
766
  else
767
  {
768
- $taxonomydata = get_taxonomy($taxonomy);
769
 
770
- if($taxonomydata)
771
- {
772
- $returnvar .= "<li>";
773
-
774
- if($labels[$i]!="")
775
- {
776
- $returnvar .= "<h4>".$taxonomydata->labels->{$labels[$i]}."</h4>";
777
- }
778
-
779
- $taxonomychildren = get_categories('name=of'.$taxonomy.'&taxonomy='.$taxonomy);
780
-
781
- if($types[$i]=="select")
782
- {
783
- $returnvar .= $this->generate_select($taxonomychildren, $taxonomy, $this->tagid, $taxonomydata->labels);
784
- }
785
- else if($types[$i]=="checkbox")
786
- {
787
- $returnvar .= $this->generate_checkbox($taxonomychildren, $taxonomy, $this->tagid);
788
- }
789
- else if($types[$i]=="radio")
790
- {
791
- $returnvar .= $this->generate_radio($taxonomychildren, $taxonomy, $this->tagid, $taxonomydata->labels);
792
- }
793
- $returnvar .= "</li>";
794
- }
795
  }
796
  $i++;
797
-
798
  }
799
-
800
  $returnvar .=
801
  '<li>
802
- <input type="hidden" name="'.SEARCHANDFILTER_FPRE.'submitted" value="1">
803
  <input type="submit" value="'.$submitlabel.'">
804
  </li>';
805
-
806
  $returnvar .= "</ul>";
807
  $returnvar .= '</div>
808
  </form>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
809
 
810
  return $returnvar;
811
  }
812
- public function generate_select($dropdata, $name, $currentid = 0, $labels = null, $defaultval = "0")
 
 
813
  {
814
  $returnvar = "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
 
816
- $returnvar .= '<select class="postform" name="'.SEARCHANDFILTER_FPRE.$name.'">';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
817
  if(isset($labels))
818
  {
819
  if($labels->all_items!="")
820
- {//check to see if all items has been registered in taxonomy then use this label
821
  $returnvar .= '<option class="level-0" value="'.$defaultval.'">'.$labels->all_items.'</option>';
822
  }
823
  else
824
- {//check to see if all items has been registered in taxonomy then use this label with prefix of "All"
825
  $returnvar .= '<option class="level-0" value="'.$defaultval.'">All '.$labels->name.'</option>';
826
  }
827
  }
828
-
829
  foreach($dropdata as $dropdown)
830
  {
831
  $selected = "";
832
-
833
- if(isset($this->defaults[SEARCHANDFILTER_FPRE.$name]))
834
  {
835
- $defaults = $this->defaults[SEARCHANDFILTER_FPRE.$name];
836
-
837
  $noselected = count($defaults);
838
-
839
  if(($noselected==1)&&(is_array($defaults))) //there should never be more than 1 default in a select, if there are then don't set any, user is obviously searching multiple values, in the case of a select this must be "all"
840
  {
841
  foreach($defaults as $defaultid)
@@ -848,23 +1298,25 @@ if ( ! class_exists( 'SearchAndFilter' ) )
848
  }
849
  }
850
  $returnvar .= '<option class="level-0" value="'.$dropdown->term_id.'"'.$selected.'>'.$dropdown->cat_name.'</option>';
851
-
852
  }
853
  $returnvar .= "</select>";
854
-
855
  return $returnvar;
856
  }
 
857
  public function generate_checkbox($dropdata, $name, $currentid = 0, $labels = null, $defaultval = '')
858
  {
859
- $returnvar = "";
 
860
  foreach($dropdata as $dropdown)
861
  {
862
  $checked = "";
863
 
864
  //check a default has been set
865
- if(isset($this->defaults[SEARCHANDFILTER_FPRE.$name]))
866
  {
867
- $defaults = $this->defaults[SEARCHANDFILTER_FPRE.$name];
868
 
869
  $noselected = count($defaults);
870
 
@@ -879,23 +1331,26 @@ if ( ! class_exists( 'SearchAndFilter' ) )
879
  }
880
  }
881
  }
882
- $returnvar .= '<label><input class="postform" type="checkbox" name="'.SEARCHANDFILTER_FPRE.$name.'[]" value="'.$dropdown->term_id.'"'.$checked.'> '.$dropdown->cat_name.'</label>';
883
 
884
  }
885
 
 
 
886
  return $returnvar;
887
  }
888
 
 
889
  public function generate_radio($dropdata, $name, $currentid = 0, $labels = null, $defaultval = "0")
890
  {
891
- $returnvar = "";
892
 
893
  if(isset($labels))
894
  {
895
  $checked = "";
896
- if(isset($this->defaults[SEARCHANDFILTER_FPRE.$name]))
897
  {
898
- $defaults = $this->defaults[SEARCHANDFILTER_FPRE.$name];
899
  $noselected = count($defaults);
900
 
901
  if($noselected==0)
@@ -904,7 +1359,7 @@ if ( ! class_exists( 'SearchAndFilter' ) )
904
  }
905
  else if($noselected==1)
906
  {
907
- if($this->defaults[SEARCHANDFILTER_FPRE.$name][0]==$defaultval)
908
  {
909
  $checked = ' checked="checked"';
910
  }
@@ -915,23 +1370,26 @@ if ( ! class_exists( 'SearchAndFilter' ) )
915
  $checked = ' checked="checked"';
916
  }
917
 
918
- if(isset($this->defaults[SEARCHANDFILTER_FPRE.$name]))
919
  {
920
- $defaults = $this->defaults[SEARCHANDFILTER_FPRE.$name];
921
  if(count($defaults)>1)
922
  {//then we are dealing with multiple defaults - this means mutliple radios are selected, this is only possible with "ALL" so set as default.
923
  $checked = ' checked="checked"';
924
  }
925
  }
926
 
 
927
  if($labels->all_items!="")
928
- {//check to see if all items has been registered in taxonomy then use this label
929
- $returnvar .= '<label><input class="postform" type="radio" name="'.SEARCHANDFILTER_FPRE.$name.'[]" value="'.$defaultval.'"'.$checked.'> '.$labels->all_items.'</label>';
930
  }
931
  else
932
- {//check to see if all items has been registered in taxonomy then use this label with prefix of "All"
933
- $returnvar .= '<label><input class="postform" type="radio" name="'.SEARCHANDFILTER_FPRE.$name.'[]" value="'.$defaultval.'"'.$checked.'> '.$labels->name.'</label>';
934
  }
 
 
935
  }
936
 
937
  foreach($dropdata as $dropdown)
@@ -939,9 +1397,9 @@ if ( ! class_exists( 'SearchAndFilter' ) )
939
  $checked = "";
940
 
941
  //check a default has been set
942
- if(isset($this->defaults[SEARCHANDFILTER_FPRE.$name]))
943
  {
944
- $defaults = $this->defaults[SEARCHANDFILTER_FPRE.$name];
945
 
946
  $noselected = count($defaults);
947
 
@@ -956,15 +1414,53 @@ if ( ! class_exists( 'SearchAndFilter' ) )
956
  }
957
  }
958
  }
959
- $returnvar .= '<label><input class="postform" type="radio" name="'.SEARCHANDFILTER_FPRE.$name.'[]" value="'.$dropdown->term_id.'"'.$checked.'> '.$dropdown->cat_name.'</label>';
960
 
961
  }
962
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
963
  return $returnvar;
964
  }
965
  }
966
  }
967
 
 
 
 
 
 
 
 
 
 
 
 
 
 
968
  if ( class_exists( 'SearchAndFilter' ) )
969
  {
970
  global $SearchAndFilter;
@@ -977,6 +1473,7 @@ if ( class_exists( 'SearchAndFilter' ) )
977
 
978
  // classes
979
  require_once(SEARCHANDFILTER_PLUGIN_DIR."/of-list-table.php");
 
980
 
981
  // admin screens & plugin mods
982
  require_once(SEARCHANDFILTER_PLUGIN_DIR."/of-admin.php");
5
  Description: Search and Filtering system for Pages, Posts, Categories, Tags and Taxonomies
6
  Author: Designs & Code
7
  Author URI: http://www.designsandcode.com/
8
+ Version: 1.2.0
9
  Text Domain: searchandfilter
10
  License: GPLv2
11
  */
16
  * Set up Plugin Globals
17
  */
18
  if (!defined('SEARCHANDFILTER_VERSION_NUM'))
19
+ define('SEARCHANDFILTER_VERSION_NUM', '1.2.0');
20
+
21
  if (!defined('SEARCHANDFILTER_THEME_DIR'))
22
  define('SEARCHANDFILTER_THEME_DIR', ABSPATH . 'wp-content/themes/' . get_template());
23
 
29
 
30
  if (!defined('SEARCHANDFILTER_PLUGIN_URL'))
31
  define('SEARCHANDFILTER_PLUGIN_URL', WP_PLUGIN_URL . '/' . SEARCHANDFILTER_PLUGIN_NAME);
32
+
33
  if (!defined('SEARCHANDFILTER_BASENAME'))
34
  define('SEARCHANDFILTER_BASENAME', plugin_basename(__FILE__));
35
 
39
 
40
 
41
  //form prefix for plugin
42
+ if (!defined('SF_FPRE'))
43
+ define('SF_FPRE', 'of');
44
 
45
  add_option(SEARCHANDFILTER_VERSION_KEY, SEARCHANDFILTER_VERSION_NUM);
46
 
60
  private $defaults = array();
61
  private $frmreserved = array();
62
  private $taxonomylist = array();
63
+
64
  public function __construct()
65
  {
66
+ // Set up reserved fields
67
+ $this->frmreserved = array(SF_FPRE."category", SF_FPRE."search", SF_FPRE."post_tag", SF_FPRE."submitted", SF_FPRE."post_date", SF_FPRE."post_types");
68
+ $this->frmqreserved = array(SF_FPRE."category_name", SF_FPRE."s", SF_FPRE."tag", SF_FPRE."submitted", SF_FPRE."post_date", SF_FPRE."post_types"); //same as reserved
69
 
70
  //add query vars
71
  add_filter('query_vars', array($this,'add_queryvars') );
72
 
73
+ //filter post type & date if it is set
74
  add_filter('pre_get_posts', array($this,'filter_query_post_types'));
75
+ add_filter('pre_get_posts', array($this,'filter_query_post_date'));
76
 
77
+ // Add shortcode support for widgets
78
+ add_shortcode('searchandfilter', array($this, 'shortcode'));
79
+ add_filter('widget_text', 'do_shortcode');
80
 
81
  // Check the header to see if the form has been submitted
82
  add_action( 'get_header', array( $this, 'check_posts' ) );
83
 
84
+ // Add styles
85
  add_action( 'wp_enqueue_scripts', array($this, 'of_enqueue_styles') );
86
  add_action( 'admin_enqueue_scripts', array($this, 'of_enqueue_admin_ss') );
87
  }
88
+
89
  public function of_enqueue_styles()
90
  {
91
  wp_enqueue_style( 'searchandfilter', SEARCHANDFILTER_PLUGIN_URL . '/style.css', false, 1.0, 'all' );
92
  }
93
  public function of_enqueue_admin_ss($hook)
94
  {
 
95
  if( 'toplevel_page_searchandfilter-settings' == $hook )
96
  {
97
  wp_enqueue_style( 'of_syntax_style', SEARCHANDFILTER_PLUGIN_URL.'/admin/github.css', false, 1.0, 'all' ); //more highlight styles http://softwaremaniacs.org/media/soft/highlight/test.html
99
  wp_enqueue_script( 'of_syntax_script', SEARCHANDFILTER_PLUGIN_URL.'/admin/syntax.highlight.min.js' );
100
  }
101
  }
102
+
103
  public function shortcode($atts, $content = null)
104
  {
105
  // extract the attributes into variables
106
  extract(shortcode_atts(array(
107
+
108
+ 'fields' => null,
109
+ 'taxonomies' => null, //will be deprecated - use `fields` instead
110
+ 'submit_label' => null,
111
+ 'submitlabel' => null, //will be deprecated - use `submit_label` instead
112
+ 'search_placeholder' => "Search &hellip;",
113
+ 'types' => "",
114
+ 'type' => "", //will be deprecated - use `types` instead
115
+ 'headings' => "",
116
  'class' => "",
117
  'post_types' => "",
118
+ 'hierarchical' => "",
119
+ 'hide_empty' => "",
120
+ 'order_by' => "",
121
+ 'order_dir' => ""
122
  ), $atts));
123
+
124
+ //init `fields`
125
+ if($fields!=null)
126
+ {
127
+ $fields = explode(",",$fields);
128
+ }
129
+ else
130
+ {
131
+ $fields = explode(",",$taxonomies);
132
+ }
133
 
134
+ $this->taxonomylist = $fields;
135
+ $nofields = count($fields);
136
 
 
137
 
138
+ //init `submitlabel`
139
+ if($submitlabel!=null)
140
+ {//then the old "submitlabel" has been supplied
141
+
142
+ if($submit_label==null)
143
+ {
144
+ //then the new label has not been supplied so do nothing
145
+ $submit_label = $submitlabel;
146
+ }
147
+ else
148
+ {
149
+ //then the new label has been supplied so take the new label value
150
+ //$submit_label = $submit_label;
151
+ }
152
+ }
153
+ else if($submitlabel==null)
154
+ {
155
+ if($submit_label==null)
156
+ {//default value
157
+ $submit_label = "Submit";
158
+ }
159
+ }
160
+
161
+ //init `post_types`
162
  if($post_types!="")
163
  {
164
  $post_types = explode(",",$post_types);
165
  }
166
+ else
167
+ {
168
+ if(in_array("post_types", $fields))
169
+ {
170
+ $post_types = array("all");
171
+ }
172
+
173
+ }
174
 
175
+ //init `hierarchical`
176
+ if($hierarchical!="")
177
+ {
178
+ $hierarchical = explode(",",$hierarchical);
179
+ }
180
+ else
181
+ {
182
+ $hierarchical = array("");
183
+ }
184
+
185
+ //init `hide_empty`
186
+ if($hide_empty!="")
187
+ {
188
+ $hide_empty = explode(",",$hide_empty);
189
+ }
190
+ else
191
+ {
192
+ $hide_empty = array("");
193
+ }
194
 
195
+ //init `order_by`
196
+ if($order_by!="")
197
+ {
198
+ $order_by = explode(",",$order_by);
199
+ }
200
+ else
201
+ {
202
+ $order_by = array("");
203
+ }
204
 
205
+ //init `order_dir`
206
+ if($order_dir!="")
 
207
  {
208
+ $order_dir = explode(",",$order_dir);
209
+ }
210
+ else
211
+ {
212
+ $order_dir = array("");
213
  }
214
 
215
+
216
+ //init `labels`
217
+ $labels = explode(",",$headings);
218
  $showlabels = true;
219
  $labeldefault = "name";
220
+
221
  if(!is_array($labels))
222
  {
223
  $labels = array("default");
224
  }
225
 
226
+ //init `types`
227
+ if($types!=null)
228
+ {
229
+ $types = explode(",",$types);
230
+ }
231
+ else
232
+ {
233
+ $types = explode(",",$type);
234
+ }
235
+
236
+ if(!is_array($types))
237
+ {
238
+ $types = array();
239
+ }
240
+
241
+
242
+ //Loop through Fields and set up default types
243
+ for($i=0; $i<$nofields; $i++)
244
+ {//loop through all fields
245
 
246
  //set up types
247
  if(isset($types[$i]))
248
  {
249
+ if($fields[$i] == 'post_date')
250
+ {//force use of input for date
251
+ if(($types[$i]=="date")||($types[$i]=="daterange"))
252
+ {
253
+ $types[$i] = $types[$i];
254
+ }
255
+ else
256
+ {//set default for post_date to 'date'
257
+
258
+ $types[$i] = "date";
259
+ }
260
  }
261
  else
262
+ {//everything else can use a standard form input - checkbox/radio/dropdown/list
263
+ if(($types[$i]=="select")||($types[$i]=="wp_dropdown")||($types[$i]=="checkbox")||($types[$i]=="radio")||($types[$i]=="wp_list"))
264
+ {
265
+ $types[$i] = $types[$i];
266
+ }
267
+ else
268
+ {
269
+ $types[$i] = "select";
270
+ }
271
  }
272
  }
273
  else
274
+ {//set default if omitted
275
+
276
+ if($fields[$i] == 'post_date')
277
+ {
278
+ $types[$i] = "date";
279
+ }
280
+ else
281
+ {
282
+ $types[$i] = "select";
283
+ }
284
  }
285
 
286
+ //setup labels
 
287
  if(isset($labels[0]))
288
  {//these means at least one option has been set
289
+
290
  if(($labels[0]=="0")||($labels[0]=="none"))
291
  {
292
  if($i!=0)
294
  $labels[$i] = ""; //then set all fields to blank ("no label").
295
  }
296
  }
 
 
 
 
297
  else
298
  {//then one or more options were passed, and the value wasn't "0" or "none"
299
 
300
  if(isset($labels[$i]))
301
+ {
302
+ //then use text supplied
303
+ $labels[$i] = $labels[$i];
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  }
305
  else
306
  {
307
+ $labels[$i] = "";
308
  }
309
  }
310
  }
311
  else
312
  {//then it has been completely omitted so use default display
313
+ $labels[$i] = "";
314
  }
315
 
316
+ if(isset($order_by[$i]))
317
+ {
318
+
319
+ if(($order_by[$i]=="id")||($order_by[$i]=="name")||($order_by[$i]=="slug")||($order_by[$i]=="count")||($order_by[$i]=="term_group"))
320
+ {
321
+ //then use text supplied
322
+ $order_by[$i] = $order_by[$i];
323
+ }
324
+ else
325
+ {
326
+ $order_by[$i] = "name"; //else use default - possible typo or use of unknown value
327
+ }
328
+ }
329
+ else
330
+ {
331
+ $order_by[$i] = "name"; //use default
332
+ }
333
 
334
+ if(isset($order_dir[$i]))
335
+ {
336
+ if(($order_dir[$i]=="asc")||($order_dir[$i]=="desc"))
337
+ {
338
+ //then use text supplied
339
+ $order_dir[$i] = $order_dir[$i];
340
+ }
341
+ else
342
+ {
343
+ $order_dir[$i] = "asc"; //else use default - possible typo or use of unknown value
344
+ }
345
+ }
346
+ else
347
  {
348
+ $order_dir[$i] = "asc"; //use default
349
  }
350
+
351
  }
352
 
353
  //set all form defaults / dropdowns etc
354
  $this->set_defaults();
355
+
356
+ return $this->get_search_filter_form($submit_label, $search_placeholder, $fields, $types, $labels, $hierarchical, $hide_empty, $post_types, $order_by, $order_dir, $class);
357
  }
358
+
359
+
360
  function add_queryvars( $qvars )
361
  {
362
  $qvars[] = 'post_types';
363
+ $qvars[] = 'post_date';
364
  return $qvars;
365
  }
366
+
367
  function filter_query_post_types($query)
368
  {
369
  global $wp_query;
371
  if(isset($wp_query->query['post_types']))
372
  {
373
  $search_all = false;
374
+
375
  $post_types = explode("+",esc_attr(urlencode($wp_query->query['post_types'])));
376
  if(isset($post_types[0]))
377
  {
385
  }
386
  if($search_all)
387
  {
388
+ $post_types = get_post_types( '', 'names' );
389
  $query->set('post_type', $post_types); //here we set the post types that we want WP to search
390
  }
391
  else
393
  $query->set('post_type', $post_types); //here we set the post types that we want WP to search
394
  }
395
  }
396
+
397
  return $query;
398
  }
399
 
400
+
401
+
402
+
403
+ /**
404
+ * Filter the SQL WHERE clause to limit the query to grabbing posts from the
405
+ * past week.
406
+ *
407
+ * @param string $where SQL WHERE clause passed from the filter.
408
+ * @return string Modified WHERE clause.
409
+ */
410
+ function limit_date_range_query( $where )
411
+ {
412
+ global $wp_query;
413
+
414
+ //get post dates into array
415
+ $post_date = explode("+", esc_attr(urlencode($wp_query->query['post_date'])));
416
+
417
+ if (count($post_date) > 1 && $post_date[0] != $post_date[1])
418
+ {
419
+ $date_query = array();
420
+
421
+ if (!empty($post_date[0]))
422
+ {
423
+ $date_query['after'] = date('Y-m-d 00:00:00', strtotime($post_date[0]));
424
+ }
425
+
426
+ if (!empty($post_date[1]))
427
+ {
428
+ $date_query['before'] = date('Y-m-d 23:59:59', strtotime($post_date[1]));
429
+ }
430
+
431
+ }
432
+
433
+ // Append fragment to WHERE clause to select posts newer than the past week.
434
+ $where .= " AND post_date >='" . $date_query['after'] . "' AND post_date <='" . $date_query['before'] . "'";
435
+
436
+ return $where;
437
+ }
438
+
439
+ /**
440
+ * Remove the filter limiting posts to the past week.
441
+ *
442
+ * Remove the filter after it runs so that it doesn't affect any other
443
+ * queries that might be performed on the same page (eg. Recent Posts
444
+ * widget).
445
+ */
446
+ function remove_limit_date_range_query()
447
+ {
448
+ remove_filter( 'posts_where', 'limit_date_range_query' );
449
+ }
450
+
451
+ function filter_query_post_date($query)
452
+ {
453
+ global $wp_query;
454
+
455
+ if(isset($wp_query->query['post_date']))
456
+ {
457
+ //get post dates into array
458
+ $post_date = explode("+", esc_attr(urlencode($wp_query->query['post_date'])));
459
+
460
+ if(!empty($post_date))
461
+ {
462
+ //if there is more than 1 post date and the dates are not the same
463
+ if (count($post_date) > 1 && $post_date[0] != $post_date[1])
464
+ {
465
+ if((!empty($post_date[0]))&&(!empty($post_date[1])))
466
+ {
467
+ // Attach hook to filter WHERE clause.
468
+ add_filter('posts_where', array($this,'limit_date_range_query'));
469
+
470
+ // Remove the filter after it is executed.
471
+ add_action('posts_selection', array($this,'remove_limit_date_range_query'));
472
+ }
473
+ }
474
+ else
475
+ { //else we are dealing with one date or both dates are the same (so need to find posts for a single day)
476
+
477
+ if (!empty($post_date[0]))
478
+ {
479
+ $post_time = strtotime($post_date[0]);
480
+ $query->set('year', date('Y', $post_time));
481
+ $query->set('monthnum', date('m', $post_time));
482
+ $query->set('day', date('d', $post_time));
483
+ }
484
+ }
485
+ }
486
+ }
487
+
488
+ return $query;
489
+ }
490
+
491
+ /*
492
+ * check to set defaults - to be called after the shortcodes have been init so we can grab the wanted list of fields
493
  */
494
  public function set_defaults()
495
  {
496
  global $wp_query;
497
 
 
 
 
 
 
 
498
  $categories = array();
499
  //if(is_category())
500
  //{
501
  if(isset($wp_query->query['category_name']))
502
  {
503
+
504
  $category_params = explode("+",esc_attr($wp_query->query['category_name']));
505
+
506
  foreach($category_params as $category_param)
507
  {
508
  $category = get_category_by_slug( $category_param );
513
  }
514
  }
515
  //}
516
+ $this->defaults[SF_FPRE.'category'] = $categories;
517
+
518
+
519
  //grab search term for prefilling search input
520
  if(isset($wp_query->query['s']))
521
  {//!"�$%^&*()
522
  $this->searchterm = get_search_query();
523
  }
524
+
525
  //check to see if tag is set
526
+
527
  $tags = array();
528
+
529
+ if(isset($wp_query->query['tag']))
530
+ {
531
+ $tag_params = explode("+",esc_attr($wp_query->query['tag']));
532
+
533
+ foreach($tag_params as $tag_param)
534
  {
535
+ $tag = get_term_by("slug",$tag_param, "post_tag");
536
+ if(isset($tag->term_id))
 
537
  {
538
+ $tags[] = $tag->term_id;
 
 
 
 
539
  }
540
  }
541
+ }
 
542
 
543
+ $this->defaults[SF_FPRE.'post_tag'] = $tags;
544
+
545
  $taxs = array();
546
  //loop through all the query vars
547
  foreach($wp_query->query as $key=>$val)
548
  {
549
+ if(!in_array(SF_FPRE.$key, $this->frmqreserved))
550
  {//make sure the get is not a reserved get as they have already been handled above
551
+
552
  //now check it is a desired key
553
  if(in_array($key, $this->taxonomylist))
554
  {
555
  $taxslug = ($val);
556
  $tax_params = explode("+",esc_attr($taxslug));
557
+
558
  foreach($tax_params as $tax_param)
559
  {
560
  $tax = get_term_by("slug",$tax_param, $key);
561
+
562
  if(isset($tax->term_id))
563
  {
564
  $taxs[] = $tax->term_id;
565
  }
566
  }
567
+
568
+ $this->defaults[SF_FPRE.$key] = $taxs;
569
  }
570
  }
571
  }
572
+
573
+ $post_date = array("","");
574
+ if(isset($wp_query->query['post_date']))
575
+ {
576
+ $post_date = explode("+", esc_attr(urlencode($wp_query->query['post_date'])));
577
+ if(count($post_date)==1)
578
+ {
579
+ $post_date[1] = "";
580
+ }
581
+ }
582
+ $this->defaults[SF_FPRE.'post_date'] = $post_date;
583
+
584
 
585
  $post_types = array();
586
  if(isset($wp_query->query['post_types']))
587
  {
588
  $post_types = explode("+",esc_attr(urlencode($wp_query->query['post_types'])));
589
  }
590
+ $this->defaults[SF_FPRE.'post_types'] = $post_types;
591
+
 
592
  //now we may be on a taxonomy page
593
  /*if(is_tax())
594
  {
595
  $taxobj = get_queried_object();
596
  $taxid = $taxobj->term_id;
597
+ $this->defaults[SF_FPRE.$taxobj->taxonomy] = $taxobj->term_id;
598
  }*/
599
+
600
  }
601
+
602
+ /*
603
  * check to see if form has been submitted and handle vars
604
  */
605
 
606
  public function check_posts()
607
  {
608
+ if(isset($_POST[SF_FPRE.'submitted']))
609
  {
610
+ if($_POST[SF_FPRE.'submitted']==="1")
611
  {
612
  //set var to confirm the form was posted
613
  $this->has_search_posted = true;
614
  }
615
  }
616
+
617
  /* CATEGORIES */
618
+ if((isset($_POST[SF_FPRE.'category']))&&($this->has_search_posted))
619
  {
620
+ $the_post_cat = ($_POST[SF_FPRE.'category']);
621
+
622
  //make the post an array for easy looping
623
+ if(!is_array($_POST[SF_FPRE.'category']))
624
  {
625
  $post_cat[] = $the_post_cat;
626
  }
629
  $post_cat = $the_post_cat;
630
  }
631
  $catarr = array();
632
+
633
  foreach ($post_cat as $cat)
634
  {
635
  $cat = esc_attr($cat);
636
  $catobj = get_category($cat);
637
+
638
  if(isset($catobj->slug))
639
  {
640
  $catarr[] = $catobj->slug;
641
  //$catarr[] = $catobj->term_id;
642
  }
643
  }
644
+
645
  if(count($catarr)>0)
646
  {
647
  $categories = implode("+",$catarr);
668
  }
669
  }
670
  }
671
+
672
  /* SEARCH BOX */
673
+ if((isset($_POST[SF_FPRE.'search']))&&($this->has_search_posted))
674
  {
675
+ $this->searchterm = stripslashes($_POST[SF_FPRE.'search']);
676
+
677
  if($this->searchterm!="")
678
  {
679
  if(!$this->hasqmark)
688
  $this->urlparams .= "s=".urlencode($this->searchterm);
689
  }
690
  }
691
+
692
  /* TAGS */
693
+ if((isset($_POST[SF_FPRE.'post_tag']))&&($this->has_search_posted))
694
  {
695
+ $the_post_tag = ($_POST[SF_FPRE.'post_tag']);
696
+
697
  //make the post an array for easy looping
698
+ if(!is_array($_POST[SF_FPRE.'post_tag']))
699
  {
700
  $post_tag[] = $the_post_tag;
701
  }
704
  $post_tag = $the_post_tag;
705
  }
706
  $tagarr = array();
707
+
708
  foreach ($post_tag as $tag)
709
  {
710
  $tag = esc_attr($tag);
711
  $tagobj = get_tag($tag);
712
+
713
  if(isset($tagobj->slug))
714
  {
715
  $tagarr[] = $tagobj->slug;
716
  }
717
  }
718
+
719
  if(count($tagarr)>0)
720
  {
721
  $tags = implode("+",$tagarr);
730
  $this->urlparams .= "&";
731
  }
732
  $this->urlparams .= "tag=".$tags;
733
+
734
  }
735
  }
736
 
 
737
 
738
+ /* POST TYPES */
739
+ if((isset($_POST[SF_FPRE.'post_types']))&&($this->has_search_posted))
 
740
  {
741
+
742
+ $the_post_types = ($_POST[SF_FPRE.'post_types']);
743
+
744
+ //make the post an array for easy looping
745
+ if(!is_array($the_post_types))
746
  {
747
+ $post_types_arr[] = $the_post_types;
748
+ }
749
+ else
750
+ {
751
+ $post_types_arr = $the_post_types;
752
+ }
753
+
754
+ $num_post_types = count($post_types_arr);
755
+
756
+ for($i=0; $i<$num_post_types; $i++)
757
+ {
758
+ if($post_types_arr[$i]=="0")
759
+ {
760
+ $post_types_arr[$i] = "all";
761
+ }
762
+ }
763
+
764
+ if(count($post_types_arr)>0)
765
+ {
766
+ $post_types = implode("+",$post_types_arr);
767
+
768
+ if(!$this->hasqmark)
769
+ {
770
+ $this->urlparams .= "?";
771
+ $this->hasqmark = true;
772
+ }
773
+ else
774
+ {
775
+ $this->urlparams .= "&";
776
+ }
777
+ $this->urlparams .= "post_types=".$post_types;
778
+
779
+ }
780
+ }
781
+
782
+
783
+ /* POST DATE */
784
+ if((isset($_POST[SF_FPRE.'post_date']))&&($this->has_search_posted))
785
+ {
786
+ $the_post_date = ($_POST[SF_FPRE.'post_date']);
787
+
788
+ //make the post an array for easy looping
789
+ if(!is_array($the_post_date))
790
+ {
791
+ $post_date_arr[] = $the_post_date;
792
+ }
793
+ else
794
+ {
795
+ $post_date_arr = $the_post_date;
796
+ }
797
+
798
+ $num_post_date = count($post_date_arr);
799
+
800
+ for($i=0; $i<$num_post_date; $i++)
801
+ {
802
+ if($post_date_arr[$i]=="0")
803
+ {
804
+ $post_date_arr[$i] = "all";
805
+ }
806
+ }
807
+
808
+ if(count($post_date_arr)>0)
809
+ {
810
+ $post_date_count = count($post_date_arr);
811
+
812
+ if($post_date_count==2)
813
+ {//see if there are 2 elements in arr (second date range selector)
814
+
815
+ if(($post_date_arr[0]!="")&&($post_date_arr[1]==""))
816
  {
817
+ $post_date = $post_date_arr[0];
818
  }
819
+ else if($post_date_arr[1]=="")
820
+ {//if second date range is blank then remove the array element - this remove the addition of a '+' by implode below and only use first element
821
+ unset($post_date_arr[1]);
822
+ }
823
+ else if($post_date_arr[0]=="")
824
+ {
825
+ $post_date = "+".$post_date_arr[1];
826
+ }
827
+ else
828
+ {
829
+ $post_date = implode("+",array_filter($post_date_arr));
830
+ }
831
+ }
832
+ else
833
+ {
834
+ $post_date = $post_date_arr[0];
835
+ }
836
+
837
+ if($post_date!="")
838
+ {
839
+ if(!$this->hasqmark)
840
+ {
841
+ $this->urlparams .= "?";
842
+ $this->hasqmark = true;
843
+ }
844
+ else
845
+ {
846
+ $this->urlparams .= "&";
847
+ }
848
+ $this->urlparams .= "post_date=".$post_date;
849
+ }
850
+ }
851
+ }
852
+
853
+
854
+ //now we have dealt with the all the special case fields - search, tags, categories, post_types, post_date
855
+
856
+ //loop through the posts - double check that it is the search form that has been posted, otherwise we could be looping through the posts submitted from an entirely unrelated form
857
+ if($this->has_search_posted)
858
+ {
859
+ foreach($_POST as $key=>$val)
860
+ {
861
+ if(!in_array($key, $this->frmreserved))
862
+ {//if the key is not in the reserved array (ie, on a custom taxonomy - not tags, categories, search term)
863
+
864
+ // strip off all prefixes for custom fields - we just want to do a redirect - no processing
865
+ if (strpos($key, SF_FPRE) === 0)
866
+ {
867
+ $key = substr($key, strlen(SF_FPRE));
868
+ }
869
+
870
  $the_post_tax = $val;
871
+
872
  //make the post an array for easy looping
873
  if(!is_array($val))
874
  {
879
  $post_tax = $the_post_tax;
880
  }
881
  $taxarr = array();
882
+
883
  foreach ($post_tax as $tax)
884
  {
885
  $tax = esc_attr($tax);
886
  $taxobj = get_term_by('id',$tax,$key);
887
+
888
  if(isset($taxobj->slug))
889
  {
890
  $taxarr[] = $taxobj->slug;
891
  }
892
  }
893
+
894
  if(count($taxarr)>0)
895
  {
896
  $tags = implode("+",$taxarr);
905
  $this->urlparams .= "&";
906
  }
907
  $this->urlparams .= $key."=".$tags;
908
+
909
  }
910
  }
911
  }
912
  }
913
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
 
915
  if($this->has_search_posted)
916
  {//if the search has been posted, redirect to the newly formed url with all the right params
917
+
918
  if($this->urlparams=="/")
919
  {//check to see if url params are set, if not ("/") then add "?s=" to force load search results, without this it would redirect to the homepage, which may be a custom page with no blog items/results
920
  $this->urlparams .= "?s=";
921
  }
922
  wp_redirect( (home_url().$this->urlparams) );
923
  }
 
924
  }
925
+
926
+ public function get_search_filter_form($submitlabel, $search_placeholder, $fields, $types, $labels, $hierarchical, $hide_empty, $post_types, $order_by, $order_dir, $class)
927
  {
928
  $returnvar = '';
929
+
930
  $addclass = "";
931
  if($class!="")
932
  {
933
  $addclass = ' '.$class;
934
  }
935
+
936
  $returnvar .= '
937
+ <form action="" method="post" class="searchandfilter'.$addclass.'">
938
  <div>';
939
+
940
+ if(!in_array("post_types", $fields))
941
+ {//then the user has not added it to the fields list so the user does not want a post types drop down... so add (if any) the post types to a hidden attribute
942
+
943
  if(($post_types!="")&&(is_array($post_types)))
944
  {
945
  foreach($post_types as $post_type)
950
  }
951
  $returnvar .= '
952
  <ul>';
953
+
 
 
 
 
 
 
 
954
  $i = 0;
955
 
956
+ foreach($fields as $field)
957
  {
958
+ //special cases - post_types & post_date.. all others assumed regular wp taxonomy
959
 
960
+ if($field == "search")
961
+ {
962
+ $returnvar .= '<li>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
963
  if($labels[$i]!="")
964
  {
965
+ $returnvar .= "<h4>".$labels[$i]."</h4>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  }
967
+ $clean_searchterm = (esc_attr($this->searchterm));
968
+ $returnvar .= '<input type="text" name="ofsearch" placeholder="'.$search_placeholder.'" value="'.$clean_searchterm.'">';
969
+ $returnvar .= '</li>';
970
+ }
971
+ else if($field == "post_types")
972
+ {//build field array
973
 
974
+ $returnvar .= $this->build_post_type_element($types, $labels, $post_types, $field, $i);
975
+
976
+ }
977
+ else if($field == 'post_date')
978
+ {
979
+ $returnvar .= $this->build_post_date_element($labels, $i, $types, $field);
980
  }
981
  else
982
  {
 
983
 
984
+ $returnvar .= $this->build_taxonomy_element($types, $labels, $field, $hierarchical, $hide_empty, $order_by, $order_dir, $i);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
  }
986
  $i++;
987
+
988
  }
989
+
990
  $returnvar .=
991
  '<li>
992
+ <input type="hidden" name="'.SF_FPRE.'submitted" value="1">
993
  <input type="submit" value="'.$submitlabel.'">
994
  </li>';
995
+
996
  $returnvar .= "</ul>";
997
  $returnvar .= '</div>
998
  </form>';
999
+
1000
+ return $returnvar;
1001
+ }
1002
+
1003
+ ///////////////////////////////////////////////////////////
1004
+ function build_post_date_element($labels, $i, $types, $field)
1005
+ {
1006
+ $returnvar = "";
1007
+
1008
+ $taxonomychildren = array();
1009
+
1010
+ $taxonomychildren = (object)$taxonomychildren;
1011
+
1012
+ $returnvar .= "<li>";
1013
+
1014
+ if($labels[$i]!="")
1015
+ {
1016
+ $returnvar .= "<h4>".$labels[$i]."</h4>";
1017
+ }
1018
+
1019
+ $defaultval = "";
1020
+
1021
+ if($types[$i]=="date")
1022
+ {
1023
+ $returnvar .= $this->generate_date($taxonomychildren, $field, $this->tagid);
1024
+ }
1025
+ if($types[$i]=="daterange")
1026
+ {
1027
+ $returnvar .= $this->generate_date($taxonomychildren, $field, 0);
1028
+ $returnvar .= "</li><li>";
1029
+ $returnvar .= $this->generate_date($taxonomychildren, $field, 1);
1030
+ }
1031
+ $returnvar .= "</li>";
1032
 
1033
  return $returnvar;
1034
  }
1035
+
1036
+
1037
+ function build_post_type_element($types, $labels, $post_types, $field, $i)
1038
  {
1039
  $returnvar = "";
1040
+ $taxonomychildren = array();
1041
+ $post_type_count = count($post_types);
1042
+
1043
+ //then check the post types array
1044
+ if(is_array($post_types))
1045
+ {
1046
+ if(($post_type_count==1)&&($post_types[0]=="all"))
1047
+ {
1048
+ $args = array('public' => true);
1049
+ $output = 'object'; // names or objects, note names is the default
1050
+ $operator = 'and'; // 'and' or 'or'
1051
+
1052
+ $post_types_objs = get_post_types( $args, $output, $operator );
1053
+
1054
+ $post_types = array();
1055
+
1056
+ foreach ( $post_types_objs as $post_type )
1057
+ {
1058
+ if($post_type->name!="attachment")
1059
+ {
1060
+ $tempobject = array();
1061
+ $tempobject['term_id'] = $post_type->name;
1062
+ $tempobject['cat_name'] = $post_type->labels->name;
1063
+
1064
+ $taxonomychildren[] = (object)$tempobject;
1065
+
1066
+ $post_types[] = $post_type->name;
1067
+
1068
+ }
1069
+ }
1070
+ $post_type_count = count($post_types_objs);
1071
+
1072
+ }
1073
+ else
1074
+ {
1075
+ foreach($post_types as $post_type)
1076
+ {
1077
+ //var_dump(get_post_type_object( $post_type ));
1078
+ $post_type_data = get_post_type_object( $post_type );
1079
+
1080
+ if($post_type_data)
1081
+ {
1082
+ $tempobject = array();
1083
+ $tempobject['term_id'] = $post_type;
1084
+ $tempobject['cat_name'] = $post_type_data->labels->name;
1085
+
1086
+ $taxonomychildren[] = (object)$tempobject;
1087
+ }
1088
+ }
1089
+ }
1090
+ }
1091
+ $taxonomychildren = (object)$taxonomychildren;
1092
+
1093
+ $returnvar .= "<li>";
1094
+
1095
+ $post_type_labels = array();
1096
+ $post_type_labels['name'] = "Post Types";
1097
+ $post_type_labels['singular_name'] = "Post Type";
1098
+ $post_type_labels['search_items'] = "Search Post Types";
1099
+ $post_type_labels['all_items'] = "All Post Types";
1100
+
1101
+ $post_type_labels = (object)$post_type_labels;
1102
+
1103
+ if($labels[$i]!="")
1104
+ {
1105
+ $returnvar .= "<h4>".$labels[$i]."</h4>";
1106
+ }
1107
+
1108
+ if($post_type_count>0)
1109
+ {
1110
+ $defaultval = implode("+",$post_types);
1111
+ }
1112
+ else
1113
+ {
1114
+ $defaultval = "all";
1115
+ }
1116
+
1117
+ if($types[$i]=="select")
1118
+ {
1119
+ $returnvar .= $this->generate_select($taxonomychildren, $field, $this->tagid, $post_type_labels, $defaultval);
1120
+ }
1121
+ else if($types[$i]=="checkbox")
1122
+ {
1123
+
1124
+ $returnvar .= $this->generate_checkbox($taxonomychildren, $field, $this->tagid);
1125
+ }
1126
+ else if($types[$i]=="radio")
1127
+ {
1128
+ $returnvar .= $this->generate_radio($taxonomychildren, $field, $this->tagid, $post_type_labels, $defaultval);
1129
+ }
1130
+ $returnvar .= "</li>";
1131
+
1132
+ return $returnvar;
1133
+ }
1134
+
1135
+ //gets all the data for the taxonomy then display as form element
1136
+ function build_taxonomy_element($types, $labels, $taxonomy, $hierarchical, $hide_empty, $order_by, $order_dir, $i)
1137
+ {
1138
+ $returnvar = "";
1139
+
1140
+ $taxonomydata = get_taxonomy($taxonomy);
1141
+
1142
+ if($taxonomydata)
1143
+ {
1144
+ $returnvar .= "<li>";
1145
+
1146
+ if($labels[$i]!="")
1147
+ {
1148
+ $returnvar .= "<h4>".$labels[$i]."</h4>";
1149
+ }
1150
+
1151
+ $args = array(
1152
+ 'name' => 'of' . $taxonomy,
1153
+ 'taxonomy' => $taxonomy,
1154
+ 'hierarchical' => false,
1155
+ 'child_of' => 0,
1156
+ 'echo' => false,
1157
+ 'hide_if_empty' => false,
1158
+ 'hide_empty' => true,
1159
+ 'order' => $order_dir[$i],
1160
+ 'orderby' => $order_by[$i],
1161
+ 'show_option_none' => ''
1162
+ );
1163
+
1164
+ if(isset($hierarchical[$i]))
1165
+ {
1166
+ if($hierarchical[$i]==1)
1167
+ {
1168
+ $args['hierarchical'] = true;
1169
+ }
1170
+ }
1171
+
1172
+ if(isset($hide_empty[$i]))
1173
+ {
1174
+ if($hide_empty[$i]==0)
1175
+ {
1176
+ $args['hide_empty'] = false;
1177
+ }
1178
+ }
1179
+
1180
+ $taxonomychildren = get_categories($args);
1181
+
1182
+ if($types[$i]=="select")
1183
+ {
1184
+
1185
+ $returnvar .= $this->generate_wp_dropdown($args, $taxonomy, $this->tagid, $taxonomydata->labels);
1186
+ }
1187
+ else if($types[$i]=="checkbox")
1188
+ {
1189
+ $args['title_li'] = '';
1190
+ $args['defaults'] = $this->defaults[$args['name']];
1191
+ $args['show_option_all'] = 0;
1192
+
1193
+ $returnvar .= $this->generate_wp_checkbox($args, $taxonomy, $this->tagid, $taxonomydata->labels);
1194
+ }
1195
+ else if($types[$i]=="radio")
1196
+ {
1197
+ $args['title_li'] = '';
1198
+ $args['defaults'] = $this->defaults[$args['name']];
1199
+ $args['show_option_all'] = 0;
1200
+
1201
+ $returnvar .= $this->generate_wp_radio($args, $taxonomy, $this->tagid, $taxonomydata->labels);
1202
+ }
1203
+ $returnvar .= "</li>";
1204
+ }
1205
 
1206
+ return $returnvar;
1207
+ }
1208
+
1209
+
1210
+ /*
1211
+ * Display various forms
1212
+ */
1213
+
1214
+ //use wp array walker to enable hierarchical display
1215
+ public function generate_wp_dropdown($args, $name, $currentid = 0, $labels = null, $defaultval = "0")
1216
+ {
1217
+ $returnvar = '';
1218
+ $args['show_option_all'] = $labels->all_items != "" ? $labels->all_items : 'All ' . $labels->name;
1219
+
1220
+ if(isset($this->defaults[SF_FPRE.$name]))
1221
+ {
1222
+ $defaults = $this->defaults[SF_FPRE . $name];
1223
+ if (is_array($defaults)) {
1224
+ if (count($defaults) == 1) {
1225
+ $args['selected'] = $defaults[0];
1226
+ }
1227
+ }
1228
+ else {
1229
+ $args['selected'] = $defaultval;
1230
+ }
1231
+ }
1232
+
1233
+ $returnvar .= wp_dropdown_categories($args);
1234
+
1235
+ return $returnvar;
1236
+ }
1237
+
1238
+ //use wp array walker to enable hierarchical display
1239
+ public function generate_wp_checkbox($args, $name, $currentid = 0, $labels = null, $defaultval = "0")
1240
+ {
1241
+ $checked = ($defaultval=="0") ? " checked='checked'" : "";
1242
+ $returnvar = '<ul>';
1243
+ $returnvar .= walk_taxonomy('checkbox', $args);
1244
+ $returnvar .= "</ul>";
1245
+
1246
+ return $returnvar;
1247
+ }
1248
+
1249
+ //use wp array walker to enable hierarchical display
1250
+ public function generate_wp_radio($args, $name, $currentid = 0, $labels = null, $defaultval = "0")
1251
+ {
1252
+ $checked = ($defaultval=="0") ? " checked='checked'" : "";
1253
+ $returnvar = '<ul>';
1254
+ $returnvar .= '<li>'."<label><input type='radio' name='".$args['name']."[]' value='0'$checked /> ".$labels->all_items."</label>".'</li>';
1255
+ $returnvar .= walk_taxonomy('radio', $args);
1256
+ $returnvar .= "</ul>";
1257
+
1258
+ return $returnvar;
1259
+ }
1260
+
1261
+ //generate generic form inputs for use elsewhere, such as post types and non taxonomy fields
1262
+ public function generate_select($dropdata, $name, $currentid = 0, $labels = null, $defaultval = "0")
1263
+ {
1264
+ $returnvar = "";
1265
+
1266
+ $returnvar .= '<select class="postform" name="'.SF_FPRE.$name.'">';
1267
  if(isset($labels))
1268
  {
1269
  if($labels->all_items!="")
1270
+ {//check to see if all items has been registered in field then use this label
1271
  $returnvar .= '<option class="level-0" value="'.$defaultval.'">'.$labels->all_items.'</option>';
1272
  }
1273
  else
1274
+ {//check to see if all items has been registered in field then use this label with prefix of "All"
1275
  $returnvar .= '<option class="level-0" value="'.$defaultval.'">All '.$labels->name.'</option>';
1276
  }
1277
  }
1278
+
1279
  foreach($dropdata as $dropdown)
1280
  {
1281
  $selected = "";
1282
+
1283
+ if(isset($this->defaults[SF_FPRE.$name]))
1284
  {
1285
+ $defaults = $this->defaults[SF_FPRE.$name];
1286
+
1287
  $noselected = count($defaults);
1288
+
1289
  if(($noselected==1)&&(is_array($defaults))) //there should never be more than 1 default in a select, if there are then don't set any, user is obviously searching multiple values, in the case of a select this must be "all"
1290
  {
1291
  foreach($defaults as $defaultid)
1298
  }
1299
  }
1300
  $returnvar .= '<option class="level-0" value="'.$dropdown->term_id.'"'.$selected.'>'.$dropdown->cat_name.'</option>';
1301
+
1302
  }
1303
  $returnvar .= "</select>";
1304
+
1305
  return $returnvar;
1306
  }
1307
+
1308
  public function generate_checkbox($dropdata, $name, $currentid = 0, $labels = null, $defaultval = '')
1309
  {
1310
+ $returnvar = '<ul>';
1311
+
1312
  foreach($dropdata as $dropdown)
1313
  {
1314
  $checked = "";
1315
 
1316
  //check a default has been set
1317
+ if(isset($this->defaults[SF_FPRE.$name]))
1318
  {
1319
+ $defaults = $this->defaults[SF_FPRE.$name];
1320
 
1321
  $noselected = count($defaults);
1322
 
1331
  }
1332
  }
1333
  }
1334
+ $returnvar .= '<li class="cat-item"><label><input class="postform cat-item" type="checkbox" name="'.SF_FPRE.$name.'[]" value="'.$dropdown->term_id.'"'.$checked.'> '.$dropdown->cat_name.'</label></li>';
1335
 
1336
  }
1337
 
1338
+ $returnvar .= '</ul>';
1339
+
1340
  return $returnvar;
1341
  }
1342
 
1343
+
1344
  public function generate_radio($dropdata, $name, $currentid = 0, $labels = null, $defaultval = "0")
1345
  {
1346
+ $returnvar = '<ul>';
1347
 
1348
  if(isset($labels))
1349
  {
1350
  $checked = "";
1351
+ if(isset($this->defaults[SF_FPRE.$name]))
1352
  {
1353
+ $defaults = $this->defaults[SF_FPRE.$name];
1354
  $noselected = count($defaults);
1355
 
1356
  if($noselected==0)
1359
  }
1360
  else if($noselected==1)
1361
  {
1362
+ if($this->defaults[SF_FPRE.$name][0]==$defaultval)
1363
  {
1364
  $checked = ' checked="checked"';
1365
  }
1370
  $checked = ' checked="checked"';
1371
  }
1372
 
1373
+ if(isset($this->defaults[SF_FPRE.$name]))
1374
  {
1375
+ $defaults = $this->defaults[SF_FPRE.$name];
1376
  if(count($defaults)>1)
1377
  {//then we are dealing with multiple defaults - this means mutliple radios are selected, this is only possible with "ALL" so set as default.
1378
  $checked = ' checked="checked"';
1379
  }
1380
  }
1381
 
1382
+ $all_items_name = "";
1383
  if($labels->all_items!="")
1384
+ {//check to see if all items has been registered in field then use this label
1385
+ $all_items_name = $labels->all_items;
1386
  }
1387
  else
1388
+ {//check to see if all items has been registered in field then use this label with prefix of "All"
1389
+ $all_items_name = "All ".$labels->name;
1390
  }
1391
+
1392
+ $returnvar .= '<li class="cat-item"><label><input class="postform" type="radio" name="'.SF_FPRE.$name.'[]" value="'.$defaultval.'"'.$checked.'> '.$all_items_name.'</label></li>';
1393
  }
1394
 
1395
  foreach($dropdata as $dropdown)
1397
  $checked = "";
1398
 
1399
  //check a default has been set
1400
+ if(isset($this->defaults[SF_FPRE.$name]))
1401
  {
1402
+ $defaults = $this->defaults[SF_FPRE.$name];
1403
 
1404
  $noselected = count($defaults);
1405
 
1414
  }
1415
  }
1416
  }
1417
+ $returnvar .= '<li class="cat-item"><label><input class="postform" type="radio" name="'.SF_FPRE.$name.'[]" value="'.$dropdown->term_id.'"'.$checked.'> '.$dropdown->cat_name.'</label></li>';
1418
 
1419
  }
1420
 
1421
+ $returnvar .= '</ul>';
1422
+
1423
+ return $returnvar;
1424
+ }
1425
+
1426
+ public function generate_date($dropdata, $name, $currentid = 0, $labels = null, $defaultval = "0")
1427
+ {
1428
+ $returnvar = '';
1429
+ $current_date = '';
1430
+ //check a default has been set - upto two possible vars for array
1431
+
1432
+ if(isset($this->defaults[SF_FPRE.$name]))
1433
+ {
1434
+ $defaults = $this->defaults[SF_FPRE.$name];
1435
+
1436
+ $noselected = count($defaults);
1437
+
1438
+ if(($noselected>0)&&(is_array($defaults)))
1439
+ {
1440
+ $current_date = $defaults[$currentid];
1441
+ }
1442
+ }
1443
+
1444
+ $returnvar .= '<input class="postform" type="date" name="'.SF_FPRE.$name.'[]" value="' . $current_date . '" />';
1445
+
1446
  return $returnvar;
1447
  }
1448
  }
1449
  }
1450
 
1451
+
1452
+ function walk_taxonomy( $type = "checkbox", $args = array() ) {
1453
+
1454
+ $args['walker'] = new Taxonomy_Walker($type, $args['name']);
1455
+
1456
+ $output = wp_list_categories($args);
1457
+ if ( $output )
1458
+ return $output;
1459
+ }
1460
+
1461
+
1462
+
1463
+
1464
  if ( class_exists( 'SearchAndFilter' ) )
1465
  {
1466
  global $SearchAndFilter;
1473
 
1474
  // classes
1475
  require_once(SEARCHANDFILTER_PLUGIN_DIR."/of-list-table.php");
1476
+ require_once(SEARCHANDFILTER_PLUGIN_DIR."/of-taxonomy-walker.php");
1477
 
1478
  // admin screens & plugin mods
1479
  require_once(SEARCHANDFILTER_PLUGIN_DIR."/of-admin.php");
style.css CHANGED
@@ -33,3 +33,8 @@ body
33
  margin:15px 0;
34
  font-size:16px;
35
  }
 
 
 
 
 
33
  margin:15px 0;
34
  font-size:16px;
35
  }
36
+
37
+ .searchandfilter ul > li > ul:not(.children)
38
+ {
39
+ margin-left:0;
40
+ }