Make WordPress Core

Ticket #4727: grouptags.php

File grouptags.php, 26.5 KB (added by jhodgdon, 19 years ago)

Group Tags plugin (GPL) with type-ahead tag lookup functionality

Line 
1<?php
2/*
3Plugin Name: Group Tag Entry
4Plugin URI:
5Description: Allows you to set up groups of tags, and then assign them to posts by selecting check boxes, drop-down lists, and the like.
6Version: 1.0
7Author: Jennifer Hodgdon, Poplar ProductivityWare
8Author URI: http://poplarware.com
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14*/
15
16$grouptagsFileName = plugin_basename(__FILE__);
17$grouptagsTextDomain = 'grouptags';
18$grouptagsDBVersion = 1;
19$grouptagsElemTable = $wpdb->prefix . 'grouptags_ui_elems';
20$grouptagsSubelemTable = $wpdb->prefix . 'grouptags_ui_subelems';
21$grouptagsBlankItemCount = 3;
22
23add_action('activate_' . $grouptagsFileName, 'grouptags_install_tables');
24add_action('dbx_post_advanced', 'grouptags_post_entry_section' );
25add_action('save_post', 'grouptags_post_save' );
26add_action('admin_menu', 'grouptags_admin_screen');
27add_action('admin_print_scripts', 'grouptags_js_header');
28
29// Activation function -- creates or updates database tables for plugin
30function grouptags_install_tables()
31{
32 global $grouptagsDBVersion, $grouptagsElemTable, $grouptagsSubelemTable;
33
34 // newer versions of WP have this file in a different place...
35
36 if( file_exists( ABSPATH . 'wp-admin/includes/upgrade.php' ))
37 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
38 else
39 require_once(ABSPATH . 'wp-admin/upgrade-functions.php');
40
41 $elemStructure = "CREATE TABLE " . $grouptagsElemTable . " (" .
42 "elem_id BIGINT(20) NOT NULL AUTO_INCREMENT, \n" .
43 "elem_type VARCHAR(15) NOT NULL, \n" .
44 "elem_display_name VARCHAR(50) NOT NULL, \n" .
45 "elem_order DOUBLE NOT NULL, \n" .
46 "PRIMARY KEY (elem_id), \n" .
47 "KEY elem_order (elem_order));";
48
49 $subelemStructure = "CREATE TABLE " . $grouptagsSubelemTable . " (" .
50 "subelem_id BIGINT(20) NOT NULL AUTO_INCREMENT, \n" .
51 "elem_id BIGINT(20) NOT NULL, \n" .
52 "subelem_display_name VARCHAR(50), \n" .
53 "subelem_order DOUBLE, \n" .
54 "subelem_tags TEXT, \n" .
55 "PRIMARY KEY (subelem_id), \n" .
56 "KEY subelem_order (subelem_order), \n" .
57 "KEY (elem_id));" ;
58
59 dbDelta( $elemStructure, true );
60 dbDelta( $subelemStructure, true );
61
62 add_option( "grouptags_db_version", $grouptagsDBVersion );
63 update_option( "grouptags_db_version", $grouptagsDBVersion );
64} // end of grouptags_install_tables function
65
66// Sets up admin screen for plugin
67function grouptags_admin_screen()
68{
69 global $grouptagsTextDomain, $grouptagsFileName;
70
71 add_options_page( __('Group Tags Setup', $grouptagsTextDomain),
72 __('Group Tags', $grouptagsTextDomain), 6,
73 $grouptagsFileName,
74 'grouptags_setup_page' );
75} // end of grouptags_admin_screen function
76
77// Creates and processes the admin setup page
78function grouptags_setup_page()
79{
80 global $grouptagsTextDomain;
81 global $grouptagsBlankItemCount;
82
83 // read current UI info from db
84
85 $info = _grouptags_get_ui_info();
86
87 // See if we have posted info
88
89 if( $_POST['grouptags_hidden'] == 'Y' ) {
90
91 // clear old info from DB
92 _grouptags_clear_elems();
93
94 $skipping = 1;
95 $last_id = -1;
96 $new_id = -1;
97 $last_type = '';
98 $last_disp = '';
99
100 // go through old IDs and see if we have info for them
101
102 for( $i = 0; $i < count( $info ); $i++ ) {
103 $id = $info[$i]['elem_id'];
104
105 if( $id != $last_id ) {
106 // we have arrived at a new item in the array...
107
108 if( !$skipping ) {
109 // process new sub-items
110 for( $j = 0; $j < $grouptagsBlankItemCount; $j++ ) {
111 $subid = "New" . $j;
112 _grouptags_process_subelem( $last_id, $subid, $new_id );
113 }
114 }
115
116 // see if we are skipping this item or not
117 // and save the item info
118
119 $last_id = $id;
120 $ord = $_POST['grouptags_order_' . $id ];
121
122 if( $ord < 0 ) {
123 $skipping = 1;
124 } else {
125 $skipping = 0;
126 $last_ord = $ord;
127 $last_type = $_POST['grouptags_type_' . $id ];
128 $last_disp = $_POST['grouptags_dispname_' . $id ];
129 $new_id = _grouptags_insert_elem( $last_type, $last_disp, $last_ord );
130 }
131 }
132
133 // process sub-item info
134
135 if( !$skipping ) {
136 if( $last_type == "checkbox" ) {
137
138 // should only be one sub-item, get and save info
139 $subid = $info[$i]['subelem_id'];
140 $tags = $_POST['grouptags_tags_' . $last_id . '_' . $subid ];
141
142 _grouptags_insert_subelem( $new_id, '', 1, $tags );
143
144 // skip any other sub-items left over from before
145 $skipping = 1;
146
147 } else if( $last_type != "label" ) {
148 // process all subitems, with full info
149
150 $subid = $info[$i]['subelem_id'];
151 _grouptags_process_subelem( $last_id, $subid, $new_id );
152 }
153 }
154
155 }
156
157 // process any new sub-items in last item
158 if( !$skipping ) {
159 for( $j = 0; $j < $grouptagsBlankItemCount; $j++ ) {
160 $subid = "New" . $j;
161 _grouptags_process_subelem( $last_id, $subid, $new_id );
162 }
163 }
164
165 // see if user has added any new items - could be up to 3 of them
166
167 for( $i = 0; $i < $grouptagsBlankItemCount; $i++ ) {
168 $id = "New" . $i;
169 $ord = $_POST['grouptags_order_' . $id ];
170
171 if( $ord > 0 ) {
172
173 $type = $_POST['grouptags_type_' . $id ];
174 $disp = $_POST['grouptags_dispname_' . $id ];
175 $new_id = _grouptags_insert_elem( $type, $disp, $ord );
176
177 // process sub-items
178
179 $todo = $grouptagsBlankItemCount;
180 if( $type == "checkbox" ) {
181 $todo = 1;
182 } else if( $type == "label" ) {
183 $todo = 0;
184 }
185
186 for( $j = 0; $j < $todo; $j++ ) {
187 $subid = "New" . $j;
188 _grouptags_process_subelem( $id, $subid, $new_id );
189 }
190 }
191 }
192
193 // now re-read info from DB
194 $info = _grouptags_get_ui_info();
195
196 }
197
198 // page header
199
200 ?>
201 <div class="wrap">
202 <h2><?php _e('Tag Groups Setup', $grouptagsTextDomain ); ?></h2>
203 <h3><?php _e('Tag Group Entry Section:', $grouptagsTextDomain ); ?></h3>
204 <p><?php _e('(Hints and Output Preview at bottom of page...)', $grouptagsTextDomain ); ?></p>
205
206<form name="form1" method="post">
207 <input type="hidden" name="grouptags_hidden" value="Y">
208 <?
209
210 // display current items in text entry fields
211
212 $last_elem_id = -1;
213 $last_elem_type = '';
214 $count = 0;
215 $elem_start = "<hr /><p>";
216 $subelems_start = "</p><ul>";
217 $elem_end = "</ul>\n";
218
219 foreach( $info as $item ) {
220 if( $item['elem_id'] != $last_elem_id ) {
221
222 // close out the previous element, if it was open
223
224 if( $count ) {
225 if( $last_elem_type != "label" &&
226 $last_elem_type != "checkbox" ) {
227 echo _grouptags_blank_subelems( $item['elem_id'] );
228 }
229
230 echo $elem_end;
231 }
232
233 // start a new element
234
235 echo $elem_start;
236
237 echo _grouptags_order_box( $item['elem_order'], 1, $item['elem_id'] ) . " " .
238 _grouptags_type_dropdown( $item['elem_type'], $item['elem_id'] ) . " " .
239 _grouptags_disp_name_box( $item['elem_display_name'], 1, $item['elem_id'] );
240
241 echo $subelems_start;
242
243 $last_elem_id = $item['elem_id'];
244 $last_elem_type = $item['elem_type'];
245 }
246
247 $count++;
248
249 // put in sub-elem info
250
251 if( $item['elem_type'] == "checkbox" ) {
252 echo "<li>" .
253 _grouptags_tag_box( $item['subelem_tags'], $item['elem_id'], $item['subelem_id'] ) .
254 "</li>";
255 } else if( $item['elem_type'] != "label" ) {
256
257 echo "<li>" .
258 _grouptags_order_box( $item['subelem_order'], 0, $item['elem_id'], $item['subelem_id'] ) . " " .
259 _grouptags_disp_name_box( $item['subelem_display_name'], 0, $item['elem_id'], $item['subelem_id'] ) . " " .
260 "<br />" .
261 _grouptags_tag_box( $item['subelem_tags'], $item['elem_id'], $item['subelem_id'] ) .
262 "</li>";
263 }
264 }
265
266 if( $count ) {
267 if( $last_elem_type != "label" &&
268 $last_elem_type != "checkbox" ) {
269 echo _grouptags_blank_subelems( $item['elem_id'] );
270 }
271
272 echo $elem_end;
273 }
274
275 // add some blank lines for new elements
276
277 for( $i = 0; $i < $grouptagsBlankItemCount; $i++ ) {
278
279 $id = "New" . $i;
280
281 echo $elem_start;
282 echo _grouptags_order_box( -1, 1, $id ) . " " .
283 _grouptags_type_dropdown( '', $id ) . " " .
284 _grouptags_disp_name_box( '', 1, $id );
285
286 echo $subelems_start;
287 echo _grouptags_blank_subelems( $id );
288 echo $elem_end;
289
290 }
291
292 // submit button and form close
293
294 ?>
295 <p class="submit">
296 <input type="submit" name="Submit" value="<?php _e('Update Tag Groups', $grouptagsTextDomain) ?>" />
297 </p>
298 </form>
299
300 <hr />
301 <h3><?php _e('Data Entry Hints:', $grouptagsTextDomain ); ?></h3>
302 <ul>
303 <li><?php _e( "Terminlology: Labels, Check Boxes, etc. are Elements. WIthin some Elements, you have Items (such as the items in a drop-down list).", $grouptagsTextDomain ); ?></li>
304 <li><?php _e( "The overall Order number determines the order of Elements on the page. The item Order number determines the order of items in a list.", $grouptagsTextDomain ); ?></li>
305 <li><?php _e( "You can use decimal points in your Order numbers, for instance 2.5 to go between order 2 and order 3.", $grouptagsTextDomain ); ?></li>
306 <li><?php _e( "Set the Order to -1 to delete/omit an item or element. When entering an item/element for the first time, you must change the Order to something other than -1, or it will be ignored.", $grouptagsTextDomain ); ?></li>
307 <li><?php _e( "Separate tags by commas in Tags fields.", $grouptagsTextDomain ); ?></li>
308 <li><?php _e( "When defining a Check Box, only fill in the Tags field on the first item in the group. Leave the other items blank.", $grouptagsTextDomain ); ?></li>
309 <li><?php _e( "When defining a Label, leave all items blank.", $grouptagsTextDomain ); ?></li>
310 <li><?php _e( "If you need more blank lines to define new elements, or to add more items within elements, save what you have and more blank lines will appear.", $grouptagsTextDomain ); ?></li>
311 </ul>
312 <hr />
313
314 <h3><?php _e('Preview of Tag Entry Section:', $grouptagsTextDomain ); ?></h3>
315 <form>
316 <?php _grouptags_tag_entry_form( ); ?>
317 </form>
318 </div>
319
320 <?php
321
322} // end of grouptags_setup_page function
323
324// internal function: processes a POSTed sub-elem
325function _grouptags_process_subelem( $elem_id, $subid, $new_elem_id ) {
326 $subord = $_POST['grouptags_sub_order_' . $elem_id . '_' . $subid ];
327 $disp = $_POST['grouptags_sub_dispname_' . $elem_id . '_' . $subid ];
328 $tags = $_POST['grouptags_tags_' . $elem_id . '_' . $subid ];
329
330 if( $subord > 0 ) {
331 _grouptags_insert_subelem( $new_elem_id, $disp, $subord, $tags );
332 }
333}
334
335// internal function: returns a string containing blank sub-elem lines
336function _grouptags_blank_subelems( $id ) {
337
338 global $grouptagsBlankItemCount;
339
340 $str = '';
341
342 for( $i = 0; $i < $grouptagsBlankItemCount; $i++ ) {
343
344 $str .= "<li>";
345 $sub_id = "New" . $i;
346 $str .= _grouptags_order_box( -1, 0, $id, $sub_id ) . " " .
347 _grouptags_disp_name_box( '', 0, $id, $sub_id ) . " " .
348 "<br />" .
349 _grouptags_tag_box( '', $id, $sub_id ) .
350 "</li>\n";
351 }
352
353 return $str;
354}
355
356// internal function: returns a string containing an order text box
357// inputs: current value of order, true/false is it an item (or subitem),
358// item ID, sub-item ID (can omit)
359function _grouptags_order_box( $ord, $is_item, $id, $sub_id = 0 ) {
360 global $grouptagsTextDomain;
361
362 $str = '';
363
364 $str .= __("Order:", $grouptagsTextDomain );
365 $str .= " ";
366 $str .= '<input type="text" size="5" value="' . $ord . '" ';
367 if( $is_item ) {
368 $str .= 'name="grouptags_order_' . $id;
369 } else {
370 $str .= 'name="grouptags_sub_order_' . $id . '_' . $sub_id;
371 }
372
373 $str .= '"' . ">\n";
374
375 return $str;
376}
377
378// internal function: returns a string containing an item type drop-down
379// inputs: current value of type, item ID
380function _grouptags_type_dropdown( $type, $id ) {
381 global $grouptagsTextDomain;
382
383 $types = array( 'label', 'checkbox', 'drop-down', 'radio' );
384 $labels = array( __('Label', $grouptagsTextDomain),
385 __('Check box', $grouptagsTextDomain),
386 __('Drop-Down List', $grouptagsTextDomain),
387 __('Radio Button Group', $grouptagsTextDomain ));
388
389 $str = '';
390
391 $str .= '<select name="grouptags_type_' . $id . '">' . "\n";
392
393 for( $i = 0; $i < count( $types ); $i++ ) {
394 $str .= '<option value="' . $types[$i] . '"';
395 if( $types[$i] == $type ) {
396 $str .= " selected";
397 }
398 $str .= ">" . $labels[$i] . "</option>\n";
399 }
400
401 $str .= "</select>\n";
402
403 return $str;
404
405}
406
407// internal function: returns a string containing a display name textbox
408// inputs: current value of name, true/false is it an item (or subitem),
409// item ID, sub-item ID (can omit)
410function _grouptags_disp_name_box( $name, $is_item, $id, $sub_id = 0 ) {
411 global $grouptagsTextDomain;
412
413 $str = '';
414
415 $str .= __("Displayed Name:", $grouptagsTextDomain );
416 $str .= " ";
417 $str .= '<input type="text" size="30" value="' .
418 _grouptags_escape_dq( $name ). '" ';
419 if( $is_item ) {
420 $str .= 'name="grouptags_dispname_' . $id;
421 } else {
422 $str .= 'name="grouptags_sub_dispname_' . $id . '_' . $sub_id;
423 }
424
425 $str .= '"' . ">\n";
426
427 return $str;
428}
429
430// internal function: returns a string containing a tags textbox
431// inputs: current value of tags, item ID, sub-item ID (can omit)
432function _grouptags_tag_box( $tags, $id, $sub_id = 0 ) {
433 global $grouptagsTextDomain;
434
435 $str = '';
436
437 $str .= __("Tags:", $grouptagsTextDomain );
438 $str .= " ";
439 $str .= '<input type="text" size="80" value="' .
440 _grouptags_escape_dq( $tags ). '" ';
441 $str .= 'name="grouptags_tags_' . $id . '_' . $sub_id . '"';
442
443 $str .= ">\n";
444
445 return $str;
446}
447
448// Internal function: returns the string with double quotes
449// escaped for HTML use
450function _grouptags_escape_dq( $str ) {
451 return preg_replace( '/"/', '&quot;', _grouptags_remove_backslash( $str ));
452}
453
454// Internal function: removes backslashes in a string and returns it
455function _grouptags_remove_backslash( $str ) {
456 return preg_replace( "/\\\\/", '', $str );
457}
458
459// Internal function: prints the tag entry form. Returns an array
460// of tags that were not found in the UI elements
461function _grouptags_tag_entry_form( $tags = array() ) {
462
463 global $grouptagsTextDomain;
464
465 $info = _grouptags_get_ui_info();
466 $tags_found = array();
467
468 $last_elem_id = -1;
469 $elem_start = "<br /><br />\n";
470 $subelem_pre = "";
471 $subelem_mid = "";
472 $subelem_post = "";
473 $elem_end = "";
474 $dosubs = 0;
475 $radio_count = 0;
476
477 foreach( $info as $item ) {
478
479 $thistags = explode( ',', $item['subelem_tags'] );
480 for( $i = 0; $i < count( $thistags ); $i++ ) {
481 $thistags[$i] = trim( $thistags[$i] );
482 }
483
484 if( $item['elem_id'] != $last_elem_id ) {
485
486 // close out the previous element
487 // and start a new element
488
489 if( $last_elem_id != -1 ) {
490 echo $elem_end;
491 echo $elem_start;
492 }
493
494 $last_elem_id = $item['elem_id'];
495 $elem_end = '';
496 $subelem_pre = '';
497 $subelem_mid = '';
498 $subelem_mid_selected = '';
499 $subelem_post = '';
500 $dosubs = 0;
501
502
503 if( $item['elem_type'] == "label" ) {
504 echo "<strong>" . $item['elem_display_name'] . "</strong>";
505
506 } else if( $item['elem_type'] == "checkbox" ) {
507
508 echo '<input type="checkbox" value="' .
509 _grouptags_escape_dq( $item['subelem_tags'] ) .
510 '" name="grouptags_tags[]"';
511
512 if( count( array_intersect( $tags, $thistags ))) {
513 echo " checked";
514 $tags_found = array_merge( $tags_found, $thistags );
515 }
516
517 echo '> '.
518 $item['elem_display_name'];
519
520 } else if( $item['elem_type'] == "drop-down" ) {
521
522 echo $item['elem_display_name'] . ": ";
523
524 echo '<select name="grouptags_tags[]">' . "\n";
525 echo "<option />\n";
526 $elem_end = '</select>' . "\n";
527 $dosubs = 1;
528
529 $subelem_pre = '<option value="';
530 $subelem_mid = '">';
531 $subelem_post = "</option>\n";
532 $subelem_mid_selected = '" selected>';
533
534 } else { // radio
535 $radio_count++;
536 echo $item['elem_display_name'] . ":\n";
537
538 $dosubs = 1;
539 $subelem_pre =
540 '<br /><input type="radio" name="grouptags_radio_' . $radio_count .
541 '" value="';
542 $subelem_mid = '"> ';
543 $subelem_post = "\n";
544 $subelem_mid_selected = '" checked>';
545 }
546
547 }
548
549 // put in sub-elem info
550
551 if( $dosubs ) {
552 echo $subelem_pre . _grouptags_escape_dq( $item['subelem_tags'] );
553
554 if( count( array_intersect( $tags, $thistags ))) {
555 echo $subelem_mid_selected;
556 $tags_found = array_merge( $tags_found, $thistags );
557 } else {
558 echo $subelem_mid;
559 }
560
561 echo $item['subelem_display_name'] .
562 $subelem_post;
563 }
564 }
565
566 echo $elem_end;
567
568 return array_diff( $tags, $tags_found );
569}
570
571// JavaScript for post editing screen
572function grouptags_js_header()
573{
574
575 global $editing, $post, $post_ID;
576 global $grouptagsTextDomain;
577
578 if( !$editing ) {
579 // not on a post/page edit screen
580 return;
581 }
582
583 if( $post && $post->post_type == 'page' ) {
584 // it's a page, not a post -- note that $post is NOT set for a new
585 // page/post, see below
586 return;
587 }
588
589 // check the URL to see if it's a new page screen
590 $req_url = $_SERVER['REQUEST_URI'];
591 if( preg_match( '/page-new.php$/', $req_url )) {
592 // it's the "new page" editing screen, not new post
593 return;
594 }
595
596 // if we get here, we are on a post editing page, so we need the
597 // JavaScript for this page
598
599 // we need JQuery library loaded...
600 wp_print_scripts( array( 'jquery' ));
601
602 // Set up JavaScript array of existing tags for lookup
603
604?>
605<style type="text/css">
606#grouptags_popup ul { list-style: none; color: black; background: #eeeeee; border: 1px solid black; margin: 0; padding: 0; width: 150px;}
607#grouptags_popup ul li { margin-left: 0; padding: 2px; text-indent: 0;}
608.gtselected { background: white; font-style: bold;}
609</style>
610
611<script type="text/javascript">
612 //<![CDATA[
613
614 var grouptags_all_tags = new Array();
615
616<?php
617
618 $all_tags = get_terms( 'post_tag', 'hide_empty=0' );
619
620 $i = 0;
621 foreach( $all_tags as $item ) {
622 $item = sanitize_term( $item, 'post_tag', 'display' );
623
624 if( strlen( $item->name )) {
625 echo "grouptags_all_tags[$i] = " . '"' .
626 _grouptags_escape_dq( $item->name ) . '";' . "\n";
627
628 $i++;
629 }
630 }
631?>
632
633 grouptags_all_tags.sort();
634
635 var grouptags_curr_choices;
636
637 function grouptags_list_choices() {
638 grouptags_hide_choices();
639
640 // figure out what tags to suggest
641
642 // first find what the user is typing
643 var txt = jQuery( '#grouptags_free_entry' ).val();
644
645 // go back to previous comma
646 var start = txt.lastIndexOf(',');
647 if( start ) {
648 txt = txt.substr( start + 1 );
649 }
650 while( txt.charAt(0) == ' ' && txt.length ) {
651 txt = txt.substr( 1 );
652 }
653
654 if( !txt.length ) {
655 // nothing to suggest
656 return;
657 }
658
659 // now see which tags match this
660
661 jQuery( '#grouptags_popup' ).html( '<ul></ul>' );
662
663 grouptags_curr_choices = new Array();
664 var count = 0;
665 var i;
666 for( i = 0; i < grouptags_all_tags.length; i++ ) {
667 if( grouptags_all_tags[i].indexOf( txt ) == 0 ) {
668 grouptags_curr_choices[ count ] = grouptags_all_tags[i];
669 count++;
670 jQuery( '#grouptags_popup ul' ).append( '<li>' + grouptags_all_tags[i] + '</li>' );
671 }
672 }
673
674 if( !count ) {
675 return;
676 }
677
678 jQuery( '#grouptags_popup ul li' ).hover(
679 function( ) {
680 jQuery( this ).addClass( "gtselected" );
681 },
682 function( ) {
683 jQuery( this ).removeClass( "gtselected" );
684 });
685
686 jQuery( '#grouptags_popup ul li' ).click( function() {
687 var prev = jQuery( '#grouptags_free_entry' ).val();
688 if( prev.lastIndexOf( ',' ) > 1 ) {
689 prev = prev.substring( 0, prev.lastIndexOf( ',' ) + 1) + ' ';
690 } else {
691 prev = '';
692 }
693 prev = prev + jQuery( this ).text() + ", ";
694
695 jQuery( '#grouptags_free_entry' ).val( prev );
696 jQuery( '#grouptags_free_entry' ).focus();
697 grouptags_hide_choices();
698 });
699
700 jQuery( '#grouptags_popup' ).show();
701
702 }
703
704 function grouptags_hide_choices() {
705 grouptags_curr_choices = new Array();
706 jQuery( '#grouptags_popup' ).hide();
707 }
708
709 addLoadEvent( function() {
710 jQuery( '#grouptags_free_entry' ).keyup( function( e ) {
711 var kc = e.which;
712 if( !e.which ) {
713 kc = window.keyCode;
714 }
715
716 if( kc == 27 || kc == 44 || kc == 188 ) {
717 // escape/comma -- hide choices
718 grouptags_hide_choices();
719 } else if(( kc >= 65 &&
720 kc <= 90 ) ||
721 ( kc >= 97 &&
722 kc <= 122 ) ||
723 kc == 8 ) {
724 // alpha character, or backspace: put up choice list
725 // note: timeout is to allow choice to get into drop-down
726 setTimeout( grouptags_list_choices, 100 );
727 }
728
729 });
730
731 });
732
733//]]>
734</script>
735<?php
736
737} // end of grouptags_js_header function
738
739
740// Post edit screen section for group tag entry
741function grouptags_post_entry_section() {
742 global $post_ID;
743 global $grouptagTextDomain;
744
745 // header info
746
747 echo '<div class="dbx-b-ox-wrapper">' . "\n";
748 echo '<fieldset id="group_tag_entry" class="dbx-box">' . "\n";
749 echo '<div class="dbx-h-andle-wrapper"><h3 class="dbx-handle">' .
750 __( "Group Tag Entry - Overrides tag field above!", $grouptagTextDomain ) . "</h3></div>";
751
752 echo '<div class="dbx-c-ontent-wrapper"><div class="dbx-content" ' .
753 ' id="group_tag_entry_section">';
754
755 echo '<p>';
756 _e( 'Note: If you have already typed in tags using the Tags field above, you MUST re-enter them in this section!', $grouptagTextDomain );
757 echo '</p>';
758
759 $curr_tags = wp_get_object_terms( $post_ID, 'post_tag' );
760 $tags = array();
761 foreach( $curr_tags as $tag ) {
762 $tags[] = $tag->name;
763 }
764
765 $leftovers = _grouptags_tag_entry_form( $tags );
766
767 echo "<br /><br />Additional Tags (separate by commas):" .
768 '<input type="text" id="grouptags_free_entry" name="grouptags_tags[]" value="' .
769 _grouptags_escape_dq( implode( ', ', $leftovers )) . '" style="width:90%">';
770
771 echo '<br /><div id="grouptags_popup"></div>';
772
773 echo "</div></fieldset></div>\n";
774} // end of grouptags_post_entry_section function
775
776// Process tags on post save
777function grouptags_post_save( $post_id ) {
778
779 $newtags = '';
780 $comma = '';
781 foreach( $_POST['grouptags_tags'] as $entry ) {
782 $entry = trim( $entry );
783 if( strlen( $entry )) {
784 $newtags .= $comma . $entry;
785 $comma = ',';
786 }
787 }
788
789 for( $i = 1; $i < 100; $i++ ) {
790 if( $_POST['grouptags_radio_' . $i ] ) {
791 $entry = trim( $_POST['grouptags_radio_' . $i ] );
792 if( strlen( $entry )) {
793 $newtags .= $comma . $entry;
794 $comma = ',';
795 }
796 }
797 }
798
799 wp_set_post_tags( $post_id, $newtags );
800
801} // end of grouptags_post_save function
802
803
804// Internal function: reads the current UI info from the database
805// and returns it as an array of objects
806function _grouptags_get_ui_info() {
807
808 global $grouptagsElemTable, $grouptagsSubelemTable;
809 global $wpdb;
810
811 $qryStr = "SELECT " .
812 "$grouptagsElemTable.elem_id as elem_id, " .
813 "$grouptagsElemTable.elem_type as elem_type, " .
814 "$grouptagsElemTable.elem_display_name as elem_display_name, " .
815 "$grouptagsElemTable.elem_order as elem_order, " .
816 "$grouptagsSubelemTable.subelem_id as subelem_id, " .
817 "$grouptagsSubelemTable.subelem_display_name as subelem_display_name, " .
818 "$grouptagsSubelemTable.subelem_order as subelem_order, " .
819 "$grouptagsSubelemTable.subelem_tags as subelem_tags " .
820 "FROM $grouptagsElemTable LEFT JOIN $grouptagsSubelemTable ON " .
821 "$grouptagsElemTable.elem_id = $grouptagsSubelemTable.elem_id " .
822 "ORDER BY elem_order, subelem_order";
823
824 $info = $wpdb->get_results( $qryStr, ARRAY_A );
825 if( !$info ) {
826 return array();
827 }
828
829 return $info;
830}
831
832// internal function: clears database of elements and sub-elements
833function _grouptags_clear_elems() {
834 global $grouptagsElemTable, $grouptagsSubelemTable;
835 global $wpdb;
836
837 $qryStr = "TRUNCATE $grouptagsElemTable";
838 $wpdb->query( $qryStr );
839
840 $qryStr = "TRUNCATE $grouptagsSubelemTable";
841 $wpdb->query( $qryStr );
842}
843
844// internal function: adds a new element, returns ID
845 function _grouptags_insert_elem( $type, $disp, $ord ) {
846
847 global $grouptagsElemTable;
848 global $wpdb;
849
850 $qryStr = "INSERT INTO $grouptagsElemTable (elem_type, elem_display_name, elem_order) VALUES ('" .
851 $wpdb->escape( _grouptags_remove_backslash( $type )) . "', '" .
852 $wpdb->escape( _grouptags_remove_backslash( $disp )) . "', '" .
853 $wpdb->escape( intval( _grouptags_remove_backslash( $ord ))) . "')";
854
855 $wpdb->query( $qryStr );
856 return $wpdb->insert_id;
857}
858
859// internal function: adds a new sub-element, returns ID
860function _grouptags_insert_subelem( $elem_id, $disp, $ord, $tags ) {
861 global $grouptagsSubelemTable;
862 global $wpdb;
863
864 $qryStr = "INSERT INTO $grouptagsSubelemTable (elem_id, subelem_display_name, subelem_order, subelem_tags) VALUES ('" .
865 $wpdb->escape( _grouptags_remove_backslash( intval( $elem_id ))) . "', '" .
866 $wpdb->escape( _grouptags_remove_backslash( $disp )) . "', '" .
867 $wpdb->escape( intval( _grouptags_remove_backslash( $ord ))) . "', '" .
868 $wpdb->escape( _grouptags_remove_backslash( $tags )) . "')";
869
870 $wpdb->query( $qryStr );
871 return $wpdb->insert_id;
872
873}
874
875?>